[CLI] Introduce utilities for creating FirSession hierarchy in CLI for all platforms

Also support session creation and compilation for HMPP projects

^KT-56209 Fixed
This commit is contained in:
Dmitriy Novozhilov
2023-02-09 22:24:32 +02:00
committed by Space Team
parent 30ea4b6b53
commit 79e4df72bf
22 changed files with 783 additions and 633 deletions
@@ -3,42 +3,31 @@ package org.jetbrains.kotlin.backend.konan
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.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.config.AnalysisFlags
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers
import org.jetbrains.kotlin.fir.BinaryModuleData
import org.jetbrains.kotlin.fir.DependencyListForCliModule
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
import org.jetbrains.kotlin.fir.pipeline.*
import org.jetbrains.kotlin.fir.session.FirNativeSessionFactory
import org.jetbrains.kotlin.fir.session.FirSessionConfigurator
import org.jetbrains.kotlin.fir.pipeline.FirResult
import org.jetbrains.kotlin.fir.pipeline.buildResolveAndCheckFir
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.CommonPlatforms
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.konan.platform.NativePlatformAnalyzerServices
import org.jetbrains.kotlin.resolve.multiplatform.isCommonSource
internal fun PhaseContext.firFrontend(
input: KotlinCoreEnvironment
): FirOutput {
internal fun PhaseContext.firFrontend(input: KotlinCoreEnvironment): 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 sessionProvider = FirProjectSessionProvider()
val extensionRegistrars = FirExtensionRegistrar.getInstances(input.project)
val sessionConfigurator: FirSessionConfigurator.() -> Unit = {
if (configuration.languageVersionSettings.getFlag(AnalysisFlags.extendedCompilerChecks)) {
registerExtendedCommonCheckers()
}
}
val mainModuleName = Name.special("<${config.moduleId}>")
val ktFiles = input.getSourceFiles()
val syntaxErrors = ktFiles.fold(false) { errorsFound, ktFile ->
@@ -51,57 +40,24 @@ internal fun PhaseContext.firFrontend(
// TODO: !!! dependencies module data?
}
val resolvedLibraries: List<KotlinResolvedLibrary> = config.resolvedLibraries.getFullResolvedList()
FirNativeSessionFactory.createLibrarySession(
mainModuleName,
resolvedLibraries,
sessionProvider,
dependencyList.moduleDataProvider,
configuration.languageVersionSettings,
registerExtraComponents = {},
val sessionsWithSources = prepareNativeSessions(
ktFiles, configuration, mainModuleName.asString(), resolvedLibraries, dependencyList,
extensionRegistrars, isCommonSourceForPsi, fileBelongsToModuleForPsi
)
fun runFrontend(
moduleName: Name,
dependsOn: List<FirModuleData>,
ktFiles: List<KtFile>
): ModuleCompilerAnalyzedOutput {
val moduleData = FirModuleDataImpl(
moduleName,
dependencyList.regularDependencies,
dependsOn,
dependencyList.friendsDependencies,
CommonPlatforms.defaultCommonPlatform,
NativePlatformAnalyzerServices
)
val session = FirNativeSessionFactory.createModuleBasedSession(
moduleData,
sessionProvider,
extensionRegistrars,
configuration.languageVersionSettings,
sessionConfigurator,
)
val output = buildResolveAndCheckFir(session, ktFiles, diagnosticsReporter)
if (shouldPrintFiles())
output.fir.forEach { println(it.render()) }
return output
}
val isMppEnabled = configuration.languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects)
val firResult = if (isMppEnabled) {
val (commonKtFiles, platformKtFiles) = ktFiles.partition { it.isCommonSource == true }
val commonOutput = runFrontend(Name.identifier("${mainModuleName}-common"), emptyList(), commonKtFiles)
val platformOutput = runFrontend(mainModuleName, listOf(commonOutput.session.moduleData), platformKtFiles)
FirResult(platformOutput, commonOutput)
} else {
FirResult(runFrontend(mainModuleName, emptyList(), ktFiles), null)
val outputs = sessionsWithSources.map { (session, sources) ->
buildResolveAndCheckFir(session, sources, diagnosticsReporter).also {
if (shouldPrintFiles()) {
it.fir.forEach { println(it.render()) }
}
}
}
return if (syntaxErrors || diagnosticsReporter.hasErrors) {
FirDiagnosticsCompilerResultsReporter.reportToMessageCollector(diagnosticsReporter, messageCollector, renderDiagnosticNames)
FirOutput.ShouldNotGenerateCode
} else {
FirOutput.Full(firResult)
FirOutput.Full(FirResult(outputs))
}
}
@@ -17,7 +17,10 @@ import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.serialization.*
import org.jetbrains.kotlin.fir.serialization.FirElementAwareSerializableStringTable
import org.jetbrains.kotlin.fir.serialization.FirElementSerializer
import org.jetbrains.kotlin.fir.serialization.FirKLibSerializerExtension
import org.jetbrains.kotlin.fir.serialization.serializeSingleFirFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.util.IrMessageLogger
@@ -26,11 +29,10 @@ import org.jetbrains.kotlin.library.SerializedIrFile
import org.jetbrains.kotlin.library.metadata.KlibMetadataProtoBuf
import org.jetbrains.kotlin.library.metadata.resolver.TopologicalLibraryOrder
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.utils.toMetadataVersion
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
import org.jetbrains.kotlin.metadata.serialization.MutableVersionRequirementTable
import org.jetbrains.kotlin.psi
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.toMetadataVersion
internal fun PhaseContext.firSerializer(
input: Fir2IrOutput
@@ -39,7 +41,7 @@ internal fun PhaseContext.firSerializer(
val sourceFiles = mutableListOf<KtSourceFile>()
val firFilesAndSessionsBySourceFile = mutableMapOf<KtSourceFile, Triple<FirFile, FirSession, ScopeSession>>()
for (firOutput in listOfNotNull(input.firResult.commonOutput, input.firResult.platformOutput)) {
for (firOutput in input.firResult.outputs) {
for (firFile in firOutput.fir) {
sourceFiles.add(firFile.sourceFile!!)
firFilesAndSessionsBySourceFile[firFile.sourceFile!!] = Triple(firFile, firOutput.session, firOutput.scopeSession)