Provide message collector for Java IC analysis

#KT-37446 Fixed
This commit is contained in:
Alexey Tsvetkov
2020-09-08 13:22:41 +03:00
parent 17db188b0e
commit c56952a01e
6 changed files with 102 additions and 42 deletions
+1
View File
@@ -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")
@@ -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()
@@ -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<File>,
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<Message>()
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) }
}
}
@@ -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" }
@@ -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<FqName> = 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<ClassId>()
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) {
@@ -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<Message>()
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) }
}
}