mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-04-05 08:31:31 +00:00
Index and locate .kotlin_metadata files in IDE
This commit is contained in:
@@ -42,7 +42,7 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.serialization.builtins.BuiltInsProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.builtins.BuiltInsSerializerExtension
|
||||
import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragment.Companion.METADATA_FILE_EXTENSION
|
||||
import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragment.Companion.DOT_METADATA_FILE_EXTENSION
|
||||
import org.jetbrains.kotlin.serialization.jvm.JvmPackageTable
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.DataOutputStream
|
||||
@@ -132,10 +132,10 @@ open class MetadataSerializer(private val dependOnOldBuiltIns: Boolean) {
|
||||
|
||||
private fun getPackageFilePath(packageFqName: FqName, fileName: String): String =
|
||||
packageFqName.asString().replace('.', '/') + "/" +
|
||||
PackagePartClassUtils.getPartClassName(fileName.substringBeforeLast(".kt")) + METADATA_FILE_EXTENSION
|
||||
PackagePartClassUtils.getPartClassName(fileName.substringBeforeLast(".kt")) + DOT_METADATA_FILE_EXTENSION
|
||||
|
||||
private fun getClassFilePath(classId: ClassId): String =
|
||||
classId.asSingleFqName().asString().replace('.', '/') + METADATA_FILE_EXTENSION
|
||||
classId.asSingleFqName().asString().replace('.', '/') + DOT_METADATA_FILE_EXTENSION
|
||||
|
||||
protected inner class PackageSerializer(
|
||||
private val classes: Collection<DeclarationDescriptor>,
|
||||
|
||||
@@ -39,13 +39,13 @@ class JvmCliVirtualFileFinder(
|
||||
override fun findMetadata(classId: ClassId): InputStream? {
|
||||
assert(!classId.isNestedClass) { "Nested classes are not supported here: $classId" }
|
||||
|
||||
return findBinaryClass(classId, classId.shortClassName.asString() + MetadataPackageFragment.METADATA_FILE_EXTENSION)?.inputStream
|
||||
return findBinaryClass(classId, classId.shortClassName.asString() + MetadataPackageFragment.DOT_METADATA_FILE_EXTENSION)?.inputStream
|
||||
}
|
||||
|
||||
override fun hasMetadataPackage(fqName: FqName): Boolean {
|
||||
var found = false
|
||||
index.traverseDirectoriesInPackage(fqName, continueSearch = { dir, _ ->
|
||||
found = found or dir.children.any { it.extension == MetadataPackageFragment.METADATA_FILE_EXTENSION.substring(1) }
|
||||
found = found or dir.children.any { it.extension == MetadataPackageFragment.METADATA_FILE_EXTENSION }
|
||||
!found
|
||||
})
|
||||
return found
|
||||
|
||||
@@ -132,6 +132,7 @@ class MetadataPackageFragment(
|
||||
}
|
||||
|
||||
companion object {
|
||||
val METADATA_FILE_EXTENSION = ".kotlin_metadata"
|
||||
val DOT_METADATA_FILE_EXTENSION = ".kotlin_metadata"
|
||||
val METADATA_FILE_EXTENSION = "kotlin_metadata"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,5 +34,6 @@
|
||||
<orderEntry type="module" module-name="idea-core" />
|
||||
<orderEntry type="module" module-name="idea-jps-common" />
|
||||
<orderEntry type="module" module-name="cli-common" />
|
||||
<orderEntry type="module" module-name="descriptors" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.idea.decompiler.textBuilder.defaultDecompilerRendere
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.serialization.builtins.BuiltInsProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragment
|
||||
import org.jetbrains.kotlin.serialization.deserialization.NameResolverImpl
|
||||
import java.io.ByteArrayInputStream
|
||||
|
||||
@@ -91,12 +92,14 @@ fun buildDecompiledTextForBuiltIns(builtInFile: VirtualFile): DecompiledText {
|
||||
sealed class BuiltInDefinitionFile {
|
||||
class Incompatible(val version: BuiltInsBinaryVersion) : BuiltInDefinitionFile()
|
||||
|
||||
class Compatible(val proto: BuiltInsProtoBuf.BuiltIns, val packageDirectory: VirtualFile) : BuiltInDefinitionFile() {
|
||||
class Compatible(val proto: BuiltInsProtoBuf.BuiltIns,
|
||||
val packageDirectory: VirtualFile,
|
||||
val isMetadata: Boolean) : BuiltInDefinitionFile() {
|
||||
val nameResolver = NameResolverImpl(proto.strings, proto.qualifiedNames)
|
||||
val packageFqName = nameResolver.getPackageFqName(proto.`package`.getExtension(BuiltInsProtoBuf.packageFqName))
|
||||
|
||||
val classesToDecompile =
|
||||
if (FILTER_OUT_CLASSES_EXISTING_AS_JVM_CLASS_FILES) proto.class_List.filter { classProto ->
|
||||
if (!isMetadata && FILTER_OUT_CLASSES_EXISTING_AS_JVM_CLASS_FILES) proto.class_List.filter { classProto ->
|
||||
shouldDecompileBuiltInClass(nameResolver.getClassId(classProto.fqName))
|
||||
}
|
||||
else proto.class_List
|
||||
@@ -114,7 +117,11 @@ sealed class BuiltInDefinitionFile {
|
||||
@TestOnly set
|
||||
|
||||
fun read(file: VirtualFile): BuiltInDefinitionFile? {
|
||||
val stream = ByteArrayInputStream(file.contentsToByteArray())
|
||||
return read(file.contentsToByteArray(), file)
|
||||
}
|
||||
|
||||
fun read(contents: ByteArray, file: VirtualFile): BuiltInDefinitionFile? {
|
||||
val stream = ByteArrayInputStream(contents)
|
||||
|
||||
val version = BuiltInsBinaryVersion.readFrom(stream)
|
||||
if (!version.isCompatible()) {
|
||||
@@ -122,7 +129,7 @@ sealed class BuiltInDefinitionFile {
|
||||
}
|
||||
|
||||
val proto = BuiltInsProtoBuf.BuiltIns.parseFrom(stream, BuiltInSerializerProtocol.extensionRegistry)
|
||||
val result = BuiltInDefinitionFile.Compatible(proto, file.parent)
|
||||
val result = BuiltInDefinitionFile.Compatible(proto, file.parent, file.extension == MetadataPackageFragment.METADATA_FILE_EXTENSION)
|
||||
if (result.classesToDecompile.isEmpty() &&
|
||||
result.proto.`package`.functionCount == 0 &&
|
||||
result.proto.`package`.propertyCount == 0) {
|
||||
|
||||
@@ -56,11 +56,14 @@ class JsIDEVirtualFileFinder(private val scope: GlobalSearchScope) : JsVirtualFi
|
||||
}
|
||||
|
||||
class JvmIDEVirtualFileFinder(private val scope: GlobalSearchScope) : VirtualFileKotlinClassFinder(), JvmVirtualFileFinder {
|
||||
// TODO
|
||||
override fun findMetadata(classId: ClassId): InputStream? = null
|
||||
override fun findMetadata(classId: ClassId): InputStream? {
|
||||
return findVirtualFileWithHeader(classId, KotlinMetadataFileIndex.KEY, scope, LOG)?.inputStream
|
||||
}
|
||||
|
||||
// TODO
|
||||
override fun hasMetadataPackage(fqName: FqName): Boolean = false
|
||||
override fun hasMetadataPackage(fqName: FqName): Boolean {
|
||||
return !FileBasedIndex.getInstance().processValues(KotlinMetadataFilePackageIndex.KEY,
|
||||
fqName, null, { _, _ -> false }, scope)
|
||||
}
|
||||
|
||||
// TODO: load built-ins metadata from scope
|
||||
override fun findBuiltInsData(packageFqName: FqName): InputStream? = null
|
||||
|
||||
@@ -22,9 +22,14 @@ import com.intellij.util.indexing.*
|
||||
import com.intellij.util.io.IOUtil
|
||||
import com.intellij.util.io.KeyDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.IDEKotlinBinaryClassCache
|
||||
import org.jetbrains.kotlin.idea.decompiler.builtIns.BuiltInDefinitionFile
|
||||
import org.jetbrains.kotlin.idea.decompiler.builtIns.KotlinBuiltInFileType
|
||||
import org.jetbrains.kotlin.idea.decompiler.js.JsMetaFileUtils
|
||||
import org.jetbrains.kotlin.idea.decompiler.js.KotlinJavaScriptMetaFileType
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragment
|
||||
import java.io.DataInput
|
||||
import java.io.DataOutput
|
||||
import java.util.*
|
||||
@@ -101,3 +106,32 @@ object KotlinJavaScriptMetaFileIndex : KotlinFileIndexBase<KotlinJavaScriptMetaF
|
||||
|
||||
override fun dependsOnFileContent(): Boolean = false
|
||||
}
|
||||
|
||||
open class KotlinMetadataFileIndexBase<T>(classOfIndex: Class<T>, indexFunction: (ClassId) -> FqName) : KotlinFileIndexBase<T>(classOfIndex) {
|
||||
override fun getIndexer() = INDEXER
|
||||
|
||||
override fun getInputFilter() = FileBasedIndex.InputFilter { file -> file.fileType == KotlinBuiltInFileType }
|
||||
|
||||
override fun getVersion() = VERSION
|
||||
|
||||
private val VERSION = 1
|
||||
|
||||
private val INDEXER = indexer { fileContent ->
|
||||
if (fileContent.fileType == KotlinBuiltInFileType && fileContent.fileName.endsWith(MetadataPackageFragment.DOT_METADATA_FILE_EXTENSION)) {
|
||||
val builtins = BuiltInDefinitionFile.read(fileContent.content, fileContent.file.parent)
|
||||
(builtins as? BuiltInDefinitionFile.Compatible)?.let { builtinDefFile ->
|
||||
val proto = builtinDefFile.proto
|
||||
proto.class_List.singleOrNull()?.let { cls ->
|
||||
indexFunction(builtinDefFile.nameResolver.getClassId(cls.fqName))
|
||||
} ?: indexFunction(ClassId(builtinDefFile.packageFqName,
|
||||
Name.identifier(fileContent.fileName.substringBeforeLast(MetadataPackageFragment.DOT_METADATA_FILE_EXTENSION))))
|
||||
}
|
||||
} else null
|
||||
}
|
||||
}
|
||||
|
||||
object KotlinMetadataFileIndex : KotlinMetadataFileIndexBase<KotlinMetadataFileIndex>(
|
||||
KotlinMetadataFileIndex::class.java, ClassId::asSingleFqName)
|
||||
|
||||
object KotlinMetadataFilePackageIndex : KotlinMetadataFileIndexBase<KotlinMetadataFilePackageIndex>(
|
||||
KotlinMetadataFilePackageIndex::class.java, ClassId::getPackageFqName)
|
||||
|
||||
@@ -43,11 +43,13 @@ object KotlinModuleMappingIndex : FileBasedIndexExtension<String, PackageParts>(
|
||||
override fun read(input: DataInput): PackageParts? =
|
||||
PackageParts(IOUtil.readUTF(input)).apply {
|
||||
parts.addAll(IOUtil.readStringList(input))
|
||||
metadataParts.addAll(IOUtil.readStringList(input))
|
||||
}
|
||||
|
||||
override fun save(out: DataOutput, value: PackageParts?) {
|
||||
IOUtil.writeUTF(out, value!!.packageFqName)
|
||||
IOUtil.writeStringList(out, value.parts)
|
||||
IOUtil.writeStringList(out, value.metadataParts)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +65,7 @@ object KotlinModuleMappingIndex : FileBasedIndexExtension<String, PackageParts>(
|
||||
return FileBasedIndex.InputFilter { file -> file.extension == ModuleMapping.MAPPING_FILE_EXT }
|
||||
}
|
||||
|
||||
override fun getVersion(): Int = 2
|
||||
override fun getVersion(): Int = 3
|
||||
|
||||
override fun getIndexer(): DataIndexer<String, PackageParts, FileContent> {
|
||||
return DataIndexer<String, PackageParts, FileContent> { inputData ->
|
||||
|
||||
@@ -662,6 +662,8 @@
|
||||
<fileBasedIndex implementation="org.jetbrains.kotlin.idea.versions.KotlinJavaScriptAbiVersionIndex"/>
|
||||
<fileBasedIndex implementation="org.jetbrains.kotlin.idea.vfilefinder.KotlinClassFileIndex"/>
|
||||
<fileBasedIndex implementation="org.jetbrains.kotlin.idea.vfilefinder.KotlinJavaScriptMetaFileIndex"/>
|
||||
<fileBasedIndex implementation="org.jetbrains.kotlin.idea.vfilefinder.KotlinMetadataFileIndex"/>
|
||||
<fileBasedIndex implementation="org.jetbrains.kotlin.idea.vfilefinder.KotlinMetadataFilePackageIndex"/>
|
||||
<fileBasedIndex implementation="org.jetbrains.kotlin.idea.vfilefinder.KotlinModuleMappingIndex"/>
|
||||
|
||||
<idIndexer filetype="Kotlin" implementationClass="org.jetbrains.kotlin.idea.search.KotlinIdIndexer"/>
|
||||
|
||||
@@ -19,9 +19,11 @@ package org.jetbrains.kotlin.idea
|
||||
import com.intellij.openapi.fileTypes.FileTypeConsumer
|
||||
import com.intellij.openapi.fileTypes.FileTypeFactory
|
||||
import org.jetbrains.kotlin.idea.decompiler.builtIns.KotlinBuiltInFileType
|
||||
import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragment
|
||||
|
||||
class KotlinBuiltInFileTypeFactory : FileTypeFactory() {
|
||||
override fun createFileTypes(consumer: FileTypeConsumer) {
|
||||
consumer.consume(KotlinBuiltInFileType, KotlinBuiltInFileType.defaultExtension)
|
||||
consumer.consume(KotlinBuiltInFileType, MetadataPackageFragment.METADATA_FILE_EXTENSION)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,9 +26,7 @@ import com.intellij.openapi.vfs.VirtualFileVisitor
|
||||
import com.intellij.openapi.vfs.newvfs.NewVirtualFile
|
||||
import com.intellij.util.indexing.FileBasedIndex
|
||||
import org.jetbrains.kotlin.idea.KotlinPluginUtil
|
||||
import org.jetbrains.kotlin.idea.vfilefinder.KotlinClassFileIndex
|
||||
import org.jetbrains.kotlin.idea.vfilefinder.KotlinJavaScriptMetaFileIndex
|
||||
import org.jetbrains.kotlin.idea.vfilefinder.KotlinModuleMappingIndex
|
||||
import org.jetbrains.kotlin.idea.vfilefinder.*
|
||||
import org.jetbrains.kotlin.utils.PathUtil
|
||||
import java.io.File
|
||||
|
||||
@@ -64,6 +62,8 @@ class KotlinUpdatePluginComponent : ApplicationComponent {
|
||||
fileBasedIndex.requestRebuild(KotlinJavaScriptAbiVersionIndex.name)
|
||||
fileBasedIndex.requestRebuild(KotlinClassFileIndex.KEY)
|
||||
fileBasedIndex.requestRebuild(KotlinJavaScriptMetaFileIndex.KEY)
|
||||
fileBasedIndex.requestRebuild(KotlinMetadataFileIndex.KEY)
|
||||
fileBasedIndex.requestRebuild(KotlinMetadataFilePackageIndex.KEY)
|
||||
fileBasedIndex.requestRebuild(KotlinModuleMappingIndex.KEY)
|
||||
|
||||
PropertiesComponent.getInstance()?.setValue(INSTALLED_KOTLIN_VERSION, KotlinPluginUtil.getPluginVersion())
|
||||
|
||||
Reference in New Issue
Block a user