AA: introduce ProjectStructureProvider builder
This commit is contained in:
committed by
Ilya Kirillov
parent
8528f6244d
commit
4cfefbd921
+2
-2
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.services.PackagePartP
|
|||||||
import org.jetbrains.kotlin.analysis.project.structure.KtModuleScopeProvider
|
import org.jetbrains.kotlin.analysis.project.structure.KtModuleScopeProvider
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtModuleScopeProviderImpl
|
import org.jetbrains.kotlin.analysis.project.structure.KtModuleScopeProviderImpl
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider
|
import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.impl.KtModuleProviderByCompilerConfiguration
|
import org.jetbrains.kotlin.analysis.project.structure.impl.buildKtModuleProviderByCompilerConfiguration
|
||||||
import org.jetbrains.kotlin.analysis.providers.*
|
import org.jetbrains.kotlin.analysis.providers.*
|
||||||
import org.jetbrains.kotlin.analysis.providers.impl.*
|
import org.jetbrains.kotlin.analysis.providers.impl.*
|
||||||
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
|
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
|
||||||
@@ -171,7 +171,7 @@ internal fun configureProjectEnvironment(
|
|||||||
|
|
||||||
project.picoContainer.registerComponentInstance(
|
project.picoContainer.registerComponentInstance(
|
||||||
ProjectStructureProvider::class.qualifiedName,
|
ProjectStructureProvider::class.qualifiedName,
|
||||||
KtModuleProviderByCompilerConfiguration(
|
buildKtModuleProviderByCompilerConfiguration(
|
||||||
compilerConfig,
|
compilerConfig,
|
||||||
project,
|
project,
|
||||||
ktFiles,
|
ktFiles,
|
||||||
|
|||||||
+15
-3
@@ -12,9 +12,21 @@ import org.jetbrains.kotlin.platform.TargetPlatform
|
|||||||
|
|
||||||
@KtModuleBuilderDsl
|
@KtModuleBuilderDsl
|
||||||
public abstract class KtModuleBuilder {
|
public abstract class KtModuleBuilder {
|
||||||
public val directRegularDependencies: MutableList<KtModule> = mutableListOf()
|
protected val directRegularDependencies: MutableList<KtModule> = mutableListOf()
|
||||||
public val directRefinementDependencies: MutableList<KtModule> = mutableListOf()
|
protected val directRefinementDependencies: MutableList<KtModule> = mutableListOf()
|
||||||
public val directFriendDependencies: MutableList<KtModule> = mutableListOf()
|
protected val directFriendDependencies: MutableList<KtModule> = mutableListOf()
|
||||||
|
|
||||||
|
public fun addRegularDependency(module: KtModule) {
|
||||||
|
directRegularDependencies.add(module)
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun addRefinementDependency(module: KtModule) {
|
||||||
|
directRefinementDependencies.add(module)
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun addFriendDependency(module: KtModule) {
|
||||||
|
directFriendDependencies.add(module)
|
||||||
|
}
|
||||||
|
|
||||||
public lateinit var contentScope: GlobalSearchScope
|
public lateinit var contentScope: GlobalSearchScope
|
||||||
public lateinit var platform: TargetPlatform
|
public lateinit var platform: TargetPlatform
|
||||||
|
|||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* 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.project.structure.builder
|
||||||
|
|
||||||
|
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 kotlin.contracts.ExperimentalContracts
|
||||||
|
import kotlin.contracts.InvocationKind
|
||||||
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
|
@KtModuleBuilderDsl
|
||||||
|
public class KtModuleProviderBuilder {
|
||||||
|
private val mainModules: MutableList<KtModule> = mutableListOf()
|
||||||
|
|
||||||
|
public fun addModule(module: KtModule) {
|
||||||
|
mainModules.add(module)
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun build(): ProjectStructureProvider {
|
||||||
|
return KtModuleProviderImpl(
|
||||||
|
mainModules,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalContracts::class)
|
||||||
|
public inline fun buildProjectStructureProvider(init: KtModuleProviderBuilder.() -> Unit): ProjectStructureProvider {
|
||||||
|
contract {
|
||||||
|
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
|
||||||
|
}
|
||||||
|
return KtModuleProviderBuilder().apply(init).build()
|
||||||
|
}
|
||||||
-123
@@ -1,123 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.project.structure.impl
|
|
||||||
|
|
||||||
import com.google.common.io.Files
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.openapi.vfs.VirtualFileManager
|
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
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.KtBinaryModule
|
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule
|
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.KtModule
|
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.ProjectStructureProvider
|
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.builder.buildKtLibraryModule
|
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.builder.buildKtSdkModule
|
|
||||||
import org.jetbrains.kotlin.analysis.project.structure.builder.buildKtSourceModule
|
|
||||||
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.*
|
|
||||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
|
||||||
import org.jetbrains.kotlin.platform.jvm.JdkPlatform
|
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
|
||||||
import java.nio.file.Paths
|
|
||||||
|
|
||||||
internal class KtModuleProviderByCompilerConfiguration(
|
|
||||||
compilerConfig: CompilerConfiguration,
|
|
||||||
project: Project,
|
|
||||||
ktFiles: List<KtFile>,
|
|
||||||
) : ProjectStructureProvider() {
|
|
||||||
private val sourceModule = buildKtSourceModule {
|
|
||||||
val platform = TargetPlatform(setOf(JdkPlatform(JvmTarget.DEFAULT)))
|
|
||||||
val moduleName = compilerConfig.get(CommonConfigurationKeys.MODULE_NAME) ?: "<no module name provided>"
|
|
||||||
|
|
||||||
val libraryRoots = compilerConfig.jvmModularRoots + compilerConfig.jvmClasspathRoots
|
|
||||||
val libraryRootsByType = libraryRoots.groupBy { it.isDirectory }
|
|
||||||
libraryRootsByType[true]?.let { directories ->
|
|
||||||
directories.forEach {
|
|
||||||
// E.g., project/app/build/intermediates/javac/debug/classes
|
|
||||||
val root = it.toPath()
|
|
||||||
directRegularDependencies.add(
|
|
||||||
buildKtLibraryModule {
|
|
||||||
contentScope = ProjectScope.getLibrariesScope(project)
|
|
||||||
this.platform = platform
|
|
||||||
this.project = project
|
|
||||||
binaryRoots = listOf(root)
|
|
||||||
libraryName = "$moduleName-${root.toString().replace("/", "-")}"
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
libraryRootsByType[false]?.let { jars ->
|
|
||||||
jars.forEach {
|
|
||||||
// E.g., project/libs/libA/a.jar
|
|
||||||
val root = it.toPath()
|
|
||||||
directRegularDependencies.add(
|
|
||||||
buildKtLibraryModule {
|
|
||||||
contentScope = ProjectScope.getLibrariesScope(project)
|
|
||||||
this.platform = platform
|
|
||||||
this.project = project
|
|
||||||
binaryRoots = listOf(root)
|
|
||||||
libraryName = Files.getNameWithoutExtension(root.toString())
|
|
||||||
isBuiltinsContainingStdlib =
|
|
||||||
libraryName.startsWith("kotlin-stdlib") &&
|
|
||||||
!libraryName.contains("common") && !libraryName.contains("jdk")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
compilerConfig.get(JVMConfigurationKeys.JDK_HOME)?.let { jdkHome ->
|
|
||||||
val vfm = VirtualFileManager.getInstance()
|
|
||||||
val jdkHomePath = jdkHome.toPath()
|
|
||||||
val jdkHomeVirtualFile = vfm.findFileByNioPath(jdkHomePath)
|
|
||||||
val binaryRoots = LibraryUtils.findClassesFromJdkHome(jdkHomePath).map {
|
|
||||||
Paths.get(URLUtil.extractPath(it))
|
|
||||||
}
|
|
||||||
directRegularDependencies.add(
|
|
||||||
buildKtSdkModule {
|
|
||||||
contentScope = GlobalSearchScope.fileScope(project, jdkHomeVirtualFile)
|
|
||||||
this.platform = platform
|
|
||||||
this.project = project
|
|
||||||
this.binaryRoots = binaryRoots
|
|
||||||
sdkName = "JDK for $moduleName"
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
contentScope = TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, ktFiles)
|
|
||||||
this.platform = platform
|
|
||||||
this.project = project
|
|
||||||
this.moduleName = moduleName
|
|
||||||
}
|
|
||||||
|
|
||||||
private val binaryModules: Collection<KtBinaryModule> by lazy {
|
|
||||||
sourceModule.directRegularDependencies.filterIsInstance<KtBinaryModule>()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getKtModuleForKtElement(element: PsiElement): KtModule {
|
|
||||||
val containingFile = element.containingFile.virtualFile
|
|
||||||
return if (containingFile in sourceModule.contentScope) {
|
|
||||||
sourceModule
|
|
||||||
} else {
|
|
||||||
binaryModules.find { libModule -> containingFile in libModule.contentScope }
|
|
||||||
?: error("Can't find module for ${containingFile.path}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getKtBinaryModules(): Collection<KtBinaryModule> {
|
|
||||||
return binaryModules
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getStdlibWithBuiltinsModule(module: KtModule): KtLibraryModule? {
|
|
||||||
return binaryModules
|
|
||||||
.filterIsInstance<KtLibraryModuleImpl>()
|
|
||||||
.firstOrNull { it.isBuiltinsContainingStdlib }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* 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.project.structure.impl
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import org.jetbrains.kotlin.analysis.project.structure.*
|
||||||
|
|
||||||
|
internal class KtModuleProviderImpl(
|
||||||
|
private val mainModules: List<KtModule>,
|
||||||
|
) : ProjectStructureProvider() {
|
||||||
|
override fun getKtModuleForKtElement(element: PsiElement): KtModule {
|
||||||
|
val containingFile = element.containingFile.virtualFile
|
||||||
|
return mainModules.first { module ->
|
||||||
|
containingFile in module.contentScope
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val binaryModules: Collection<KtBinaryModule> by lazy {
|
||||||
|
mainModules
|
||||||
|
.flatMap { it.allDirectDependencies() }
|
||||||
|
.filterIsInstance<KtBinaryModule>()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getKtBinaryModules(): Collection<KtBinaryModule> {
|
||||||
|
return binaryModules
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getStdlibWithBuiltinsModule(module: KtModule): KtLibraryModule? {
|
||||||
|
return binaryModules
|
||||||
|
.filterIsInstance<KtLibraryModuleImpl>()
|
||||||
|
.firstOrNull { it.isBuiltinsContainingStdlib }
|
||||||
|
}
|
||||||
|
}
|
||||||
+92
@@ -5,16 +5,38 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.analysis.project.structure.impl
|
package org.jetbrains.kotlin.analysis.project.structure.impl
|
||||||
|
|
||||||
|
import com.google.common.io.Files
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.vfs.VirtualFileManager
|
||||||
|
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.buildKtLibraryModule
|
||||||
|
import org.jetbrains.kotlin.analysis.project.structure.builder.buildKtSdkModule
|
||||||
|
import org.jetbrains.kotlin.analysis.project.structure.builder.buildKtSourceModule
|
||||||
|
import org.jetbrains.kotlin.analysis.project.structure.builder.buildProjectStructureProvider
|
||||||
import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices
|
import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices
|
||||||
|
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.CommonConfigurationKeys
|
||||||
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
|
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||||
|
import org.jetbrains.kotlin.config.JvmTarget
|
||||||
import org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices
|
import org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices
|
||||||
import org.jetbrains.kotlin.platform.TargetPlatform
|
import org.jetbrains.kotlin.platform.TargetPlatform
|
||||||
import org.jetbrains.kotlin.platform.isCommon
|
import org.jetbrains.kotlin.platform.isCommon
|
||||||
import org.jetbrains.kotlin.platform.js.isJs
|
import org.jetbrains.kotlin.platform.js.isJs
|
||||||
|
import org.jetbrains.kotlin.platform.jvm.JdkPlatform
|
||||||
import org.jetbrains.kotlin.platform.jvm.isJvm
|
import org.jetbrains.kotlin.platform.jvm.isJvm
|
||||||
import org.jetbrains.kotlin.platform.konan.isNative
|
import org.jetbrains.kotlin.platform.konan.isNative
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
|
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
|
||||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
|
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
|
||||||
import org.jetbrains.kotlin.resolve.konan.platform.NativePlatformAnalyzerServices
|
import org.jetbrains.kotlin.resolve.konan.platform.NativePlatformAnalyzerServices
|
||||||
|
import java.nio.file.Paths
|
||||||
|
|
||||||
internal fun TargetPlatform.getAnalyzerServices(): PlatformDependentAnalyzerServices {
|
internal fun TargetPlatform.getAnalyzerServices(): PlatformDependentAnalyzerServices {
|
||||||
return when {
|
return when {
|
||||||
@@ -26,3 +48,73 @@ internal fun TargetPlatform.getAnalyzerServices(): PlatformDependentAnalyzerServ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun buildKtModuleProviderByCompilerConfiguration(
|
||||||
|
compilerConfig: CompilerConfiguration,
|
||||||
|
project: Project,
|
||||||
|
ktFiles: List<KtFile>,
|
||||||
|
): ProjectStructureProvider = buildProjectStructureProvider {
|
||||||
|
addModule(
|
||||||
|
buildKtSourceModule {
|
||||||
|
val platform = TargetPlatform(setOf(JdkPlatform(JvmTarget.DEFAULT)))
|
||||||
|
val moduleName = compilerConfig.get(CommonConfigurationKeys.MODULE_NAME) ?: "<no module name provided>"
|
||||||
|
|
||||||
|
val libraryRoots = compilerConfig.jvmModularRoots + compilerConfig.jvmClasspathRoots
|
||||||
|
val libraryRootsByType = libraryRoots.groupBy { it.isDirectory }
|
||||||
|
libraryRootsByType[true]?.let { directories ->
|
||||||
|
directories.forEach {
|
||||||
|
// E.g., project/app/build/intermediates/javac/debug/classes
|
||||||
|
val root = it.toPath()
|
||||||
|
addRegularDependency(
|
||||||
|
buildKtLibraryModule {
|
||||||
|
contentScope = ProjectScope.getLibrariesScope(project)
|
||||||
|
this.platform = platform
|
||||||
|
this.project = project
|
||||||
|
binaryRoots = listOf(root)
|
||||||
|
libraryName = "$moduleName-${root.toString().replace("/", "-")}"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
libraryRootsByType[false]?.let { jars ->
|
||||||
|
jars.forEach {
|
||||||
|
// E.g., project/libs/libA/a.jar
|
||||||
|
val root = it.toPath()
|
||||||
|
addRegularDependency(
|
||||||
|
buildKtLibraryModule {
|
||||||
|
contentScope = ProjectScope.getLibrariesScope(project)
|
||||||
|
this.platform = platform
|
||||||
|
this.project = project
|
||||||
|
binaryRoots = listOf(root)
|
||||||
|
libraryName = Files.getNameWithoutExtension(root.toString())
|
||||||
|
isBuiltinsContainingStdlib =
|
||||||
|
libraryName.startsWith("kotlin-stdlib") &&
|
||||||
|
!libraryName.contains("common") && !libraryName.contains("jdk")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
compilerConfig.get(JVMConfigurationKeys.JDK_HOME)?.let { jdkHome ->
|
||||||
|
val vfm = VirtualFileManager.getInstance()
|
||||||
|
val jdkHomePath = jdkHome.toPath()
|
||||||
|
val jdkHomeVirtualFile = vfm.findFileByNioPath(jdkHomePath)
|
||||||
|
val binaryRoots = LibraryUtils.findClassesFromJdkHome(jdkHomePath).map {
|
||||||
|
Paths.get(URLUtil.extractPath(it))
|
||||||
|
}
|
||||||
|
addRegularDependency(
|
||||||
|
buildKtSdkModule {
|
||||||
|
contentScope = GlobalSearchScope.fileScope(project, jdkHomeVirtualFile)
|
||||||
|
this.platform = platform
|
||||||
|
this.project = project
|
||||||
|
this.binaryRoots = binaryRoots
|
||||||
|
sdkName = "JDK for $moduleName"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
contentScope = TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, ktFiles)
|
||||||
|
this.platform = platform
|
||||||
|
this.project = project
|
||||||
|
this.moduleName = moduleName
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user