Index and locate .kotlin_metadata files in IDE
This commit is contained in:
+3
-3
@@ -42,7 +42,7 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
|||||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||||
import org.jetbrains.kotlin.serialization.builtins.BuiltInsProtoBuf
|
import org.jetbrains.kotlin.serialization.builtins.BuiltInsProtoBuf
|
||||||
import org.jetbrains.kotlin.serialization.builtins.BuiltInsSerializerExtension
|
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 org.jetbrains.kotlin.serialization.jvm.JvmPackageTable
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.DataOutputStream
|
import java.io.DataOutputStream
|
||||||
@@ -132,10 +132,10 @@ open class MetadataSerializer(private val dependOnOldBuiltIns: Boolean) {
|
|||||||
|
|
||||||
private fun getPackageFilePath(packageFqName: FqName, fileName: String): String =
|
private fun getPackageFilePath(packageFqName: FqName, fileName: String): String =
|
||||||
packageFqName.asString().replace('.', '/') + "/" +
|
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 =
|
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(
|
protected inner class PackageSerializer(
|
||||||
private val classes: Collection<DeclarationDescriptor>,
|
private val classes: Collection<DeclarationDescriptor>,
|
||||||
|
|||||||
@@ -39,13 +39,13 @@ class JvmCliVirtualFileFinder(
|
|||||||
override fun findMetadata(classId: ClassId): InputStream? {
|
override fun findMetadata(classId: ClassId): InputStream? {
|
||||||
assert(!classId.isNestedClass) { "Nested classes are not supported here: $classId" }
|
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 {
|
override fun hasMetadataPackage(fqName: FqName): Boolean {
|
||||||
var found = false
|
var found = false
|
||||||
index.traverseDirectoriesInPackage(fqName, continueSearch = { dir, _ ->
|
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
|
!found
|
||||||
})
|
})
|
||||||
return found
|
return found
|
||||||
|
|||||||
+2
-1
@@ -132,6 +132,7 @@ class MetadataPackageFragment(
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
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-core" />
|
||||||
<orderEntry type="module" module-name="idea-jps-common" />
|
<orderEntry type="module" module-name="idea-jps-common" />
|
||||||
<orderEntry type="module" module-name="cli-common" />
|
<orderEntry type="module" module-name="cli-common" />
|
||||||
|
<orderEntry type="module" module-name="descriptors" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
+11
-4
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.idea.decompiler.textBuilder.defaultDecompilerRendere
|
|||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||||
import org.jetbrains.kotlin.serialization.builtins.BuiltInsProtoBuf
|
import org.jetbrains.kotlin.serialization.builtins.BuiltInsProtoBuf
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragment
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.NameResolverImpl
|
import org.jetbrains.kotlin.serialization.deserialization.NameResolverImpl
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
|
|
||||||
@@ -91,12 +92,14 @@ fun buildDecompiledTextForBuiltIns(builtInFile: VirtualFile): DecompiledText {
|
|||||||
sealed class BuiltInDefinitionFile {
|
sealed class BuiltInDefinitionFile {
|
||||||
class Incompatible(val version: BuiltInsBinaryVersion) : 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 nameResolver = NameResolverImpl(proto.strings, proto.qualifiedNames)
|
||||||
val packageFqName = nameResolver.getPackageFqName(proto.`package`.getExtension(BuiltInsProtoBuf.packageFqName))
|
val packageFqName = nameResolver.getPackageFqName(proto.`package`.getExtension(BuiltInsProtoBuf.packageFqName))
|
||||||
|
|
||||||
val classesToDecompile =
|
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))
|
shouldDecompileBuiltInClass(nameResolver.getClassId(classProto.fqName))
|
||||||
}
|
}
|
||||||
else proto.class_List
|
else proto.class_List
|
||||||
@@ -114,7 +117,11 @@ sealed class BuiltInDefinitionFile {
|
|||||||
@TestOnly set
|
@TestOnly set
|
||||||
|
|
||||||
fun read(file: VirtualFile): BuiltInDefinitionFile? {
|
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)
|
val version = BuiltInsBinaryVersion.readFrom(stream)
|
||||||
if (!version.isCompatible()) {
|
if (!version.isCompatible()) {
|
||||||
@@ -122,7 +129,7 @@ sealed class BuiltInDefinitionFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val proto = BuiltInsProtoBuf.BuiltIns.parseFrom(stream, BuiltInSerializerProtocol.extensionRegistry)
|
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() &&
|
if (result.classesToDecompile.isEmpty() &&
|
||||||
result.proto.`package`.functionCount == 0 &&
|
result.proto.`package`.functionCount == 0 &&
|
||||||
result.proto.`package`.propertyCount == 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 {
|
class JvmIDEVirtualFileFinder(private val scope: GlobalSearchScope) : VirtualFileKotlinClassFinder(), JvmVirtualFileFinder {
|
||||||
// TODO
|
override fun findMetadata(classId: ClassId): InputStream? {
|
||||||
override fun findMetadata(classId: ClassId): InputStream? = null
|
return findVirtualFileWithHeader(classId, KotlinMetadataFileIndex.KEY, scope, LOG)?.inputStream
|
||||||
|
}
|
||||||
|
|
||||||
// TODO
|
override fun hasMetadataPackage(fqName: FqName): Boolean {
|
||||||
override fun hasMetadataPackage(fqName: FqName): Boolean = false
|
return !FileBasedIndex.getInstance().processValues(KotlinMetadataFilePackageIndex.KEY,
|
||||||
|
fqName, null, { _, _ -> false }, scope)
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: load built-ins metadata from scope
|
// TODO: load built-ins metadata from scope
|
||||||
override fun findBuiltInsData(packageFqName: FqName): InputStream? = null
|
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.IOUtil
|
||||||
import com.intellij.util.io.KeyDescriptor
|
import com.intellij.util.io.KeyDescriptor
|
||||||
import org.jetbrains.kotlin.idea.caches.IDEKotlinBinaryClassCache
|
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.JsMetaFileUtils
|
||||||
import org.jetbrains.kotlin.idea.decompiler.js.KotlinJavaScriptMetaFileType
|
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.FqName
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragment
|
||||||
import java.io.DataInput
|
import java.io.DataInput
|
||||||
import java.io.DataOutput
|
import java.io.DataOutput
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@@ -101,3 +106,32 @@ object KotlinJavaScriptMetaFileIndex : KotlinFileIndexBase<KotlinJavaScriptMetaF
|
|||||||
|
|
||||||
override fun dependsOnFileContent(): Boolean = false
|
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)
|
||||||
|
|||||||
+3
-1
@@ -43,11 +43,13 @@ object KotlinModuleMappingIndex : FileBasedIndexExtension<String, PackageParts>(
|
|||||||
override fun read(input: DataInput): PackageParts? =
|
override fun read(input: DataInput): PackageParts? =
|
||||||
PackageParts(IOUtil.readUTF(input)).apply {
|
PackageParts(IOUtil.readUTF(input)).apply {
|
||||||
parts.addAll(IOUtil.readStringList(input))
|
parts.addAll(IOUtil.readStringList(input))
|
||||||
|
metadataParts.addAll(IOUtil.readStringList(input))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun save(out: DataOutput, value: PackageParts?) {
|
override fun save(out: DataOutput, value: PackageParts?) {
|
||||||
IOUtil.writeUTF(out, value!!.packageFqName)
|
IOUtil.writeUTF(out, value!!.packageFqName)
|
||||||
IOUtil.writeStringList(out, value.parts)
|
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 }
|
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> {
|
override fun getIndexer(): DataIndexer<String, PackageParts, FileContent> {
|
||||||
return DataIndexer<String, PackageParts, FileContent> { inputData ->
|
return DataIndexer<String, PackageParts, FileContent> { inputData ->
|
||||||
|
|||||||
@@ -662,6 +662,8 @@
|
|||||||
<fileBasedIndex implementation="org.jetbrains.kotlin.idea.versions.KotlinJavaScriptAbiVersionIndex"/>
|
<fileBasedIndex implementation="org.jetbrains.kotlin.idea.versions.KotlinJavaScriptAbiVersionIndex"/>
|
||||||
<fileBasedIndex implementation="org.jetbrains.kotlin.idea.vfilefinder.KotlinClassFileIndex"/>
|
<fileBasedIndex implementation="org.jetbrains.kotlin.idea.vfilefinder.KotlinClassFileIndex"/>
|
||||||
<fileBasedIndex implementation="org.jetbrains.kotlin.idea.vfilefinder.KotlinJavaScriptMetaFileIndex"/>
|
<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"/>
|
<fileBasedIndex implementation="org.jetbrains.kotlin.idea.vfilefinder.KotlinModuleMappingIndex"/>
|
||||||
|
|
||||||
<idIndexer filetype="Kotlin" implementationClass="org.jetbrains.kotlin.idea.search.KotlinIdIndexer"/>
|
<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.FileTypeConsumer
|
||||||
import com.intellij.openapi.fileTypes.FileTypeFactory
|
import com.intellij.openapi.fileTypes.FileTypeFactory
|
||||||
import org.jetbrains.kotlin.idea.decompiler.builtIns.KotlinBuiltInFileType
|
import org.jetbrains.kotlin.idea.decompiler.builtIns.KotlinBuiltInFileType
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragment
|
||||||
|
|
||||||
class KotlinBuiltInFileTypeFactory : FileTypeFactory() {
|
class KotlinBuiltInFileTypeFactory : FileTypeFactory() {
|
||||||
override fun createFileTypes(consumer: FileTypeConsumer) {
|
override fun createFileTypes(consumer: FileTypeConsumer) {
|
||||||
consumer.consume(KotlinBuiltInFileType, KotlinBuiltInFileType.defaultExtension)
|
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.openapi.vfs.newvfs.NewVirtualFile
|
||||||
import com.intellij.util.indexing.FileBasedIndex
|
import com.intellij.util.indexing.FileBasedIndex
|
||||||
import org.jetbrains.kotlin.idea.KotlinPluginUtil
|
import org.jetbrains.kotlin.idea.KotlinPluginUtil
|
||||||
import org.jetbrains.kotlin.idea.vfilefinder.KotlinClassFileIndex
|
import org.jetbrains.kotlin.idea.vfilefinder.*
|
||||||
import org.jetbrains.kotlin.idea.vfilefinder.KotlinJavaScriptMetaFileIndex
|
|
||||||
import org.jetbrains.kotlin.idea.vfilefinder.KotlinModuleMappingIndex
|
|
||||||
import org.jetbrains.kotlin.utils.PathUtil
|
import org.jetbrains.kotlin.utils.PathUtil
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@@ -64,6 +62,8 @@ class KotlinUpdatePluginComponent : ApplicationComponent {
|
|||||||
fileBasedIndex.requestRebuild(KotlinJavaScriptAbiVersionIndex.name)
|
fileBasedIndex.requestRebuild(KotlinJavaScriptAbiVersionIndex.name)
|
||||||
fileBasedIndex.requestRebuild(KotlinClassFileIndex.KEY)
|
fileBasedIndex.requestRebuild(KotlinClassFileIndex.KEY)
|
||||||
fileBasedIndex.requestRebuild(KotlinJavaScriptMetaFileIndex.KEY)
|
fileBasedIndex.requestRebuild(KotlinJavaScriptMetaFileIndex.KEY)
|
||||||
|
fileBasedIndex.requestRebuild(KotlinMetadataFileIndex.KEY)
|
||||||
|
fileBasedIndex.requestRebuild(KotlinMetadataFilePackageIndex.KEY)
|
||||||
fileBasedIndex.requestRebuild(KotlinModuleMappingIndex.KEY)
|
fileBasedIndex.requestRebuild(KotlinModuleMappingIndex.KEY)
|
||||||
|
|
||||||
PropertiesComponent.getInstance()?.setValue(INSTALLED_KOTLIN_VERSION, KotlinPluginUtil.getPluginVersion())
|
PropertiesComponent.getInstance()?.setValue(INSTALLED_KOTLIN_VERSION, KotlinPluginUtil.getPluginVersion())
|
||||||
|
|||||||
Reference in New Issue
Block a user