@@ -18,130 +18,59 @@ package org.jetbrains.kotlin.idea.decompiler.builtIns
18
18
19
19
import com.intellij.ide.highlighter.JavaClassFileType
20
20
import com.intellij.openapi.vfs.VirtualFile
21
- import com.intellij.psi.FileViewProvider
22
- import com.intellij.psi.PsiManager
23
- import com.intellij.psi.compiled.ClassFileDecompilers
24
21
import org.jetbrains.annotations.TestOnly
25
22
import org.jetbrains.kotlin.builtins.BuiltInSerializerProtocol
26
23
import org.jetbrains.kotlin.builtins.BuiltInsBinaryVersion
27
- import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
28
- import org.jetbrains.kotlin.idea.decompiler.KotlinDecompiledFileViewProvider
29
- import org.jetbrains.kotlin.idea.decompiler.KtDecompiledFile
30
- import org.jetbrains.kotlin.idea.decompiler.common.KotlinMetadataDeserializerForDecompiler
31
- import org.jetbrains.kotlin.idea.decompiler.common.createIncompatibleAbiVersionDecompiledText
32
- import org.jetbrains.kotlin.idea.decompiler.textBuilder.DecompiledText
33
- import org.jetbrains.kotlin.idea.decompiler.textBuilder.buildDecompiledText
34
- import org.jetbrains.kotlin.idea.decompiler.textBuilder.defaultDecompilerRendererOptions
24
+ import org.jetbrains.kotlin.idea.decompiler.common.FileWithMetadata
25
+ import org.jetbrains.kotlin.idea.decompiler.common.KotlinMetadataDecompiler
35
26
import org.jetbrains.kotlin.name.ClassId
36
- import org.jetbrains.kotlin.renderer.DescriptorRenderer
37
27
import org.jetbrains.kotlin.resolve.TargetPlatform
38
28
import org.jetbrains.kotlin.serialization.ProtoBuf
39
- import org.jetbrains.kotlin.serialization.builtins.BuiltInsProtoBuf
40
- import org.jetbrains.kotlin.serialization.deserialization.ClassDeserializer
41
29
import org.jetbrains.kotlin.serialization.deserialization.FlexibleTypeDeserializer
42
30
import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragment
43
- import org.jetbrains.kotlin.serialization.deserialization.NameResolverImpl
44
- import org.jetbrains.kotlin.utils.addIfNotNull
45
31
import java.io.ByteArrayInputStream
46
32
47
- class KotlinBuiltInDecompiler : ClassFileDecompilers .Full () {
48
- private val stubBuilder = KotlinBuiltInStubBuilder ()
49
-
50
- override fun accepts (file : VirtualFile ): Boolean {
51
- return file.fileType == KotlinBuiltInFileType
52
- }
53
-
54
- override fun getStubBuilder () = stubBuilder
55
-
56
- override fun createFileViewProvider (file : VirtualFile , manager : PsiManager , physical : Boolean ): FileViewProvider {
57
- return KotlinDecompiledFileViewProvider (manager, file, physical) { provider ->
58
- if (BuiltInDefinitionFile .read(provider.virtualFile) == null ) {
59
- null
60
- }
61
- else {
62
- KtDecompiledFile (provider) { file ->
63
- buildDecompiledTextForBuiltIns(file)
64
- }
65
- }
66
- }
33
+ class KotlinBuiltInDecompiler : KotlinMetadataDecompiler <BuiltInsBinaryVersion >(
34
+ KotlinBuiltInFileType , KotlinBuiltInStubBuilder (), TargetPlatform .Default , BuiltInSerializerProtocol ,
35
+ FlexibleTypeDeserializer .ThrowException , BuiltInsBinaryVersion .INSTANCE , BuiltInsBinaryVersion .INVALID_VERSION
36
+ ) {
37
+ override fun readFile (bytes : ByteArray , file : VirtualFile ): FileWithMetadata ? {
38
+ return BuiltInDefinitionFile .read(bytes, file)
67
39
}
68
40
}
69
41
70
- private val decompilerRendererForBuiltIns = DescriptorRenderer .withOptions { defaultDecompilerRendererOptions() }
71
-
72
- fun buildDecompiledTextForBuiltIns (builtInFile : VirtualFile ): DecompiledText {
73
- if (builtInFile.fileType != KotlinBuiltInFileType ) {
74
- error(" Unexpected file type ${builtInFile.fileType} " )
75
- }
76
-
77
- val file = BuiltInDefinitionFile .read(builtInFile)
78
- ? : error(" Unexpectedly empty built-in file: $builtInFile " )
79
-
80
- when (file) {
81
- is BuiltInDefinitionFile .Incompatible -> {
82
- return createIncompatibleAbiVersionDecompiledText(BuiltInsBinaryVersion .INSTANCE , file.version)
83
- }
84
- is BuiltInDefinitionFile .Compatible -> {
85
- val packageFqName = file.packageFqName
86
- val resolver = KotlinMetadataDeserializerForDecompiler (
87
- packageFqName, file.proto, file.nameResolver,
88
- TargetPlatform .Default , BuiltInSerializerProtocol , FlexibleTypeDeserializer .ThrowException
89
- )
90
- val declarations = arrayListOf<DeclarationDescriptor >()
91
- declarations.addAll(resolver.resolveDeclarationsInFacade(packageFqName))
92
- for (classProto in file.classesToDecompile) {
93
- val classId = file.nameResolver.getClassId(classProto.fqName)
94
- declarations.addIfNotNull(resolver.resolveTopLevelClass(classId))
42
+ class BuiltInDefinitionFile (
43
+ proto : ProtoBuf .PackageFragment ,
44
+ val packageDirectory : VirtualFile ,
45
+ val isMetadata : Boolean
46
+ ) : FileWithMetadata.Compatible(proto, BuiltInSerializerProtocol ) {
47
+ override val classesToDecompile: List <ProtoBuf .Class >
48
+ get() = super .classesToDecompile.let { classes ->
49
+ if (isMetadata || ! FILTER_OUT_CLASSES_EXISTING_AS_JVM_CLASS_FILES ) classes
50
+ else classes.filter { classProto ->
51
+ shouldDecompileBuiltInClass(nameResolver.getClassId(classProto.fqName))
95
52
}
96
- return buildDecompiledText(packageFqName, declarations, decompilerRendererForBuiltIns)
97
53
}
98
- }
99
- }
100
-
101
- sealed class BuiltInDefinitionFile {
102
- class Incompatible (val version : BuiltInsBinaryVersion ) : BuiltInDefinitionFile()
103
54
104
- class Compatible (val proto : ProtoBuf .PackageFragment ,
105
- val packageDirectory : VirtualFile ,
106
- val isMetadata : Boolean ) : BuiltInDefinitionFile() {
107
- val nameResolver = NameResolverImpl (proto.strings, proto.qualifiedNames)
108
- val packageFqName = nameResolver.getPackageFqName(proto.`package`.getExtension(BuiltInsProtoBuf .packageFqName))
109
-
110
- val classesToDecompile =
111
- proto.class_List.filter { proto ->
112
- val classId = nameResolver.getClassId(proto.fqName)
113
- ! classId.isNestedClass && classId !in ClassDeserializer .BLACK_LIST
114
- }.let { classes ->
115
- if (isMetadata || ! FILTER_OUT_CLASSES_EXISTING_AS_JVM_CLASS_FILES ) classes
116
- else classes.filter { classProto ->
117
- shouldDecompileBuiltInClass(nameResolver.getClassId(classProto.fqName))
118
- }
119
- }
120
-
121
- private fun shouldDecompileBuiltInClass (classId : ClassId ): Boolean {
122
- val realJvmClassFileName = classId.shortClassName.asString() + " ." + JavaClassFileType .INSTANCE .defaultExtension
123
- return packageDirectory.findChild(realJvmClassFileName) == null
124
- }
55
+ private fun shouldDecompileBuiltInClass (classId : ClassId ): Boolean {
56
+ val realJvmClassFileName = classId.shortClassName.asString() + " ." + JavaClassFileType .INSTANCE .defaultExtension
57
+ return packageDirectory.findChild(realJvmClassFileName) == null
125
58
}
126
59
127
60
companion object {
128
61
var FILTER_OUT_CLASSES_EXISTING_AS_JVM_CLASS_FILES = true
129
62
@TestOnly set
130
63
131
- fun read (file : VirtualFile ): BuiltInDefinitionFile ? {
132
- return read(file.contentsToByteArray(), file)
133
- }
134
-
135
- fun read (contents : ByteArray , file : VirtualFile ): BuiltInDefinitionFile ? {
64
+ fun read (contents : ByteArray , file : VirtualFile ): FileWithMetadata ? {
136
65
val stream = ByteArrayInputStream (contents)
137
66
138
67
val version = BuiltInsBinaryVersion .readFrom(stream)
139
68
if (! version.isCompatible()) {
140
- return BuiltInDefinitionFile .Incompatible (version)
69
+ return FileWithMetadata .Incompatible (version)
141
70
}
142
71
143
72
val proto = ProtoBuf .PackageFragment .parseFrom(stream, BuiltInSerializerProtocol .extensionRegistry)
144
- val result = BuiltInDefinitionFile . Compatible (proto, file.parent, file.extension == MetadataPackageFragment .METADATA_FILE_EXTENSION )
73
+ val result = BuiltInDefinitionFile (proto, file.parent, file.extension == MetadataPackageFragment .METADATA_FILE_EXTENSION )
145
74
val packageProto = result.proto.`package`
146
75
if (result.classesToDecompile.isEmpty() &&
147
76
packageProto.typeAliasCount == 0 && packageProto.functionCount == 0 && packageProto.propertyCount == 0 ) {
0 commit comments