Optimize DirectoriesScope::contains

Previously its complexity was O(directoriesCount * pathSize),
now it's O(pathSize) in average
This commit is contained in:
Denis Zharkov
2017-07-20 19:14:18 +03:00
parent 5bb88b659b
commit 8753baeab6
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.cli.jvm.compiler
import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiJavaModule import com.intellij.psi.PsiJavaModule
import com.intellij.psi.PsiManager import com.intellij.psi.PsiManager
@@ -129,7 +128,7 @@ object KotlinToJVMBytecodeCompiler {
} }
val targetDescription = "in targets [" + chunk.joinToString { input -> input.getModuleName() + "-" + input.getModuleType() } + "]" val targetDescription = "in targets [" + chunk.joinToString { input -> input.getModuleName() + "-" + input.getModuleType() } + "]"
val result = repeatAnalysisIfNeeded(analyze(environment, targetDescription), environment, targetDescription) val result = repeatAnalysisIfNeeded(analyze(environment, targetDescription), environment, targetDescription)
if (result == null || !result.shouldGenerateCode) return false if (result == null || !result.shouldGenerateCode) return false
@@ -279,15 +278,15 @@ object KotlinToJVMBytecodeCompiler {
return ExitCode.OK return ExitCode.OK
} }
private fun repeatAnalysisIfNeeded( private fun repeatAnalysisIfNeeded(
result: AnalysisResult?, result: AnalysisResult?,
environment: KotlinCoreEnvironment, environment: KotlinCoreEnvironment,
targetDescription: String? targetDescription: String?
): AnalysisResult? { ): AnalysisResult? {
if (result is AnalysisResult.RetryWithAdditionalJavaRoots) { if (result is AnalysisResult.RetryWithAdditionalJavaRoots) {
val configuration = environment.configuration val configuration = environment.configuration
val oldReadOnlyValue = configuration.isReadOnly val oldReadOnlyValue = configuration.isReadOnly
configuration.isReadOnly = false configuration.isReadOnly = false
configuration.addJavaSourceRoots(result.additionalJavaRoots) configuration.addJavaSourceRoots(result.additionalJavaRoots)
@@ -308,7 +307,7 @@ object KotlinToJVMBytecodeCompiler {
// Repeat analysis with additional Java roots (kapt generated sources) // Repeat analysis with additional Java roots (kapt generated sources)
return analyze(environment, targetDescription) return analyze(environment, targetDescription)
} }
return result return result
} }
@@ -367,7 +366,7 @@ object KotlinToJVMBytecodeCompiler {
val analyzerWithCompilerReport = AnalyzerWithCompilerReport(collector) val analyzerWithCompilerReport = AnalyzerWithCompilerReport(collector)
analyzerWithCompilerReport.analyzeAndReport(sourceFiles) { analyzerWithCompilerReport.analyzeAndReport(sourceFiles) {
val project = environment.project val project = environment.project
val moduleOutputs = environment.configuration.get(JVMConfigurationKeys.MODULES)?.mapNotNull { module -> val moduleOutputs = environment.configuration.get(JVMConfigurationKeys.MODULES)?.mapNotNullTo(hashSetOf()) { module ->
environment.findLocalFile(module.getOutputDirectory()) environment.findLocalFile(module.getOutputDirectory())
}.orEmpty() }.orEmpty()
val sourcesOnly = TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, sourceFiles) val sourcesOnly = TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, sourceFiles)
@@ -404,11 +403,20 @@ object KotlinToJVMBytecodeCompiler {
} }
class DirectoriesScope( class DirectoriesScope(
project: Project, private val directories: List<VirtualFile> project: Project,
private val directories: Set<VirtualFile>
) : DelegatingGlobalSearchScope(GlobalSearchScope.allScope(project)) { ) : DelegatingGlobalSearchScope(GlobalSearchScope.allScope(project)) {
// TODO: optimize somehow? private val fileSystems = directories.mapTo(hashSetOf(), VirtualFile::getFileSystem)
override fun contains(file: VirtualFile) =
directories.any { directory -> VfsUtilCore.isAncestor(directory, file, false) } override fun contains(file: VirtualFile): Boolean {
if (file.fileSystem !in fileSystems) return false
var parent: VirtualFile = file
while (true) {
if (parent in directories) return true
parent = parent.parent ?: return false
}
}
override fun toString() = "All files under: $directories" override fun toString() = "All files under: $directories"
} }