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.KtModuleScopeProviderImpl
|
||||
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.impl.*
|
||||
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
|
||||
@@ -171,7 +171,7 @@ internal fun configureProjectEnvironment(
|
||||
|
||||
project.picoContainer.registerComponentInstance(
|
||||
ProjectStructureProvider::class.qualifiedName,
|
||||
KtModuleProviderByCompilerConfiguration(
|
||||
buildKtModuleProviderByCompilerConfiguration(
|
||||
compilerConfig,
|
||||
project,
|
||||
ktFiles,
|
||||
|
||||
+15
-3
@@ -12,9 +12,21 @@ import org.jetbrains.kotlin.platform.TargetPlatform
|
||||
|
||||
@KtModuleBuilderDsl
|
||||
public abstract class KtModuleBuilder {
|
||||
public val directRegularDependencies: MutableList<KtModule> = mutableListOf()
|
||||
public val directRefinementDependencies: MutableList<KtModule> = mutableListOf()
|
||||
public val directFriendDependencies: MutableList<KtModule> = mutableListOf()
|
||||
protected val directRegularDependencies: MutableList<KtModule> = mutableListOf()
|
||||
protected val directRefinementDependencies: 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 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
|
||||
|
||||
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.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.platform.TargetPlatform
|
||||
import org.jetbrains.kotlin.platform.isCommon
|
||||
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.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 java.nio.file.Paths
|
||||
|
||||
internal fun TargetPlatform.getAnalyzerServices(): PlatformDependentAnalyzerServices {
|
||||
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