Skip to content

Commit 2362ee7

Browse files
committed
Convert to using metadata's Flags util class universally
Modified metadata jar made in Vineflower/kt-metadata-minifier@5bd1751
1 parent fec7cd2 commit 2362ee7

File tree

10 files changed

+135
-364
lines changed

10 files changed

+135
-364
lines changed

plugins/kotlin/libs/metadata.jar

-11.7 KB
Binary file not shown.

plugins/kotlin/src/main/java/org/vineflower/kotlin/KotlinWriter.java

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
package org.vineflower.kotlin;
33

44
import kotlin.metadata.internal.metadata.ProtoBuf;
5+
import kotlin.metadata.internal.metadata.deserialization.Flags;
56
import net.fabricmc.fernflower.api.IFabricJavadocProvider;
67
import org.jetbrains.java.decompiler.api.plugin.StatementWriter;
78
import org.jetbrains.java.decompiler.code.CodeConstants;
@@ -32,19 +33,21 @@
3233
import org.jetbrains.java.decompiler.struct.gen.generics.GenericClassDescriptor;
3334
import org.jetbrains.java.decompiler.struct.gen.generics.GenericFieldDescriptor;
3435
import org.jetbrains.java.decompiler.struct.gen.generics.GenericMethodDescriptor;
35-
import org.jetbrains.java.decompiler.util.*;
36+
import org.jetbrains.java.decompiler.util.InterpreterUtil;
37+
import org.jetbrains.java.decompiler.util.Key;
38+
import org.jetbrains.java.decompiler.util.TextBuffer;
39+
import org.jetbrains.java.decompiler.util.TextUtil;
3640
import org.jetbrains.java.decompiler.util.collections.VBStyleCollection;
3741
import org.vineflower.kotlin.expr.KAnnotationExprent;
3842
import org.vineflower.kotlin.metadata.MetadataNameResolver;
3943
import org.vineflower.kotlin.struct.*;
4044
import org.vineflower.kotlin.util.KTypes;
4145
import org.vineflower.kotlin.util.KUtils;
42-
import org.vineflower.kotlin.util.ProtobufFlags;
4346

4447
import java.io.IOException;
4548
import java.util.*;
4649

