Skip to content

Commit 1c14529

Browse files
committed
Fix all the cases where the tests indicated I messed up
Also upload the intended test result for TestCorruptedSignatures
1 parent 1480c4b commit 1c14529

File tree

6 files changed

+94
-29
lines changed

6 files changed

+94
-29
lines changed

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

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.jetbrains.java.decompiler.struct.gen.generics.GenericClassDescriptor;
3333
import org.jetbrains.java.decompiler.struct.gen.generics.GenericFieldDescriptor;
3434
import org.jetbrains.java.decompiler.struct.gen.generics.GenericMethodDescriptor;
35+
import org.jetbrains.java.decompiler.struct.gen.generics.GenericsChecker;
3536
import org.jetbrains.java.decompiler.util.*;
3637
import org.jetbrains.java.decompiler.util.collections.VBStyleCollection;
3738
import org.vineflower.kotlin.expr.KAnnotationExprent;
@@ -1082,10 +1083,24 @@ public boolean writeMethod(ClassNode node, StructMethod mt, int methodIndex, Tex
10821083
exceptions.add(new VarType(attr.getExcClassname(i, node.classStruct.getPool()), true));
10831084
}
10841085
}
1085-
1086+
10861087
GenericClassDescriptor classSig = (mt.getAccessFlags() & CodeConstants.ACC_STATIC) == 0 ? node.classStruct.getSignature() : null;
1088+
GenericsChecker checker = null;
1089+
if (classSig != null) {
1090+
checker = classSig.getChecker();
1091+
1092+
ClassNode currentParent = node.parent;
1093+
while (currentParent != null) {
1094+
GenericClassDescriptor parentSignature = currentParent.classStruct.getSignature();
1095+
if (parentSignature != null) {
1096+
checker = checker.copy(parentSignature.getChecker());
1097+
}
1098+
1099+
currentParent = currentParent.parent;
1100+
}
1101+
}
10871102

1088-
descriptor.verifyTypes(classSig, params, mt.methodDescriptor().ret, exceptions);
1103+
descriptor.verifyTypes(checker, params, mt.methodDescriptor().ret, exceptions);
10891104
}
10901105

10911106
boolean throwsExceptions = false;

