refactor for clarity; don't ignore XxxPackage files not related to Kotlin

This commit is contained in:
Dmitry Jemerov
2014-12-29 13:57:56 +01:00
parent 553fd4dd12
commit d1123e116f
@@ -26,8 +26,6 @@ import java.io.File
import org.jetbrains.jet.lang.psi.JetFile import org.jetbrains.jet.lang.psi.JetFile
import org.jetbrains.jet.plugin.debugger.JetPositionManager import org.jetbrains.jet.plugin.debugger.JetPositionManager
import org.jetbrains.jet.plugin.caches.resolve.getModuleInfo import org.jetbrains.jet.plugin.caches.resolve.getModuleInfo
import java.util.HashSet
import org.jetbrains.jet.lang.psi.JetTreeVisitor
import org.jetbrains.jet.lang.psi.JetDeclaration import org.jetbrains.jet.lang.psi.JetDeclaration
import com.intellij.openapi.roots.ProjectRootManager import com.intellij.openapi.roots.ProjectRootManager
import org.jetbrains.jet.lang.psi.JetTreeVisitorVoid import org.jetbrains.jet.lang.psi.JetTreeVisitorVoid
@@ -46,6 +44,10 @@ import org.jetbrains.jet.lang.psi.JetClassOrObject
import org.jetbrains.jet.lang.resolve.kotlin.PackagePartClassUtils import org.jetbrains.jet.lang.resolve.kotlin.PackagePartClassUtils
import com.intellij.openapi.vfs.VfsUtilCore import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.diagnostic.Logger
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils
import org.jetbrains.jet.lang.resolve.kotlin.KotlinBinaryClassCache
import com.intellij.openapi.vfs.LocalFileSystem
import org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassHeader
public class KotlinCoverageExtension(): JavaCoverageEngineExtension() { public class KotlinCoverageExtension(): JavaCoverageEngineExtension() {
private val LOG = Logger.getInstance(javaClass<KotlinCoverageExtension>()) private val LOG = Logger.getInstance(javaClass<KotlinCoverageExtension>())
@@ -63,50 +65,68 @@ public class KotlinCoverageExtension(): JavaCoverageEngineExtension() {
// Implements API added in IDEA 14.1 // Implements API added in IDEA 14.1
fun getSummaryCoverageInfo(coverageAnnotator: JavaCoverageAnnotator, fun getSummaryCoverageInfo(coverageAnnotator: JavaCoverageAnnotator,
element: PsiNamedElement): PackageAnnotator.ClassCoverageInfo? { element: PsiNamedElement): PackageAnnotator.ClassCoverageInfo? {
if (element is JetFile) { if (element !is JetFile) {
LOG.info("Retrieving coverage for " + element.getName()) return null
val module = ModuleUtilCore.findModuleForPsiElement(element) }
if (module == null) return null LOG.info("Retrieving coverage for " + element.getName())
val fileIndex = ProjectRootManager.getInstance(element.getProject()).getFileIndex() val outputRoot = findOutputRoot(element)
val inTests = fileIndex.isInTestSourceContent(element.getVirtualFile()) val existingClassFiles = getClassesGeneratedFromFile(outputRoot, element)
val compilerOutputExtension = CompilerModuleExtension.getInstance(module) if (existingClassFiles.isEmpty()) {
val outputRoot = if (inTests) return null
compilerOutputExtension.getCompilerOutputPathForTests() }
else LOG.debug("Classfiles: [${existingClassFiles.map { it.getName() }.join()}]")
compilerOutputExtension.getCompilerOutputPath() val qualifiedNames = existingClassFiles.map {
if (outputRoot == null) return null val relativePath = VfsUtilCore.getRelativePath(it, outputRoot)
val fqName = element.getPackageFqName().asString().replace('.', '/') StringUtil.trimEnd(relativePath, ".class").replace("/", ".")
val packageOutputDir = outputRoot.findFileByRelativePath(fqName) }
if (packageOutputDir == null) return null
val prefixes = collectClassFilePrefixes(element) return totalCoverageForQualifiedNames(coverageAnnotator, qualifiedNames)
LOG.debug("Classfile prefixes: [${prefixes.join(", ")}]") }
val existingClassFiles = packageOutputDir.getChildren().filter {
file -> prefixes.any { file.getName().startsWith(it + "$") || file.getName().equals(it + ".class") } private fun getClassesGeneratedFromFile(outputRoot: VirtualFile?, file: JetFile): List<VirtualFile> {
val relativePath = file.getPackageFqName().asString().replace('.', '/')
val packageOutputDir = outputRoot?.findFileByRelativePath(relativePath)
if (packageOutputDir == null) return listOf()
val prefixes = collectClassFilePrefixes(file)
LOG.debug("Classfile prefixes: [${prefixes.join(", ")}]")
return packageOutputDir.getChildren().filter {
file -> prefixes.any { file.getName().startsWith(it + "$") || file.getName().equals(it + ".class") }
}
}
private fun totalCoverageForQualifiedNames(coverageAnnotator: JavaCoverageAnnotator,
qualifiedNames: List<String>): PackageAnnotator.ClassCoverageInfo {
val result = PackageAnnotator.ClassCoverageInfo()
result.totalClassCount = 0
qualifiedNames.forEach {
val classInfo = coverageAnnotator.getClassCoverageInfo(it)
if (classInfo != null) {
result.totalClassCount += classInfo.totalClassCount
result.coveredClassCount += classInfo.coveredClassCount
result.totalMethodCount += classInfo.totalMethodCount
result.coveredMethodCount += classInfo.coveredMethodCount
result.totalLineCount += classInfo.totalLineCount
result.fullyCoveredLineCount += classInfo.fullyCoveredLineCount
result.partiallyCoveredLineCount += classInfo.partiallyCoveredLineCount
} }
if (existingClassFiles.size() > 0) { else {
LOG.debug("Classfiles: [${existingClassFiles.map { it.getName() }.join()}]") LOG.debug("Found no coverage for ${it}")
val result = PackageAnnotator.ClassCoverageInfo()
result.totalClassCount = 0
existingClassFiles.forEach {
val relativePath = VfsUtilCore.getRelativePath(it, outputRoot)
val qName = StringUtil.trimEnd(relativePath, ".class").replace("/", ".")
val classInfo = coverageAnnotator.getClassCoverageInfo(qName)
if (classInfo != null) {
result.totalClassCount += classInfo.totalClassCount
result.coveredClassCount += classInfo.coveredClassCount
result.totalMethodCount += classInfo.totalMethodCount
result.coveredMethodCount += classInfo.coveredMethodCount
result.totalLineCount += classInfo.totalLineCount
result.fullyCoveredLineCount += classInfo.fullyCoveredLineCount
result.partiallyCoveredLineCount += classInfo.partiallyCoveredLineCount
} else {
LOG.debug("Found no coverage for ${qName}")
}
}
return result
} }
} }
return null return result
}
private fun findOutputRoot(file: JetFile): VirtualFile? {
val module = ModuleUtilCore.findModuleForPsiElement(file)
if (module == null) return null
val fileIndex = ProjectRootManager.getInstance(file.getProject()).getFileIndex()
val inTests = fileIndex.isInTestSourceContent(file.getVirtualFile())
val compilerOutputExtension = CompilerModuleExtension.getInstance(module)
return if (inTests)
compilerOutputExtension.getCompilerOutputPathForTests()
else
compilerOutputExtension.getCompilerOutputPath()
} }
private fun collectClassFilePrefixes(file: JetFile): Collection<String> { private fun collectClassFilePrefixes(file: JetFile): Collection<String> {
@@ -123,14 +143,21 @@ public class KotlinCoverageExtension(): JavaCoverageEngineExtension() {
// Implements API added in IDEA 14.1 // Implements API added in IDEA 14.1
fun ignoreCoverageForClass(bundle: CoverageSuitesBundle, classFile: File): Boolean { fun ignoreCoverageForClass(bundle: CoverageSuitesBundle, classFile: File): Boolean {
val packageName = classFile.getParentFile().getName()
// Ignore classes that only contain bridge methods delegating to package parts. // Ignore classes that only contain bridge methods delegating to package parts.
if (classFile.getName().equals(StringUtil.capitalize(packageName) + "Package.class")) { if (looksLikePackageFacade(classFile)) {
return true val classVFile = LocalFileSystem.getInstance().findFileByIoFile(classFile)
if (classVFile == null) return false
val header = KotlinBinaryClassCache.getKotlinBinaryClass(classVFile)?.getClassHeader()
return header != null && header.kind == KotlinClassHeader.Kind.PACKAGE_FACADE;
} }
return false; return false;
} }
fun looksLikePackageFacade(classFile: File): Boolean {
val packageName = classFile.getParentFile().getName()
return classFile.getName() == StringUtil.capitalize(packageName) + PackageClassUtils.PACKAGE_CLASS_NAME_SUFFIX + ".class"
}
override fun collectOutputFiles(srcFile: PsiFile, override fun collectOutputFiles(srcFile: PsiFile,
output: VirtualFile?, output: VirtualFile?,
testoutput: VirtualFile?, testoutput: VirtualFile?,