From 657b50737155165e86a4ab016855747865255cc3 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 13 Jan 2015 15:42:15 +0100 Subject: [PATCH] Improve code coverage performance: always get the .class files corresponding to a source file by looking at the output directory, not by analyzing the source file. --- .../idea/coverage/KotlinCoverageExtension.kt | 72 +++++-------------- 1 file changed, 19 insertions(+), 53 deletions(-) diff --git a/idea/src/org/jetbrains/kotlin/idea/coverage/KotlinCoverageExtension.kt b/idea/src/org/jetbrains/kotlin/idea/coverage/KotlinCoverageExtension.kt index ca2c2f35c90..fe2d4b206bc 100644 --- a/idea/src/org/jetbrains/kotlin/idea/coverage/KotlinCoverageExtension.kt +++ b/idea/src/org/jetbrains/kotlin/idea/coverage/KotlinCoverageExtension.kt @@ -24,15 +24,7 @@ import com.intellij.openapi.vfs.VirtualFile import com.intellij.coverage.CoverageSuitesBundle import java.io.File import org.jetbrains.kotlin.psi.JetFile -import org.jetbrains.kotlin.idea.debugger.JetPositionManager -import org.jetbrains.kotlin.idea.caches.resolve.getModuleInfo -import org.jetbrains.kotlin.psi.JetDeclaration import com.intellij.openapi.roots.ProjectRootManager -import org.jetbrains.kotlin.psi.JetTreeVisitorVoid -import com.intellij.openapi.application.ApplicationManager -import org.jetbrains.kotlin.psi.JetFunctionLiteralExpression -import com.intellij.psi.PsiElement -import java.util.LinkedHashSet import com.intellij.psi.PsiClass import com.intellij.openapi.util.text.StringUtil import com.intellij.psi.PsiNamedElement @@ -49,6 +41,7 @@ import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache import com.intellij.openapi.vfs.LocalFileSystem import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import com.intellij.openapi.util.io.FileUtilRt +import org.jetbrains.kotlin.idea.util.application.runReadAction public class KotlinCoverageExtension(): JavaCoverageEngineExtension() { private val LOG = Logger.getInstance(javaClass()) @@ -57,8 +50,11 @@ public class KotlinCoverageExtension(): JavaCoverageEngineExtension() { override fun suggestQualifiedName(sourceFile: PsiFile, classes: Array, names: MutableSet): Boolean { if (sourceFile is JetFile) { - names.addAll(collectOutputClassNames(sourceFile).map { StringUtil.replaceChar(it, '/', '.' )}) - return true + val qNames = collectGeneratedClassQualifiedNames(sourceFile) + if (qNames != null) { + names.addAll(qNames) + return true + } } return false } @@ -70,18 +66,22 @@ public class KotlinCoverageExtension(): JavaCoverageEngineExtension() { return null } LOG.info("Retrieving coverage for " + element.getName()) - val outputRoot = findOutputRoot(element) - val existingClassFiles = getClassesGeneratedFromFile(outputRoot, element) + + val qualifiedNames = collectGeneratedClassQualifiedNames(element) + return if (qualifiedNames == null) null else totalCoverageForQualifiedNames(coverageAnnotator, qualifiedNames) + } + + private fun collectGeneratedClassQualifiedNames(file: JetFile): List? { + val outputRoot = findOutputRoot(file) + val existingClassFiles = getClassesGeneratedFromFile(outputRoot, file) if (existingClassFiles.isEmpty()) { return null } LOG.debug("Classfiles: [${existingClassFiles.map { it.getName() }.join()}]") - val qualifiedNames = existingClassFiles.map { + return existingClassFiles.map { val relativePath = VfsUtilCore.getRelativePath(it, outputRoot) StringUtil.trimEnd(relativePath, ".class").replace("/", ".") } - - return totalCoverageForQualifiedNames(coverageAnnotator, qualifiedNames) } private fun getClassesGeneratedFromFile(outputRoot: VirtualFile?, file: JetFile): List { @@ -174,47 +174,13 @@ public class KotlinCoverageExtension(): JavaCoverageEngineExtension() { return false } - val classNames = ApplicationManager.getApplication().runReadAction> { collectOutputClassNames(srcFile) } - - fun findUnder(name: String, root: VirtualFile?): File? { - if (root != null) { - val outputFile = File(root.getPath(), name + ".class") - if (outputFile.exists()) { - return outputFile - } - } - return null + runReadAction { + val outputRoot = findOutputRoot(srcFile) + val existingClassFiles = getClassesGeneratedFromFile(outputRoot, srcFile) + existingClassFiles.mapTo(classFiles) { File(it.getPath())} } - - classNames.map { findUnder(it, output) ?: findUnder(it, testoutput) }.filterNotNullTo(classFiles) return true } return false } - - class object { - public fun collectOutputClassNames(srcFile: JetFile): Set { - val typeMapper = JetPositionManager.createTypeMapper(srcFile, srcFile.getModuleInfo()) - val classNames = LinkedHashSet() - srcFile.acceptChildren(object: JetTreeVisitorVoid() { - override fun visitDeclaration(dcl: JetDeclaration) { - super.visitDeclaration(dcl) - collectClassName(dcl.getFirstChild()) - } - - override fun visitFunctionLiteralExpression(expression: JetFunctionLiteralExpression) { - super.visitFunctionLiteralExpression(expression) - collectClassName(expression.getFunctionLiteral().getFirstChild()) - } - - private fun collectClassName(element: PsiElement) { - val className = JetPositionManager.getClassNameForElement(element, typeMapper, srcFile, false) - if (className != null) { - classNames.add(className) - } - } - }) - return classNames - } - } }