diff --git a/benchmarks/src/org/jetbrains/kotlin/benchmarks/AbstractSimpleFileBenchmark.kt b/benchmarks/src/org/jetbrains/kotlin/benchmarks/AbstractSimpleFileBenchmark.kt index 3d954879331..ddf73f53bee 100644 --- a/benchmarks/src/org/jetbrains/kotlin/benchmarks/AbstractSimpleFileBenchmark.kt +++ b/benchmarks/src/org/jetbrains/kotlin/benchmarks/AbstractSimpleFileBenchmark.kt @@ -12,6 +12,7 @@ import com.intellij.psi.PsiFileFactory import com.intellij.psi.impl.PsiFileFactoryImpl import com.intellij.psi.search.GlobalSearchScope import com.intellij.testFramework.LightVirtualFile +import org.jetbrains.kotlin.ObsoleteTestInfrastructure import org.jetbrains.kotlin.asJava.finder.JavaElementFinder import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys @@ -147,6 +148,7 @@ abstract class AbstractSimpleFileBenchmark { bh.consume(result.shouldGenerateCode) } + @OptIn(ObsoleteTestInfrastructure::class) private fun analyzeGreenFileIr(bh: Blackhole) { val scope = GlobalSearchScope.filesScope(env.project, listOf(file.virtualFile)) .uniteWith(TopDownAnalyzerFacadeForJVM.AllJavaSourcesInProjectScope(env.project)) diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt index ff7eb3d307e..dd9b819e789 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt @@ -58,6 +58,7 @@ import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendClassResolver import org.jetbrains.kotlin.fir.backend.jvm.FirJvmBackendExtension import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers import org.jetbrains.kotlin.fir.createSessionWithDependencies +import org.jetbrains.kotlin.fir.session.FirSessionFactory import org.jetbrains.kotlin.ir.backend.jvm.jvmResolveLibraries import org.jetbrains.kotlin.javac.JavacWrapper import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityManager @@ -65,11 +66,13 @@ import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackagePartProvid import org.jetbrains.kotlin.modules.Module import org.jetbrains.kotlin.modules.TargetId import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.platform.jvm.JvmPlatforms import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.CompilerEnvironment import org.jetbrains.kotlin.resolve.diagnostics.SimpleGenericDiagnostics import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade +import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory import org.jetbrains.kotlin.utils.newLinkedHashMapWithExpectedSize import java.io.File @@ -337,24 +340,29 @@ object KotlinToJVMBytecodeCompiler { val languageVersionSettings = moduleConfiguration.languageVersionSettings val session = createSessionWithDependencies( module, + JvmPlatforms.unspecifiedJvmPlatform, + JvmPlatformAnalyzerServices, + externalSessionProvider = null, project, languageVersionSettings, sourceScope, librariesScope, lookupTracker = environment.configuration.get(CommonConfigurationKeys.LOOKUP_TRACKER), getPackagePartProvider = { environment.createPackagePartProvider(it) }, - getAdditionalModulePackagePartProvider = { - if (targetIds == null || incrementalComponents == null) null - else IncrementalPackagePartProvider( - environment.createPackagePartProvider(it), + getProviderAndScopeForIncrementalCompilation = get@{ + if (targetIds == null || incrementalComponents == null) return@get null + val packagePartProvider = IncrementalPackagePartProvider( + environment.createPackagePartProvider(sourceScope), targetIds.map(incrementalComponents::getIncrementalCache) ) + FirSessionFactory.ProviderAndScopeForIncrementalCompilation(packagePartProvider, librariesScope) + }, + sessionConfigurator = { + if (extendedAnalysisMode) { + registerExtendedCommonCheckers() + } } - ) { - if (extendedAnalysisMode) { - registerExtendedCommonCheckers() - } - } + ) val firAnalyzerFacade = FirAnalyzerFacade(session, languageVersionSettings, ktFiles) diff --git a/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/AbstractFirLoadCompiledKotlin.kt b/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/AbstractFirLoadCompiledKotlin.kt index 9e624b33396..e00a2282c7b 100644 --- a/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/AbstractFirLoadCompiledKotlin.kt +++ b/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/AbstractFirLoadCompiledKotlin.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.fir import com.intellij.psi.search.GlobalSearchScope +import org.jetbrains.kotlin.ObsoleteTestInfrastructure import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.descriptors.ModuleDescriptor @@ -30,6 +31,7 @@ abstract class AbstractFirLoadCompiledKotlin : AbstractFirLoadBinariesTest() { return createEnvironmentWithMockJdk(ConfigurationKind.JDK_NO_RUNTIME) } + @OptIn(ObsoleteTestInfrastructure::class) fun doTest(path: String) { val moduleDescriptor = compileKtFileToTmpDir(path) diff --git a/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/BuiltInsDeserializationForFirTestCase.kt b/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/BuiltInsDeserializationForFirTestCase.kt index dace2ee4a6c..d1da405cfe7 100644 --- a/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/BuiltInsDeserializationForFirTestCase.kt +++ b/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/BuiltInsDeserializationForFirTestCase.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.fir import com.intellij.psi.search.GlobalSearchScope +import org.jetbrains.kotlin.ObsoleteTestInfrastructure import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.serialization.builtins.BuiltinsTestUtils import org.jetbrains.kotlin.test.ConfigurationKind @@ -16,6 +17,7 @@ class BuiltInsDeserializationForFirTestCase : AbstractFirLoadBinariesTest() { return createEnvironmentWithJdk(ConfigurationKind.ALL, TestJdkKind.FULL_JDK) } + @OptIn(ObsoleteTestInfrastructure::class) fun testBuiltInPackagesContent() { val moduleDescriptor = BuiltinsTestUtils.compileBuiltinsModule(environment) val session = createSessionForTests(environment, GlobalSearchScope.allScope(project)) diff --git a/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/java/AbstractFirTypeEnhancementTest.kt b/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/java/AbstractFirTypeEnhancementTest.kt index d5266b091da..34a299a54d0 100644 --- a/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/java/AbstractFirTypeEnhancementTest.kt +++ b/compiler/fir/analysis-tests/legacy-fir-tests/tests/org/jetbrains/kotlin/fir/java/AbstractFirTypeEnhancementTest.kt @@ -16,6 +16,7 @@ import com.intellij.psi.PsiPackageStatement import com.intellij.psi.impl.PsiFileFactoryImpl import com.intellij.psi.search.GlobalSearchScope import com.intellij.testFramework.LightVirtualFile +import org.jetbrains.kotlin.ObsoleteTestInfrastructure import org.jetbrains.kotlin.asJava.finder.JavaElementFinder import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment @@ -82,6 +83,7 @@ abstract class AbstractFirTypeEnhancementTest : KtUsefulTestCase() { } } + @OptIn(ObsoleteTestInfrastructure::class) fun doTest(path: String) { val javaFile = File(path) val javaLines = javaFile.readLines() diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/DependencyListForCliModule.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/DependencyListForCliModule.kt new file mode 100644 index 00000000000..0c7091d1029 --- /dev/null +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/DependencyListForCliModule.kt @@ -0,0 +1,169 @@ +/* + * 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.fir + +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() + } + } + + 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() + + 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 + } + + 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) } + } + + @JvmName("dependenciesString") + fun dependencies(paths: Collection) { + paths.mapTo(filtersMap.getValue(binaryRegularDependenciesModuleData)) { Paths.get(it) } + } + + @JvmName("friendDependenciesString") + fun friendDependencies(paths: Collection) { + paths.mapTo(filtersMap.getValue(binaryFriendsModuleData)) { Paths.get(it) } + } + + @JvmName("dependsOnDependenciesString") + fun dependsOnDependencies(paths: Collection) { + paths.mapTo(filtersMap.getValue(binaryDependsOnModuleData)) { Paths.get(it) } + } + + fun dependencies(paths: Collection) { + filtersMap.getValue(binaryRegularDependenciesModuleData) += paths + } + + fun friendDependencies(paths: Collection) { + filtersMap.getValue(binaryFriendsModuleData) += paths + } + + fun dependsOnDependencies(paths: Collection) { + filtersMap.getValue(binaryDependsOnModuleData) += paths + } + + fun sourceDependencies(modules: Collection) { + allRegularDependencies += modules + } + + fun sourceFriendsDependencies(modules: Collection) { + allFriendsDependencies += modules + } + + fun sourceDependsOnDependencies(modules: Collection) { + allDependsOnDependencies += modules + } + + fun build(): DependencyListForCliModule { + val pathFiltersMap: MutableMap = filtersMap + .filterValues { it.isNotEmpty() } + .mapValues { LibraryPathFilter.LibraryList(it.value) } + .toMutableMap() + + allRegularDependencies += binaryRegularDependenciesModuleData + if (pathFiltersMap.isEmpty()) { + return DependencyListForCliModule( + platform, + analyzerServices, + allRegularDependencies, + dependsOnDependencies = allDependsOnDependencies, + friendsDependencies = allFriendsDependencies, + SingleModuleDataProvider(binaryRegularDependenciesModuleData) + ) + } + if (binaryFriendsModuleData in pathFiltersMap) { + allFriendsDependencies += binaryFriendsModuleData + } + if (binaryDependsOnModuleData in pathFiltersMap) { + allDependsOnDependencies += binaryDependsOnModuleData + } + + val moduleDataProvider = MultipleModuleDataProvider(pathFiltersMap) + pathFiltersMap.putIfAbsent(binaryRegularDependenciesModuleData, LibraryPathFilter.TakeAll) + return DependencyListForCliModule( + platform, + analyzerServices, + allRegularDependencies, + allDependsOnDependencies, + allFriendsDependencies, + moduleDataProvider + ) + } + } +} diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirSessionFactory.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirSessionFactory.kt index e062166b9f2..ce478df7e55 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirSessionFactory.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/session/FirSessionFactory.kt @@ -9,13 +9,10 @@ import com.intellij.openapi.project.Project import com.intellij.psi.PsiElementFinder import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.annotations.TestOnly -import org.jetbrains.kotlin.analyzer.ModuleInfo +import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl -import org.jetbrains.kotlin.fir.FirModuleData -import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.PrivateSessionConstructor -import org.jetbrains.kotlin.fir.SessionConfiguration +import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers import org.jetbrains.kotlin.fir.analysis.checkers.expression.ExpressionCheckers import org.jetbrains.kotlin.fir.analysis.checkers.type.TypeCheckers @@ -23,6 +20,8 @@ import org.jetbrains.kotlin.fir.analysis.checkersComponent import org.jetbrains.kotlin.fir.analysis.extensions.additionalCheckers import org.jetbrains.kotlin.fir.checkers.registerCommonCheckers import org.jetbrains.kotlin.fir.checkers.registerJvmCheckers +import org.jetbrains.kotlin.fir.deserialization.ModuleDataProvider +import org.jetbrains.kotlin.fir.deserialization.SingleModuleDataProvider import org.jetbrains.kotlin.fir.extensions.BunchOfRegisteredExtensions import org.jetbrains.kotlin.fir.extensions.extensionService import org.jetbrains.kotlin.fir.extensions.registerExtensions @@ -37,6 +36,11 @@ import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.load.java.JavaClassFinderImpl import org.jetbrains.kotlin.load.kotlin.PackagePartProvider import org.jetbrains.kotlin.load.kotlin.VirtualFileFinderFactory +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.platform.TargetPlatform +import org.jetbrains.kotlin.platform.jvm.JvmPlatforms +import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices +import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices @OptIn(PrivateSessionConstructor::class, SessionConfiguration::class) object FirSessionFactory { @@ -66,20 +70,24 @@ object FirSessionFactory { } } + data class ProviderAndScopeForIncrementalCompilation( + val packagePartProvider: PackagePartProvider, + val scope: GlobalSearchScope + ) + fun createJavaModuleBasedSession( - moduleInfo: ModuleInfo, + moduleData: FirModuleData, sessionProvider: FirProjectSessionProvider, scope: GlobalSearchScope, project: Project, - additionalPackagePartProvider: PackagePartProvider? = null, - additionalScope: GlobalSearchScope? = null, - dependenciesProvider: FirSymbolProvider? = null, + providerAndScopeForIncrementalCompilation: ProviderAndScopeForIncrementalCompilation?, languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT, lookupTracker: LookupTracker? = null, init: FirSessionConfigurator.() -> Unit = {} ): FirSession { return FirCliSession(sessionProvider, FirCliSession.Kind.Source).apply session@{ - val moduleData = FirModuleInfoBasedModuleData(moduleInfo).apply { bindSession(this@session) } + moduleData.bindSession(this@session) + sessionProvider.registerSession(moduleData, this@session) registerModuleData(moduleData) registerCliCompilerOnlyComponents() registerCommonComponents(languageVersionSettings) @@ -91,20 +99,19 @@ object FirSessionFactory { val firProvider = FirProviderImpl(this, kotlinScopeProvider) register(FirProvider::class, firProvider) - val deserializedJvmSymbolsProvider = - if (additionalPackagePartProvider == null) null - else { - val javaSymbolProvider = JavaSymbolProvider(this, moduleData, project, additionalScope ?: scope) + val symbolProviderForBinariesFromIncrementalCompilation = providerAndScopeForIncrementalCompilation?.let { + val javaSymbolProvider = JavaSymbolProvider(this, moduleData, project, it.scope) - makeDeserializedJvmSymbolsProvider( - moduleData, - project, - additionalScope ?: scope, - additionalPackagePartProvider, - javaSymbolProvider, - kotlinScopeProvider - ) - } + makeDeserializedJvmSymbolsProvider( + this@session, + SingleModuleDataProvider(moduleData), + project, + it.scope, + it.packagePartProvider, + javaSymbolProvider, + kotlinScopeProvider + ) + } register( FirSymbolProvider::class, @@ -112,11 +119,11 @@ object FirSessionFactory { this, listOfNotNull( firProvider.symbolProvider, + symbolProviderForBinariesFromIncrementalCompilation, JavaSymbolProvider(this, moduleData, project, scope), - dependenciesProvider ?: FirDependenciesSymbolProviderImpl(this), - deserializedJvmSymbolsProvider + FirDependenciesSymbolProviderImpl(this) ) - ) as FirSymbolProvider + ) ) FirSessionConfigurator(this).apply { @@ -130,34 +137,50 @@ object FirSessionFactory { } fun createLibrarySession( - moduleInfo: ModuleInfo, + mainModuleName: Name, sessionProvider: FirProjectSessionProvider, + moduleDataProvider: ModuleDataProvider, scope: GlobalSearchScope, project: Project, packagePartProvider: PackagePartProvider, languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT, ): FirSession { return FirCliSession(sessionProvider, FirCliSession.Kind.Library).apply session@{ - val moduleData = FirModuleInfoBasedModuleData(moduleInfo).apply { bindSession(this@session) } - sessionProvider.registerSession(moduleData, this) + moduleDataProvider.allModuleData.forEach { + sessionProvider.registerSession(it, this) + it.bindSession(this) + } + registerCliCompilerOnlyComponents() registerCommonComponents(languageVersionSettings) - val javaSymbolProvider = JavaSymbolProvider(this, moduleData, project, scope) + val javaSymbolProvider = JavaSymbolProvider(this, moduleDataProvider.allModuleData.last(), project, scope) val kotlinScopeProvider = FirKotlinScopeProvider(::wrapScopeWithJvmMapped) val deserializedJvmSymbolsProvider = makeDeserializedJvmSymbolsProvider( - moduleData, project, scope, packagePartProvider, javaSymbolProvider, kotlinScopeProvider + librarySession = this, + moduleDataProvider, + project, + scope, + packagePartProvider, + javaSymbolProvider, + kotlinScopeProvider ) + val builtinsModuleData = createModuleDataForBuiltins( + mainModuleName, + moduleDataProvider.platform, + moduleDataProvider.analyzerServices + ).also { it.bindSession(this@session) } + val symbolProvider = FirCompositeSymbolProvider( this, listOf( deserializedJvmSymbolsProvider, - FirBuiltinSymbolProvider(this, moduleData, kotlinScopeProvider), - FirCloneableSymbolProvider(this, moduleData, kotlinScopeProvider), - javaSymbolProvider, + FirBuiltinSymbolProvider(this, builtinsModuleData, kotlinScopeProvider), + FirCloneableSymbolProvider(this, builtinsModuleData, kotlinScopeProvider), + javaSymbolProvider, // TODO: looks like it can be removed FirDependenciesSymbolProviderImpl(this) ) ) @@ -167,7 +190,8 @@ object FirSessionFactory { } private fun makeDeserializedJvmSymbolsProvider( - moduleData: FirModuleData, + librarySession: FirSession, + moduleDataProvider: ModuleDataProvider, project: Project, scope: GlobalSearchScope, packagePartProvider: PackagePartProvider, @@ -182,12 +206,41 @@ object FirSessionFactory { } return KotlinDeserializedJvmSymbolsProvider( - moduleData, kotlinScopeProvider, packagePartProvider, kotlinClassFinder, javaSymbolProvider, javaClassFinder + librarySession, + moduleDataProvider, + kotlinScopeProvider, + packagePartProvider, + kotlinClassFinder, + javaSymbolProvider, + javaClassFinder ) } @TestOnly fun createEmptySession(): FirSession { - return object : FirSession(null) {} + return object : FirSession(null) {}.apply { + val moduleData = FirModuleDataImpl( + Name.identifier(""), + dependencies = emptyList(), + dependsOnDependencies = emptyList(), + friendDependencies = emptyList(), + platform = JvmPlatforms.unspecifiedJvmPlatform, + analyzerServices = JvmPlatformAnalyzerServices + ) + registerModuleData(moduleData) + moduleData.bindSession(this) + } + } + + fun createModuleDataForBuiltins( + parentModuleName: Name, + platform: TargetPlatform, + analyzerServices: PlatformDependentAnalyzerServices + ): FirModuleData { + return DependencyListForCliModule.createDependencyModuleData( + Name.special(", - outputDirectory: String?, + platform: TargetPlatform, + analyzerServices: PlatformDependentAnalyzerServices, + externalSessionProvider: FirProjectSessionProvider?, project: Project, languageVersionSettings: LanguageVersionSettings, sourceScope: GlobalSearchScope, librariesScope: GlobalSearchScope, lookupTracker: LookupTracker?, getPackagePartProvider: (GlobalSearchScope) -> PackagePartProvider, - getAdditionalModulePackagePartProvider: (GlobalSearchScope) -> PackagePartProvider?, - sessionConfigurator: FirSessionFactory.FirSessionConfigurator.() -> Unit = {} + getProviderAndScopeForIncrementalCompilation: () -> FirSessionFactory.ProviderAndScopeForIncrementalCompilation?, + dependenciesConfigurator: DependencyListForCliModule.Builder.() -> Unit = {}, + noinline sessionConfigurator: FirSessionFactory.FirSessionConfigurator.() -> Unit = {}, ): FirSession { - return createSessionWithDependencies( - name.identifier, + val dependencyList = DependencyListForCliModule.build(name, platform, analyzerServices, dependenciesConfigurator) + return createSessionWithDependenciesImpl( + name, + dependencyList, + externalSessionProvider, project, languageVersionSettings, sourceScope, librariesScope, lookupTracker, getPackagePartProvider, - getAdditionalModulePackagePartProvider, + getProviderAndScopeForIncrementalCompilation, sessionConfigurator - ) { - FirJvmModuleInfo(name, it, friendPaths, outputDirectory) - } + ) } -fun createSessionWithDependencies( +@OptIn(PrivateForInline::class) +inline fun createSessionWithDependencies( module: Module, + platform: TargetPlatform, + analyzerServices: PlatformDependentAnalyzerServices, + externalSessionProvider: FirProjectSessionProvider?, project: Project, languageVersionSettings: LanguageVersionSettings, sourceScope: GlobalSearchScope, librariesScope: GlobalSearchScope, lookupTracker: LookupTracker?, getPackagePartProvider: (GlobalSearchScope) -> PackagePartProvider, - getAdditionalModulePackagePartProvider: (GlobalSearchScope) -> PackagePartProvider?, - sessionConfigurator: FirSessionFactory.FirSessionConfigurator.() -> Unit = {} + getProviderAndScopeForIncrementalCompilation: () -> FirSessionFactory.ProviderAndScopeForIncrementalCompilation?, + noinline sessionConfigurator: FirSessionFactory.FirSessionConfigurator.() -> Unit = {}, ): FirSession { - return createSessionWithDependencies( - module.getModuleName(), + val moduleName = Name.identifier(module.getModuleName()) + val dependencyList = DependencyListForCliModule.build( + moduleName, + platform, + analyzerServices + ) { + friendDependencies(module.getFriendPaths()) + dependencies(module.getClasspathRoots()) + } + return createSessionWithDependenciesImpl( + moduleName, + dependencyList, + externalSessionProvider, project, languageVersionSettings, sourceScope, librariesScope, lookupTracker, getPackagePartProvider, - getAdditionalModulePackagePartProvider, + getProviderAndScopeForIncrementalCompilation, sessionConfigurator - ) { - FirJvmModuleInfo(module, it) - } + ) } -private inline fun createSessionWithDependencies( - moduleName: String, +@PrivateForInline +inline fun createSessionWithDependenciesImpl( + moduleName: Name, + dependencyListForCliModule: DependencyListForCliModule, + externalSessionProvider: FirProjectSessionProvider?, project: Project, languageVersionSettings: LanguageVersionSettings, sourceScope: GlobalSearchScope, librariesScope: GlobalSearchScope, lookupTracker: LookupTracker?, getPackagePartProvider: (GlobalSearchScope) -> PackagePartProvider, - getAdditionalModulePackagePartProvider: (GlobalSearchScope) -> PackagePartProvider?, + getProviderAndScopeForIncrementalCompilation: () -> FirSessionFactory.ProviderAndScopeForIncrementalCompilation?, noinline sessionConfigurator: FirSessionFactory.FirSessionConfigurator.() -> Unit, - moduleInfoProvider: (dependencies: List) -> ModuleInfo, ): FirSession { - val provider = FirProjectSessionProvider() - val librariesModuleInfo = FirJvmModuleInfo.createForLibraries(moduleName) + val sessionProvider = externalSessionProvider ?: FirProjectSessionProvider() FirSessionFactory.createLibrarySession( - librariesModuleInfo, provider, librariesScope, - project, getPackagePartProvider(librariesScope) + moduleName, + sessionProvider, + dependencyListForCliModule.moduleDataProvider, + librariesScope, + project, + getPackagePartProvider(librariesScope) + ) + + val mainModuleData = FirModuleDataImpl( + moduleName, + dependencyListForCliModule.regularDependencies, + dependencyListForCliModule.dependsOnDependencies, + dependencyListForCliModule.friendsDependencies, + dependencyListForCliModule.platform, + dependencyListForCliModule.analyzerServices ) return FirSessionFactory.createJavaModuleBasedSession( - moduleInfoProvider(listOf(librariesModuleInfo)), - provider, + mainModuleData, + sessionProvider, sourceScope, project, - additionalPackagePartProvider = getAdditionalModulePackagePartProvider(sourceScope), - additionalScope = librariesScope, + providerAndScopeForIncrementalCompilation = getProviderAndScopeForIncrementalCompilation(), languageVersionSettings = languageVersionSettings, lookupTracker = lookupTracker, init = sessionConfigurator diff --git a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/AbstractFirDeserializedSymbolsProvider.kt b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/AbstractFirDeserializedSymbolsProvider.kt index 18641766db6..58154e61519 100644 --- a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/AbstractFirDeserializedSymbolsProvider.kt +++ b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/AbstractFirDeserializedSymbolsProvider.kt @@ -6,7 +6,7 @@ package org.jetbrains.kotlin.fir.deserialization import com.intellij.openapi.progress.ProcessCanceledException -import org.jetbrains.kotlin.fir.FirModuleData +import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.caches.* import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProviderInternals @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.metadata.deserialization.NameResolver import org.jetbrains.kotlin.name.* import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import org.jetbrains.kotlin.serialization.deserialization.getName +import java.nio.file.Path class PackagePartsCacheData( val proto: ProtoBuf.Package, @@ -36,13 +37,30 @@ class PackagePartsCacheData( } } +abstract class LibraryPathFilter { + abstract fun accepts(path: Path?): Boolean + + object TakeAll : LibraryPathFilter() { + override fun accepts(path: Path?): Boolean { + return true + } + } + + class LibraryList(val libs: Set) : LibraryPathFilter() { + override fun accepts(path: Path?): Boolean { + if (path == null) return false + return libs.any { path.startsWith(it) } + } + } +} + typealias DeserializedClassPostProcessor = (FirRegularClassSymbol) -> Unit abstract class AbstractFirDeserializedSymbolsProvider( - val moduleData: FirModuleData, - val kotlinScopeProvider: FirKotlinScopeProvider -) : FirSymbolProvider(moduleData.session) { - + session: FirSession, + val moduleDataProvider: ModuleDataProvider, + val kotlinScopeProvider: FirKotlinScopeProvider, +) : FirSymbolProvider(session) { // ------------------------ Caches ------------------------ private val packagePartsCache = session.firCachesFactory.createCache(::tryComputePackagePartInfos) @@ -75,6 +93,7 @@ abstract class AbstractFirDeserializedSymbolsProvider( val nameResolver: NameResolver, val classProto: ProtoBuf.Class, val annotationDeserializer: AbstractAnnotationDeserializer, + val containingLibraryPath: Path?, val sourceElement: DeserializedContainerSource, val classPostProcessor: DeserializedClassPostProcessor ) : ClassMetadataFindResult() @@ -107,7 +126,8 @@ abstract class AbstractFirDeserializedSymbolsProvider( ): Pair { return when (val result = extractClassMetadata(classId, parentContext)) { is ClassMetadataFindResult.Metadata -> { - val (nameResolver, classProto, annotationDeserializer, sourceElement, postProcessor) = result + val (nameResolver, classProto, annotationDeserializer, containingLibrary, sourceElement, postProcessor) = result + val moduleData = moduleDataProvider.getModuleData(containingLibrary) ?: return null to null val symbol = FirRegularClassSymbol(classId) deserializeClassToSymbol( classId, @@ -158,6 +178,20 @@ abstract class AbstractFirDeserializedSymbolsProvider( return packagePartsCache.getValue(packageFqName) } + private fun getClass( + classId: ClassId, + parentContext: FirDeserializationContext? = null + ): FirRegularClassSymbol? { + return classCache.getValue(classId, parentContext) + } + + private fun getTypeAlias( + classId: ClassId, + ): FirTypeAliasSymbol? { + if (!classId.relativeClassName.isOneSegmentFQN()) return null + return typeAliasCache.getValue(classId) + } + // ------------------------ SymbolProvider methods ------------------------ @FirSymbolProviderInternals @@ -181,19 +215,5 @@ abstract class AbstractFirDeserializedSymbolsProvider( return getClass(classId) ?: getTypeAlias(classId) } - private fun getClass( - classId: ClassId, - parentContext: FirDeserializationContext? = null - ): FirRegularClassSymbol? { - return classCache.getValue(classId, parentContext) - } - - private fun getTypeAlias( - classId: ClassId, - ): FirTypeAliasSymbol? { - if (!classId.relativeClassName.isOneSegmentFQN()) return null - return typeAliasCache.getValue(classId) - } - override fun getPackage(fqName: FqName): FqName? = null } diff --git a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ModuleDataProvider.kt b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ModuleDataProvider.kt new file mode 100644 index 00000000000..4ce319c2dc2 --- /dev/null +++ b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/ModuleDataProvider.kt @@ -0,0 +1,57 @@ +/* + * 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.fir.deserialization + +import org.jetbrains.kotlin.fir.FirModuleData +import org.jetbrains.kotlin.platform.TargetPlatform +import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices +import org.jetbrains.kotlin.utils.addToStdlib.same +import java.nio.file.Path + +abstract class ModuleDataProvider { + abstract val platform: TargetPlatform + abstract val analyzerServices: PlatformDependentAnalyzerServices + abstract val allModuleData: Collection + + abstract fun getModuleData(path: Path?): FirModuleData? +} + +class SingleModuleDataProvider(private val moduleData: FirModuleData) : ModuleDataProvider() { + override val platform: TargetPlatform + get() = moduleData.platform + override val analyzerServices: PlatformDependentAnalyzerServices + get() = moduleData.analyzerServices + override val allModuleData: Collection + get() = listOf(moduleData) + + override fun getModuleData(path: Path?): FirModuleData { + return moduleData + } +} + +class MultipleModuleDataProvider(private val moduleDataWithFilters: Map) : ModuleDataProvider() { + init { + require(moduleDataWithFilters.isNotEmpty()) { "ModuleDataProvider must contain at least one module data" } + require(moduleDataWithFilters.keys.same { it.platform }) { "All module data should have same target platform" } + require(moduleDataWithFilters.keys.same { it.analyzerServices }) { "All module data should have same analyzerServices" } + } + + override val platform: TargetPlatform = allModuleData.first().platform + + override val analyzerServices: PlatformDependentAnalyzerServices = allModuleData.first().analyzerServices + + override val allModuleData: Collection + get() = moduleDataWithFilters.keys + + override fun getModuleData(path: Path?): FirModuleData? { + for ((session, filter) in moduleDataWithFilters.entries) { + if (filter.accepts(path)) { + return session + } + } + return null + } +} diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/KotlinDeserializedJvmSymbolsProvider.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/KotlinDeserializedJvmSymbolsProvider.kt index 5946d5971c1..4e9d31e5a0e 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/KotlinDeserializedJvmSymbolsProvider.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/KotlinDeserializedJvmSymbolsProvider.kt @@ -7,7 +7,6 @@ package org.jetbrains.kotlin.fir.java.deserialization import com.intellij.openapi.progress.ProcessCanceledException import org.jetbrains.kotlin.descriptors.SourceElement -import org.jetbrains.kotlin.fir.FirModuleData import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.ThreadSafeMutableState import org.jetbrains.kotlin.fir.caches.* @@ -35,13 +34,14 @@ import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErr @ThreadSafeMutableState class KotlinDeserializedJvmSymbolsProvider( - moduleData: FirModuleData, + session: FirSession, + moduleDataProvider: ModuleDataProvider, kotlinScopeProvider: FirKotlinScopeProvider, private val packagePartProvider: PackagePartProvider, private val kotlinClassFinder: KotlinClassFinder, private val javaSymbolProvider: JavaSymbolProvider, javaClassFinder: JavaClassFinder, -) : AbstractFirDeserializedSymbolsProvider(moduleData, kotlinScopeProvider) { +) : AbstractFirDeserializedSymbolsProvider(session, moduleDataProvider, kotlinScopeProvider) { private val knownNameInPackageCache = KnownNameInPackageCache(session, javaClassFinder) private val annotationsLoader = AnnotationsLoader(session) @@ -56,6 +56,8 @@ class KotlinDeserializedJvmSymbolsProvider( val facadeFqName = facadeName?.let { JvmClassName.byInternalName(it).fqNameForTopLevelClassMaybeWithDollars } val facadeBinaryClass = facadeFqName?.let { kotlinClassFinder.findKotlinClass(ClassId.topLevel(it)) } + val moduleData = moduleDataProvider.getModuleData(kotlinJvmBinaryClass.containingLibrary) ?: return@mapNotNull null + val header = kotlinJvmBinaryClass.classHeader val data = header.data ?: header.incompatibleData ?: return@mapNotNull null val strings = header.strings ?: return@mapNotNull null @@ -113,6 +115,7 @@ class KotlinDeserializedJvmSymbolsProvider( nameResolver, classProto, JvmBinaryAnnotationDeserializer(session, kotlinClass.kotlinJvmBinaryClass, kotlinClassFinder, kotlinClass.byteContent), + kotlinClass.kotlinJvmBinaryClass.containingLibrary, KotlinJvmBinarySourceElement(kotlinClass.kotlinJvmBinaryClass), classPostProcessor = { loadAnnotationsFromClassFile(kotlinClass, it) } ) diff --git a/compiler/fir/modularized-tests/tests/org/jetbrains/kotlin/fir/FirResolveModularizedTotalKotlinTest.kt b/compiler/fir/modularized-tests/tests/org/jetbrains/kotlin/fir/FirResolveModularizedTotalKotlinTest.kt index 161f58fda80..fa8e42cb957 100644 --- a/compiler/fir/modularized-tests/tests/org/jetbrains/kotlin/fir/FirResolveModularizedTotalKotlinTest.kt +++ b/compiler/fir/modularized-tests/tests/org/jetbrains/kotlin/fir/FirResolveModularizedTotalKotlinTest.kt @@ -12,6 +12,7 @@ import com.intellij.psi.search.ProjectScope import com.sun.jna.Library import com.sun.jna.Native import com.sun.management.HotSpotDiagnosticMXBean +import org.jetbrains.kotlin.ObsoleteTestInfrastructure import org.jetbrains.kotlin.asJava.finder.JavaElementFinder import org.jetbrains.kotlin.cli.common.profiling.AsyncProfilerHelper import org.jetbrains.kotlin.cli.common.toBooleanLenient @@ -149,6 +150,7 @@ class FirResolveModularizedTotalKotlinTest : AbstractModularizedTest() { } } + @OptIn(ObsoleteTestInfrastructure::class) private fun runAnalysis(moduleData: ModuleData, environment: KotlinCoreEnvironment) { val project = environment.project val ktFiles = environment.getSourceFiles() @@ -161,7 +163,7 @@ class FirResolveModularizedTotalKotlinTest : AbstractModularizedTest() { scope, librariesScope, moduleData.qualifiedName, - moduleData.friendDirs.map { it.canonicalPath } + moduleData.friendDirs.map { it.toPath() } ) val scopeSession = ScopeSession() val processors = createAllCompilerResolveProcessors(session, scopeSession).let { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirDependenciesSymbolProviderImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirDependenciesSymbolProviderImpl.kt index 4cc8d43c9f3..73821a34c8c 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirDependenciesSymbolProviderImpl.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirDependenciesSymbolProviderImpl.kt @@ -30,7 +30,7 @@ open class FirDependenciesSymbolProviderImpl(session: FirSession) : FirSymbolPro protected open val dependencyProviders by lazy { val moduleData = session.nullableModuleData ?: return@lazy emptyList() - moduleData.dependencies.mapNotNull { + (moduleData.dependencies + moduleData.friendDependencies + moduleData.dependsOnDependencies).mapNotNull { session.sessionProvider?.getSession(it)?.symbolProvider } } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirModuleData.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirModuleData.kt index a6e5c8ab533..c73f5be0615 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirModuleData.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirModuleData.kt @@ -22,11 +22,11 @@ abstract class FirModuleData : FirSessionComponent { private var _session: FirSession? = null val session: FirSession - get() = _session!! + get() = _session ?: error("module data not bound to session") fun bindSession(session: FirSession) { if (_session != null) { - error("session already bound to $this") + error("module data already bound to $this") } _session = session } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/VirtualFileKotlinClass.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/VirtualFileKotlinClass.kt index 8e500be9ea7..9e194392729 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/VirtualFileKotlinClass.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/kotlin/VirtualFileKotlinClass.kt @@ -26,6 +26,8 @@ import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.util.PerformanceCounter import java.io.FileNotFoundException import java.io.IOException +import java.nio.file.Path +import java.nio.file.Paths class VirtualFileKotlinClass private constructor( val file: VirtualFile, @@ -38,6 +40,9 @@ class VirtualFileKotlinClass private constructor( override val location: String get() = file.path + override val containingLibrary: Path? + get() = file.path.split("!/").firstOrNull()?.let { Paths.get(it) } + override fun getFileContents(): ByteArray { try { return file.contentsToByteArray() @@ -61,7 +66,7 @@ class VirtualFileKotlinClass private constructor( try { val byteContent = fileContent ?: file.contentsToByteArray(false) if (byteContent.isNotEmpty()) { - val kotlinJvmBinaryClass = FileBasedKotlinClass.create(byteContent) { name, classVersion, header, innerClasses -> + val kotlinJvmBinaryClass = create(byteContent) { name, classVersion, header, innerClasses -> VirtualFileKotlinClass(file, name, classVersion, header, innerClasses) } diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/ObsoleteTestInfrastructure.kt b/compiler/test-infrastructure-utils/tests/org/jetbrains/kotlin/ObsoleteTestInfrastructure.kt similarity index 100% rename from compiler/tests-common/tests/org/jetbrains/kotlin/ObsoleteTestInfrastructure.kt rename to compiler/test-infrastructure-utils/tests/org/jetbrains/kotlin/ObsoleteTestInfrastructure.kt 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 c34c5872392..99d5b2c94ea 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,19 +5,29 @@ package org.jetbrains.kotlin.test.frontend.fir -import com.intellij.openapi.project.Project import com.intellij.psi.PsiElementFinder -import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.ProjectScope +import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices import org.jetbrains.kotlin.asJava.finder.JavaElementFinder -import org.jetbrains.kotlin.cli.jvm.compiler.JvmPackagePartProvider import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM +import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots +import org.jetbrains.kotlin.cli.jvm.config.jvmModularRoots +import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.fir.analysis.FirAnalyzerFacade import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers -import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider -import org.jetbrains.kotlin.fir.session.FirJvmModuleInfo -import org.jetbrains.kotlin.fir.session.FirSessionFactory +import org.jetbrains.kotlin.fir.createSessionWithDependencies +import org.jetbrains.kotlin.fir.moduleData +import org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.platform.TargetPlatform +import org.jetbrains.kotlin.platform.isCommon +import org.jetbrains.kotlin.platform.js.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.directives.FirDiagnosticsDirectives import org.jetbrains.kotlin.test.directives.model.DirectivesContainer import org.jetbrains.kotlin.test.model.* @@ -48,28 +58,43 @@ class FirFrontendFacade( testServices.sourceFileProvider.getKtFilesForSourceFiles(module.files, project).values to emptyList() } - val sessionProvider = moduleInfoProvider.firSessionProvider - val languageVersionSettings = module.languageVersionSettings - val builtinsModuleInfo = moduleInfoProvider.builtinsModuleInfoForModule(module) val packagePartProviderFactory = compilerConfigurationProvider.getPackagePartProviderFactory(module) - createSessionForBuiltins(builtinsModuleInfo, sessionProvider, project, packagePartProviderFactory) - createSessionForBinaryDependencies(module, sessionProvider, project, packagePartProviderFactory) + val configuration = compilerConfigurationProvider.getCompilerConfiguration(module) + val librariesScope = ProjectScope.getLibrariesScope(project) val sourcesScope = TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, ktFiles) - val sourcesModuleInfo = moduleInfoProvider.convertToFirModuleInfo(module) - val session = FirSessionFactory.createJavaModuleBasedSession( - sourcesModuleInfo, - sessionProvider, - sourcesScope, + + val session = createSessionWithDependencies( + Name.identifier(module.name), + module.targetPlatform, + module.targetPlatform.getAnalyzerServices(), + moduleInfoProvider.firSessionProvider, project, - languageVersionSettings = languageVersionSettings - ) { - if (FirDiagnosticsDirectives.WITH_EXTENDED_CHECKERS in module.directives) { - registerExtendedCommonCheckers() + languageVersionSettings, + sourcesScope, + librariesScope, + lookupTracker = null, + getPackagePartProvider = packagePartProviderFactory, + getProviderAndScopeForIncrementalCompilation = { null }, + dependenciesConfigurator = { + dependencies(configuration.jvmModularRoots.map { it.toPath() }) + dependencies(configuration.jvmClasspathRoots.map { it.toPath() }) + + friendDependencies(configuration[JVMConfigurationKeys.FRIEND_PATHS] ?: emptyList()) + + sourceDependencies(moduleInfoProvider.getDependentSourceModules(module)) + sourceFriendsDependencies(moduleInfoProvider.getDependentFriendSourceModules(module)) + }, + sessionConfigurator = { + if (FirDiagnosticsDirectives.WITH_EXTENDED_CHECKERS in module.directives) { + registerExtendedCommonCheckers() + } } - } + ) + + moduleInfoProvider.registerModuleData(module, session.moduleData) val firAnalyzerFacade = FirAnalyzerFacade(session, languageVersionSettings, ktFiles, originalFiles, lightTreeEnabled) val firFiles = firAnalyzerFacade.runResolution() @@ -81,35 +106,13 @@ class FirFrontendFacade( return FirOutputArtifactImpl(session, filesMap, firAnalyzerFacade) } - private fun createSessionForBuiltins( - builtinsModuleInfo: FirJvmModuleInfo, - sessionProvider: FirProjectSessionProvider, - project: Project, - packagePartProviderFactory: (GlobalSearchScope) -> JvmPackagePartProvider, - ) { - //For BuiltIns, registered in sessionProvider automatically - val allProjectScope = GlobalSearchScope.allScope(project) - - FirSessionFactory.createLibrarySession( - builtinsModuleInfo, sessionProvider, allProjectScope, project, - packagePartProviderFactory(allProjectScope) - ) - } - - private fun createSessionForBinaryDependencies( - module: TestModule, - sessionProvider: FirProjectSessionProvider, - project: Project, - packagePartProviderFactory: (GlobalSearchScope) -> JvmPackagePartProvider, - ) { - val librariesScope = ProjectScope.getLibrariesScope(project) - val librariesModuleInfo = FirJvmModuleInfo.createForLibraries(module.name) - FirSessionFactory.createLibrarySession( - librariesModuleInfo, - sessionProvider, - librariesScope, - project, - packagePartProviderFactory(librariesScope) - ) + private 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 9cb6a93521f..00e3fb4f59c 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 @@ -5,36 +5,40 @@ package org.jetbrains.kotlin.test.frontend.fir +import org.jetbrains.kotlin.fir.FirModuleData import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider -import org.jetbrains.kotlin.fir.session.FirJvmModuleInfo -import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.test.model.DependencyDescription import org.jetbrains.kotlin.test.model.DependencyKind +import org.jetbrains.kotlin.test.model.TestModule import org.jetbrains.kotlin.test.services.TestService import org.jetbrains.kotlin.test.services.TestServices import org.jetbrains.kotlin.test.services.dependencyProvider -import org.jetbrains.kotlin.test.model.TestModule -class FirModuleInfoProvider( - private val testServices: TestServices -) : TestService { +class FirModuleInfoProvider(private val testServices: TestServices) : TestService { val firSessionProvider = FirProjectSessionProvider() - private val builtinsByModule: MutableMap = mutableMapOf() - private val firModuleInfoByModule: MutableMap = mutableMapOf() + private val firModuleDataByModule: MutableMap = mutableMapOf() - fun convertToFirModuleInfo(module: TestModule): FirJvmModuleInfo { - return firModuleInfoByModule.getOrPut(module) { - val dependencies = mutableListOf(builtinsModuleInfoForModule(module)) - module.dependencies.filter { it.kind == DependencyKind.Source }.mapTo(dependencies) { - convertToFirModuleInfo(testServices.dependencyProvider.getTestModule(it.moduleName)) - } - FirJvmModuleInfo(Name.identifier(module.name), dependencies) - } + fun registerModuleData(module: TestModule, moduleData: FirModuleData) { + if (module in firModuleDataByModule) error("module data for module $module already registered") + firModuleDataByModule[module] = moduleData } - fun builtinsModuleInfoForModule(module: TestModule): FirJvmModuleInfo { - return builtinsByModule.getOrPut(module) { - FirJvmModuleInfo(Name.special("")) + fun getCorrespondingModuleData(module: TestModule): FirModuleData { + return firModuleDataByModule[module] ?: error("module data for module $module is not registered") + } + + fun getDependentSourceModules(module: TestModule): List { + return getDependentModulesImpl(module.dependencies) + } + + fun getDependentFriendSourceModules(module: TestModule): List { + return getDependentModulesImpl(module.friends) + } + + private fun getDependentModulesImpl(dependencies: List): List { + return dependencies.filter { it.kind == DependencyKind.Source }.map { + getCorrespondingModuleData(testServices.dependencyProvider.getTestModule(it.moduleName)) } } } diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.kt index 62265d9bc9f..785d048eb33 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.kt @@ -8,16 +8,13 @@ package org.jetbrains.kotlin.checkers import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.text.StringUtil import com.intellij.psi.PsiElement -import com.intellij.psi.PsiElementFinder import com.intellij.psi.search.GlobalSearchScope -import com.intellij.rt.execution.junit.FileComparisonFailure import junit.framework.AssertionFailedError import junit.framework.TestCase import org.jetbrains.kotlin.ObsoleteTestInfrastructure import org.jetbrains.kotlin.TestsCompilerError import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.analyzer.common.CommonResolverForModuleFactory -import org.jetbrains.kotlin.asJava.finder.JavaElementFinder import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport import org.jetbrains.kotlin.cli.common.messages.GroupingMessageCollector @@ -41,8 +38,6 @@ import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.DiagnosticFactory import org.jetbrains.kotlin.diagnostics.DiagnosticUtils import org.jetbrains.kotlin.diagnostics.Errors.* -import org.jetbrains.kotlin.fir.AbstractFirOldFrontendDiagnosticsTest -import org.jetbrains.kotlin.fir.loadTestDataWithoutDiagnostics import org.jetbrains.kotlin.frontend.java.di.createContainerForLazyResolveWithJava import org.jetbrains.kotlin.frontend.java.di.initJvmBuiltInsForTopDownAnalysis import org.jetbrains.kotlin.incremental.components.ExpectActualTracker diff --git a/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/codegen/GenerationUtils.kt b/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/codegen/GenerationUtils.kt index 5aef406b700..323c9159446 100644 --- a/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/codegen/GenerationUtils.kt +++ b/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/codegen/GenerationUtils.kt @@ -9,6 +9,7 @@ import com.intellij.openapi.project.Project import com.intellij.psi.PsiElementFinder import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.ProjectScope +import org.jetbrains.kotlin.ObsoleteTestInfrastructure import org.jetbrains.kotlin.TestsCompiletimeError import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.asJava.finder.JavaElementFinder @@ -91,6 +92,7 @@ object GenerationUtils { return state } + @OptIn(ObsoleteTestInfrastructure::class) private fun compileFilesUsingFrontendIR( project: Project, files: List, diff --git a/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/SessionTestUtils.kt b/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/SessionTestUtils.kt index e60569c2b50..35ea55df57b 100644 --- a/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/SessionTestUtils.kt +++ b/compiler/tests-compiler-utils/tests/org/jetbrains/kotlin/fir/SessionTestUtils.kt @@ -7,50 +7,55 @@ package org.jetbrains.kotlin.fir import com.intellij.openapi.project.Project import com.intellij.psi.search.GlobalSearchScope +import org.jetbrains.kotlin.ObsoleteTestInfrastructure import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl -import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.load.kotlin.PackagePartProvider import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.platform.jvm.JvmPlatforms +import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices +import java.nio.file.Path +@ObsoleteTestInfrastructure fun createSessionForTests( environment: KotlinCoreEnvironment, sourceScope: GlobalSearchScope, librariesScope: GlobalSearchScope = GlobalSearchScope.notScope(sourceScope), moduleName: String = "TestModule", - friendPaths: List = emptyList(), - lookupTracker: LookupTracker? = null + friendsPaths: List = emptyList(), ): FirSession = createSessionForTests( environment.project, sourceScope, librariesScope, moduleName, - friendPaths, - lookupTracker, + friendsPaths, environment::createPackagePartProvider ) +@ObsoleteTestInfrastructure fun createSessionForTests( project: Project, sourceScope: GlobalSearchScope, librariesScope: GlobalSearchScope, moduleName: String = "TestModule", - friendPaths: List = emptyList(), - lookupTracker: LookupTracker? = null, + friendsPaths: List = emptyList(), getPackagePartProvider: (GlobalSearchScope) -> PackagePartProvider, - getAdditionalModulePackagePartProvider: (GlobalSearchScope) -> PackagePartProvider? = { null } ): FirSession { return createSessionWithDependencies( Name.identifier(moduleName), - friendPaths, - outputDirectory = null, + JvmPlatforms.unspecifiedJvmPlatform, + JvmPlatformAnalyzerServices, + externalSessionProvider = null, project, languageVersionSettings = LanguageVersionSettingsImpl.DEFAULT, sourceScope, librariesScope, - lookupTracker, + lookupTracker = null, getPackagePartProvider, - getAdditionalModulePackagePartProvider + getProviderAndScopeForIncrementalCompilation = { null }, + dependenciesConfigurator = { + friendDependencies(friendsPaths) + } ) } diff --git a/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmBinaryClass.kt b/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmBinaryClass.kt index 229b4fc632f..ec0bce7d816 100644 --- a/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmBinaryClass.kt +++ b/core/deserialization.common.jvm/src/org/jetbrains/kotlin/load/kotlin/KotlinJvmBinaryClass.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.constants.ClassLiteralValue +import java.nio.file.Path interface KotlinJvmBinaryClass { val classId: ClassId @@ -19,6 +20,9 @@ interface KotlinJvmBinaryClass { */ val location: String + val containingLibrary: Path? + get() = null + fun loadClassAnnotations(visitor: AnnotationVisitor, cachedContents: ByteArray?) fun visitMembers(visitor: MemberVisitor, cachedContents: ByteArray?) diff --git a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt index dcbcd68fc7a..57c8b4d12d3 100644 --- a/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt +++ b/idea/idea-frontend-fir/idea-fir-low-level-api/src/org/jetbrains/kotlin/idea/fir/low/level/api/sessions/FirIdeSessionFactory.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.backend.jvm.FirJvmTypeMapper import org.jetbrains.kotlin.fir.caches.FirCachesFactory import org.jetbrains.kotlin.fir.checkers.registerExtendedCommonCheckers import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProvider +import org.jetbrains.kotlin.fir.deserialization.SingleModuleDataProvider import org.jetbrains.kotlin.fir.java.JavaSymbolProvider import org.jetbrains.kotlin.fir.java.deserialization.KotlinDeserializedJvmSymbolsProvider import org.jetbrains.kotlin.fir.resolve.providers.FirProvider @@ -191,7 +192,8 @@ internal object FirIdeSessionFactory { add( FirThreadSafeSymbolProviderWrapper( KotlinDeserializedJvmSymbolsProvider( - moduleData, + this@session, + SingleModuleDataProvider(moduleData), kotlinScopeProvider, packagePartProvider, kotlinClassFinder,