[java-decompiler] synthetic inner class constructor parameter filtering (IDEA-147606)

master
Roman Shevchenko 9 years ago
parent 45a41684e6
commit 1794156473
  1. 24
      src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java
  2. BIN
      testData/classes/pkg/TestInnerClassConstructor$1.class
  3. BIN
      testData/classes/pkg/TestInnerClassConstructor$Another.class
  4. BIN
      testData/classes/pkg/TestInnerClassConstructor$Inner.class
  5. BIN
      testData/classes/pkg/TestInnerClassConstructor.class
  6. BIN
      testData/classes/v11/TestInnerClassConstructor$1.class
  7. BIN
      testData/classes/v11/TestInnerClassConstructor$Another.class
  8. BIN
      testData/classes/v11/TestInnerClassConstructor$Inner.class
  9. BIN
      testData/classes/v11/TestInnerClassConstructor.class
  10. 60
      testData/results/TestInnerClassConstructor.dec
  11. 12
      testData/src/pkg/TestInnerClassConstructor.java

@ -65,9 +65,9 @@ public class NestedClassProcessor {
int nameless = 0, synthetics = 0; int nameless = 0, synthetics = 0;
for (ClassNode child : node.nested) { for (ClassNode child : node.nested) {
StructClass cl = child.classStruct;
// ensure not-empty class name // ensure not-empty class name
if ((child.type == ClassNode.CLASS_LOCAL || child.type == ClassNode.CLASS_MEMBER) && child.simpleName == null) { if ((child.type == ClassNode.CLASS_LOCAL || child.type == ClassNode.CLASS_MEMBER) && child.simpleName == null) {
StructClass cl = child.classStruct;
if ((child.access & CodeConstants.ACC_SYNTHETIC) != 0 || cl.isSynthetic()) { if ((child.access & CodeConstants.ACC_SYNTHETIC) != 0 || cl.isSynthetic()) {
child.simpleName = "SyntheticClass_" + (++synthetics); child.simpleName = "SyntheticClass_" + (++synthetics);
} }
@ -78,6 +78,9 @@ public class NestedClassProcessor {
} }
child.namelessConstructorStub = !cl.hasModifier(CodeConstants.ACC_STATIC) && cl.getMethods().size() + cl.getFields().size() == 0; child.namelessConstructorStub = !cl.hasModifier(CodeConstants.ACC_STATIC) && cl.getMethods().size() + cl.getFields().size() == 0;
} }
else if (child.type == ClassNode.CLASS_ANONYMOUS && (child.access & CodeConstants.ACC_SYNTHETIC) != 0 || cl.isSynthetic()) {
child.namelessConstructorStub = !cl.hasModifier(CodeConstants.ACC_STATIC) && cl.getMethods().size() + cl.getFields().size() == 0;
}
} }
for (ClassNode child : node.nested) { for (ClassNode child : node.nested) {
@ -180,10 +183,14 @@ public class NestedClassProcessor {
List<ClassNode> copy = new ArrayList<ClassNode>(node.nested); List<ClassNode> copy = new ArrayList<ClassNode>(node.nested);
for (ClassNode child : copy) { for (ClassNode child : copy) {
if (child.classStruct.hasModifier(CodeConstants.ACC_SYNTHETIC)) {
continue;
}
if ((child.type == ClassNode.CLASS_LOCAL || child.type == ClassNode.CLASS_ANONYMOUS) && child.enclosingMethod == null) { if ((child.type == ClassNode.CLASS_LOCAL || child.type == ClassNode.CLASS_ANONYMOUS) && child.enclosingMethod == null) {
Set<String> setEnclosing = child.enclosingClasses; Set<String> setEnclosing = child.enclosingClasses;
if (setEnclosing.size() == 1) { if (!setEnclosing.isEmpty()) {
StructEnclosingMethodAttribute attr = StructEnclosingMethodAttribute attr =
(StructEnclosingMethodAttribute)child.classStruct.getAttributes().getWithKey("EnclosingMethod"); (StructEnclosingMethodAttribute)child.classStruct.getAttributes().getWithKey("EnclosingMethod");
if (attr != null && if (attr != null &&
@ -199,18 +206,13 @@ public class NestedClassProcessor {
child.parent = null; child.parent = null;
setEnclosing.remove(node.classStruct.qualifiedName); setEnclosing.remove(node.classStruct.qualifiedName);
boolean hasEnclosing = !setEnclosing.isEmpty(); boolean hasEnclosing = !setEnclosing.isEmpty() && insertNestedClass(root, child);
if (hasEnclosing) {
hasEnclosing = insertNestedClass(root, child);
}
if (!hasEnclosing) { if (!hasEnclosing) {
if (child.type == ClassNode.CLASS_ANONYMOUS) { if (child.type == ClassNode.CLASS_ANONYMOUS) {
if (!child.classStruct.hasModifier(CodeConstants.ACC_SYNTHETIC)) {
String message = "Unreferenced anonymous class " + child.classStruct.qualifiedName + "!"; String message = "Unreferenced anonymous class " + child.classStruct.qualifiedName + "!";
DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN); DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN);
} }
}
else if (child.type == ClassNode.CLASS_LOCAL) { else if (child.type == ClassNode.CLASS_LOCAL) {
String message = "Unreferenced local class " + child.classStruct.qualifiedName + "!"; String message = "Unreferenced local class " + child.classStruct.qualifiedName + "!";
DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN); DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN);
@ -251,6 +253,10 @@ public class NestedClassProcessor {
int clTypes = 0; int clTypes = 0;
for (ClassNode nd : node.nested) { for (ClassNode nd : node.nested) {
if (nd.classStruct.hasModifier(CodeConstants.ACC_SYNTHETIC)) {
continue;
}
if (nd.type != ClassNode.CLASS_LAMBDA && if (nd.type != ClassNode.CLASS_LAMBDA &&
(nd.access & CodeConstants.ACC_STATIC) == 0 && (nd.access & CodeConstants.ACC_STATIC) == 0 &&
(nd.access & CodeConstants.ACC_INTERFACE) == 0) { (nd.access & CodeConstants.ACC_INTERFACE) == 0) {
@ -258,11 +264,9 @@ public class NestedClassProcessor {
Map<String, List<VarFieldPair>> mask = getMaskLocalVars(nd.getWrapper()); Map<String, List<VarFieldPair>> mask = getMaskLocalVars(nd.getWrapper());
if (mask.isEmpty()) { if (mask.isEmpty()) {
if (!nd.classStruct.hasModifier(CodeConstants.ACC_SYNTHETIC)) {
String message = "Nested class " + nd.classStruct.qualifiedName + " has no constructor!"; String message = "Nested class " + nd.classStruct.qualifiedName + " has no constructor!";
DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN); DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN);
} }
}
else { else {
mapVarMasks.put(nd.classStruct.qualifiedName, mask); mapVarMasks.put(nd.classStruct.qualifiedName, mask);
} }

@ -1,40 +1,65 @@
package pkg; package pkg;
class TestInnerClassConstructor { class TestInnerClassConstructor {
void m() { void l() {
new TestInnerClassConstructor.Inner("text");// 5 new TestInnerClassConstructor.Inner("text");// 5
}// 6 }// 6
void n(String var1) { void m() {
System.out.println("n(): " + var1);// 9 new TestInnerClassConstructor.Another(3, 4);// 9
}// 10 }// 10
void n(String var1) {
System.out.println("n(): " + var1);// 13
}// 14
private class Another {
private Another(int var2, int var3) {
TestInnerClassConstructor.this.n(var2 + "+" + var3);// 24
}// 25
}
final class Inner { final class Inner {
private Inner(String var2) { private Inner(String var2) {
TestInnerClassConstructor.this.n(var2);// 14 TestInnerClassConstructor.this.n(var2);// 18
}// 15 }// 19
} }
} }
class 'pkg/TestInnerClassConstructor' { class 'pkg/TestInnerClassConstructor' {
method 'm ()V' { method 'l ()V' {
5 4 5 4
c 5 c 5
} }
method 'm ()V' {
5 8
6 8
c 9
}
method 'n (Ljava/lang/String;)V' { method 'n (Ljava/lang/String;)V' {
0 8 0 12
a 8 a 12
13 8 13 12
16 8 16 12
19 9 19 13
}
}
class 'pkg/TestInnerClassConstructor$Another' {
method '<init> (Lpkg/TestInnerClassConstructor;II)V' {
15 17
1e 17
21 17
24 18
} }
} }
class 'pkg/TestInnerClassConstructor$Inner' { class 'pkg/TestInnerClassConstructor$Inner' {
method '<init> (Lpkg/TestInnerClassConstructor;Ljava/lang/String;)V' { method '<init> (Lpkg/TestInnerClassConstructor;Ljava/lang/String;)V' {
b 13 b 23
e 14 e 24
} }
} }
@ -43,7 +68,12 @@ Lines mapping:
6 <-> 6 6 <-> 6
9 <-> 9 9 <-> 9
10 <-> 10 10 <-> 10
13 <-> 13
14 <-> 14 14 <-> 14
15 <-> 15 18 <-> 24
19 <-> 25
24 <-> 18
25 <-> 19
Not mapped: Not mapped:
13 17
23

@ -1,10 +1,14 @@
package pkg; package pkg;
class TestInnerClassConstructor { class TestInnerClassConstructor {
void m() { void l() {
new Inner("text"); new Inner("text");
} }
void m() {
new Another(3, 4);
}
void n(String s) { void n(String s) {
System.out.println("n(): " + s); System.out.println("n(): " + s);
} }
@ -14,4 +18,10 @@ class TestInnerClassConstructor {
n(s); n(s);
} }
} }
private class Another {
private Another(int a, int b) {
n(a + "+" + b);
}
}
} }

Loading…
Cancel
Save