Support inner classes in -Xjdk-release

#KT-52823 Fixed
This commit is contained in:
Mikhael Bogdanov
2022-07-28 11:50:53 +02:00
committed by Space
parent 8a71d75ee9
commit 90f8f8e14e
24 changed files with 572 additions and 86 deletions
@@ -129,10 +129,7 @@ class ClasspathRootsResolver(
addModularRoots(modules, result)
} else {
//TODO: see also `addJvmSdkRoots` usages, some refactoring is required with moving such logic into one place
val listFoldersForRelease = javaModuleFinder.listFoldersForRelease
listFoldersForRelease.forEach {
result += JavaRoot(it, JavaRoot.RootType.BINARY_SIG)
}
result += JavaRoot(javaModuleFinder.nonModuleRoot.file, JavaRoot.RootType.BINARY_SIG)
}
return RootsAndModules(result, modules)
@@ -134,8 +134,16 @@ class CliJavaModuleFinder(
}
private fun createModuleFromSignature(moduleInfo: JavaModuleInfo): List<JavaModule.Root> {
return listOf(createModuleFromSignature(!isCompilationJDK12OrLater, isCompilationJDK12OrLater, moduleInfo))
}
private fun createModuleFromSignature(
filterPackages: Boolean,
filterModules: Boolean,
moduleInfo: JavaModuleInfo
): JavaModule.Root {
val packageParts =
if (isCompilationJDK12OrLater) emptyMap()
if (!filterPackages) emptyMap()
else hashMapOf<String, Boolean>().also { parts ->
moduleInfo.exports.forEach {
for (part in generateSequence(it.packageFqName) { part -> if (!part.isRoot) part.parent() else null }) {
@@ -148,21 +156,24 @@ class CliJavaModuleFinder(
}
}
val moduleFolders =
if (filterModules)
listFoldersForRelease.filter { virtualFile -> virtualFile.name == moduleInfo.moduleName }
else
listFoldersForRelease
return listFoldersForRelease.mapNotNull { virtualFile ->
val rootFolder = when {
isCompilationJDK12OrLater -> if (virtualFile.name == moduleInfo.moduleName) virtualFile else return@mapNotNull null
else -> {
if (virtualFile.children.none { it.name in packageParts }) return@mapNotNull null
ModuleVirtualFileForRootPart(virtualFile.parent, virtualFile, packageParts, "")
}
}
JavaModule.Root(
rootFolder,
isBinary = true,
isBinarySignature = true
)
}
return JavaModule.Root(
CtSymDirectoryContainer(
ctSymRootFolder ?: ctSymFile,
moduleFolders,
packageParts,
"",
moduleInfo.moduleName,
skipPackageCheck = !filterPackages
),
isBinary = true,
isBinarySignature = true
)
}
private fun codeFor(release: Int): String = release.toString(36).toUpperCase()
@@ -170,7 +181,12 @@ class CliJavaModuleFinder(
private fun matchesRelease(fileName: String, release: Int) =
!fileName.contains("-") && fileName.contains(codeFor(release)) // skip `*-modules`
val listFoldersForRelease: List<VirtualFile> by lazy {
val nonModuleRoot: JavaModule.Root by lazy {
createModuleFromSignature(false, false, JavaModuleInfo("*", emptyList(), emptyList(), emptyList()))
}
private val listFoldersForRelease: List<VirtualFile> by lazy {
if (ctSymRootFolder == null) emptyList()
else ctSymRootFolder!!.children.filter { matchesRelease(it.name, jdkRelease!!) }.flatMap {
if (isCompilationJDK12OrLater)
@@ -179,7 +195,7 @@ class CliJavaModuleFinder(
listOf(it)
}
}.apply {
if (isEmpty()) reportError("'-Xrelease=${jdkRelease}' option is not supported by used JDK: ${jdkHome?.path}")
if (isEmpty()) reportError("'-Xjdk-release=${jdkRelease}' option is not supported by used JDK: ${jdkHome?.path}")
}
}
@@ -197,7 +213,7 @@ class CliJavaModuleFinder(
children.forEach {
result[it.name] = it
}
} ?: reportError("Can't find modules signatures in `ct.sym` file for `-Xrelease=$jdkRelease` in ${ctSymFile!!.path}")
} ?: reportError("Can't find modules signatures in `ct.sym` file for `-Xjdk-release=$jdkRelease` in ${ctSymFile!!.path}")
}
}
return result
@@ -0,0 +1,42 @@
/*
* 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.cli.jvm.modules
import com.intellij.openapi.vfs.VirtualFile
import java.io.InputStream
class CtSymClassVirtualFile(
private val parent: VirtualFile?,
private val file: VirtualFile
): VirtualFile() {
override fun getName() = file.name
override fun getFileSystem() = file.fileSystem
override fun getPath() = file.path
override fun isWritable() = file.isWritable
override fun isDirectory() = false
override fun isValid() = file.isValid
override fun getParent(): VirtualFile? = parent
override fun getChildren(): Array<VirtualFile>? = null
override fun getOutputStream(p0: Any?, p1: Long, p2: Long) = file.getOutputStream(p0, p1, p2)
override fun contentsToByteArray(): ByteArray = file.contentsToByteArray()
override fun getTimeStamp() = file.timeStamp
override fun getLength() = file.length
override fun refresh(p0: Boolean, p1: Boolean, p2: Runnable?) = file.refresh(p0, p1, p2)
override fun getInputStream(): InputStream? = file.inputStream
}
@@ -0,0 +1,83 @@
/*
* Copyright 2010-2021 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.cli.jvm.modules
import com.intellij.openapi.vfs.VirtualFile
import java.io.InputStream
class CtSymDirectoryContainer(
private val parent: VirtualFile?,
private val rootOrPackageParts: List<VirtualFile>,
private val packages: Map<String, Boolean>,
private val currentPackage: String,
private val moduleRoot: String,
private val skipPackageCheck: Boolean
) : VirtualFile() {
private val _path by lazy { parent?.path + currentPackage + "/" }
private val _fileSystem by lazy { parent!!.fileSystem }
private val _isValid by lazy { rootOrPackageParts.all { it.isValid } }
private val _children by lazy {
val children = rootOrPackageParts.flatMap { it.children?.toList() ?: emptyList() }
if (children.isEmpty()) return@lazy emptyArray()
val isExported = skipPackageCheck || packages.getOrDefault(currentPackage, false)
val containers = mutableMapOf<String, Pair<CtSymDirectoryContainer, MutableList<VirtualFile>>>()
children.mapNotNull { child ->
when {
child.isDirectory -> {
val childPackage = if (currentPackage.isEmpty()) child.name else currentPackage + "." + child.name
if (skipPackageCheck || packages.contains(childPackage)) {
containers.getOrPut(childPackage) {
val list = mutableListOf<VirtualFile>()
CtSymDirectoryContainer(
this,
list,
packages,
childPackage,
moduleRoot,
skipPackageCheck
) to list
}.also { it.second.add(child) }.first
} else null
}
isExported -> CtSymClassVirtualFile(this, child)
else -> null
}
}.toTypedArray()
}
override fun getName() = currentPackage.substringAfterLast(".")
override fun getFileSystem() = _fileSystem
override fun getPath() = _path
override fun isWritable() = false
override fun isDirectory() = true
override fun isValid() = _isValid
override fun getParent(): VirtualFile? = parent
override fun getChildren(): Array<VirtualFile>? = _children
override fun getOutputStream(p0: Any?, p1: Long, p2: Long) = error("not supported")
override fun contentsToByteArray(): ByteArray = error("not supported")
override fun getTimeStamp() = error("not supported")
override fun getLength() = error("not supported")
override fun refresh(p0: Boolean, p1: Boolean, p2: Runnable?) {}
override fun getInputStream(): InputStream? = error("not supported")
}
@@ -1,62 +0,0 @@
/*
* Copyright 2010-2021 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.cli.jvm.modules
import com.intellij.openapi.vfs.VirtualFile
import java.io.InputStream
class ModuleVirtualFileForRootPart(
private val parent: VirtualFile?,
private val virtualFile: VirtualFile,
private val packages: Map<String, Boolean>,
private val currentPackage: String
) : VirtualFile() {
private val _children by lazy {
val children = virtualFile.children ?: return@lazy null
val isExported = packages.getOrDefault(currentPackage, false)
children.mapNotNull {
when {
it.isDirectory -> {
val childPackage = if (currentPackage.isEmpty()) it.name else currentPackage + "." + it.name
if (packages.contains(childPackage))
ModuleVirtualFileForRootPart(this, it, packages, childPackage)
else null
}
isExported -> ModuleVirtualFileForRootPart(this, it, emptyMap(), currentPackage)
else -> null
}
}.toTypedArray<VirtualFile>()
}
override fun getName() = virtualFile.name
override fun getFileSystem() = virtualFile.fileSystem
override fun getPath() = virtualFile.path
override fun isWritable() = virtualFile.isWritable
override fun isDirectory() = virtualFile.isDirectory
override fun isValid() = virtualFile.isValid
override fun getParent(): VirtualFile? = parent
override fun getChildren(): Array<VirtualFile>? = _children
override fun getOutputStream(p0: Any?, p1: Long, p2: Long) = virtualFile.getOutputStream(p0, p1, p2)
override fun contentsToByteArray(): ByteArray = virtualFile.contentsToByteArray()
override fun getTimeStamp() = virtualFile.timeStamp
override fun getLength() = virtualFile.length
override fun refresh(p0: Boolean, p1: Boolean, p2: Runnable?) = virtualFile.refresh(p0, p1, p2)
override fun getInputStream(): InputStream? = virtualFile.inputStream
}