Migrate stub and psi builders by classfiles form IJ repository
This commit is contained in:
+73
@@ -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<ClassId> {
|
||||||
|
|
||||||
|
override fun loadClassAnnotations(container: ProtoContainer.Class): List<ClassId> =
|
||||||
|
container.classProto.getExtension(protocol.classAnnotation).orEmpty().map { container.nameResolver.getClassId(it.id) }
|
||||||
|
|
||||||
|
override fun loadCallableAnnotations(
|
||||||
|
container: ProtoContainer,
|
||||||
|
proto: MessageLite,
|
||||||
|
kind: AnnotatedCallableKind
|
||||||
|
): List<ClassId> {
|
||||||
|
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<ClassId> =
|
||||||
|
emptyList()
|
||||||
|
|
||||||
|
override fun loadPropertyDelegateFieldAnnotations(container: ProtoContainer, proto: ProtoBuf.Property): List<ClassId> =
|
||||||
|
emptyList()
|
||||||
|
|
||||||
|
override fun loadEnumEntryAnnotations(container: ProtoContainer, proto: ProtoBuf.EnumEntry): List<ClassId> =
|
||||||
|
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<ClassId> =
|
||||||
|
proto.getExtension(protocol.parameterAnnotation).orEmpty().map { container.nameResolver.getClassId(it.id) }
|
||||||
|
|
||||||
|
override fun loadExtensionReceiverParameterAnnotations(
|
||||||
|
container: ProtoContainer,
|
||||||
|
proto: MessageLite,
|
||||||
|
kind: AnnotatedCallableKind
|
||||||
|
): List<ClassId> = emptyList()
|
||||||
|
|
||||||
|
override fun loadTypeAnnotations(
|
||||||
|
proto: ProtoBuf.Type,
|
||||||
|
nameResolver: NameResolver
|
||||||
|
): List<ClassId> =
|
||||||
|
proto.getExtension(protocol.typeAnnotation).orEmpty().map { nameResolver.getClassId(it.id) }
|
||||||
|
|
||||||
|
override fun loadTypeParameterAnnotations(proto: ProtoBuf.TypeParameter, nameResolver: NameResolver): List<ClassId> =
|
||||||
|
proto.getExtension(protocol.typeParameterAnnotation).orEmpty().map { nameResolver.getClassId(it.id) }
|
||||||
|
}
|
||||||
+89
@@ -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<ProtoBuf.Class> =
|
||||||
|
proto.class_List.filter { proto ->
|
||||||
|
val classId = nameResolver.getClassId(proto.fqName)
|
||||||
|
!classId.isNestedClass && classId !in ClassDeserializer.BLACK_LIST
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
+74
@@ -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<BuiltInsBinaryVersion>(
|
||||||
|
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<ProtoBuf.Class>
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+29
@@ -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"
|
||||||
|
}
|
||||||
+17
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
+100
@@ -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<out V : BinaryVersion>(
|
||||||
|
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<DeclarationDescriptor>()
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
+66
@@ -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<DeclarationDescriptor> {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -27,7 +27,7 @@ object ByDescriptorIndexer : DecompiledTextIndexer<String> {
|
|||||||
return listOf(descriptor.toStringKey())
|
return listOf(descriptor.toStringKey())
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun getDeclarationForDescriptor(descriptor: DeclarationDescriptor, file: KtDecompiledFile): KtDeclaration? {
|
fun getDeclarationForDescriptor(descriptor: DeclarationDescriptor, file: KtDecompiledFile): KtDeclaration? {
|
||||||
val original = descriptor.original
|
val original = descriptor.original
|
||||||
|
|
||||||
if (original is TypeAliasConstructorDescriptor) {
|
if (original is TypeAliasConstructorDescriptor) {
|
||||||
|
|||||||
+1
-1
@@ -38,7 +38,7 @@ fun buildDecompiledText(
|
|||||||
packageFqName: FqName,
|
packageFqName: FqName,
|
||||||
descriptors: List<DeclarationDescriptor>,
|
descriptors: List<DeclarationDescriptor>,
|
||||||
descriptorRenderer: DescriptorRenderer,
|
descriptorRenderer: DescriptorRenderer,
|
||||||
indexers: Collection<DecompiledTextIndexer<*>>,
|
indexers: Collection<DecompiledTextIndexer<*>> = listOf(ByDescriptorIndexer),
|
||||||
): DecompiledText {
|
): DecompiledText {
|
||||||
val builder = StringBuilder()
|
val builder = StringBuilder()
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import javax.swing.*;
|
|||||||
|
|
||||||
public abstract class KotlinIconProviderService {
|
public abstract class KotlinIconProviderService {
|
||||||
public abstract Icon getFileIcon();
|
public abstract Icon getFileIcon();
|
||||||
|
public abstract Icon getBuiltInFileIcon();
|
||||||
|
|
||||||
public abstract Icon getLightVariableIcon(@NotNull PsiModifierListOwner element, int flags);
|
public abstract Icon getLightVariableIcon(@NotNull PsiModifierListOwner element, int flags);
|
||||||
|
|
||||||
public static class CompilerKotlinFileIconProviderService extends KotlinIconProviderService {
|
public static class CompilerKotlinFileIconProviderService extends KotlinIconProviderService {
|
||||||
@@ -21,6 +23,11 @@ public abstract class KotlinIconProviderService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Icon getBuiltInFileIcon() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Icon getLightVariableIcon(@NotNull PsiModifierListOwner element, int flags) {
|
public Icon getLightVariableIcon(@NotNull PsiModifierListOwner element, int flags) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
Reference in New Issue
Block a user