1616import org .jetbrains .java .decompiler .util .Key ;
1717import org .vineflower .kotlin .metadata .BitEncoding ;
1818import org .vineflower .kotlin .metadata .MetadataNameResolver ;
19+ import org .vineflower .kotlin .metadata .StructKotlinMetadataAttribute ;
1920
2021import java .io .ByteArrayInputStream ;
21- import java .util .Objects ;
2222
2323public class KotlinChooser implements LanguageChooser {
2424 private static final Key <?>[] ANNOTATION_ATTRIBUTES = {
@@ -32,31 +32,32 @@ public class KotlinChooser implements LanguageChooser {
3232
3333 @ Override
3434 public boolean isLanguage (StructClass cl ) {
35- if (!DecompilerContext .getOption (KotlinOptions .DECOMPILE_KOTLIN )) {
35+ boolean decompEnabled = DecompilerContext .getOption (KotlinOptions .DECOMPILE_KOTLIN );
36+ if (!decompEnabled && !DecompilerContext .getOption (KotlinOptions .ALWAYS_EXPORT_METADATA )) {
3637 return false ;
3738 }
3839
3940 // Try to find @Metadata()
40-
4141 for (Key <?> key : ANNOTATION_ATTRIBUTES ) {
4242 if (cl .hasAttribute (key )) {
4343 StructAnnotationAttribute attr = cl .getAttribute ((Key <StructAnnotationAttribute >) key );
4444 for (AnnotationExprent anno : attr .getAnnotations ()) {
4545 if (anno .getClassName ().equals ("kotlin/Metadata" )) {
46- // Line removed as it slows down decompilation significantly, and it doesn't seem to break anything
47- //TODO double-check if it breaks anything
48- // setContextVariables(cl);
49- return true ;
46+ parseMetadataFor (cl );
47+ return decompEnabled ;
5048 }
5149 }
5250 }
5351 }
5452
55- DecompilerContext .setProperty (KotlinDecompilationContext .CURRENT_TYPE , null );
5653 return false ;
5754 }
5855
59- public static void setContextVariables (StructClass cl ) {
56+ public static void parseMetadataFor (StructClass cl ) {
57+ if (cl .getAttribute (StructKotlinMetadataAttribute .KEY ) != null ) {
58+ return ;
59+ }
60+
6061 AnnotationExprent anno = null ;
6162
6263 loop :
@@ -78,62 +79,58 @@ public static void setContextVariables(StructClass cl) {
7879 int d2Index = anno .getParNames ().indexOf ("d2" );
7980
8081 if (kIndex == -1 ) {
81- DecompilerContext .getLogger ().writeMessage ("No k attribute in class metadata for class " + cl .qualifiedName , IFernflowerLogger .Severity .WARN );
82- DecompilerContext .setProperty (KotlinDecompilationContext .CURRENT_TYPE , null );
82+ DecompilerContext .getLogger ().writeMessage ("No k attribute (type) in class metadata for class " + cl .qualifiedName + ", cannot continue Kotlin parsing" , IFernflowerLogger .Severity .WARN );
8383 return ;
8484 }
8585
8686 if (d1Index == -1 ) {
87- DecompilerContext .getLogger ().writeMessage ("No d1 attribute in class metadata for class " + cl .qualifiedName , IFernflowerLogger .Severity .WARN );
88- DecompilerContext .setProperty (KotlinDecompilationContext .CURRENT_TYPE , null );
87+ DecompilerContext .getLogger ().writeMessage ("No d1 attribute (data) in class metadata for class " + cl .qualifiedName + ", cannot continue Kotlin parsing" , IFernflowerLogger .Severity .WARN );
8988 return ;
9089 }
9190
9291 if (d2Index == -1 ) {
93- DecompilerContext .getLogger ().writeMessage ("No d2 attribute in class metadata for class " + cl .qualifiedName , IFernflowerLogger .Severity .WARN );
94- DecompilerContext .setProperty (KotlinDecompilationContext .CURRENT_TYPE , null );
95- return ;
92+ DecompilerContext .getLogger ().writeMessage ("No d2 attribute (strings) in class metadata for class " + cl .qualifiedName , IFernflowerLogger .Severity .WARN );
9693 }
9794
9895 int k = (int ) ((ConstExprent ) anno .getParValues ().get (kIndex )).getValue ();
9996 Exprent d1 = anno .getParValues ().get (d1Index );
100- Exprent d2 = anno .getParValues ().get (d2Index );
97+ Exprent d2 = d2Index != - 1 ? anno .getParValues ().get (d2Index ) : null ;
10198
10299 String [] data1 = getDataFromExpr ((NewExprent ) d1 );
103100
104- String [] data2 = getDataFromExpr ((NewExprent ) d2 );
105-
106101 byte [] buf = BitEncoding .decodeBytes (data1 );
107102
108103 ByteArrayInputStream input = new ByteArrayInputStream (buf );
109- JvmProtoBuf .StringTableTypes types = JvmProtoBuf .StringTableTypes .parseDelimitedFrom (input , EXTENSIONS );
110104
111- DecompilerContext .setProperty (KotlinDecompilationContext .NAME_RESOLVER , new MetadataNameResolver (types , data2 ));
105+ MetadataNameResolver resolver ;
106+ if (d2 != null ) {
107+ String [] data2 = getDataFromExpr ((NewExprent ) d2 );
108+ JvmProtoBuf .StringTableTypes types = JvmProtoBuf .StringTableTypes .parseDelimitedFrom (input , EXTENSIONS );
109+ resolver = new MetadataNameResolver (types , data2 );
110+ } else {
111+ resolver = null ;
112+ }
112113
114+ StructKotlinMetadataAttribute .Metadata metadata ;
113115 if (k == 1 ) { // Class file
114116 ProtoBuf .Class pcl = ProtoBuf .Class .parseFrom (input , EXTENSIONS );
115-
116- DecompilerContext .setProperty (KotlinDecompilationContext .CURRENT_TYPE , KotlinDecompilationContext .KotlinType .CLASS );
117- DecompilerContext .setProperty (KotlinDecompilationContext .CURRENT_CLASS , pcl );
118-
117+ metadata = new StructKotlinMetadataAttribute .Class (cl , pcl );
119118 } else if (k == 2 ) { // File facade
120119 ProtoBuf .Package pcl = ProtoBuf .Package .parseFrom (input , EXTENSIONS );
121- DecompilerContext .setProperty (KotlinDecompilationContext .CURRENT_TYPE , KotlinDecompilationContext .KotlinType .FILE );
122- DecompilerContext .setProperty (KotlinDecompilationContext .FILE_PACKAGE , pcl );
120+ metadata = new StructKotlinMetadataAttribute .File (cl , pcl );
123121 } else if (k == 3 ) { // Synthetic class
124122 ProtoBuf .Function func = ProtoBuf .Function .parseFrom (input , EXTENSIONS );
125- DecompilerContext .setProperty (KotlinDecompilationContext .CURRENT_TYPE , KotlinDecompilationContext .KotlinType .SYNTHETIC_CLASS );
126- DecompilerContext .setProperty (KotlinDecompilationContext .SYNTHETIC_CLASS , func );
123+ metadata = new StructKotlinMetadataAttribute .SyntheticClass (cl , func );
127124 } else if (k == 5 ) { // Multi-file facade
128125 ProtoBuf .Package pcl = ProtoBuf .Package .parseFrom (input , EXTENSIONS );
129- DecompilerContext .setProperty (KotlinDecompilationContext .CURRENT_TYPE , KotlinDecompilationContext .KotlinType .MULTIFILE_CLASS );
130- DecompilerContext .setProperty (KotlinDecompilationContext .MULTIFILE_PACKAGE , pcl );
126+ metadata = new StructKotlinMetadataAttribute .MultifileClass (cl , pcl );
131127 } else {
132- DecompilerContext . setProperty ( KotlinDecompilationContext . CURRENT_TYPE , null ) ;
128+ return ;
133129 }
130+
131+ cl .getAttributes ().put (StructKotlinMetadataAttribute .KEY .name , new StructKotlinMetadataAttribute (metadata , resolver ));
134132 } catch (Exception e ) {
135133 DecompilerContext .getLogger ().writeMessage ("Failed to parse metadata for class " + cl .qualifiedName , IFernflowerLogger .Severity .WARN , e );
136- DecompilerContext .setProperty (KotlinDecompilationContext .CURRENT_TYPE , null );
137134 }
138135 }
139136
0 commit comments