From c56952a01eba045759f14cce1420484f813b5cf8 Mon Sep 17 00:00:00 2001 From: Alexey Tsvetkov Date: Tue, 8 Sep 2020 13:22:41 +0300 Subject: [PATCH] Provide message collector for Java IC analysis #KT-37446 Fixed --- build.gradle.kts | 1 + .../build.gradle.kts | 8 +++ .../incremental/IncrementalCompilerRunner.kt | 49 +++++++------------ .../IncrementalJsCompilerRunner.kt | 3 +- .../IncrementalJvmCompilerRunner.kt | 45 ++++++++++++----- .../util/BufferingMessageCollector.kt | 38 ++++++++++++++ 6 files changed, 102 insertions(+), 42 deletions(-) create mode 100644 compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/util/BufferingMessageCollector.kt diff --git a/build.gradle.kts b/build.gradle.kts index 4860a94a18d..7adee9699cd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -710,6 +710,7 @@ tasks { dependsOn("scriptingTest") dependsOn(":kotlin-build-common:test") dependsOn(":compiler:incremental-compilation-impl:test") + dependsOn(":compiler:incremental-compilation-impl:testJvmICWithJdk11") dependsOn(":core:descriptors.runtime:test") dependsOn("jvmCompilerIntegrationTest") diff --git a/compiler/incremental-compilation-impl/build.gradle.kts b/compiler/incremental-compilation-impl/build.gradle.kts index 2ca58fdf556..6f44c1e3b85 100644 --- a/compiler/incremental-compilation-impl/build.gradle.kts +++ b/compiler/incremental-compilation-impl/build.gradle.kts @@ -42,4 +42,12 @@ projectTest(parallel = true) { dependsOn(":kotlin-stdlib-js-ir:packFullRuntimeKLib") } +projectTest("testJvmICWithJdk11", parallel = true) { + workingDir = rootDir + filter { + includeTestsMatching("org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunnerTestGenerated*") + } + executable = "${rootProject.extra["JDK_11"]}/bin/java" +} + testsJar() diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCompilerRunner.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCompilerRunner.kt index b3afb5fd51e..80fc775b2ff 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCompilerRunner.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalCompilerRunner.kt @@ -20,8 +20,6 @@ import org.jetbrains.kotlin.build.DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS import org.jetbrains.kotlin.build.GeneratedFile import org.jetbrains.kotlin.cli.common.ExitCode import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSourceLocation -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.compilerRunner.MessageCollectorToOutputItemsCollectorAdapter import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl @@ -31,6 +29,7 @@ import org.jetbrains.kotlin.config.Services import org.jetbrains.kotlin.incremental.components.ExpectActualTracker import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.parsing.classesFqNames +import org.jetbrains.kotlin.incremental.util.BufferingMessageCollector import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.progress.CompilationCanceledStatus import java.io.File @@ -83,7 +82,7 @@ abstract class IncrementalCompilerRunner< return try { val changedFiles = providedChangedFiles ?: caches.inputsCache.sourceSnapshotMap.compareAndUpdate(allSourceFiles) - val compilationMode = sourcesToCompile(caches, changedFiles, args) + val compilationMode = sourcesToCompile(caches, changedFiles, args, messageCollector) val exitCode = when (compilationMode) { is CompilationMode.Incremental -> { @@ -131,13 +130,23 @@ abstract class IncrementalCompilerRunner< workingDir.mkdirs() } - private fun sourcesToCompile(caches: CacheManager, changedFiles: ChangedFiles, args: Args): CompilationMode = + private fun sourcesToCompile( + caches: CacheManager, + changedFiles: ChangedFiles, + args: Args, + messageCollector: MessageCollector + ): CompilationMode = when (changedFiles) { - is ChangedFiles.Known -> calculateSourcesToCompile(caches, changedFiles, args) + is ChangedFiles.Known -> calculateSourcesToCompile(caches, changedFiles, args, messageCollector) is ChangedFiles.Unknown -> CompilationMode.Rebuild { "inputs' changes are unknown (first or clean build)" } } - protected abstract fun calculateSourcesToCompile(caches: CacheManager, changedFiles: ChangedFiles.Known, args: Args): CompilationMode + protected abstract fun calculateSourcesToCompile( + caches: CacheManager, + changedFiles: ChangedFiles.Known, + args: Args, + messageCollector: MessageCollector + ): CompilationMode protected fun initDirtyFiles(dirtyFiles: DirtyFilesContainer, changedFiles: ChangedFiles.Known) { dirtyFiles.add(changedFiles.modified, "was modified since last time") @@ -197,7 +206,7 @@ abstract class IncrementalCompilerRunner< caches: CacheManager, allKotlinSources: List, compilationMode: CompilationMode, - messageCollector: MessageCollector + originalMessageCollector: MessageCollector ): ExitCode { preBuildHook(args, compilationMode) @@ -234,8 +243,8 @@ abstract class IncrementalCompilerRunner< args.reportOutputFiles = true val outputItemsCollector = OutputItemsCollectorImpl() - val temporaryMessageCollector = TemporaryMessageCollector(messageCollector) - val messageCollectorAdapter = MessageCollectorToOutputItemsCollectorAdapter(temporaryMessageCollector, outputItemsCollector) + val bufferingMessageCollector = BufferingMessageCollector() + val messageCollectorAdapter = MessageCollectorToOutputItemsCollectorAdapter(bufferingMessageCollector, outputItemsCollector) exitCode = runCompiler(sourcesToCompile.toSet(), args, caches, services, messageCollectorAdapter) @@ -252,7 +261,7 @@ abstract class IncrementalCompilerRunner< } reporter.reportCompileIteration(compilationMode is CompilationMode.Incremental, sourcesToCompile, exitCode) - temporaryMessageCollector.flush() + bufferingMessageCollector.flush(originalMessageCollector) if (exitCode != ExitCode.OK) break @@ -352,23 +361,3 @@ abstract class IncrementalCompilerRunner< } } -private class TemporaryMessageCollector(private val delegate: MessageCollector) : MessageCollector { - private class Message(val severity: CompilerMessageSeverity, val message: String, val location: CompilerMessageSourceLocation?) - - private val messages = ArrayList() - - override fun clear() { - messages.clear() - } - - override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageSourceLocation?) { - messages.add(Message(severity, message, location)) - } - - override fun hasErrors(): Boolean = - messages.any { it.severity.isError } - - fun flush() { - messages.forEach { delegate.report(it.severity, it.message, it.location) } - } -} diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJsCompilerRunner.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJsCompilerRunner.kt index 386b3420a51..9709b75e6a4 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJsCompilerRunner.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJsCompilerRunner.kt @@ -93,7 +93,8 @@ class IncrementalJsCompilerRunner( override fun calculateSourcesToCompile( caches: IncrementalJsCachesManager, changedFiles: ChangedFiles.Known, - args: K2JSCompilerArguments + args: K2JSCompilerArguments, + messageCollector: MessageCollector ): CompilationMode { val lastBuildInfo = BuildInfo.read(lastBuildInfoFile) ?: return CompilationMode.Rebuild { "No information on previous build" } diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJvmCompilerRunner.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJvmCompilerRunner.kt index df1c96b9987..2694e9337d2 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJvmCompilerRunner.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalJvmCompilerRunner.kt @@ -25,8 +25,10 @@ import com.intellij.psi.PsiJavaFile import org.jetbrains.kotlin.build.DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS import org.jetbrains.kotlin.build.GeneratedFile import org.jetbrains.kotlin.build.GeneratedJvmClass +import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.ExitCode import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments +import org.jetbrains.kotlin.cli.common.messages.FilteringMessageCollector import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles @@ -38,6 +40,7 @@ import org.jetbrains.kotlin.incremental.components.ExpectActualTracker import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.multiproject.EmptyModulesApiHistory import org.jetbrains.kotlin.incremental.multiproject.ModulesApiHistory +import org.jetbrains.kotlin.incremental.util.BufferingMessageCollector import org.jetbrains.kotlin.load.java.JavaClassesTracker import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents @@ -125,23 +128,46 @@ class IncrementalJvmCompilerRunner( private var dirtyClasspathChanges: Collection = emptySet() - private val psiFileFactory: PsiFileFactory by lazy { - val rootDisposable = Disposer.newDisposable() - val configuration = CompilerConfiguration() - val environment = KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES) - val project = environment.project - PsiFileFactory.getInstance(project) + private val psiFileProvider = object { + val messageCollector = BufferingMessageCollector() + + fun javaFile(file: File): PsiFile? = + psiFileFactory.createFileFromText(file.nameWithoutExtension, JavaLanguage.INSTANCE, file.readText()) + + private val psiFileFactory: PsiFileFactory by lazy { + val rootDisposable = Disposer.newDisposable() + val configuration = CompilerConfiguration() + val filterMessageCollector = FilteringMessageCollector(messageCollector, { !it.isError }) + configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, filterMessageCollector) + val environment = KotlinCoreEnvironment.createForProduction(rootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES) + val project = environment.project + PsiFileFactory.getInstance(project) + } } private val changedUntrackedJavaClasses = mutableSetOf() private var javaFilesProcessor = if (!usePreciseJavaTracking) - ChangedJavaFilesProcessor(reporter) { it.psiFile() } + ChangedJavaFilesProcessor(reporter) { psiFileProvider.javaFile(it) } else null override fun calculateSourcesToCompile( + caches: IncrementalJvmCachesManager, + changedFiles: ChangedFiles.Known, + args: K2JVMCompilerArguments, + messageCollector: MessageCollector + ): CompilationMode { + return try { + calculateSourcesToCompileImpl(caches, changedFiles, args) + } finally { + psiFileProvider.messageCollector.flush(messageCollector) + psiFileProvider.messageCollector.clear() + } + } + + private fun calculateSourcesToCompileImpl( caches: IncrementalJvmCachesManager, changedFiles: ChangedFiles.Known, args: K2JVMCompilerArguments @@ -201,7 +227,7 @@ class IncrementalJvmCompilerRunner( return false } - val psiFile = javaFile.psiFile() + val psiFile = psiFileProvider.javaFile(javaFile) if (psiFile !is PsiJavaFile) { reporter.report { "[Precise Java tracking] Expected PsiJavaFile, got ${psiFile?.javaClass}" } return false @@ -223,9 +249,6 @@ class IncrementalJvmCompilerRunner( return true } - private fun File.psiFile(): PsiFile? = - psiFileFactory.createFileFromText(nameWithoutExtension, JavaLanguage.INSTANCE, readText()) - private fun processChangedUntrackedJavaClass(psiClass: PsiClass, classId: ClassId) { changedUntrackedJavaClasses.add(classId) for (innerClass in psiClass.innerClasses) { diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/util/BufferingMessageCollector.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/util/BufferingMessageCollector.kt new file mode 100644 index 00000000000..b415b68d826 --- /dev/null +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/util/BufferingMessageCollector.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.incremental.util + +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSourceLocation +import org.jetbrains.kotlin.cli.common.messages.MessageCollector +import java.util.ArrayList + +internal class BufferingMessageCollector : MessageCollector { + private class Message(val severity: CompilerMessageSeverity, val message: String, val location: CompilerMessageSourceLocation?) + + private val messages = ArrayList() + + override fun clear() { + messages.clear() + } + + override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageSourceLocation?) { + messages.add( + Message( + severity, + message, + location + ) + ) + } + + override fun hasErrors(): Boolean = + messages.any { it.severity.isError } + + fun flush(delegate: MessageCollector) { + messages.forEach { delegate.report(it.severity, it.message, it.location) } + } +} \ No newline at end of file