AA: introduce AA session and builder
This commit is contained in:
committed by
Ilya Kirillov
parent
5585d84808
commit
aef3df0336
+9
-7
@@ -25,8 +25,7 @@ import org.jetbrains.kotlin.cli.jvm.index.SingleJavaFileRootsIndex
|
||||
import org.jetbrains.kotlin.cli.jvm.modules.CliJavaModuleFinder
|
||||
import org.jetbrains.kotlin.cli.jvm.modules.CliJavaModuleResolver
|
||||
import org.jetbrains.kotlin.cli.jvm.modules.JavaModuleGraph
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.config.*
|
||||
import org.jetbrains.kotlin.load.kotlin.MetadataFinderFactory
|
||||
import org.jetbrains.kotlin.load.kotlin.VirtualFileFinderFactory
|
||||
import org.jetbrains.kotlin.resolve.ModuleAnnotationsResolver
|
||||
@@ -52,8 +51,8 @@ object StandaloneProjectFactory {
|
||||
projectStructureProvider: ProjectStructureProvider,
|
||||
modules: List<KtModule>,
|
||||
sourceFiles: List<PsiFileSystemItem>,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
jdkHome: Path?,
|
||||
languageVersionSettings: LanguageVersionSettings = latestLanguageVersionSettings,
|
||||
jdkHome: Path? = null,
|
||||
) {
|
||||
val project = environment.project
|
||||
|
||||
@@ -96,7 +95,7 @@ object StandaloneProjectFactory {
|
||||
javaFileManager.initialize(
|
||||
JvmDependenciesIndexImpl(sourceAndLibraryRoots),
|
||||
listOf(
|
||||
createPackagePartsProvider(languageVersionSettings, project, libraryRoots)
|
||||
createPackagePartsProvider(project, libraryRoots, languageVersionSettings)
|
||||
.invoke(ProjectScope.getLibrariesScope(project))
|
||||
),
|
||||
SingleJavaFileRootsIndex(emptyList()),
|
||||
@@ -174,9 +173,9 @@ object StandaloneProjectFactory {
|
||||
}
|
||||
|
||||
fun createPackagePartsProvider(
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
project: MockProject,
|
||||
libraryRoots: List<JavaRoot>
|
||||
libraryRoots: List<JavaRoot>,
|
||||
languageVersionSettings: LanguageVersionSettings = latestLanguageVersionSettings,
|
||||
): (GlobalSearchScope) -> JvmPackagePartProvider = { scope ->
|
||||
JvmPackagePartProvider(languageVersionSettings, scope).apply {
|
||||
addRoots(libraryRoots, MessageCollector.NONE)
|
||||
@@ -185,4 +184,7 @@ object StandaloneProjectFactory {
|
||||
.addPackagePartProvider(this)
|
||||
}
|
||||
}
|
||||
|
||||
private val latestLanguageVersionSettings: LanguageVersionSettings =
|
||||
LanguageVersionSettingsImpl(LanguageVersion.LATEST_STABLE, ApiVersion.LATEST)
|
||||
}
|
||||
@@ -18,6 +18,7 @@ dependencies {
|
||||
api(project(":analysis:low-level-api-fir"))
|
||||
api(project(":analysis:symbol-light-classes"))
|
||||
api(project(":analysis:decompiled:light-classes-for-decompiled"))
|
||||
api(project(":analysis:analysis-api-standalone:analysis-api-standalone-base"))
|
||||
|
||||
testApi(projectTests(":analysis:analysis-api-impl-base"))
|
||||
testApi(projectTests(":analysis:analysis-api-fir"))
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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
|
||||
|
||||
import com.intellij.core.CoreApplicationEnvironment
|
||||
import com.intellij.mock.MockProject
|
||||
import com.intellij.openapi.application.Application
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreProjectEnvironment
|
||||
|
||||
public class StandaloneAnalysisAPISession internal constructor(
|
||||
kotlinCoreProjectEnvironment: KotlinCoreProjectEnvironment,
|
||||
) {
|
||||
// TODO: better to limit exposure? Current usages are: addExtension, jarFileSystem
|
||||
public val coreApplicationEnvironment: CoreApplicationEnvironment = kotlinCoreProjectEnvironment.environment
|
||||
|
||||
public val application: Application = kotlinCoreProjectEnvironment.environment.application
|
||||
|
||||
public val project: Project = kotlinCoreProjectEnvironment.project
|
||||
|
||||
@Deprecated(
|
||||
"Use session builder's service registration.",
|
||||
ReplaceWith("project")
|
||||
)
|
||||
public val mockProject: MockProject = kotlinCoreProjectEnvironment.project
|
||||
}
|
||||
+219
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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
|
||||
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.application.Application
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.psi.PsiElementFinder
|
||||
import com.intellij.psi.impl.PsiElementFinderImpl
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisApiInternals
|
||||
import org.jetbrains.kotlin.analysis.api.fir.KtFirAnalysisSessionProvider
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.references.HLApiReferenceProviderService
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.KtDefaultLifetimeTokenProvider
|
||||
import org.jetbrains.kotlin.analysis.api.lifetime.KtReadActionConfinementDefaultLifetimeTokenProvider
|
||||
import org.jetbrains.kotlin.analysis.api.session.KtAnalysisSessionProvider
|
||||
import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.StandaloneProjectFactory
|
||||
import org.jetbrains.kotlin.analysis.decompiled.light.classes.ClsJavaStubByVirtualFileCache
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.FirSealedClassInheritorsProcessorFactory
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.PackagePartProviderFactory
|
||||
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
|
||||
import org.jetbrains.kotlin.analysis.project.structure.impl.buildKtModuleProviderByCompilerConfiguration
|
||||
import org.jetbrains.kotlin.analysis.project.structure.impl.getPsiFilesFromPaths
|
||||
import org.jetbrains.kotlin.analysis.project.structure.impl.getSourceFilePaths
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinAnnotationsResolverFactory
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinDeclarationProviderFactory
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinModificationTrackerFactory
|
||||
import org.jetbrains.kotlin.analysis.providers.KotlinPackageProviderFactory
|
||||
import org.jetbrains.kotlin.analysis.providers.impl.KotlinStaticAnnotationsResolverFactory
|
||||
import org.jetbrains.kotlin.analysis.providers.impl.KotlinStaticDeclarationProviderFactory
|
||||
import org.jetbrains.kotlin.analysis.providers.impl.KotlinStaticModificationTrackerFactory
|
||||
import org.jetbrains.kotlin.analysis.providers.impl.KotlinStaticPackageProviderFactory
|
||||
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
|
||||
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreProjectEnvironment
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.setupIdeaStandaloneExecution
|
||||
import org.jetbrains.kotlin.config.*
|
||||
import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProvider
|
||||
import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProviderImpl
|
||||
import org.jetbrains.kotlin.idea.references.KotlinFirReferenceContributor
|
||||
import org.jetbrains.kotlin.idea.references.KotlinReferenceProviderContributor
|
||||
import org.jetbrains.kotlin.light.classes.symbol.KotlinAsJavaFirSupport
|
||||
import org.jetbrains.kotlin.light.classes.symbol.caches.SymbolLightClassFacadeCache
|
||||
import org.jetbrains.kotlin.load.kotlin.PackagePartProvider
|
||||
import org.jetbrains.kotlin.psi.KotlinReferenceProvidersService
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
public class StandaloneAnalysisAPISessionBuilder(
|
||||
applicationDisposable: Disposable,
|
||||
projectDisposable: Disposable,
|
||||
) {
|
||||
init {
|
||||
setupIdeaStandaloneExecution()
|
||||
}
|
||||
|
||||
private val kotlinCoreProjectEnvironment: KotlinCoreProjectEnvironment =
|
||||
StandaloneProjectFactory.createProjectEnvironment(
|
||||
projectDisposable,
|
||||
applicationDisposable,
|
||||
)
|
||||
|
||||
public val application: Application = kotlinCoreProjectEnvironment.environment.application
|
||||
|
||||
public val project: Project = kotlinCoreProjectEnvironment.project
|
||||
|
||||
private lateinit var projectStructureProvider: ProjectStructureProvider
|
||||
|
||||
public fun buildKtModuleProvider(init: KtModuleProviderBuilder.() -> Unit) {
|
||||
projectStructureProvider = buildProjectStructureProvider(init)
|
||||
}
|
||||
|
||||
@Deprecated(
|
||||
"Compiler configuration is not a good fit for specifying multi-module project.",
|
||||
ReplaceWith("buildKtModuleProvider { }")
|
||||
)
|
||||
public fun buildKtModuleProviderByCompilerConfiguration(
|
||||
compilerConfiguration: CompilerConfiguration,
|
||||
) {
|
||||
val project = kotlinCoreProjectEnvironment.project
|
||||
projectStructureProvider = buildKtModuleProviderByCompilerConfiguration(
|
||||
compilerConfiguration,
|
||||
project,
|
||||
getPsiFilesFromPaths(project, getSourceFilePaths(compilerConfiguration)),
|
||||
)
|
||||
}
|
||||
|
||||
private fun registerApplicationServices() {
|
||||
kotlinCoreProjectEnvironment.environment.application.apply {
|
||||
registerService(KotlinReferenceProvidersService::class.java, HLApiReferenceProviderService::class.java)
|
||||
registerService(KotlinReferenceProviderContributor::class.java, KotlinFirReferenceContributor::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
public fun <T : Any> registerApplicationService(serviceInterface: Class<T>, serviceImplementation: T) {
|
||||
kotlinCoreProjectEnvironment.environment.application.apply {
|
||||
registerService(serviceInterface, serviceImplementation)
|
||||
}
|
||||
}
|
||||
|
||||
public fun <T : Any> registerApplicationService(serviceImplementation: Class<T>) {
|
||||
kotlinCoreProjectEnvironment.environment.application.apply {
|
||||
registerService(serviceImplementation)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(KtAnalysisApiInternals::class)
|
||||
private fun registerProjectServices(
|
||||
ktFiles: List<KtFile>,
|
||||
packagePartProvider: (GlobalSearchScope) -> PackagePartProvider,
|
||||
) {
|
||||
val project = kotlinCoreProjectEnvironment.project
|
||||
project.apply {
|
||||
registerService(KotlinModificationTrackerFactory::class.java, KotlinStaticModificationTrackerFactory::class.java)
|
||||
registerService(KtDefaultLifetimeTokenProvider::class.java, KtReadActionConfinementDefaultLifetimeTokenProvider::class.java)
|
||||
|
||||
registerService(KtModuleScopeProvider::class.java, KtModuleScopeProviderImpl())
|
||||
registerService(KotlinModificationTrackerFactory::class.java, KotlinStaticModificationTrackerFactory::class.java)
|
||||
registerService(KotlinAnnotationsResolverFactory::class.java, KotlinStaticAnnotationsResolverFactory(ktFiles))
|
||||
registerService(KotlinDeclarationProviderFactory::class.java, KotlinStaticDeclarationProviderFactory(ktFiles))
|
||||
registerService(KotlinPackageProviderFactory::class.java, KotlinStaticPackageProviderFactory(ktFiles))
|
||||
|
||||
registerService(KtAnalysisSessionProvider::class.java, KtFirAnalysisSessionProvider(this))
|
||||
registerService(
|
||||
FirSealedClassInheritorsProcessorFactory::class.java,
|
||||
object : FirSealedClassInheritorsProcessorFactory() {
|
||||
override fun createSealedClassInheritorsProvider(): SealedClassInheritorsProvider {
|
||||
return SealedClassInheritorsProviderImpl
|
||||
}
|
||||
}
|
||||
)
|
||||
RegisterComponentService.registerLLFirResolveSessionService(this)
|
||||
registerService(
|
||||
PackagePartProviderFactory::class.java,
|
||||
object : PackagePartProviderFactory() {
|
||||
override fun createPackagePartProviderForLibrary(scope: GlobalSearchScope): PackagePartProvider {
|
||||
return packagePartProvider(scope)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
registerService(SymbolLightClassFacadeCache::class.java)
|
||||
registerService(ClsJavaStubByVirtualFileCache::class.java)
|
||||
registerService(KotlinAsJavaSupport::class.java, KotlinAsJavaFirSupport(this))
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
PsiElementFinder.EP.getPoint(project).registerExtension(JavaElementFinder(project))
|
||||
@Suppress("DEPRECATION")
|
||||
PsiElementFinder.EP.getPoint(project).registerExtension(PsiElementFinderImpl(project))
|
||||
}
|
||||
|
||||
public fun <T : Any> registerProjectService(serviceInterface: Class<T>, serviceImplementation: T) {
|
||||
kotlinCoreProjectEnvironment.project.apply {
|
||||
registerService(serviceInterface, serviceImplementation)
|
||||
}
|
||||
}
|
||||
|
||||
public fun <T : Any> registerProjectService(serviceImplementation: Class<T>) {
|
||||
kotlinCoreProjectEnvironment.project.apply {
|
||||
registerService(serviceImplementation)
|
||||
}
|
||||
}
|
||||
|
||||
public fun build(): StandaloneAnalysisAPISession {
|
||||
val ktModuleProviderImpl = projectStructureProvider as KtModuleProviderImpl
|
||||
val modules = ktModuleProviderImpl.mainModules
|
||||
val allSourceFiles = ktModuleProviderImpl.allSourceFiles()
|
||||
StandaloneProjectFactory.registerServicesForProjectEnvironment(
|
||||
kotlinCoreProjectEnvironment,
|
||||
projectStructureProvider,
|
||||
modules,
|
||||
allSourceFiles,
|
||||
)
|
||||
|
||||
registerApplicationServices()
|
||||
|
||||
val project = kotlinCoreProjectEnvironment.project
|
||||
val ktFiles = allSourceFiles.filterIsInstance<KtFile>()
|
||||
val libraryRoots = StandaloneProjectFactory.getAllBinaryRoots(modules, kotlinCoreProjectEnvironment)
|
||||
registerProjectServices(
|
||||
ktFiles,
|
||||
StandaloneProjectFactory.createPackagePartsProvider(
|
||||
project,
|
||||
libraryRoots,
|
||||
)
|
||||
)
|
||||
|
||||
return StandaloneAnalysisAPISession(
|
||||
kotlinCoreProjectEnvironment,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
public inline fun buildStandaloneAnalysisAPISession(
|
||||
applicationDisposable: Disposable = Disposer.newDisposable("StandaloneAnalysisAPISession.application"),
|
||||
projectDisposable: Disposable = Disposer.newDisposable("StandaloneAnalysisAPISession.project"),
|
||||
init: StandaloneAnalysisAPISessionBuilder.() -> Unit
|
||||
): StandaloneAnalysisAPISession {
|
||||
contract {
|
||||
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return StandaloneAnalysisAPISessionBuilder(
|
||||
applicationDisposable,
|
||||
projectDisposable,
|
||||
).apply(init).build()
|
||||
}
|
||||
+11
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.project.structure.builder
|
||||
|
||||
import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.impl.KtSourceModuleImpl
|
||||
import org.jetbrains.kotlin.config.ApiVersion
|
||||
@@ -20,6 +21,15 @@ public class KtSourceModuleBuilder : KtModuleBuilder() {
|
||||
public lateinit var moduleName: String
|
||||
public var languageVersionSettings: LanguageVersionSettings =
|
||||
LanguageVersionSettingsImpl(LanguageVersion.LATEST_STABLE, ApiVersion.LATEST)
|
||||
private val sourceRoots: MutableList<PsiFile> = mutableListOf()
|
||||
|
||||
public fun addSourceRoot(file: PsiFile) {
|
||||
sourceRoots.add(file)
|
||||
}
|
||||
|
||||
public fun addSourceRoots(files: Collection<PsiFile>) {
|
||||
sourceRoots.addAll(files)
|
||||
}
|
||||
|
||||
override fun build(): KtSourceModule {
|
||||
return KtSourceModuleImpl(
|
||||
@@ -31,6 +41,7 @@ public class KtSourceModuleBuilder : KtModuleBuilder() {
|
||||
project,
|
||||
moduleName,
|
||||
languageVersionSettings,
|
||||
sourceRoots,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+10
-1
@@ -6,10 +6,13 @@
|
||||
package org.jetbrains.kotlin.analysis.project.structure.impl
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFileSystemItem
|
||||
import com.intellij.psi.PsiJavaFile
|
||||
import org.jetbrains.kotlin.analysis.api.standalone.base.project.structure.StandaloneProjectFactory.findJvmRootsForJavaFiles
|
||||
import org.jetbrains.kotlin.analysis.project.structure.*
|
||||
|
||||
internal class KtModuleProviderImpl(
|
||||
private val mainModules: List<KtModule>,
|
||||
internal val mainModules: List<KtModule>,
|
||||
) : ProjectStructureProvider() {
|
||||
override fun getKtModuleForKtElement(element: PsiElement): KtModule {
|
||||
val containingFile = element.containingFile.virtualFile
|
||||
@@ -33,4 +36,10 @@ internal class KtModuleProviderImpl(
|
||||
.filterIsInstance<KtLibraryModuleImpl>()
|
||||
.firstOrNull { it.isBuiltinsContainingStdlib }
|
||||
}
|
||||
|
||||
internal fun allSourceFiles(): List<PsiFileSystemItem> = buildList {
|
||||
val files = mainModules.mapNotNull { (it as? KtSourceModuleImpl)?.sourceRoots }.flatten()
|
||||
addAll(files)
|
||||
addAll(findJvmRootsForJavaFiles(files.filterIsInstance<PsiJavaFile>()))
|
||||
}
|
||||
}
|
||||
+1
@@ -154,6 +154,7 @@ internal fun buildKtModuleProviderByCompilerConfiguration(
|
||||
this.platform = platform
|
||||
this.project = project
|
||||
this.moduleName = moduleName
|
||||
addSourceRoots(getPsiFilesFromPaths(project, getSourceFilePaths(compilerConfig)))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
+2
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.analysis.project.structure.impl
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
||||
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
|
||||
@@ -22,6 +23,7 @@ internal class KtSourceModuleImpl(
|
||||
override val project: Project,
|
||||
override val moduleName: String,
|
||||
override val languageVersionSettings: LanguageVersionSettings,
|
||||
internal val sourceRoots: List<PsiFile>,
|
||||
) : KtSourceModule, KtModuleWithPlatform {
|
||||
override val analyzerServices: PlatformDependentAnalyzerServices = super.analyzerServices
|
||||
}
|
||||
@@ -2,4 +2,9 @@ plugins {
|
||||
kotlin("jvm")
|
||||
}
|
||||
|
||||
publishJarsForIde(listOf(":analysis:analysis-api-standalone"))
|
||||
publishJarsForIde(
|
||||
listOf(
|
||||
":analysis:analysis-api-standalone:analysis-api-standalone-base",
|
||||
":analysis:analysis-api-standalone",
|
||||
)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user