diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/FirFrontend.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/FirFrontend.kt index fbaa7357147..0ac15bd16bf 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/FirFrontend.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/FirFrontend.kt @@ -1,18 +1,17 @@ package org.jetbrains.kotlin.backend.konan +import org.jetbrains.kotlin.KtSourceFile import org.jetbrains.kotlin.backend.konan.driver.PhaseContext import org.jetbrains.kotlin.backend.konan.driver.phases.FirOutput -import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys -import org.jetbrains.kotlin.cli.common.fileBelongsToModuleForPsi +import org.jetbrains.kotlin.cli.common.* import org.jetbrains.kotlin.cli.common.fir.FirDiagnosticsCompilerResultsReporter -import org.jetbrains.kotlin.cli.common.isCommonSourceForPsi import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport -import org.jetbrains.kotlin.cli.common.prepareNativeSessions import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar import org.jetbrains.kotlin.fir.pipeline.FirResult +import org.jetbrains.kotlin.fir.pipeline.ModuleCompilerAnalyzedOutput import org.jetbrains.kotlin.fir.pipeline.buildResolveAndCheckFir import org.jetbrains.kotlin.fir.resolve.ImplicitIntegerCoercionModuleCapability import org.jetbrains.kotlin.fir.scopes.FirOverrideChecker @@ -23,18 +22,23 @@ import org.jetbrains.kotlin.platform.CommonPlatforms import org.jetbrains.kotlin.resolve.konan.platform.NativePlatformAnalyzerServices @OptIn(SessionConfiguration::class) -internal fun PhaseContext.firFrontend(input: KotlinCoreEnvironment): FirOutput { +internal inline fun PhaseContext.firFrontend( + input: KotlinCoreEnvironment, + files: List, + fileHasSyntaxErrors: (F) -> Boolean, + noinline isCommonSource: (F) -> Boolean, + noinline fileBelongsToModule: (F, String) -> Boolean, + buildResolveAndCheckFir: (FirSession, List) -> ModuleCompilerAnalyzedOutput, +): FirOutput { val configuration = input.configuration val messageCollector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) val diagnosticsReporter = DiagnosticReporterFactory.createPendingReporter() val renderDiagnosticNames = configuration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME) + // FIR val extensionRegistrars = FirExtensionRegistrar.getInstances(input.project) val mainModuleName = Name.special("<${config.moduleId}>") - val ktFiles = input.getSourceFiles() - val syntaxErrors = ktFiles.fold(false) { errorsFound, ktFile -> - AnalyzerWithCompilerReport.reportSyntaxErrors(ktFile, messageCollector).isHasErrors or errorsFound - } + val syntaxErrors = files.fold(false) { errorsFound, file -> fileHasSyntaxErrors(file) or errorsFound } val binaryModuleData = BinaryModuleData.initialize(mainModuleName, CommonPlatforms.defaultCommonPlatform, NativePlatformAnalyzerServices) val dependencyList = DependencyListForCliModule.build(binaryModuleData) { val (interopLibs, regularLibs) = config.resolvedLibraries.getFullList().partition { it.isInterop } @@ -55,24 +59,24 @@ internal fun PhaseContext.firFrontend(input: KotlinCoreEnvironment): FirOutput { val resolvedLibraries: List = config.resolvedLibraries.getFullResolvedList() val sessionsWithSources = prepareNativeSessions( - ktFiles, + files, configuration, mainModuleName, resolvedLibraries, dependencyList, extensionRegistrars, metadataCompilationMode = configuration.get(KonanConfigKeys.METADATA_KLIB) ?: false, - isCommonSourceForPsi, - fileBelongsToModuleForPsi, + isCommonSource = isCommonSource, + fileBelongsToModule = fileBelongsToModule, registerExtraComponents = { it.register(FirOverrideChecker::class, FirNativeOverrideChecker(it)) }, ) val outputs = sessionsWithSources.map { (session, sources) -> - buildResolveAndCheckFir(session, sources, diagnosticsReporter).also { + buildResolveAndCheckFir(session, sources).also { if (shouldPrintFiles()) { - it.fir.forEach { println(it.render()) } + it.fir.forEach { file -> println(file.render()) } } } } @@ -84,3 +88,49 @@ internal fun PhaseContext.firFrontend(input: KotlinCoreEnvironment): FirOutput { FirOutput.Full(FirResult(outputs)) } } + +internal fun PhaseContext.firFrontendWithPsi(input: KotlinCoreEnvironment): FirOutput { + val configuration = input.configuration + val messageCollector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) + val diagnosticsReporter = DiagnosticReporterFactory.createPendingReporter() + // FIR + + val ktFiles = input.getSourceFiles() + return firFrontend( + input, + ktFiles, + fileHasSyntaxErrors = { + AnalyzerWithCompilerReport.reportSyntaxErrors(it, messageCollector).isHasErrors + }, + isCommonSource = isCommonSourceForPsi, + fileBelongsToModule = fileBelongsToModuleForPsi, + buildResolveAndCheckFir = { session, files -> + buildResolveAndCheckFir(session, files, diagnosticsReporter) + }, + ) +} + +internal fun PhaseContext.firFrontendWithLightTree(input: KotlinCoreEnvironment): FirOutput { + val configuration = input.configuration + val messageCollector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) + val diagnosticsReporter = DiagnosticReporterFactory.createPendingReporter() + // FIR + + val groupedSources = collectSources(configuration, input.project, messageCollector) + + val ktSourceFiles = mutableListOf().apply { + addAll(groupedSources.commonSources) + addAll(groupedSources.platformSources) + } + + return firFrontend( + input, + ktSourceFiles, + fileHasSyntaxErrors = { false }, + isCommonSource = { groupedSources.isCommonSourceForLt(it) }, + fileBelongsToModule = { file, it -> groupedSources.fileBelongsToModuleForLt(file, it) }, + buildResolveAndCheckFir = { session, files -> + buildResolveAndCheckFir(session, files, diagnosticsReporter, null) + }, + ) +} diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/FirFrontend.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/FirFrontend.kt index 6c56e864fac..7e6236fc4cc 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/FirFrontend.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/driver/phases/FirFrontend.kt @@ -7,8 +7,10 @@ package org.jetbrains.kotlin.backend.konan.driver.phases import org.jetbrains.kotlin.backend.konan.driver.PhaseContext import org.jetbrains.kotlin.backend.konan.driver.PhaseEngine -import org.jetbrains.kotlin.backend.konan.firFrontend +import org.jetbrains.kotlin.backend.konan.firFrontendWithPsi +import org.jetbrains.kotlin.backend.konan.firFrontendWithLightTree import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.fir.pipeline.FirResult sealed class FirOutput { @@ -21,7 +23,11 @@ internal val FIRPhase = createSimpleNamedCompilerPhase( "FirFrontend", "Compiler Fir Frontend", outputIfNotEnabled = { _, _, _, _ -> FirOutput.ShouldNotGenerateCode } ) { context: PhaseContext, input: KotlinCoreEnvironment -> - context.firFrontend(input) + if (input.configuration.getBoolean(CommonConfigurationKeys.USE_LIGHT_TREE)) { + context.firFrontendWithLightTree(input) + } else { + context.firFrontendWithPsi(input) + } } internal fun PhaseEngine.runFirFrontend(environment: KotlinCoreEnvironment): FirOutput {