[java decompiler] detecting Groovy synthetic constructor parameters

master
Roman Shevchenko 7 years ago
parent f83c480383
commit a3332a5f31
  1. 11
      src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java
  2. 1
      test/org/jetbrains/java/decompiler/SingleClassesTest.java
  3. BIN
      testData/classes/pkg/TestGroovyClass$Inner.class
  4. BIN
      testData/classes/pkg/TestGroovyClass$Nested.class
  5. BIN
      testData/classes/pkg/TestGroovyClass$_closure1.class
  6. BIN
      testData/classes/pkg/TestGroovyClass$_closure2.class
  7. BIN
      testData/classes/pkg/TestGroovyClass.class
  8. 230
      testData/results/TestGroovyClass.dec
  9. 13
      testData/src/pkg/TestGroovyClass.groovy

@ -376,10 +376,8 @@ public class NestedClassProcessor {
mergeListSignatures(entry.getValue(), interPairMask, false); mergeListSignatures(entry.getValue(), interPairMask, false);
List<VarVersionPair> mask = new ArrayList<>(entry.getValue().size()); List<VarVersionPair> mask = new ArrayList<>(entry.getValue().size());
boolean firstSignField = nestedNode.type != ClassNode.CLASS_ANONYMOUS;
for (VarFieldPair pair : entry.getValue()) { for (VarFieldPair pair : entry.getValue()) {
mask.add(pair == null || (!firstSignField && pair.fieldKey.isEmpty()) ? null : pair.varPair); mask.add(pair != null && !pair.fieldKey.isEmpty() ? pair.varPair : null);
firstSignField = false;
} }
nestedNode.getWrapper().getMethodWrapper(CodeConstants.INIT_NAME, entry.getKey()).synthParameters = mask; nestedNode.getWrapper().getMethodWrapper(CodeConstants.INIT_NAME, entry.getKey()).synthParameters = mask;
} }
@ -620,8 +618,7 @@ public class NestedClassProcessor {
StructField fd = cl.getField(left.getName(), left.getDescriptor().descriptorString); StructField fd = cl.getField(left.getName(), left.getDescriptor().descriptorString);
if (fd != null && if (fd != null &&
cl.qualifiedName.equals(left.getClassname()) && cl.qualifiedName.equals(left.getClassname()) &&
fd.hasModifier(CodeConstants.ACC_FINAL) && (fd.isSynthetic() || noSynthFlag && possiblySyntheticField(fd))) {
(fd.isSynthetic() || noSynthFlag && fd.hasModifier(CodeConstants.ACC_PRIVATE))) {
// local (== not inherited) field // local (== not inherited) field
field = InterpreterUtil.makeUniqueKey(left.getName(), left.getDescriptor().descriptorString); field = InterpreterUtil.makeUniqueKey(left.getName(), left.getDescriptor().descriptorString);
break; break;
@ -634,6 +631,10 @@ public class NestedClassProcessor {
return field; return field;
} }
private static boolean possiblySyntheticField(StructField fd) {
return fd.getName().contains("$") && fd.hasModifier(CodeConstants.ACC_FINAL) && fd.hasModifier(CodeConstants.ACC_PRIVATE);
}
private static void mergeListSignatures(List<VarFieldPair> first, List<VarFieldPair> second, boolean both) { private static void mergeListSignatures(List<VarFieldPair> first, List<VarFieldPair> second, boolean both) {
int i = 1; int i = 1;

@ -111,6 +111,7 @@ public class SingleClassesTest {
//@Test public void testInUse() { doTest("pkg/TestInUse"); } //@Test public void testInUse() { doTest("pkg/TestInUse"); }
//@Test public void testInterfaceSuper() { doTest("pkg/TestInterfaceSuper"); } //@Test public void testInterfaceSuper() { doTest("pkg/TestInterfaceSuper"); }
@Test public void testGroovyClass() { doTest("pkg/TestGroovyClass"); }
@Test public void testGroovyTrait() { doTest("pkg/TestGroovyTrait"); } @Test public void testGroovyTrait() { doTest("pkg/TestGroovyTrait"); }
private void doTest(String testFile, String... companionFiles) { private void doTest(String testFile, String... companionFiles) {

@ -0,0 +1,230 @@
package pkg;
import groovy.lang.Closure;
import groovy.lang.GroovyObject;
import groovy.lang.MetaClass;
import java.util.concurrent.Callable;
import org.codehaus.groovy.runtime.GeneratedClosure;
import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
import org.codehaus.groovy.runtime.callsite.CallSite;
public class TestGroovyClass implements GroovyObject {
private final TestGroovyClass.Nested n;
private final TestGroovyClass.Inner i;
private final Runnable r;
private final Callable<String> c;
public TestGroovyClass() {
CallSite[] var1 = $getCallSiteArray();
Object var2 = var1[0].callConstructor(TestGroovyClass.Nested.class);// 9
this.n = (TestGroovyClass.Nested)ScriptBytecodeAdapter.castToType(var2, TestGroovyClass.Nested.class);
Object var3 = var1[1].callConstructor(TestGroovyClass.Inner.class, this);
this.i = (TestGroovyClass.Inner)ScriptBytecodeAdapter.castToType(var3, TestGroovyClass.Inner.class);
TestGroovyClass._closure1 var4 = new TestGroovyClass._closure1(this, this);// 10
this.r = var4;
TestGroovyClass._closure2 var5 = new TestGroovyClass._closure2(this, this);
this.c = var5;
MetaClass var6 = this.$getStaticMetaClass();
this.metaClass = var6;
}
public final TestGroovyClass.Nested getN() {
return this.n;
}
public final TestGroovyClass.Inner getI() {
return this.i;
}
public final Runnable getR() {
return this.r;
}
public final Callable<String> getC() {
return this.c;
}
public static class Nested implements GroovyObject {
public Nested() {
CallSite[] var1 = $getCallSiteArray();
MetaClass var2 = this.$getStaticMetaClass();
this.metaClass = var2;
}
}
public class Inner implements GroovyObject {
public Inner() {
CallSite[] var2 = $getCallSiteArray();
super();
MetaClass var4 = this.$getStaticMetaClass();
this.metaClass = var4;
}
}
public class _closure1 extends Closure implements GeneratedClosure {
public _closure1(Object _outerInstance, Object _thisObject) {
CallSite[] var3 = $getCallSiteArray();
super(_outerInstance, _thisObject);
}
public Object doCall(Object it) {
CallSite[] var2 = $getCallSiteArray();
return var2[0].callCurrent(this, "I'm runnable");// 11
}
public Object doCall() {
CallSite[] var1 = $getCallSiteArray();
return this.doCall((Object)null);
}
}
public class _closure2 extends Closure implements GeneratedClosure {
public _closure2(Object _outerInstance, Object _thisObject) {
CallSite[] var3 = $getCallSiteArray();
super(_outerInstance, _thisObject);
}
public Object doCall(Object it) {
CallSite[] var2 = $getCallSiteArray();
return "I'm callable";// 12
}
public Object doCall() {
CallSite[] var1 = $getCallSiteArray();
return this.doCall((Object)null);
}
}
}
class 'pkg/TestGroovyClass' {
method '<init> ()V' {
4 17
7 17
9 18
b 18
c 18
e 18
13 18
15 19
17 19
1a 19
1f 19
25 20
27 20
28 20
2b 20
30 20
32 21
34 21
37 21
3c 21
4a 22
50 23
5f 24
65 25
6c 26
6f 26
75 27
7b 28
}
method 'getN ()Lpkg/TestGroovyClass$Nested;' {
1 31
4 31
}
method 'getI ()Lpkg/TestGroovyClass$Inner;' {
1 35
4 35
}
method 'getR ()Ljava/lang/Runnable;' {
1 39
4 39
}
method 'getC ()Ljava/util/concurrent/Callable;' {
1 43
4 43
}
}
class 'pkg/TestGroovyClass$Nested' {
method '<init> ()V' {
4 48
7 48
9 49
c 49
10 50
15 51
}
}
class 'pkg/TestGroovyClass$Inner' {
method '<init> (Lpkg/TestGroovyClass;)V' {
0 56
3 56
f 57
13 58
16 58
1c 59
22 60
}
}
class 'pkg/TestGroovyClass$_closure1' {
method '<init> (Ljava/lang/Object;Ljava/lang/Object;)V' {
0 65
3 65
7 66
a 67
}
method 'doCall (Ljava/lang/Object;)Ljava/lang/Object;' {
0 70
3 70
5 71
7 71
9 71
b 71
10 71
}
method 'doCall ()Ljava/lang/Object;' {
0 75
3 75
5 76
6 76
9 76
}
}
class 'pkg/TestGroovyClass$_closure2' {
method '<init> (Ljava/lang/Object;Ljava/lang/Object;)V' {
0 82
3 82
7 83
a 84
}
method 'doCall (Ljava/lang/Object;)Ljava/lang/Object;' {
0 87
3 87
4 88
6 88
}
method 'doCall ()Ljava/lang/Object;' {
0 92
3 92
5 93
6 93
9 93
}
}
Lines mapping:
9 <-> 19
10 <-> 23
11 <-> 72
12 <-> 89

@ -0,0 +1,13 @@
package pkg
import java.util.concurrent.Callable
class TestGroovyClass {
static class Nested { }
class Inner { }
final Nested n = new Nested()
final Inner i = new Inner()
final Runnable r = { println("I'm runnable") }
final Callable<String> c = { "I'm callable" }
}
Loading…
Cancel
Save