From aa87524513c5f5036e202770cd986fddf534d969 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Tue, 21 Dec 2021 14:16:10 +0300 Subject: [PATCH] Migrate stub and psi builders by classfiles form IJ repository --- .../AnnotationLoaderForStubBuilderImpl.kt | 73 +++++++++++++ .../stub/file/KotlinMetadataStubBuilder.kt | 89 ++++++++++++++++ .../decompiler/psi/KotlinBuiltInDecompiler.kt | 74 +++++++++++++ .../decompiler/psi/KotlinBuiltInFileType.kt | 29 +++++ .../psi/KotlinLabelProviderService.kt | 17 +++ .../psi/KotlinMetadataDecompiler.kt | 100 ++++++++++++++++++ ...KotlinMetadataDeserializerForDecompiler.kt | 66 ++++++++++++ .../psi/text/ByDescriptorIndexer.kt | 2 +- .../psi/text/buildDecompiledText.kt | 2 +- .../idea/KotlinIconProviderService.java | 7 ++ 10 files changed, 457 insertions(+), 2 deletions(-) create mode 100644 analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/AnnotationLoaderForStubBuilderImpl.kt create mode 100644 analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/KotlinMetadataStubBuilder.kt create mode 100644 analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/KotlinBuiltInDecompiler.kt create mode 100644 analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/KotlinBuiltInFileType.kt create mode 100644 analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/KotlinLabelProviderService.kt create mode 100644 analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/KotlinMetadataDecompiler.kt create mode 100644 analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/KotlinMetadataDeserializerForDecompiler.kt diff --git a/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/AnnotationLoaderForStubBuilderImpl.kt b/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/AnnotationLoaderForStubBuilderImpl.kt new file mode 100644 index 00000000000..a7e901fce90 --- /dev/null +++ b/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/AnnotationLoaderForStubBuilderImpl.kt @@ -0,0 +1,73 @@ +/* + * 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.analysis.decompiler.stub.file + +import org.jetbrains.kotlin.metadata.ProtoBuf +import org.jetbrains.kotlin.metadata.deserialization.NameResolver +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.protobuf.MessageLite +import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol +import org.jetbrains.kotlin.serialization.deserialization.* + +class AnnotationLoaderForStubBuilderImpl( + private val protocol: SerializerExtensionProtocol +) : AnnotationLoader { + + override fun loadClassAnnotations(container: ProtoContainer.Class): List = + container.classProto.getExtension(protocol.classAnnotation).orEmpty().map { container.nameResolver.getClassId(it.id) } + + override fun loadCallableAnnotations( + container: ProtoContainer, + proto: MessageLite, + kind: AnnotatedCallableKind + ): List { + val annotations = when (proto) { + is ProtoBuf.Constructor -> proto.getExtension(protocol.constructorAnnotation) + is ProtoBuf.Function -> proto.getExtension(protocol.functionAnnotation) + is ProtoBuf.Property -> when (kind) { + AnnotatedCallableKind.PROPERTY -> proto.getExtension(protocol.propertyAnnotation) + AnnotatedCallableKind.PROPERTY_GETTER -> proto.getExtension(protocol.propertyGetterAnnotation) + AnnotatedCallableKind.PROPERTY_SETTER -> proto.getExtension(protocol.propertySetterAnnotation) + else -> error("Unsupported callable kind with property proto") + } + else -> error("Unknown message: $proto") + }.orEmpty() + return annotations.map { container.nameResolver.getClassId(it.id) } + } + + override fun loadPropertyBackingFieldAnnotations(container: ProtoContainer, proto: ProtoBuf.Property): List = + emptyList() + + override fun loadPropertyDelegateFieldAnnotations(container: ProtoContainer, proto: ProtoBuf.Property): List = + emptyList() + + override fun loadEnumEntryAnnotations(container: ProtoContainer, proto: ProtoBuf.EnumEntry): List = + proto.getExtension(protocol.enumEntryAnnotation).orEmpty().map { container.nameResolver.getClassId(it.id) } + + override fun loadValueParameterAnnotations( + container: ProtoContainer, + callableProto: MessageLite, + kind: AnnotatedCallableKind, + parameterIndex: Int, + proto: ProtoBuf.ValueParameter + ): List = + proto.getExtension(protocol.parameterAnnotation).orEmpty().map { container.nameResolver.getClassId(it.id) } + + override fun loadExtensionReceiverParameterAnnotations( + container: ProtoContainer, + proto: MessageLite, + kind: AnnotatedCallableKind + ): List = emptyList() + + override fun loadTypeAnnotations( + proto: ProtoBuf.Type, + nameResolver: NameResolver + ): List = + proto.getExtension(protocol.typeAnnotation).orEmpty().map { nameResolver.getClassId(it.id) } + + override fun loadTypeParameterAnnotations(proto: ProtoBuf.TypeParameter, nameResolver: NameResolver): List = + proto.getExtension(protocol.typeParameterAnnotation).orEmpty().map { nameResolver.getClassId(it.id) } +} diff --git a/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/KotlinMetadataStubBuilder.kt b/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/KotlinMetadataStubBuilder.kt new file mode 100644 index 00000000000..059c25ab50f --- /dev/null +++ b/analysis/decompiled/decompiler-to-file-stubs/src/org/jetbrains/kotlin/analysis/decompiler/stub/file/KotlinMetadataStubBuilder.kt @@ -0,0 +1,89 @@ +/* + * 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.analysis.decompiler.stub.file + +import com.intellij.openapi.fileTypes.FileType +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.compiled.ClsStubBuilder +import com.intellij.psi.impl.compiled.ClassFileStubBuilder +import com.intellij.psi.stubs.PsiFileStub +import com.intellij.util.indexing.FileContent +import org.jetbrains.kotlin.analysis.decompiler.stub.* +import org.jetbrains.kotlin.metadata.ProtoBuf +import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion +import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl +import org.jetbrains.kotlin.metadata.deserialization.TypeTable +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol +import org.jetbrains.kotlin.serialization.deserialization.ClassDeserializer +import org.jetbrains.kotlin.serialization.deserialization.ProtoBasedClassDataFinder +import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer +import org.jetbrains.kotlin.serialization.deserialization.getClassId + +open class KotlinMetadataStubBuilder( + private val version: Int, + private val fileType: FileType, + private val serializerProtocol: () -> SerializerExtensionProtocol, + private val readFile: (VirtualFile, ByteArray) -> FileWithMetadata? +) : ClsStubBuilder() { + override fun getStubVersion() = ClassFileStubBuilder.STUB_VERSION + version + + override fun buildFileStub(content: FileContent): PsiFileStub<*>? { + val virtualFile = content.file + assert(virtualFile.fileType == fileType) { "Unexpected file type ${virtualFile.fileType}" } + val file = readFile(virtualFile, content.content) ?: return null + + when (file) { + is FileWithMetadata.Incompatible -> { + return createIncompatibleAbiVersionFileStub() + } + is FileWithMetadata.Compatible -> { + val packageProto = file.proto.`package` + val packageFqName = file.packageFqName + val nameResolver = file.nameResolver + val components = ClsStubBuilderComponents( + ProtoBasedClassDataFinder(file.proto, nameResolver, file.version), + AnnotationLoaderForStubBuilderImpl(serializerProtocol()), + virtualFile + ) + val context = components.createContext(nameResolver, packageFqName, TypeTable(packageProto.typeTable)) + + val fileStub = createFileStub(packageFqName, isScript = false) + createPackageDeclarationsStubs( + fileStub, context, + ProtoContainer.Package(packageFqName, context.nameResolver, context.typeTable, source = null), + packageProto + ) + for (classProto in file.classesToDecompile) { + createClassStub( + fileStub, classProto, nameResolver, nameResolver.getClassId(classProto.fqName), source = null, context = context + ) + } + return fileStub + } + } + } + + sealed class FileWithMetadata { + class Incompatible(val version: BinaryVersion) : FileWithMetadata() + + open class Compatible( + val proto: ProtoBuf.PackageFragment, + val version: BinaryVersion, + serializerProtocol: SerializerExtensionProtocol + ) : FileWithMetadata() { + val nameResolver = NameResolverImpl(proto.strings, proto.qualifiedNames) + val packageFqName = FqName(nameResolver.getPackageFqName(proto.`package`.getExtension(serializerProtocol.packageFqName))) + + open val classesToDecompile: List = + proto.class_List.filter { proto -> + val classId = nameResolver.getClassId(proto.fqName) + !classId.isNestedClass && classId !in ClassDeserializer.BLACK_LIST + } + } + } +} + diff --git a/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/KotlinBuiltInDecompiler.kt b/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/KotlinBuiltInDecompiler.kt new file mode 100644 index 00000000000..1100d4f3d95 --- /dev/null +++ b/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/KotlinBuiltInDecompiler.kt @@ -0,0 +1,74 @@ +// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + +package org.jetbrains.kotlin.analysis.decompiler.psi + +import com.intellij.ide.highlighter.JavaClassFileType +import com.intellij.openapi.vfs.VirtualFile +import org.jetbrains.annotations.TestOnly +import org.jetbrains.kotlin.analysis.decompiler.stub.file.KotlinMetadataStubBuilder +import org.jetbrains.kotlin.metadata.ProtoBuf +import org.jetbrains.kotlin.metadata.builtins.BuiltInsBinaryVersion +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.psi.stubs.KotlinStubVersions +import org.jetbrains.kotlin.serialization.deserialization.FlexibleTypeDeserializer +import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragment +import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol +import org.jetbrains.kotlin.serialization.deserialization.getClassId +import java.io.ByteArrayInputStream + +class KotlinBuiltInDecompiler : KotlinMetadataDecompiler( + KotlinBuiltInFileType, { BuiltInSerializerProtocol }, + FlexibleTypeDeserializer.ThrowException, { BuiltInsBinaryVersion.INSTANCE }, { BuiltInsBinaryVersion.INVALID_VERSION }, + KotlinStubVersions.BUILTIN_STUB_VERSION +) { + override fun readFile(bytes: ByteArray, file: VirtualFile): KotlinMetadataStubBuilder.FileWithMetadata? { + return BuiltInDefinitionFile.read(bytes, file) + } +} + +class BuiltInDefinitionFile( + proto: ProtoBuf.PackageFragment, + version: BuiltInsBinaryVersion, + val packageDirectory: VirtualFile, + val isMetadata: Boolean +) : KotlinMetadataStubBuilder.FileWithMetadata.Compatible(proto, version, BuiltInSerializerProtocol) { + override val classesToDecompile: List + get() = super.classesToDecompile.let { classes -> + if (isMetadata || !FILTER_OUT_CLASSES_EXISTING_AS_JVM_CLASS_FILES) classes + else classes.filter { classProto -> + shouldDecompileBuiltInClass(nameResolver.getClassId(classProto.fqName)) + } + } + + private fun shouldDecompileBuiltInClass(classId: ClassId): Boolean { + val realJvmClassFileName = classId.shortClassName.asString() + "." + JavaClassFileType.INSTANCE.defaultExtension + return packageDirectory.findChild(realJvmClassFileName) == null + } + + companion object { + var FILTER_OUT_CLASSES_EXISTING_AS_JVM_CLASS_FILES = true + @TestOnly set + + fun read(contents: ByteArray, file: VirtualFile): KotlinMetadataStubBuilder.FileWithMetadata? { + val stream = ByteArrayInputStream(contents) + + val version = BuiltInsBinaryVersion.readFrom(stream) + if (!version.isCompatible()) { + return Incompatible(version) + } + + val proto = ProtoBuf.PackageFragment.parseFrom(stream, BuiltInSerializerProtocol.extensionRegistry) + val result = + BuiltInDefinitionFile(proto, version, file.parent, file.extension == MetadataPackageFragment.METADATA_FILE_EXTENSION) + val packageProto = result.proto.`package` + if (result.classesToDecompile.isEmpty() && + packageProto.typeAliasCount == 0 && packageProto.functionCount == 0 && packageProto.propertyCount == 0 + ) { + // No declarations to decompile: should skip this file + return null + } + + return result + } + } +} diff --git a/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/KotlinBuiltInFileType.kt b/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/KotlinBuiltInFileType.kt new file mode 100644 index 00000000000..1e640440e5c --- /dev/null +++ b/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/KotlinBuiltInFileType.kt @@ -0,0 +1,29 @@ +// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + +package org.jetbrains.kotlin.analysis.decompiler.psi + +import com.intellij.openapi.fileTypes.FileType +import com.intellij.openapi.vfs.VirtualFile +import org.jetbrains.kotlin.idea.KotlinIconProviderService +import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol +import javax.swing.Icon + +object KotlinBuiltInFileType : FileType { + override fun getName() = "kotlin_builtins" + + override fun getDescription(): String = + KotlinLabelProviderService.getService()?.getLabelForBuiltInFileType() + ?: DEFAULT_DESCRIPTION + + override fun getDefaultExtension() = BuiltInSerializerProtocol.BUILTINS_FILE_EXTENSION + + override fun getIcon(): Icon = KotlinIconProviderService.getInstance().builtInFileIcon + + override fun isBinary() = true + + override fun isReadOnly() = true + + override fun getCharset(file: VirtualFile, content: ByteArray): String? = null + + private const val DEFAULT_DESCRIPTION = "Kotlin built-in declarations" +} diff --git a/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/KotlinLabelProviderService.kt b/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/KotlinLabelProviderService.kt new file mode 100644 index 00000000000..17e8e5b3f8f --- /dev/null +++ b/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/KotlinLabelProviderService.kt @@ -0,0 +1,17 @@ +/* + * 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.analysis.decompiler.psi + +import com.intellij.openapi.application.ApplicationManager + +abstract class KotlinLabelProviderService { + abstract fun getLabelForBuiltInFileType(): String + + companion object { + fun getService(): KotlinLabelProviderService? = + ApplicationManager.getApplication().getServiceIfCreated(KotlinLabelProviderService::class.java) + } +} \ No newline at end of file diff --git a/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/KotlinMetadataDecompiler.kt b/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/KotlinMetadataDecompiler.kt new file mode 100644 index 00000000000..84579ec686c --- /dev/null +++ b/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/KotlinMetadataDecompiler.kt @@ -0,0 +1,100 @@ +// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + +package org.jetbrains.kotlin.analysis.decompiler.psi + +import com.intellij.openapi.fileTypes.FileType +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.FileViewProvider +import com.intellij.psi.PsiManager +import com.intellij.psi.compiled.ClassFileDecompilers +import org.jetbrains.annotations.TestOnly +import org.jetbrains.kotlin.analysis.decompiler.psi.file.KtDecompiledFile +import org.jetbrains.kotlin.analysis.decompiler.psi.text.DecompiledText +import org.jetbrains.kotlin.analysis.decompiler.psi.text.buildDecompiledText +import org.jetbrains.kotlin.analysis.decompiler.psi.text.createIncompatibleAbiVersionDecompiledText +import org.jetbrains.kotlin.analysis.decompiler.psi.text.defaultDecompilerRendererOptions +import org.jetbrains.kotlin.analysis.decompiler.stub.file.KotlinMetadataStubBuilder +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion +import org.jetbrains.kotlin.renderer.DescriptorRenderer +import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol +import org.jetbrains.kotlin.serialization.deserialization.FlexibleTypeDeserializer +import org.jetbrains.kotlin.serialization.deserialization.getClassId +import org.jetbrains.kotlin.utils.addIfNotNull +import java.io.IOException + +abstract class KotlinMetadataDecompiler( + private val fileType: FileType, + private val serializerProtocol: () -> SerializerExtensionProtocol, + private val flexibleTypeDeserializer: FlexibleTypeDeserializer, + private val expectedBinaryVersion: () -> V, + private val invalidBinaryVersion: () -> V, + stubVersion: Int +) : ClassFileDecompilers.Full() { + private val metadataStubBuilder: KotlinMetadataStubBuilder = + KotlinMetadataStubBuilder(stubVersion, fileType, serializerProtocol, ::readFileSafely) + + private val renderer: DescriptorRenderer by lazy { + DescriptorRenderer.withOptions { defaultDecompilerRendererOptions() } + } + + abstract fun readFile(bytes: ByteArray, file: VirtualFile): KotlinMetadataStubBuilder.FileWithMetadata? + + override fun accepts(file: VirtualFile) = file.fileType == fileType + + override fun getStubBuilder() = metadataStubBuilder + + override fun createFileViewProvider(file: VirtualFile, manager: PsiManager, physical: Boolean): FileViewProvider { + return KotlinDecompiledFileViewProvider(manager, file, physical) { provider -> + val virtualFile = provider.virtualFile + readFileSafely(virtualFile)?.let { fileWithMetadata -> + KtDecompiledFile(provider) { + check(it == virtualFile) { + "Unexpected file $it, expected ${virtualFile.fileType}" + } + buildDecompiledText(fileWithMetadata) + } + } + } + } + + @TestOnly + fun readFile(file: VirtualFile) = readFileSafely(file) + + private fun readFileSafely(file: VirtualFile, content: ByteArray? = null): KotlinMetadataStubBuilder.FileWithMetadata? { + if (!file.isValid) return null + + return try { + readFile(content ?: file.contentsToByteArray(false), file) + } catch (e: IOException) { + // This is needed because sometimes we're given VirtualFile instances that point to non-existent .jar entries. + // Such files are valid (isValid() returns true), but an attempt to read their contents results in a FileNotFoundException. + // Note that although calling "refresh()" instead of catching an exception would seem more correct here, + // it's not always allowed and also is likely to degrade performance + null + } + } + + private fun buildDecompiledText(file: KotlinMetadataStubBuilder.FileWithMetadata): DecompiledText { + return when (file) { + is KotlinMetadataStubBuilder.FileWithMetadata.Incompatible -> { + createIncompatibleAbiVersionDecompiledText(expectedBinaryVersion(), file.version) + } + is KotlinMetadataStubBuilder.FileWithMetadata.Compatible -> { + val packageFqName = file.packageFqName + val resolver = KotlinMetadataDeserializerForDecompiler( + packageFqName, file.proto, file.nameResolver, file.version, + serializerProtocol(), flexibleTypeDeserializer + ) + val declarations = arrayListOf() + declarations.addAll(resolver.resolveDeclarationsInFacade(packageFqName)) + for (classProto in file.classesToDecompile) { + val classId = file.nameResolver.getClassId(classProto.fqName) + declarations.addIfNotNull(resolver.resolveTopLevelClass(classId)) + } + buildDecompiledText(packageFqName, declarations, renderer) + } + } + } +} + diff --git a/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/KotlinMetadataDeserializerForDecompiler.kt b/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/KotlinMetadataDeserializerForDecompiler.kt new file mode 100644 index 00000000000..b35c51ef150 --- /dev/null +++ b/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/KotlinMetadataDeserializerForDecompiler.kt @@ -0,0 +1,66 @@ +// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + +package org.jetbrains.kotlin.analysis.decompiler.psi + +import com.intellij.openapi.diagnostic.Logger +import org.jetbrains.kotlin.builtins.DefaultBuiltIns +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.NotFoundClasses +import org.jetbrains.kotlin.incremental.components.LookupTracker +import org.jetbrains.kotlin.metadata.ProtoBuf +import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion +import org.jetbrains.kotlin.metadata.deserialization.NameResolver +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.resolve.sam.SamConversionResolverImpl +import org.jetbrains.kotlin.serialization.SerializerExtensionProtocol +import org.jetbrains.kotlin.serialization.deserialization.* +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope + +class KotlinMetadataDeserializerForDecompiler( + packageFqName: FqName, + private val proto: ProtoBuf.PackageFragment, + private val nameResolver: NameResolver, + private val metadataVersion: BinaryVersion, + serializerProtocol: SerializerExtensionProtocol, + flexibleTypeDeserializer: FlexibleTypeDeserializer +) : DeserializerForDecompilerBase(packageFqName) { + override val builtIns: KotlinBuiltIns get() = DefaultBuiltIns.Instance + + override val deserializationComponents: DeserializationComponents + + init { + val notFoundClasses = NotFoundClasses(storageManager, moduleDescriptor) + + deserializationComponents = DeserializationComponents( + storageManager, moduleDescriptor, DeserializationConfiguration.Default, + ProtoBasedClassDataFinder(proto, nameResolver, metadataVersion), + AnnotationAndConstantLoaderImpl(moduleDescriptor, notFoundClasses, serializerProtocol), packageFragmentProvider, + ResolveEverythingToKotlinAnyLocalClassifierResolver(builtIns), LoggingErrorReporter(LOG), + LookupTracker.DO_NOTHING, flexibleTypeDeserializer, emptyList(), notFoundClasses, + ContractDeserializer.DEFAULT, + extensionRegistryLite = serializerProtocol.extensionRegistry, + samConversionResolver = SamConversionResolverImpl(storageManager, samWithReceiverResolvers = emptyList()) + ) + } + + override fun resolveDeclarationsInFacade(facadeFqName: FqName): List { + assert(facadeFqName == directoryPackageFqName) { + "Was called for $facadeFqName; only members of $directoryPackageFqName package are expected." + } + + val dummyPackageFragment = createDummyPackageFragment(facadeFqName) + val membersScope = DeserializedPackageMemberScope( + dummyPackageFragment, proto.`package`, nameResolver, metadataVersion, containerSource = null, + components = deserializationComponents, + debugName = "scope of dummyPackageFragment ${dummyPackageFragment.fqName} in module " + + "${deserializationComponents.moduleDescriptor} @KotlinMetadataDeserializerForDecompiler" + ) { emptyList() } + + return membersScope.getContributedDescriptors().toList() + } + + companion object { + private val LOG = Logger.getInstance(KotlinMetadataDeserializerForDecompiler::class.java) + } +} diff --git a/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/text/ByDescriptorIndexer.kt b/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/text/ByDescriptorIndexer.kt index fe69bbade0b..ddf4569b6d8 100644 --- a/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/text/ByDescriptorIndexer.kt +++ b/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/text/ByDescriptorIndexer.kt @@ -27,7 +27,7 @@ object ByDescriptorIndexer : DecompiledTextIndexer { return listOf(descriptor.toStringKey()) } - internal fun getDeclarationForDescriptor(descriptor: DeclarationDescriptor, file: KtDecompiledFile): KtDeclaration? { + fun getDeclarationForDescriptor(descriptor: DeclarationDescriptor, file: KtDecompiledFile): KtDeclaration? { val original = descriptor.original if (original is TypeAliasConstructorDescriptor) { diff --git a/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/text/buildDecompiledText.kt b/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/text/buildDecompiledText.kt index afcacf18137..c80b75ab555 100644 --- a/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/text/buildDecompiledText.kt +++ b/analysis/decompiled/decompiler-to-psi/src/org/jetbrains/kotlin/analysis/decompiler/psi/text/buildDecompiledText.kt @@ -38,7 +38,7 @@ fun buildDecompiledText( packageFqName: FqName, descriptors: List, descriptorRenderer: DescriptorRenderer, - indexers: Collection>, + indexers: Collection> = listOf(ByDescriptorIndexer), ): DecompiledText { val builder = StringBuilder() diff --git a/compiler/psi/src/org/jetbrains/kotlin/idea/KotlinIconProviderService.java b/compiler/psi/src/org/jetbrains/kotlin/idea/KotlinIconProviderService.java index c1a599fdabe..51725fe9454 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/idea/KotlinIconProviderService.java +++ b/compiler/psi/src/org/jetbrains/kotlin/idea/KotlinIconProviderService.java @@ -13,6 +13,8 @@ import javax.swing.*; public abstract class KotlinIconProviderService { public abstract Icon getFileIcon(); + public abstract Icon getBuiltInFileIcon(); + public abstract Icon getLightVariableIcon(@NotNull PsiModifierListOwner element, int flags); public static class CompilerKotlinFileIconProviderService extends KotlinIconProviderService { @@ -21,6 +23,11 @@ public abstract class KotlinIconProviderService { return null; } + @Override + public Icon getBuiltInFileIcon() { + return null; + } + @Override public Icon getLightVariableIcon(@NotNull PsiModifierListOwner element, int flags) { return null;