[AA] Standalone Analysis API: Introduce KtStaticProjectStructureProvider
- `registerServicesForProjectEnvironment` relied on lists of all modules and source files, which the standalone project structure providers would have already been able to provide with the right interface. - In `StandaloneAnalysisAPISessionBuilder.build`, to get all modules and source files, `projectStructureProvider` had to be hard-casted to `KtModuleProviderImpl`. - This commit introduces `KtStaticProjectStructureProvider`, a shared interface for project structure providers with static module structures that know about their modules and source files.
This commit is contained in:
committed by
Space Team
parent
e3d803de8b
commit
7fd8e4d0fd
+7
-5
@@ -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<KtModule>
|
||||
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<KtModule> = projectStructure.allKtModules()
|
||||
|
||||
override val allSourceFiles: List<PsiFileSystemItem> = projectStructure.allSourceFiles()
|
||||
}
|
||||
+28
@@ -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<KtModule>
|
||||
|
||||
public abstract val allSourceFiles: List<PsiFileSystemItem>
|
||||
}
|
||||
+8
-4
@@ -162,9 +162,7 @@ object StandaloneProjectFactory {
|
||||
|
||||
fun registerServicesForProjectEnvironment(
|
||||
environment: KotlinCoreProjectEnvironment,
|
||||
projectStructureProvider: ProjectStructureProvider,
|
||||
modules: List<KtModule>,
|
||||
sourceFiles: List<PsiFileSystemItem>,
|
||||
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(
|
||||
|
||||
+10
-12
@@ -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<KtFile>()
|
||||
val libraryRoots = StandaloneProjectFactory.getAllBinaryRoots(modules, kotlinCoreProjectEnvironment)
|
||||
val ktFiles = projectStructureProvider.allSourceFiles.filterIsInstance<KtFile>()
|
||||
val libraryRoots = StandaloneProjectFactory.getAllBinaryRoots(
|
||||
projectStructureProvider.allKtModules,
|
||||
kotlinCoreProjectEnvironment,
|
||||
)
|
||||
val createPackagePartProvider =
|
||||
StandaloneProjectFactory.createPackagePartsProvider(
|
||||
project,
|
||||
|
||||
+3
-3
@@ -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)
|
||||
}
|
||||
|
||||
+12
-9
@@ -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<KtModule>,
|
||||
) : ProjectStructureProvider() {
|
||||
override val allKtModules: List<KtModule>,
|
||||
) : 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<KtBinaryModule> by lazy {
|
||||
mainModules
|
||||
allKtModules
|
||||
.flatMap { it.allDirectDependencies() }
|
||||
.filterIsInstance<KtBinaryModule>()
|
||||
}
|
||||
|
||||
internal fun allSourceFiles(): List<PsiFileSystemItem> = buildList {
|
||||
val files = mainModules.mapNotNull { (it as? KtSourceModuleImpl)?.sourceRoots }.flatten()
|
||||
addAll(files)
|
||||
addAll(findJvmRootsForJavaFiles(files.filterIsInstance<PsiJavaFile>()))
|
||||
override val allSourceFiles: List<PsiFileSystemItem> by lazy {
|
||||
buildList {
|
||||
val files = allKtModules.mapNotNull { (it as? KtSourceModuleImpl)?.sourceRoots }.flatten()
|
||||
addAll(files)
|
||||
addAll(findJvmRootsForJavaFiles(files.filterIsInstance<PsiJavaFile>()))
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -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<KtFile>,
|
||||
): ProjectStructureProvider = buildProjectStructureProvider {
|
||||
): KtStaticProjectStructureProvider = buildProjectStructureProvider {
|
||||
val (scriptFiles, ordinaryFiles) = ktFiles.partition { it.isScript() }
|
||||
val platform = JvmPlatforms.defaultJvmPlatform
|
||||
|
||||
|
||||
+2
-4
@@ -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<KtBinaryModule>()
|
||||
(projectStructureProvider as? KtStaticModuleProvider)?.allKtModules?.filterIsInstance<KtBinaryModule>()
|
||||
?: emptyList()
|
||||
val projectEnvironment = testServices.environmentManager.getProjectEnvironment()
|
||||
project.apply {
|
||||
|
||||
-2
@@ -67,8 +67,6 @@ class AnalysisApiEnvironmentManagerImpl(
|
||||
StandaloneProjectFactory.registerServicesForProjectEnvironment(
|
||||
_projectEnvironment,
|
||||
KtStaticModuleProvider(builtinsModule, ktModuleProjectStructure),
|
||||
ktModuleProjectStructure.allKtModules(),
|
||||
ktModuleProjectStructure.allSourceFiles(),
|
||||
useSiteCompilerConfiguration.languageVersionSettings,
|
||||
useSiteCompilerConfiguration.get(JVMConfigurationKeys.JDK_HOME)?.toPath(),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user