diff --git a/compiler/builtins-serializer/src/org/jetbrains/kotlin/serialization/MetadataSerializer.kt b/compiler/builtins-serializer/src/org/jetbrains/kotlin/serialization/MetadataSerializer.kt index 7dca39927d5..c4280e0d3cb 100644 --- a/compiler/builtins-serializer/src/org/jetbrains/kotlin/serialization/MetadataSerializer.kt +++ b/compiler/builtins-serializer/src/org/jetbrains/kotlin/serialization/MetadataSerializer.kt @@ -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, diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/JvmCliVirtualFileFinder.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/JvmCliVirtualFileFinder.kt index 86dbf41e106..e2cf4027d42 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/JvmCliVirtualFileFinder.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/JvmCliVirtualFileFinder.kt @@ -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 diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MetadataPackageFragmentProvider.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MetadataPackageFragmentProvider.kt index bf25ae0504d..863d3816453 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MetadataPackageFragmentProvider.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/MetadataPackageFragmentProvider.kt @@ -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" } } diff --git a/idea/idea-analysis/idea-analysis.iml b/idea/idea-analysis/idea-analysis.iml index f55193503f4..41cf1cdfca0 100644 --- a/idea/idea-analysis/idea-analysis.iml +++ b/idea/idea-analysis/idea-analysis.iml @@ -34,5 +34,6 @@ + \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/builtIns/KotlinBuiltInDecompiler.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/builtIns/KotlinBuiltInDecompiler.kt index d6a0f045464..5f06aeb77ec 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/builtIns/KotlinBuiltInDecompiler.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/builtIns/KotlinBuiltInDecompiler.kt @@ -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) { diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/vfilefinder/fileFinders.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/vfilefinder/fileFinders.kt index bc46b39a46f..9e3ab75eb02 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/vfilefinder/fileFinders.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/vfilefinder/fileFinders.kt @@ -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 diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/vfilefinder/fileIndexes.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/vfilefinder/fileIndexes.kt index 97750e0ed16..2fe7742ca78 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/vfilefinder/fileIndexes.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/vfilefinder/fileIndexes.kt @@ -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(classOfIndex: Class, indexFunction: (ClassId) -> FqName) : KotlinFileIndexBase(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::class.java, ClassId::asSingleFqName) + +object KotlinMetadataFilePackageIndex : KotlinMetadataFileIndexBase( + KotlinMetadataFilePackageIndex::class.java, ClassId::getPackageFqName) diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/vfilefinder/moduleMappingIndexes.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/vfilefinder/moduleMappingIndexes.kt index b1d9fb4eb94..88350db2e45 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/vfilefinder/moduleMappingIndexes.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/vfilefinder/moduleMappingIndexes.kt @@ -43,11 +43,13 @@ object KotlinModuleMappingIndex : FileBasedIndexExtension( 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( return FileBasedIndex.InputFilter { file -> file.extension == ModuleMapping.MAPPING_FILE_EXT } } - override fun getVersion(): Int = 2 + override fun getVersion(): Int = 3 override fun getIndexer(): DataIndexer { return DataIndexer { inputData -> diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 3c460fee48f..e11d744e16a 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -662,6 +662,8 @@ + + diff --git a/idea/src/org/jetbrains/kotlin/idea/KotlinBuiltInFileTypeFactory.kt b/idea/src/org/jetbrains/kotlin/idea/KotlinBuiltInFileTypeFactory.kt index 769f071ee0c..176c9a159f3 100644 --- a/idea/src/org/jetbrains/kotlin/idea/KotlinBuiltInFileTypeFactory.kt +++ b/idea/src/org/jetbrains/kotlin/idea/KotlinBuiltInFileTypeFactory.kt @@ -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) } } diff --git a/idea/src/org/jetbrains/kotlin/idea/versions/KotlinUpdatePluginComponent.kt b/idea/src/org/jetbrains/kotlin/idea/versions/KotlinUpdatePluginComponent.kt index d81a759afe8..4c0d957eb92 100644 --- a/idea/src/org/jetbrains/kotlin/idea/versions/KotlinUpdatePluginComponent.kt +++ b/idea/src/org/jetbrains/kotlin/idea/versions/KotlinUpdatePluginComponent.kt @@ -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())