[java-decompiler] IDEA-346312 adapt patches

- show constructors and getters for IDEA
- cast with null
- more tests

GitOrigin-RevId: 4a9aef46e4cac7fd15a27b1c75d88dedd8825659
This commit is contained in:
Mikhail Pyltsin
2024-09-11 15:06:41 +02:00
committed by intellij-monorepo-bot
parent 26b21b852e
commit e7546bddfd
25 changed files with 815 additions and 76 deletions

View File

@@ -2,6 +2,7 @@
package org.jetbrains.java.decompiler.main;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
@@ -29,6 +30,7 @@ import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.struct.gen.generics.GenericClassDescriptor;
import org.jetbrains.java.decompiler.struct.gen.generics.GenericFieldDescriptor;
import org.jetbrains.java.decompiler.struct.gen.generics.GenericMethodDescriptor;
import org.jetbrains.java.decompiler.struct.gen.generics.GenericType;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
import org.jetbrains.java.decompiler.util.TextBuffer;
@@ -354,12 +356,18 @@ public class ClassWriter {
}
}
boolean hideConstructorAndGetters = DecompilerContext.getOption(IFernflowerPreferences.HIDE_RECORD_CONSTRUCTOR_AND_GETTERS);
if (!hideConstructorAndGetters) return false;
// Default getters
for (StructRecordComponent rec : cl.getRecordComponents()) {
if (name.equals(rec.getName()) && descriptor.equals("()" + rec.getDescriptor())) {
if (code.countLines() == 1) {
String str = code.toString().trim();
Set<AnnotationExprent> methodAnnotations = collectAllAnnotations(mt);
Set<AnnotationExprent> fieldAnnotations = collectAllAnnotations(rec);
if (fieldAnnotations.containsAll(methodAnnotations)) {
return str.equals("return this." + mt.getName() + ';');
}
} else {
return false;
}
@@ -369,6 +377,27 @@ public class ClassWriter {
return false;
}
@NotNull
private static Set<AnnotationExprent> collectAllAnnotations(@Nullable StructMember mt) {
Set<AnnotationExprent> result = new HashSet<>();
if (mt == null) {
return result;
}
for (StructGeneralAttribute.Key<?> key : StructGeneralAttribute.ANNOTATION_ATTRIBUTES) {
StructAnnotationAttribute attribute = (StructAnnotationAttribute)mt.getAttribute(key);
if (attribute != null) {
for (AnnotationExprent annotation : attribute.getAnnotations()) {
if (mt.memberAnnCollidesWithTypeAnnotation(annotation)) continue;
result.add(annotation);
}
}
}
for (TypeAnnotation annotation : TypeAnnotation.listFrom(mt)) {
result.add(annotation.getAnnotationExpr());
}
return result;
}
private void writeClassDefinition(ClassNode node, TextBuffer buffer, int indent) {
if (node.type == ClassNode.CLASS_ANONYMOUS) {
buffer.append(" {").appendLineSeparator();
@@ -755,7 +784,8 @@ public class ClassWriter {
String desc = buf.append(")V").toString();
if (desc.equals(mt.getDescriptor())) {
boolean[] found = new boolean[1];
compact = methodWrapper.getOrBuildGraph().iterateExprents((exprent) -> {
boolean hideConstructorAndGetters = DecompilerContext.getOption(IFernflowerPreferences.HIDE_RECORD_CONSTRUCTOR_AND_GETTERS);
compact = hideConstructorAndGetters && methodWrapper.getOrBuildGraph().iterateExprents((exprent) -> {
if (exprent.type == Exprent.EXPRENT_ASSIGNMENT) {
AssignmentExprent assignment = (AssignmentExprent)exprent;
if (assignment.getLeft() != null && assignment.getRight() != null &&
@@ -777,6 +807,10 @@ public class ClassWriter {
if (entry.myName == null || !entry.myName.equals(((VarExprent)assignment.getRight()).getName())) {
return 1;
}
Set<AnnotationExprent> recordComponentAnnotations = collectAllAnnotations(cl.getRecordComponents().get(index));
VarType parameterType = descriptor != null ? descriptor.parameterTypes.get(index) : md.params[index];
List<AnnotationExprent> paramAnnotations = collectParameterAnnotations(mt, parameterType, index);
if (!recordComponentAnnotations.containsAll(paramAnnotations)) return 1;
found[0] = true;
return 0;
@@ -880,6 +914,11 @@ public class ClassWriter {
DecompilerContext.getOption(IFernflowerPreferences.UNDEFINED_PARAM_TYPE_OBJECT)) {
typeName = ExprProcessor.getCastTypeName(VarType.VARTYPE_OBJECT, TypeAnnotationWriteHelper.create(typeParamAnnotations));
}
//workaround to send to usages
VarType type = methodWrapper.varproc.getVarType(pair);
if (parameterType instanceof GenericType && (type == null || type.equals(VarType.VARTYPE_OBJECT))) {
methodWrapper.varproc.setVarType(pair, parameterType);
}
buffer.append(typeName);
if (isVarArg) {
buffer.append("...");
@@ -992,6 +1031,25 @@ public class ClassWriter {
return !hideMethod;
}
@NotNull
private static List<AnnotationExprent> collectParameterAnnotations(StructMethod mt, Type type, int param) {
List<AnnotationExprent> result = new ArrayList<>();
if (mt == null || type == null) return result;
for (StructGeneralAttribute.Key<?> key : StructGeneralAttribute.PARAMETER_ANNOTATION_ATTRIBUTES) {
StructAnnotationParameterAttribute attribute = (StructAnnotationParameterAttribute)mt.getAttribute(key);
if (attribute != null) {
List<List<AnnotationExprent>> annotations = attribute.getParamAnnotations();
if (param < annotations.size()) {
for (AnnotationExprent annotation : annotations.get(param)) {
if (mt.paramAnnCollidesWithTypeAnnotation(annotation, type, param)) continue;
result.add(annotation);
}
}
}
}
return result;
}
private static boolean isVarArgRecord(StructClass cl) {
String canonicalConstructorDescriptor =
cl.getRecordComponents().stream().map(StructField::getDescriptor).collect(Collectors.joining("", "(", ")V"));
@@ -1280,20 +1338,12 @@ public class ClassWriter {
}
private static void appendParameterAnnotations(TextBuffer buffer, StructMethod mt, @NotNull Type type, int param) {
for (StructGeneralAttribute.Key<?> key : StructGeneralAttribute.PARAMETER_ANNOTATION_ATTRIBUTES) {
StructAnnotationParameterAttribute attribute = (StructAnnotationParameterAttribute)mt.getAttribute(key);
if (attribute != null) {
List<List<AnnotationExprent>> annotations = attribute.getParamAnnotations();
if (param < annotations.size()) {
for (AnnotationExprent annotation : annotations.get(param)) {
if (mt.paramAnnCollidesWithTypeAnnotation(annotation, type, param)) continue;
List<AnnotationExprent> exprents = collectParameterAnnotations(mt, type, param);
for (AnnotationExprent annotation : exprents) {
String text = annotation.toJava(-1, BytecodeMappingTracer.DUMMY).toString();
buffer.append(text).append(' ');
}
}
}
}
}
private static final Map<Integer, String> MODIFIERS;
static {

View File

@@ -40,6 +40,7 @@ public interface IFernflowerPreferences {
String STANDARDIZE_FLOATING_POINT_NUMBERS = "sfn";
String INCLUDE_ENTIRE_CLASSPATH = "iec";
String INLINE_SIMPLE_LAMBDAS = "isl";
String HIDE_RECORD_CONSTRUCTOR_AND_GETTERS = "ucrc";
String LOG_LEVEL = "log";
String MAX_PROCESSING_METHOD = "mpm";
@@ -98,8 +99,9 @@ public interface IFernflowerPreferences {
defaults.put(STANDARDIZE_FLOATING_POINT_NUMBERS, "0");
defaults.put(INCLUDE_ENTIRE_CLASSPATH, "0");
defaults.put(CHECK_CLOSABLE_INTERFACE, "0"); //less accurate, but it will work for not full environment
defaults.put(CHECK_CLOSABLE_INTERFACE, "1");
defaults.put(INLINE_SIMPLE_LAMBDAS, "1");
defaults.put(HIDE_RECORD_CONSTRUCTOR_AND_GETTERS, "1");
defaults.put(LOG_LEVEL, IFernflowerLogger.Severity.INFO.name());
defaults.put(MAX_PROCESSING_METHOD, "0");

View File

@@ -1052,10 +1052,12 @@ public class ExprProcessor {
VarType rightType = exprent.getInferredExprType(leftType);
boolean isCastNull =
rightType.getType() == CodeConstants.TYPE_NULL && !UNDEFINED_TYPE_STRING.equals(getTypeName(leftType, Collections.emptyList()));
boolean cast =
castAlways ||
(!leftType.isSuperset(rightType) && (rightType.equals(VarType.VARTYPE_OBJECT) || leftType.getType() != CodeConstants.TYPE_OBJECT)) ||
(castNull && rightType.getType() == CodeConstants.TYPE_NULL && !UNDEFINED_TYPE_STRING.equals(getTypeName(leftType, Collections.emptyList()))) ||
(!leftType.isSuperset(rightType) && (rightType.equals(VarType.VARTYPE_OBJECT) || leftType.getType() != CodeConstants.TYPE_OBJECT && !isCastNull)) ||
(castNull && isCastNull) ||
(castNarrowing && isIntConstant(exprent) && isNarrowedIntType(leftType));
boolean castLambda = !cast && exprent.type == Exprent.EXPRENT_NEW && !leftType.equals(rightType) &&

View File

@@ -26,7 +26,9 @@ public class SingleClassesTest extends SingleClassesTestBase {
IFernflowerPreferences.VERIFY_ANONYMOUS_CLASSES, "1",
IFernflowerPreferences.CONVERT_PATTERN_SWITCH, "1",
IFernflowerPreferences.CONVERT_RECORD_PATTERN, "1",
IFernflowerPreferences.INLINE_SIMPLE_LAMBDAS, "1"
IFernflowerPreferences.INLINE_SIMPLE_LAMBDAS, "1",
IFernflowerPreferences.CHECK_CLOSABLE_INTERFACE, "0",
IFernflowerPreferences.HIDE_RECORD_CONSTRUCTOR_AND_GETTERS, "0"
//IFernflowerPreferences.INCLUDE_ENTIRE_CLASSPATH, "1"
);
}
@@ -251,5 +253,6 @@ public class SingleClassesTest extends SingleClassesTestBase {
@Test public void testFinally() { doTest("pkg/TestFinally"); }
@Test public void testEnumInit() { doTest("pkg/TestEnumInit"); }
@Test public void testGenericInit() { doTest("pkg/TestInitGeneric"); }
@Test public void testNotNullRecord() { doTest("pkg/TestNotNullRecord"); }
}

View File

@@ -42,7 +42,7 @@ public class b<K, V> {
}
public void a(V var1) {
this.e = (V)var1;
this.e = var1;
}
public b(K var1, V var2, long var3, long var5) {
@@ -51,12 +51,12 @@ public class b<K, V> {
this.a = new ah();
this.b = 0L;
this.c = 0L;
this.d = (K)var1;
this.d = var1;
this.f = var3;
this.g = var5;
this.c = System.currentTimeMillis();
this.b = this.c;
this.e = (V)var2;
this.e = var2;
if (ap.c != 0) {
boolean var10000;
label18: {

View File

@@ -15,12 +15,12 @@ public class n<F, S> {
}
public n(F var1) {
this.a = (F)var1;
this.a = var1;
}
public n(F var1, S var2) {
this.a = (F)var1;
this.b = (S)var2;
this.a = var1;
this.b = var2;
}
public F a() {
@@ -28,7 +28,7 @@ public class n<F, S> {
}
public void a(F var1) {
this.a = (F)var1;
this.a = var1;
}
public S b() {
@@ -36,7 +36,7 @@ public class n<F, S> {
}
public void b(S var1) {
this.b = (S)var1;
this.b = var1;
}
public boolean equals(Object param1) {

View File

@@ -199,7 +199,7 @@ public class o {
public <E extends Enum<E>> E a(Class<E> var1) {
try {
if (this.a == null) {
return (E)null;
return null;
}
} catch (Exception var4) {
throw var4;
@@ -216,7 +216,7 @@ public class o {
try {
return (E)Enum.valueOf(var1, String.valueOf(this.a));
} catch (Exception var3) {
return (E)null;
return null;
}
}

View File

@@ -5,6 +5,14 @@ public record PreserveAssignmentToRecord(int x, int y) {
this.x = 52122221;// 5
this.y = 52122223;// 6
}// 7
public int x() {
return this.x;
}
public int y() {
return this.y;// 3
}
}
class 'org/example/PreserveAssignmentToRecord' {
@@ -23,9 +31,26 @@ class 'org/example/PreserveAssignmentToRecord' {
f 5
10 6
}
method 'x ()I' {
0 9
1 9
2 9
3 9
4 9
}
method 'y ()I' {
0 13
1 13
2 13
3 13
4 13
}
}
Lines mapping:
3 <-> 14
5 <-> 5
6 <-> 6
7 <-> 7

View File

@@ -7,6 +7,10 @@ public record PreserveAssignmentToRecord2(int x) {
this.x = 1;// 7
System.out.println("1");// 8
}// 9
public int x() {
return this.x;// 3
}
}
class 'org/example/PreserveAssignmentToRecord2' {
@@ -26,9 +30,18 @@ class 'org/example/PreserveAssignmentToRecord2' {
10 7
11 8
}
method 'x ()I' {
0 11
1 11
2 11
3 11
4 11
}
}
Lines mapping:
3 <-> 12
7 <-> 7
8 <-> 8
9 <-> 9

View File

@@ -54,9 +54,28 @@ public class TestComplexInstanceOfRecordPatternJavac {
}// 41
static record R(Object o) {
R(Object o) {
this.o = o;
}
public Object o() {
return this.o;// 53
}
}
static record R2(Object o1, Object o2) {
R2(Object o1, Object o2) {
this.o1 = o1;
this.o2 = o2;
}
public Object o1() {
return this.o1;
}
public Object o2() {
return this.o2;// 56
}
}
}
@@ -313,6 +332,57 @@ class 'pkg/TestComplexInstanceOfRecordPatternJavac' {
}
}
class 'pkg/TestComplexInstanceOfRecordPatternJavac$R' {
method '<init> (Ljava/lang/Object;)V' {
4 57
5 57
6 57
7 57
8 57
9 58
}
method 'o ()Ljava/lang/Object;' {
0 61
1 61
2 61
3 61
4 61
}
}
class 'pkg/TestComplexInstanceOfRecordPatternJavac$R2' {
method '<init> (Ljava/lang/Object;Ljava/lang/Object;)V' {
4 67
5 67
6 67
7 67
8 67
9 68
a 68
b 68
c 68
d 68
e 69
}
method 'o1 ()Ljava/lang/Object;' {
0 72
1 72
2 72
3 72
4 72
}
method 'o2 ()Ljava/lang/Object;' {
0 76
1 76
2 76
3 76
4 76
}
}
Lines mapping:
6 <-> 5
9 <-> 14
@@ -338,6 +408,8 @@ Lines mapping:
46 <-> 48
47 <-> 49
50 <-> 53
53 <-> 62
56 <-> 77
Not mapped:
14
22

View File

@@ -2,17 +2,37 @@ package pkg;
public class TestCustomSyntheticRecords {
public static record CustomGetter(String a, String a22) {
public CustomGetter(String a, String a22) {
this.a = a;
this.a22 = a22;
}
public String a() {
return this.a + "1";// 9
}
public String a22() {
return this.a22;// 6
}
}
public static record CustomCompactConstructor(String a, String a22) {
public CustomCompactConstructor {
public CustomCompactConstructor(String a, String a22) {
if (a.equals("a")) {// 15
throw new AssertionError();// 16
} else {
this.a = a;// 14
this.a22 = a22;
}
}// 18
public String a() {
return this.a;
}
public String a22() {
return this.a22;// 13
}
}
public static record CustomFullConstructor(String a, String a22) {
@@ -20,62 +40,137 @@ public class TestCustomSyntheticRecords {
this.a = a;// 22
this.a22 = a;// 23
}// 24
public String a() {
return this.a;
}
public String a22() {
return this.a22;// 20
}
}
}
class 'pkg/TestCustomSyntheticRecords$CustomGetter' {
method 'a ()Ljava/lang/String;' {
0 5
1 5
2 5
3 5
method '<init> (Ljava/lang/String;Ljava/lang/String;)V' {
4 5
5 5
6 5
7 5
8 5
9 5
9 6
a 6
b 6
c 6
d 6
e 7
}
method 'a ()Ljava/lang/String;' {
0 10
1 10
2 10
3 10
4 10
5 10
6 10
7 10
8 10
9 10
}
method 'a22 ()Ljava/lang/String;' {
0 14
1 14
2 14
3 14
4 14
}
}
class 'pkg/TestCustomSyntheticRecords$CustomCompactConstructor' {
method '<init> (Ljava/lang/String;Ljava/lang/String;)V' {
4 11
5 11
6 11
7 11
8 11
9 11
a 11
14 12
1f 14
4 20
5 20
6 20
7 20
8 20
9 20
a 20
14 21
15 23
16 23
17 23
18 23
19 23
1a 24
1b 24
1c 24
1d 24
1e 24
1f 26
}
method 'a ()Ljava/lang/String;' {
0 29
1 29
2 29
3 29
4 29
}
method 'a22 ()Ljava/lang/String;' {
0 33
1 33
2 33
3 33
4 33
}
}
class 'pkg/TestCustomSyntheticRecords$CustomFullConstructor' {
method '<init> (Ljava/lang/String;Ljava/lang/String;)V' {
4 19
5 19
6 19
7 19
8 19
9 20
a 20
b 20
c 20
d 20
e 21
4 39
5 39
6 39
7 39
8 39
9 40
a 40
b 40
c 40
d 40
e 41
}
method 'a ()Ljava/lang/String;' {
0 44
1 44
2 44
3 44
4 44
}
method 'a22 ()Ljava/lang/String;' {
0 48
1 48
2 48
3 48
4 48
}
}
Lines mapping:
9 <-> 6
15 <-> 12
16 <-> 13
18 <-> 15
22 <-> 20
23 <-> 21
24 <-> 22
6 <-> 15
9 <-> 11
13 <-> 34
14 <-> 24
15 <-> 21
16 <-> 22
18 <-> 27
20 <-> 49
22 <-> 40
23 <-> 41
24 <-> 42
Not mapped:
14
21

View File

@@ -2,11 +2,11 @@ package pkg;
public class TestExtendsList {
static <T extends Comparable<? super T>> T m1(T var0) {
return (T)null;// 20
return null;// 20
}
static <T extends Object & Comparable<? super T>> T m2(T var0) {
return (T)null;// 24
return null;// 24
}
}

View File

@@ -7,28 +7,28 @@ public class TestInitGeneric<T> {
}// 10
public T test() {
return (T)null;// 13
return null;// 13
}
class A<T> {
public T test() {
return (T)null;// 18
return null;// 18
}
}
class B<L extends T> {
public L test() {
return (L)null;// 24
return null;// 24
}
public <AA extends CharSequence> AA test2() {
return (AA)null;// 28
return null;// 28
}
}
static class C<L extends CharSequence, K> {
public K test(List<? super L> list) {
return (K)null;// 34
return null;// 34
}
public L test2(List<? extends L> list) {

View File

@@ -0,0 +1,56 @@
package records;
import org.jetbrains.annotations.NotNull;
public record TestNotNullRecord(Integer integer) {
public TestNotNullRecord(@NotNull Integer integer) {
if (integer == null) {
$$$reportNull$$$0(0);
}
super();
this.integer = integer;
}
@NotNull
public Integer integer() {
Integer var10000 = this.integer;// 5
if (var10000 == null) {
$$$reportNull$$$0(1);
}
return var10000;
}
}
class 'records/TestNotNullRecord' {
method '<init> (Ljava/lang/Integer;)V' {
0 6
1 6
4 7
5 7
9 10
a 10
b 10
c 11
d 11
e 11
f 11
10 11
11 12
}
method 'integer ()Ljava/lang/Integer;' {
0 16
1 16
2 16
3 16
5 17
8 18
9 18
c 21
}
}
Lines mapping:
5 <-> 17

View File

@@ -1,5 +1,52 @@
package records;
public record TestRecordAnno(@RC @TA int x, int y) {
public TestRecordAnno(@TA int x, @P int y) {
this.x = x;
this.y = y;
}
public @TA int x() {
return this.x;
}
@M
public int y() {
return this.y;// 5
}
}
class 'records/TestRecordAnno' {
method '<init> (II)V' {
4 4
5 4
6 4
7 4
8 4
9 5
a 5
b 5
c 5
d 5
e 6
}
method 'x ()I' {
0 9
1 9
2 9
3 9
4 9
}
method 'y ()I' {
0 14
1 14
2 14
3 14
4 14
}
}
Lines mapping:
5 <-> 15

View File

@@ -1,5 +1,53 @@
package records;
public record TestRecordGenericVararg<T>(T first, T... other) {
@SafeVarargs
public TestRecordGenericVararg(T first, T... other) {
this.first = first;// 5
this.other = other;
}
public T first() {
return this.first;
}
public T[] other() {
return this.other;// 3
}
}
class 'records/TestRecordGenericVararg' {
method '<init> (Ljava/lang/Object;[Ljava/lang/Object;)V' {
4 5
5 5
6 5
7 5
8 5
9 6
a 6
b 6
c 6
d 6
e 7
}
method 'first ()Ljava/lang/Object;' {
0 10
1 10
2 10
3 10
4 10
}
method 'other ()[Ljava/lang/Object;' {
0 14
1 14
2 14
3 14
4 14
}
}
Lines mapping:
3 <-> 15
5 <-> 6

View File

@@ -1,5 +1,51 @@
package records;
public record TestRecordSimple(int x, int y) {
public TestRecordSimple(int x, int y) {
this.x = x;
this.y = y;
}
public int x() {
return this.x;
}
public int y() {
return this.y;// 3
}
}
class 'records/TestRecordSimple' {
method '<init> (II)V' {
4 4
5 4
6 4
7 4
8 4
9 5
a 5
b 5
c 5
d 5
e 6
}
method 'x ()I' {
0 9
1 9
2 9
3 9
4 9
}
method 'y ()I' {
0 13
1 13
2 13
3 13
4 13
}
}
Lines mapping:
3 <-> 14

View File

@@ -1,5 +1,51 @@
package records;
public record TestRecordVararg(int x, int[]... y) {
public TestRecordVararg(int x, int[]... y) {
this.x = x;
this.y = y;
}
public int x() {
return this.x;
}
public int[][] y() {
return this.y;// 3
}
}
class 'records/TestRecordVararg' {
method '<init> (I[[I)V' {
4 4
5 4
6 4
7 4
8 4
9 5
a 5
b 5
c 5
d 5
e 6
}
method 'x ()I' {
0 9
1 9
2 9
3 9
4 9
}
method 'y ()[[I' {
0 13
1 13
2 13
3 13
4 13
}
}
Lines mapping:
3 <-> 14

View File

@@ -115,6 +115,13 @@ public class TestSimpleInstanceOfRecordPatternJavac {
}
static record R(Object o) {
R(Object o) {
this.o = o;
}
public Object o() {
return this.o;// 113
}
}
}
@@ -564,6 +571,25 @@ class 'pkg/TestSimpleInstanceOfRecordPatternJavac' {
}
}
class 'pkg/TestSimpleInstanceOfRecordPatternJavac$R' {
method '<init> (Ljava/lang/Object;)V' {
4 118
5 118
6 118
7 118
8 118
9 119
}
method 'o ()Ljava/lang/Object;' {
0 122
1 122
2 122
3 122
4 122
}
}
Lines mapping:
6 <-> 5
9 <-> 13
@@ -622,6 +648,7 @@ Lines mapping:
106 <-> 109
108 <-> 109
110 <-> 110
113 <-> 123
Not mapped:
13
25

View File

@@ -268,9 +268,28 @@ public class TestSwitchNestedDeconstructionsJavac {
}
static record R1(Object o) {
R1(Object o) {
this.o = o;
}
public Object o() {
return this.o;// 8
}
}
static record R2(Object o, Object o2) {
R2(Object o, Object o2) {
this.o = o;
this.o2 = o2;
}
public Object o() {
return this.o;
}
public Object o2() {
return this.o2;// 183
}
}
}
@@ -1006,8 +1025,60 @@ class 'pkg/TestSwitchNestedDeconstructionsJavac' {
}
}
class 'pkg/TestSwitchNestedDeconstructionsJavac$R1' {
method '<init> (Ljava/lang/Object;)V' {
4 271
5 271
6 271
7 271
8 271
9 272
}
method 'o ()Ljava/lang/Object;' {
0 275
1 275
2 275
3 275
4 275
}
}
class 'pkg/TestSwitchNestedDeconstructionsJavac$R2' {
method '<init> (Ljava/lang/Object;Ljava/lang/Object;)V' {
4 281
5 281
6 281
7 281
8 281
9 282
a 282
b 282
c 282
d 282
e 283
}
method 'o ()Ljava/lang/Object;' {
0 286
1 286
2 286
3 286
4 286
}
method 'o2 ()Ljava/lang/Object;' {
0 290
1 290
2 290
3 290
4 290
}
}
Lines mapping:
6 <-> 7
8 <-> 276
14 <-> 10
15 <-> 11
16 <-> 12
@@ -1104,6 +1175,7 @@ Lines mapping:
175 <-> 255
177 <-> 207
180 <-> 236
183 <-> 291
Not mapped:
54
97

View File

@@ -176,12 +176,33 @@ public class TestSwitchPatternWithExpression {
}
static record A(String a) implements I {
A(String a) {
this.a = a;
}
public String a() {
return this.a;// 5
}
}
static record B(String a) implements I {
B(String a) {
this.a = a;
}
public String a() {
return this.a;// 8
}
}
static record AA(I i) {
AA(I i) {
this.i = i;
}
public I i() {
return this.i;// 11
}
}
sealed interface I permits TestSwitchPatternWithExpression.A, TestSwitchPatternWithExpression.B {
@@ -485,7 +506,67 @@ class 'TestSwitchPatternWithExpression' {
}
}
class 'TestSwitchPatternWithExpression$A' {
method '<init> (Ljava/lang/String;)V' {
4 179
5 179
6 179
7 179
8 179
9 180
}
method 'a ()Ljava/lang/String;' {
0 183
1 183
2 183
3 183
4 183
}
}
class 'TestSwitchPatternWithExpression$B' {
method '<init> (Ljava/lang/String;)V' {
4 189
5 189
6 189
7 189
8 189
9 190
}
method 'a ()Ljava/lang/String;' {
0 193
1 193
2 193
3 193
4 193
}
}
class 'TestSwitchPatternWithExpression$AA' {
method '<init> (LTestSwitchPatternWithExpression$I;)V' {
4 199
5 199
6 199
7 199
8 199
9 200
}
method 'i ()LTestSwitchPatternWithExpression$I;' {
0 203
1 203
2 203
3 203
4 203
}
}
Lines mapping:
5 <-> 184
8 <-> 194
11 <-> 204
15 <-> 3
16 <-> 4
19 <-> 17

View File

@@ -79,6 +79,18 @@ public class TestSwitchWithDeconstructionsWithoutNestedJavac {
}// 64
static record R1(Object o, Object o2) {
R1(Object o, Object o2) {
this.o = o;
this.o2 = o2;
}
public Object o() {
return this.o;
}
public Object o2() {
return this.o2;// 8
}
}
}
@@ -394,8 +406,41 @@ class 'pkg/TestSwitchWithDeconstructionsWithoutNestedJavac' {
}
}
class 'pkg/TestSwitchWithDeconstructionsWithoutNestedJavac$R1' {
method '<init> (Ljava/lang/Object;Ljava/lang/Object;)V' {
4 82
5 82
6 82
7 82
8 82
9 83
a 83
b 83
c 83
d 83
e 84
}
method 'o ()Ljava/lang/Object;' {
0 87
1 87
2 87
3 87
4 87
}
method 'o2 ()Ljava/lang/Object;' {
0 91
1 91
2 91
3 91
4 91
}
}
Lines mapping:
6 <-> 5
8 <-> 92
13 <-> 8
14 <-> 20
15 <-> 10

View File

@@ -0,0 +1,7 @@
package records;
import org.jetbrains.annotations.NotNull;
public record TestNotNullRecord(@NotNull Integer integer) {
}

View File

@@ -245,6 +245,8 @@ private fun getOptions(): Map<String, Any> {
IFernflowerPreferences.VERIFY_ANONYMOUS_CLASSES to "1",
IFernflowerPreferences.CONVERT_PATTERN_SWITCH to "1",
IFernflowerPreferences.CONVERT_RECORD_PATTERN to "1",
IFernflowerPreferences.HIDE_RECORD_CONSTRUCTOR_AND_GETTERS to "0", //must be 0. Otherwise there are problems with mirroring
IFernflowerPreferences.CHECK_CLOSABLE_INTERFACE to "0", //must be 0. Otherwise it doesn't work in idea
//IFernflowerPreferences.UNIT_TEST_MODE to if (ApplicationManager.getApplication().isUnitTestMode) "1" else "0"
)
}