[JS IR] Check fir compilation errors after checking IC next round

This commit is contained in:
Alexander Korepanov
2023-05-03 13:07:08 +02:00
committed by Space Team
parent 28b781f60a
commit e4d7897071
4 changed files with 90 additions and 74 deletions
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.cli.js
import com.intellij.openapi.Disposable
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.text.StringUtil
import org.jetbrains.kotlin.KtSourceFile
import org.jetbrains.kotlin.analyzer.CompilationErrorException
import org.jetbrains.kotlin.backend.common.CompilationException
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.backend.wasm.compileToLoweredIr
@@ -482,7 +482,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
friendLibraries: List<String>,
arguments: K2JSCompilerArguments,
outputKlibPath: String
): ModulesStructure? {
): ModulesStructure {
val configuration = environmentForJS.configuration
val messageCollector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
val diagnosticsReporter = DiagnosticReporterFactory.createPendingReporter()
@@ -492,7 +492,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
val lookupTracker = configuration.get(CommonConfigurationKeys.LOOKUP_TRACKER) ?: LookupTracker.DO_NOTHING
val outputs = if (
val analyzedOutput = if (
configuration.getBoolean(CommonConfigurationKeys.USE_FIR) && configuration.getBoolean(CommonConfigurationKeys.USE_LIGHT_TREE)
) {
val groupedSources = collectSources(configuration, environmentForJS.project, messageCollector)
@@ -506,38 +506,46 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
ktSourceFiles = groupedSources.commonSources + groupedSources.platformSources,
libraries = libraries,
friendLibraries = friendLibraries,
messageCollector = messageCollector,
diagnosticsReporter = diagnosticsReporter,
incrementalDataProvider = configuration[JSConfigurationKeys.INCREMENTAL_DATA_PROVIDER],
lookupTracker = lookupTracker,
) ?: return null
)
} else {
compileModuleToAnalyzedFirWithPsi(
moduleStructure = moduleStructure,
ktFiles = environmentForJS.getSourceFiles(),
libraries = libraries,
friendLibraries = friendLibraries,
messageCollector = messageCollector,
diagnosticsReporter = diagnosticsReporter,
incrementalDataProvider = configuration[JSConfigurationKeys.INCREMENTAL_DATA_PROVIDER],
lookupTracker = lookupTracker,
) ?: return null
)
}
// FIR2IR
val fir2IrActualizedResult = transformFirToIr(moduleStructure, outputs, diagnosticsReporter)
val fir2IrActualizedResult = transformFirToIr(moduleStructure, analyzedOutput.output, diagnosticsReporter)
if (configuration.getBoolean(CommonConfigurationKeys.INCREMENTAL_COMPILATION)) {
if (shouldGoToNextIcRound(moduleStructure, outputs, fir2IrActualizedResult)) {
// TODO: During checking the next round, fir serializer may throw an exception, e.g.
// during annotation serialization when it cannot find the removed constant
// (see ConstantValueUtils.kt:convertToConstantValues())
// This happens because we check the next round before compilation errors.
// Test reproducer: testFileWithConstantRemoved
// Issue: https://youtrack.jetbrains.com/issue/KT-58824/
if (shouldGoToNextIcRound(moduleStructure, analyzedOutput.output, fir2IrActualizedResult)) {
throw IncrementalNextRoundException()
}
}
if (analyzedOutput.reportCompilationErrors(moduleStructure, diagnosticsReporter, messageCollector)) {
throw CompilationErrorException()
}
// Serialize klib
if (arguments.irProduceKlibDir || arguments.irProduceKlibFile) {
serializeFirKlib(
moduleStructure = moduleStructure,
firOutputs = outputs,
firOutputs = analyzedOutput.output,
fir2IrActualizedResult = fir2IrActualizedResult,
outputKlibPath = outputKlibPath,
messageCollector = messageCollector,
@@ -55,27 +55,18 @@ inline fun <F> compileModuleToAnalyzedFir(
files: List<F>,
libraries: List<String>,
friendLibraries: List<String>,
messageCollector: MessageCollector,
diagnosticsReporter: BaseDiagnosticsCollector,
incrementalDataProvider: IncrementalDataProvider?,
lookupTracker: LookupTracker?,
fileHasSyntaxErrors: (F) -> Boolean,
noinline isCommonSource: (F) -> Boolean,
noinline fileBelongsToModule: (F, String) -> Boolean,
buildResolveAndCheckFir: (FirSession, List<F>) -> ModuleCompilerAnalyzedOutput,
): List<ModuleCompilerAnalyzedOutput>? {
val renderDiagnosticNames = moduleStructure.compilerConfiguration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME)
): List<ModuleCompilerAnalyzedOutput> {
// FIR
val extensionRegistrars = FirExtensionRegistrar.getInstances(moduleStructure.project)
val mainModuleName = moduleStructure.compilerConfiguration.get(CommonConfigurationKeys.MODULE_NAME)!!
val escapedMainModuleName = Name.special("<$mainModuleName>")
val syntaxErrors = files.fold(false) { errorsFound, file ->
fileHasSyntaxErrors(file) or errorsFound
}
val binaryModuleData = BinaryModuleData.initialize(escapedMainModuleName, JsPlatforms.defaultJsPlatform, JsPlatformAnalyzerServices)
val dependencyList = DependencyListForCliModule.build(binaryModuleData) {
dependencies(libraries.map { Paths.get(it).toAbsolutePath() })
@@ -97,40 +88,61 @@ inline fun <F> compileModuleToAnalyzedFir(
buildResolveAndCheckFir(it.session, it.files)
}
if (syntaxErrors || diagnosticsReporter.hasErrors) {
FirDiagnosticsCompilerResultsReporter.reportToMessageCollector(diagnosticsReporter, messageCollector, renderDiagnosticNames)
return null
}
return outputs
}
open class AnalyzedFirOutput(val output: List<ModuleCompilerAnalyzedOutput>) {
protected open fun checkSyntaxErrors(messageCollector: MessageCollector) = false
fun reportCompilationErrors(
moduleStructure: ModulesStructure,
diagnosticsReporter: BaseDiagnosticsCollector,
messageCollector: MessageCollector,
): Boolean {
if (checkSyntaxErrors(messageCollector) || diagnosticsReporter.hasErrors) {
val renderName = moduleStructure.compilerConfiguration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME)
FirDiagnosticsCompilerResultsReporter.reportToMessageCollector(diagnosticsReporter, messageCollector, renderName)
return true
}
return false
}
}
class AnalyzedFirWithPsiOutput(
output: List<ModuleCompilerAnalyzedOutput>,
private val compiledFiles: List<KtFile>
) : AnalyzedFirOutput(output) {
override fun checkSyntaxErrors(messageCollector: MessageCollector): Boolean {
return compiledFiles.fold(false) { errorsFound, file ->
AnalyzerWithCompilerReport.reportSyntaxErrors(file, messageCollector).isHasErrors or errorsFound
}
}
}
fun compileModuleToAnalyzedFirWithPsi(
moduleStructure: ModulesStructure,
ktFiles: List<KtFile>,
libraries: List<String>,
friendLibraries: List<String>,
messageCollector: MessageCollector,
diagnosticsReporter: BaseDiagnosticsCollector,
incrementalDataProvider: IncrementalDataProvider?,
lookupTracker: LookupTracker?,
): List<ModuleCompilerAnalyzedOutput>? {
return compileModuleToAnalyzedFir(
): AnalyzedFirWithPsiOutput {
val output = compileModuleToAnalyzedFir(
moduleStructure,
ktFiles,
libraries,
friendLibraries,
messageCollector,
diagnosticsReporter,
incrementalDataProvider,
lookupTracker,
fileHasSyntaxErrors = { AnalyzerWithCompilerReport.reportSyntaxErrors(it, messageCollector).isHasErrors },
isCommonSource = isCommonSourceForPsi,
fileBelongsToModule = fileBelongsToModuleForPsi,
buildResolveAndCheckFir = { session, files ->
buildResolveAndCheckFirFromKtFiles(session, files, diagnosticsReporter)
},
)
return AnalyzedFirWithPsiOutput(output, ktFiles)
}
fun compileModulesToAnalyzedFirWithLightTree(
@@ -139,27 +151,24 @@ fun compileModulesToAnalyzedFirWithLightTree(
ktSourceFiles: List<KtSourceFile>,
libraries: List<String>,
friendLibraries: List<String>,
messageCollector: MessageCollector,
diagnosticsReporter: BaseDiagnosticsCollector,
incrementalDataProvider: IncrementalDataProvider?,
lookupTracker: LookupTracker?,
): List<ModuleCompilerAnalyzedOutput>? {
return compileModuleToAnalyzedFir(
): AnalyzedFirOutput {
val output = compileModuleToAnalyzedFir(
moduleStructure,
ktSourceFiles,
libraries,
friendLibraries,
messageCollector,
diagnosticsReporter,
incrementalDataProvider,
lookupTracker,
fileHasSyntaxErrors = { false },
isCommonSource = { groupedSources.isCommonSourceForLt(it) },
fileBelongsToModule = { file, it -> groupedSources.fileBelongsToModuleForLt(file, it) },
buildResolveAndCheckFir = { session, files ->
buildResolveAndCheckFirViaLightTree(session, files, diagnosticsReporter, null)
},
)
return AnalyzedFirOutput(output)
}
fun transformFirToIr(
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector
import org.jetbrains.kotlin.cli.js.klib.compileModuleToAnalyzedFirWithPsi
import org.jetbrains.kotlin.cli.js.klib.serializeFirKlib
import org.jetbrains.kotlin.cli.js.klib.transformFirToIr
import org.jetbrains.kotlin.codegen.ProjectInfo
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
import org.jetbrains.kotlin.ir.backend.js.MainModule
@@ -64,34 +63,36 @@ abstract class FirAbstractInvalidationTest(
friendDependenciesPaths = friendLibraries
)
val outputs = compileModuleToAnalyzedFirWithPsi(
val analyzedOutput = compileModuleToAnalyzedFirWithPsi(
moduleStructure = moduleStructure,
ktFiles = sourceFiles,
libraries = libraries,
friendLibraries = friendLibraries,
messageCollector = messageCollector,
diagnosticsReporter = diagnosticsReporter,
incrementalDataProvider = null,
lookupTracker = null,
)
if (outputs != null) {
val fir2IrActualizedResult = transformFirToIr(moduleStructure, outputs, diagnosticsReporter)
val fir2IrActualizedResult = transformFirToIr(moduleStructure, analyzedOutput.output, diagnosticsReporter)
serializeFirKlib(
moduleStructure = moduleStructure,
firOutputs = outputs,
fir2IrActualizedResult = fir2IrActualizedResult,
outputKlibPath = outputKlibFile.absolutePath,
messageCollector = messageCollector,
diagnosticsReporter = diagnosticsReporter,
jsOutputName = moduleName
)
}
if (messageCollector.hasErrors()) {
if (analyzedOutput.reportCompilationErrors(moduleStructure, diagnosticsReporter, messageCollector)) {
val messages = outputStream.toByteArray().toString(Charset.forName("UTF-8"))
throw AssertionError("The following errors occurred compiling test:\n$messages")
}
serializeFirKlib(
moduleStructure = moduleStructure,
firOutputs = analyzedOutput.output,
fir2IrActualizedResult = fir2IrActualizedResult,
outputKlibPath = outputKlibFile.absolutePath,
messageCollector = messageCollector,
diagnosticsReporter = diagnosticsReporter,
jsOutputName = moduleName
)
if (messageCollector.hasErrors()) {
val messages = outputStream.toByteArray().toString(Charset.forName("UTF-8"))
throw AssertionError("The following errors occurred serializing test klib:\n$messages")
}
}
}
@@ -15,10 +15,7 @@ import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector
import org.jetbrains.kotlin.cli.js.klib.compileModuleToAnalyzedFirWithPsi
import org.jetbrains.kotlin.cli.js.klib.generateIrForKlibSerialization
import org.jetbrains.kotlin.cli.js.klib.serializeFirKlib
import org.jetbrains.kotlin.cli.js.klib.transformFirToIr
import org.jetbrains.kotlin.cli.js.klib.*
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.CommonConfigurationKeys
@@ -205,36 +202,37 @@ abstract class AbstractJsPartialLinkageTestCase(val compilerType: CompilerType)
val outputStream = ByteArrayOutputStream()
val messageCollector = PrintingMessageCollector(PrintStream(outputStream), MessageRenderer.PLAIN_FULL_PATHS, true)
val outputs = compileModuleToAnalyzedFirWithPsi(
val analyzedOutput = compileModuleToAnalyzedFirWithPsi(
moduleStructure = moduleStructure,
ktFiles = ktFiles,
libraries = regularDependencies,
friendLibraries = friendDependencies,
messageCollector = messageCollector,
diagnosticsReporter = diagnosticsReporter,
incrementalDataProvider = null,
lookupTracker = null
)
if (outputs != null) {
val fir2IrActualizedResult = transformFirToIr(moduleStructure, outputs, diagnosticsReporter)
val fir2IrActualizedResult = transformFirToIr(moduleStructure, analyzedOutput.output, diagnosticsReporter)
serializeFirKlib(
moduleStructure = moduleStructure,
firOutputs = outputs,
fir2IrActualizedResult = fir2IrActualizedResult,
outputKlibPath = klibFile.absolutePath,
messageCollector = messageCollector,
diagnosticsReporter = diagnosticsReporter,
jsOutputName = moduleName
)
}
if (messageCollector.hasErrors()) {
if (analyzedOutput.reportCompilationErrors(moduleStructure, diagnosticsReporter, messageCollector)) {
val messages = outputStream.toByteArray().toString(Charset.forName("UTF-8"))
throw AssertionError("The following errors occurred compiling test:\n$messages")
}
serializeFirKlib(
moduleStructure = moduleStructure,
firOutputs = analyzedOutput.output,
fir2IrActualizedResult = fir2IrActualizedResult,
outputKlibPath = klibFile.absolutePath,
messageCollector = messageCollector,
diagnosticsReporter = diagnosticsReporter,
jsOutputName = moduleName
)
if (messageCollector.hasErrors()) {
val messages = outputStream.toByteArray().toString(Charset.forName("UTF-8"))
throw AssertionError("The following errors occurred serializing test klib:\n$messages")
}
}
private fun buildBinaryAndRun(mainModuleKlibFile: File, allDependencies: Dependencies) {