diff --git a/analysis/analysis-api-standalone/analysis-api-standalone-base/src/org/jetbrains/kotlin/analysis/api/standalone/base/project/structure/KtStaticModuleProvider.kt b/analysis/analysis-api-standalone/analysis-api-standalone-base/src/org/jetbrains/kotlin/analysis/api/standalone/base/project/structure/KtStaticModuleProvider.kt index 3778ed7eb27..617b17ba20f 100644 --- a/analysis/analysis-api-standalone/analysis-api-standalone-base/src/org/jetbrains/kotlin/analysis/api/standalone/base/project/structure/KtStaticModuleProvider.kt +++ b/analysis/analysis-api-standalone/analysis-api-standalone-base/src/org/jetbrains/kotlin/analysis/api/standalone/base/project/structure/KtStaticModuleProvider.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.analysis.api.standalone.base.project.structure import com.intellij.psi.PsiElement +import com.intellij.psi.PsiFileSystemItem import org.jetbrains.kotlin.analysis.project.structure.* import org.jetbrains.kotlin.psi.psiUtil.contains import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol @@ -14,10 +15,7 @@ import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments class KtStaticModuleProvider( private val builtinsModule: KtBuiltinsModule, private val projectStructure: KtModuleProjectStructure, -) : ProjectStructureProvider() { - val allModules: List - get() = projectStructure.allKtModules() - +) : KtStaticProjectStructureProvider() { @OptIn(KtModuleStructureInternals::class) override fun getModule(element: PsiElement, contextualModule: KtModule?): KtModule { val containingFileAsPsiFile = element.containingFile @@ -38,7 +36,11 @@ class KtStaticModuleProvider( ?: throw KotlinExceptionWithAttachments("Cannot find KtModule; see the attachment for more details.") .withAttachment( containingFileAsVirtualFile.path, - allModules.joinToString(separator = System.lineSeparator()) { it.asDebugString() } + allKtModules.joinToString(separator = System.lineSeparator()) { it.asDebugString() } ) } + + override val allKtModules: List = projectStructure.allKtModules() + + override val allSourceFiles: List = projectStructure.allSourceFiles() } \ No newline at end of file diff --git a/analysis/analysis-api-standalone/analysis-api-standalone-base/src/org/jetbrains/kotlin/analysis/api/standalone/base/project/structure/KtStaticProjectStructureProvider.kt b/analysis/analysis-api-standalone/analysis-api-standalone-base/src/org/jetbrains/kotlin/analysis/api/standalone/base/project/structure/KtStaticProjectStructureProvider.kt new file mode 100644 index 00000000000..4235e5d96e3 --- /dev/null +++ b/analysis/analysis-api-standalone/analysis-api-standalone-base/src/org/jetbrains/kotlin/analysis/api/standalone/base/project/structure/KtStaticProjectStructureProvider.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.analysis.api.standalone.base.project.structure + +import com.intellij.psi.PsiFileSystemItem +import org.jetbrains.kotlin.analysis.project.structure.KtModule +import org.jetbrains.kotlin.analysis.project.structure.KtNotUnderContentRootModule +import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider + +/** + * A [ProjectStructureProvider] with a static module structure. + * + * Static project structure providers may still create [KtNotUnderContentRootModule]s on the fly, because files which don't belong to any + * of the pre-registered modules are by definition not part of the *static* module structure. + */ +public abstract class KtStaticProjectStructureProvider : ProjectStructureProvider() { + /** + * All [KtModule]s registered with the project structure provider, excluding [KtNotUnderContentRootModule]s and the built-ins module. + * + * [allKtModules] may be used by other services to pre-build caches based on the full module structure. + */ + public abstract val allKtModules: List + + public abstract val allSourceFiles: List +} diff --git a/analysis/analysis-api-standalone/analysis-api-standalone-base/src/org/jetbrains/kotlin/analysis/api/standalone/base/project/structure/StandaloneProjectFactory.kt b/analysis/analysis-api-standalone/analysis-api-standalone-base/src/org/jetbrains/kotlin/analysis/api/standalone/base/project/structure/StandaloneProjectFactory.kt index c667c1a2aa0..2c2560b3acd 100644 --- a/analysis/analysis-api-standalone/analysis-api-standalone-base/src/org/jetbrains/kotlin/analysis/api/standalone/base/project/structure/StandaloneProjectFactory.kt +++ b/analysis/analysis-api-standalone/analysis-api-standalone-base/src/org/jetbrains/kotlin/analysis/api/standalone/base/project/structure/StandaloneProjectFactory.kt @@ -162,9 +162,7 @@ object StandaloneProjectFactory { fun registerServicesForProjectEnvironment( environment: KotlinCoreProjectEnvironment, - projectStructureProvider: ProjectStructureProvider, - modules: List, - sourceFiles: List, + projectStructureProvider: KtStaticProjectStructureProvider, languageVersionSettings: LanguageVersionSettings = latestLanguageVersionSettings, jdkHome: Path? = null, ) { @@ -181,7 +179,13 @@ object StandaloneProjectFactory { } project.registerService(ProjectStructureProvider::class.java, projectStructureProvider) - initialiseVirtualFileFinderServices(environment, modules, sourceFiles, languageVersionSettings, jdkHome) + initialiseVirtualFileFinderServices( + environment, + projectStructureProvider.allKtModules, + projectStructureProvider.allSourceFiles, + languageVersionSettings, + jdkHome, + ) } private fun initialiseVirtualFileFinderServices( diff --git a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/api/standalone/StandaloneAnalysisAPISessionBuilder.kt b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/api/standalone/StandaloneAnalysisAPISessionBuilder.kt index 4a4c098ac18..20b66229e66 100644 --- a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/api/standalone/StandaloneAnalysisAPISessionBuilder.kt +++ b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/api/standalone/StandaloneAnalysisAPISessionBuilder.kt @@ -12,16 +12,13 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.util.Disposer import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem import com.intellij.psi.search.GlobalSearchScope -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract import org.jetbrains.kotlin.analysis.api.KtAnalysisApiInternals import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.FirStandaloneServiceRegistrar +import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtStaticProjectStructureProvider import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.StandaloneProjectFactory import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.FirSealedClassInheritorsProcessorFactory import org.jetbrains.kotlin.analysis.project.structure.KtModuleScopeProvider import org.jetbrains.kotlin.analysis.project.structure.KtModuleScopeProviderImpl -import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider import org.jetbrains.kotlin.analysis.project.structure.builder.KtModuleProviderBuilder import org.jetbrains.kotlin.analysis.project.structure.builder.buildProjectStructureProvider import org.jetbrains.kotlin.analysis.project.structure.impl.KtModuleProviderImpl @@ -38,6 +35,9 @@ import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProvider import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProviderImpl import org.jetbrains.kotlin.load.kotlin.PackagePartProvider import org.jetbrains.kotlin.psi.KtFile +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract public class StandaloneAnalysisAPISessionBuilder( applicationDisposable: Disposable, @@ -70,7 +70,7 @@ public class StandaloneAnalysisAPISessionBuilder( public val project: Project = kotlinCoreProjectEnvironment.project - private lateinit var projectStructureProvider: ProjectStructureProvider + private lateinit var projectStructureProvider: KtStaticProjectStructureProvider public fun buildKtModuleProvider(init: KtModuleProviderBuilder.() -> Unit) { projectStructureProvider = buildProjectStructureProvider(init) @@ -181,18 +181,16 @@ public class StandaloneAnalysisAPISessionBuilder( public fun build( withPsiDeclarationFromBinaryModuleProvider: Boolean = false, ): StandaloneAnalysisAPISession { - val ktModuleProviderImpl = projectStructureProvider as KtModuleProviderImpl - val modules = ktModuleProviderImpl.mainModules - val allSourceFiles = ktModuleProviderImpl.allSourceFiles() StandaloneProjectFactory.registerServicesForProjectEnvironment( kotlinCoreProjectEnvironment, projectStructureProvider, - modules, - allSourceFiles, ) val project = kotlinCoreProjectEnvironment.project - val ktFiles = allSourceFiles.filterIsInstance() - val libraryRoots = StandaloneProjectFactory.getAllBinaryRoots(modules, kotlinCoreProjectEnvironment) + val ktFiles = projectStructureProvider.allSourceFiles.filterIsInstance() + val libraryRoots = StandaloneProjectFactory.getAllBinaryRoots( + projectStructureProvider.allKtModules, + kotlinCoreProjectEnvironment, + ) val createPackagePartProvider = StandaloneProjectFactory.createPackagePartsProvider( project, diff --git a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/builder/KtModuleProviderBuilder.kt b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/builder/KtModuleProviderBuilder.kt index f31874b546f..c41f6547628 100644 --- a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/builder/KtModuleProviderBuilder.kt +++ b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/builder/KtModuleProviderBuilder.kt @@ -7,12 +7,12 @@ package org.jetbrains.kotlin.analysis.project.structure.builder import com.intellij.openapi.project.Project import org.jetbrains.kotlin.analysis.project.structure.KtModule -import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider import org.jetbrains.kotlin.analysis.project.structure.impl.KtModuleProviderImpl import org.jetbrains.kotlin.platform.TargetPlatform import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract +import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtStaticProjectStructureProvider @KtModuleBuilderDsl public class KtModuleProviderBuilder { @@ -25,7 +25,7 @@ public class KtModuleProviderBuilder { public lateinit var platform: TargetPlatform public lateinit var project: Project - public fun build(): ProjectStructureProvider { + public fun build(): KtStaticProjectStructureProvider { return KtModuleProviderImpl( platform, project, @@ -35,7 +35,7 @@ public class KtModuleProviderBuilder { } @OptIn(ExperimentalContracts::class) -public inline fun buildProjectStructureProvider(init: KtModuleProviderBuilder.() -> Unit): ProjectStructureProvider { +public inline fun buildProjectStructureProvider(init: KtModuleProviderBuilder.() -> Unit): KtStaticProjectStructureProvider { contract { callsInPlace(init, InvocationKind.EXACTLY_ONCE) } diff --git a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/impl/KtModuleProviderImpl.kt b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/impl/KtModuleProviderImpl.kt index 36f5f1f3bd3..239e5853c15 100644 --- a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/impl/KtModuleProviderImpl.kt +++ b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/impl/KtModuleProviderImpl.kt @@ -11,6 +11,7 @@ import com.intellij.psi.PsiFile import com.intellij.psi.PsiFileSystemItem import com.intellij.psi.PsiJavaFile import com.intellij.util.containers.ContainerUtil +import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtStaticProjectStructureProvider import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.StandaloneProjectFactory.findJvmRootsForJavaFiles import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.LLFirBuiltinsSessionFactory import org.jetbrains.kotlin.analysis.project.structure.* @@ -23,8 +24,8 @@ import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments internal class KtModuleProviderImpl( private val platform: TargetPlatform, private val project: Project, - internal val mainModules: List, -) : ProjectStructureProvider() { + override val allKtModules: List, +) : KtStaticProjectStructureProvider() { private val ktNotUnderContentRootModuleWithoutPsiFile by lazy { KtNotUnderContentRootModuleImpl( name = "unnamed-outside-content-root", @@ -65,25 +66,27 @@ internal class KtModuleProviderImpl( containingFileAsVirtualFile.analysisExtensionFileContextModule?.let { return it } - return mainModules.firstOrNull { module -> + return allKtModules.firstOrNull { module -> containingFileAsVirtualFile in module.contentScope } ?: throw KotlinExceptionWithAttachments("Cannot find KtModule; see the attachment for more details.") .withAttachment( containingFileAsVirtualFile.path, - mainModules.joinToString(separator = System.lineSeparator()) { it.asDebugString() } + allKtModules.joinToString(separator = System.lineSeparator()) { it.asDebugString() } ) } internal val binaryModules: List by lazy { - mainModules + allKtModules .flatMap { it.allDirectDependencies() } .filterIsInstance() } - internal fun allSourceFiles(): List = buildList { - val files = mainModules.mapNotNull { (it as? KtSourceModuleImpl)?.sourceRoots }.flatten() - addAll(files) - addAll(findJvmRootsForJavaFiles(files.filterIsInstance())) + override val allSourceFiles: List by lazy { + buildList { + val files = allKtModules.mapNotNull { (it as? KtSourceModuleImpl)?.sourceRoots }.flatten() + addAll(files) + addAll(findJvmRootsForJavaFiles(files.filterIsInstance())) + } } } \ No newline at end of file diff --git a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/impl/KtModuleUtils.kt b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/impl/KtModuleUtils.kt index 7a5ab4706f0..b83c912f373 100644 --- a/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/impl/KtModuleUtils.kt +++ b/analysis/analysis-api-standalone/src/org/jetbrains/kotlin/analysis/project/structure/impl/KtModuleUtils.kt @@ -16,7 +16,6 @@ import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.ProjectScope import com.intellij.util.io.URLUtil import org.jetbrains.kotlin.analysis.api.impl.base.util.LibraryUtils -import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider import org.jetbrains.kotlin.analysis.project.structure.builder.* import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM @@ -44,6 +43,7 @@ import org.jetbrains.kotlin.resolve.konan.platform.NativePlatformAnalyzerService import java.io.IOException import java.nio.file.* import java.nio.file.attribute.BasicFileAttributes +import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.KtStaticProjectStructureProvider internal fun TargetPlatform.getAnalyzerServices(): PlatformDependentAnalyzerServices { return when { @@ -154,7 +154,7 @@ internal fun buildKtModuleProviderByCompilerConfiguration( compilerConfig: CompilerConfiguration, project: Project, ktFiles: List, -): ProjectStructureProvider = buildProjectStructureProvider { +): KtStaticProjectStructureProvider = buildProjectStructureProvider { val (scriptFiles, ordinaryFiles) = ktFiles.partition { it.isScript() } val platform = JvmPlatforms.defaultJvmPlatform diff --git a/analysis/analysis-api-standalone/tests/org/jetbrains/kotlin/analysis/api/standalone/fir/test/StandaloneModeTestServiceRegistrar.kt b/analysis/analysis-api-standalone/tests/org/jetbrains/kotlin/analysis/api/standalone/fir/test/StandaloneModeTestServiceRegistrar.kt index f28b5813b5a..8bbe3a9c18e 100644 --- a/analysis/analysis-api-standalone/tests/org/jetbrains/kotlin/analysis/api/standalone/fir/test/StandaloneModeTestServiceRegistrar.kt +++ b/analysis/analysis-api-standalone/tests/org/jetbrains/kotlin/analysis/api/standalone/fir/test/StandaloneModeTestServiceRegistrar.kt @@ -13,9 +13,7 @@ import org.jetbrains.kotlin.analysis.decompiled.light.classes.ClsJavaStubByVirtu import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.JvmFirDeserializedSymbolProviderFactory import org.jetbrains.kotlin.analysis.project.structure.KtBinaryModule import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider -import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProviderFactory import org.jetbrains.kotlin.analysis.providers.KotlinPsiDeclarationProviderFactory -import org.jetbrains.kotlin.analysis.providers.impl.KotlinStaticDeclarationProviderFactory import org.jetbrains.kotlin.analysis.providers.impl.KotlinStaticPsiDeclarationProviderFactory import org.jetbrains.kotlin.analysis.test.framework.services.environmentManager import org.jetbrains.kotlin.analysis.test.framework.test.configurators.AnalysisApiTestServiceRegistrar @@ -29,9 +27,9 @@ public object StandaloneModeTestServiceRegistrar : AnalysisApiTestServiceRegistr } override fun registerProjectModelServices(project: MockProject, testServices: TestServices) { - val projectStructureProvider = project.getService(ProjectStructureProvider::class.java) + val projectStructureProvider = ProjectStructureProvider.getInstance(project) val binaryModules = - (projectStructureProvider as? KtStaticModuleProvider)?.allModules?.filterIsInstance() + (projectStructureProvider as? KtStaticModuleProvider)?.allKtModules?.filterIsInstance() ?: emptyList() val projectEnvironment = testServices.environmentManager.getProjectEnvironment() project.apply { 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 0f520facea3..ae563b10a23 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 @@ -67,8 +67,6 @@ class AnalysisApiEnvironmentManagerImpl( StandaloneProjectFactory.registerServicesForProjectEnvironment( _projectEnvironment, KtStaticModuleProvider(builtinsModule, ktModuleProjectStructure), - ktModuleProjectStructure.allKtModules(), - ktModuleProjectStructure.allSourceFiles(), useSiteCompilerConfiguration.languageVersionSettings, useSiteCompilerConfiguration.get(JVMConfigurationKeys.JDK_HOME)?.toPath(), )