mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-08 15:09:39 +07:00
[java-decompiler] IDEA-291240 Fix switch over enum for Eclipse compiled bytecode
GitOrigin-RevId: fcbbc78a08fa3c0afe7bdad129c0427007f0c3d5
This commit is contained in:
committed by
intellij-monorepo-bot
parent
e51e3ad1ef
commit
4c219967ed
@@ -86,21 +86,44 @@ public final class SwitchHelper {
|
||||
private static Map<Exprent, Exprent> evaluateCaseLabelsToFieldsMapping(@NotNull List<List<Exprent>> caseValues,
|
||||
@NotNull ArrayExprent array) {
|
||||
Map<Exprent, Exprent> mapping = new HashMap<>(caseValues.size());
|
||||
FieldExprent arrayField = (FieldExprent)array.getArray();
|
||||
ClassesProcessor.ClassNode classNode = DecompilerContext.getClassProcessor().getMapRootClasses().get(arrayField.getClassname());
|
||||
if (classNode == null) return mapping;
|
||||
MethodWrapper wrapper = classNode.getWrapper().getMethodWrapper(CodeConstants.CLINIT_NAME, "()V");
|
||||
if (wrapper != null && wrapper.root != null) {
|
||||
wrapper.getOrBuildGraph().iterateExprents(exprent -> {
|
||||
if (exprent instanceof AssignmentExprent) {
|
||||
AssignmentExprent assignment = (AssignmentExprent)exprent;
|
||||
Exprent left = assignment.getLeft();
|
||||
if (left.type == Exprent.EXPRENT_ARRAY && ((ArrayExprent)left).getArray().equals(arrayField)) {
|
||||
mapping.put(assignment.getRight(), ((InvocationExprent)((ArrayExprent)left).getIndex()).getInstance());
|
||||
if (array.getArray().type == Exprent.EXPRENT_FIELD) { // Javac compiler
|
||||
FieldExprent arrayField = (FieldExprent)array.getArray();
|
||||
ClassesProcessor.ClassNode classNode = DecompilerContext.getClassProcessor().getMapRootClasses().get(arrayField.getClassname());
|
||||
if (classNode == null) return mapping;
|
||||
MethodWrapper wrapper = classNode.getWrapper().getMethodWrapper(CodeConstants.CLINIT_NAME, "()V");
|
||||
if (wrapper != null && wrapper.root != null) {
|
||||
wrapper.getOrBuildGraph().iterateExprents(exprent -> {
|
||||
if (exprent instanceof AssignmentExprent) {
|
||||
AssignmentExprent assignment = (AssignmentExprent)exprent;
|
||||
Exprent left = assignment.getLeft();
|
||||
if (left.type == Exprent.EXPRENT_ARRAY && ((ArrayExprent)left).getArray().equals(arrayField)) {
|
||||
mapping.put(assignment.getRight(), ((InvocationExprent)((ArrayExprent)left).getIndex()).getInstance());
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
} else if (array.getArray().type == Exprent.EXPRENT_INVOCATION) { // Eclipse compiler
|
||||
InvocationExprent invocationExprent = (InvocationExprent) array.getArray();
|
||||
ClassesProcessor.ClassNode classNode = DecompilerContext.getClassProcessor().getMapRootClasses().get(invocationExprent.getClassName());
|
||||
if (classNode == null) return mapping;
|
||||
MethodWrapper wrapper = classNode.getWrapper().getMethodWrapper(invocationExprent.getName(), "()[I");
|
||||
if (wrapper != null && wrapper.root != null) {
|
||||
wrapper.getOrBuildGraph().iterateExprents(exprent -> {
|
||||
if (exprent instanceof AssignmentExprent) {
|
||||
AssignmentExprent assignment = (AssignmentExprent)exprent;
|
||||
Exprent left = assignment.getLeft();
|
||||
if (left.type == Exprent.EXPRENT_ARRAY) {
|
||||
Exprent indexExprent = ((ArrayExprent)left).getIndex();
|
||||
if (indexExprent.type == Exprent.EXPRENT_INVOCATION && ((InvocationExprent) indexExprent).getName().equals("ordinal")) {
|
||||
mapping.put(assignment.getRight(), ((InvocationExprent)((ArrayExprent)left).getIndex()).getInstance());
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
return mapping;
|
||||
}
|
||||
@@ -134,9 +157,12 @@ public final class SwitchHelper {
|
||||
if (!(exprent instanceof ArrayExprent)) return false;
|
||||
Exprent field = ((ArrayExprent)exprent).getArray();
|
||||
Exprent index = ((ArrayExprent)exprent).getIndex();
|
||||
return field instanceof FieldExprent &&
|
||||
(((FieldExprent)field).getName().startsWith("$SwitchMap") ||
|
||||
(index instanceof InvocationExprent && ((InvocationExprent)index).getName().equals("ordinal")));
|
||||
boolean isJavacEnumArray = field instanceof FieldExprent &&
|
||||
(((FieldExprent)field).getName().startsWith("$SwitchMap") ||
|
||||
(index instanceof InvocationExprent && ((InvocationExprent)index).getName().equals("ordinal")));
|
||||
boolean isEclipseEnumArray = field instanceof InvocationExprent &&
|
||||
((InvocationExprent)field).getName().startsWith("$SWITCH_TABLE");
|
||||
return isJavacEnumArray || isEclipseEnumArray;
|
||||
}
|
||||
|
||||
static void removeTempVariableDeclarations(@NotNull Map<VarExprent, Statement> tempVarAssignments) {
|
||||
|
||||
@@ -120,6 +120,7 @@ public class SingleClassesTest {
|
||||
"pkg/SharedName2", "pkg/SharedName3", "pkg/SharedName4", "pkg/NonSharedName",
|
||||
"pkg/TestClashNameParent", "ext/TestClashNameParent","pkg/TestClashNameIface", "ext/TestClashNameIface"); }
|
||||
@Test public void testSwitchOnEnum() { doTest("pkg/TestSwitchOnEnum");}
|
||||
@Test public void testSwitchOnEnumEclipse() { doTest("pkg/TestSwitchOnEnumEclipse"); }
|
||||
@Test public void testVarArgCalls() { doTest("pkg/TestVarArgCalls"); }
|
||||
@Test public void testLambdaParams() { doTest("pkg/TestLambdaParams"); }
|
||||
@Test public void testInterfaceMethods() { doTest("pkg/TestInterfaceMethods"); }
|
||||
@@ -215,8 +216,6 @@ public class SingleClassesTest {
|
||||
@Test public void testNestedType() { doTest("pkg/NestedType"); }
|
||||
@Test public void testInheritanceChainCycle() { doTest("pkg/TestInheritanceChainCycle"); }
|
||||
@Test public void testDynamicConstantPoolEntry() { doTest("java11/TestDynamicConstantPoolEntry"); }
|
||||
|
||||
|
||||
@Test public void testInstanceofWithPattern() {
|
||||
doTest("patterns/TestInstanceofWithPattern");
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,101 @@
|
||||
package pkg;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class TestSwitchOnEnumEclipse {
|
||||
int myInt;
|
||||
|
||||
public int testSOE(TimeUnit t) {
|
||||
switch (t) {// 11
|
||||
case MICROSECONDS:
|
||||
return 2;// 13
|
||||
case MILLISECONDS:
|
||||
default:
|
||||
return 0;// 17
|
||||
case SECONDS:
|
||||
return 1;// 15
|
||||
}
|
||||
}
|
||||
|
||||
static class Example {
|
||||
void test(A a, B b) {
|
||||
switch (a) {// 27
|
||||
case A1:
|
||||
System.out.println("A1");// 29
|
||||
break;// 30
|
||||
case A2:
|
||||
System.out.println("A2");// 32
|
||||
}
|
||||
|
||||
switch (b) {// 35
|
||||
case B1:
|
||||
System.out.println("B1");// 37
|
||||
break;// 38
|
||||
case B2:
|
||||
System.out.println("B2");// 40
|
||||
}
|
||||
|
||||
}// 43
|
||||
|
||||
static enum A {
|
||||
A1,
|
||||
A2;
|
||||
}
|
||||
|
||||
static enum B {
|
||||
B1,
|
||||
B2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class 'pkg/TestSwitchOnEnumEclipse' {
|
||||
method 'testSOE (Ljava/util/concurrent/TimeUnit;)I' {
|
||||
8 8
|
||||
24 10
|
||||
25 10
|
||||
26 15
|
||||
27 15
|
||||
28 13
|
||||
29 13
|
||||
}
|
||||
}
|
||||
|
||||
class 'pkg/TestSwitchOnEnumEclipse$Example' {
|
||||
method 'test (Lpkg/TestSwitchOnEnumEclipse$Example$A;Lpkg/TestSwitchOnEnumEclipse$Example$B;)V' {
|
||||
8 21
|
||||
20 23
|
||||
23 23
|
||||
25 23
|
||||
28 24
|
||||
2b 26
|
||||
2e 26
|
||||
30 26
|
||||
3b 29
|
||||
50 31
|
||||
53 31
|
||||
55 31
|
||||
58 32
|
||||
5b 34
|
||||
5e 34
|
||||
60 34
|
||||
63 37
|
||||
}
|
||||
}
|
||||
|
||||
Lines mapping:
|
||||
11 <-> 9
|
||||
13 <-> 11
|
||||
15 <-> 16
|
||||
17 <-> 14
|
||||
27 <-> 22
|
||||
29 <-> 24
|
||||
30 <-> 25
|
||||
32 <-> 27
|
||||
35 <-> 30
|
||||
37 <-> 32
|
||||
38 <-> 33
|
||||
40 <-> 35
|
||||
43 <-> 38
|
||||
Not mapped:
|
||||
34
|
||||
@@ -0,0 +1,44 @@
|
||||
package pkg;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class TestSwitchOnEnumEclipse {
|
||||
|
||||
int myInt;
|
||||
|
||||
public int testSOE(TimeUnit t) {
|
||||
switch (t) {
|
||||
case MICROSECONDS:
|
||||
return 2;
|
||||
case SECONDS:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static class Example {
|
||||
|
||||
enum A { A1, A2 }
|
||||
|
||||
enum B { B1, B2 }
|
||||
|
||||
void test(A a, B b) {
|
||||
switch (a) {
|
||||
case A1:
|
||||
System.out.println("A1");
|
||||
break;
|
||||
case A2:
|
||||
System.out.println("A2");
|
||||
break;
|
||||
}
|
||||
switch (b) {
|
||||
case B1:
|
||||
System.out.println("B1");
|
||||
break;
|
||||
case B2:
|
||||
System.out.println("B2");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user