diff --git a/analysis/analysis-test-framework/tests/org/jetbrains/kotlin/analysis/test/framework/project/structure/KtSourceModuleByCompilerConfiguration.kt b/analysis/analysis-test-framework/tests/org/jetbrains/kotlin/analysis/test/framework/project/structure/KtSourceModuleByCompilerConfiguration.kt index 23c0edcb0ae..4bff1afcc75 100644 --- a/analysis/analysis-test-framework/tests/org/jetbrains/kotlin/analysis/test/framework/project/structure/KtSourceModuleByCompilerConfiguration.kt +++ b/analysis/analysis-test-framework/tests/org/jetbrains/kotlin/analysis/test/framework/project/structure/KtSourceModuleByCompilerConfiguration.kt @@ -21,7 +21,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices -import org.jetbrains.kotlin.test.frontend.fir.getAnalyzerServices +import org.jetbrains.kotlin.test.getAnalyzerServices import org.jetbrains.kotlin.test.model.TestModule import org.jetbrains.kotlin.test.services.TestServices import org.jetbrains.kotlin.test.services.compilerConfigurationProvider diff --git a/analysis/analysis-test-framework/tests/org/jetbrains/kotlin/analysis/test/framework/project/structure/KtSourceModuleImpl.kt b/analysis/analysis-test-framework/tests/org/jetbrains/kotlin/analysis/test/framework/project/structure/KtSourceModuleImpl.kt index a4437623290..466d592a1ec 100644 --- a/analysis/analysis-test-framework/tests/org/jetbrains/kotlin/analysis/test/framework/project/structure/KtSourceModuleImpl.kt +++ b/analysis/analysis-test-framework/tests/org/jetbrains/kotlin/analysis/test/framework/project/structure/KtSourceModuleImpl.kt @@ -11,7 +11,7 @@ import org.jetbrains.kotlin.analysis.project.structure.* import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices -import org.jetbrains.kotlin.test.frontend.fir.getAnalyzerServices +import org.jetbrains.kotlin.test.getAnalyzerServices import java.nio.file.Path interface KtModuleWithModifiableDependencies { diff --git a/analysis/analysis-test-framework/tests/org/jetbrains/kotlin/analysis/test/framework/services/AnalysisApiEnvironmentManager.kt b/analysis/analysis-test-framework/tests/org/jetbrains/kotlin/analysis/test/framework/services/AnalysisApiEnvironmentManager.kt index 499f60fcd35..792be499db2 100644 --- a/analysis/analysis-test-framework/tests/org/jetbrains/kotlin/analysis/test/framework/services/AnalysisApiEnvironmentManager.kt +++ b/analysis/analysis-test-framework/tests/org/jetbrains/kotlin/analysis/test/framework/services/AnalysisApiEnvironmentManager.kt @@ -16,7 +16,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreApplicationEnvironment import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreProjectEnvironment import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.config.languageVersionSettings -import org.jetbrains.kotlin.test.frontend.fir.getAnalyzerServices +import org.jetbrains.kotlin.test.getAnalyzerServices import org.jetbrains.kotlin.test.services.* abstract class AnalysisApiEnvironmentManager : TestService { diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/AbstractCompilerBasedTestForFir.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/AbstractCompilerBasedTestForFir.kt index e5ff7772cab..b9c6b0c9f1e 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/AbstractCompilerBasedTestForFir.kt +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/AbstractCompilerBasedTestForFir.kt @@ -9,11 +9,13 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.compiler.based import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile import org.jetbrains.kotlin.analysis.low.level.api.fir.createFirResolveSessionForNoCaching +import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.FirLowLevelCompilerBasedTestConfigurator import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirLazyTransformer import org.jetbrains.kotlin.analysis.test.framework.AbstractCompilerBasedTest import org.jetbrains.kotlin.analysis.test.framework.base.registerAnalysisApiBaseTestServices import org.jetbrains.kotlin.analysis.test.framework.project.structure.KtSourceModuleByCompilerConfiguration import org.jetbrains.kotlin.analysis.test.framework.project.structure.ktModuleProvider +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.platform.jvm.JvmPlatforms import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.test.TestInfrastructureInternals @@ -23,15 +25,13 @@ import org.jetbrains.kotlin.test.builders.testConfiguration import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives import org.jetbrains.kotlin.test.directives.model.DirectivesContainer import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifact +import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifactImpl +import org.jetbrains.kotlin.test.frontend.fir.FirOutputPartForDependsOnModule import org.jetbrains.kotlin.test.model.DependencyKind import org.jetbrains.kotlin.test.model.FrontendFacade import org.jetbrains.kotlin.test.model.FrontendKinds import org.jetbrains.kotlin.test.model.TestModule -import org.jetbrains.kotlin.test.services.TestServices -import org.jetbrains.kotlin.test.services.compilerConfigurationProvider -import org.jetbrains.kotlin.test.services.isKtFile import org.jetbrains.kotlin.test.services.* -import org.jetbrains.kotlin.analysis.low.level.api.fir.test.base.FirLowLevelCompilerBasedTestConfigurator abstract class AbstractCompilerBasedTestForFir : AbstractCompilerBasedTest() { @OptIn(TestInfrastructureInternals::class) @@ -58,11 +58,55 @@ abstract class AbstractCompilerBasedTestForFir : AbstractCompilerBasedTest() { inner class LowLevelFirFrontendFacade( testServices: TestServices ) : FrontendFacade(testServices, FrontendKinds.FIR) { + private val testModulesByName by lazy { testServices.moduleStructure.modules.associateBy { it.name } } override val directiveContainers: List get() = listOf(FirDiagnosticsDirectives) + override fun shouldRunAnalysis(module: TestModule): Boolean { + if (!super.shouldRunAnalysis(module)) return false + + return if (module.languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects)) { + testServices.moduleStructure + .modules.none { testModule -> testModule.dependsOnDependencies.any { testModulesByName[it.moduleName] == module } } + } else { + true + } + } + override fun analyze(module: TestModule): FirOutputArtifact { + val isMppSupported = module.languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects) + + val sortedModules = if (isMppSupported) sortDependsOnTopologically(module) else listOf(module) + + val firOutputPartForDependsOnModules = mutableListOf() + for (testModule in sortedModules) { + firOutputPartForDependsOnModules.add(analyzeDependsOnModule(testModule)) + } + + return FirOutputArtifactImpl(firOutputPartForDependsOnModules) + } + + private fun sortDependsOnTopologically(module: TestModule): List { + val sortedModules = mutableListOf() + val visitedModules = mutableSetOf() + val modulesQueue = ArrayDeque() + modulesQueue.add(module) + + while (modulesQueue.isNotEmpty()) { + val currentModule = modulesQueue.removeFirst() + if (!visitedModules.add(currentModule)) continue + sortedModules.add(currentModule) + + for (dependency in currentModule.dependsOnDependencies) { + modulesQueue.add(testServices.dependencyProvider.getTestModule(dependency.moduleName)) + } + } + + return sortedModules.reversed() + } + + private fun analyzeDependsOnModule(module: TestModule): FirOutputPartForDependsOnModule { val moduleInfoProvider = testServices.ktModuleProvider val ktModule = moduleInfoProvider.getModule(module.name) as KtSourceModuleByCompilerConfiguration @@ -81,7 +125,12 @@ abstract class AbstractCompilerBasedTestForFir : AbstractCompilerBasedTest() { } else DiagnosticCheckerFilter.ONLY_COMMON_CHECKERS val analyzerFacade = LowLevelFirAnalyzerFacade(firResolveSession, allFirFiles.toMap(), diagnosticCheckerFilter) - return LowLevelFirOutputArtifact(firResolveSession.useSiteFirSession, analyzerFacade) + return FirOutputPartForDependsOnModule( + module, + firResolveSession.useSiteFirSession, + analyzerFacade, + analyzerFacade.allFirFiles + ) } } diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/LLDiagnosticParameterChecker.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/LLDiagnosticParameterChecker.kt index 2097dc11dbd..f144af39dde 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/LLDiagnosticParameterChecker.kt +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/LLDiagnosticParameterChecker.kt @@ -18,10 +18,12 @@ import org.jetbrains.kotlin.test.services.assertions internal class LLDiagnosticParameterChecker(testServices: TestServices) : FirAnalysisHandler(testServices) { override fun processModule(module: TestModule, info: FirOutputArtifact) { - val diagnostics = info.firAnalyzerFacade.runCheckers().values.flatten() + for (part in info.partsForDependsOnModules) { + val diagnostics = part.firAnalyzerFacade.runCheckers().values.flatten() - for (diagnostic in diagnostics) { - checkDiagnosticIsSuitableForFirIde(diagnostic as KtPsiDiagnostic) + for (diagnostic in diagnostics) { + checkDiagnosticIsSuitableForFirIde(diagnostic as KtPsiDiagnostic) + } } } diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/LowLevelFirAnalyzerFacade.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/LowLevelFirAnalyzerFacade.kt index a98c8ffaa05..296c6824711 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/LowLevelFirAnalyzerFacade.kt +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/LowLevelFirAnalyzerFacade.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.LLFirResolveSession import org.jetbrains.kotlin.analysis.low.level.api.fir.api.collectDiagnosticsForFile import org.jetbrains.kotlin.diagnostics.KtDiagnostic import org.jetbrains.kotlin.fir.AbstractFirAnalyzerFacade +import org.jetbrains.kotlin.fir.backend.Fir2IrComponents import org.jetbrains.kotlin.fir.backend.Fir2IrExtensions import org.jetbrains.kotlin.fir.backend.Fir2IrResult import org.jetbrains.kotlin.fir.declarations.FirFile @@ -36,7 +37,7 @@ class LowLevelFirAnalyzerFacade( } override fun runResolution(): List = shouldNotBeCalled() - override fun convertToIr(fir2IrExtensions: Fir2IrExtensions): Fir2IrResult = shouldNotBeCalled() + override fun convertToIr(fir2IrExtensions: Fir2IrExtensions, dependentComponents: List): Fir2IrResult = shouldNotBeCalled() } private fun shouldNotBeCalled(): Nothing = error("Should not be called for LL test") diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/LowLevelFirOutputArtifact.kt b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/LowLevelFirOutputArtifact.kt deleted file mode 100644 index 24f72f662d7..00000000000 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/compiler/based/LowLevelFirOutputArtifact.kt +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2010-2021 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.analysis.low.level.api.fir.compiler.based - -import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.declarations.FirFile -import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifact -import org.jetbrains.kotlin.test.model.TestFile - -class LowLevelFirOutputArtifact( - override val session: FirSession, - override val firAnalyzerFacade: LowLevelFirAnalyzerFacade, -) : FirOutputArtifact() { - override val allFirFiles: Map - get() = firAnalyzerFacade.allFirFiles -} diff --git a/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt b/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt index 9b301fc69ba..92949a54f20 100644 --- a/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt +++ b/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt @@ -43,9 +43,7 @@ import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory -import org.jetbrains.kotlin.fir.DependencyListForCliModule -import org.jetbrains.kotlin.fir.FirModuleDataImpl -import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.backend.Fir2IrConverter import org.jetbrains.kotlin.fir.backend.Fir2IrExtensions import org.jetbrains.kotlin.fir.backend.Fir2IrVisibilityConverter @@ -55,7 +53,6 @@ import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor 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.pipeline.buildFirFromKtFiles import org.jetbrains.kotlin.fir.pipeline.runCheckers import org.jetbrains.kotlin.fir.pipeline.runResolution @@ -509,7 +506,8 @@ class K2JsIrCompiler : CLICompiler() { val mainModule = MainModule.SourceFiles(environmentForJS.getSourceFiles()) - val dependencyList = DependencyListForCliModule.build(mainModuleName, JsPlatforms.defaultJsPlatform, JsPlatformAnalyzerServices) { + val binaryModuleData = BinaryModuleData.initialize(mainModuleName, JsPlatforms.defaultJsPlatform, JsPlatformAnalyzerServices) + val dependencyList = DependencyListForCliModule.build(binaryModuleData) { dependencies(libraries.map { Paths.get(it).toAbsolutePath() }) friendDependencies(friendLibraries.map { Paths.get(it).toAbsolutePath() }) // TODO: !!! dependencies module data? @@ -533,8 +531,8 @@ class K2JsIrCompiler : CLICompiler() { dependencyList.regularDependencies, dependencyList.dependsOnDependencies, dependencyList.friendsDependencies, - dependencyList.platform, - dependencyList.analyzerServices + JsPlatforms.defaultJsPlatform, + JsPlatformAnalyzerServices ) val session = FirJsSessionFactory.createJsModuleBasedSession( @@ -598,7 +596,8 @@ class K2JsIrCompiler : CLICompiler() { Fir2IrJvmSpecialAnnotationSymbolProvider(), // TODO: replace with appropriate (probably empty) implementation IrGenerationExtension.getInstances(environmentForJS.project), generateSignatures = false, - kotlinBuiltIns = builtInsModule ?: DefaultBuiltIns.Instance // TODO: consider passing externally + kotlinBuiltIns = builtInsModule ?: DefaultBuiltIns.Instance, // TODO: consider passing externally + dependentComponents = emptyList() ).also { (it.irModuleFragment.descriptor as? FirModuleDescriptor)?.let { it.allDependencyModules = librariesDescriptors } } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/FirKotlinToJvmBytecodeCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/FirKotlinToJvmBytecodeCompiler.kt index e46bf29282c..44cb59fe103 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/FirKotlinToJvmBytecodeCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/FirKotlinToJvmBytecodeCompiler.kt @@ -7,7 +7,6 @@ package org.jetbrains.kotlin.cli.jvm.compiler -import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.jvm.JvmGeneratorExtensions import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory @@ -26,24 +25,21 @@ import org.jetbrains.kotlin.cli.jvm.config.jvmModularRoots import org.jetbrains.kotlin.codegen.ClassBuilderFactories import org.jetbrains.kotlin.codegen.CodegenFactory import org.jetbrains.kotlin.codegen.state.GenerationState -import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar import org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar +import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory import org.jetbrains.kotlin.diagnostics.impl.BaseDiagnosticsCollector import org.jetbrains.kotlin.fir.* -import org.jetbrains.kotlin.fir.backend.Fir2IrResult -import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendClassResolver -import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendExtension -import org.jetbrains.kotlin.fir.backend.jvm.JvmFir2IrExtensions +import org.jetbrains.kotlin.fir.backend.* +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.FirSimpleFunction import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider import org.jetbrains.kotlin.fir.pipeline.* -import org.jetbrains.kotlin.fir.session.FirSessionFactoryHelper -import org.jetbrains.kotlin.fir.session.IncrementalCompilationContext +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.fir.types.arrayElementType @@ -52,18 +48,16 @@ import org.jetbrains.kotlin.fir.types.isArrayType import org.jetbrains.kotlin.fir.types.isString import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmIrMangler +import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackagePartProvider import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents import org.jetbrains.kotlin.modules.Module import org.jetbrains.kotlin.modules.TargetId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.platform.CommonPlatforms -import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.platform.jvm.JvmPlatforms import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus 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.multiplatform.isCommonSource import org.jetbrains.kotlin.utils.addToStdlib.runIf @@ -102,15 +96,8 @@ object FirKotlinToJvmBytecodeCompiler { ) return false } - if (projectConfiguration.languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects)) { - messageCollector.report( - CompilerMessageSeverity.ERROR, - "K2 compiler does not support multi-platform projects yet, so please remove -Xuse-k2 flag" - ) - return false - } - val outputs = ArrayList>(chunk.size) + val outputs = ArrayList>(chunk.size) val targetIds = projectConfiguration.get(JVMConfigurationKeys.MODULES)?.map(::TargetId) val incrementalComponents = projectConfiguration.get(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS) val isMultiModuleChunk = chunk.size > 1 @@ -140,14 +127,14 @@ object FirKotlinToJvmBytecodeCompiler { } val mainClassFqName: FqName? = runIf(chunk.size == 1 && projectConfiguration.get(JVMConfigurationKeys.OUTPUT_JAR) != null) { - findMainClass(outputs.single().first.fir) + findMainClass(outputs.single().first.platformOutput.fir) } return writeOutputsIfNeeded( project, projectConfiguration, chunk, - outputs.map(Pair::second), + outputs.map(Pair::second), mainClassFqName ) } @@ -160,7 +147,7 @@ object FirKotlinToJvmBytecodeCompiler { ?.mapTo(destination) { it::class.qualifiedName } } - private fun CompilationContext.compileModule(): Pair? { + private fun CompilationContext.compileModule(): Pair? { performanceManager?.notifyAnalysisStarted() ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() @@ -181,8 +168,11 @@ object FirKotlinToJvmBytecodeCompiler { performanceManager?.notifyIRTranslationStarted() val fir2IrExtensions = JvmFir2IrExtensions(moduleConfiguration, JvmIrDeserializerImpl(), JvmIrMangler) - val linkViaSignatures = moduleConfiguration.getBoolean(JVMConfigurationKeys.LINK_VIA_SIGNATURES) - val fir2IrResult = firResult.convertToIr(fir2IrExtensions, irGenerationExtensions, linkViaSignatures) + val fir2IrResult = firResult.convertToIrAndActualize( + fir2IrExtensions, + irGenerationExtensions, + linkViaSignatures = moduleConfiguration.getBoolean(JVMConfigurationKeys.LINK_VIA_SIGNATURES) + ) performanceManager?.notifyIRTranslationFinished() @@ -190,7 +180,7 @@ object FirKotlinToJvmBytecodeCompiler { allSources, fir2IrResult, fir2IrExtensions, - firResult.session, + firResult.platformOutput.session, diagnosticsReporter ) @@ -203,14 +193,12 @@ object FirKotlinToJvmBytecodeCompiler { return firResult to generationState } - private fun CompilationContext.runFrontend(ktFiles: List, diagnosticsReporter: BaseDiagnosticsCollector): ModuleCompilerAnalyzedOutput? { - @Suppress("NAME_SHADOWING") - var ktFiles = ktFiles + private fun CompilationContext.runFrontend(ktFiles: List, diagnosticsReporter: BaseDiagnosticsCollector): FirResult? { val syntaxErrors = ktFiles.fold(false) { errorsFound, ktFile -> AnalyzerWithCompilerReport.reportSyntaxErrors(ktFile, messageCollector).isHasErrors or errorsFound } - var sourceScope = (projectEnvironment as VfsBasedProjectEnvironment).getSearchScopeByPsiFiles(ktFiles) + + val sourceScope = (projectEnvironment as VfsBasedProjectEnvironment).getSearchScopeByPsiFiles(ktFiles) + projectEnvironment.getSearchScopeForProjectJavaSources() var librariesScope = projectEnvironment.getSearchScopeForProjectLibraries() @@ -223,85 +211,132 @@ object FirKotlinToJvmBytecodeCompiler { val languageVersionSettings = moduleConfiguration.languageVersionSettings - val commonKtFiles = ktFiles.filter { it.isCommonSource == true } + val isMppEnabled = languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects) val sessionProvider = FirProjectSessionProvider() - fun createSession( - name: String, - platform: TargetPlatform, - analyzerServices: PlatformDependentAnalyzerServices, - sourceScope: AbstractProjectFileSearchScope, - needRegisterJavaElementFinder: Boolean, - dependenciesConfigurator: DependencyListForCliModule.Builder.() -> Unit = {} - ): FirSession { - return FirSessionFactoryHelper.createSessionWithDependencies( - Name.identifier(name), - platform, - analyzerServices, - externalSessionProvider = sessionProvider, - projectEnvironment, - languageVersionSettings, - sourceScope, - librariesScope, - lookupTracker = moduleConfiguration.get(CommonConfigurationKeys.LOOKUP_TRACKER), - enumWhenTracker = moduleConfiguration.get(CommonConfigurationKeys.ENUM_WHEN_TRACKER), - providerAndScopeForIncrementalCompilation, - firExtensionRegistrars, - needRegisterJavaElementFinder, - dependenciesConfigurator = { - dependencies(moduleConfiguration.jvmClasspathRoots.map { it.toPath() }) - dependencies(moduleConfiguration.jvmModularRoots.map { it.toPath() }) - friendDependencies(moduleConfiguration[JVMConfigurationKeys.FRIEND_PATHS] ?: emptyList()) - dependenciesConfigurator() - } - ) { - if (extendedAnalysisMode) { - registerExtendedCommonCheckers() - } - } - } + val moduleName = module.getModuleName() + val libraryList = createLibraryListAndSession(moduleName, sessionProvider, librariesScope, languageVersionSettings) - val commonSession = runIf( - languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects) && commonKtFiles.isNotEmpty() - ) { - val commonSourcesScope = projectEnvironment.getSearchScopeByPsiFiles(commonKtFiles) - sourceScope -= commonSourcesScope - ktFiles = ktFiles.filterNot { it.isCommonSource == true } - createSession( - "${module.getModuleName()}-common", - CommonPlatforms.defaultCommonPlatform, - CommonPlatformAnalyzerServices, - commonSourcesScope, - needRegisterJavaElementFinder = false + val commonModuleData = runIf(isMppEnabled) { + FirModuleDataImpl( + Name.identifier("${module.getModuleName()}-common"), + libraryList.regularDependencies, + listOf(), + libraryList.friendsDependencies, + JvmPlatforms.unspecifiedJvmPlatform, + JvmPlatformAnalyzerServices ) } - - val session = createSession( - module.getModuleName(), + val platformModuleData = FirModuleDataImpl( + Name.identifier(module.getModuleName()), + libraryList.regularDependencies, + listOfNotNull(commonModuleData), + libraryList.friendsDependencies, JvmPlatforms.unspecifiedJvmPlatform, - JvmPlatformAnalyzerServices, - sourceScope, - needRegisterJavaElementFinder = true - ) { - if (commonSession != null) { - sourceDependsOnDependencies(listOf(commonSession.moduleData)) + 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() + val platformKtFiles = mutableListOf() + 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.createLibraryListAndSession( + moduleName: String, + sessionProvider: FirProjectSessionProvider, + librariesScope: AbstractProjectFileSearchScope, + languageVersionSettings: LanguageVersionSettings + ): DependencyListForCliModule { + val binaryModuleData = BinaryModuleData.initialize( + Name.identifier(moduleName), + JvmPlatforms.unspecifiedJvmPlatform, + JvmPlatformAnalyzerServices + ) + val libraryList = DependencyListForCliModule.build(binaryModuleData) { + dependencies(moduleConfiguration.jvmClasspathRoots.map { it.toPath() }) + dependencies(moduleConfiguration.jvmModularRoots.map { it.toPath() }) + friendDependencies(moduleConfiguration[JVMConfigurationKeys.FRIEND_PATHS] ?: emptyList()) friendDependencies(module.getFriendPaths()) } + FirJvmSessionFactory.createLibrarySession( + Name.identifier(moduleName), + sessionProvider, + libraryList.moduleDataProvider, + projectEnvironment, + librariesScope, + projectEnvironment.getPackagePartProvider(librariesScope), + languageVersionSettings, + registerExtraComponents = {}, + ) + return libraryList + } - val commonRawFir = commonSession?.buildFirFromKtFiles(commonKtFiles) + private fun buildResolveAndCheckFir( + session: FirSession, + ktFiles: List, + diagnosticsReporter: BaseDiagnosticsCollector + ): ModuleCompilerAnalyzedOutput { val rawFir = session.buildFirFromKtFiles(ktFiles) - - commonSession?.apply { - val (commonScopeSession, commonFir) = runResolution(commonRawFir!!) - runCheckers(commonScopeSession, commonFir, diagnosticsReporter) - } - val (scopeSession, fir) = session.runResolution(rawFir) session.runCheckers(scopeSession, fir, diagnosticsReporter) - - return if (syntaxErrors || diagnosticsReporter.hasErrors) null else ModuleCompilerAnalyzedOutput(session, scopeSession, fir) + return ModuleCompilerAnalyzedOutput(session, scopeSession, fir) } private fun CompilationContext.createComponentsForIncrementalCompilation( diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/pipeline/compilerPipeline.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/pipeline/compilerPipeline.kt index bf0fd7054d2..dc40bee41c8 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/pipeline/compilerPipeline.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/pipeline/compilerPipeline.kt @@ -19,7 +19,6 @@ import com.intellij.psi.search.GlobalSearchScope import com.intellij.util.io.URLUtil import org.jetbrains.kotlin.KtSourceFile import org.jetbrains.kotlin.KtVirtualFileSourceFile -import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory import org.jetbrains.kotlin.backend.jvm.JvmIrDeserializerImpl @@ -44,7 +43,9 @@ import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory +import org.jetbrains.kotlin.fir.BinaryModuleData import org.jetbrains.kotlin.fir.DependencyListForCliModule +import org.jetbrains.kotlin.fir.FirModuleDataImpl import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendClassResolver import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendExtension @@ -52,10 +53,10 @@ 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.java.FirProjectSessionProvider -import org.jetbrains.kotlin.fir.moduleData import org.jetbrains.kotlin.fir.pipeline.* import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider -import org.jetbrains.kotlin.fir.session.FirSessionFactoryHelper +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.environment.AbstractProjectEnvironment import org.jetbrains.kotlin.fir.session.environment.AbstractProjectFileSearchScope @@ -71,16 +72,14 @@ import org.jetbrains.kotlin.modules.TargetId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.platform.CommonPlatforms -import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.platform.jvm.JvmPlatforms import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus import org.jetbrains.kotlin.resolve.ModuleAnnotationsResolver -import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices 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.util.LinkedHashSet +import kotlin.reflect.KFunction2 private const val kotlinFileExtensionWithDot = ".${KotlinFileType.EXTENSION}" private const val javaFileExtensionWithDot = ".${JavaFileType.DEFAULT_EXTENSION}" @@ -105,14 +104,6 @@ fun compileModulesUsingFrontendIrAndLightTree( "ATTENTION!\n This build uses experimental K2 compiler: \n -Xuse-k2" ) - if (compilerConfiguration.languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects)) { - messageCollector.report( - CompilerMessageSeverity.ERROR, - "K2 compiler does not support multi-platform projects yet, so please remove -Xuse-k2 flag" - ) - return false - } - val outputs = mutableListOf() var mainClassFqName: FqName? = null @@ -148,7 +139,7 @@ fun compileModulesUsingFrontendIrAndLightTree( // TODO: consider what to do if many modules has main classes if (mainClassFqName == null && moduleConfiguration.get(JVMConfigurationKeys.OUTPUT_JAR) != null) { - mainClassFqName = findMainClass(analysisResults.fir) + mainClassFqName = findMainClass(analysisResults.platformOutput.fir) } if (diagnosticsReporter.hasErrors) { @@ -225,7 +216,7 @@ fun collectSources( fun convertAnalyzedFirToIr( input: ModuleCompilerInput, - analysisResults: ModuleCompilerAnalyzedOutput, + analysisResults: FirResult, environment: ModuleCompilerEnvironment ): ModuleCompilerIrBackendInput { val extensions = JvmFir2IrExtensions(input.configuration, JvmIrDeserializerImpl(), JvmIrMangler) @@ -237,7 +228,7 @@ fun convertAnalyzedFirToIr( } ?: emptyList() val linkViaSignatures = input.configuration.getBoolean(JVMConfigurationKeys.LINK_VIA_SIGNATURES) val (irModuleFragment, components, pluginContext) = - analysisResults.convertToIr(extensions, irGenerationExtensions, linkViaSignatures) + analysisResults.convertToIrAndActualize(extensions, irGenerationExtensions, linkViaSignatures) return ModuleCompilerIrBackendInput( input.targetId, @@ -246,7 +237,7 @@ fun convertAnalyzedFirToIr( irModuleFragment, components.symbolTable, components, - analysisResults.session, + analysisResults.platformOutput.session, pluginContext ) } @@ -310,73 +301,158 @@ fun compileModuleToAnalyzedFir( incrementalExcludesScope: AbstractProjectFileSearchScope?, diagnosticsReporter: DiagnosticReporter, performanceManager: CommonCompilerPerformanceManager? -): ModuleCompilerAnalyzedOutput { - var sourcesScope = environment.projectEnvironment.getSearchScopeBySourceFiles(input.platformSources) - val sessionProvider = FirProjectSessionProvider() - val extendedAnalysisMode = input.configuration.getBoolean(CommonConfigurationKeys.USE_FIR_EXTENDED_CHECKERS) +): FirResult { + val languageVersionSettings = input.configuration.languageVersionSettings + val projectEnvironment = environment.projectEnvironment + val moduleConfiguration = input.configuration + val isMppEnabled = languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects) + val sourcesScope = environment.projectEnvironment.getSearchScopeBySourceFiles(input.platformSources) - val commonSession = runIf( - input.commonSources.isNotEmpty() && input.configuration.languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects) - ) { - val commonSourcesScope = environment.projectEnvironment.getSearchScopeBySourceFiles(input.commonSources) - sourcesScope -= commonSourcesScope - createSession( - "${input.targetId.name}-common", - input.commonPlatform, - input.configuration, - environment.projectEnvironment, - commonSourcesScope, - CommonPlatformAnalyzerServices, - sessionProvider, + 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() + val commonProviderAndScopeForIncrementalCompilation = runIf(isMppEnabled) { + createContextForIncrementalCompilation( + moduleConfiguration, + projectEnvironment, + commonSourcesScope!!, previousStepsSymbolProviders, - incrementalExcludesScope, - extendedAnalysisMode, - needRegisterJavaElementFinder = false + 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 moduleName = input.targetId.name + + val libraryList = createLibraryListAndSession(moduleName, input.configuration, projectEnvironment, librariesScope, 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 session = createSession( - input.targetId.name, - input.platform, - input.configuration, - environment.projectEnvironment, - sourcesScope, - JvmPlatformAnalyzerServices, - sessionProvider, - previousStepsSymbolProviders, - incrementalExcludesScope, - extendedAnalysisMode, - needRegisterJavaElementFinder = true - ) { - if (commonSession != null) { - sourceDependsOnDependencies(listOf(commonSession.moduleData)) + val extensionRegistrars = (projectEnvironment as? VfsBasedProjectEnvironment)?.let { FirExtensionRegistrar.getInstances(it.project) } + ?: 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() } - friendDependencies(input.configuration[JVMConfigurationKeys.FRIEND_PATHS] ?: emptyList()) - sourceFriendsDependencies(input.friendFirModules) } + val javaSourcesScope = projectEnvironment.getSearchScopeForProjectJavaSources() + + val commonSession = runIf(isMppEnabled) { + FirJvmSessionFactory.createModuleBasedSession( + commonModuleData!!, + sessionProvider, + javaSourcesScope, + projectEnvironment, + commonProviderAndScopeForIncrementalCompilation, + extensionRegistrars, + languageVersionSettings, + lookupTracker, + enumWhenTracker, + needRegisterJavaElementFinder = true, + registerExtraComponents = {}, + sessionConfigurator, + ) + } + val platformSession = FirJvmSessionFactory.createModuleBasedSession( + platformModuleData, + sessionProvider, + javaSourcesScope, + projectEnvironment, + platformProviderAndScopeForIncrementalCompilation, + extensionRegistrars, + languageVersionSettings, + lookupTracker, + enumWhenTracker, + needRegisterJavaElementFinder = true, + registerExtraComponents = {}, + sessionConfigurator + ) 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) - // raw fir - val commonRawFir = commonSession?.buildFirViaLightTree( - input.commonSources, - diagnosticsReporter, - countFilesAndLines + return FirResult(platformOutput, commonOutput) +} + +fun createLibraryListAndSession( + moduleName: String, + configuration: CompilerConfiguration, + projectEnvironment: AbstractProjectEnvironment, + librariesScope: AbstractProjectFileSearchScope, + sessionProvider: FirProjectSessionProvider +): DependencyListForCliModule { + val binaryModuleData = BinaryModuleData.initialize( + Name.identifier(moduleName), + JvmPlatforms.unspecifiedJvmPlatform, + JvmPlatformAnalyzerServices ) - val rawFir = - session.buildFirViaLightTree(input.platformSources, diagnosticsReporter, countFilesAndLines) - - // resolution - commonSession?.apply { - val (commonScopeSession, commonFir) = runResolution(commonRawFir!!) - // TODO: find out what to do with commonFir - runCheckers(commonScopeSession, commonFir, environment.diagnosticsReporter) + val libraryList = DependencyListForCliModule.build(binaryModuleData) { + dependencies(configuration.jvmClasspathRoots.map { it.toPath() }) + dependencies(configuration.jvmModularRoots.map { it.toPath() }) + friendDependencies(configuration[JVMConfigurationKeys.FRIEND_PATHS] ?: emptyList()) } + FirJvmSessionFactory.createLibrarySession( + Name.identifier(moduleName), + sessionProvider, + libraryList.moduleDataProvider, + projectEnvironment, + projectEnvironment.getSearchScopeForProjectLibraries(), + projectEnvironment.getPackagePartProvider(librariesScope), + configuration.languageVersionSettings, + registerExtraComponents = {}, + ) + return libraryList +} - val (scopeSession, fir) = session.runResolution(rawFir) - // checkers - session.runCheckers(scopeSession, fir, environment.diagnosticsReporter) - +private fun buildResolveAndCheckFir( + session: FirSession, + ktFiles: Collection, + diagnosticsReporter: DiagnosticReporter, + countFilesAndLines: KFunction2? +): ModuleCompilerAnalyzedOutput { + val firFiles = session.buildFirViaLightTree(ktFiles, diagnosticsReporter, countFilesAndLines) + val (scopeSession, fir) = session.runResolution(firFiles) + session.runCheckers(scopeSession, fir, diagnosticsReporter) return ModuleCompilerAnalyzedOutput(session, scopeSession, fir) } @@ -413,63 +489,7 @@ fun writeOutputs( return true } -fun createSession( - name: String, - platform: TargetPlatform, - moduleConfiguration: CompilerConfiguration, - projectEnvironment: AbstractProjectEnvironment, - sourceScope: AbstractProjectFileSearchScope, - analyzerServices: PlatformDependentAnalyzerServices, - sessionProvider: FirProjectSessionProvider?, - previousStepsSymbolProviders: List, - incrementalExcludesScope: AbstractProjectFileSearchScope?, - extendedAnalysisMode: Boolean, - needRegisterJavaElementFinder: Boolean, - dependenciesConfigurator: DependencyListForCliModule.Builder.() -> Unit = {}, -): FirSession { - var librariesScope = projectEnvironment.getSearchScopeForProjectLibraries() - - val providerAndScopeForIncrementalCompilation = - createContextForIncrementalCompilation( - moduleConfiguration, - projectEnvironment, - sourceScope, - previousStepsSymbolProviders, - incrementalExcludesScope - ) - ?.also { (_, _, precompiledBinariesFileScope) -> - precompiledBinariesFileScope?.let { librariesScope -= it } - } - - return FirSessionFactoryHelper.createSessionWithDependencies( - Name.identifier(name), - platform, - analyzerServices, - externalSessionProvider = sessionProvider, - projectEnvironment, - moduleConfiguration.languageVersionSettings, - projectEnvironment.getSearchScopeForProjectJavaSources(), - librariesScope, - lookupTracker = moduleConfiguration.get(CommonConfigurationKeys.LOOKUP_TRACKER), - enumWhenTracker = moduleConfiguration.get(CommonConfigurationKeys.ENUM_WHEN_TRACKER), - providerAndScopeForIncrementalCompilation, - extensionRegistrars = (projectEnvironment as? VfsBasedProjectEnvironment)?.let { FirExtensionRegistrar.getInstances(it.project) } - ?: emptyList(), - needRegisterJavaElementFinder = needRegisterJavaElementFinder, - dependenciesConfigurator = { - dependencies(moduleConfiguration.jvmClasspathRoots.map { it.toPath() }) - dependencies(moduleConfiguration.jvmModularRoots.map { it.toPath() }) - friendDependencies(moduleConfiguration[JVMConfigurationKeys.FRIEND_PATHS] ?: emptyList()) - dependenciesConfigurator() - } - ) { - if (extendedAnalysisMode) { - registerExtendedCommonCheckers() - } - } -} - -private fun createContextForIncrementalCompilation( +fun createContextForIncrementalCompilation( compilerConfiguration: CompilerConfiguration, projectEnvironment: AbstractProjectEnvironment, sourceScope: AbstractProjectFileSearchScope, diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/DependencyListForCliModule.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/DependencyListForCliModule.kt index 0c7091d1029..df5d5a59128 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/DependencyListForCliModule.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/DependencyListForCliModule.kt @@ -9,117 +9,66 @@ import org.jetbrains.kotlin.fir.deserialization.LibraryPathFilter import org.jetbrains.kotlin.fir.deserialization.ModuleDataProvider import org.jetbrains.kotlin.fir.deserialization.MultipleModuleDataProvider import org.jetbrains.kotlin.fir.deserialization.SingleModuleDataProvider -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.platform.TargetPlatform -import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices import java.nio.file.Path import java.nio.file.Paths class DependencyListForCliModule( - val platform: TargetPlatform, - val analyzerServices: PlatformDependentAnalyzerServices, val regularDependencies: List, val dependsOnDependencies: List, val friendsDependencies: List, val moduleDataProvider: ModuleDataProvider, ) { companion object { - fun createDependencyModuleData( - name: Name, - platform: TargetPlatform, - analyzerServices: PlatformDependentAnalyzerServices - ): FirModuleData { - return FirModuleDataImpl( - name, - dependencies = emptyList(), - dependsOnDependencies = emptyList(), - friendDependencies = emptyList(), - platform, - analyzerServices, - ) - } - - inline fun build( - mainModuleName: Name, - platform: TargetPlatform, - analyzerServices: PlatformDependentAnalyzerServices, - init: Builder.() -> Unit = {} - ): DependencyListForCliModule { - return Builder(mainModuleName, platform, analyzerServices).apply(init).build() + inline fun build(binaryModuleData: BinaryModuleData, init: Builder.() -> Unit = {}): DependencyListForCliModule { + return Builder(binaryModuleData).apply(init).build() } } - class Builder(val mainModuleName: Name, val platform: TargetPlatform, val analyzerServices: PlatformDependentAnalyzerServices) { - private fun createData(name: String): FirModuleData = createDependencyModuleData(Name.special(name), platform, analyzerServices) - - private val binaryRegularDependenciesModuleData: FirModuleData = createData("") - private val binaryDependsOnModuleData: FirModuleData = createData("() private val allFriendsDependencies = mutableListOf() private val allDependsOnDependencies = mutableListOf() private val filtersMap: Map> = listOf( - binaryDependsOnModuleData, - binaryFriendsModuleData, - binaryRegularDependenciesModuleData - ).map { it to mutableSetOf() }.toMap() + binaryModuleData.dependsOn, + binaryModuleData.friends, + binaryModuleData.regular + ).associateWith { mutableSetOf() } fun dependency(vararg path: Path) { - filtersMap.getValue(binaryRegularDependenciesModuleData) += path - } - - fun friendDependency(vararg path: Path) { - filtersMap.getValue(binaryFriendsModuleData) += path - } - - fun dependsOnDependency(vararg path: Path) { - filtersMap.getValue(binaryDependsOnModuleData) += path + filtersMap.getValue(binaryModuleData.regular) += path } fun dependency(vararg path: String) { - path.mapTo(filtersMap.getValue(binaryRegularDependenciesModuleData)) { Paths.get(it) } - } - - fun friendDependency(vararg path: String) { - path.mapTo(filtersMap.getValue(binaryFriendsModuleData)) { Paths.get(it) } - } - - fun dependsOnDependency(vararg path: String) { - path.mapTo(filtersMap.getValue(binaryDependsOnModuleData)) { Paths.get(it) } + path.mapTo(filtersMap.getValue(binaryModuleData.regular)) { Paths.get(it) } } @JvmName("dependenciesString") fun dependencies(paths: Collection) { - paths.mapTo(filtersMap.getValue(binaryRegularDependenciesModuleData)) { Paths.get(it) } + paths.mapTo(filtersMap.getValue(binaryModuleData.regular)) { Paths.get(it) } } @JvmName("friendDependenciesString") fun friendDependencies(paths: Collection) { - paths.mapTo(filtersMap.getValue(binaryFriendsModuleData)) { Paths.get(it) } + paths.mapTo(filtersMap.getValue(binaryModuleData.friends)) { Paths.get(it) } } @JvmName("dependsOnDependenciesString") fun dependsOnDependencies(paths: Collection) { - paths.mapTo(filtersMap.getValue(binaryDependsOnModuleData)) { Paths.get(it) } + paths.mapTo(filtersMap.getValue(binaryModuleData.dependsOn)) { Paths.get(it) } } fun dependencies(paths: Collection) { - filtersMap.getValue(binaryRegularDependenciesModuleData) += paths + filtersMap.getValue(binaryModuleData.regular) += paths } fun friendDependencies(paths: Collection) { - filtersMap.getValue(binaryFriendsModuleData) += paths + filtersMap.getValue(binaryModuleData.friends) += paths } fun dependsOnDependencies(paths: Collection) { - filtersMap.getValue(binaryDependsOnModuleData) += paths - } - - fun sourceDependencies(modules: Collection) { - allRegularDependencies += modules + filtersMap.getValue(binaryModuleData.dependsOn) += paths } fun sourceFriendsDependencies(modules: Collection) { @@ -136,29 +85,25 @@ class DependencyListForCliModule( .mapValues { LibraryPathFilter.LibraryList(it.value) } .toMutableMap() - allRegularDependencies += binaryRegularDependenciesModuleData + allRegularDependencies += binaryModuleData.regular if (pathFiltersMap.isEmpty()) { return DependencyListForCliModule( - platform, - analyzerServices, allRegularDependencies, dependsOnDependencies = allDependsOnDependencies, friendsDependencies = allFriendsDependencies, - SingleModuleDataProvider(binaryRegularDependenciesModuleData) + SingleModuleDataProvider(binaryModuleData.regular) ) } - if (binaryFriendsModuleData in pathFiltersMap) { - allFriendsDependencies += binaryFriendsModuleData + if (binaryModuleData.friends in pathFiltersMap) { + allFriendsDependencies += binaryModuleData.friends } - if (binaryDependsOnModuleData in pathFiltersMap) { - allDependsOnDependencies += binaryDependsOnModuleData + if (binaryModuleData.dependsOn in pathFiltersMap) { + allDependsOnDependencies += binaryModuleData.dependsOn } val moduleDataProvider = MultipleModuleDataProvider(pathFiltersMap) - pathFiltersMap.putIfAbsent(binaryRegularDependenciesModuleData, LibraryPathFilter.TakeAll) + pathFiltersMap.putIfAbsent(binaryModuleData.regular, LibraryPathFilter.TakeAll) return DependencyListForCliModule( - platform, - analyzerServices, allRegularDependencies, allDependsOnDependencies, allFriendsDependencies, diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/convertToIr.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/convertToIr.kt index ec0ec858952..04f99d1ab7c 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/convertToIr.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/pipeline/convertToIr.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.jvm.serialization.JvmIdSignatureDescriptor import org.jetbrains.kotlin.builtins.DefaultBuiltIns import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.backend.Fir2IrComponents import org.jetbrains.kotlin.fir.backend.Fir2IrConverter import org.jetbrains.kotlin.fir.backend.Fir2IrExtensions import org.jetbrains.kotlin.fir.backend.Fir2IrResult @@ -17,34 +18,65 @@ import org.jetbrains.kotlin.fir.backend.jvm.FirJvmKotlinMangler import org.jetbrains.kotlin.fir.backend.jvm.FirJvmVisibilityConverter import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.languageVersionSettings -import org.jetbrains.kotlin.fir.moduleData import org.jetbrains.kotlin.fir.resolve.ScopeSession -import org.jetbrains.kotlin.fir.resolve.providers.firProvider -import org.jetbrains.kotlin.fir.resolve.providers.impl.FirProviderImpl import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmDescriptorMangler import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmIrMangler import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl +data class FirResult( + val platformOutput: ModuleCompilerAnalyzedOutput, + val commonOutput: ModuleCompilerAnalyzedOutput? +) + data class ModuleCompilerAnalyzedOutput( val session: FirSession, val scopeSession: ScopeSession, val fir: List ) -fun ModuleCompilerAnalyzedOutput.convertToIr( +fun FirResult.convertToIrAndActualize( fir2IrExtensions: Fir2IrExtensions, irGeneratorExtensions: Collection, - linkViaSignatures: Boolean + linkViaSignatures: Boolean, ): Fir2IrResult { - val commonFirFiles = session.moduleData.dependsOnDependencies - .map { it.session } - .filter { it.kind == FirSession.Kind.Source } - .flatMap { (it.firProvider as FirProviderImpl).getAllFirFiles() } + val result: Fir2IrResult + if (commonOutput != null) { + val commonIrOutput = commonOutput.convertToIr( + fir2IrExtensions, + irGeneratorExtensions, + linkViaSignatures = true, + dependentComponents = emptyList() + ) + result = platformOutput.convertToIr( + fir2IrExtensions, + irGeneratorExtensions, + linkViaSignatures = true, + dependentComponents = listOf(commonIrOutput.components) + ) + // TODO: implement IR actualization + } else { + result = platformOutput.convertToIr( + fir2IrExtensions, + irGeneratorExtensions, + linkViaSignatures = linkViaSignatures, + dependentComponents = emptyList() + ) + } + + return result +} + +private fun ModuleCompilerAnalyzedOutput.convertToIr( + fir2IrExtensions: Fir2IrExtensions, + irGeneratorExtensions: Collection, + linkViaSignatures: Boolean, + dependentComponents: List +): Fir2IrResult { if (linkViaSignatures) { val signaturer = JvmIdSignatureDescriptor(mangler = JvmDescriptorMangler(mainDetector = null)) return Fir2IrConverter.createModuleFragmentWithSignaturesIfNeeded( - session, scopeSession, fir + commonFirFiles, + session, scopeSession, fir, session.languageVersionSettings, signaturer, fir2IrExtensions, FirJvmKotlinMangler(session), JvmIrMangler, IrFactoryImpl, FirJvmVisibilityConverter, @@ -55,7 +87,7 @@ fun ModuleCompilerAnalyzedOutput.convertToIr( ) } else { return Fir2IrConverter.createModuleFragmentWithoutSignatures( - session, scopeSession, fir + commonFirFiles, + session, scopeSession, fir, session.languageVersionSettings, fir2IrExtensions, FirJvmKotlinMangler(session), JvmIrMangler, IrFactoryImpl, FirJvmVisibilityConverter, diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirAbstractSessionFactory.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirAbstractSessionFactory.kt index 0d20b6b4939..bcd9d13cfc5 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirAbstractSessionFactory.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirAbstractSessionFactory.kt @@ -6,17 +6,13 @@ package org.jetbrains.kotlin.fir.session import org.jetbrains.kotlin.config.LanguageVersionSettings -import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl import org.jetbrains.kotlin.fir.* -import org.jetbrains.kotlin.fir.analysis.FirOverridesBackwardCompatibilityHelper import org.jetbrains.kotlin.fir.checkers.registerCommonCheckers -import org.jetbrains.kotlin.fir.checkers.registerJsCheckers import org.jetbrains.kotlin.fir.deserialization.ModuleDataProvider import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar import org.jetbrains.kotlin.fir.extensions.FirSwitchableExtensionDeclarationsSymbolProvider import org.jetbrains.kotlin.fir.java.FirCliSession import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider -import org.jetbrains.kotlin.fir.resolve.calls.ConeCallConflictResolverFactory import org.jetbrains.kotlin.fir.resolve.providers.FirDependenciesSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider @@ -25,7 +21,6 @@ import org.jetbrains.kotlin.fir.resolve.providers.impl.FirDependenciesSymbolProv import org.jetbrains.kotlin.fir.resolve.providers.impl.FirLibrarySessionProvider import org.jetbrains.kotlin.fir.resolve.providers.impl.FirProviderImpl import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider -import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper import org.jetbrains.kotlin.incremental.components.EnumWhenTracker import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.name.Name @@ -54,12 +49,12 @@ abstract class FirAbstractSessionFactory { val kotlinScopeProvider = createKotlinScopeProvider.invoke() register(FirKotlinScopeProvider::class, kotlinScopeProvider) - val builtinsModuleData = DependencyListForCliModule.createDependencyModuleData( + val builtinsModuleData = BinaryModuleData.createDependencyModuleData( Name.special(", sessionProvider: FirProjectSessionProvider, - dependencyListForCliModule: DependencyListForCliModule, + moduleDataProvider: ModuleDataProvider, languageVersionSettings: LanguageVersionSettings, registerExtraComponents: ((FirSession) -> Unit) = {}, ): FirSession { - val moduleDataProvider = dependencyListForCliModule.moduleDataProvider return createLibrarySession( mainModuleName, sessionProvider, diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirSessionFactoryHelper.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirSessionFactoryHelper.kt index ca7b17532f8..801ecd2b4e1 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirSessionFactoryHelper.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirSessionFactoryHelper.kt @@ -38,13 +38,14 @@ object FirSessionFactoryHelper { dependenciesConfigurator: DependencyListForCliModule.Builder.() -> Unit = {}, noinline sessionConfigurator: FirSessionConfigurator.() -> Unit = {}, ): FirSession { - val dependencyList = DependencyListForCliModule.build(moduleName, platform, analyzerServices, dependenciesConfigurator) + val binaryModuleData = BinaryModuleData.initialize(moduleName, platform, analyzerServices) + val dependencyList = DependencyListForCliModule.build(binaryModuleData, init = dependenciesConfigurator) val sessionProvider = externalSessionProvider ?: FirProjectSessionProvider() val packagePartProvider = projectEnvironment.getPackagePartProvider(librariesScope) FirJvmSessionFactory.createLibrarySession( moduleName, sessionProvider, - dependencyList, + dependencyList.moduleDataProvider, projectEnvironment, librariesScope, packagePartProvider, @@ -57,8 +58,8 @@ object FirSessionFactoryHelper { dependencyList.regularDependencies, dependencyList.dependsOnDependencies, dependencyList.friendsDependencies, - dependencyList.platform, - dependencyList.analyzerServices + platform, + analyzerServices ) return FirJvmSessionFactory.createModuleBasedSession( mainModuleData, diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalFirJvmCompilerRunner.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalFirJvmCompilerRunner.kt index 72d3e835ceb..e0d8b4898a2 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalFirJvmCompilerRunner.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/IncrementalFirJvmCompilerRunner.kt @@ -48,7 +48,9 @@ import org.jetbrains.kotlin.fir.backend.jvm.FirJvmVisibilityConverter 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.ModuleCompilerAnalyzedOutput +import org.jetbrains.kotlin.fir.pipeline.convertToIrAndActualize 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 @@ -203,7 +205,7 @@ class IncrementalFirJvmCompilerRunner( var incrementalExcludesScope: AbstractProjectFileSearchScope? = null - fun firIncrementalCycle(): ModuleCompilerAnalyzedOutput? { + fun firIncrementalCycle(): FirResult? { while (true) { val compilerInput = ModuleCompilerInput( @@ -229,7 +231,7 @@ class IncrementalFirJvmCompilerRunner( // TODO: consider what to do if many compilations find a main class if (mainClassFqName == null && configuration.get(JVMConfigurationKeys.OUTPUT_JAR) != null) { - mainClassFqName = findMainClass(analysisResults.fir) + mainClassFqName = findMainClass(analysisResults.platformOutput.fir) } // TODO: switch the whole IC to KtSourceFile instead of FIle @@ -273,19 +275,7 @@ class IncrementalFirJvmCompilerRunner( val extensions = JvmFir2IrExtensions(configuration, JvmIrDeserializerImpl(), JvmIrMangler) val irGenerationExtensions = (projectEnvironment as? VfsBasedProjectEnvironment)?.project?.let { IrGenerationExtension.getInstances(it) }.orEmpty() - val allCommonFirFiles = cycleResult.session.moduleData.dependsOnDependencies - .map { it.session } - .filter { it.kind == FirSession.Kind.Source } - .flatMap { (it.firProvider as FirProviderImpl).getAllFirFiles() } - - val (irModuleFragment, components, pluginContext) = Fir2IrConverter.createModuleFragmentWithoutSignatures( - cycleResult.session, cycleResult.scopeSession, cycleResult.fir + allCommonFirFiles, - cycleResult.session.languageVersionSettings, extensions, - FirJvmKotlinMangler(cycleResult.session), JvmIrMangler, IrFactoryImpl, FirJvmVisibilityConverter, - Fir2IrJvmSpecialAnnotationSymbolProvider(), - irGenerationExtensions, - kotlinBuiltIns = DefaultBuiltIns.Instance // TODO: consider passing externally - ) + val platformIrOutput = cycleResult.convertToIrAndActualize(extensions, irGenerationExtensions, linkViaSignatures = false) performanceManager?.notifyIRTranslationFinished() @@ -293,11 +283,11 @@ class IncrementalFirJvmCompilerRunner( targetId, configuration, extensions, - irModuleFragment, - components.symbolTable, - components, - cycleResult.session, - pluginContext + platformIrOutput.irModuleFragment, + platformIrOutput.components.symbolTable, + platformIrOutput.components, + cycleResult.platformOutput.session, + platformIrOutput.pluginContext ) val codegenOutput = generateCodeFromIr(irInput, compilerEnvironment, performanceManager) diff --git a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/incrementalFirCacheUtils.kt b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/incrementalFirCacheUtils.kt index 6863cfa8494..5096871e96c 100644 --- a/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/incrementalFirCacheUtils.kt +++ b/compiler/incremental-compilation-impl/src/org/jetbrains/kotlin/incremental/incrementalFirCacheUtils.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.backend.FirMetadataSource import org.jetbrains.kotlin.fir.backend.jvm.makeLocalFirMetadataSerializerForMetadataSource import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.utils.classId +import org.jetbrains.kotlin.fir.pipeline.FirResult import org.jetbrains.kotlin.fir.pipeline.ModuleCompilerAnalyzedOutput import org.jetbrains.kotlin.fir.scopes.jvm.computeJvmDescriptor import org.jetbrains.kotlin.fir.visitors.FirVisitor @@ -26,7 +27,7 @@ import org.jetbrains.org.objectweb.asm.commons.Method import java.io.File internal fun collectNewDirtySources( - analysisResults: ModuleCompilerAnalyzedOutput, + analysisResults: FirResult, targetId: TargetId, configuration: CompilerConfiguration, caches: IncrementalJvmCachesManager, @@ -35,96 +36,101 @@ internal fun collectNewDirtySources( ): LinkedHashSet { val changesCollector = ChangesCollector() val globalSerializationBindings = JvmSerializationBindings() - analysisResults.fir.forEach { - it.accept(object : FirVisitor>() { - inline fun withMetadataSerializer( - metadata: FirMetadataSource, - data: MutableList, - body: (MetadataSerializer) -> Unit - ) { - val serializer = makeLocalFirMetadataSerializerForMetadataSource( - metadata, - analysisResults.session, - analysisResults.scopeSession, - globalSerializationBindings, - data.lastOrNull(), - targetId, - configuration - ) - data.push(serializer) - body(serializer) - data.pop() - } - - override fun visitElement(element: FirElement, data: MutableList) { - element.acceptChildren(this, data) - } - - override fun visitRegularClass(regularClass: FirRegularClass, data: MutableList) { - visitClass(regularClass, data) - } - - override fun visitAnonymousObject(anonymousObject: FirAnonymousObject, data: MutableList) { - visitClass(anonymousObject, data) - } - - override fun visitFile(file: FirFile, data: MutableList) { - val metadata = FirMetadataSource.File(listOf(file)) - withMetadataSerializer(metadata, data) { - file.acceptChildren(this, data) - // TODO: compare package fragments? - } - } - - override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: MutableList) { - data.firstOrNull()?.let { serializer -> - super.visitFunction(simpleFunction, data) - serializer.bindMethodMetadata( - FirMetadataSource.Function(simpleFunction), - Method(simpleFunction.name.asString(), simpleFunction.computeJvmDescriptor()) + fun visitFirFiles(analyzedOutput: ModuleCompilerAnalyzedOutput) { + analyzedOutput.fir.forEach { + it.accept(object : FirVisitor>() { + inline fun withMetadataSerializer( + metadata: FirMetadataSource, + data: MutableList, + body: (MetadataSerializer) -> Unit + ) { + val serializer = makeLocalFirMetadataSerializerForMetadataSource( + metadata, + analyzedOutput.session, + analyzedOutput.scopeSession, + globalSerializationBindings, + data.lastOrNull(), + targetId, + configuration ) + data.push(serializer) + body(serializer) + data.pop() } - } - override fun visitConstructor(constructor: FirConstructor, data: MutableList) { - super.visitConstructor(constructor, data) - data.first().bindMethodMetadata( - FirMetadataSource.Function(constructor), - Method(SpecialNames.INIT.asString(), constructor.computeJvmDescriptor("")) - ) - } + override fun visitElement(element: FirElement, data: MutableList) { + element.acceptChildren(this, data) + } - override fun visitProperty(property: FirProperty, data: MutableList) { - property.acceptChildren(this, data) -// data.firstOrNull()?.let { -// property.acceptChildren(this, data) -// it.bindPropertyMetadata( -// FirMetadataSource.Property(property), -// Method(property.name.asString(), ""),//property.computeJvmDescriptor()) -// IrDeclarationOrigin.DEFINED -// ) -// } - } + override fun visitRegularClass(regularClass: FirRegularClass, data: MutableList) { + visitClass(regularClass, data) + } - override fun visitClass(klass: FirClass, data: MutableList) { - val metadata = FirMetadataSource.Class(klass) - withMetadataSerializer(metadata, data) { serializer -> - klass.acceptChildren(this, data) - serializer.serialize(metadata)?.let { (classProto, nameTable) -> - caches.platformCache.saveFrontendClassToCache( - klass.classId, - classProto as ProtoBuf.Class, - nameTable, - null, // TODO: !! - changesCollector + override fun visitAnonymousObject(anonymousObject: FirAnonymousObject, data: MutableList) { + visitClass(anonymousObject, data) + } + + override fun visitFile(file: FirFile, data: MutableList) { + val metadata = FirMetadataSource.File(listOf(file)) + withMetadataSerializer(metadata, data) { + file.acceptChildren(this, data) + // TODO: compare package fragments? + } + } + + override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: MutableList) { + data.firstOrNull()?.let { serializer -> + super.visitFunction(simpleFunction, data) + serializer.bindMethodMetadata( + FirMetadataSource.Function(simpleFunction), + Method(simpleFunction.name.asString(), simpleFunction.computeJvmDescriptor()) ) } } - } - }, mutableListOf()) + + override fun visitConstructor(constructor: FirConstructor, data: MutableList) { + super.visitConstructor(constructor, data) + data.first().bindMethodMetadata( + FirMetadataSource.Function(constructor), + Method(SpecialNames.INIT.asString(), constructor.computeJvmDescriptor("")) + ) + } + + override fun visitProperty(property: FirProperty, data: MutableList) { + property.acceptChildren(this, data) + // data.firstOrNull()?.let { + // property.acceptChildren(this, data) + // it.bindPropertyMetadata( + // FirMetadataSource.Property(property), + // Method(property.name.asString(), ""),//property.computeJvmDescriptor()) + // IrDeclarationOrigin.DEFINED + // ) + // } + } + + override fun visitClass(klass: FirClass, data: MutableList) { + val metadata = FirMetadataSource.Class(klass) + withMetadataSerializer(metadata, data) { serializer -> + klass.acceptChildren(this, data) + serializer.serialize(metadata)?.let { (classProto, nameTable) -> + caches.platformCache.saveFrontendClassToCache( + klass.classId, + classProto as ProtoBuf.Class, + nameTable, + null, // TODO: !! + changesCollector + ) + } + } + } + }, mutableListOf()) + } } + analysisResults.commonOutput?.let { visitFirFiles(it) } + visitFirFiles(analysisResults.platformOutput) + val (dirtyLookupSymbols, dirtyClassFqNames, forceRecompile) = changesCollector.getDirtyData(listOf(caches.platformCache), reporter) val forceToRecompileFiles = mapClassesFqNamesToFiles(listOf(caches.platformCache), forceRecompile, reporter) diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/nestedClasses.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/nestedClasses.fir.kt index 79d7baefc84..700ff3878f4 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/nestedClasses.fir.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/nestedClasses.fir.kt @@ -3,9 +3,9 @@ // FILE: common.kt import kotlin.reflect.KProperty -fun lazy(initializer: () -> T): Lazy = TODO() +fun lazy(initializer: () -> T): Lazy = TODO() interface Lazy { - operator fun getValue(thisRef: Any?, property: KProperty<*>): T = TODO() + operator fun getValue(thisRef: Any?, property: KProperty<*>): T = TODO() } expect class OuterClass { diff --git a/compiler/testData/diagnostics/tests/multiplatform/headerClass/superClass.fir.kt b/compiler/testData/diagnostics/tests/multiplatform/headerClass/superClass.fir.kt index bd6634ae7e5..3e1c7edda7f 100644 --- a/compiler/testData/diagnostics/tests/multiplatform/headerClass/superClass.fir.kt +++ b/compiler/testData/diagnostics/tests/multiplatform/headerClass/superClass.fir.kt @@ -7,7 +7,7 @@ interface J expect class Foo : I, C, J -expect class Bar : C() +expect class Bar : C() // MODULE: m2-jvm()()(m1-common) // FILE: jvm.kt diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/TestSetupUtils.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/TestSetupUtils.kt index 940cd990d26..d0c7e9d1b79 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/TestSetupUtils.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/TestSetupUtils.kt @@ -5,6 +5,16 @@ package org.jetbrains.kotlin.test +import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices +import org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices +import org.jetbrains.kotlin.platform.TargetPlatform +import org.jetbrains.kotlin.platform.isCommon +import org.jetbrains.kotlin.platform.isJs +import org.jetbrains.kotlin.platform.jvm.isJvm +import org.jetbrains.kotlin.platform.konan.isNative +import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices +import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices +import org.jetbrains.kotlin.resolve.konan.platform.NativePlatformAnalyzerServices import java.io.File /** @@ -22,3 +32,13 @@ private fun computeHomeDirectory(): String { val userDir = System.getProperty("user.dir") return File(userDir ?: ".").canonicalPath } + +fun TargetPlatform.getAnalyzerServices(): PlatformDependentAnalyzerServices { + return when { + isJvm() -> JvmPlatformAnalyzerServices + isJs() -> JsPlatformAnalyzerServices + isNative() -> NativePlatformAnalyzerServices + isCommon() -> CommonPlatformAnalyzerServices + else -> error("Unknown target platform: $this") + } +} \ No newline at end of file diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/JvmBackendDiagnosticsHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/JvmBackendDiagnosticsHandler.kt index 789fc3651b7..728eb56f730 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/JvmBackendDiagnosticsHandler.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/JvmBackendDiagnosticsHandler.kt @@ -41,7 +41,7 @@ class JvmBackendDiagnosticsHandler(testServices: TestServices) : JvmBinaryArtifa private fun getKtFiles(module: TestModule): Map { return when (module.frontendKind) { FrontendKinds.ClassicFrontend -> testServices.dependencyProvider.getArtifact(module, FrontendKinds.ClassicFrontend).ktFiles - FrontendKinds.FIR -> testServices.dependencyProvider.getArtifact(module, FrontendKinds.FIR).firFiles.entries + FrontendKinds.FIR -> testServices.dependencyProvider.getArtifact(module, FrontendKinds.FIR).mainFirFiles.entries .associate { it.key to (it.value.psi as KtFile) } else -> testServices.assertions.fail { "Unknown frontend kind ${module.frontendKind}" } } diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/NoFirCompilationErrorsHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/NoFirCompilationErrorsHandler.kt index 98f0f50278f..7a06d43c963 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/NoFirCompilationErrorsHandler.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/handlers/NoFirCompilationErrorsHandler.kt @@ -22,25 +22,29 @@ class NoFirCompilationErrorsHandler(testServices: TestServices) : FirAnalysisHan get() = listOf(CodegenTestDirectives) override fun processModule(module: TestModule, info: FirOutputArtifact) { - var hasError = false - val ignoreErrors = IGNORE_FIR_DIAGNOSTICS in module.directives - for ((firFile, diagnostics) in info.firAnalyzerFacade.runCheckers()) { - for (diagnostic in diagnostics) { - if (diagnostic.severity == Severity.ERROR) { - hasError = true - if (!ignoreErrors) { - val diagnosticText = RootDiagnosticRendererFactory(diagnostic).render(diagnostic) - val range = diagnostic.textRanges.first() - val locationText = firFile.source?.psi?.containingFile?.let { psiFile -> - PsiDiagnosticUtils.atLocation(psiFile, range) - } ?: "${firFile.name}:$range" - throw IllegalStateException("${diagnostic.factory.name}: $diagnosticText at $locationText") + for (part in info.partsForDependsOnModules) { + var hasError = false + + val ignoreErrors = IGNORE_FIR_DIAGNOSTICS in part.module.directives + for ((firFile, diagnostics) in part.firAnalyzerFacade.runCheckers()) { + for (diagnostic in diagnostics) { + if (diagnostic.severity == Severity.ERROR) { + hasError = true + if (!ignoreErrors) { + val diagnosticText = RootDiagnosticRendererFactory(diagnostic).render(diagnostic) + val range = diagnostic.textRanges.first() + val locationText = firFile.source?.psi?.containingFile?.let { psiFile -> + PsiDiagnosticUtils.atLocation(psiFile, range) + } ?: "${firFile.name}:$range" + throw IllegalStateException("${diagnostic.factory.name}: $diagnosticText at $locationText") + } } } } - } - if (!hasError && ignoreErrors) { - assertions.fail { "Test contains $IGNORE_FIR_DIAGNOSTICS directive but no errors was reported. Please remove directive" } + + if (!hasError && ignoreErrors) { + assertions.fail { "Test contains $IGNORE_FIR_DIAGNOSTICS directive but no errors was reported. Please remove directive" } + } } } diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/ir/IrBackendInput.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/ir/IrBackendInput.kt index 79ae4a24cc9..e9728a02380 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/ir/IrBackendInput.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/ir/IrBackendInput.kt @@ -14,7 +14,6 @@ import org.jetbrains.kotlin.ir.backend.js.KotlinFileSerializedData import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.metadata.ProtoBuf -import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.test.model.BackendKinds import org.jetbrains.kotlin.test.model.ResultingArtifact @@ -43,6 +42,7 @@ sealed class IrBackendInput : ResultingArtifact.BackendInput() { data class JvmIrBackendInput( val state: GenerationState, val codegenFactory: JvmIrCodegenFactory, + val dependentInputs: List, val backendInput: JvmIrCodegenFactory.JvmIrBackendInput, val sourceFiles: List ) : IrBackendInput() { diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/ir/JvmIrBackendFacade.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/ir/JvmIrBackendFacade.kt index a81e79e5334..e4413cd8f91 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/ir/JvmIrBackendFacade.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/backend/ir/JvmIrBackendFacade.kt @@ -37,7 +37,7 @@ class JvmIrBackendFacade( } val state = inputArtifact.state try { - inputArtifact.codegenFactory.generateModule(state, inputArtifact.backendInput) + inputArtifact.codegenFactory.generateModule(state, inputArtifact.backendInput.last()) } catch (e: BackendException) { if (CodegenTestDirectives.IGNORE_ERRORS in module.directives) { return null diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/classic/ClassicFrontend2IrConverter.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/classic/ClassicFrontend2IrConverter.kt index ea2702d36b9..ac40187b49d 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/classic/ClassicFrontend2IrConverter.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/classic/ClassicFrontend2IrConverter.kt @@ -64,13 +64,14 @@ class ClassicFrontend2IrConverter( .diagnosticReporter(DiagnosticReporterFactory.createReporter()) .build() - val convertionResult = + val conversionResult = codegenFactory.convertToIr(CodegenFactory.IrConversionInput.fromGenerationStateAndFiles(state, psiFiles.values)) return IrBackendInput.JvmIrBackendInput( state, codegenFactory, - convertionResult, - emptyList() + dependentInputs = emptyList(), + conversionResult, + sourceFiles = emptyList() ) } diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/Fir2IrJsResultsConverter.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/Fir2IrJsResultsConverter.kt index fb6a9263189..c077e402524 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/Fir2IrJsResultsConverter.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/Fir2IrJsResultsConverter.kt @@ -69,7 +69,7 @@ class Fir2IrJsResultsConverter( val fir2IrExtensions = Fir2IrExtensions.Default val firFiles = inputArtifact.allFirFiles.values val (irModuleFragment, components, pluginContext) = - inputArtifact.firAnalyzerFacade.convertToJsIr(firFiles, fir2IrExtensions, module, configuration, testServices) + inputArtifact.partsForDependsOnModules.last().firAnalyzerFacade.convertToJsIr(firFiles, fir2IrExtensions, module, configuration, testServices) val sourceFiles = firFiles.mapNotNull { it.sourceFile } val firFilesBySourceFile = firFiles.associateBy { it.sourceFile } @@ -81,7 +81,7 @@ class Fir2IrJsResultsConverter( ?: GenerationState.LANGUAGE_TO_METADATA_VERSION.getValue(module.languageVersionSettings.languageVersion) // At this point, checkers will already have been run by a previous test step. `runCheckers` returns the cached diagnostics map. - val diagnosticsMap = inputArtifact.firAnalyzerFacade.runCheckers() + val diagnosticsMap = inputArtifact.partsForDependsOnModules.last().firAnalyzerFacade.runCheckers() val hasErrors = diagnosticsMap.any { entry -> entry.value.any { it.severity == Severity.ERROR } } return IrBackendInput.JsIrBackendInput( diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/Fir2IrResultsConverter.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/Fir2IrResultsConverter.kt index adfe8ca9d40..5752103f187 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/Fir2IrResultsConverter.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/Fir2IrResultsConverter.kt @@ -12,7 +12,9 @@ import org.jetbrains.kotlin.cli.jvm.compiler.NoScopeRecordCliBindingTrace import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM import org.jetbrains.kotlin.codegen.ClassBuilderFactories import org.jetbrains.kotlin.codegen.state.GenerationState +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.container.get +import org.jetbrains.kotlin.fir.backend.Fir2IrComponents import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendClassResolver import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendExtension import org.jetbrains.kotlin.fir.backend.jvm.JvmFir2IrExtensions @@ -40,22 +42,18 @@ class Fir2IrResultsConverter( module: TestModule, inputArtifact: FirOutputArtifact ): IrBackendInput { + val isMppSupported = module.languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects) + val compilerConfigurationProvider = testServices.compilerConfigurationProvider val configuration = compilerConfigurationProvider.getCompilerConfiguration(module) val fir2IrExtensions = JvmFir2IrExtensions(configuration, JvmIrDeserializerImpl(), JvmIrMangler) - val (irModuleFragment, components, pluginContext) = inputArtifact.firAnalyzerFacade.convertToIr(fir2IrExtensions) - val dummyBindingContext = NoScopeRecordCliBindingTrace().bindingContext - - val phaseConfig = configuration.get(CLIConfigurationKeys.PHASE_CONFIG) - val codegenFactory = JvmIrCodegenFactory(configuration, phaseConfig) - - // TODO: handle fir from light tree - val ktFiles = inputArtifact.firFiles.values.mapNotNull { it.psi as KtFile? } - val sourceFiles = inputArtifact.firFiles.values.mapNotNull { it.sourceFile } // Create and initialize the module and its dependencies val project = compilerConfigurationProvider.getProject(module) + // TODO: handle fir from light tree + val ktFiles = inputArtifact.mainFirFiles.mapNotNull { it.value.psi as KtFile? } + val sourceFiles = inputArtifact.mainFirFiles.mapNotNull { it.value.sourceFile } val container = TopDownAnalyzerFacadeForJVM.createContainer( project, ktFiles, NoScopeRecordCliBindingTrace(), configuration, compilerConfigurationProvider.getPackagePartProviderFactory(module), @@ -63,28 +61,49 @@ class Fir2IrResultsConverter( TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, ktFiles), emptyList() ) - val generationState = GenerationState.Builder( - project, ClassBuilderFactories.TEST, - container.get(), dummyBindingContext, configuration - ).isIrBackend( - true - ).jvmBackendClassResolver( - FirJvmBackendClassResolver(components) - ).build() + val phaseConfig = configuration.get(CLIConfigurationKeys.PHASE_CONFIG) - return IrBackendInput.JvmIrBackendInput( - generationState, - codegenFactory, - JvmIrCodegenFactory.JvmIrBackendInput( + val componentsMap = mutableMapOf() + val dependentIrParts = mutableListOf() + lateinit var mainIrPart: JvmIrCodegenFactory.JvmIrBackendInput + + for ((index, firOutputPart) in inputArtifact.partsForDependsOnModules.withIndex()) { + val (irModuleFragment, components, pluginContext) = firOutputPart.firAnalyzerFacade.convertToIr(fir2IrExtensions) + componentsMap[firOutputPart.module.name] = components + + val irPart = JvmIrCodegenFactory.JvmIrBackendInput( irModuleFragment, components.symbolTable, phaseConfig, components.irProviders, fir2IrExtensions, - FirJvmBackendExtension(inputArtifact.session, components), + FirJvmBackendExtension(firOutputPart.session, components), pluginContext, notifyCodegenStart = {}, - ), + ) + + if (index < inputArtifact.partsForDependsOnModules.size - 1) { + dependentIrParts.add(irPart) + } else { + mainIrPart = irPart + } + } + + val codegenFactory = JvmIrCodegenFactory(configuration, phaseConfig) + val generationState = GenerationState.Builder( + project, ClassBuilderFactories.TEST, + container.get(), NoScopeRecordCliBindingTrace().bindingContext, configuration + ).isIrBackend( + true + ).jvmBackendClassResolver( + FirJvmBackendClassResolver(componentsMap[module.name]!!) + ).build() + + return IrBackendInput.JvmIrBackendInput( + generationState, + codegenFactory, + dependentIrParts, + mainIrPart, sourceFiles ) } diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/FirFrontendFacade.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/FirFrontendFacade.kt index f712cb41ecb..3fb20c8d918 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/FirFrontendFacade.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/FirFrontendFacade.kt @@ -5,11 +5,11 @@ package org.jetbrains.kotlin.test.frontend.fir +import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.StandardFileSystems import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.psi.PsiElementFinder import com.intellij.psi.search.ProjectScope -import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices import org.jetbrains.kotlin.asJava.finder.JavaElementFinder import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.cli.jvm.compiler.PsiBasedProjectFileSearchScope @@ -19,17 +19,16 @@ import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots import org.jetbrains.kotlin.cli.jvm.config.jvmModularRoots import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.JVMConfigurationKeys +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers +import org.jetbrains.kotlin.fir.deserialization.ModuleDataProvider import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar +import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider import org.jetbrains.kotlin.fir.session.FirJvmSessionFactory import org.jetbrains.kotlin.fir.session.FirNativeSessionFactory import org.jetbrains.kotlin.fir.session.FirSessionConfigurator -import org.jetbrains.kotlin.ir.backend.js.jsResolveLibraries -import org.jetbrains.kotlin.ir.backend.js.resolverLogger -import org.jetbrains.kotlin.js.config.JSConfigurationKeys -import org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices -import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary +import org.jetbrains.kotlin.fir.session.environment.AbstractProjectEnvironment import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.platform.isCommon @@ -37,25 +36,22 @@ import org.jetbrains.kotlin.platform.isJs import org.jetbrains.kotlin.platform.jvm.isJvm import org.jetbrains.kotlin.platform.konan.isNative 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.test.TargetBackend import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives import org.jetbrains.kotlin.test.directives.model.DirectivesContainer -import org.jetbrains.kotlin.test.model.DependencyRelation +import org.jetbrains.kotlin.test.getAnalyzerServices import org.jetbrains.kotlin.test.model.FrontendFacade import org.jetbrains.kotlin.test.model.FrontendKinds import org.jetbrains.kotlin.test.model.TestModule import org.jetbrains.kotlin.test.services.* -import org.jetbrains.kotlin.test.services.configuration.JsEnvironmentConfigurator -import java.io.File import java.nio.file.Paths open class FirFrontendFacade( testServices: TestServices, private val additionalSessionConfiguration: SessionConfiguration? ) : FrontendFacade(testServices, FrontendKinds.FIR) { + private val testModulesByName by lazy { testServices.moduleStructure.modules.associateBy { it.name } } + // Separate constructor is needed for creating callable references to it constructor(testServices: TestServices) : this(testServices, additionalSessionConfiguration = null) @@ -67,53 +63,150 @@ open class FirFrontendFacade( override val directiveContainers: List get() = listOf(FirDiagnosticsDirectives) + override fun shouldRunAnalysis(module: TestModule): Boolean { + if (!super.shouldRunAnalysis(module)) return false + + return if (module.languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects)) { + testServices.moduleStructure + .modules.none { testModule -> testModule.dependsOnDependencies.any { testModulesByName[it.moduleName] == module } } + } else { + true + } + } + open fun registerExtraComponents(session: FirSession) {} override fun analyze(module: TestModule): FirOutputArtifact { - val moduleInfoProvider = testServices.firModuleInfoProvider - val compilerConfigurationProvider = testServices.compilerConfigurationProvider - // TODO: add configurable parser + val isMppSupported = module.languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects) - val project = compilerConfigurationProvider.getProject(module) + val sortedModules = if (isMppSupported) sortDependsOnTopologically(module) else listOf(module) - PsiElementFinder.EP.getPoint(project).unregisterExtension(JavaElementFinder::class.java) + val (moduleDataMap, moduleDataProvider) = initializeModuleData(sortedModules) - val lightTreeEnabled = FirDiagnosticsDirectives.USE_LIGHT_TREE in module.directives - val (ktFiles, lightTreeFiles) = if (lightTreeEnabled) { - emptyList() to testServices.sourceFileProvider.getLightTreeFilesForSourceFiles(module.files).values - } else { - testServices.sourceFileProvider.getKtFilesForSourceFiles(module.files, project).values to emptyList() + val projectEnvironment = createLibrarySession( + module, + testServices.compilerConfigurationProvider.getProject(module), + Name.special("<${module.name}>"), + testServices.firModuleInfoProvider.firSessionProvider, + moduleDataProvider, + testServices.compilerConfigurationProvider.getCompilerConfiguration(module) + ) + + val targetPlatform = module.targetPlatform + val firOutputPartForDependsOnModules = mutableListOf() + for (testModule in sortedModules) { + firOutputPartForDependsOnModules.add( + analyze( + testModule, + moduleDataMap[testModule]!!, + targetPlatform, + projectEnvironment, + isMppSupported = isMppSupported + ) + ) } + return FirOutputArtifactImpl(firOutputPartForDependsOnModules) + } + + private fun sortDependsOnTopologically(module: TestModule): List { + val sortedModules = mutableListOf() + val visitedModules = mutableSetOf() + val modulesQueue = ArrayDeque() + modulesQueue.add(module) + + while (modulesQueue.isNotEmpty()) { + val currentModule = modulesQueue.removeFirst() + if (!visitedModules.add(currentModule)) continue + sortedModules.add(currentModule) + + for (dependency in currentModule.dependsOnDependencies) { + modulesQueue.add(testServices.dependencyProvider.getTestModule(dependency.moduleName)) + } + } + + return sortedModules.reversed() + } + + private fun initializeModuleData(modules: List): Pair, ModuleDataProvider> { + val mainModule = modules.last() + + val targetPlatform = mainModule.targetPlatform + val analyzerServices = targetPlatform.getAnalyzerServices() + // the special name is required for `KlibMetadataModuleDescriptorFactoryImpl.createDescriptorOptionalBuiltIns` // it doesn't seem convincingly legitimate, probably should be refactored - val moduleName = Name.special("<${module.name}>") + val moduleName = Name.special("<${mainModule.name}>") + val binaryModuleData = BinaryModuleData.initialize(moduleName, targetPlatform, analyzerServices) + + val compilerConfigurationProvider = testServices.compilerConfigurationProvider + val configuration = compilerConfigurationProvider.getCompilerConfiguration(mainModule) + + val libraryList = initializeLibraryList(mainModule, binaryModuleData, targetPlatform, configuration) + + val moduleInfoProvider = testServices.firModuleInfoProvider + val moduleDataMap = mutableMapOf() + + for (module in modules) { + val regularModules = libraryList.regularDependencies + moduleInfoProvider.getRegularDependentSourceModules(module) + val friendModules = libraryList.friendsDependencies + moduleInfoProvider.getDependentFriendSourceModules(module) + val dependsOnModules = libraryList.dependsOnDependencies + moduleInfoProvider.getDependentDependsOnSourceModules(module) + + val moduleData = FirModuleDataImpl( + Name.special("<${module.name}>"), + regularModules, + dependsOnModules, + friendModules, + module.targetPlatform, + module.targetPlatform.getAnalyzerServices() + ) + + moduleInfoProvider.registerModuleData(module, moduleData) + + moduleDataMap[module] = moduleData + } + + return moduleDataMap to libraryList.moduleDataProvider + } + + private fun initializeLibraryList( + mainModule: TestModule, + binaryModuleData: BinaryModuleData, + targetPlatform: TargetPlatform, + configuration: CompilerConfiguration, + ): DependencyListForCliModule { + return DependencyListForCliModule.build(binaryModuleData) { + when { + targetPlatform.isCommon() || targetPlatform.isJvm() || targetPlatform.isNative() -> { + dependencies(configuration.jvmModularRoots.map { it.toPath() }) + dependencies(configuration.jvmClasspathRoots.map { it.toPath() }) + friendDependencies(configuration[JVMConfigurationKeys.FRIEND_PATHS] ?: emptyList()) + } + targetPlatform.isJs() -> { + val (runtimeKlibsPaths, transitiveLibraries, friendLibraries) = getJsDependencies(mainModule, testServices) + dependencies(runtimeKlibsPaths.map { Paths.get(it).toAbsolutePath() }) + dependencies(transitiveLibraries.map { it.toPath().toAbsolutePath() }) + friendDependencies(friendLibraries.map { it.toPath().toAbsolutePath() }) + } + else -> error("Unsupported") + } + } + } + + private fun createLibrarySession( + module: TestModule, + project: Project, + moduleName: Name, + sessionProvider: FirProjectSessionProvider, + moduleDataProvider: ModuleDataProvider, + configuration: CompilerConfiguration + ): AbstractProjectEnvironment? { + val compilerConfigurationProvider = testServices.compilerConfigurationProvider + val projectEnvironment: AbstractProjectEnvironment? val languageVersionSettings = module.languageVersionSettings - val analyzerServices = module.targetPlatform.getAnalyzerServices() - val configuration = compilerConfigurationProvider.getCompilerConfiguration(module) - val extensionRegistrars = FirExtensionRegistrar.getInstances(project) - - val sessionConfigurator: FirSessionConfigurator.() -> Unit = { - if (FirDiagnosticsDirectives.WITH_EXTENDED_CHECKERS in module.directives) { - registerExtendedCommonCheckers() - } - additionalSessionConfiguration?.invoke(this) - } - - val isCommonOrJvm = module.targetPlatform.isJvm() || module.targetPlatform.isCommon() - - val dependencyList = buildDependencyList(module, moduleName, moduleInfoProvider, analyzerServices) { - if (isCommonOrJvm || module.targetPlatform.isNative()) { - configureJvmDependencies(configuration) - } else { - configureJsDependencies(module, testServices) - } - } - - val projectEnvironment: VfsBasedProjectEnvironment? - when { - isCommonOrJvm -> { + // TODO: use common session for common target platform when it's implemented + module.targetPlatform.isCommon() || module.targetPlatform.isJvm() -> { val packagePartProviderFactory = compilerConfigurationProvider.getPackagePartProviderFactory(module) projectEnvironment = VfsBasedProjectEnvironment( project, VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL), @@ -123,8 +216,8 @@ open class FirFrontendFacade( FirJvmSessionFactory.createLibrarySession( moduleName, - moduleInfoProvider.firSessionProvider, - dependencyList, + sessionProvider, + moduleDataProvider, projectEnvironment, projectFileSearchScope, packagePartProvider, @@ -136,8 +229,8 @@ open class FirFrontendFacade( projectEnvironment = null TestFirJsSessionFactory.createLibrarySession( moduleName, - moduleInfoProvider.firSessionProvider, - dependencyList, + sessionProvider, + moduleDataProvider, module, testServices, configuration, @@ -150,29 +243,97 @@ open class FirFrontendFacade( FirNativeSessionFactory.createLibrarySession( moduleName, listOf(), - moduleInfoProvider.firSessionProvider, - dependencyList, + sessionProvider, + moduleDataProvider, languageVersionSettings, registerExtraComponents = ::registerExtraComponents, ) } else -> error("Unsupported") } + return projectEnvironment + } - val mainModuleData = FirModuleDataImpl( - moduleName, - dependencyList.regularDependencies, - dependencyList.dependsOnDependencies, - dependencyList.friendsDependencies, - dependencyList.platform, - dependencyList.analyzerServices + private fun analyze( + module: TestModule, + moduleData: FirModuleData, + targetPlatform: TargetPlatform, + projectEnvironment: AbstractProjectEnvironment?, + isMppSupported: Boolean, + ): FirOutputPartForDependsOnModule { + val compilerConfigurationProvider = testServices.compilerConfigurationProvider + val moduleInfoProvider = testServices.firModuleInfoProvider + val sessionProvider = moduleInfoProvider.firSessionProvider + + val project = compilerConfigurationProvider.getProject(module) + + PsiElementFinder.EP.getPoint(project).unregisterExtension(JavaElementFinder::class.java) + + val lightTreeEnabled = FirDiagnosticsDirectives.USE_LIGHT_TREE in module.directives + val (ktFiles, lightTreeFiles) = if (lightTreeEnabled) { + emptyList() to testServices.sourceFileProvider.getLightTreeFilesForSourceFiles(module.files).values + } else { + testServices.sourceFileProvider.getKtFilesForSourceFiles(module.files, project).values to emptyList() + } + + val extensionRegistrars = FirExtensionRegistrar.getInstances(project) + val sessionConfigurator: FirSessionConfigurator.() -> Unit = { + if (FirDiagnosticsDirectives.WITH_EXTENDED_CHECKERS in module.directives) { + registerExtendedCommonCheckers() + } + additionalSessionConfiguration?.invoke(this) + } + + val moduleBasedSession = createModuleBasedSession( + module, + moduleData, + targetPlatform, + sessionProvider, + projectEnvironment, + extensionRegistrars, + sessionConfigurator, + project, + ktFiles ) - val session = when { - isCommonOrJvm -> { + val enablePluginPhases = FirDiagnosticsDirectives.ENABLE_PLUGIN_PHASES in module.directives + val firAnalyzerFacade = FirAnalyzerFacade( + moduleBasedSession, + module.languageVersionSettings, + ktFiles, + lightTreeFiles, + IrGenerationExtension.getInstances(project), + lightTreeEnabled, + enablePluginPhases, + generateSignatures = module.targetBackend == TargetBackend.JVM_IR_SERIALIZE || isMppSupported, + ) + val firFiles = firAnalyzerFacade.runResolution() + val filesMap = firFiles.mapNotNull { firFile -> + val testFile = module.files.firstOrNull { it.name == firFile.name } ?: return@mapNotNull null + testFile to firFile + }.toMap() + + return FirOutputPartForDependsOnModule(module, moduleBasedSession, firAnalyzerFacade, filesMap) + } + + private fun createModuleBasedSession( + module: TestModule, + moduleData: FirModuleData, + targetPlatform: TargetPlatform, + sessionProvider: FirProjectSessionProvider, + projectEnvironment: AbstractProjectEnvironment?, + extensionRegistrars: List, + sessionConfigurator: FirSessionConfigurator.() -> Unit, + project: Project, + ktFiles: Collection + ): FirSession { + val languageVersionSettings = module.languageVersionSettings + return when { + // TODO: use common session for common target platform when it's implemented + targetPlatform.isCommon() || targetPlatform.isJvm() -> { FirJvmSessionFactory.createModuleBasedSession( - mainModuleData, - moduleInfoProvider.firSessionProvider, + moduleData, + sessionProvider, PsiBasedProjectFileSearchScope(TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, ktFiles)), projectEnvironment!!, incrementalCompilationContext = null, @@ -185,10 +346,10 @@ open class FirFrontendFacade( sessionConfigurator, ) } - module.targetPlatform.isJs() -> { + targetPlatform.isJs() -> { TestFirJsSessionFactory.createModuleBasedSession( - mainModuleData, - moduleInfoProvider.firSessionProvider, + moduleData, + sessionProvider, extensionRegistrars, languageVersionSettings, null, @@ -196,10 +357,10 @@ open class FirFrontendFacade( sessionConfigurator, ) } - module.targetPlatform.isNative() -> { + targetPlatform.isNative() -> { FirNativeSessionFactory.createModuleBasedSession( - mainModuleData, - moduleInfoProvider.firSessionProvider, + moduleData, + sessionProvider, extensionRegistrars, languageVersionSettings, registerExtraComponents = ::registerExtraComponents, @@ -208,93 +369,5 @@ open class FirFrontendFacade( } else -> error("Unsupported") } - - moduleInfoProvider.registerModuleData(module, session.moduleData) - - val enablePluginPhases = FirDiagnosticsDirectives.ENABLE_PLUGIN_PHASES in module.directives - val firAnalyzerFacade = FirAnalyzerFacade( - session, - languageVersionSettings, - ktFiles, - lightTreeFiles, - IrGenerationExtension.getInstances(project), - lightTreeEnabled, - enablePluginPhases, - generateSignatures = module.targetBackend == TargetBackend.JVM_IR_SERIALIZE - ) - val firFiles = firAnalyzerFacade.runResolution() - val filesMap = firFiles.mapNotNull { firFile -> - val testFile = module.files.firstOrNull { it.name == firFile.name } ?: return@mapNotNull null - testFile to firFile - }.toMap() - - return FirOutputArtifactImpl(session, filesMap, firAnalyzerFacade) - } -} - -private fun DependencyListForCliModule.Builder.configureJvmDependencies( - configuration: CompilerConfiguration, -) { - dependencies(configuration.jvmModularRoots.map { it.toPath() }) - dependencies(configuration.jvmClasspathRoots.map { it.toPath() }) - - friendDependencies(configuration[JVMConfigurationKeys.FRIEND_PATHS] ?: emptyList()) -} - -private fun DependencyListForCliModule.Builder.configureJsDependencies( - module: TestModule, - testServices: TestServices, -) { - val (runtimeKlibsPaths, transitiveLibraries, friendLibraries) = getJsDependencies(module, testServices) - - dependencies(runtimeKlibsPaths.map { Paths.get(it).toAbsolutePath() }) - dependencies(transitiveLibraries.map { it.toPath().toAbsolutePath() }) - - friendDependencies(friendLibraries.map { it.toPath().toAbsolutePath() }) -} - -private fun getJsDependencies(module: TestModule, testServices: TestServices): Triple, List, List> { - val runtimeKlibsPaths = JsEnvironmentConfigurator.getRuntimePathsForModule(module, testServices) - val transitiveLibraries = JsEnvironmentConfigurator.getKlibDependencies(module, testServices, DependencyRelation.RegularDependency) - val friendLibraries = JsEnvironmentConfigurator.getKlibDependencies(module, testServices, DependencyRelation.FriendDependency) - return Triple(runtimeKlibsPaths, transitiveLibraries, friendLibraries) -} - -fun getAllJsDependenciesPaths(module: TestModule, testServices: TestServices): List { - val (runtimeKlibsPaths, transitiveLibraries, friendLibraries) = getJsDependencies(module, testServices) - return runtimeKlibsPaths + transitiveLibraries.map { it.path } + friendLibraries.map { it.path } -} - -fun resolveJsLibraries( - module: TestModule, - testServices: TestServices, - configuration: CompilerConfiguration -): List { - val paths = getAllJsDependenciesPaths(module, testServices) - val repositories = configuration[JSConfigurationKeys.REPOSITORIES] ?: emptyList() - val logger = configuration.resolverLogger - return jsResolveLibraries(paths, repositories, logger).getFullResolvedList() -} - -private fun buildDependencyList( - module: TestModule, - moduleName: Name, - moduleInfoProvider: FirModuleInfoProvider, - analyzerServices: PlatformDependentAnalyzerServices, - configureDependencies: DependencyListForCliModule.Builder.() -> Unit, -) = DependencyListForCliModule.build(moduleName, module.targetPlatform, analyzerServices) { - configureDependencies() - sourceDependencies(moduleInfoProvider.getRegularDependentSourceModules(module)) - sourceFriendsDependencies(moduleInfoProvider.getDependentFriendSourceModules(module)) - sourceDependsOnDependencies(moduleInfoProvider.getDependentDependsOnSourceModules(module)) -} - -fun TargetPlatform.getAnalyzerServices(): PlatformDependentAnalyzerServices { - return when { - isJvm() -> JvmPlatformAnalyzerServices - isJs() -> JsPlatformAnalyzerServices - isNative() -> NativePlatformAnalyzerServices - isCommon() -> CommonPlatformAnalyzerServices - else -> error("Unknown target platform: $this") } } diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/FirModuleInfoProvider.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/FirModuleInfoProvider.kt index a61f16145dc..3fec8f03e31 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/FirModuleInfoProvider.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/FirModuleInfoProvider.kt @@ -20,7 +20,9 @@ class FirModuleInfoProvider(private val testServices: TestServices) : TestServic private val firModuleDataByModule: MutableMap = mutableMapOf() fun registerModuleData(module: TestModule, moduleData: FirModuleData) { - if (module in firModuleDataByModule) error("module data for module $module already registered") + // Allow reregistering since tests with several targets are possible (JVM, JS) + // FirFrontendFacade creates modules for every platform. But if several targets are presented, several common modules will be initialized. + // It's not possible to reuse moduleData for the same modules because moduleData depends on the platform. firModuleDataByModule[module] = moduleData } diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/FirOutputArtifact.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/FirOutputArtifact.kt index bb7d2fb87b7..a02e5c24f40 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/FirOutputArtifact.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/FirOutputArtifact.kt @@ -6,27 +6,28 @@ package org.jetbrains.kotlin.test.frontend.fir import org.jetbrains.kotlin.fir.AbstractFirAnalyzerFacade -import org.jetbrains.kotlin.fir.FirAnalyzerFacade import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.test.model.FrontendKinds import org.jetbrains.kotlin.test.model.ResultingArtifact import org.jetbrains.kotlin.test.model.TestFile +import org.jetbrains.kotlin.test.model.TestModule -abstract class FirOutputArtifact : ResultingArtifact.FrontendOutput() { - abstract val session: FirSession - abstract val firAnalyzerFacade: AbstractFirAnalyzerFacade - abstract val allFirFiles: Map +// Only MPP contains several parts inside FirOutputArtifact, other projects only contain single part. +data class FirOutputPartForDependsOnModule( + val module: TestModule, + val session: FirSession, + val firAnalyzerFacade: AbstractFirAnalyzerFacade, + val firFiles: Map +) + +abstract class FirOutputArtifact(val partsForDependsOnModules: List) : ResultingArtifact.FrontendOutput() { + val allFirFiles: Map = partsForDependsOnModules.fold(emptyMap()) { acc, part -> acc + part.firFiles } override val kind: FrontendKinds.FIR get() = FrontendKinds.FIR - - val firFiles: Map by lazy { allFirFiles.filterKeys { !it.isAdditional } } + val mainFirFiles: Map by lazy { allFirFiles.filterKeys { !it.isAdditional } } } -data class FirOutputArtifactImpl( - override val session: FirSession, - override val allFirFiles: Map, - override val firAnalyzerFacade: FirAnalyzerFacade -) : FirOutputArtifact() \ No newline at end of file +class FirOutputArtifactImpl(parts: List) : FirOutputArtifact(parts) \ No newline at end of file diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/TestFirJsSessionFactory.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/TestFirJsSessionFactory.kt index b3902f6e45a..0ad6d3dfa96 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/TestFirJsSessionFactory.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/TestFirJsSessionFactory.kt @@ -7,9 +7,9 @@ package org.jetbrains.kotlin.test.frontend.fir import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.LanguageVersionSettings -import org.jetbrains.kotlin.fir.DependencyListForCliModule -import org.jetbrains.kotlin.fir.FirModuleDataImpl +import org.jetbrains.kotlin.fir.FirModuleData import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.deserialization.ModuleDataProvider import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider import org.jetbrains.kotlin.fir.session.FirJsSessionFactory @@ -18,15 +18,19 @@ import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.ir.backend.js.jsResolveLibraries import org.jetbrains.kotlin.ir.backend.js.resolverLogger import org.jetbrains.kotlin.js.config.JSConfigurationKeys +import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.test.model.DependencyRelation import org.jetbrains.kotlin.test.model.TestModule import org.jetbrains.kotlin.test.services.TestServices +import org.jetbrains.kotlin.test.services.configuration.JsEnvironmentConfigurator +import java.io.File object TestFirJsSessionFactory { fun createLibrarySession( mainModuleName: Name, sessionProvider: FirProjectSessionProvider, - dependencyListForCliModule: DependencyListForCliModule, + moduleDataProvider: ModuleDataProvider, module: TestModule, testServices: TestServices, configuration: CompilerConfiguration, @@ -42,14 +46,14 @@ object TestFirJsSessionFactory { mainModuleName, resolvedLibraries, sessionProvider, - dependencyListForCliModule.moduleDataProvider, + moduleDataProvider, languageVersionSettings, registerExtraComponents, ) } fun createModuleBasedSession( - mainModuleData: FirModuleDataImpl, sessionProvider: FirProjectSessionProvider, extensionRegistrars: List, + mainModuleData: FirModuleData, sessionProvider: FirProjectSessionProvider, extensionRegistrars: List, languageVersionSettings: LanguageVersionSettings, lookupTracker: LookupTracker?, registerExtraComponents: ((FirSession) -> Unit), sessionConfigurator: FirSessionConfigurator.() -> Unit, @@ -63,4 +67,27 @@ object TestFirJsSessionFactory { registerExtraComponents, sessionConfigurator ) -} \ No newline at end of file +} + +fun resolveJsLibraries( + module: TestModule, + testServices: TestServices, + configuration: CompilerConfiguration +): List { + val paths = getAllJsDependenciesPaths(module, testServices) + val repositories = configuration[JSConfigurationKeys.REPOSITORIES] ?: emptyList() + val logger = configuration.resolverLogger + return jsResolveLibraries(paths, repositories, logger).getFullResolvedList() +} + +fun getAllJsDependenciesPaths(module: TestModule, testServices: TestServices): List { + val (runtimeKlibsPaths, transitiveLibraries, friendLibraries) = getJsDependencies(module, testServices) + return runtimeKlibsPaths + transitiveLibraries.map { it.path } + friendLibraries.map { it.path } +} + +fun getJsDependencies(module: TestModule, testServices: TestServices): Triple, List, List> { + val runtimeKlibsPaths = JsEnvironmentConfigurator.getRuntimePathsForModule(module, testServices) + val transitiveLibraries = JsEnvironmentConfigurator.getKlibDependencies(module, testServices, DependencyRelation.RegularDependency) + val friendLibraries = JsEnvironmentConfigurator.getKlibDependencies(module, testServices, DependencyRelation.FriendDependency) + return Triple(runtimeKlibsPaths, transitiveLibraries, friendLibraries) +} diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirCfgConsistencyHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirCfgConsistencyHandler.kt index dd3bcd92b19..f3ccf3b5c39 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirCfgConsistencyHandler.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirCfgConsistencyHandler.kt @@ -12,7 +12,7 @@ import org.jetbrains.kotlin.test.services.TestServices class FirCfgConsistencyHandler(testServices: TestServices) : FirAnalysisHandler(testServices) { override fun processModule(module: TestModule, info: FirOutputArtifact) { - info.firFiles.values.forEach { it.accept(FirCfgConsistencyChecker(assertions)) } + info.mainFirFiles.values.forEach { it.accept(FirCfgConsistencyChecker(assertions)) } } override fun processAfterAllModules(someAssertionWasFailed: Boolean) {} diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirCfgDumpHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirCfgDumpHandler.kt index aede4a8a82d..ef893557abb 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirCfgDumpHandler.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirCfgDumpHandler.kt @@ -24,7 +24,7 @@ class FirCfgDumpHandler(testServices: TestServices) : FirAnalysisHandler(testSer override fun processModule(module: TestModule, info: FirOutputArtifact) { if (alreadyDumped || FirDiagnosticsDirectives.DUMP_CFG !in module.directives) return - val file = info.firFiles.values.first() + val file = info.mainFirFiles.values.first() val renderLevels = RENDERER_CFG_LEVELS in module.directives file.accept(FirControlFlowGraphRenderVisitor(builder, renderLevels)) alreadyDumped = true diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticsHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticsHandler.kt index 33abf5b8ca0..fb85f4b26e8 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticsHandler.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDiagnosticsHandler.kt @@ -61,39 +61,43 @@ class FirDiagnosticsHandler(testServices: TestServices) : FirAnalysisHandler(tes listOf(service(::DiagnosticsService)) override fun processModule(module: TestModule, info: FirOutputArtifact) { - val diagnosticsPerFile = info.firAnalyzerFacade.runCheckers() - val lightTreeComparingModeEnabled = FirDiagnosticsDirectives.COMPARE_WITH_LIGHT_TREE in module.directives - val lightTreeEnabled = FirDiagnosticsDirectives.USE_LIGHT_TREE in module.directives + for (part in info.partsForDependsOnModules) { + val diagnosticsPerFile = part.firAnalyzerFacade.runCheckers() + val currentModule = part.module - for (file in module.files) { - val firFile = info.firFiles[file] ?: continue - var diagnostics = diagnosticsPerFile[firFile] ?: continue - if (AdditionalFilesDirectives.CHECK_TYPE in module.directives) { - diagnostics = diagnostics.filter { it.factory.name != FirErrors.UNDERSCORE_USAGE_WITHOUT_BACKTICKS.name } - } - if (LanguageSettingsDirectives.API_VERSION in module.directives) { - diagnostics = diagnostics.filter { it.factory.name != FirErrors.NEWER_VERSION_IN_SINCE_KOTLIN.name } - } - val diagnosticsMetadataInfos = diagnostics.flatMap { diagnostic -> - if (!diagnosticsService.shouldRenderDiagnostic( - module, - diagnostic.factory.name, - diagnostic.severity + val lightTreeComparingModeEnabled = FirDiagnosticsDirectives.COMPARE_WITH_LIGHT_TREE in currentModule.directives + val lightTreeEnabled = FirDiagnosticsDirectives.USE_LIGHT_TREE in currentModule.directives + + for (file in currentModule.files) { + val firFile = info.mainFirFiles[file] ?: continue + var diagnostics = diagnosticsPerFile[firFile] ?: continue + if (AdditionalFilesDirectives.CHECK_TYPE in currentModule.directives) { + diagnostics = diagnostics.filter { it.factory.name != FirErrors.UNDERSCORE_USAGE_WITHOUT_BACKTICKS.name } + } + if (LanguageSettingsDirectives.API_VERSION in currentModule.directives) { + diagnostics = diagnostics.filter { it.factory.name != FirErrors.NEWER_VERSION_IN_SINCE_KOTLIN.name } + } + val diagnosticsMetadataInfos = diagnostics.flatMap { diagnostic -> + if (!diagnosticsService.shouldRenderDiagnostic( + currentModule, + diagnostic.factory.name, + diagnostic.severity + ) + ) return@flatMap emptyList() + // SYNTAX errors will be reported later + if (diagnostic.factory == FirSyntaxErrors.SYNTAX) return@flatMap emptyList() + if (!diagnostic.isValid) return@flatMap emptyList() + diagnostic.toMetaInfos( + file, + globalMetadataInfoHandler, + lightTreeEnabled, + lightTreeComparingModeEnabled ) - ) return@flatMap emptyList() - // SYNTAX errors will be reported later - if (diagnostic.factory == FirSyntaxErrors.SYNTAX) return@flatMap emptyList() - if (!diagnostic.isValid) return@flatMap emptyList() - diagnostic.toMetaInfos( - file, - globalMetadataInfoHandler, - lightTreeEnabled, - lightTreeComparingModeEnabled - ) + } + globalMetadataInfoHandler.addMetadataInfosForFile(file, diagnosticsMetadataInfos) + collectSyntaxDiagnostics(file, firFile, lightTreeEnabled, lightTreeComparingModeEnabled) + collectDebugInfoDiagnostics(currentModule, file, firFile, lightTreeEnabled, lightTreeComparingModeEnabled) } - globalMetadataInfoHandler.addMetadataInfosForFile(file, diagnosticsMetadataInfos) - collectSyntaxDiagnostics(file, firFile, lightTreeEnabled, lightTreeComparingModeEnabled) - collectDebugInfoDiagnostics(module, file, firFile, lightTreeEnabled, lightTreeComparingModeEnabled) } } diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDumpHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDumpHandler.kt index e0105276752..cdb021cc32b 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDumpHandler.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirDumpHandler.kt @@ -32,25 +32,28 @@ class FirDumpHandler( get() = listOf(FirDiagnosticsDirectives) override fun processModule(module: TestModule, info: FirOutputArtifact) { - if (FirDiagnosticsDirectives.FIR_DUMP !in module.directives) return - val builderForModule = dumper.builderForModule(module) - val firFiles = info.firFiles + for (part in info.partsForDependsOnModules) { + val currentModule = part.module + if (FirDiagnosticsDirectives.FIR_DUMP !in currentModule.directives) return + val builderForModule = dumper.builderForModule(currentModule) + val firFiles = info.mainFirFiles - val allFiles = buildList { - addAll(firFiles.values) - addAll(info.session.createFilesWithGeneratedDeclarations()) - } - info.session.lazyDeclarationResolver.startResolvingPhase(FirResolvePhase.BODY_RESOLVE) + val allFiles = buildList { + addAll(firFiles.values) + addAll(part.session.createFilesWithGeneratedDeclarations()) + } + part.session.lazyDeclarationResolver.startResolvingPhase(FirResolvePhase.BODY_RESOLVE) - val renderer = FirRenderer( - builder = builderForModule, - packageDirectiveRenderer = FirPackageDirectiveRenderer(), - classMemberRenderer = FirClassMemberRendererWithGeneratedDeclarations(info.session) - ) - allFiles.forEach { - renderer.renderElementAsString(it) + val renderer = FirRenderer( + builder = builderForModule, + packageDirectiveRenderer = FirPackageDirectiveRenderer(), + classMemberRenderer = FirClassMemberRendererWithGeneratedDeclarations(part.session) + ) + allFiles.forEach { + renderer.renderElementAsString(it) + } + part.session.lazyDeclarationResolver.finishResolvingPhase(FirResolvePhase.BODY_RESOLVE) } - info.session.lazyDeclarationResolver.finishResolvingPhase(FirResolvePhase.BODY_RESOLVE) } override fun processAfterAllModules(someAssertionWasFailed: Boolean) { diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirResolveContractViolationErrorHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirResolveContractViolationErrorHandler.kt index 30f95f6f003..8e4f15a59f9 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirResolveContractViolationErrorHandler.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirResolveContractViolationErrorHandler.kt @@ -13,10 +13,12 @@ import org.jetbrains.kotlin.test.services.assertions class FirResolveContractViolationErrorHandler(testServices: TestServices) : FirAnalysisHandler(testServices) { override fun processModule(module: TestModule, info: FirOutputArtifact) { - val session = info.session - val lazyResolver = session.lazyDeclarationResolver as? FirCompilerLazyDeclarationResolverWithPhaseChecking ?: return - val exceptions = lazyResolver.getContractViolationExceptions().ifEmpty { return } - testServices.assertions.failAll(exceptions) + for (part in info.partsForDependsOnModules) { + val session = part.session + val lazyResolver = session.lazyDeclarationResolver as? FirCompilerLazyDeclarationResolverWithPhaseChecking ?: return + val exceptions = lazyResolver.getContractViolationExceptions().ifEmpty { return } + testServices.assertions.failAll(exceptions) + } } override fun processAfterAllModules(someAssertionWasFailed: Boolean) {} diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirResolvedTypesVerifier.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirResolvedTypesVerifier.kt index abb544c4690..1f3d9af0fb9 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirResolvedTypesVerifier.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirResolvedTypesVerifier.kt @@ -6,16 +6,13 @@ package org.jetbrains.kotlin.test.frontend.fir.handlers import org.jetbrains.kotlin.fir.FirElement -import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.diagnostics.ConeAmbiguousSuper import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticHolder import org.jetbrains.kotlin.fir.expressions.FirErrorLoop -import org.jetbrains.kotlin.fir.expressions.FirLoop import org.jetbrains.kotlin.fir.expressions.FirLoopJump import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeFunctionExpectedError -import org.jetbrains.kotlin.fir.resolve.substitution.AbstractConeSubstitutor import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives @@ -31,7 +28,7 @@ class FirResolvedTypesVerifier(testServices: TestServices) : FirAnalysisHandler( override fun processModule(module: TestModule, info: FirOutputArtifact) { val visitor = Visitor() - for (firFile in info.firFiles.values) { + for (firFile in info.mainFirFiles.values) { firFile.acceptChildren(visitor, firFile) } val ignored = IGNORE_LEAKED_INTERNAL_TYPES in module.directives diff --git a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirScopeDumpHandler.kt b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirScopeDumpHandler.kt index d24c0ebd961..1d9ec16b53b 100644 --- a/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirScopeDumpHandler.kt +++ b/compiler/tests-common-new/tests/org/jetbrains/kotlin/test/frontend/fir/handlers/FirScopeDumpHandler.kt @@ -41,12 +41,15 @@ class FirScopeDumpHandler(testServices: TestServices) : FirAnalysisHandler(testS get() = listOf(FirDiagnosticsDirectives) override fun processModule(module: TestModule, info: FirOutputArtifact) { - val fqNamesWithNames = module.directives[FirDiagnosticsDirectives.SCOPE_DUMP] - if (fqNamesWithNames.isEmpty()) return - val printer = SmartPrinter(dumper.builderForModule(module), indent = " ") - for (fqNameWithNames in fqNamesWithNames) { - val (fqName, names) = extractFqNameAndMemberNames(fqNameWithNames) - printer.processClass(fqName, names, info.session, info.firAnalyzerFacade.scopeSession, module) + for (part in info.partsForDependsOnModules) { + val currentModule = part.module + val fqNamesWithNames = currentModule.directives[FirDiagnosticsDirectives.SCOPE_DUMP] + if (fqNamesWithNames.isEmpty()) return + val printer = SmartPrinter(dumper.builderForModule(currentModule), indent = " ") + for (fqNameWithNames in fqNamesWithNames) { + val (fqName, names) = extractFqNameAndMemberNames(fqNameWithNames) + printer.processClass(fqName, names, part.session, part.firAnalyzerFacade.scopeSession, currentModule) + } } } diff --git a/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/FirAnalyzerFacade.kt b/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/FirAnalyzerFacade.kt index 3b29614e937..2ec812c4376 100644 --- a/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/FirAnalyzerFacade.kt +++ b/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/FirAnalyzerFacade.kt @@ -48,7 +48,7 @@ class FirAnalyzerFacade( val irGeneratorExtensions: Collection, val useLightTree: Boolean = false, val enablePluginPhases: Boolean = false, - val generateSignatures: Boolean = false, + val generateSignatures: Boolean = false ) : AbstractFirAnalyzerFacade() { private var firFiles: List? = null private var _scopeSession: ScopeSession? = null @@ -108,13 +108,8 @@ class FirAnalyzerFacade( val mangler = JvmDescriptorMangler(null) val signaturer = JvmIdSignatureDescriptor(mangler) - val commonFirFiles = session.moduleData.dependsOnDependencies - .map { it.session } - .filter { it.kind == FirSession.Kind.Source } - .flatMap { (it.firProvider as FirProviderImpl).getAllFirFiles() } - return Fir2IrConverter.createModuleFragmentWithSignaturesIfNeeded( - session, _scopeSession!!, firFiles!! + commonFirFiles, + session, _scopeSession!!, firFiles!!, languageVersionSettings, signaturer, fir2IrExtensions, FirJvmKotlinMangler(session), JvmIrMangler, IrFactoryImpl, diff --git a/compiler/visualizer/tests/org/jetbrains/kotlin/visualizer/AbstractVisualizerBlackBoxTest.kt b/compiler/visualizer/tests/org/jetbrains/kotlin/visualizer/AbstractVisualizerBlackBoxTest.kt index 51c3d517877..7970d776b0d 100644 --- a/compiler/visualizer/tests/org/jetbrains/kotlin/visualizer/AbstractVisualizerBlackBoxTest.kt +++ b/compiler/visualizer/tests/org/jetbrains/kotlin/visualizer/AbstractVisualizerBlackBoxTest.kt @@ -80,7 +80,7 @@ abstract class AbstractVisualizerBlackBoxTest { TestRunner(firConfiguration).runTest(filePath) { testConfiguration -> testConfiguration.testServices.moduleStructure.modules.forEach { firModule -> val firArtifact = testConfiguration.testServices.dependencyProvider.getArtifact(firModule, FrontendKinds.FIR) - val firRenderer = firArtifact.firFiles.values.firstOrNull()?.let { FirVisualizer(it) } + val firRenderer = firArtifact.mainFirFiles.values.firstOrNull()?.let { FirVisualizer(it) } firRenderResult = firRenderer?.render()?.trim() ?: "" } } diff --git a/compiler/visualizer/tests/org/jetbrains/kotlin/visualizer/fir/FirOutputHandler.kt b/compiler/visualizer/tests/org/jetbrains/kotlin/visualizer/fir/FirOutputHandler.kt index 0eed7ff0ce3..fdd262419a8 100644 --- a/compiler/visualizer/tests/org/jetbrains/kotlin/visualizer/fir/FirOutputHandler.kt +++ b/compiler/visualizer/tests/org/jetbrains/kotlin/visualizer/fir/FirOutputHandler.kt @@ -15,7 +15,7 @@ import java.io.File internal class FirOutputHandler(testServices: TestServices) : FirAnalysisHandler(testServices) { override fun processModule(module: TestModule, info: FirOutputArtifact) { - val renderer = info.firFiles.values.firstOrNull()?.let { FirVisualizer(it) } ?: return + val renderer = info.mainFirFiles.values.firstOrNull()?.let { FirVisualizer(it) } ?: return val firRenderResult = renderer.render().trim() val replaceFrom = module.directives[VisualizerDirectives.TEST_FILE_PATH].first() diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/FirFrontend.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/FirFrontend.kt index 0e64a3a4cc8..bf875400534 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/FirFrontend.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/FirFrontend.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.config.AnalysisFlags import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory +import org.jetbrains.kotlin.fir.BinaryModuleData import org.jetbrains.kotlin.fir.DependencyListForCliModule import org.jetbrains.kotlin.fir.FirModuleDataImpl import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers @@ -45,7 +46,8 @@ internal fun PhaseContext.firFrontend( val syntaxErrors = ktFiles.fold(false) { errorsFound, ktFile -> AnalyzerWithCompilerReport.reportSyntaxErrors(ktFile, messageCollector).isHasErrors or errorsFound } - val dependencyList = DependencyListForCliModule.build(mainModuleName, CommonPlatforms.defaultCommonPlatform, NativePlatformAnalyzerServices) { + val binaryModuleData = BinaryModuleData.initialize(mainModuleName, CommonPlatforms.defaultCommonPlatform, NativePlatformAnalyzerServices) + val dependencyList = DependencyListForCliModule.build(binaryModuleData) { dependencies(config.resolvedLibraries.getFullList().map { it.libraryFile.absolutePath }) friendDependencies(config.friendModuleFiles.map { it.absolutePath }) // TODO: !!! dependencies module data? @@ -55,7 +57,7 @@ internal fun PhaseContext.firFrontend( mainModuleName, resolvedLibraries, sessionProvider, - dependencyList, + dependencyList.moduleDataProvider, configuration.languageVersionSettings, registerExtraComponents = {}, ) @@ -64,8 +66,8 @@ internal fun PhaseContext.firFrontend( dependencyList.regularDependencies, dependencyList.dependsOnDependencies, dependencyList.friendsDependencies, - dependencyList.platform, - dependencyList.analyzerServices + CommonPlatforms.defaultCommonPlatform, + NativePlatformAnalyzerServices ) val session = FirNativeSessionFactory.createModuleBasedSession( mainModuleData, diff --git a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/ScriptJvmCompilerImpls.kt b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/ScriptJvmCompilerImpls.kt index b5bb24e6ec0..870525835a8 100644 --- a/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/ScriptJvmCompilerImpls.kt +++ b/plugins/scripting/scripting-compiler/src/org/jetbrains/kotlin/scripting/compiler/plugin/impl/ScriptJvmCompilerImpls.kt @@ -13,11 +13,8 @@ import org.jetbrains.kotlin.cli.common.fir.FirDiagnosticsCompilerResultsReporter import org.jetbrains.kotlin.cli.common.fir.reportToMessageCollector import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport import org.jetbrains.kotlin.cli.common.messages.MessageCollector -import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.jetbrains.kotlin.cli.jvm.compiler.NoScopeRecordCliBindingTrace -import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM +import org.jetbrains.kotlin.cli.jvm.compiler.* import org.jetbrains.kotlin.cli.jvm.compiler.pipeline.* -import org.jetbrains.kotlin.cli.jvm.compiler.toAbstractProjectEnvironment import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot import org.jetbrains.kotlin.cli.jvm.config.JvmModulePathRoot import org.jetbrains.kotlin.codegen.ClassBuilderFactories @@ -29,10 +26,11 @@ import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.config.languageVersionSettings 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.java.FirProjectSessionProvider -import org.jetbrains.kotlin.fir.pipeline.buildFirFromKtFiles -import org.jetbrains.kotlin.fir.pipeline.runCheckers -import org.jetbrains.kotlin.fir.pipeline.runResolution +import org.jetbrains.kotlin.fir.pipeline.* import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil import org.jetbrains.kotlin.modules.TargetId import org.jetbrains.kotlin.platform.CommonPlatforms @@ -52,6 +50,8 @@ import kotlin.script.experimental.jvm.JvmDependencyFromClassLoader import kotlin.script.experimental.jvm.compilationCache import kotlin.script.experimental.jvm.impl.KJvmCompiledScript import kotlin.script.experimental.jvm.jvm +import org.jetbrains.kotlin.fir.session.FirJvmSessionFactory +import org.jetbrains.kotlin.name.Name class ScriptJvmCompilerIsolated(val hostConfiguration: ScriptingHostConfiguration) : ScriptCompilerProxy { @@ -349,20 +349,42 @@ private fun doCompileWithK2( val sessionProvider = FirProjectSessionProvider() val extendedAnalysisMode = kotlinCompilerConfiguration.getBoolean(CommonConfigurationKeys.USE_FIR_EXTENDED_CHECKERS) - val session = createSession( - targetId.name, - JvmPlatforms.unspecifiedJvmPlatform, - kotlinCompilerConfiguration, + var librariesScope = projectEnvironment.getSearchScopeForProjectLibraries() + val providerAndScopeForIncrementalCompilation = createContextForIncrementalCompilation( + compilerInput.configuration, projectEnvironment, sourcesScope, - JvmPlatformAnalyzerServices, + emptyList(), + null + )?.also { (_, _, precompiledBinariesFileScope) -> + precompiledBinariesFileScope?.let { librariesScope -= it } + } + val libraryList = createLibraryListAndSession(targetId.name, kotlinCompilerConfiguration, projectEnvironment, librariesScope, sessionProvider) + val moduleData = FirModuleDataImpl( + Name.identifier(targetId.name), + libraryList.regularDependencies, + listOf(), + libraryList.friendsDependencies, + JvmPlatforms.unspecifiedJvmPlatform, + JvmPlatformAnalyzerServices + ) + val session = FirJvmSessionFactory.createModuleBasedSession( + moduleData, sessionProvider, - previousStepsSymbolProviders = emptyList(), - incrementalExcludesScope = null, - extendedAnalysisMode = extendedAnalysisMode, - needRegisterJavaElementFinder = true + 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 = {}, ) { - friendDependencies(kotlinCompilerConfiguration[JVMConfigurationKeys.FRIEND_PATHS] ?: emptyList()) + if (extendedAnalysisMode) { + registerExtendedCommonCheckers() + } } session.scriptDefinitionProviderService?.run { @@ -376,7 +398,7 @@ private fun doCompileWithK2( // checkers session.runCheckers(scopeSession, fir, diagnosticsReporter) - val analysisResults = ModuleCompilerAnalyzedOutput(session, scopeSession, fir) + val analysisResults = FirResult(ModuleCompilerAnalyzedOutput(session, scopeSession, fir), null) if (diagnosticsReporter.hasErrors) { diagnosticsReporter.reportToMessageCollector(messageCollector, renderDiagnosticName)