src/org/jetbrains/java/decompiler/main/ClassWriter.java

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.jetbrains.java.decompiler.struct.gen.generics.GenericClassDescriptor;
3838
import org.jetbrains.java.decompiler.struct.gen.generics.GenericFieldDescriptor;
3939
import org.jetbrains.java.decompiler.struct.gen.generics.GenericMethodDescriptor;
40+
import org.jetbrains.java.decompiler.struct.gen.generics.GenericsChecker;
4041
import org.jetbrains.java.decompiler.util.InterpreterUtil;
4142
import org.jetbrains.java.decompiler.util.Key;
4243
import org.jetbrains.java.decompiler.util.TextBuffer;
@@ -1157,12 +1158,23 @@ public boolean writeMethod(ClassNode node, StructMethod mt, int methodIndex, Tex
11571158
GenericMethodDescriptor descriptor = mt.getSignature();
11581159
if (descriptor != null) {
11591160
List<VarType> params = new ArrayList<>(Arrays.asList(mt.methodDescriptor().params));
1160-
if ((node.access & CodeConstants.ACC_ENUM) != 0 && init) {
1161-
// Signatures skip enum parameters, the checker must as well
1161+
1162+
if (init && node.classStruct.hasModifier(CodeConstants.ACC_ENUM)) {
1163+
// Enum name and ordinal parameters need to be explicitly excluded
11621164
params.remove(0);
11631165
params.remove(0);
11641166
}
11651167

1168+
// Exclude any parameters that the signature itself won't contain
1169+
List<VarVersionPair> mask = methodWrapper.synthParameters;
1170+
if (mask != null) {
1171+
for (int i = 0, j = 0; i < mask.size(); i++, j++) {
1172+
if (mask.get(i) != null) {
1173+
params.remove(j--);
1174+
}
1175+
}
1176+
}
1177+
11661178
StructExceptionsAttribute attr = mt.getAttribute(StructGeneralAttribute.ATTRIBUTE_EXCEPTIONS);
11671179
List<VarType> exceptions = new ArrayList<>();
11681180
if (attr != null) {
@@ -1171,9 +1183,19 @@ public boolean writeMethod(ClassNode node, StructMethod mt, int methodIndex, Tex
11711183
}
11721184
}
11731185

1174-
GenericClassDescriptor classSig = (mt.getAccessFlags() & CodeConstants.ACC_STATIC) == 0 ? node.classStruct.getSignature() : null;
1186+
GenericsChecker checker = new GenericsChecker();
1187+
1188+
ClassNode currentNode = node;
1189+
while (currentNode != null) {
1190+
GenericClassDescriptor parentSignature = currentNode.classStruct.getSignature();
1191+
if (parentSignature != null) {
1192+
checker = checker.copy(parentSignature.getChecker());
1193+
}
1194+
1195+
currentNode = currentNode.parent;
1196+
}
11751197

1176-
descriptor.verifyTypes(classSig, params, mt.methodDescriptor().ret, exceptions);
1198+
descriptor.verifyTypes(checker, params, mt.methodDescriptor().ret, exceptions);
11771199
}
11781200

11791201
boolean throwsExceptions = false;

src/org/jetbrains/java/decompiler/struct/gen/generics/GenericFieldDescriptor.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,18 @@ public GenericFieldDescriptor(VarType type) {
1313
this.type = type;
1414
}
1515

16-
public void verifyType(GenericClassDescriptor containingClassGenerics, VarType actualType) {
16+
public void verifyType(GenericClassDescriptor containingClassGenerics, VarType realType) {
1717
if (containingClassGenerics == null) {
1818
DecompilerContext.getLogger().writeMessage("Class generics were not found, verifying type loosely", IFernflowerLogger.Severity.INFO);
19-
verifyLoosely(actualType);
19+
verifyLoosely(realType);
2020
return;
2121
}
2222

2323
GenericsChecker checker = containingClassGenerics.getChecker();
2424

25-
if (!checker.isProperlyBounded(actualType, type)) {
26-
DecompilerContext.getLogger().writeMessage("Mismatched field signature, expected: " + type.value + ", actual: " + actualType.value, IFernflowerLogger.Severity.WARN);
27-
type = actualType;
25+
if (!checker.isProperlyBounded(type, realType)) {
26+
DecompilerContext.getLogger().writeMessage("Mismatched field signature, expected: " + realType.value + ", actual: " + type.value, IFernflowerLogger.Severity.WARN);
27+
type = realType;
2828
}
2929
}
3030

src/org/jetbrains/java/decompiler/struct/gen/generics/GenericMethodDescriptor.java

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,22 +31,30 @@ private static <T> List<T> substitute(List<T> list) {
3131
return list.isEmpty() ? Collections.emptyList() : list;
3232
}
3333

34-
public void verifyTypes(GenericClassDescriptor descriptor, List<VarType> realParamTypes, VarType realReturnType, List<VarType> realExceptionTypes) {
35-
GenericsChecker checker = descriptor == null ? new GenericsChecker(typeParameters, typeParameterBounds) : descriptor.getChecker().copy(typeParameters, typeParameterBounds);
34+
public void verifyTypes(GenericsChecker checker, List<VarType> realParamTypes, VarType realReturnType, List<VarType> realExceptionTypes) {
35+
checker = checker == null ? new GenericsChecker(typeParameters, typeParameterBounds) : checker.copy(typeParameters, typeParameterBounds);
3636

3737
for (int i = 0; i < parameterTypes.size(); i++) {
3838
VarType parameterType = parameterTypes.get(i);
39-
VarType actualType = realParamTypes.get(i);
39+
VarType realType = realParamTypes.get(i);
4040

41-
if (!checker.isProperlyBounded(parameterType, actualType)) {
42-
DecompilerContext.getLogger().writeMessage("Mismatched method parameter signature, expected: " + actualType.value + ", actual: " + parameterType.value, IFernflowerLogger.Severity.WARN);
43-
parameterTypes.set(i, actualType);
41+
if (!checker.isProperlyBounded(parameterType, realType)) {
42+
DecompilerContext.getLogger().writeMessage("Mismatched method parameter signature, expected: " + realType.value + ", actual: " + parameterType.value, IFernflowerLogger.Severity.WARN);
43+
parameterTypes.set(i, realType);
4444
}
4545
}
4646

4747
if (!checker.isProperlyBounded(returnType, realReturnType)) {
48-
DecompilerContext.getLogger().writeMessage("Mismatched method parameter signature, expected: " + realReturnType.value + ", actual: " + returnType.value, IFernflowerLogger.Severity.WARN);
48+
DecompilerContext.getLogger().writeMessage("Mismatched method return signature, expected: " + realReturnType.value + ", actual: " + returnType.value, IFernflowerLogger.Severity.WARN);
4949
returnType = realReturnType;
5050
}
51+
52+
for (int i = 0; i < exceptionTypes.size(); i++) {
53+
VarType exceptionType = exceptionTypes.get(i);
54+
VarType realType = realExceptionTypes.get(i);
55+
if (!checker.isProperlyBounded(exceptionType, realType)) {
56+
DecompilerContext.getLogger().writeMessage("Mismatched method exception signature, expected: " + realType.value + ", actual: " + exceptionType.value, IFernflowerLogger.Severity.WARN);
57+
}
58+
}
5159
}
5260
}

src/org/jetbrains/java/decompiler/struct/gen/generics/GenericsChecker.java

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,57 @@
33
import org.jetbrains.java.decompiler.struct.gen.CodeType;
44
import org.jetbrains.java.decompiler.struct.gen.VarType;
55

6+
import java.util.ArrayList;
67
import java.util.HashMap;
78
import java.util.List;
89
import java.util.Map;
910

1011
public class GenericsChecker {
1112
private final Map<String, List<VarType>> boundsMap;
1213

14+
public GenericsChecker() {
15+
boundsMap = Map.of();
16+
}
17+
1318
public GenericsChecker(List<String> typeVariables, List<List<VarType>> bounds) {
1419
boundsMap = new HashMap<>(typeVariables.size(), 1);
1520
for (int i = 0; i < typeVariables.size(); i++) {
1621
boundsMap.put(typeVariables.get(i), bounds.get(i));
1722
}
1823
}
1924

20-
private GenericsChecker(Map<String, List<VarType>> existingBounds, List<String> typeVariables, List<List<VarType>> bounds) {
21-
boundsMap = new HashMap<>(existingBounds);
25+
private GenericsChecker(Map<String, List<VarType>> boundsMap) {
26+
this.boundsMap = boundsMap;
27+
}
28+
29+
public GenericsChecker copy(List<String> typeVariables, List<List<VarType>> bounds) {
30+
HashMap<String, List<VarType>> newBounds = new HashMap<>(boundsMap);
2231
for (int i = 0; i < typeVariables.size(); i++) {
23-
boundsMap.put(typeVariables.get(i), bounds.get(i));
32+
newBounds.put(typeVariables.get(i), bounds.get(i));
2433
}
34+
35+
return new GenericsChecker(newBounds);
2536
}
2637

27-
public GenericsChecker copy(List<String> typeVariables, List<List<VarType>> bounds) {
28-
return new GenericsChecker(boundsMap, typeVariables, bounds);
38+
public GenericsChecker copy(GenericsChecker parent) {
39+
HashMap<String, List<VarType>> newBoundsMap = new HashMap<>(this.boundsMap);
40+
for (Map.Entry<String, List<VarType>> entry : parent.boundsMap.entrySet()) {
41+
if (!newBoundsMap.containsKey(entry.getKey())) {
42+
newBoundsMap.put(entry.getKey(), new ArrayList<>(entry.getValue()));
43+
}
44+
}
45+
46+
return new GenericsChecker(newBoundsMap);
2947
}
3048

3149
public boolean isProperlyBounded(VarType type, VarType bound) {
3250
if (type.isSuperset(bound)) {
3351
return true;
3452
}
3553

54+
// Get base type if array
55+
bound = bound.resizeArrayDim(0);
56+
3657
if (type.type == CodeType.GENVAR && type instanceof GenericType genericType) {
3758
List<VarType> typeBounds = boundsMap.get(genericType.value);
3859
if (typeBounds != null) {
Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
import java.util.ArrayList;
22
import java.util.List;
3-
import java.util.Map;
43

5-
abstract class Signatures implements Map<String, String> {
6-
Map<String, String> field = new ArrayList();
4+
abstract class Signatures implements List {
5+
List field = new ArrayList();
76

8-
void method(Map<String, String> o) {
7+
void method(List o) {
98
}// 9
109
}
1110

1211
class 'Signatures' {
1312
method 'method (Ljava/util/List;)V' {
14-
0 8
13+
0 7
1514
}
1615
}
1716

1817
Lines mapping:
19-
9 <-> 9
18+
9 <-> 8

0 commit comments

Comments
 (0)