AA: add JDK_HOME as dependent SDK module

This commit is contained in:
Jinseong Jeon
2022-05-03 23:24:47 -07:00
committed by Ilya Kirillov
parent af32a65c78
commit 3f05ba04a9
6 changed files with 92 additions and 19 deletions
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.analysis.api.impl.base.util
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.text.StringUtil
import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VirtualFile
@@ -13,7 +14,9 @@ import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiManager
import com.intellij.util.io.URLUtil.JAR_SEPARATOR
import java.nio.file.Files
import java.nio.file.Path
import java.util.Properties
object LibraryUtils {
/**
@@ -83,4 +86,46 @@ object LibraryUtils {
)
return files
}
// Copied (and adjusted) from JavaSdkImpl#readModulesFromReleaseFile
private fun readModulesFromReleaseFile(jrtBaseDir: Path): List<String?>? {
Files.newInputStream(jrtBaseDir.resolve("release")).use { stream ->
val p = Properties()
p.load(stream)
val modules = p.getProperty("MODULES")
if (modules != null) {
return StringUtil.split(StringUtil.unquoteString(modules), " ")
}
}
return null
}
// Copied from JdkUtil#isModularRuntime
private fun isModularRuntime(homePath: Path): Boolean {
return Files.isRegularFile(homePath.resolve("lib/jrt-fs.jar")) || isExplodedModularRuntime(homePath)
}
// Copied from JdkUtil#isExplodedModularRuntime
private fun isExplodedModularRuntime(homePath: Path): Boolean {
return Files.isDirectory(homePath.resolve("modules/java.base"))
}
// Copied (and adjusted) from JavaSdkImpl#findClasses
// Currently, handle modular runtime only
fun findClassesFromJdkHome(jdkHome: Path): List<String> {
val result = mutableListOf<String>()
if (isModularRuntime(jdkHome)) {
val jrtBaseUrl: String = StandardFileSystems.JRT_PROTOCOL_PREFIX + jdkHome.toString() + JAR_SEPARATOR
val modules = readModulesFromReleaseFile(jdkHome)
if (modules != null) {
for (module in modules) {
result.add(jrtBaseUrl + module)
}
}
}
result.sort()
return result
}
}
@@ -13,22 +13,23 @@ import com.intellij.openapi.vfs.VirtualFileSystem
import com.intellij.openapi.vfs.impl.jar.CoreJarFileSystem
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.util.io.URLUtil
import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule
import org.jetbrains.kotlin.analysis.project.structure.KtBinaryModule
import org.jetbrains.kotlin.name.FqName
import java.nio.file.Files
import java.nio.file.Path
public interface AbstractDeclarationFromLibraryModuleProvider {
public interface AbstractDeclarationFromBinaryModuleProvider {
public val scope: GlobalSearchScope
public val jarFileSystem: CoreJarFileSystem
public fun virtualFilesFromModule(
libraryModule: KtLibraryModule,
binaryModule: KtBinaryModule,
fqName: FqName,
isPackageName: Boolean,
): Collection<VirtualFile> {
val fqNameString = fqName.asString()
val fs = StandardFileSystems.local()
return libraryModule.getBinaryRoots().flatMap r@{ rootPath ->
return binaryModule.getBinaryRoots().flatMap r@{ rootPath ->
val root = findRoot(rootPath, fs) ?: return@r emptySet()
val files = mutableSetOf<VirtualFile>()
VfsUtilCore.iterateChildrenRecursively(
@@ -68,10 +69,10 @@ public interface AbstractDeclarationFromLibraryModuleProvider {
rootPath: Path,
fs: VirtualFileSystem,
): VirtualFile? {
return if (rootPath.toFile().isDirectory) {
fs.findFileByPath(rootPath.toAbsolutePath().toString())
} else {
return if (Files.isRegularFile(rootPath) && ".jar" in rootPath.toString()) {
jarFileSystem.refreshAndFindFileByPath(rootPath.toAbsolutePath().toString() + URLUtil.JAR_SEPARATOR)
} else {
fs.findFileByPath(rootPath.toAbsolutePath().toString())
}
}
@@ -19,8 +19,8 @@ class KtStaticModuleProvider(
}.ktModule
}
override fun getKtLibraryModules(): Collection<KtLibraryModule> {
return testProjectStructure.allKtModules().filterIsInstance<KtLibraryModule>()
override fun getKtBinaryModules(): Collection<KtBinaryModule> {
return testProjectStructure.allKtModules().filterIsInstance<KtBinaryModule>()
}
override fun getStdlibWithBuiltinsModule(module: KtModule): KtLibraryModule {
@@ -6,12 +6,13 @@
package org.jetbrains.kotlin.analysis.project.structure.impl
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.ProjectScope
import org.jetbrains.kotlin.analysis.project.structure.KtLibraryModule
import org.jetbrains.kotlin.analysis.project.structure.KtLibrarySourceModule
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.analysis.project.structure.KtSourceModule
import com.intellij.util.io.URLUtil
import org.jetbrains.kotlin.analysis.api.impl.base.util.LibraryUtils
import org.jetbrains.kotlin.analysis.project.structure.*
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
import org.jetbrains.kotlin.cli.jvm.config.jvmModularRoots
@@ -22,6 +23,7 @@ import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
import java.nio.file.Path
import java.nio.file.Paths
internal abstract class BaseKtModuleByCompilerConfiguration(
private val compilerConfig: CompilerConfiguration,
@@ -51,7 +53,7 @@ internal class KtSourceModuleByCompilerConfiguration(
project: Project,
ktFiles: List<KtFile>,
) : BaseKtModuleByCompilerConfiguration(compilerConfig, project), KtSourceModule {
override val directRegularDependencies: List<KtLibraryModule> by lazy {
override val directRegularDependencies: List<KtBinaryModule> by lazy {
val libraryRoots = compilerConfig.jvmModularRoots + compilerConfig.jvmClasspathRoots
val libraryRootsByType = libraryRoots.groupBy { it.isDirectory }
buildList {
@@ -69,6 +71,15 @@ internal class KtSourceModuleByCompilerConfiguration(
add(KtLibraryModuleByCompilerConfiguration(compilerConfig, project, root))
}
}
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))
}
add(KtSdkModuleByCompilerConfiguration(compilerConfig, project, "JDK", jdkHomeVirtualFile, binaryRoots))
}
}
}
@@ -98,3 +109,18 @@ internal class KtLibraryModuleByCompilerConfiguration(
override fun getBinaryRoots(): Collection<Path> = binaryRoots
}
internal class KtSdkModuleByCompilerConfiguration(
compilerConfig: CompilerConfiguration,
project: Project,
override val sdkName: String,
sdkHome: VirtualFile?,
private val binaryRoots: Collection<Path>
) : BaseKtModuleByCompilerConfiguration(compilerConfig, project), KtSdkModule {
override val directRegularDependencies: List<KtModule> get() = emptyList()
override val contentScope: GlobalSearchScope =
GlobalSearchScope.fileScope(project, sdkHome)
override fun getBinaryRoots(): Collection<Path> = binaryRoots
}
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.analysis.project.structure.impl
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
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
@@ -20,7 +21,7 @@ internal class KtModuleProviderByCompilerConfiguration(
) : ProjectStructureProvider() {
private val sourceModule = KtSourceModuleByCompilerConfiguration(compilerConfig, project, ktFiles)
private val libraryModules: Collection<KtLibraryModule> by lazy {
private val binaryModules: Collection<KtBinaryModule> by lazy {
sourceModule.directRegularDependencies
}
@@ -34,8 +35,8 @@ internal class KtModuleProviderByCompilerConfiguration(
}
}
override fun getKtLibraryModules(): Collection<KtLibraryModule> {
return libraryModules
override fun getKtBinaryModules(): Collection<KtBinaryModule> {
return binaryModules
}
override fun getStdlibWithBuiltinsModule(module: KtModule): KtLibraryModule? {
@@ -15,10 +15,10 @@ public abstract class ProjectStructureProvider {
public abstract fun getKtModuleForKtElement(element: PsiElement): KtModule
/**
* Returns all [KtLibraryModule]s in this project.
* Returns all dependent [KtBinaryModule]s in this project.
*/
// TODO: We rather need a session or facade that maintains this information.
public abstract fun getKtLibraryModules(): Collection<KtLibraryModule>
public abstract fun getKtBinaryModules(): Collection<KtBinaryModule>
public abstract fun getStdlibWithBuiltinsModule(module: KtModule): KtLibraryModule?
}