[LL API] Provide basic support for scripts in K2 (KTIJ-21108)

This commit is contained in:
Yan Zhulanow
2023-02-27 20:18:05 +09:00
committed by Space Team
parent ca7d1d0194
commit ae40ddcf03
13 changed files with 490 additions and 94 deletions
@@ -0,0 +1,45 @@
/*
* 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.project.structure.builder
import org.jetbrains.kotlin.analysis.project.structure.KtScriptModule
import org.jetbrains.kotlin.analysis.project.structure.impl.KtScriptModuleImpl
import org.jetbrains.kotlin.config.ApiVersion
import org.jetbrains.kotlin.config.LanguageVersion
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.psi.KtFile
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
@KtModuleBuilderDsl
public class KtScriptModuleBuilder : KtModuleBuilder() {
public lateinit var file: KtFile
public var languageVersionSettings: LanguageVersionSettings =
LanguageVersionSettingsImpl(LanguageVersion.LATEST_STABLE, ApiVersion.LATEST)
override fun build(): KtScriptModule {
return KtScriptModuleImpl(
directRegularDependencies,
directDependsOnDependencies,
directFriendDependencies,
platform,
project,
file,
languageVersionSettings
)
}
}
@OptIn(ExperimentalContracts::class)
public inline fun buildKtScriptModule(init: KtScriptModuleBuilder.() -> Unit): KtScriptModule {
contract {
callsInPlace(init, InvocationKind.EXACTLY_ONCE)
}
return KtScriptModuleBuilder().apply(init).build()
}
@@ -17,10 +17,7 @@ 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.analysis.project.structure.builder.*
import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
import org.jetbrains.kotlin.cli.jvm.config.javaSourceRoots
@@ -154,51 +151,66 @@ internal fun buildKtModuleProviderByCompilerConfiguration(
project: Project,
ktFiles: List<KtFile>,
): ProjectStructureProvider = buildProjectStructureProvider {
val (scriptFiles, ordinaryFiles) = ktFiles.partition { it.isScript() }
val platform = JvmPlatforms.defaultJvmPlatform
addModule(
buildKtSourceModule {
val moduleName = compilerConfig.get(CommonConfigurationKeys.MODULE_NAME) ?: "<no module name provided>"
val libraryRoots = compilerConfig.jvmModularRoots + compilerConfig.jvmClasspathRoots
fun KtModuleBuilder.addModuleDependencies(moduleName: String) {
val libraryRoots = compilerConfig.jvmModularRoots + compilerConfig.jvmClasspathRoots
addRegularDependency(
buildKtLibraryModule {
contentScope = ProjectScope.getLibrariesScope(project)
this.platform = platform
this.project = project
binaryRoots = libraryRoots.map { it.toPath() }
libraryName = "Library for $moduleName"
}
)
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(
buildKtLibraryModule {
contentScope = ProjectScope.getLibrariesScope(project)
buildKtSdkModule {
contentScope = GlobalSearchScope.fileScope(project, jdkHomeVirtualFile)
this.platform = platform
this.project = project
binaryRoots = libraryRoots.map { it.toPath() }
libraryName = "Library for $moduleName"
this.binaryRoots = binaryRoots
sdkName = "JDK for $moduleName"
}
)
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
addSourceRoots(
getPsiFilesFromPaths(
project,
getSourceFilePaths(compilerConfig, includeDirectoryRoot = true)
)
)
}
)
}
for (scriptFile in scriptFiles) {
buildKtScriptModule {
this.project = project
this.platform = platform
this.file = scriptFile
addModuleDependencies("Script " + scriptFile.name)
}.apply(::addModule)
}
buildKtSourceModule {
this.project = project
this.platform = platform
this.moduleName = compilerConfig.get(CommonConfigurationKeys.MODULE_NAME) ?: "<no module name provided>"
addModuleDependencies(moduleName)
contentScope = TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, ordinaryFiles)
addSourceRoots(
getPsiFilesFromPaths(
project,
getSourceFilePaths(compilerConfig, includeDirectoryRoot = true)
)
)
}.apply(::addModule)
this.platform = platform
this.project = project
}
@@ -0,0 +1,37 @@
/*
* 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.project.structure.impl
import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.analysis.project.structure.KtScriptModule
import org.jetbrains.kotlin.analysis.project.structure.computeTransitiveDependsOnDependencies
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
internal class KtScriptModuleImpl(
override val directRegularDependencies: List<KtModule> = emptyList(),
override val directDependsOnDependencies: List<KtModule> = emptyList(),
override val directFriendDependencies: List<KtModule> = emptyList(),
override val platform: TargetPlatform = JvmPlatforms.defaultJvmPlatform,
override val project: Project,
override val file: KtFile,
override val languageVersionSettings: LanguageVersionSettings
) : KtScriptModule, KtModuleWithPlatform {
override val transitiveDependsOnDependencies: List<KtModule> by lazy {
computeTransitiveDependsOnDependencies(directDependsOnDependencies)
}
override val analyzerServices: PlatformDependentAnalyzerServices
get() = super.analyzerServices
override val contentScope: GlobalSearchScope
get() = GlobalSearchScope.fileScope(file)
}