From bd50ad87ba84527c3dcab5c25f1ce2fe44086303 Mon Sep 17 00:00:00 2001 From: Alexey Tsvetkov Date: Tue, 10 Apr 2018 16:08:11 +0300 Subject: [PATCH] Use KotlinCoreEnvironment for parsing Kotlin in IC Creating and disposing CoreApplicationEnvironment on each call leads to problems with parallel builds, while KotlinCoreEnvironment avoids disposing application environment in case of parallel builds. #KT-23694 fixed --- .../incremental/parsing/parseFileUtils.kt | 80 ++++++------------- .../compilerRunner/CompilerRunnerUtil.kt | 2 +- 2 files changed, 24 insertions(+), 58 deletions(-) diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/parsing/parseFileUtils.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/parsing/parseFileUtils.kt index 71e9e2ed8c5..78993d65dd7 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/parsing/parseFileUtils.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/parsing/parseFileUtils.kt @@ -5,44 +5,48 @@ package org.jetbrains.kotlin.incremental.parsing -import com.intellij.core.CoreApplicationEnvironment -import com.intellij.core.CoreProjectEnvironment -import com.intellij.lang.MetaLanguage import com.intellij.openapi.Disposable -import com.intellij.openapi.extensions.Extensions -import com.intellij.openapi.project.Project import com.intellij.openapi.util.Disposer import com.intellij.openapi.vfs.StandardFileSystems import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.openapi.vfs.local.CoreLocalFileSystem import com.intellij.psi.PsiManager import com.intellij.psi.SingleRootFileViewProvider -import org.jetbrains.kotlin.idea.KotlinFileType -import org.jetbrains.kotlin.parsing.KotlinParserDefinition +import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.script.KotlinScriptDefinition -import org.jetbrains.kotlin.script.ScriptDefinitionProvider import java.io.File import java.util.* -fun classesFqNames(files: Set): Set = withPsiSetup { - val psiManager = PsiManager.getInstance(project) +fun classesFqNames(files: Set): Set { + val existingKotlinFiles = files.filter { it.name.endsWith(".kt", ignoreCase = true) && it.isFile } + if (existingKotlinFiles.isEmpty()) return emptySet() + + val disposable = Disposer.newDisposable() + + return try { + classesFqNames(existingKotlinFiles, disposable) + } finally { + Disposer.dispose(disposable) + } +} + +private fun classesFqNames(kotlinFiles: Collection, disposable: Disposable): Set { + val config = CompilerConfiguration() + val configFiles = EnvironmentConfigFiles.JVM_CONFIG_FILES + val environment = KotlinCoreEnvironment.createForProduction(disposable, config, configFiles) + val psiManager = PsiManager.getInstance(environment.project) val fileManager = VirtualFileManager.getInstance() val localFS = fileManager.getFileSystem(StandardFileSystems.FILE_PROTOCOL) as CoreLocalFileSystem - classesFqNames(files, psiManager, localFS) -} - -private fun classesFqNames(files: Collection, psiManager: PsiManager, localFS: CoreLocalFileSystem): Set { val result = HashSet() - for (file in files) { - if (!file.name.endsWith(".kt", ignoreCase = true)) continue - - val virtualFile = localFS.findFileByIoFile(file) ?: continue + for (file in kotlinFiles) { + val virtualFile = localFS.findFileByIoFile(file)!! for (psiFile in SingleRootFileViewProvider(psiManager, virtualFile).allFiles) { if (psiFile !is KtFile) continue @@ -65,41 +69,3 @@ private fun classesFqNames(files: Collection, psiManager: PsiManager, loca private fun Collection.filterClassesTo(classes: Deque) { filterIsInstanceTo>(classes) } - -private data class PsiSetup( - val applicationEnvironment: CoreApplicationEnvironment, - val projectEnvironment: CoreProjectEnvironment, - val project: Project, - val disposable: Disposable -) - -private inline fun withPsiSetup(fn: PsiSetup.() -> T): T { - val disposable = Disposer.newDisposable() - - return try { - val applicationEnvironment = CoreApplicationEnvironment(disposable, false) - val projectEnvironment = CoreProjectEnvironment(disposable, applicationEnvironment) - CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), MetaLanguage.EP_NAME, MetaLanguage::class.java) - applicationEnvironment.registerApplicationService(ScriptDefinitionProvider::class.java, - NoopScriptDefinitionProvider() - ) - applicationEnvironment.registerFileType(KotlinFileType.INSTANCE, "kt") - applicationEnvironment.registerParserDefinition(KotlinParserDefinition()) - - val project = projectEnvironment.project - val setup = PsiSetup(applicationEnvironment, projectEnvironment, project, disposable) - setup.fn() - } finally { - Disposer.dispose(disposable) - } -} - -private class NoopScriptDefinitionProvider : ScriptDefinitionProvider { - override fun isScript(fileName: String): Boolean { - return false - } - - override fun findScriptDefinition(fileName: String): KotlinScriptDefinition? { - return null - } -} \ No newline at end of file diff --git a/jps-plugin/src/org/jetbrains/kotlin/compilerRunner/CompilerRunnerUtil.kt b/jps-plugin/src/org/jetbrains/kotlin/compilerRunner/CompilerRunnerUtil.kt index 998f615ceff..66ace28275e 100644 --- a/jps-plugin/src/org/jetbrains/kotlin/compilerRunner/CompilerRunnerUtil.kt +++ b/jps-plugin/src/org/jetbrains/kotlin/compilerRunner/CompilerRunnerUtil.kt @@ -104,7 +104,7 @@ object CompilerRunnerUtil { environment: JpsCompilerEnvironment, files: Set ): Set = withCompilerClassloader(environment) { classLoader -> - val klass = Class.forName("org.jetbrains.kotlin.parsing.util.ParseFileUtilsKt", true, classLoader) + val klass = Class.forName("org.jetbrains.kotlin.incremental.parsing.ParseFileUtilsKt", true, classLoader) val method = klass.getMethod("classesFqNames", Set::class.java) @Suppress("UNCHECKED_CAST") method.invoke(klass, files) as? Set