[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
@@ -41,25 +41,19 @@ import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
import org.jetbrains.kotlin.fir.BinaryModuleData import org.jetbrains.kotlin.fir.BinaryModuleData
import org.jetbrains.kotlin.fir.DependencyListForCliModule import org.jetbrains.kotlin.fir.DependencyListForCliModule
import org.jetbrains.kotlin.fir.FirModuleDataImpl
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.backend.Fir2IrExtensions import org.jetbrains.kotlin.fir.backend.Fir2IrExtensions
import org.jetbrains.kotlin.fir.backend.Fir2IrVisibilityConverter import org.jetbrains.kotlin.fir.backend.Fir2IrVisibilityConverter
import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers
import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
import org.jetbrains.kotlin.fir.pipeline.FirResult 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.pipeline.buildResolveAndCheckFir
import org.jetbrains.kotlin.fir.pipeline.convertToIrAndActualize import org.jetbrains.kotlin.fir.pipeline.convertToIrAndActualize
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.serialization.FirElementAwareSerializableStringTable import org.jetbrains.kotlin.fir.serialization.FirElementAwareSerializableStringTable
import org.jetbrains.kotlin.fir.serialization.FirKLibSerializerExtension import org.jetbrains.kotlin.fir.serialization.FirKLibSerializerExtension
import org.jetbrains.kotlin.fir.serialization.serializeSingleFirFile import org.jetbrains.kotlin.fir.serialization.serializeSingleFirFile
import org.jetbrains.kotlin.fir.session.FirJsSessionFactory
import org.jetbrains.kotlin.fir.session.FirSessionConfigurator
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.js.IncrementalDataProvider import org.jetbrains.kotlin.incremental.js.IncrementalDataProvider
@@ -91,11 +85,12 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.js.JsPlatforms import org.jetbrains.kotlin.platform.js.JsPlatforms
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.multiplatform.isCommonSource
import org.jetbrains.kotlin.serialization.js.ModuleKind import org.jetbrains.kotlin.serialization.js.ModuleKind
import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.utils.* import org.jetbrains.kotlin.utils.KotlinPaths
import org.jetbrains.kotlin.utils.addToStdlib.runIf import org.jetbrains.kotlin.utils.PathUtil
import org.jetbrains.kotlin.utils.join
import org.jetbrains.kotlin.utils.metadataVersion
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
import java.nio.file.Paths import java.nio.file.Paths
@@ -453,7 +448,11 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
} }
val metadataSerializer = val metadataSerializer =
KlibMetadataIncrementalSerializer(environmentForJS.configuration, sourceModule.project, sourceModule.jsFrontEndResult.hasErrors) KlibMetadataIncrementalSerializer(
environmentForJS.configuration,
sourceModule.project,
sourceModule.jsFrontEndResult.hasErrors
)
generateKLib( generateKLib(
sourceModule, sourceModule,
@@ -483,16 +482,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
val renderDiagnosticNames = configuration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME) val renderDiagnosticNames = configuration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME)
// FIR // FIR
val isMppEnabled = configuration.languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects)
val sessionProvider = FirProjectSessionProvider()
val extensionRegistrars = FirExtensionRegistrar.getInstances(environmentForJS.project) val extensionRegistrars = FirExtensionRegistrar.getInstances(environmentForJS.project)
val sessionConfigurator: FirSessionConfigurator.() -> Unit = {
if (arguments.extendedCompilerChecks) {
registerExtendedCommonCheckers()
}
}
val mainModuleName = configuration.get(CommonConfigurationKeys.MODULE_NAME)!! val mainModuleName = configuration.get(CommonConfigurationKeys.MODULE_NAME)!!
val escapedMainModuleName = Name.special("<$mainModuleName>") val escapedMainModuleName = Name.special("<$mainModuleName>")
@@ -514,67 +504,14 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
val logger = configuration.resolverLogger val logger = configuration.resolverLogger
val resolvedLibraries = jsResolveLibraries(libraries + friendLibraries, logger).getFullResolvedList() val resolvedLibraries = jsResolveLibraries(libraries + friendLibraries, logger).getFullResolvedList()
FirJsSessionFactory.createLibrarySession( val sessionsWithSources = prepareJsSessions(
escapedMainModuleName, ktFiles, configuration, escapedMainModuleName.asString(), resolvedLibraries, dependencyList,
resolvedLibraries, extensionRegistrars, isCommonSourceForPsi, fileBelongsToModuleForPsi
sessionProvider,
dependencyList.moduleDataProvider,
configuration.languageVersionSettings,
registerExtraComponents = {},
) )
val commonModuleData = runIf(isMppEnabled) { val outputs = sessionsWithSources.map {
FirModuleDataImpl( buildResolveAndCheckFir(it.session, it.files, diagnosticsReporter)
Name.identifier("<$mainModuleName-common>"),
dependencyList.regularDependencies,
listOf(),
dependencyList.friendsDependencies,
JsPlatforms.defaultJsPlatform,
JsPlatformAnalyzerServices
)
} }
val mainModuleData = FirModuleDataImpl(
escapedMainModuleName,
dependencyList.regularDependencies,
listOfNotNull(commonModuleData),
dependencyList.friendsDependencies,
JsPlatforms.defaultJsPlatform,
JsPlatformAnalyzerServices
)
val commonKtFiles = mutableListOf<KtFile>()
val platformKtFiles = mutableListOf<KtFile>()
if (isMppEnabled) {
for (ktFile in ktFiles) {
(if (ktFile.isCommonSource == true) commonKtFiles else platformKtFiles).add(ktFile)
}
} else {
platformKtFiles.addAll(ktFiles)
}
val commonSession = runIf(isMppEnabled) {
FirJsSessionFactory.createModuleBasedSession(
commonModuleData!!,
sessionProvider,
extensionRegistrars,
configuration.languageVersionSettings,
null,
registerExtraComponents = {},
init = sessionConfigurator,
)
}
val platformSession = FirJsSessionFactory.createModuleBasedSession(
mainModuleData,
sessionProvider,
extensionRegistrars,
configuration.languageVersionSettings,
null,
registerExtraComponents = {},
init = sessionConfigurator,
)
val commonFirOutput = commonSession?.let { buildResolveAndCheckFir(it, commonKtFiles, diagnosticsReporter) }
val platformFirOutput = buildResolveAndCheckFir(platformSession, platformKtFiles, diagnosticsReporter)
if (syntaxErrors || diagnosticsReporter.hasErrors) { if (syntaxErrors || diagnosticsReporter.hasErrors) {
FirDiagnosticsCompilerResultsReporter.reportToMessageCollector(diagnosticsReporter, messageCollector, renderDiagnosticNames) FirDiagnosticsCompilerResultsReporter.reportToMessageCollector(diagnosticsReporter, messageCollector, renderDiagnosticNames)
@@ -608,7 +545,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
moduleDescriptor moduleDescriptor
} }
val firResult = FirResult(platformFirOutput, commonFirOutput) val firResult = FirResult(outputs)
val irResult = firResult.convertToIrAndActualize( val irResult = firResult.convertToIrAndActualize(
fir2IrExtensions, fir2IrExtensions,
IrGenerationExtension.getInstances(environmentForJS.project), IrGenerationExtension.getInstances(environmentForJS.project),
@@ -628,13 +565,11 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
val sourceFiles = mutableListOf<KtSourceFile>() val sourceFiles = mutableListOf<KtSourceFile>()
val firFilesAndSessionsBySourceFile = mutableMapOf<KtSourceFile, Triple<FirFile, FirSession, ScopeSession>>() val firFilesAndSessionsBySourceFile = mutableMapOf<KtSourceFile, Triple<FirFile, FirSession, ScopeSession>>()
commonFirOutput?.fir?.forEach { for (output in outputs) {
sourceFiles.add(it.sourceFile!!) output.fir.forEach {
firFilesAndSessionsBySourceFile[it.sourceFile!!] = Triple(it, commonFirOutput.session, commonFirOutput.scopeSession) sourceFiles.add(it.sourceFile!!)
} firFilesAndSessionsBySourceFile[it.sourceFile!!] = Triple(it, output.session, output.scopeSession)
platformFirOutput.fir.forEach { }
sourceFiles.add(it.sourceFile!!)
firFilesAndSessionsBySourceFile[it.sourceFile!!] = Triple(it, platformFirOutput.session, platformFirOutput.scopeSession)
} }
val icData = environmentForJS.configuration.incrementalDataProvider?.getSerializedData(sourceFiles) ?: emptyList() val icData = environmentForJS.configuration.incrementalDataProvider?.getSerializedData(sourceFiles) ?: emptyList()
@@ -0,0 +1,411 @@
/*
* Copyright 2010-2023 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.cli.common
import org.jetbrains.kotlin.KtSourceFile
import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices
import org.jetbrains.kotlin.cli.jvm.compiler.pipeline.GroupedKtSources
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.fir.DependencyListForCliModule
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.FirModuleDataImpl
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
import org.jetbrains.kotlin.fir.session.*
import org.jetbrains.kotlin.fir.session.environment.AbstractProjectEnvironment
import org.jetbrains.kotlin.fir.session.environment.AbstractProjectFileSearchScope
import org.jetbrains.kotlin.incremental.components.EnumWhenTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices
import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary
import org.jetbrains.kotlin.load.kotlin.PackageAndMetadataPartProvider
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.CommonPlatforms
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.js.JsPlatforms
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.platform.konan.NativePlatforms
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
import org.jetbrains.kotlin.resolve.konan.platform.NativePlatformAnalyzerServices
import org.jetbrains.kotlin.resolve.multiplatform.hmppModuleName
import org.jetbrains.kotlin.resolve.multiplatform.isCommonSource
val isCommonSourceForPsi: (KtFile) -> Boolean = { it.isCommonSource == true }
val fileBelongsToModuleForPsi: (KtFile, String) -> Boolean = { file, moduleName -> file.hmppModuleName == moduleName }
val GroupedKtSources.isCommonSourceForLt: (KtSourceFile) -> Boolean
get() = { it in commonSources }
val GroupedKtSources.fileBelongsToModuleForLt: (KtSourceFile, String) -> Boolean
get() = { file, moduleName -> sourcesByModuleName[moduleName].orEmpty().contains(file) }
/**
* Creates library session and sources session for JVM platform
* Number of created session depends on mode of MPP:
* - disabled
* - legacy (one platform and one common module)
* - HMPP (multiple number of modules)
*/
fun <F> prepareJvmSessions(
files: List<F>,
configuration: CompilerConfiguration,
projectEnvironment: AbstractProjectEnvironment,
rootModuleName: String,
extensionRegistrars: List<FirExtensionRegistrar>,
librariesScope: AbstractProjectFileSearchScope,
libraryList: DependencyListForCliModule,
isCommonSource: (F) -> Boolean,
fileBelongsToModule: (F, String) -> Boolean,
createProviderAndScopeForIncrementalCompilation: (List<F>) -> IncrementalCompilationContext?,
): List<SessionWithSources<F>> {
val javaSourcesScope = projectEnvironment.getSearchScopeForProjectJavaSources()
class Context(
val javaSourcesScope: AbstractProjectFileSearchScope,
val lookupTracker: LookupTracker?,
val enumWhenTracker: EnumWhenTracker?
)
return prepareSessions(
files, configuration, rootModuleName, JvmPlatforms.unspecifiedJvmPlatform,
JvmPlatformAnalyzerServices, libraryList, isCommonSource, fileBelongsToModule,
createContext = {
val lookupTracker = configuration.get(CommonConfigurationKeys.LOOKUP_TRACKER)
val enumWhenTracker = configuration.get(CommonConfigurationKeys.ENUM_WHEN_TRACKER)
Context(javaSourcesScope, lookupTracker, enumWhenTracker)
},
createLibrarySession = { sessionProvider ->
FirJvmSessionFactory.createLibrarySession(
Name.identifier(rootModuleName),
sessionProvider,
libraryList.moduleDataProvider,
projectEnvironment,
librariesScope,
projectEnvironment.getPackagePartProvider(librariesScope),
configuration.languageVersionSettings,
registerExtraComponents = {},
)
}
) { context, moduleFiles, moduleData, sessionProvider, sessionConfigurator ->
FirJvmSessionFactory.createModuleBasedSession(
moduleData,
sessionProvider,
context.javaSourcesScope,
projectEnvironment,
createProviderAndScopeForIncrementalCompilation(moduleFiles),
extensionRegistrars,
configuration.languageVersionSettings,
context.lookupTracker,
context.enumWhenTracker,
needRegisterJavaElementFinder = true,
registerExtraComponents = {},
sessionConfigurator,
)
}
}
/**
* Creates library session and sources session for JS platform
* Number of created session depends on mode of MPP:
* - disabled
* - legacy (one platform and one common module)
* - HMPP (multiple number of modules)
*/
fun <F> prepareJsSessions(
files: List<F>,
configuration: CompilerConfiguration,
rootModuleName: String,
resolvedLibraries: List<KotlinResolvedLibrary>,
libraryList: DependencyListForCliModule,
extensionRegistrars: List<FirExtensionRegistrar>,
isCommonSource: (F) -> Boolean,
fileBelongsToModule: (F, String) -> Boolean,
): List<SessionWithSources<F>> {
return prepareSessions(
files, configuration, rootModuleName, JsPlatforms.defaultJsPlatform, JsPlatformAnalyzerServices,
libraryList, isCommonSource, fileBelongsToModule,
createContext = { null },
createLibrarySession = { sessionProvider ->
FirJsSessionFactory.createLibrarySession(
Name.identifier(rootModuleName),
resolvedLibraries,
sessionProvider,
libraryList.moduleDataProvider,
configuration.languageVersionSettings,
registerExtraComponents = {},
)
}
) { _, _, moduleData, sessionProvider, sessionConfigurator ->
FirJsSessionFactory.createModuleBasedSession(
moduleData,
sessionProvider,
extensionRegistrars,
configuration.languageVersionSettings,
null,
registerExtraComponents = {},
init = sessionConfigurator,
)
}
}
/**
* Creates library session and sources session for Native platform
* Number of created session depends on mode of MPP:
* - disabled
* - legacy (one platform and one common module)
* - HMPP (multiple number of modules)
*/
fun <F> prepareNativeSessions(
files: List<F>,
configuration: CompilerConfiguration,
rootModuleName: String,
resolvedLibraries: List<KotlinResolvedLibrary>,
libraryList: DependencyListForCliModule,
extensionRegistrars: List<FirExtensionRegistrar>,
isCommonSource: (F) -> Boolean,
fileBelongsToModule: (F, String) -> Boolean,
): List<SessionWithSources<F>> {
return prepareSessions(
files, configuration, rootModuleName, NativePlatforms.unspecifiedNativePlatform, NativePlatformAnalyzerServices,
libraryList, isCommonSource, fileBelongsToModule, createContext = { null },
createLibrarySession = { sessionProvider ->
FirNativeSessionFactory.createLibrarySession(
Name.identifier(rootModuleName),
resolvedLibraries,
sessionProvider,
libraryList.moduleDataProvider,
configuration.languageVersionSettings,
registerExtraComponents = {},
)
}
) { _, _, moduleData, sessionProvider, sessionConfigurator ->
FirNativeSessionFactory.createModuleBasedSession(
moduleData,
sessionProvider,
extensionRegistrars,
configuration.languageVersionSettings,
sessionConfigurator,
)
}
}
/**
* Creates library session and sources session for Common platform (for metadata compilation)
* Number of created session depends on mode of MPP:
* - disabled
* - legacy (one platform and one common module)
* - HMPP (multiple number of modules)
*/
fun <F> prepareCommonSessions(
files: List<F>,
configuration: CompilerConfiguration,
projectEnvironment: AbstractProjectEnvironment,
rootModuleName: String,
extensionRegistrars: List<FirExtensionRegistrar>,
librariesScope: AbstractProjectFileSearchScope,
libraryList: DependencyListForCliModule,
isCommonSource: (F) -> Boolean,
fileBelongsToModule: (F, String) -> Boolean,
createProviderAndScopeForIncrementalCompilation: (List<F>) -> IncrementalCompilationContext?,
): List<SessionWithSources<F>> {
return prepareSessions(
files, configuration, rootModuleName, CommonPlatforms.defaultCommonPlatform, CommonPlatformAnalyzerServices,
libraryList, isCommonSource, fileBelongsToModule, createContext = { null },
createLibrarySession = { sessionProvider ->
FirCommonSessionFactory.createLibrarySession(
Name.identifier(rootModuleName),
sessionProvider,
libraryList.moduleDataProvider,
projectEnvironment,
librariesScope,
projectEnvironment.getPackagePartProvider(librariesScope) as PackageAndMetadataPartProvider,
configuration.languageVersionSettings,
registerExtraComponents = {},
)
}
) { _, moduleFiles, moduleData, sessionProvider, sessionConfigurator ->
FirCommonSessionFactory.createModuleBasedSession(
moduleData,
sessionProvider,
librariesScope,
projectEnvironment,
incrementalCompilationContext = createProviderAndScopeForIncrementalCompilation(moduleFiles),
extensionRegistrars,
configuration.languageVersionSettings,
lookupTracker = configuration.get(CommonConfigurationKeys.LOOKUP_TRACKER),
enumWhenTracker = configuration.get(CommonConfigurationKeys.ENUM_WHEN_TRACKER),
needRegisterJavaElementFinder = true,
registerExtraComponents = {},
init = sessionConfigurator
)
}
}
// ---------------------------------------------------- Implementation ----------------------------------------------------
private typealias FirSessionProducer<F, C> = (C, List<F>, FirModuleData, FirProjectSessionProvider, FirSessionConfigurator.() -> Unit) -> FirSession
private inline fun <F, C> prepareSessions(
files: List<F>,
configuration: CompilerConfiguration,
rootModuleName: String,
targetPlatform: TargetPlatform,
analyzerServices: PlatformDependentAnalyzerServices,
libraryList: DependencyListForCliModule,
isCommonSource: (F) -> Boolean,
fileBelongsToModule: (F, String) -> Boolean,
createContext: () -> C,
createLibrarySession: (FirProjectSessionProvider) -> FirSession,
createSourceSession: FirSessionProducer<F, C>,
): List<SessionWithSources<F>> {
val languageVersionSettings = configuration.languageVersionSettings
val isMppEnabled = languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects)
val hmppModuleStructure = configuration.get(CommonConfigurationKeys.HMPP_MODULE_STRUCTURE)
val sessionProvider = FirProjectSessionProvider()
val context = createContext()
createLibrarySession(sessionProvider)
val extendedAnalysisMode = configuration.getBoolean(CommonConfigurationKeys.USE_FIR_EXTENDED_CHECKERS)
val sessionConfigurator: FirSessionConfigurator.() -> Unit = {
if (extendedAnalysisMode) {
registerExtendedCommonCheckers()
}
}
return when {
!isMppEnabled -> listOf(
createSessionForNonMppProject(
context, files, rootModuleName, libraryList, targetPlatform, analyzerServices,
sessionProvider, sessionConfigurator, createSourceSession
)
)
hmppModuleStructure == null -> createSessionsForLegacyMppProject(
context, files, rootModuleName, libraryList, targetPlatform, analyzerServices,
sessionProvider, sessionConfigurator, isCommonSource, createSourceSession
)
else -> createSessionsForHmppProject(
context, files, hmppModuleStructure, libraryList, targetPlatform, analyzerServices,
sessionProvider, sessionConfigurator, fileBelongsToModule, createSourceSession
)
}
}
private inline fun <F, C> createSessionForNonMppProject(
context: C,
files: List<F>,
rootModuleName: String,
libraryList: DependencyListForCliModule,
targetPlatform: TargetPlatform,
analyzerServices: PlatformDependentAnalyzerServices,
sessionProvider: FirProjectSessionProvider,
noinline sessionConfigurator: FirSessionConfigurator.() -> Unit,
createFirSession: FirSessionProducer<F, C>,
): SessionWithSources<F> {
val platformModuleData = FirModuleDataImpl(
Name.identifier(rootModuleName),
libraryList.regularDependencies,
dependsOnDependencies = emptyList(),
libraryList.friendsDependencies,
targetPlatform,
analyzerServices
)
val session = createFirSession(context, files, platformModuleData, sessionProvider, sessionConfigurator)
return SessionWithSources(session, files)
}
private inline fun <F, C> createSessionsForLegacyMppProject(
context: C,
files: List<F>,
rootModuleName: String,
libraryList: DependencyListForCliModule,
targetPlatform: TargetPlatform,
analyzerServices: PlatformDependentAnalyzerServices,
sessionProvider: FirProjectSessionProvider,
noinline sessionConfigurator: FirSessionConfigurator.() -> Unit,
isCommonSource: (F) -> Boolean,
createFirSession: FirSessionProducer<F, C>,
): List<SessionWithSources<F>> {
val commonModuleData = FirModuleDataImpl(
Name.identifier("${rootModuleName}-common"),
libraryList.regularDependencies,
listOf(),
libraryList.friendsDependencies,
targetPlatform,
analyzerServices
)
val platformModuleData = FirModuleDataImpl(
Name.identifier(rootModuleName),
libraryList.regularDependencies,
listOf(commonModuleData),
libraryList.friendsDependencies,
targetPlatform,
analyzerServices
)
val commonFiles = mutableListOf<F>()
val platformFiles = mutableListOf<F>()
for (file in files) {
(if (isCommonSource(file)) commonFiles else platformFiles).add(file)
}
val commonSession = createFirSession(context, commonFiles, commonModuleData, sessionProvider, sessionConfigurator)
val platformSession = createFirSession(context, platformFiles, platformModuleData, sessionProvider, sessionConfigurator)
return listOf(
SessionWithSources(commonSession, commonFiles),
SessionWithSources(platformSession, platformFiles)
)
}
private inline fun <F, C> createSessionsForHmppProject(
context: C,
files: List<F>,
hmppModuleStructure: HmppCliModuleStructure,
libraryList: DependencyListForCliModule,
targetPlatform: TargetPlatform,
analyzerServices: PlatformDependentAnalyzerServices,
sessionProvider: FirProjectSessionProvider,
noinline sessionConfigurator: FirSessionConfigurator.() -> Unit,
fileBelongsToModule: (F, String) -> Boolean,
createFirSession: FirSessionProducer<F, C>,
): List<SessionWithSources<F>> {
val moduleDataForHmppModule = LinkedHashMap<HmppCliModule, FirModuleData>()
for (module in hmppModuleStructure.modules) {
val dependencies = hmppModuleStructure.dependenciesMap[module]
?.map { moduleDataForHmppModule.getValue(it) }
.orEmpty()
val moduleData = FirModuleDataImpl(
Name.identifier(module.name),
libraryList.regularDependencies,
dependsOnDependencies = dependencies,
libraryList.friendsDependencies,
targetPlatform,
analyzerServices
)
moduleDataForHmppModule[module] = moduleData
}
return hmppModuleStructure.modules.map { module ->
val moduleData = moduleDataForHmppModule.getValue(module)
val sources = files.filter { fileBelongsToModule(it, module.name) }
val session = createFirSession(context, sources, moduleData, sessionProvider, sessionConfigurator)
SessionWithSources(session, sources)
}
}
data class SessionWithSources<F>(val session: FirSession, val files: List<F>)
@@ -11,10 +11,7 @@ import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.backend.jvm.JvmGeneratorExtensions import org.jetbrains.kotlin.backend.jvm.JvmGeneratorExtensions
import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory
import org.jetbrains.kotlin.backend.jvm.JvmIrDeserializerImpl import org.jetbrains.kotlin.backend.jvm.JvmIrDeserializerImpl
import org.jetbrains.kotlin.cli.common.CLICompiler import org.jetbrains.kotlin.cli.common.*
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.CommonCompilerPerformanceManager
import org.jetbrains.kotlin.cli.common.checkKotlinPackageUsage
import org.jetbrains.kotlin.cli.common.fir.FirDiagnosticsCompilerResultsReporter import org.jetbrains.kotlin.cli.common.fir.FirDiagnosticsCompilerResultsReporter
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
@@ -30,15 +27,12 @@ import org.jetbrains.kotlin.diagnostics.impl.BaseDiagnosticsCollector
import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.backend.* import org.jetbrains.kotlin.fir.backend.*
import org.jetbrains.kotlin.fir.backend.jvm.* import org.jetbrains.kotlin.fir.backend.jvm.*
import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers
import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar 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.pipeline.*
import org.jetbrains.kotlin.fir.session.* import org.jetbrains.kotlin.fir.session.*
import org.jetbrains.kotlin.fir.session.environment.AbstractProjectEnvironment import org.jetbrains.kotlin.fir.session.environment.AbstractProjectEnvironment
import org.jetbrains.kotlin.fir.session.environment.AbstractProjectFileSearchScope
import org.jetbrains.kotlin.fir.types.arrayElementType import org.jetbrains.kotlin.fir.types.arrayElementType
import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.isArrayType import org.jetbrains.kotlin.fir.types.isArrayType
@@ -50,13 +44,12 @@ import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompil
import org.jetbrains.kotlin.modules.Module import org.jetbrains.kotlin.modules.Module
import org.jetbrains.kotlin.modules.TargetId import org.jetbrains.kotlin.modules.TargetId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices import org.jetbrains.kotlin.resolve.multiplatform.hmppModuleName
import org.jetbrains.kotlin.resolve.multiplatform.isCommonSource import org.jetbrains.kotlin.resolve.multiplatform.isCommonSource
import org.jetbrains.kotlin.utils.addToStdlib.runIf import org.jetbrains.kotlin.utils.addToStdlib.runIf
import org.jetbrains.kotlin.utils.addToStdlib.runUnless
import java.io.File import java.io.File
object FirKotlinToJvmBytecodeCompiler { object FirKotlinToJvmBytecodeCompiler {
@@ -66,14 +59,15 @@ object FirKotlinToJvmBytecodeCompiler {
messageCollector: MessageCollector, messageCollector: MessageCollector,
allSources: List<KtFile>, allSources: List<KtFile>,
buildFile: File?, buildFile: File?,
chunk: List<Module>, chunk: List<Module>
extendedAnalysisMode: Boolean
): Boolean { ): Boolean {
val performanceManager = projectConfiguration.get(CLIConfigurationKeys.PERF_MANAGER) val performanceManager = projectConfiguration.get(CLIConfigurationKeys.PERF_MANAGER)
val notSupportedPlugins = mutableListOf<String?>().apply { val notSupportedPlugins = mutableListOf<String?>().apply {
projectConfiguration.get(ComponentRegistrar.PLUGIN_COMPONENT_REGISTRARS).collectIncompatiblePluginNamesTo(this, ComponentRegistrar::supportsK2) projectConfiguration.get(ComponentRegistrar.PLUGIN_COMPONENT_REGISTRARS)
projectConfiguration.get(CompilerPluginRegistrar.COMPILER_PLUGIN_REGISTRARS).collectIncompatiblePluginNamesTo(this, CompilerPluginRegistrar::supportsK2) .collectIncompatiblePluginNamesTo(this, ComponentRegistrar::supportsK2)
projectConfiguration.get(CompilerPluginRegistrar.COMPILER_PLUGIN_REGISTRARS)
.collectIncompatiblePluginNamesTo(this, CompilerPluginRegistrar::supportsK2)
} }
if (notSupportedPlugins.isNotEmpty()) { if (notSupportedPlugins.isNotEmpty()) {
@@ -109,8 +103,7 @@ object FirKotlinToJvmBytecodeCompiler {
performanceManager, performanceManager,
targetIds, targetIds,
incrementalComponents, incrementalComponents,
extendedAnalysisMode, extensionRegistrars = project?.let { FirExtensionRegistrar.getInstances(it) } ?: emptyList(),
firExtensionRegistrars = project?.let { FirExtensionRegistrar.getInstances(it) } ?: emptyList(),
irGenerationExtensions = project?.let { IrGenerationExtension.getInstances(it) } ?: emptyList() irGenerationExtensions = project?.let { IrGenerationExtension.getInstances(it) } ?: emptyList()
) )
val generationState = context.compileModule() ?: return false val generationState = context.compileModule() ?: return false
@@ -118,7 +111,7 @@ object FirKotlinToJvmBytecodeCompiler {
} }
val mainClassFqName: FqName? = runIf(chunk.size == 1 && projectConfiguration.get(JVMConfigurationKeys.OUTPUT_JAR) != null) { val mainClassFqName: FqName? = runIf(chunk.size == 1 && projectConfiguration.get(JVMConfigurationKeys.OUTPUT_JAR) != null) {
findMainClass(outputs.single().first.platformOutput.fir) findMainClass(outputs.single().first.outputs.last().fir)
} }
return writeOutputsIfNeeded( return writeOutputsIfNeeded(
@@ -204,97 +197,21 @@ object FirKotlinToJvmBytecodeCompiler {
providerAndScopeForIncrementalCompilation?.precompiledBinariesFileScope?.let { providerAndScopeForIncrementalCompilation?.precompiledBinariesFileScope?.let {
librariesScope -= it librariesScope -= it
} }
val rootModuleName = module.getModuleName()
val languageVersionSettings = moduleConfiguration.languageVersionSettings val libraryList = createLibraryListForJvm(rootModuleName, moduleConfiguration, module.getFriendPaths())
val sessionsWithSources = prepareJvmSessions(
val isMppEnabled = languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects) ktFiles, moduleConfiguration, projectEnvironment, rootModuleName,
extensionRegistrars, librariesScope, libraryList,
val sessionProvider = FirProjectSessionProvider() isCommonSource = { it.isCommonSource == true },
fileBelongsToModule = { file, moduleName -> file.hmppModuleName == moduleName },
val moduleName = module.getModuleName() createProviderAndScopeForIncrementalCompilation = { providerAndScopeForIncrementalCompilation }
val libraryList = createFirLibraryListAndSession(
moduleName, moduleConfiguration, projectEnvironment,
scope = librariesScope, librariesScope = librariesScope, friendPaths = module.getFriendPaths(), sessionProvider
) )
val commonModuleData = runIf(isMppEnabled) { val outputs = sessionsWithSources.map { (session, sources) ->
FirModuleDataImpl( buildResolveAndCheckFir(session, sources, diagnosticsReporter)
Name.identifier("${module.getModuleName()}-common"),
libraryList.regularDependencies,
listOf(),
libraryList.friendsDependencies,
JvmPlatforms.unspecifiedJvmPlatform,
JvmPlatformAnalyzerServices
)
}
val platformModuleData = FirModuleDataImpl(
Name.identifier(module.getModuleName()),
libraryList.regularDependencies,
listOfNotNull(commonModuleData),
libraryList.friendsDependencies,
JvmPlatforms.unspecifiedJvmPlatform,
JvmPlatformAnalyzerServices
)
val lookupTracker = moduleConfiguration.get(CommonConfigurationKeys.LOOKUP_TRACKER)
val enumWhenTracker = moduleConfiguration.get(CommonConfigurationKeys.ENUM_WHEN_TRACKER)
val sessionConfigurator: FirSessionConfigurator.() -> Unit = {
if (extendedAnalysisMode) {
registerExtendedCommonCheckers()
}
} }
val commonKtFiles = mutableListOf<KtFile>() return runUnless(syntaxErrors || diagnosticsReporter.hasErrors) { FirResult(outputs) }
val platformKtFiles = mutableListOf<KtFile>()
val commonSourcesScope: AbstractProjectFileSearchScope?
val platformSourcesScope: AbstractProjectFileSearchScope
if (isMppEnabled) {
for (ktFile in ktFiles) {
(if (ktFile.isCommonSource == true) commonKtFiles else platformKtFiles).add(ktFile)
}
commonSourcesScope = projectEnvironment.getSearchScopeByPsiFiles(commonKtFiles)
platformSourcesScope = sourceScope - commonSourcesScope
} else {
platformKtFiles.addAll(ktFiles)
commonSourcesScope = null
platformSourcesScope = sourceScope
}
val commonSession = runIf(isMppEnabled) {
FirJvmSessionFactory.createModuleBasedSession(
commonModuleData!!,
sessionProvider,
commonSourcesScope!!,
projectEnvironment,
providerAndScopeForIncrementalCompilation,
firExtensionRegistrars,
languageVersionSettings,
lookupTracker,
enumWhenTracker,
needRegisterJavaElementFinder = true,
registerExtraComponents = {},
sessionConfigurator
)
}
val platformSession = FirJvmSessionFactory.createModuleBasedSession(
platformModuleData,
sessionProvider,
platformSourcesScope,
projectEnvironment,
providerAndScopeForIncrementalCompilation,
firExtensionRegistrars,
languageVersionSettings,
lookupTracker,
enumWhenTracker,
needRegisterJavaElementFinder = true,
registerExtraComponents = {},
sessionConfigurator,
)
val commonOutput = commonSession?.let { buildResolveAndCheckFir(it, commonKtFiles, diagnosticsReporter) }
val platformOutput = buildResolveAndCheckFir(platformSession, platformKtFiles, diagnosticsReporter)
return if (syntaxErrors || diagnosticsReporter.hasErrors) null else FirResult(platformOutput, commonOutput)
} }
private fun CompilationContext.runBackend( private fun CompilationContext.runBackend(
@@ -365,8 +282,7 @@ object FirKotlinToJvmBytecodeCompiler {
val performanceManager: CommonCompilerPerformanceManager?, val performanceManager: CommonCompilerPerformanceManager?,
val targetIds: List<TargetId>?, val targetIds: List<TargetId>?,
val incrementalComponents: IncrementalCompilationComponents?, val incrementalComponents: IncrementalCompilationComponents?,
val extendedAnalysisMode: Boolean, val extensionRegistrars: List<FirExtensionRegistrar>,
val firExtensionRegistrars: List<FirExtensionRegistrar>,
val irGenerationExtensions: Collection<IrGenerationExtension> val irGenerationExtensions: Collection<IrGenerationExtension>
) )
} }
@@ -70,7 +70,6 @@ object KotlinToJVMBytecodeCompiler {
val projectConfiguration = environment.configuration val projectConfiguration = environment.configuration
if (projectConfiguration.getBoolean(CommonConfigurationKeys.USE_FIR)) { if (projectConfiguration.getBoolean(CommonConfigurationKeys.USE_FIR)) {
val extendedAnalysisMode = projectConfiguration.getBoolean(CommonConfigurationKeys.USE_FIR_EXTENDED_CHECKERS)
val projectEnvironment = val projectEnvironment =
VfsBasedProjectEnvironment( VfsBasedProjectEnvironment(
environment.project, environment.project,
@@ -81,7 +80,7 @@ object KotlinToJVMBytecodeCompiler {
environment.configuration, environment.configuration,
environment.messageCollector, environment.messageCollector,
environment.getSourceFiles(), environment.getSourceFiles(),
buildFile, chunk, extendedAnalysisMode buildFile, chunk
) )
} }
@@ -10,7 +10,6 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VfsUtilCore import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.VirtualFileSystem import com.intellij.openapi.vfs.VirtualFileSystem
import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices
import org.jetbrains.kotlin.backend.common.output.OutputFileCollection import org.jetbrains.kotlin.backend.common.output.OutputFileCollection
import org.jetbrains.kotlin.backend.common.output.SimpleOutputFileCollection import org.jetbrains.kotlin.backend.common.output.SimpleOutputFileCollection
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
@@ -27,17 +26,12 @@ import org.jetbrains.kotlin.codegen.state.GenerationStateEventCallback
import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.fir.BinaryModuleData import org.jetbrains.kotlin.fir.BinaryModuleData
import org.jetbrains.kotlin.fir.DependencyListForCliModule import org.jetbrains.kotlin.fir.DependencyListForCliModule
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
import org.jetbrains.kotlin.fir.session.FirCommonSessionFactory
import org.jetbrains.kotlin.fir.session.FirJvmSessionFactory
import org.jetbrains.kotlin.fir.session.IncrementalCompilationContext import org.jetbrains.kotlin.fir.session.IncrementalCompilationContext
import org.jetbrains.kotlin.fir.session.environment.AbstractProjectEnvironment import org.jetbrains.kotlin.fir.session.environment.AbstractProjectEnvironment
import org.jetbrains.kotlin.fir.session.environment.AbstractProjectFileSearchScope import org.jetbrains.kotlin.fir.session.environment.AbstractProjectFileSearchScope
import org.jetbrains.kotlin.javac.JavacWrapper import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.load.kotlin.PackageAndMetadataPartProvider
import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackagePartProvider import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackagePartProvider
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
import org.jetbrains.kotlin.modules.JavaRootPath import org.jetbrains.kotlin.modules.JavaRootPath
@@ -45,7 +39,6 @@ import org.jetbrains.kotlin.modules.Module
import org.jetbrains.kotlin.modules.TargetId import org.jetbrains.kotlin.modules.TargetId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.CommonPlatforms
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
@@ -226,20 +219,15 @@ fun createContextForIncrementalCompilation(
return IncrementalCompilationContext(emptyList(), packagePartProvider, incrementalCompilationScope) return IncrementalCompilationContext(emptyList(), packagePartProvider, incrementalCompilationScope)
} }
fun createFirLibraryListAndSession( fun createLibraryListForJvm(
moduleName: String, moduleName: String,
configuration: CompilerConfiguration, configuration: CompilerConfiguration,
projectEnvironment: AbstractProjectEnvironment, friendPaths: List<String>
scope: AbstractProjectFileSearchScope,
librariesScope: AbstractProjectFileSearchScope,
friendPaths: List<String>,
sessionProvider: FirProjectSessionProvider,
isJvm: Boolean = true
): DependencyListForCliModule { ): DependencyListForCliModule {
val binaryModuleData = BinaryModuleData.initialize( val binaryModuleData = BinaryModuleData.initialize(
Name.identifier(moduleName), Name.identifier(moduleName),
if (isJvm) JvmPlatforms.unspecifiedJvmPlatform else CommonPlatforms.defaultCommonPlatform, JvmPlatforms.unspecifiedJvmPlatform,
if (isJvm) JvmPlatformAnalyzerServices else CommonPlatformAnalyzerServices JvmPlatformAnalyzerServices
) )
val libraryList = DependencyListForCliModule.build(binaryModuleData) { val libraryList = DependencyListForCliModule.build(binaryModuleData) {
dependencies(configuration.jvmClasspathRoots.map { it.toPath() }) dependencies(configuration.jvmClasspathRoots.map { it.toPath() })
@@ -247,29 +235,6 @@ fun createFirLibraryListAndSession(
friendDependencies(configuration[JVMConfigurationKeys.FRIEND_PATHS] ?: emptyList()) friendDependencies(configuration[JVMConfigurationKeys.FRIEND_PATHS] ?: emptyList())
friendDependencies(friendPaths) friendDependencies(friendPaths)
} }
if (isJvm) {
FirJvmSessionFactory.createLibrarySession(
Name.identifier(moduleName),
sessionProvider,
libraryList.moduleDataProvider,
projectEnvironment,
scope,
projectEnvironment.getPackagePartProvider(librariesScope),
configuration.languageVersionSettings,
registerExtraComponents = {},
)
} else {
FirCommonSessionFactory.createLibrarySession(
Name.identifier(moduleName),
sessionProvider,
libraryList.moduleDataProvider,
projectEnvironment,
scope,
projectEnvironment.getPackagePartProvider(librariesScope) as PackageAndMetadataPartProvider,
configuration.languageVersionSettings,
registerExtraComponents = {},
)
}
return libraryList return libraryList
} }
@@ -22,8 +22,7 @@ import org.jetbrains.kotlin.KtVirtualFileSourceFile
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory
import org.jetbrains.kotlin.backend.jvm.JvmIrDeserializerImpl import org.jetbrains.kotlin.backend.jvm.JvmIrDeserializerImpl
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.*
import org.jetbrains.kotlin.cli.common.CommonCompilerPerformanceManager
import org.jetbrains.kotlin.cli.common.config.kotlinSourceRoots import org.jetbrains.kotlin.cli.common.config.kotlinSourceRoots
import org.jetbrains.kotlin.cli.common.fir.reportToMessageCollector import org.jetbrains.kotlin.cli.common.fir.reportToMessageCollector
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
@@ -40,21 +39,19 @@ import org.jetbrains.kotlin.cli.jvm.modules.CliJavaModuleResolver
import org.jetbrains.kotlin.codegen.ClassBuilderFactories import org.jetbrains.kotlin.codegen.ClassBuilderFactories
import org.jetbrains.kotlin.codegen.CodegenFactory import org.jetbrains.kotlin.codegen.CodegenFactory
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
import org.jetbrains.kotlin.fir.FirModuleDataImpl
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendClassResolver import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendClassResolver
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendExtension import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendExtension
import org.jetbrains.kotlin.fir.backend.jvm.JvmFir2IrExtensions import org.jetbrains.kotlin.fir.backend.jvm.JvmFir2IrExtensions
import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar 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.pipeline.*
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
import org.jetbrains.kotlin.fir.session.FirJvmSessionFactory
import org.jetbrains.kotlin.fir.session.FirSessionConfigurator
import org.jetbrains.kotlin.fir.session.IncrementalCompilationContext import org.jetbrains.kotlin.fir.session.IncrementalCompilationContext
import org.jetbrains.kotlin.fir.session.environment.AbstractProjectEnvironment import org.jetbrains.kotlin.fir.session.environment.AbstractProjectEnvironment
import org.jetbrains.kotlin.fir.session.environment.AbstractProjectFileSearchScope import org.jetbrains.kotlin.fir.session.environment.AbstractProjectFileSearchScope
@@ -68,14 +65,11 @@ import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackagePartProvid
import org.jetbrains.kotlin.modules.Module import org.jetbrains.kotlin.modules.Module
import org.jetbrains.kotlin.modules.TargetId import org.jetbrains.kotlin.modules.TargetId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.CommonPlatforms import org.jetbrains.kotlin.platform.CommonPlatforms
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.resolve.ModuleAnnotationsResolver import org.jetbrains.kotlin.resolve.ModuleAnnotationsResolver
import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
import org.jetbrains.kotlin.utils.addToStdlib.runIf
import java.io.File import java.io.File
import kotlin.reflect.KFunction2 import kotlin.reflect.KFunction2
@@ -104,13 +98,13 @@ fun compileModulesUsingFrontendIrAndLightTree(
val moduleConfiguration = compilerConfiguration.copy().applyModuleProperties(module, buildFile).apply { val moduleConfiguration = compilerConfiguration.copy().applyModuleProperties(module, buildFile).apply {
put(JVMConfigurationKeys.FRIEND_PATHS, module.getFriendPaths()) put(JVMConfigurationKeys.FRIEND_PATHS, module.getFriendPaths())
} }
val (platformSources, commonSources, sourcesByModuleName) = collectSources(compilerConfiguration, projectEnvironment, messageCollector) val groupedSources = collectSources(compilerConfiguration, projectEnvironment, messageCollector)
val compilerInput = ModuleCompilerInput( val compilerInput = ModuleCompilerInput(
TargetId(module), TargetId(module),
CommonPlatforms.defaultCommonPlatform, commonSources, groupedSources,
JvmPlatforms.unspecifiedJvmPlatform, platformSources, CommonPlatforms.defaultCommonPlatform,
sourcesByModuleName, JvmPlatforms.unspecifiedJvmPlatform,
moduleConfiguration moduleConfiguration
) )
@@ -133,7 +127,7 @@ fun compileModulesUsingFrontendIrAndLightTree(
// TODO: consider what to do if many modules has main classes // TODO: consider what to do if many modules has main classes
if (mainClassFqName == null && moduleConfiguration.get(JVMConfigurationKeys.OUTPUT_JAR) != null) { if (mainClassFqName == null && moduleConfiguration.get(JVMConfigurationKeys.OUTPUT_JAR) != null) {
mainClassFqName = findMainClass(analysisResults.platformOutput.fir) mainClassFqName = findMainClass(analysisResults.outputs.last().fir)
} }
if (diagnosticsReporter.hasErrors) { if (diagnosticsReporter.hasErrors) {
@@ -171,8 +165,8 @@ fun compileModulesUsingFrontendIrAndLightTree(
} }
data class GroupedKtSources( data class GroupedKtSources(
val platformSources: Set<KtSourceFile>, val platformSources: Collection<KtSourceFile>,
val commonSources: Set<KtSourceFile>, val commonSources: Collection<KtSourceFile>,
val sourcesByModuleName: Map<String, Set<KtSourceFile>>, val sourcesByModuleName: Map<String, Set<KtSourceFile>>,
) )
@@ -187,7 +181,8 @@ fun collectSources(
// TODO: the scripts checking should be part of the scripting plugin functionality, as it is implemented now in ScriptingProcessSourcesBeforeCompilingExtension // TODO: the scripts checking should be part of the scripting plugin functionality, as it is implemented now in ScriptingProcessSourcesBeforeCompilingExtension
// TODO: implement in the next round of K2 scripting support (https://youtrack.jetbrains.com/issue/KT-55728) // TODO: implement in the next round of K2 scripting support (https://youtrack.jetbrains.com/issue/KT-55728)
val skipScriptsInLtMode = compilerConfiguration.getBoolean(CommonConfigurationKeys.USE_FIR) && compilerConfiguration.getBoolean(CommonConfigurationKeys.USE_LIGHT_TREE) val skipScriptsInLtMode = compilerConfiguration.getBoolean(CommonConfigurationKeys.USE_FIR) &&
compilerConfiguration.getBoolean(CommonConfigurationKeys.USE_LIGHT_TREE)
var skipScriptsInLtModeWarning = false var skipScriptsInLtModeWarning = false
compilerConfiguration.kotlinSourceRoots.forAllFiles( compilerConfiguration.kotlinSourceRoots.forAllFiles(
@@ -308,122 +303,48 @@ fun compileModuleToAnalyzedFir(
diagnosticsReporter: DiagnosticReporter, diagnosticsReporter: DiagnosticReporter,
performanceManager: CommonCompilerPerformanceManager? performanceManager: CommonCompilerPerformanceManager?
): FirResult { ): FirResult {
val languageVersionSettings = input.configuration.languageVersionSettings
val projectEnvironment = environment.projectEnvironment val projectEnvironment = environment.projectEnvironment
val moduleConfiguration = input.configuration val moduleConfiguration = input.configuration
val isMppEnabled = languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects)
val sourcesScope = environment.projectEnvironment.getSearchScopeBySourceFiles(input.platformSources)
val commonSourcesScope: AbstractProjectFileSearchScope?
val platformSourcesScope: AbstractProjectFileSearchScope
if (isMppEnabled) {
commonSourcesScope = projectEnvironment.getSearchScopeBySourceFiles(input.commonSources)
platformSourcesScope = sourcesScope - commonSourcesScope
} else {
commonSourcesScope = null
platformSourcesScope = sourcesScope
}
var librariesScope = projectEnvironment.getSearchScopeForProjectLibraries() var librariesScope = projectEnvironment.getSearchScopeForProjectLibraries()
val commonProviderAndScopeForIncrementalCompilation = runIf(isMppEnabled) { val rootModuleName = input.targetId.name
createContextForIncrementalCompilation(
moduleConfiguration,
projectEnvironment,
commonSourcesScope!!,
previousStepsSymbolProviders,
incrementalExcludesScope
)?.also { (_, _, precompiledBinariesFileScope) ->
precompiledBinariesFileScope?.let { librariesScope -= it }
}
}
val platformProviderAndScopeForIncrementalCompilation = createContextForIncrementalCompilation(
moduleConfiguration,
projectEnvironment,
platformSourcesScope,
previousStepsSymbolProviders,
incrementalExcludesScope
)?.also { (_, _, precompiledBinariesFileScope) ->
precompiledBinariesFileScope?.let { librariesScope -= it }
}
val sessionProvider = FirProjectSessionProvider() val extensionRegistrars = (projectEnvironment as? VfsBasedProjectEnvironment)
val moduleName = input.targetId.name ?.let { FirExtensionRegistrar.getInstances(it.project) }
val libraryList = createFirLibraryListAndSession(
moduleName, input.configuration, projectEnvironment,
scope = projectEnvironment.getSearchScopeForProjectLibraries(),
librariesScope = librariesScope,
friendPaths = emptyList(),
sessionProvider
)
val commonModuleData = runIf(isMppEnabled) {
FirModuleDataImpl(
Name.identifier("${moduleName}-common"),
libraryList.regularDependencies,
listOf(),
libraryList.friendsDependencies,
JvmPlatforms.unspecifiedJvmPlatform,
JvmPlatformAnalyzerServices
)
}
val platformModuleData = FirModuleDataImpl(
Name.identifier(moduleName),
libraryList.regularDependencies,
listOfNotNull(commonModuleData),
libraryList.friendsDependencies,
JvmPlatforms.unspecifiedJvmPlatform,
JvmPlatformAnalyzerServices
)
val extensionRegistrars = (projectEnvironment as? VfsBasedProjectEnvironment)?.let { FirExtensionRegistrar.getInstances(it.project) }
?: emptyList() ?: emptyList()
val lookupTracker = moduleConfiguration.get(CommonConfigurationKeys.LOOKUP_TRACKER)
val enumWhenTracker = moduleConfiguration.get(CommonConfigurationKeys.ENUM_WHEN_TRACKER)
val extendedAnalysisMode = input.configuration.getBoolean(CommonConfigurationKeys.USE_FIR_EXTENDED_CHECKERS)
val sessionConfigurator: FirSessionConfigurator.() -> Unit = {
if (extendedAnalysisMode) {
registerExtendedCommonCheckers()
}
}
val javaSourcesScope = projectEnvironment.getSearchScopeForProjectJavaSources()
val commonSession = runIf(isMppEnabled) { val allSources = mutableListOf<KtSourceFile>().apply {
FirJvmSessionFactory.createModuleBasedSession( addAll(input.groupedSources.commonSources)
commonModuleData!!, addAll(input.groupedSources.platformSources)
sessionProvider,
javaSourcesScope,
projectEnvironment,
commonProviderAndScopeForIncrementalCompilation,
extensionRegistrars,
languageVersionSettings,
lookupTracker,
enumWhenTracker,
needRegisterJavaElementFinder = true,
registerExtraComponents = {},
sessionConfigurator,
)
} }
val platformSession = FirJvmSessionFactory.createModuleBasedSession( // TODO: handle friends paths
platformModuleData, val libraryList = createLibraryListForJvm(rootModuleName, moduleConfiguration, friendPaths = emptyList())
sessionProvider, val sessionWithSources = prepareJvmSessions(
javaSourcesScope, allSources, moduleConfiguration, projectEnvironment, rootModuleName,
projectEnvironment, extensionRegistrars, librariesScope, libraryList,
platformProviderAndScopeForIncrementalCompilation, isCommonSource = input.groupedSources.isCommonSourceForLt,
extensionRegistrars, fileBelongsToModule = input.groupedSources.fileBelongsToModuleForLt,
languageVersionSettings, createProviderAndScopeForIncrementalCompilation = { files ->
lookupTracker, val scope = projectEnvironment.getSearchScopeBySourceFiles(files)
enumWhenTracker, createContextForIncrementalCompilation(
needRegisterJavaElementFinder = true, moduleConfiguration,
registerExtraComponents = {}, projectEnvironment,
sessionConfigurator scope,
previousStepsSymbolProviders,
incrementalExcludesScope
)?.also { (_, _, precompiledBinariesFileScope) ->
precompiledBinariesFileScope?.let { librariesScope -= it }
}
}
) )
val countFilesAndLines = if (performanceManager == null) null else performanceManager::addSourcesStats val countFilesAndLines = if (performanceManager == null) null else performanceManager::addSourcesStats
val commonOutput = commonSession?.let { buildResolveAndCheckFir(it, input.commonSources, diagnosticsReporter, countFilesAndLines) }
val platformOutput = buildResolveAndCheckFir(platformSession, input.platformSources, diagnosticsReporter, countFilesAndLines)
return FirResult(platformOutput, commonOutput) val outputs = sessionWithSources.map { (session, sources) ->
buildResolveAndCheckFir(session, sources, diagnosticsReporter, countFilesAndLines)
}
return FirResult(outputs)
} }
private fun buildResolveAndCheckFir( private fun buildResolveAndCheckFir(
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.cli.jvm.compiler.pipeline package org.jetbrains.kotlin.cli.jvm.compiler.pipeline
import org.jetbrains.kotlin.KtSourceFile
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.diagnostics.impl.BaseDiagnosticsCollector import org.jetbrains.kotlin.diagnostics.impl.BaseDiagnosticsCollector
@@ -22,11 +21,9 @@ import org.jetbrains.kotlin.platform.TargetPlatform
data class ModuleCompilerInput( data class ModuleCompilerInput(
val targetId: TargetId, val targetId: TargetId,
val groupedSources: GroupedKtSources,
val commonPlatform: TargetPlatform, val commonPlatform: TargetPlatform,
val commonSources: Collection<KtSourceFile>,
val platform: TargetPlatform, val platform: TargetPlatform,
val platformSources: Collection<KtSourceFile>,
val sourcesByModule: Map<String, Collection<KtSourceFile>>,
val configuration: CompilerConfiguration, val configuration: CompilerConfiguration,
val friendFirModules: Collection<FirModuleData> = emptyList() val friendFirModules: Collection<FirModuleData> = emptyList()
) )
@@ -7,22 +7,25 @@ package org.jetbrains.kotlin.cli.metadata
import com.intellij.openapi.vfs.StandardFileSystems import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.openapi.vfs.VirtualFileManager
import org.jetbrains.kotlin.KtSourceFile
import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.*
import org.jetbrains.kotlin.cli.common.fir.FirDiagnosticsCompilerResultsReporter import org.jetbrains.kotlin.cli.common.fir.FirDiagnosticsCompilerResultsReporter
import org.jetbrains.kotlin.cli.jvm.compiler.* import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.jvm.compiler.VfsBasedProjectEnvironment
import org.jetbrains.kotlin.cli.jvm.compiler.createContextForIncrementalCompilation
import org.jetbrains.kotlin.cli.jvm.compiler.pipeline.collectSources import org.jetbrains.kotlin.cli.jvm.compiler.pipeline.collectSources
import org.jetbrains.kotlin.cli.jvm.compiler.pipeline.createContextForIncrementalCompilation import org.jetbrains.kotlin.cli.jvm.compiler.pipeline.createContextForIncrementalCompilation
import org.jetbrains.kotlin.cli.jvm.compiler.toAbstractProjectEnvironment
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
import org.jetbrains.kotlin.cli.jvm.config.jvmModularRoots
import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
import org.jetbrains.kotlin.fir.FirModuleDataImpl import org.jetbrains.kotlin.fir.BinaryModuleData
import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers import org.jetbrains.kotlin.fir.DependencyListForCliModule
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
import org.jetbrains.kotlin.fir.moduleData import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.packageFqName import org.jetbrains.kotlin.fir.packageFqName
import org.jetbrains.kotlin.fir.pipeline.ModuleCompilerAnalyzedOutput import org.jetbrains.kotlin.fir.pipeline.ModuleCompilerAnalyzedOutput
@@ -32,23 +35,19 @@ import org.jetbrains.kotlin.fir.pipeline.resolveAndCheckFir
import org.jetbrains.kotlin.fir.serialization.FirElementAwareSerializableStringTable import org.jetbrains.kotlin.fir.serialization.FirElementAwareSerializableStringTable
import org.jetbrains.kotlin.fir.serialization.FirKLibSerializerExtension import org.jetbrains.kotlin.fir.serialization.FirKLibSerializerExtension
import org.jetbrains.kotlin.fir.serialization.serializeSingleFirFile import org.jetbrains.kotlin.fir.serialization.serializeSingleFirFile
import org.jetbrains.kotlin.fir.session.FirCommonSessionFactory
import org.jetbrains.kotlin.fir.session.IncrementalCompilationContext
import org.jetbrains.kotlin.fir.session.environment.AbstractProjectFileSearchScope
import org.jetbrains.kotlin.library.SerializedMetadata import org.jetbrains.kotlin.library.SerializedMetadata
import org.jetbrains.kotlin.library.metadata.KlibMetadataHeaderFlags import org.jetbrains.kotlin.library.metadata.KlibMetadataHeaderFlags
import org.jetbrains.kotlin.library.metadata.KlibMetadataProtoBuf import org.jetbrains.kotlin.library.metadata.KlibMetadataProtoBuf
import org.jetbrains.kotlin.modules.TargetId import org.jetbrains.kotlin.modules.TargetId
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.CommonPlatforms import org.jetbrains.kotlin.platform.CommonPlatforms
import org.jetbrains.kotlin.psi.KtFile
import java.io.File import java.io.File
internal class FirMetadataSerializer( internal class FirMetadataSerializer(
configuration: CompilerConfiguration, configuration: CompilerConfiguration,
environment: KotlinCoreEnvironment environment: KotlinCoreEnvironment
) : AbstractMetadataSerializer<ModuleCompilerAnalyzedOutput>(configuration, environment) { ) : AbstractMetadataSerializer<List<ModuleCompilerAnalyzedOutput>>(configuration, environment) {
override fun analyze(): ModuleCompilerAnalyzedOutput? { override fun analyze(): List<ModuleCompilerAnalyzedOutput>? {
val performanceManager = environment.configuration.getNotNull(CLIConfigurationKeys.PERF_MANAGER) val performanceManager = environment.configuration.getNotNull(CLIConfigurationKeys.PERF_MANAGER)
performanceManager.notifyAnalysisStarted() performanceManager.notifyAnalysisStarted()
@@ -57,23 +56,28 @@ internal class FirMetadataSerializer(
val moduleName = Name.special("<${configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)}>") val moduleName = Name.special("<${configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)}>")
val isLightTree = configuration.getBoolean(CommonConfigurationKeys.USE_LIGHT_TREE) val isLightTree = configuration.getBoolean(CommonConfigurationKeys.USE_LIGHT_TREE)
val sessionProvider = FirProjectSessionProvider() val rootModuleName = moduleName.asString()
val binaryModuleData = BinaryModuleData.initialize(
Name.identifier(rootModuleName),
CommonPlatforms.defaultCommonPlatform,
CommonPlatformAnalyzerServices
)
val libraryList = DependencyListForCliModule.build(binaryModuleData) {
dependencies(configuration.jvmClasspathRoots.map { it.toPath() })
dependencies(configuration.jvmModularRoots.map { it.toPath() })
friendDependencies(configuration[JVMConfigurationKeys.FRIEND_PATHS] ?: emptyList())
}
val projectEnvironment: VfsBasedProjectEnvironment val diagnosticsReporter = DiagnosticReporterFactory.createPendingReporter()
var librariesScope: AbstractProjectFileSearchScope
val sourceScope: AbstractProjectFileSearchScope
val librariesHelperScope: AbstractProjectFileSearchScope
var psiFiles: List<KtFile>? = null
var ltFiles: List<KtSourceFile>? = null
val providerAndScopeForIncrementalCompilation: IncrementalCompilationContext?
if (isLightTree) { val outputs = if (isLightTree) {
projectEnvironment = environment.toAbstractProjectEnvironment() as VfsBasedProjectEnvironment val projectEnvironment = environment.toAbstractProjectEnvironment() as VfsBasedProjectEnvironment
librariesScope = projectEnvironment.getSearchScopeForProjectLibraries() var librariesScope = projectEnvironment.getSearchScopeForProjectLibraries()
librariesHelperScope = projectEnvironment.getSearchScopeForProjectLibraries() val groupedSources = collectSources(configuration, projectEnvironment, messageCollector)
ltFiles = collectSources(configuration, projectEnvironment, messageCollector).let { it.commonSources + it.platformSources }.toList() val extensionRegistrars = FirExtensionRegistrar.getInstances(projectEnvironment.project)
sourceScope = projectEnvironment.getSearchScopeBySourceFiles(ltFiles) val ltFiles = groupedSources.let { it.commonSources + it.platformSources }.toList()
providerAndScopeForIncrementalCompilation = createContextForIncrementalCompilation( val sourceScope = projectEnvironment.getSearchScopeBySourceFiles(ltFiles)
val providerAndScopeForIncrementalCompilation = createContextForIncrementalCompilation(
configuration, configuration,
projectEnvironment, projectEnvironment,
sourceScope, sourceScope,
@@ -82,16 +86,26 @@ internal class FirMetadataSerializer(
)?.also { (_, _, precompiledBinariesFileScope) -> )?.also { (_, _, precompiledBinariesFileScope) ->
precompiledBinariesFileScope?.let { librariesScope -= it } precompiledBinariesFileScope?.let { librariesScope -= it }
} }
val sessionsWithSources = prepareCommonSessions(
ltFiles, configuration, projectEnvironment, rootModuleName, extensionRegistrars,
librariesScope, libraryList, groupedSources.isCommonSourceForLt, groupedSources.fileBelongsToModuleForLt,
createProviderAndScopeForIncrementalCompilation = { providerAndScopeForIncrementalCompilation }
)
sessionsWithSources.map { (session, files) ->
val firFiles = session.buildFirViaLightTree(files, diagnosticsReporter, performanceManager::addSourcesStats)
resolveAndCheckFir(session, firFiles, diagnosticsReporter)
}
} else { } else {
projectEnvironment = VfsBasedProjectEnvironment( val projectEnvironment = VfsBasedProjectEnvironment(
environment.project, environment.project,
VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL) VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL)
) { environment.createPackagePartProvider(it) } ) { environment.createPackagePartProvider(it) }
librariesScope = projectEnvironment.getSearchScopeForProjectLibraries() var librariesScope = projectEnvironment.getSearchScopeForProjectLibraries()
librariesHelperScope = librariesScope val extensionRegistrars = FirExtensionRegistrar.getInstances(projectEnvironment.project)
psiFiles = environment.getSourceFiles() val psiFiles = environment.getSourceFiles()
sourceScope = projectEnvironment.getSearchScopeByPsiFiles(psiFiles) + projectEnvironment.getSearchScopeForProjectJavaSources() val sourceScope =
providerAndScopeForIncrementalCompilation = createContextForIncrementalCompilation( projectEnvironment.getSearchScopeByPsiFiles(psiFiles) + projectEnvironment.getSearchScopeForProjectJavaSources()
val providerAndScopeForIncrementalCompilation = createContextForIncrementalCompilation(
projectEnvironment, projectEnvironment,
configuration.get(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS), configuration.get(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS),
configuration, configuration,
@@ -101,80 +115,51 @@ internal class FirMetadataSerializer(
providerAndScopeForIncrementalCompilation?.precompiledBinariesFileScope?.let { providerAndScopeForIncrementalCompilation?.precompiledBinariesFileScope?.let {
librariesScope -= it librariesScope -= it
} }
val sessionsWithSources = prepareCommonSessions(
psiFiles, configuration, projectEnvironment, rootModuleName, extensionRegistrars,
librariesScope, libraryList, isCommonSourceForPsi, fileBelongsToModuleForPsi,
createProviderAndScopeForIncrementalCompilation = { providerAndScopeForIncrementalCompilation }
)
sessionsWithSources.map { (session, files) ->
val firFiles = session.buildFirFromKtFiles(files)
resolveAndCheckFir(session, firFiles, diagnosticsReporter)
}
} }
val libraryList = createFirLibraryListAndSession(
moduleName.asString(), configuration, projectEnvironment,
scope = librariesHelperScope, librariesScope = librariesScope, friendPaths = emptyList(), sessionProvider = sessionProvider,
isJvm = false
)
val commonModuleData = FirModuleDataImpl(
moduleName,
libraryList.regularDependencies,
listOf(),
libraryList.friendsDependencies,
CommonPlatforms.defaultCommonPlatform,
CommonPlatformAnalyzerServices
)
val project = projectEnvironment.project
val session = FirCommonSessionFactory.createModuleBasedSession(
commonModuleData,
sessionProvider,
sourceScope,
projectEnvironment,
incrementalCompilationContext = providerAndScopeForIncrementalCompilation,
FirExtensionRegistrar.getInstances(project),
configuration.languageVersionSettings,
lookupTracker = configuration.get(CommonConfigurationKeys.LOOKUP_TRACKER),
enumWhenTracker = configuration.get(CommonConfigurationKeys.ENUM_WHEN_TRACKER),
needRegisterJavaElementFinder = true,
registerExtraComponents = {},
init = {
if (configuration.getBoolean(CommonConfigurationKeys.USE_FIR_EXTENDED_CHECKERS)) {
registerExtendedCommonCheckers()
}
}
)
val diagnosticsReporter = DiagnosticReporterFactory.createPendingReporter()
val firFiles = if (isLightTree)
session.buildFirViaLightTree(ltFiles!!, diagnosticsReporter, performanceManager::addSourcesStats)
else
session.buildFirFromKtFiles(psiFiles!!)
val result = resolveAndCheckFir(session, firFiles, diagnosticsReporter)
return if (diagnosticsReporter.hasErrors) { return if (diagnosticsReporter.hasErrors) {
val renderDiagnosticNames = configuration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME) val renderDiagnosticNames = configuration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME)
FirDiagnosticsCompilerResultsReporter.reportToMessageCollector(diagnosticsReporter, messageCollector, renderDiagnosticNames) FirDiagnosticsCompilerResultsReporter.reportToMessageCollector(diagnosticsReporter, messageCollector, renderDiagnosticNames)
null null
} else { } else {
result outputs
}.also { }.also {
performanceManager.notifyAnalysisFinished() performanceManager.notifyAnalysisFinished()
} }
} }
override fun serialize(analysisResult: ModuleCompilerAnalyzedOutput, destDir: File) { override fun serialize(analysisResult: List<ModuleCompilerAnalyzedOutput>, destDir: File) {
val fragments = mutableMapOf<String, MutableList<ByteArray>>() val fragments = mutableMapOf<String, MutableList<ByteArray>>()
val (session, scopeSession, fir) = analysisResult for (output in analysisResult) {
val (session, scopeSession, fir) = output
val languageVersionSettings = environment.configuration.languageVersionSettings val languageVersionSettings = environment.configuration.languageVersionSettings
for (firFile in fir) { for (firFile in fir) {
val packageFragment = serializeSingleFirFile( val packageFragment = serializeSingleFirFile(
firFile, firFile,
session, session,
scopeSession, scopeSession,
FirKLibSerializerExtension(session, metadataVersion, FirElementAwareSerializableStringTable()), FirKLibSerializerExtension(session, metadataVersion, FirElementAwareSerializableStringTable()),
languageVersionSettings languageVersionSettings
) )
fragments.getOrPut(firFile.packageFqName.asString()) { mutableListOf() }.add(packageFragment.toByteArray()) fragments.getOrPut(firFile.packageFqName.asString()) { mutableListOf() }.add(packageFragment.toByteArray())
}
} }
val header = KlibMetadataProtoBuf.Header.newBuilder() val header = KlibMetadataProtoBuf.Header.newBuilder()
header.moduleName = session.moduleData.name.asString() header.moduleName = analysisResult.last().session.moduleData.name.asString()
if (configuration.languageVersionSettings.isPreRelease()) { if (configuration.languageVersionSettings.isPreRelease()) {
header.flags = KlibMetadataHeaderFlags.PRE_RELEASE header.flags = KlibMetadataHeaderFlags.PRE_RELEASE
@@ -24,10 +24,7 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
import org.jetbrains.kotlin.ir.util.IdSignatureComposer import org.jetbrains.kotlin.ir.util.IdSignatureComposer
import org.jetbrains.kotlin.ir.util.KotlinMangler import org.jetbrains.kotlin.ir.util.KotlinMangler
data class FirResult( data class FirResult(val outputs: List<ModuleCompilerAnalyzedOutput>)
val platformOutput: ModuleCompilerAnalyzedOutput,
val commonOutput: ModuleCompilerAnalyzedOutput?
)
data class ModuleCompilerAnalyzedOutput( data class ModuleCompilerAnalyzedOutput(
val session: FirSession, val session: FirSession,
@@ -67,46 +64,58 @@ fun FirResult.convertToIrAndActualize(
manglerCreator = { FirJvmKotlinMangler() } // TODO: replace with potentially simpler version for other backends. manglerCreator = { FirJvmKotlinMangler() } // TODO: replace with potentially simpler version for other backends.
) )
if (commonOutput != null) { when (outputs.size) {
val commonIrOutput = commonOutput.convertToIr( 0 -> error("No modules found")
fir2IrExtensions, 1 -> {
irGeneratorExtensions, result = outputs.single().convertToIr(
linkViaSignatures = linkViaSignatures, fir2IrExtensions,
commonMemberStorage = commonMemberStorage, irGeneratorExtensions,
irBuiltIns = null, linkViaSignatures = linkViaSignatures,
irMangler, commonMemberStorage = commonMemberStorage,
visibilityConverter, irBuiltIns = null,
kotlinBuiltIns, irMangler,
).also { visibilityConverter,
fir2IrResultPostCompute(it) kotlinBuiltIns,
)
} }
result = platformOutput.convertToIr( else -> {
fir2IrExtensions, val platformOutput = outputs.last()
irGeneratorExtensions, val commonOutputs = outputs.dropLast(1)
linkViaSignatures = linkViaSignatures, var irBuiltIns: IrBuiltInsOverFir? = null
commonMemberStorage = commonMemberStorage, val commonIrOutputs = commonOutputs.map {
irBuiltIns = commonIrOutput.components.irBuiltIns, it.convertToIr(
irMangler, fir2IrExtensions,
visibilityConverter, irGeneratorExtensions,
kotlinBuiltIns, linkViaSignatures = linkViaSignatures,
).also { commonMemberStorage = commonMemberStorage,
fir2IrResultPostCompute(it) irBuiltIns = irBuiltIns,
irMangler,
visibilityConverter,
kotlinBuiltIns,
).also { result ->
fir2IrResultPostCompute(result)
if (irBuiltIns == null) {
irBuiltIns = result.components.irBuiltIns
}
}
}
result = platformOutput.convertToIr(
fir2IrExtensions,
irGeneratorExtensions,
linkViaSignatures = linkViaSignatures,
commonMemberStorage = commonMemberStorage,
irBuiltIns = irBuiltIns!!,
irMangler,
visibilityConverter,
kotlinBuiltIns,
).also {
fir2IrResultPostCompute(it)
}
IrActualizer.actualize(
result.irModuleFragment,
commonIrOutputs.map { it.irModuleFragment }
)
} }
IrActualizer.actualize(
result.irModuleFragment,
listOf(commonIrOutput.irModuleFragment)
)
} else {
result = platformOutput.convertToIr(
fir2IrExtensions,
irGeneratorExtensions,
linkViaSignatures = linkViaSignatures,
commonMemberStorage = commonMemberStorage,
irBuiltIns = null,
irMangler,
visibilityConverter,
kotlinBuiltIns,
)
} }
return result return result
@@ -37,7 +37,7 @@ object FirCommonSessionFactory : FirAbstractSessionFactory() {
sessionProvider: FirProjectSessionProvider, sessionProvider: FirProjectSessionProvider,
moduleDataProvider: ModuleDataProvider, moduleDataProvider: ModuleDataProvider,
projectEnvironment: AbstractProjectEnvironment, projectEnvironment: AbstractProjectEnvironment,
scope: AbstractProjectFileSearchScope, librariesScope: AbstractProjectFileSearchScope,
packageAndMetadataPartProvider: PackageAndMetadataPartProvider, packageAndMetadataPartProvider: PackageAndMetadataPartProvider,
languageVersionSettings: LanguageVersionSettings, languageVersionSettings: LanguageVersionSettings,
registerExtraComponents: ((FirSession) -> Unit), registerExtraComponents: ((FirSession) -> Unit),
@@ -59,7 +59,7 @@ object FirCommonSessionFactory : FirAbstractSessionFactory() {
moduleDataProvider, moduleDataProvider,
kotlinScopeProvider, kotlinScopeProvider,
packageAndMetadataPartProvider, packageAndMetadataPartProvider,
projectEnvironment.getKotlinClassFinder(scope) projectEnvironment.getKotlinClassFinder(librariesScope)
), ),
FirBuiltinSymbolProvider(session, builtinsModuleData, kotlinScopeProvider), FirBuiltinSymbolProvider(session, builtinsModuleData, kotlinScopeProvider),
FirCloneableSymbolProvider(session, builtinsModuleData, kotlinScopeProvider), FirCloneableSymbolProvider(session, builtinsModuleData, kotlinScopeProvider),
@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.backend.jvm.JvmIrDeserializerImpl import org.jetbrains.kotlin.backend.jvm.JvmIrDeserializerImpl
import org.jetbrains.kotlin.build.DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS import org.jetbrains.kotlin.build.DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS
import org.jetbrains.kotlin.build.report.BuildReporter import org.jetbrains.kotlin.build.report.BuildReporter
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.ExitCode import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
@@ -40,26 +39,15 @@ import org.jetbrains.kotlin.cli.jvm.config.*
import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser import org.jetbrains.kotlin.cli.jvm.plugins.PluginCliParser
import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.backend.Fir2IrConverter
import org.jetbrains.kotlin.fir.backend.jvm.Fir2IrJvmSpecialAnnotationSymbolProvider
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmKotlinMangler
import org.jetbrains.kotlin.fir.backend.jvm.FirJvmVisibilityConverter
import org.jetbrains.kotlin.fir.backend.jvm.JvmFir2IrExtensions import org.jetbrains.kotlin.fir.backend.jvm.JvmFir2IrExtensions
import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.pipeline.FirResult import org.jetbrains.kotlin.fir.pipeline.FirResult
import org.jetbrains.kotlin.fir.pipeline.ModuleCompilerAnalyzedOutput
import org.jetbrains.kotlin.fir.pipeline.convertToIrAndActualizeForJvm import org.jetbrains.kotlin.fir.pipeline.convertToIrAndActualizeForJvm
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirProviderImpl
import org.jetbrains.kotlin.fir.session.environment.AbstractProjectFileSearchScope import org.jetbrains.kotlin.fir.session.environment.AbstractProjectFileSearchScope
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
import org.jetbrains.kotlin.incremental.components.InlineConstTracker import org.jetbrains.kotlin.incremental.components.InlineConstTracker
import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.multiproject.ModulesApiHistory import org.jetbrains.kotlin.incremental.multiproject.ModulesApiHistory
import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmIrMangler import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmIrMangler
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
import org.jetbrains.kotlin.ir.util.IrMessageLogger import org.jetbrains.kotlin.ir.util.IrMessageLogger
import org.jetbrains.kotlin.load.java.JavaClassesTracker import org.jetbrains.kotlin.load.java.JavaClassesTracker
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
@@ -212,13 +200,18 @@ class IncrementalFirJvmCompilerRunner(
fun firIncrementalCycle(): FirResult? { fun firIncrementalCycle(): FirResult? {
while (true) { while (true) {
val dirtySourcesByModuleName = sourcesByModuleName.mapValues { (_, sources) -> val dirtySourcesByModuleName = sourcesByModuleName.mapValues { (_, sources) ->
sources.filter { dirtySources.any { df -> df.path == it.path } } sources.filterTo(mutableSetOf()) { dirtySources.any { df -> df.path == it.path } }
} }
val groupedSource = GroupedKtSources(
commonSources = allCommonSourceFiles.filter { dirtySources.any { df -> df.path == it.path } },
platformSources = allPlatformSourceFiles.filter { dirtySources.any { df -> df.path == it.path } },
sourcesByModuleName = dirtySourcesByModuleName
)
val compilerInput = ModuleCompilerInput( val compilerInput = ModuleCompilerInput(
targetId, targetId,
CommonPlatforms.defaultCommonPlatform, allCommonSourceFiles.filter { dirtySources.any { df -> df.path == it.path } }, groupedSource,
JvmPlatforms.unspecifiedJvmPlatform, allPlatformSourceFiles.filter { dirtySources.any { df -> df.path == it.path } }, CommonPlatforms.defaultCommonPlatform,
dirtySourcesByModuleName, JvmPlatforms.unspecifiedJvmPlatform,
configuration configuration
) )
@@ -238,7 +231,7 @@ class IncrementalFirJvmCompilerRunner(
// TODO: consider what to do if many compilations find a main class // TODO: consider what to do if many compilations find a main class
if (mainClassFqName == null && configuration.get(JVMConfigurationKeys.OUTPUT_JAR) != null) { if (mainClassFqName == null && configuration.get(JVMConfigurationKeys.OUTPUT_JAR) != null) {
mainClassFqName = findMainClass(analysisResults.platformOutput.fir) mainClassFqName = findMainClass(analysisResults.outputs.last().fir)
} }
// TODO: switch the whole IC to KtSourceFile instead of FIle // TODO: switch the whole IC to KtSourceFile instead of FIle
@@ -128,8 +128,9 @@ internal fun collectNewDirtySources(
} }
} }
analysisResults.commonOutput?.let { visitFirFiles(it) } for (output in analysisResults.outputs) {
visitFirFiles(analysisResults.platformOutput) visitFirFiles(output)
}
val (dirtyLookupSymbols, dirtyClassFqNames, forceRecompile) = changesCollector.getDirtyData(listOf(caches.platformCache), reporter) val (dirtyLookupSymbols, dirtyClassFqNames, forceRecompile) = changesCollector.getDirtyData(listOf(caches.platformCache), reporter)
+15
View File
@@ -0,0 +1,15 @@
$TESTDATA_DIR$/../jvm/hmpp/src/a.kt
$TESTDATA_DIR$/../jvm/hmpp/src/b.kt
$TESTDATA_DIR$/../jvm/hmpp/src/c.kt
-ir-output-dir
$TEMP_DIR$/out.js
-ir-output-name
fir-hmpp
-language-version
2.0
-XXLanguage\:+MultiPlatformProjects
-Xmodule=a;$TESTDATA_DIR$/../jvm/hmpp/src/a.kt
-Xmodule=b;$TESTDATA_DIR$/../jvm/hmpp/src/b.kt
-Xmodule=c;$TESTDATA_DIR$/../jvm/hmpp/src/c.kt
-XdependsOn=b\:a
-XdependsOn=c\:b
+11
View File
@@ -0,0 +1,11 @@
warning: ATTENTION!
This build uses unsafe internal compiler arguments:
-XXLanguage:+MultiPlatformProjects
This mode is not recommended for production use,
as no stability/compatibility guarantees are given on
compiler or generated code. Use it at your own risk!
warning: language version 2.0 is experimental, there are no backwards compatibility guarantees for new language and library features
OK
@@ -0,0 +1,13 @@
$TESTDATA_DIR$/src/a.kt
$TESTDATA_DIR$/src/b.kt
$TESTDATA_DIR$/src/c.kt
-d
$TEMP_DIR$
-language-version
2.0
-XXLanguage\:+MultiPlatformProjects
-Xmodule=a;$TESTDATA_DIR$/src/a.kt
-Xmodule=b;$TESTDATA_DIR$/src/b.kt
-Xmodule=c;$TESTDATA_DIR$/src/c.kt
-XdependsOn=b\:a
-XdependsOn=c\:b
@@ -0,0 +1,11 @@
warning: ATTENTION!
This build uses unsafe internal compiler arguments:
-XXLanguage:+MultiPlatformProjects
This mode is not recommended for production use,
as no stability/compatibility guarantees are given on
compiler or generated code. Use it at your own risk!
warning: language version 2.0 is experimental, there are no backwards compatibility guarantees for new language and library features
OK
+13
View File
@@ -0,0 +1,13 @@
$TESTDATA_DIR$/../jvm/hmpp/src/a.kt
$TESTDATA_DIR$/../jvm/hmpp/src/b.kt
$TESTDATA_DIR$/../jvm/hmpp/src/c.kt
-d
$TEMP_DIR$
-language-version
2.0
-XXLanguage\:+MultiPlatformProjects
-Xmodule=a;$TESTDATA_DIR$/../jvm/hmpp/src/a.kt
-Xmodule=b;$TESTDATA_DIR$/../jvm/hmpp/src/b.kt
-Xmodule=c;$TESTDATA_DIR$/../jvm/hmpp/src/c.kt
-XdependsOn=b\:a
-XdependsOn=c\:b
+11
View File
@@ -0,0 +1,11 @@
warning: ATTENTION!
This build uses unsafe internal compiler arguments:
-XXLanguage:+MultiPlatformProjects
This mode is not recommended for production use,
as no stability/compatibility guarantees are given on
compiler or generated code. Use it at your own risk!
warning: language version 2.0 is experimental, there are no backwards compatibility guarantees for new language and library features
OK
@@ -166,6 +166,11 @@ public class CliTestGenerated extends AbstractCliTest {
public void testSourceNotInAnyModule() throws Exception { public void testSourceNotInAnyModule() throws Exception {
runTest("compiler/testData/cli/jvm/hmpp/sourceNotInAnyModule.args"); runTest("compiler/testData/cli/jvm/hmpp/sourceNotInAnyModule.args");
} }
@TestMetadata("successfulCompilation.args")
public void testSuccessfulCompilation() throws Exception {
runTest("compiler/testData/cli/jvm/hmpp/successfulCompilation.args");
}
} }
@TestMetadata("compiler/testData/cli/jvm") @TestMetadata("compiler/testData/cli/jvm")
@@ -1453,6 +1458,11 @@ public class CliTestGenerated extends AbstractCliTest {
runTest("compiler/testData/cli/js/sourceMapRootMultiple.args"); runTest("compiler/testData/cli/js/sourceMapRootMultiple.args");
} }
@TestMetadata("successfulHmpp.args")
public void testSuccessfulHmpp() throws Exception {
runTest("compiler/testData/cli/js/successfulHmpp.args");
}
@TestMetadata("suppressAllWarningsJS.args") @TestMetadata("suppressAllWarningsJS.args")
public void testSuppressAllWarningsJS() throws Exception { public void testSuppressAllWarningsJS() throws Exception {
runTest("compiler/testData/cli/js/suppressAllWarningsJS.args"); runTest("compiler/testData/cli/js/suppressAllWarningsJS.args");
@@ -1618,5 +1628,10 @@ public class CliTestGenerated extends AbstractCliTest {
public void testOptionalExpectationUsageWithFir() throws Exception { public void testOptionalExpectationUsageWithFir() throws Exception {
runTest("compiler/testData/cli/metadata/optionalExpectationUsageWithFir.args"); runTest("compiler/testData/cli/metadata/optionalExpectationUsageWithFir.args");
} }
@TestMetadata("successfulHmpp.args")
public void testSuccessfulHmpp() throws Exception {
runTest("compiler/testData/cli/metadata/successfulHmpp.args");
}
} }
} }
@@ -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.PhaseContext
import org.jetbrains.kotlin.backend.konan.driver.phases.FirOutput import org.jetbrains.kotlin.backend.konan.driver.phases.FirOutput
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys 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.fir.FirDiagnosticsCompilerResultsReporter
import org.jetbrains.kotlin.cli.common.isCommonSourceForPsi
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport 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.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.diagnostics.DiagnosticReporterFactory
import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.BinaryModuleData
import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers import org.jetbrains.kotlin.fir.DependencyListForCliModule
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider import org.jetbrains.kotlin.fir.pipeline.FirResult
import org.jetbrains.kotlin.fir.pipeline.* import org.jetbrains.kotlin.fir.pipeline.buildResolveAndCheckFir
import org.jetbrains.kotlin.fir.session.FirNativeSessionFactory import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.session.FirSessionConfigurator
import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.CommonPlatforms 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.konan.platform.NativePlatformAnalyzerServices
import org.jetbrains.kotlin.resolve.multiplatform.isCommonSource
internal fun PhaseContext.firFrontend( internal fun PhaseContext.firFrontend(input: KotlinCoreEnvironment): FirOutput {
input: KotlinCoreEnvironment
): FirOutput {
val configuration = input.configuration val configuration = input.configuration
val messageCollector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) val messageCollector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
val diagnosticsReporter = DiagnosticReporterFactory.createPendingReporter() val diagnosticsReporter = DiagnosticReporterFactory.createPendingReporter()
val renderDiagnosticNames = configuration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME) val renderDiagnosticNames = configuration.getBoolean(CLIConfigurationKeys.RENDER_DIAGNOSTIC_INTERNAL_NAME)
// FIR // FIR
val sessionProvider = FirProjectSessionProvider()
val extensionRegistrars = FirExtensionRegistrar.getInstances(input.project) val extensionRegistrars = FirExtensionRegistrar.getInstances(input.project)
val sessionConfigurator: FirSessionConfigurator.() -> Unit = {
if (configuration.languageVersionSettings.getFlag(AnalysisFlags.extendedCompilerChecks)) {
registerExtendedCommonCheckers()
}
}
val mainModuleName = Name.special("<${config.moduleId}>") val mainModuleName = Name.special("<${config.moduleId}>")
val ktFiles = input.getSourceFiles() val ktFiles = input.getSourceFiles()
val syntaxErrors = ktFiles.fold(false) { errorsFound, ktFile -> val syntaxErrors = ktFiles.fold(false) { errorsFound, ktFile ->
@@ -51,57 +40,24 @@ internal fun PhaseContext.firFrontend(
// TODO: !!! dependencies module data? // TODO: !!! dependencies module data?
} }
val resolvedLibraries: List<KotlinResolvedLibrary> = config.resolvedLibraries.getFullResolvedList() val resolvedLibraries: List<KotlinResolvedLibrary> = config.resolvedLibraries.getFullResolvedList()
FirNativeSessionFactory.createLibrarySession(
mainModuleName, val sessionsWithSources = prepareNativeSessions(
resolvedLibraries, ktFiles, configuration, mainModuleName.asString(), resolvedLibraries, dependencyList,
sessionProvider, extensionRegistrars, isCommonSourceForPsi, fileBelongsToModuleForPsi
dependencyList.moduleDataProvider,
configuration.languageVersionSettings,
registerExtraComponents = {},
) )
fun runFrontend( val outputs = sessionsWithSources.map { (session, sources) ->
moduleName: Name, buildResolveAndCheckFir(session, sources, diagnosticsReporter).also {
dependsOn: List<FirModuleData>, if (shouldPrintFiles()) {
ktFiles: List<KtFile> it.fir.forEach { println(it.render()) }
): 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)
} }
return if (syntaxErrors || diagnosticsReporter.hasErrors) { return if (syntaxErrors || diagnosticsReporter.hasErrors) {
FirDiagnosticsCompilerResultsReporter.reportToMessageCollector(diagnosticsReporter, messageCollector, renderDiagnosticNames) FirDiagnosticsCompilerResultsReporter.reportToMessageCollector(diagnosticsReporter, messageCollector, renderDiagnosticNames)
FirOutput.ShouldNotGenerateCode FirOutput.ShouldNotGenerateCode
} else { } 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.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirAnnotation import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.resolve.ScopeSession 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.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.util.IrMessageLogger 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.KlibMetadataProtoBuf
import org.jetbrains.kotlin.library.metadata.resolver.TopologicalLibraryOrder import org.jetbrains.kotlin.library.metadata.resolver.TopologicalLibraryOrder
import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.utils.toMetadataVersion
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
import org.jetbrains.kotlin.metadata.serialization.MutableVersionRequirementTable import org.jetbrains.kotlin.metadata.serialization.MutableVersionRequirementTable
import org.jetbrains.kotlin.psi import org.jetbrains.kotlin.psi
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.toMetadataVersion
internal fun PhaseContext.firSerializer( internal fun PhaseContext.firSerializer(
input: Fir2IrOutput input: Fir2IrOutput
@@ -39,7 +41,7 @@ internal fun PhaseContext.firSerializer(
val sourceFiles = mutableListOf<KtSourceFile>() val sourceFiles = mutableListOf<KtSourceFile>()
val firFilesAndSessionsBySourceFile = mutableMapOf<KtSourceFile, Triple<FirFile, FirSession, ScopeSession>>() 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) { for (firFile in firOutput.fir) {
sourceFiles.add(firFile.sourceFile!!) sourceFiles.add(firFile.sourceFile!!)
firFilesAndSessionsBySourceFile[firFile.sourceFile!!] = Triple(firFile, firOutput.session, firOutput.scopeSession) firFilesAndSessionsBySourceFile[firFile.sourceFile!!] = Triple(firFile, firOutput.session, firOutput.scopeSession)
@@ -7,8 +7,7 @@ package org.jetbrains.kotlin.scripting.compiler.plugin.impl
import org.jetbrains.kotlin.KtPsiSourceFile import org.jetbrains.kotlin.KtPsiSourceFile
import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.*
import org.jetbrains.kotlin.cli.common.checkKotlinPackageUsage
import org.jetbrains.kotlin.cli.common.fir.FirDiagnosticsCompilerResultsReporter import org.jetbrains.kotlin.cli.common.fir.FirDiagnosticsCompilerResultsReporter
import org.jetbrains.kotlin.cli.common.fir.reportToMessageCollector import org.jetbrains.kotlin.cli.common.fir.reportToMessageCollector
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
@@ -26,20 +25,14 @@ import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
import org.jetbrains.kotlin.fir.FirModuleDataImpl
import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar 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.pipeline.*
import org.jetbrains.kotlin.fir.session.FirJvmSessionFactory
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
import org.jetbrains.kotlin.modules.TargetId import org.jetbrains.kotlin.modules.TargetId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.CommonPlatforms import org.jetbrains.kotlin.platform.CommonPlatforms
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
import org.jetbrains.kotlin.scripting.compiler.plugin.ScriptCompilerProxy import org.jetbrains.kotlin.scripting.compiler.plugin.ScriptCompilerProxy
import org.jetbrains.kotlin.scripting.compiler.plugin.dependencies.ScriptsCompilationDependencies import org.jetbrains.kotlin.scripting.compiler.plugin.dependencies.ScriptsCompilationDependencies
import org.jetbrains.kotlin.scripting.compiler.plugin.services.scriptDefinitionProviderService import org.jetbrains.kotlin.scripting.compiler.plugin.services.scriptDefinitionProviderService
@@ -108,16 +101,17 @@ private fun withScriptCompilationCache(
messageCollector: ScriptDiagnosticsMessageCollector, messageCollector: ScriptDiagnosticsMessageCollector,
body: () -> ResultWithDiagnostics<CompiledScript> body: () -> ResultWithDiagnostics<CompiledScript>
): ResultWithDiagnostics<CompiledScript> { ): ResultWithDiagnostics<CompiledScript> {
val cache = scriptCompilationConfiguration[ScriptCompilationConfiguration.hostConfiguration]?.get(ScriptingHostConfiguration.jvm.compilationCache) val cache = scriptCompilationConfiguration[ScriptCompilationConfiguration.hostConfiguration]
?.get(ScriptingHostConfiguration.jvm.compilationCache)
val cached = cache?.get(script, scriptCompilationConfiguration) val cached = cache?.get(script, scriptCompilationConfiguration)
return if (cached != null) cached.asSuccess(messageCollector.diagnostics) return cached?.asSuccess(messageCollector.diagnostics)
else body().also { ?: body().also {
if (cache != null && it is ResultWithDiagnostics.Success) { if (cache != null && it is ResultWithDiagnostics.Success) {
cache.store(it.value, script, scriptCompilationConfiguration) cache.store(it.value, script, scriptCompilationConfiguration)
}
} }
}
} }
private fun compileImpl( private fun compileImpl(
@@ -312,7 +306,6 @@ private fun doCompileWithK2(
messageCollector: ScriptDiagnosticsMessageCollector, messageCollector: ScriptDiagnosticsMessageCollector,
getScriptConfiguration: (KtFile) -> ScriptCompilationConfiguration getScriptConfiguration: (KtFile) -> ScriptCompilationConfiguration
): ResultWithDiagnostics<KJvmCompiledScript> { ): ResultWithDiagnostics<KJvmCompiledScript> {
val syntaxErrors = sourceFiles.fold(false) { errorsFound, ktFile -> val syntaxErrors = sourceFiles.fold(false) { errorsFound, ktFile ->
AnalyzerWithCompilerReport.reportSyntaxErrors(ktFile, messageCollector).isHasErrors or errorsFound AnalyzerWithCompilerReport.reportSyntaxErrors(ktFile, messageCollector).isHasErrors or errorsFound
} }
@@ -337,9 +330,9 @@ private fun doCompileWithK2(
val compilerInput = ModuleCompilerInput( val compilerInput = ModuleCompilerInput(
targetId, targetId,
CommonPlatforms.defaultCommonPlatform, emptyList(), GroupedKtSources(platformSources = sources, commonSources = emptySet(), sourcesByModuleName = emptyMap()),
JvmPlatforms.unspecifiedJvmPlatform, sources, CommonPlatforms.defaultCommonPlatform,
sourcesByModule = emptyMap(), JvmPlatforms.unspecifiedJvmPlatform,
kotlinCompilerConfiguration kotlinCompilerConfiguration
) )
@@ -347,9 +340,6 @@ private fun doCompileWithK2(
val compilerEnvironment = ModuleCompilerEnvironment(projectEnvironment, diagnosticsReporter) val compilerEnvironment = ModuleCompilerEnvironment(projectEnvironment, diagnosticsReporter)
val sourcesScope = compilerEnvironment.projectEnvironment.getSearchScopeBySourceFiles(sources) val sourcesScope = compilerEnvironment.projectEnvironment.getSearchScopeBySourceFiles(sources)
val sessionProvider = FirProjectSessionProvider()
val extendedAnalysisMode = kotlinCompilerConfiguration.getBoolean(CommonConfigurationKeys.USE_FIR_EXTENDED_CHECKERS)
var librariesScope = projectEnvironment.getSearchScopeForProjectLibraries() var librariesScope = projectEnvironment.getSearchScopeForProjectLibraries()
val providerAndScopeForIncrementalCompilation = createContextForIncrementalCompilation( val providerAndScopeForIncrementalCompilation = createContextForIncrementalCompilation(
compilerInput.configuration, compilerInput.configuration,
@@ -360,41 +350,22 @@ private fun doCompileWithK2(
)?.also { (_, _, precompiledBinariesFileScope) -> )?.also { (_, _, precompiledBinariesFileScope) ->
precompiledBinariesFileScope?.let { librariesScope -= it } precompiledBinariesFileScope?.let { librariesScope -= it }
} }
val libraryList = createFirLibraryListAndSession(
targetId.name, val extensionRegistrars = (projectEnvironment as? VfsBasedProjectEnvironment)
?.let { FirExtensionRegistrar.getInstances(it.project) }
.orEmpty()
val rootModuleName = targetId.name
val libraryList = createLibraryListForJvm(
rootModuleName,
kotlinCompilerConfiguration, kotlinCompilerConfiguration,
projectEnvironment, friendPaths = emptyList()
scope = projectEnvironment.getSearchScopeForProjectLibraries(),
librariesScope = librariesScope,
friendPaths = emptyList(),
sessionProvider
) )
val moduleData = FirModuleDataImpl( val session = prepareJvmSessions(
Name.identifier(targetId.name), sourceFiles, kotlinCompilerConfiguration, projectEnvironment, rootModuleName, extensionRegistrars,
libraryList.regularDependencies, librariesScope, libraryList, isCommonSourceForPsi, fileBelongsToModuleForPsi,
listOf(), createProviderAndScopeForIncrementalCompilation = { providerAndScopeForIncrementalCompilation }
libraryList.friendsDependencies, ).single().session
JvmPlatforms.unspecifiedJvmPlatform,
JvmPlatformAnalyzerServices
)
val session = FirJvmSessionFactory.createModuleBasedSession(
moduleData,
sessionProvider,
sourcesScope,
projectEnvironment,
providerAndScopeForIncrementalCompilation,
extensionRegistrars = (projectEnvironment as? VfsBasedProjectEnvironment)?.let { FirExtensionRegistrar.getInstances(it.project) }
?: emptyList(),
kotlinCompilerConfiguration.languageVersionSettings,
lookupTracker = kotlinCompilerConfiguration.get(CommonConfigurationKeys.LOOKUP_TRACKER),
enumWhenTracker = kotlinCompilerConfiguration.get(CommonConfigurationKeys.ENUM_WHEN_TRACKER),
needRegisterJavaElementFinder = true,
registerExtraComponents = {},
) {
if (extendedAnalysisMode) {
registerExtendedCommonCheckers()
}
}
session.scriptDefinitionProviderService?.run { session.scriptDefinitionProviderService?.run {
definitionProvider = ScriptDefinitionProvider.getInstance(context.environment.project) definitionProvider = ScriptDefinitionProvider.getInstance(context.environment.project)
@@ -407,7 +378,7 @@ private fun doCompileWithK2(
// checkers // checkers
session.runCheckers(scopeSession, fir, diagnosticsReporter) session.runCheckers(scopeSession, fir, diagnosticsReporter)
val analysisResults = FirResult(ModuleCompilerAnalyzedOutput(session, scopeSession, fir), null) val analysisResults = FirResult(listOf(ModuleCompilerAnalyzedOutput(session, scopeSession, fir)))
if (diagnosticsReporter.hasErrors) { if (diagnosticsReporter.hasErrors) {
diagnosticsReporter.reportToMessageCollector(messageCollector, renderDiagnosticName) diagnosticsReporter.reportToMessageCollector(messageCollector, renderDiagnosticName)