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

master
Roman Shevchenko 9 years ago
parent 45a41684e6
commit 1794156473
  1. 32
      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;
for (ClassNode child : node.nested) {
StructClass cl = child.classStruct;
// ensure not-empty class name
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()) {
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;
}
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) {
@ -180,10 +183,14 @@ public class NestedClassProcessor {
List<ClassNode> copy = new ArrayList<ClassNode>(node.nested);
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) {
Set<String> setEnclosing = child.enclosingClasses;
if (setEnclosing.size() == 1) {
if (!setEnclosing.isEmpty()) {
StructEnclosingMethodAttribute attr =
(StructEnclosingMethodAttribute)child.classStruct.getAttributes().getWithKey("EnclosingMethod");
if (attr != null &&
@ -199,17 +206,12 @@ public class NestedClassProcessor {
child.parent = null;
setEnclosing.remove(node.classStruct.qualifiedName);
boolean hasEnclosing = !setEnclosing.isEmpty();
if (hasEnclosing) {
hasEnclosing = insertNestedClass(root, child);
}
boolean hasEnclosing = !setEnclosing.isEmpty() && insertNestedClass(root, child);
if (!hasEnclosing) {
if (child.type == ClassNode.CLASS_ANONYMOUS) {
if (!child.classStruct.hasModifier(CodeConstants.ACC_SYNTHETIC)) {
String message = "Unreferenced anonymous class " + child.classStruct.qualifiedName + "!";
DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN);
}
String message = "Unreferenced anonymous class " + child.classStruct.qualifiedName + "!";
DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN);
}
else if (child.type == ClassNode.CLASS_LOCAL) {
String message = "Unreferenced local class " + child.classStruct.qualifiedName + "!";
@ -251,6 +253,10 @@ public class NestedClassProcessor {
int clTypes = 0;
for (ClassNode nd : node.nested) {
if (nd.classStruct.hasModifier(CodeConstants.ACC_SYNTHETIC)) {
continue;
}
if (nd.type != ClassNode.CLASS_LAMBDA &&
(nd.access & CodeConstants.ACC_STATIC) == 0 &&
(nd.access & CodeConstants.ACC_INTERFACE) == 0) {
@ -258,10 +264,8 @@ public class NestedClassProcessor {
Map<String, List<VarFieldPair>> mask = getMaskLocalVars(nd.getWrapper());
if (mask.isEmpty()) {
if (!nd.classStruct.hasModifier(CodeConstants.ACC_SYNTHETIC)) {
String message = "Nested class " + nd.classStruct.qualifiedName + " has no constructor!";
DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN);
}
String message = "Nested class " + nd.classStruct.qualifiedName + " has no constructor!";
DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN);
}
else {
mapVarMasks.put(nd.classStruct.qualifiedName, mask);

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

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

Loading…
Cancel
Save