org.jetbrains.kotlin.analysis.decompiler.psi.KotlinBuiltInDecompiler.kt Maven / Gradle / Ivy
// 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.isCompatibleWithCurrentCompilerVersion()) {
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
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy