From bb5e698f4d6106132de45f0749510d2c66eed4aa Mon Sep 17 00:00:00 2001 From: Joachim Hofer Date: Fri, 16 Apr 2010 21:03:02 +0200 Subject: [PATCH 1/8] added directory for instrumented classes and improved cleanup --- .../scala/ecobertura/core/state/PluginState.scala | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/ecobertura.core/src/main/scala/ecobertura/core/state/PluginState.scala b/ecobertura.core/src/main/scala/ecobertura/core/state/PluginState.scala index dd23823..2db9d2c 100644 --- a/ecobertura.core/src/main/scala/ecobertura/core/state/PluginState.scala +++ b/ecobertura.core/src/main/scala/ecobertura/core/state/PluginState.scala @@ -28,10 +28,21 @@ object PluginState { class PluginState(stateLocation: IPath) { val instrumentationDataDirectory = new File(stateLocation.toFile, "cobertura") + val instrumentedClassesDirectory = new File(stateLocation.toFile, "bin") + instrumentationDataDirectory.mkdirs + instrumentedClassesDirectory.mkdirs def cleanUp = { - instrumentationDataDirectory.listFiles.map(_.delete) - instrumentationDataDirectory.delete + deleteRecursively(instrumentationDataDirectory) + deleteRecursively(instrumentedClassesDirectory) + } + + private def deleteRecursively(file: File) : Unit = { + if (file.isFile) file.delete + else { + file.listFiles.foreach (deleteRecursively(_)) + file.delete + } } } From f1894b7713330d17df20b893389a88e2ec370b7a Mon Sep 17 00:00:00 2001 From: Joachim Hofer Date: Fri, 16 Apr 2010 21:24:28 +0200 Subject: [PATCH 2/8] added helper methods for copying files --- .../ecobertura/core/state/PluginState.scala | 122 +++++++++++------- 1 file changed, 74 insertions(+), 48 deletions(-) diff --git a/ecobertura.core/src/main/scala/ecobertura/core/state/PluginState.scala b/ecobertura.core/src/main/scala/ecobertura/core/state/PluginState.scala index 2db9d2c..50197d2 100644 --- a/ecobertura.core/src/main/scala/ecobertura/core/state/PluginState.scala +++ b/ecobertura.core/src/main/scala/ecobertura/core/state/PluginState.scala @@ -1,48 +1,74 @@ -/* - * This file is part of eCobertura. - * - * Copyright (c) 2009, 2010 Joachim Hofer - * All rights reserved. - * - * eCobertura is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * eCobertura is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with eCobertura. If not, see . - */ -package ecobertura.core.state - -import java.io.File -import org.eclipse.core.runtime.IPath - -object PluginState { - def initialize(stateLocation: IPath) = new PluginState(stateLocation) -} - -class PluginState(stateLocation: IPath) { - val instrumentationDataDirectory = new File(stateLocation.toFile, "cobertura") - val instrumentedClassesDirectory = new File(stateLocation.toFile, "bin") - - instrumentationDataDirectory.mkdirs - instrumentedClassesDirectory.mkdirs - - def cleanUp = { - deleteRecursively(instrumentationDataDirectory) - deleteRecursively(instrumentedClassesDirectory) - } - - private def deleteRecursively(file: File) : Unit = { - if (file.isFile) file.delete - else { - file.listFiles.foreach (deleteRecursively(_)) - file.delete - } - } -} +/* + * This file is part of eCobertura. + * + * Copyright (c) 2009, 2010 Joachim Hofer + * All rights reserved. + * + * eCobertura is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * eCobertura is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with eCobertura. If not, see . + */ +package ecobertura.core.state +import java.io._ + +import org.eclipse.core.runtime.IPath + +object PluginState { + def initialize(stateLocation: IPath) = new PluginState(stateLocation) +} + +class PluginState(stateLocation: IPath) { + val instrumentationDataDirectory = new File(stateLocation.toFile, "cobertura") + val instrumentedClassesDirectory = new File(stateLocation.toFile, "bin") + + instrumentationDataDirectory.mkdirs + instrumentedClassesDirectory.mkdirs + + def cleanUp = { + deleteRecursively(instrumentationDataDirectory) + deleteRecursively(instrumentedClassesDirectory) + } + + private def deleteRecursively(file: File) : Unit = { + if (file.isFile) file.delete + else { + file.listFiles.foreach (deleteRecursively(_)) + file.delete + } + } + + def copyClassesFrom(source: File) = { + deleteRecursively(instrumentedClassesDirectory) + copyRecursively(source, instrumentedClassesDirectory) + } + + private def copyRecursively(source: File, destination: File) : Unit = { + if (source.isFile) copyFile(source, destination) + else { + if (!destination.exists) destination.mkdirs + source.list.foreach { file => + copyRecursively(new File(source, file), new File(destination, file)) + } + } + } + + private def copyFile(source: File, destination: File) = { + val sourceStream = new FileInputStream(source) + val destinationStream = new FileOutputStream(destination) + val buffer = new Array[Byte](4096) + var bytesRead = sourceStream.read(buffer) + while (bytesRead >= 0) { + destinationStream.write(buffer, 0, bytesRead) + bytesRead = sourceStream.read(buffer) + } + } +} From 975ffe9f01687b834c92d83949ef07f90b269d85 Mon Sep 17 00:00:00 2001 From: Joachim Hofer Date: Fri, 16 Apr 2010 21:29:36 +0200 Subject: [PATCH 3/8] copying class files over should work now --- .../scala/ecobertura/core/launching/LaunchInstrumenter.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/ecobertura.core/src/main/scala/ecobertura/core/launching/LaunchInstrumenter.scala b/ecobertura.core/src/main/scala/ecobertura/core/launching/LaunchInstrumenter.scala index c711116..1220bee 100644 --- a/ecobertura.core/src/main/scala/ecobertura/core/launching/LaunchInstrumenter.scala +++ b/ecobertura.core/src/main/scala/ecobertura/core/launching/LaunchInstrumenter.scala @@ -79,6 +79,7 @@ class LaunchInstrumenter(configuration: ILaunchConfiguration) { if (containsUserClassesFromProject(classpathEntry)) { val userClasspath = classpathEntry.getLocation logger.fine(String format ("instrumenting classes within %s", userClasspath)) + CorePlugin.instance.pluginState.copyClassesFrom(new File(userClasspath)) instrumentFilesWithin(new File(userClasspath)) } else logger.fine(String.format("skipping %s", classpathEntry.getLocation)) }) From 85fba2bd4335d15646f96b3b8ebda2accce0dec8 Mon Sep 17 00:00:00 2001 From: Joachim Hofer Date: Fri, 16 Apr 2010 22:37:43 +0200 Subject: [PATCH 4/8] no more in-place instrumentation, yay! --- .../core/cobertura/CoberturaWrapper.scala | 2 +- .../launching/CoverageClasspathProvider.scala | 32 ++++++++++++++++--- .../core/launching/LaunchInstrumenter.scala | 7 ++-- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/ecobertura.core/src/main/scala/ecobertura/core/cobertura/CoberturaWrapper.scala b/ecobertura.core/src/main/scala/ecobertura/core/cobertura/CoberturaWrapper.scala index 4693928..d13701b 100644 --- a/ecobertura.core/src/main/scala/ecobertura/core/cobertura/CoberturaWrapper.scala +++ b/ecobertura.core/src/main/scala/ecobertura/core/cobertura/CoberturaWrapper.scala @@ -85,7 +85,7 @@ class CoberturaWrapper extends ICoberturaWrapper { CoverageDataFileHandler.loadCoverageData(coberturaFile) } - override def resetProjectData= { + override def resetProjectData = { defaultCoberturaFile.delete initializeCoberturaProjectData } diff --git a/ecobertura.core/src/main/scala/ecobertura/core/launching/CoverageClasspathProvider.scala b/ecobertura.core/src/main/scala/ecobertura/core/launching/CoverageClasspathProvider.scala index 0e80db3..4b6d4ee 100644 --- a/ecobertura.core/src/main/scala/ecobertura/core/launching/CoverageClasspathProvider.scala +++ b/ecobertura.core/src/main/scala/ecobertura/core/launching/CoverageClasspathProvider.scala @@ -23,10 +23,12 @@ import java.util.Arrays import java.util.logging.Logger import org.eclipse.core.runtime.IPath +import org.eclipse.core.runtime.Path import org.eclipse.debug.core.ILaunchConfiguration import org.eclipse.jdt.launching._ -import _root_.ecobertura.core.cobertura.CoberturaWrapper; +import _root_.ecobertura.core.CorePlugin +import _root_.ecobertura.core.cobertura.CoberturaWrapper object CoverageClasspathProvider { val ID = "ecobertura.core.launching.coverageClasspathProvider" //$NON-NLS-1$ @@ -56,13 +58,35 @@ class CoverageClasspathProvider extends IRuntimeClasspathProvider { JavaRuntime.newArchiveRuntimeClasspathEntry(pathToCoberturaJar) } - logger fine "resolving classpath..." + logger.fine("resolving classpath...") val resolvedEntries = wrappedProvider.get.resolveClasspath(entries, configuration) + logger.fine("resolved entries: " + resolvedEntries.mkString) + + val resolvedEntriesWithCoveredClasses = substituteProjectClassesByCoveredClasses(resolvedEntries) val resolvedEntriesWithCobertura = Arrays.copyOf( - resolvedEntries, resolvedEntries.length + 1) + resolvedEntriesWithCoveredClasses, resolvedEntriesWithCoveredClasses.size + 1) resolvedEntriesWithCobertura(resolvedEntries.size) = coberturaEntry - logger.fine("resolved entries: " + resolvedEntries) + + logger.fine("resolved entries with cobertura: " + resolvedEntriesWithCobertura.mkString) resolvedEntriesWithCobertura } + + private def substituteProjectClassesByCoveredClasses(resolvedEntries: Array[IRuntimeClasspathEntry]) = { + for { + i <- 0 until resolvedEntries.size + entry = resolvedEntries(i) + if entry.getClasspathProperty == IRuntimeClasspathEntry.USER_CLASSES && + entry.getType == IRuntimeClasspathEntry.PROJECT + } resolvedEntries(i) = adaptedProjectClassesEntry(entry) + + resolvedEntries + } + + private def adaptedProjectClassesEntry(projectClasses: IRuntimeClasspathEntry) = { + logger.fine("adapting %s".format(projectClasses.getLocation)) + val newPath = new Path(CorePlugin.instance.pluginState.instrumentedClassesDirectory.getAbsolutePath) + logger.fine("new path: %s".format(newPath.toString)) + JavaRuntime.newArchiveRuntimeClasspathEntry(newPath) + } } diff --git a/ecobertura.core/src/main/scala/ecobertura/core/launching/LaunchInstrumenter.scala b/ecobertura.core/src/main/scala/ecobertura/core/launching/LaunchInstrumenter.scala index 1220bee..8040b51 100644 --- a/ecobertura.core/src/main/scala/ecobertura/core/launching/LaunchInstrumenter.scala +++ b/ecobertura.core/src/main/scala/ecobertura/core/launching/LaunchInstrumenter.scala @@ -46,7 +46,7 @@ class LaunchInstrumenter(configuration: ILaunchConfiguration) { CoberturaWrapper.get.resetProjectData instrumentClasspath CoberturaWrapper.get.saveProjectDataToDefaultFile - addCoberturaToClasspath + addCoberturaAndCoveredClassesToClasspath addDatafileSystemProperty private def instrumentClasspath = { @@ -80,12 +80,13 @@ class LaunchInstrumenter(configuration: ILaunchConfiguration) { val userClasspath = classpathEntry.getLocation logger.fine(String format ("instrumenting classes within %s", userClasspath)) CorePlugin.instance.pluginState.copyClassesFrom(new File(userClasspath)) - instrumentFilesWithin(new File(userClasspath)) + instrumentFilesWithin(CorePlugin.instance.pluginState.instrumentedClassesDirectory) + } else logger.fine(String.format("skipping %s", classpathEntry.getLocation)) }) } - private def addCoberturaToClasspath = { + private def addCoberturaAndCoveredClassesToClasspath = { configWC.setAttribute(IJavaLaunchConfigurationConstants.ATTR_CLASSPATH_PROVIDER, CoverageClasspathProvider.ID) CoverageClasspathProvider.wrap(JavaRuntime.getClasspathProvider(configuration)) From ba888b0afadc690e5f9dc4e496b555fa3f92fc71 Mon Sep 17 00:00:00 2001 From: Joachim Hofer Date: Sat, 17 Apr 2010 14:09:18 +0200 Subject: [PATCH 5/8] trying to improve the source file search --- .../ecobertura/core/data/ClassCoverage.scala | 2 +- ecobertura.ui/META-INF/MANIFEST.MF | 3 +- .../ui/util/JavaElementFinder.scala | 41 +++++++++--- .../ecobertura/ui/util/SourceFileFinder.scala | 63 +++++++++++++++++++ .../commands/OpenCoveredClassHandler.scala | 4 +- 5 files changed, 101 insertions(+), 12 deletions(-) create mode 100644 ecobertura.ui/src/main/scala/ecobertura/ui/util/SourceFileFinder.scala diff --git a/ecobertura.core/src/main/scala/ecobertura/core/data/ClassCoverage.scala b/ecobertura.core/src/main/scala/ecobertura/core/data/ClassCoverage.scala index 60ea584..efa745f 100644 --- a/ecobertura.core/src/main/scala/ecobertura/core/data/ClassCoverage.scala +++ b/ecobertura.core/src/main/scala/ecobertura/core/data/ClassCoverage.scala @@ -34,7 +34,7 @@ trait ClassCoverage extends CoverageData { def sourceFileName: String def lines: List[LineCoverage] - override def toString = String.format("ClassCoverage(%s)%s", name, super.toString) + override def toString = "ClassCoverage(%s, %s)%s".format(name, sourceFileName, super.toString) } class CoberturaClassData(classData: ClassData) extends ClassCoverage { diff --git a/ecobertura.ui/META-INF/MANIFEST.MF b/ecobertura.ui/META-INF/MANIFEST.MF index 4e4717d..b444823 100644 --- a/ecobertura.ui/META-INF/MANIFEST.MF +++ b/ecobertura.ui/META-INF/MANIFEST.MF @@ -15,7 +15,8 @@ Require-Bundle: org.eclipse.ui, org.eclipse.jdt.launching, org.eclipse.jdt.ui, org.eclipse.core.expressions, - org.eclipse.ui.ide + org.eclipse.ui.ide, + org.eclipse.search Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Bundle-ActivationPolicy: lazy Bundle-Vendor: jmhofer diff --git a/ecobertura.ui/src/main/scala/ecobertura/ui/util/JavaElementFinder.scala b/ecobertura.ui/src/main/scala/ecobertura/ui/util/JavaElementFinder.scala index 7927e20..e03ae0d 100644 --- a/ecobertura.ui/src/main/scala/ecobertura/ui/util/JavaElementFinder.scala +++ b/ecobertura.ui/src/main/scala/ecobertura/ui/util/JavaElementFinder.scala @@ -19,7 +19,7 @@ */ package ecobertura.ui.util -import java.util.logging.Logger +import java.util.logging._ import org.eclipse.jdt.core.IJavaElement import org.eclipse.jdt.core.search._ @@ -35,27 +35,52 @@ object JavaElementFinder { class JavaElementFinder(covClass: CoverageSessionClass) { import JavaElementFinder._ + + val qualifiedClassNameToFind = + if (covClass.coverageData.packageName.isEmpty) covClass.coverageData.name + else "%s.%s".format(covClass.coverageData.packageName, covClass.coverageData.name) + logger.fine("looking for %s".format(qualifiedClassNameToFind)) val searchPattern = SearchPattern.createPattern( - covClass.coverageData.packageName + "." + covClass.coverageData.name, + qualifiedClassNameToFind, IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, - SearchPattern.R_EXACT_MATCH); + SearchPattern.R_EXACT_MATCH) def find(callback: IJavaElement => Unit) = { - searchEngine.search(searchPattern, - Array[SearchParticipant](SearchEngine.getDefaultSearchParticipant()), - searchScope, new SearchHandler(callback), null); + try { + searchEngine.search(searchPattern, + Array[SearchParticipant](SearchEngine.getDefaultSearchParticipant), + searchScope, new SearchHandler(callback), null) + logger.fine("searching...") + } catch { + case e: ClassCastException => findBySourceFile(callback) + case otherException => logger.log(Level.FINE, "some other exception occured", otherException) + } } class SearchHandler(callback: IJavaElement => Unit) extends SearchRequestor { + private var matchFound = false + override def acceptSearchMatch(searchMatch: SearchMatch) = { searchMatch.getElement match { case javaElement: IJavaElement => { - logger.fine(String.format("Match found: %s", javaElement)) + logger.fine("Match found: %s".format(javaElement)) + matchFound = true callback(javaElement) } - case _ => /* nothing to do */ + case other => logger.fine("something else found: %s".format(other.toString)) /* nothing to do */ + } + } + + override def endReporting = { + if (!matchFound) { + logger.fine("no match found") + findBySourceFile(callback) } } } + + private def findBySourceFile(callback: IJavaElement => Unit) = { + SourceFileFinder.fromSourceFileName(covClass.coverageData.sourceFileName) + } } \ No newline at end of file diff --git a/ecobertura.ui/src/main/scala/ecobertura/ui/util/SourceFileFinder.scala b/ecobertura.ui/src/main/scala/ecobertura/ui/util/SourceFileFinder.scala new file mode 100644 index 0000000..4d3d848 --- /dev/null +++ b/ecobertura.ui/src/main/scala/ecobertura/ui/util/SourceFileFinder.scala @@ -0,0 +1,63 @@ +/* + * This file is part of eCobertura. + * + * Copyright (c) 2010 Joachim Hofer + * All rights reserved. + * + * eCobertura is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * eCobertura is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with eCobertura. If not, see . + */ +package ecobertura.ui.util + +import java.util.logging._ +import java.util.regex.Pattern + +import org.eclipse.core.resources._ +import org.eclipse.search.core.text._ + +import ecobertura.ui.views.session.CoverageSessionClass + +object SourceFileFinder { + val logger = Logger.getLogger("ecobertura.ui.util") + val searchEngine = TextSearchEngine.create + val everythingPattern = Pattern.compile(".*") + + def fromSourceFileName(sourceFileName: String) = new SourceFileFinder(sourceFileName) +} + +class SourceFileFinder(sourceFileName: String) { + import SourceFileFinder._ + + logger.fine("trying to find %s".format(sourceFileName)) + val workspaceRoot = ResourcesPlugin.getWorkspace.getRoot + val fileSearchPattern = Pattern.compile(Pattern.quote(sourceFileName)) + + val scope = TextSearchScope.newSearchScope(Array[IResource](workspaceRoot), + fileSearchPattern, false) + + searchEngine.search(scope, new SearchHandler, everythingPattern, null) + + class SearchHandler extends TextSearchRequestor { + private var matchFound = false + + override def acceptFile(file: IFile) = { + logger.fine("file found: %s".format(file.toString)) + matchFound = true + false + } + + override def endReporting = { + if (!matchFound) logger.fine("no match found") + } + } +} diff --git a/ecobertura.ui/src/main/scala/ecobertura/ui/views/session/commands/OpenCoveredClassHandler.scala b/ecobertura.ui/src/main/scala/ecobertura/ui/views/session/commands/OpenCoveredClassHandler.scala index f24988f..656ea08 100644 --- a/ecobertura.ui/src/main/scala/ecobertura/ui/views/session/commands/OpenCoveredClassHandler.scala +++ b/ecobertura.ui/src/main/scala/ecobertura/ui/views/session/commands/OpenCoveredClassHandler.scala @@ -42,12 +42,12 @@ class OpenCoveredClassHandler extends AbstractHandler { view.selection match { case structuredSelection: IStructuredSelection => handleStructuredSelection(structuredSelection.getFirstElement) - case _ => /* nothing to do */ + case _ => logger.fine("not a structured selection") /* nothing to do */ } def handleStructuredSelection(selectedObject: Any) = selectedObject match { case covClass: CoverageSessionClass => handleClassSelection(covClass) - case _ => /* nothing to do */ + case _ => logger.fine("not a CoverageSessionClass") /* nothing to do */ } def handleClassSelection(covClass: CoverageSessionClass) = { From 3c6e7b243219ca6d4419a6a54247a2f25c4d176a Mon Sep 17 00:00:00 2001 From: Joachim Hofer Date: Sat, 17 Apr 2010 15:37:47 +0200 Subject: [PATCH 6/8] Now finds files and opens editors via standard TextSearchEngine instead of the Java SearchEngine, which works a lot better with Scala files. --- .../ui/util/JavaElementFinder.scala | 86 ------------ .../ecobertura/ui/util/SourceFileFinder.scala | 12 +- .../commands/OpenCoveredClassHandler.scala | 123 +++++++++--------- 3 files changed, 71 insertions(+), 150 deletions(-) delete mode 100644 ecobertura.ui/src/main/scala/ecobertura/ui/util/JavaElementFinder.scala diff --git a/ecobertura.ui/src/main/scala/ecobertura/ui/util/JavaElementFinder.scala b/ecobertura.ui/src/main/scala/ecobertura/ui/util/JavaElementFinder.scala deleted file mode 100644 index e03ae0d..0000000 --- a/ecobertura.ui/src/main/scala/ecobertura/ui/util/JavaElementFinder.scala +++ /dev/null @@ -1,86 +0,0 @@ -/* - * This file is part of eCobertura. - * - * Copyright (c) 2009, 2010 Joachim Hofer - * All rights reserved. - * - * eCobertura is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * eCobertura is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with eCobertura. If not, see . - */ -package ecobertura.ui.util - -import java.util.logging._ -import org.eclipse.jdt.core.IJavaElement -import org.eclipse.jdt.core.search._ - -import ecobertura.ui.views.session.CoverageSessionClass - -object JavaElementFinder { - val logger = Logger.getLogger("ecobertura.ui.util") - val searchEngine = new SearchEngine - val searchScope = SearchEngine.createWorkspaceScope - - def fromCoverageSessionClass(covClass: CoverageSessionClass) = new JavaElementFinder(covClass) -} - -class JavaElementFinder(covClass: CoverageSessionClass) { - import JavaElementFinder._ - - val qualifiedClassNameToFind = - if (covClass.coverageData.packageName.isEmpty) covClass.coverageData.name - else "%s.%s".format(covClass.coverageData.packageName, covClass.coverageData.name) - logger.fine("looking for %s".format(qualifiedClassNameToFind)) - - val searchPattern = SearchPattern.createPattern( - qualifiedClassNameToFind, - IJavaSearchConstants.TYPE, IJavaSearchConstants.DECLARATIONS, - SearchPattern.R_EXACT_MATCH) - - def find(callback: IJavaElement => Unit) = { - try { - searchEngine.search(searchPattern, - Array[SearchParticipant](SearchEngine.getDefaultSearchParticipant), - searchScope, new SearchHandler(callback), null) - logger.fine("searching...") - } catch { - case e: ClassCastException => findBySourceFile(callback) - case otherException => logger.log(Level.FINE, "some other exception occured", otherException) - } - } - - class SearchHandler(callback: IJavaElement => Unit) extends SearchRequestor { - private var matchFound = false - - override def acceptSearchMatch(searchMatch: SearchMatch) = { - searchMatch.getElement match { - case javaElement: IJavaElement => { - logger.fine("Match found: %s".format(javaElement)) - matchFound = true - callback(javaElement) - } - case other => logger.fine("something else found: %s".format(other.toString)) /* nothing to do */ - } - } - - override def endReporting = { - if (!matchFound) { - logger.fine("no match found") - findBySourceFile(callback) - } - } - } - - private def findBySourceFile(callback: IJavaElement => Unit) = { - SourceFileFinder.fromSourceFileName(covClass.coverageData.sourceFileName) - } -} \ No newline at end of file diff --git a/ecobertura.ui/src/main/scala/ecobertura/ui/util/SourceFileFinder.scala b/ecobertura.ui/src/main/scala/ecobertura/ui/util/SourceFileFinder.scala index 4d3d848..78c81fa 100644 --- a/ecobertura.ui/src/main/scala/ecobertura/ui/util/SourceFileFinder.scala +++ b/ecobertura.ui/src/main/scala/ecobertura/ui/util/SourceFileFinder.scala @@ -41,18 +41,20 @@ class SourceFileFinder(sourceFileName: String) { logger.fine("trying to find %s".format(sourceFileName)) val workspaceRoot = ResourcesPlugin.getWorkspace.getRoot val fileSearchPattern = Pattern.compile(Pattern.quote(sourceFileName)) - val scope = TextSearchScope.newSearchScope(Array[IResource](workspaceRoot), fileSearchPattern, false) - - searchEngine.search(scope, new SearchHandler, everythingPattern, null) - - class SearchHandler extends TextSearchRequestor { + + def find(callback: IFile => Unit) = { + searchEngine.search(scope, new SearchHandler(callback), everythingPattern, null) + } + + class SearchHandler(callback: IFile => Unit) extends TextSearchRequestor { private var matchFound = false override def acceptFile(file: IFile) = { logger.fine("file found: %s".format(file.toString)) matchFound = true + callback(file) false } diff --git a/ecobertura.ui/src/main/scala/ecobertura/ui/views/session/commands/OpenCoveredClassHandler.scala b/ecobertura.ui/src/main/scala/ecobertura/ui/views/session/commands/OpenCoveredClassHandler.scala index 656ea08..f0af87d 100644 --- a/ecobertura.ui/src/main/scala/ecobertura/ui/views/session/commands/OpenCoveredClassHandler.scala +++ b/ecobertura.ui/src/main/scala/ecobertura/ui/views/session/commands/OpenCoveredClassHandler.scala @@ -1,60 +1,65 @@ -/* - * This file is part of eCobertura. - * - * Copyright (c) 2009, 2010 Joachim Hofer - * All rights reserved. - * - * eCobertura is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * eCobertura is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with eCobertura. If not, see . - */ -package ecobertura.ui.views.session.commands +/* + * This file is part of eCobertura. + * + * Copyright (c) 2009, 2010 Joachim Hofer + * All rights reserved. + * + * eCobertura is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * eCobertura is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with eCobertura. If not, see . + */ +package ecobertura.ui.views.session.commands + import org.eclipse.ui.part.FileEditorInput -import java.util.logging.Logger -import org.eclipse.jface.viewers.IStructuredSelection -import org.eclipse.jface.viewers.ISelection -import org.eclipse.core.commands._ -import org.eclipse.ui.handlers.HandlerUtil - -import ecobertura.core.data.CoverageSession - -import ecobertura.ui.views.session.CoverageSessionView -import ecobertura.ui.views.session._ -import ecobertura.ui.util._ - -class OpenCoveredClassHandler extends AbstractHandler { - val logger = Logger.getLogger("ecobertura.ui.views.session.command") - - override def execute(event: ExecutionEvent) = { - val window = HandlerUtil.getActiveWorkbenchWindow(event) - val page = window.getActivePage - val view = page.findView(CoverageSessionView.ID).asInstanceOf[CoverageSessionView]; - - view.selection match { - case structuredSelection: IStructuredSelection => - handleStructuredSelection(structuredSelection.getFirstElement) - case _ => logger.fine("not a structured selection") /* nothing to do */ - } - - def handleStructuredSelection(selectedObject: Any) = selectedObject match { - case covClass: CoverageSessionClass => handleClassSelection(covClass) - case _ => logger.fine("not a CoverageSessionClass") /* nothing to do */ - } - - def handleClassSelection(covClass: CoverageSessionClass) = { - JavaElementFinder.fromCoverageSessionClass(covClass).find( - JavaEditorOpener.openAndReveal) - logger.fine(covClass.coverageData.lines.mkString(", ")) - } - null - } -} +import java.util.logging.Logger +import org.eclipse.jface.viewers.IStructuredSelection +import org.eclipse.jface.viewers.ISelection +import org.eclipse.core.commands._ +import org.eclipse.ui.PlatformUI +import org.eclipse.ui.handlers.HandlerUtil + +import ecobertura.core.data.CoverageSession + +import ecobertura.ui.views.session.CoverageSessionView +import ecobertura.ui.views.session._ +import ecobertura.ui.util._ + +class OpenCoveredClassHandler extends AbstractHandler { + val logger = Logger.getLogger("ecobertura.ui.views.session.command") + + override def execute(event: ExecutionEvent) = { + val window = HandlerUtil.getActiveWorkbenchWindow(event) + val page = window.getActivePage + val view = page.findView(CoverageSessionView.ID).asInstanceOf[CoverageSessionView]; + + view.selection match { + case structuredSelection: IStructuredSelection => + handleStructuredSelection(structuredSelection.getFirstElement) + case _ => logger.fine("not a structured selection") /* nothing to do */ + } + + def handleStructuredSelection(selectedObject: Any) = selectedObject match { + case covClass: CoverageSessionClass => handleClassSelection(covClass) + case _ => logger.fine("not a CoverageSessionClass") /* nothing to do */ + } + + def handleClassSelection(covClass: CoverageSessionClass) = { + SourceFileFinder.fromSourceFileName(covClass.coverageData.sourceFileName).find( + file => { + val defaultEditor = PlatformUI.getWorkbench.getEditorRegistry.getDefaultEditor(file.getName); + page.openEditor(new FileEditorInput(file), defaultEditor.getId()); + } + ) + } + null + } +} From 632d5eada193fcb193f16d533a53cccbe7b10afd Mon Sep 17 00:00:00 2001 From: Joachim Hofer Date: Sat, 17 Apr 2010 15:40:58 +0200 Subject: [PATCH 7/8] preparing for 0.9.4 release... --- ecobertura.core/META-INF/MANIFEST.MF | 2 +- ecobertura.feature/feature.xml | 2 +- ecobertura.pde/category.xml | 2 +- ecobertura.ui/META-INF/MANIFEST.MF | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ecobertura.core/META-INF/MANIFEST.MF b/ecobertura.core/META-INF/MANIFEST.MF index c0dc505..fead7ef 100644 --- a/ecobertura.core/META-INF/MANIFEST.MF +++ b/ecobertura.core/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: eCobertura Core Bundle-SymbolicName: ecobertura.core;singleton:=true -Bundle-Version: 0.9.3.qualifier +Bundle-Version: 0.9.4.qualifier Bundle-Activator: ecobertura.core.CorePlugin Bundle-Localization: OSGI-INF/l10n/bundle Bundle-Vendor: jmhofer diff --git a/ecobertura.feature/feature.xml b/ecobertura.feature/feature.xml index 7d0fa32..905506c 100644 --- a/ecobertura.feature/feature.xml +++ b/ecobertura.feature/feature.xml @@ -2,7 +2,7 @@ diff --git a/ecobertura.pde/category.xml b/ecobertura.pde/category.xml index de11d8e..3d0a332 100644 --- a/ecobertura.pde/category.xml +++ b/ecobertura.pde/category.xml @@ -1,6 +1,6 @@ - + diff --git a/ecobertura.ui/META-INF/MANIFEST.MF b/ecobertura.ui/META-INF/MANIFEST.MF index b444823..9f0b162 100644 --- a/ecobertura.ui/META-INF/MANIFEST.MF +++ b/ecobertura.ui/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: eCobertura UI Bundle-SymbolicName: ecobertura.ui;singleton:=true -Bundle-Version: 0.9.3.qualifier +Bundle-Version: 0.9.4.qualifier Bundle-Activator: ecobertura.ui.UIPlugin Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime, From abfedd3afb06c9ca56b46368f46c5004c2b95dbf Mon Sep 17 00:00:00 2001 From: Joachim Hofer Date: Sat, 17 Apr 2010 16:07:22 +0200 Subject: [PATCH 8/8] changed website in feature description --- ecobertura.feature/feature.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ecobertura.feature/feature.xml b/ecobertura.feature/feature.xml index 905506c..2223053 100644 --- a/ecobertura.feature/feature.xml +++ b/ecobertura.feature/feature.xml @@ -6,8 +6,10 @@ provider-name="jmhofer" plugin="ecobertura.ui"> - - eCobertura is a free Eclipse plug-in for Cobertura (a Java code coverage reporting tool based on jcoverage 1.0.5). See the eCobertura web page for more details. + + eCobertura is a free Eclipse plug-in for Cobertura (a Java code +coverage reporting tool based on jcoverage 1.0.5). See the eCobertura +web page for more details.