47-
public class KotlinWriter implements StatementWriter {
50+
public class KotlinWriter implements StatementWriter, Flags {
4851
private static final Set<String> ERROR_DUMP_STOP_POINTS = new HashSet<>(Arrays.asList(
4952
"Fernflower.decompileContext",
5053
"MethodProcessor.codeToJava",
@@ -223,14 +226,14 @@ public void writeClass(ClassNode node, TextBuffer buffer, int indent) {
223226

224227
ProtoBuf.Class proto = KotlinDecompilationContext.getCurrentClass();
225228

226-
ProtobufFlags.Class kotlinFlags;
229+
int kotlinFlags;
227230
if (proto != null) {
228-
kotlinFlags = new ProtobufFlags.Class(proto.getFlags());
231+
kotlinFlags = proto.getFlags();
229232
} else {
230233
if (KotlinDecompilationContext.getCurrentType() == null) {
231234
appendComment(buffer, "Class flags could not be determined", indent);
232235
}
233-
kotlinFlags = new ProtobufFlags.Class(0);
236+
kotlinFlags = 0;
234237
}
235238

236239
if (DecompilerContext.getOption(IFernflowerPreferences.SOURCE_FILE_COMMENTS)) {
@@ -247,7 +250,7 @@ public void writeClass(ClassNode node, TextBuffer buffer, int indent) {
247250
}
248251
}
249252

250-
if (kotlinFlags.kind == ProtoBuf.Class.Kind.ANNOTATION_CLASS || cl.hasModifier(CodeConstants.ACC_ANNOTATION)) {
253+
if (CLASS_KIND.get(kotlinFlags) == ProtoBuf.Class.Kind.ANNOTATION_CLASS || cl.hasModifier(CodeConstants.ACC_ANNOTATION)) {
251254
// Kotlin's annotation classes are treated quite differently from other classes
252255
writeAnnotationDefinition(node, buffer, indent, propertyData, functions, constructorData);
253256
return;
@@ -703,7 +706,7 @@ private void writeAnnotationDefinition(ClassNode node, TextBuffer buffer, int in
703706
buffer.appendLineSeparator();
704707
}
705708

706-
private void writeClassDefinition(ClassNode node, TextBuffer buffer, int indent, KConstructor.Data constructorData, ProtobufFlags.Class kotlinFlags) {
709+
private void writeClassDefinition(ClassNode node, TextBuffer buffer, int indent, KConstructor.Data constructorData, int kotlinFlags) {
707710
if (node.type == ClassNode.Type.ANONYMOUS) {
708711
buffer.append(" {").appendLineSeparator();
709712
return;
@@ -739,31 +742,35 @@ private void writeClassDefinition(ClassNode node, TextBuffer buffer, int indent,
739742

740743
buffer.appendIndent(indent);
741744

742-
if (kotlinFlags.visibility != ProtoBuf.Visibility.PUBLIC || DecompilerContext.getOption(KotlinOptions.SHOW_PUBLIC_VISIBILITY)) {
743-
buffer.append(ProtobufFlags.toString(kotlinFlags.visibility)).append(' ');
745+
if (VISIBILITY.get(kotlinFlags) != ProtoBuf.Visibility.PUBLIC || DecompilerContext.getOption(KotlinOptions.SHOW_PUBLIC_VISIBILITY)) {
746+
KUtils.appendVisibility(buffer, VISIBILITY.get(kotlinFlags));
747+
buffer.append(" ");
744748
}
745749

746-
if (kotlinFlags.isExpect) {
750+
if (IS_EXPECT_CLASS.get(kotlinFlags)) {
747751
buffer.append("expect ");
748752
}
749753

750-
if ((!isInterface && kotlinFlags.modality != ProtoBuf.Modality.FINAL) || kotlinFlags.modality == ProtoBuf.Modality.SEALED) {
751-
buffer.append(ProtobufFlags.toString(kotlinFlags.modality)).append(' ');
752-
}
754+
buffer.append(switch (MODALITY.get(kotlinFlags)) {
755+
case FINAL -> isInterface ? "final " : "";
756+
case OPEN -> isInterface ? "" : "open ";
757+
case ABSTRACT -> isInterface ? "" : "abstract ";
758+
case SEALED -> "sealed ";
759+
});
753760

754-
if (kotlinFlags.isExternal) {
761+
if (IS_EXTERNAL_CLASS.get(kotlinFlags)) {
755762
buffer.append("external ");
756763
}
757-
if (kotlinFlags.isInner) {
764+
if (IS_INNER.get(kotlinFlags)) {
758765
buffer.append("inner ");
759766
}
760-
if (kotlinFlags.isFun) {
767+
if (IS_FUN_INTERFACE.get(kotlinFlags)) {
761768
buffer.append("fun ");
762769
}
763-
if (kotlinFlags.isInline) {
770+
if (IS_INLINE.get(kotlinFlags)) {
764771
buffer.append("inline ");
765772
}
766-
if (kotlinFlags.isData) {
773+
if (IS_DATA.get(kotlinFlags)) {
767774
buffer.append("data ");
768775
}
769776

@@ -773,15 +780,15 @@ private void writeClassDefinition(ClassNode node, TextBuffer buffer, int indent,
773780
buffer.append("interface");
774781
} else if (isAnnotation) {
775782
buffer.append("annotation class");
776-
} else if (kotlinFlags.kind == ProtoBuf.Class.Kind.OBJECT) {
783+
} else if (CLASS_KIND.get(kotlinFlags) == ProtoBuf.Class.Kind.OBJECT) {
777784
buffer.append("object");
778-
} else if (kotlinFlags.kind == ProtoBuf.Class.Kind.COMPANION_OBJECT) {
785+
} else if (CLASS_KIND.get(kotlinFlags) == ProtoBuf.Class.Kind.COMPANION_OBJECT) {
779786
buffer.append("companion object");
780787
} else {
781788
buffer.append("class");
782789
}
783790

784-
if (kotlinFlags.kind != ProtoBuf.Class.Kind.COMPANION_OBJECT || !node.simpleName.equals("Companion")) {
791+
if (CLASS_KIND.get(kotlinFlags) != ProtoBuf.Class.Kind.COMPANION_OBJECT || !node.simpleName.equals("Companion")) {
785792
buffer.append(" ").append(toValidKotlinIdentifier(node.simpleName));
786793
}
787794

plugins/kotlin/src/main/java/org/vineflower/kotlin/struct/DefaultArgsMap.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.vineflower.kotlin.struct;
22

3+
import kotlin.metadata.internal.metadata.deserialization.Flags;
34
import org.jetbrains.java.decompiler.code.CodeConstants;
45
import org.jetbrains.java.decompiler.main.DecompilerContext;
56
import org.jetbrains.java.decompiler.main.rels.MethodWrapper;
@@ -120,7 +121,7 @@ public static DefaultArgsMap from(MethodWrapper defaults, MethodWrapper calling,
120121

121122
if (KUtils.assertionsEnabled()) {
122123
for (KParameter param : params) {
123-
assert map.containsKey(param) == param.flags().declaresDefault : "Parameter " + param.name() + " has default value but no default value was found";
124+
assert map.containsKey(param) == Flags.DECLARES_DEFAULT_VALUE.get(param.flags()) : "Parameter " + param.name() + " has default value but no default value was found";
124125
}
125126
}
126127

plugins/kotlin/src/main/java/org/vineflower/kotlin/struct/KConstructor.java

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.vineflower.kotlin.struct;
22

33
import kotlin.metadata.internal.metadata.ProtoBuf;
4+
import kotlin.metadata.internal.metadata.deserialization.Flags;
45
import kotlin.metadata.internal.metadata.jvm.JvmProtoBuf;
56
import org.jetbrains.java.decompiler.main.ClassesProcessor;
67
import org.jetbrains.java.decompiler.main.DecompilerContext;
@@ -22,21 +23,20 @@
2223
import org.vineflower.kotlin.KotlinWriter;
2324
import org.vineflower.kotlin.metadata.MetadataNameResolver;
2425
import org.vineflower.kotlin.util.KUtils;
25-
import org.vineflower.kotlin.util.ProtobufFlags;
2626

2727
import java.util.HashMap;
2828
import java.util.List;
2929
import java.util.Map;
3030

3131
public record KConstructor(
3232
KParameter[] parameters,
33-
ProtobufFlags.Constructor flags,
33+
int flags,
3434
MethodWrapper method,
3535
boolean isPrimary,
3636
DefaultArgsMap defaultArgs,
3737
ClassesProcessor.ClassNode node,
38-
ProtobufFlags.Class classFlags
39-
) {
38+
int classFlags
39+
) implements Flags {
4040
private static final VarType DEFAULT_CONSTRUCTOR_MARKER = new VarType("kotlin/jvm/internal/DefaultConstructorMarker", true);
4141

4242
public static Data parse(ClassesProcessor.ClassNode node) {
@@ -47,8 +47,8 @@ public static Data parse(ClassesProcessor.ClassNode node) {
4747
KotlinDecompilationContext.KotlinType type = KotlinDecompilationContext.getCurrentType();
4848
if (type != KotlinDecompilationContext.KotlinType.CLASS) return null;
4949

50-
ProtobufFlags.Class classFlags = new ProtobufFlags.Class(KotlinDecompilationContext.getCurrentClass().getFlags());
51-
if (classFlags.modality == ProtoBuf.Modality.ABSTRACT) return null;
50+
int classFlags = KotlinDecompilationContext.getCurrentClass().getFlags();
51+
if (MODALITY.get(classFlags) == ProtoBuf.Modality.ABSTRACT) return null;
5252

5353
List<ProtoBuf.Constructor> protoConstructors = KotlinDecompilationContext.getCurrentClass().getConstructorList();
5454
if (protoConstructors.isEmpty()) return null;
@@ -61,21 +61,21 @@ public static Data parse(ClassesProcessor.ClassNode node) {
6161
for (int i = 0; i < parameters.length; i++) {
6262
ProtoBuf.ValueParameter protoParameter = constructor.getValueParameter(i);
6363
parameters[i] = new KParameter(
64-
new ProtobufFlags.ValueParameter(protoParameter.getFlags()),
64+
protoParameter.getFlags(),
6565
resolver.resolve(protoParameter.getName()),
6666
KType.from(protoParameter.getType(), resolver),
6767
KType.from(protoParameter.getVarargElementType(), resolver),
6868
protoParameter.getTypeId()
6969
);
7070
}
7171

72-
ProtobufFlags.Constructor flags = new ProtobufFlags.Constructor(constructor.getFlags());
72+
int flags = constructor.getFlags();
7373

7474
JvmProtoBuf.JvmMethodSignature signature = constructor.getExtension(JvmProtoBuf.constructorSignature);
7575
String desc = resolver.resolve(signature.getDesc());
7676
MethodWrapper method = wrapper.getMethodWrapper("<init>", desc);
7777
if (method == null) {
78-
if (classFlags.kind == ProtoBuf.Class.Kind.ANNOTATION_CLASS) {
78+
if (CLASS_KIND.get(classFlags) == ProtoBuf.Class.Kind.ANNOTATION_CLASS) {
7979
// Annotation classes are very odd and don't actually have a constructor under the hood
8080
KConstructor kConstructor = new KConstructor(parameters, flags, null, false, null, node, classFlags);
8181
return new Data(null, kConstructor);
@@ -85,10 +85,10 @@ public static Data parse(ClassesProcessor.ClassNode node) {
8585
continue;
8686
}
8787

88-
boolean isPrimary = !flags.isSecondary;
88+
boolean isPrimary = !IS_SECONDARY.get(flags);
8989

9090
StringBuilder defaultArgsDesc = new StringBuilder("(");
91-
if (classFlags.kind == ProtoBuf.Class.Kind.ENUM_CLASS) {
91+
if (CLASS_KIND.get(classFlags) == ProtoBuf.Class.Kind.ENUM_CLASS) {
9292
// Kotlin drops hidden name/ordinal parameters for enum constructors in its metadata
9393
defaultArgsDesc.append("Ljava/lang/String;").append("I");
9494
}
@@ -124,15 +124,15 @@ public boolean stringify(TextBuffer buffer, int indent) {
124124
String methodKey = InterpreterUtil.makeUniqueKey(method.methodStruct.getName(), method.methodStruct.getDescriptor());
125125

126126
if (!isPrimary) {
127-
if (flags.hasAnnotations) {
127+
if (HAS_ANNOTATIONS.get(flags)) {
128128
KotlinWriter.appendAnnotations(buf, indent, method.methodStruct, TypeAnnotation.METHOD_RETURN_TYPE);
129129
KotlinWriter.appendJvmAnnotations(buf, indent, method.methodStruct, false, method.classStruct.getPool(), TypeAnnotation.METHOD_RETURN_TYPE);
130130
}
131131

132132
buf.appendIndent(indent);
133133

134-
if (flags.visibility != ProtoBuf.Visibility.PUBLIC || DecompilerContext.getOption(KotlinOptions.SHOW_PUBLIC_VISIBILITY)) {
135-
KUtils.appendVisibility(buf, flags.visibility);
134+
if (VISIBILITY.get(flags) != ProtoBuf.Visibility.PUBLIC || DecompilerContext.getOption(KotlinOptions.SHOW_PUBLIC_VISIBILITY)) {
135+
KUtils.appendVisibility(buf, VISIBILITY.get(flags));
136136
}
137137

138138
buf.append("constructor");
@@ -149,7 +149,7 @@ public boolean stringify(TextBuffer buffer, int indent) {
149149

150150
parameter.stringify(indent + 1, buf);
151151

152-
if (parameter.flags().declaresDefault) {
152+
if (DECLARES_DEFAULT_VALUE.get(parameter.flags())) {
153153
buf.append(defaultArgs.toJava(parameter, indent + 1), node.classStruct.qualifiedName, methodKey);
154154
}
155155
}
@@ -213,8 +213,8 @@ public boolean writePrimaryConstructor(TextBuffer buffer, int indent) {
213213

214214
String methodKey = InterpreterUtil.makeUniqueKey(method.methodStruct.getName(), method.methodStruct.getDescriptor());
215215

216-
if (classFlags.kind != ProtoBuf.Class.Kind.OBJECT && classFlags.kind != ProtoBuf.Class.Kind.COMPANION_OBJECT) {
217-
if (flags.hasAnnotations) {
216+
if (CLASS_KIND.get(classFlags) != ProtoBuf.Class.Kind.OBJECT && CLASS_KIND.get(classFlags) != ProtoBuf.Class.Kind.COMPANION_OBJECT) {
217+
if (HAS_ANNOTATIONS.get(flags)) {
218218
buf.append(" ");
219219
// -1 for indent indicates inline
220220
KotlinWriter.appendAnnotations(buf, -1, method.methodStruct, TypeAnnotation.METHOD_RETURN_TYPE);
@@ -223,11 +223,11 @@ public boolean writePrimaryConstructor(TextBuffer buffer, int indent) {
223223
}
224224

225225
// For cleanliness, public primary constructors are not forced public by the config option
226-
if ((flags.visibility != ProtoBuf.Visibility.PUBLIC || (appended && DecompilerContext.getOption(KotlinOptions.SHOW_PUBLIC_VISIBILITY))) &&
227-
classFlags.kind != ProtoBuf.Class.Kind.ENUM_CLASS // Enum constructors are always private implicitly
226+
if ((VISIBILITY.get(flags) != ProtoBuf.Visibility.PUBLIC || (appended && DecompilerContext.getOption(KotlinOptions.SHOW_PUBLIC_VISIBILITY))) &&
227+
CLASS_KIND.get(classFlags) != ProtoBuf.Class.Kind.ENUM_CLASS // Enum constructors are always private implicitly
228228
) {
229229
buf.append(" ");
230-
KUtils.appendVisibility(buf, flags.visibility);
230+
KUtils.appendVisibility(buf, VISIBILITY.get(flags));
231231
appended = true;
232232
}
233233

@@ -248,7 +248,7 @@ public boolean writePrimaryConstructor(TextBuffer buffer, int indent) {
248248

249249
parameter.stringify(indent + 1, buf);
250250

251-
if (parameter.flags().declaresDefault) {
251+
if (DECLARES_DEFAULT_VALUE.get(parameter.flags())) {
252252
buf.append(defaultArgs.toJava(parameter, indent + 1), node.classStruct.qualifiedName, methodKey);
253253
}
254254
}
@@ -271,7 +271,7 @@ public boolean writePrimaryConstructor(TextBuffer buffer, int indent) {
271271
// throw new IllegalStateException("First expression of constructor is not InvocationExprent");
272272
}
273273

274-
if (invocation.getClassname().equals("java/lang/Object") || classFlags.kind == ProtoBuf.Class.Kind.ENUM_CLASS) {
274+
if (invocation.getClassname().equals("java/lang/Object") || CLASS_KIND.get(classFlags) == ProtoBuf.Class.Kind.ENUM_CLASS) {
275275
// No need to declare super constructor call
276276
buffer.append(buf);
277277
return false;

plugins/kotlin/src/main/java/org/vineflower/kotlin/struct/KContract.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
package org.vineflower.kotlin.struct;
22

33
import kotlin.metadata.internal.metadata.ProtoBuf;
4+
import kotlin.metadata.internal.metadata.deserialization.Flags;
45
import org.jetbrains.annotations.NotNull;
56
import org.jetbrains.annotations.Nullable;
67
import org.jetbrains.java.decompiler.main.DecompilerContext;
78
import org.jetbrains.java.decompiler.util.TextBuffer;
89
import org.vineflower.kotlin.KotlinWriter;
910
import org.vineflower.kotlin.metadata.MetadataNameResolver;
10-
import org.vineflower.kotlin.util.ProtobufFlags;
1111

1212
import java.util.List;
1313
import java.util.stream.Collectors;
1414

15-
public class KContract {
15+
public class KContract implements Flags {
1616
private static final String INVOCATION_KIND = "kotlin.contracts.InvocationKind";
1717
@NotNull
1818
public final List<KEffect> effects;
@@ -110,18 +110,18 @@ public void stringify(TextBuffer buf, int indent) {
110110
}
111111

112112
public record KExpression(
113-
@NotNull ProtobufFlags.Expression flags,
113+
int flags,
114114
@Nullable KParameter valueParameterReference,
115115
@Nullable ProtoBuf.Expression.ConstantValue constantValue,
116116
@Nullable KType instanceofType,
117117
@NotNull List<KExpression> andArguments,
118118
@NotNull List<KExpression> orArguments
119119
) {
120120
// Placeholder type for receiver type
121-
private static final KParameter THIS_TYPE = new KParameter(new ProtobufFlags.ValueParameter(0), "this", KType.NOTHING, null, 0);
121+
private static final KParameter THIS_TYPE = new KParameter(0, "this", KType.NOTHING, null, 0);
122122

123123
static KExpression from(ProtoBuf.Expression proto, List<KParameter> params, MetadataNameResolver nameResolver) {
124-
ProtobufFlags.Expression flags = new ProtobufFlags.Expression(proto.getFlags());
124+
int flags = proto.getFlags();
125125
KParameter valueParameterReference = null;
126126
if (proto.hasValueParameterReference()) {
127127
int index = proto.getValueParameterReference();
@@ -158,28 +158,28 @@ public void stringify(TextBuffer buf, int indent, boolean partOfOr) {
158158
if (instanceofType != null) {
159159
buf.append(paramName)
160160
.append(' ')
161-
.append(flags.isNegated ? "!is" : "is")
161+
.append(IS_NEGATED.get(flags) ? "!is" : "is")
162162
.append(' ')
163163
.append(instanceofType.stringify(indent));
164-
} else if (flags.isNullPredicate) {
164+
} else if (IS_NULL_CHECK_PREDICATE.get(flags)) {
165165
buf.append(paramName)
166166
.append(' ')
167-
.append(flags.isNegated ? "!=" : "==")
167+
.append(IS_NEGATED.get(flags) ? "!=" : "==")
168168
.append(' ')
169169
.append("null");
170170
} else if (constantValue != null) {
171171
if (valueParameterReference != null && valueParameterReference.type().isNullable) {
172172
buf.append(paramName)
173173
.append(' ')
174-
.append(flags.isNegated ? "!=" : "==")
174+
.append(IS_NEGATED.get(flags) ? "!=" : "==")
175175
.append(' ')
176176
.append(constantValue.name().toLowerCase());
177177
} else {
178178
String output = valueParameterReference != null && "kotlin/Boolean".equals(valueParameterReference.type().kotlinType)
179179
? paramName
180180
: constantValue.name().toLowerCase();
181181

182-
if (flags.isNegated) {
182+
if (IS_NEGATED.get(flags)) {
183183
buf.append('!');
184184
}
185185

@@ -189,7 +189,7 @@ public void stringify(TextBuffer buf, int indent, boolean partOfOr) {
189189
if (!valueParameterReference.type().kotlinType.equals("kotlin/Boolean")) {
190190
//TODO figure out why this happens
191191
}
192-
if (flags.isNegated) {
192+
if (IS_NEGATED.get(flags)) {
193193
buf.append('!');
194194
}
195195
buf.append(paramName);

0 commit comments

Comments
 (0)