From 84d62f37ebcebb7938f763035444c37bec492027 Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Tue, 21 Jun 2016 21:19:14 +0300 Subject: [PATCH] Kapt: Analyze sources again if the received analysis result is 'RetryWithAdditionalJavaRoots'. -> Add additional Java roots to Java source roots and clear diagnostic messages before the next analysis round. (cherry picked from commit 17ad807) --- .../messages/FilteringMessageCollector.java | 5 +++ .../messages/GroupingMessageCollector.java | 5 +++ .../cli/common/messages/MessageCollector.java | 7 ++++ .../messages/PrintingMessageCollector.java | 5 +++ .../CliLightClassGenerationSupport.kt | 2 +- .../cli/jvm/compiler/JvmDependenciesIndex.kt | 12 +++---- .../cli/jvm/compiler/KotlinCoreEnvironment.kt | 32 ++++++++----------- .../compiler/KotlinToJVMBytecodeCompiler.kt | 32 +++++++++++++++++-- .../kotlin/analyzer/AnalysisResult.kt | 7 ++++ .../kotlin/config/CompilerConfiguration.java | 4 +++ .../xml/AbstractModuleXmlParserTest.java | 5 +++ .../kotlin/jps/build/KotlinBuilder.kt | 4 +++ 12 files changed, 93 insertions(+), 27 deletions(-) diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/messages/FilteringMessageCollector.java b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/messages/FilteringMessageCollector.java index 379fdfa586a93..677f75b0d7a42 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/messages/FilteringMessageCollector.java +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/messages/FilteringMessageCollector.java @@ -28,6 +28,11 @@ public FilteringMessageCollector(@NotNull MessageCollector messageCollector, @No this.decline = decline; } + @Override + public void clear() { + messageCollector.clear(); + } + @Override public void report( @NotNull CompilerMessageSeverity severity, @NotNull String message, @NotNull CompilerMessageLocation location diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/messages/GroupingMessageCollector.java b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/messages/GroupingMessageCollector.java index 971abc9bd8722..793c0b358d38b 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/messages/GroupingMessageCollector.java +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/messages/GroupingMessageCollector.java @@ -33,6 +33,11 @@ public GroupingMessageCollector(@NotNull MessageCollector delegate) { this.delegate = delegate; } + @Override + public void clear() { + groupedMessages.clear(); + } + @Override public void report( @NotNull CompilerMessageSeverity severity, diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/messages/MessageCollector.java b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/messages/MessageCollector.java index 265e1f14ef264..c82ccc612997c 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/messages/MessageCollector.java +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/messages/MessageCollector.java @@ -25,12 +25,19 @@ public void report(@NotNull CompilerMessageSeverity severity, @NotNull String me // Do nothing } + @Override + public void clear() { + // Do nothing + } + @Override public boolean hasErrors() { return false; } }; + void clear(); + void report(@NotNull CompilerMessageSeverity severity, @NotNull String message, @NotNull CompilerMessageLocation location); boolean hasErrors(); diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/PrintingMessageCollector.java b/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/PrintingMessageCollector.java index 476f0ab0581c5..6fd2bacf80922 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/PrintingMessageCollector.java +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/PrintingMessageCollector.java @@ -32,6 +32,11 @@ public PrintingMessageCollector(@NotNull PrintStream errStream, @NotNull Message this.messageRenderer = messageRenderer; } + @Override + public void clear() { + // Do nothing, messages are already reported + } + @Override public void report( @NotNull CompilerMessageSeverity severity, diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliLightClassGenerationSupport.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliLightClassGenerationSupport.kt index 15c3440b1dd5d..b491749d48f58 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliLightClassGenerationSupport.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliLightClassGenerationSupport.kt @@ -64,7 +64,7 @@ class CliLightClassGenerationSupport(project: Project) : LightClassGenerationSup private var bindingContext: BindingContext by Delegates.notNull() private var module: ModuleDescriptor by Delegates.notNull() - + override fun initialize(trace: BindingTrace, module: ModuleDescriptor, codeAnalyzer: KotlinCodeAnalyzer) { this.bindingContext = trace.bindingContext this.module = module diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/JvmDependenciesIndex.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/JvmDependenciesIndex.kt index 592cb9bc2ec1c..004ba086dcefd 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/JvmDependenciesIndex.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/JvmDependenciesIndex.kt @@ -58,16 +58,16 @@ interface JvmDependenciesIndex { ): Set } -interface JvmDependenciesIndexFactory { - fun makeIndexFor(roots: List): JvmDependenciesIndex +interface JvmDependenciesIndexFactory { + fun makeIndexFor(roots: List): T } -class JvmStaticDependenciesIndexFactory : JvmDependenciesIndexFactory { - override fun makeIndexFor(roots: List): JvmDependenciesIndex = JvmDependenciesIndexImpl(roots) +class JvmStaticDependenciesIndexFactory : JvmDependenciesIndexFactory { + override fun makeIndexFor(roots: List) = JvmDependenciesIndexImpl(roots) } -class JvmUpdatableDependenciesIndexFactory : JvmDependenciesIndexFactory { - override fun makeIndexFor(roots: List): JvmDependenciesIndex = JvmDependenciesDynamicCompoundIndex().apply { +class JvmUpdatableDependenciesIndexFactory : JvmDependenciesIndexFactory { + override fun makeIndexFor(roots: List) = JvmDependenciesDynamicCompoundIndex().apply { addIndex(JvmDependenciesIndexImpl(roots)) } } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt index 6db375ee9bc8e..5d43a5778fcb3 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment.kt @@ -107,9 +107,9 @@ class KotlinCoreEnvironment private constructor( } } private val sourceFiles = ArrayList() - private val rootsIndex: JvmDependenciesIndex + private val rootsIndex: JvmDependenciesDynamicCompoundIndex - val configuration: CompilerConfiguration = configuration.copy().apply { setReadOnly(true) } + val configuration: CompilerConfiguration = configuration.copy() init { PersistentFSConstants.setMaxIntellisenseFileSize(FileUtilRt.LARGE_FOR_CONTENT_LOADING) @@ -154,11 +154,9 @@ class KotlinCoreEnvironment private constructor( } val initialRoots = configuration.getList(JVMConfigurationKeys.CONTENT_ROOTS).classpathRoots() - - // TODO: pass index factory in the configuration to avoid selection logic here - // for a moment using updatable index for REPL mode, so we can add roots to classpath then compiling subsequent lines in REPL - val indexFactory = if (configuration.getBoolean(CommonConfigurationKeys.REPL_MODE)) JvmUpdatableDependenciesIndexFactory() - else JvmStaticDependenciesIndexFactory() + + // REPL and kapt2 update classpath dynamically + val indexFactory = JvmUpdatableDependenciesIndexFactory() rootsIndex = indexFactory.makeIndexFor(initialRoots) updateClasspathFromRootsIndex(rootsIndex) @@ -226,19 +224,17 @@ class KotlinCoreEnvironment private constructor( projectEnvironment.addSourcesToClasspath(it.file) } } + + fun updateClasspath(roots: List): List? { + return rootsIndex.addNewIndexForRoots(roots.classpathRoots())?.let { + updateClasspathFromRootsIndex(it) + it.indexedRoots.mapNotNull { File(it.file.path.substringBefore(URLUtil.JAR_SEPARATOR)) }.toList() + } ?: emptyList() + } @Suppress("unused") // used externally - fun tryUpdateClasspath(files: Iterable): List? = - if (rootsIndex !is JvmDependenciesDynamicCompoundIndex) { - report(WARNING, "Unable to update classpath after initialization, it is only allowed in REPL") - null - } - else { - rootsIndex.addNewIndexForRoots(files.map { JvmClasspathRoot(it) }.classpathRoots())?.let { - updateClasspathFromRootsIndex(it) - it.indexedRoots.mapNotNull { File(it.file.path.substringBefore(URLUtil.JAR_SEPARATOR)) }.toList() - } ?: emptyList() - } + @Deprecated("Use updateClasspath() instead.", ReplaceWith("updateClasspath(files)")) + fun tryUpdateClasspath(files: Iterable): List? = updateClasspath(files.map(::JvmClasspathRoot)) fun contentRootToVirtualFile(root: JvmContentRoot): VirtualFile? { when (root) { diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt index bff3bead3f232..fde2ccd3b4f05 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt @@ -18,6 +18,8 @@ package org.jetbrains.kotlin.cli.jvm.compiler import com.intellij.openapi.util.io.JarUtil import org.jetbrains.annotations.TestOnly +import com.intellij.psi.PsiManager +import com.intellij.psi.impl.PsiModificationTrackerImpl import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.asJava.FilteredJvmDiagnostics import org.jetbrains.kotlin.backend.common.output.OutputFileCollection @@ -34,6 +36,8 @@ import org.jetbrains.kotlin.codegen.ClassBuilderFactories import org.jetbrains.kotlin.codegen.CompilationErrorHandler import org.jetbrains.kotlin.codegen.GeneratedClassLoader import org.jetbrains.kotlin.codegen.KotlinCodegenFacade +import org.jetbrains.kotlin.cli.jvm.config.* +import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationStateEventCallback import org.jetbrains.kotlin.config.CompilerConfiguration @@ -124,7 +128,26 @@ object KotlinToJVMBytecodeCompiler { } val targetDescription = "in targets [" + chunk.joinToString { input -> input.getModuleName() + "-" + input.getModuleType() } + "]" - val result = analyze(environment, targetDescription) + var result = analyze(environment, targetDescription) + + if (result is AnalysisResult.RetryWithAdditionalJavaRoots) { + val oldReadOnlyValue = projectConfiguration.isReadOnly + projectConfiguration.isReadOnly = false + projectConfiguration.addJavaSourceRoots(result.additionalJavaRoots) + projectConfiguration.isReadOnly = oldReadOnlyValue + + environment.updateClasspath(result.additionalJavaRoots.map { JavaSourceRoot(it, null) }) + + // Clear package caches (see KotlinJavaPsiFacade) + (PsiManager.getInstance(environment.project).modificationTracker as? PsiModificationTrackerImpl)?.incCounter() + + // Clear all diagnostic messages + projectConfiguration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY]?.clear() + + // Repeat analysis with additional Java roots (kapt generated sources) + result = analyze(environment, targetDescription) + } + if (result == null || !result.shouldGenerateCode) return false ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() @@ -402,7 +425,12 @@ object KotlinToJVMBytecodeCompiler { K2JVMCompiler.reportPerf(environment.configuration, message) - return if (analyzerWithCompilerReport.hasErrors()) null else analyzerWithCompilerReport.analysisResult + val analysisResult = analyzerWithCompilerReport.analysisResult + + return if (!analyzerWithCompilerReport.hasErrors() || analysisResult is AnalysisResult.RetryWithAdditionalJavaRoots) + analysisResult + else + null } private fun generate( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalysisResult.kt b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalysisResult.kt index f96cf4df11ee8..14882d9e416fe 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalysisResult.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/analyzer/AnalysisResult.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.analyzer import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.types.ErrorUtils +import java.io.File open class AnalysisResult protected constructor( val bindingContext: BindingContext, @@ -58,6 +59,12 @@ open class AnalysisResult protected constructor( } private class Error(bindingContext: BindingContext, val exception: Throwable) : AnalysisResult(bindingContext, ErrorUtils.getErrorModule()) + + class RetryWithAdditionalJavaRoots( + bindingContext: BindingContext, + moduleDescriptor: ModuleDescriptor, + val additionalJavaRoots: List + ) : AnalysisResult(bindingContext, moduleDescriptor) companion object { val EMPTY: AnalysisResult = success(BindingContext.EMPTY, ErrorUtils.getErrorModule()) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/config/CompilerConfiguration.java b/compiler/frontend/src/org/jetbrains/kotlin/config/CompilerConfiguration.java index d43db1f772dc8..eb55c800e2e4c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/config/CompilerConfiguration.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/config/CompilerConfiguration.java @@ -122,6 +122,10 @@ public void setReadOnly(boolean readOnly) { this.readOnly = readOnly; } } + + public boolean isReadOnly() { + return readOnly; + } @NotNull private static T unmodifiable(@NotNull T object) { diff --git a/compiler/tests/org/jetbrains/kotlin/modules/xml/AbstractModuleXmlParserTest.java b/compiler/tests/org/jetbrains/kotlin/modules/xml/AbstractModuleXmlParserTest.java index ce67c2fe5efcf..a409180ec89a1 100644 --- a/compiler/tests/org/jetbrains/kotlin/modules/xml/AbstractModuleXmlParserTest.java +++ b/compiler/tests/org/jetbrains/kotlin/modules/xml/AbstractModuleXmlParserTest.java @@ -44,6 +44,11 @@ public void report( throw new AssertionError(MessageRenderer.PLAIN_FULL_PATHS.render(severity, message, location)); } + @Override + public void clear() { + // Do nothing + } + @Override public boolean hasErrors() { throw new UnsupportedOperationException(); diff --git a/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt b/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt index 558f82c70ba47..0e42cb33ed9e6 100644 --- a/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt +++ b/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt @@ -707,6 +707,10 @@ class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) { )) } + override fun clear() { + hasErrors = false + } + override fun hasErrors(): Boolean = hasErrors private fun renderLocationIfNeeded(location: CompilerMessageLocation): String {