[java-decompiler] synthetic inner class constructor parameter filtering (IDEA-147606)
This commit is contained in:
@@ -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,17 +206,12 @@ 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 + "!";
|
||||||
@@ -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,10 +264,8 @@ 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);
|
||||||
|
|||||||
Binary file not shown.
BIN
testData/classes/pkg/TestInnerClassConstructor$Another.class
Normal file
BIN
testData/classes/pkg/TestInnerClassConstructor$Another.class
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
testData/classes/v11/TestInnerClassConstructor$Another.class
Normal file
BIN
testData/classes/v11/TestInnerClassConstructor$Another.class
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user