replace increment / decrement synthetic access method, pull-request #373

master
Egor.Ushakov 9 years ago
parent 081a208a6a
commit 95215dc2e2
  1. 44
      src/org/jetbrains/java/decompiler/main/rels/NestedMemberAccess.java
  2. 3
      test/org/jetbrains/java/decompiler/SingleClassesTest.java
  3. BIN
      testData/classes/pkg/TestSyntheticAccess$Assigner.class
  4. BIN
      testData/classes/pkg/TestSyntheticAccess$Incrementer.class
  5. BIN
      testData/classes/pkg/TestSyntheticAccess.class
  6. 85
      testData/results/TestSyntheticAccess.dec
  7. 44
      testData/src/pkg/TestSyntheticAccess.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2000-2015 JetBrains s.r.o. * Copyright 2000-2016 JetBrains s.r.o.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -29,10 +29,7 @@ import org.jetbrains.java.decompiler.struct.StructMethod;
import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor; import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.util.HashMap; import java.util.*;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
public class NestedMemberAccess { public class NestedMemberAccess {
@ -40,6 +37,7 @@ public class NestedMemberAccess {
private static final int METHOD_ACCESS_FIELD_GET = 2; private static final int METHOD_ACCESS_FIELD_GET = 2;
private static final int METHOD_ACCESS_FIELD_SET = 3; private static final int METHOD_ACCESS_FIELD_SET = 3;
private static final int METHOD_ACCESS_METHOD = 4; private static final int METHOD_ACCESS_METHOD = 4;
private static final int METHOD_ACCESS_FUNCTION = 5;
private boolean noSynthFlag; private boolean noSynthFlag;
private final Map<MethodWrapper, Integer> mapMethodType = new HashMap<MethodWrapper, Integer>(); private final Map<MethodWrapper, Integer> mapMethodType = new HashMap<MethodWrapper, Integer>();
@ -117,6 +115,16 @@ public class NestedMemberAccess {
} }
} }
break;
case Exprent.EXPRENT_FUNCTION:
// for now detect only increment/decrement
FunctionExprent functionExprent = (FunctionExprent)exprCore;
if (functionExprent.getFuncType() >= FunctionExprent.FUNCTION_IMM &&
functionExprent.getFuncType() <= FunctionExprent.FUNCTION_PPI) {
if (functionExprent.getLstOperands().get(0).type == Exprent.EXPRENT_FIELD) {
type = METHOD_ACCESS_FUNCTION;
}
}
break; break;
case Exprent.EXPRENT_INVOCATION: case Exprent.EXPRENT_INVOCATION:
type = METHOD_ACCESS_METHOD; type = METHOD_ACCESS_METHOD;
@ -139,7 +147,6 @@ public class NestedMemberAccess {
} }
} }
if (type == METHOD_ACCESS_METHOD) { // FIXME: check for private flag of the method if (type == METHOD_ACCESS_METHOD) { // FIXME: check for private flag of the method
type = METHOD_ACCESS_NORMAL; type = METHOD_ACCESS_NORMAL;
@ -323,7 +330,6 @@ public class NestedMemberAccess {
} }
private Exprent replaceAccessExprent(ClassNode caller, MethodWrapper methdest, InvocationExprent invexpr) { private Exprent replaceAccessExprent(ClassNode caller, MethodWrapper methdest, InvocationExprent invexpr) {
ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(invexpr.getClassname()); ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(invexpr.getClassname());
MethodWrapper methsource = null; MethodWrapper methsource = null;
@ -408,6 +414,9 @@ public class NestedMemberAccess {
} }
retexprent = ret; retexprent = ret;
break; break;
case METHOD_ACCESS_FUNCTION:
retexprent = replaceFunction(invexpr, source);
break;
case METHOD_ACCESS_METHOD: case METHOD_ACCESS_METHOD:
if (source.type == Exprent.EXPRENT_EXIT) { if (source.type == Exprent.EXPRENT_EXIT) {
source = ((ExitExprent)source).getValue(); source = ((ExitExprent)source).getValue();
@ -446,4 +455,25 @@ public class NestedMemberAccess {
return retexprent; return retexprent;
} }
private static Exprent replaceFunction(final InvocationExprent invexpr, final Exprent source) {
FunctionExprent functionExprent = (FunctionExprent)((ExitExprent)source).getValue().copy();
List<Exprent> lstParameters = invexpr.getLstParameters();
FieldExprent fieldExprent = (FieldExprent)functionExprent.getLstOperands().get(0);
if (fieldExprent.isStatic()) {
if (!lstParameters.isEmpty()) {
return null;
}
return functionExprent;
}
if (lstParameters.size() != 1) {
return null;
}
fieldExprent.replaceExprent(fieldExprent.getInstance(), lstParameters.get(0));
return functionExprent;
}
} }

@ -85,8 +85,9 @@ public class SingleClassesTest {
@Test public void testMemberAnnotations() { doTest("pkg/TestMemberAnnotations"); } @Test public void testMemberAnnotations() { doTest("pkg/TestMemberAnnotations"); }
@Test public void testStaticNameClash() { doTest("pkg/TestStaticNameClash"); } @Test public void testStaticNameClash() { doTest("pkg/TestStaticNameClash"); }
@Test public void testExtendingSubclass() { doTest("pkg/TestExtendingSubclass"); } @Test public void testExtendingSubclass() { doTest("pkg/TestExtendingSubclass"); }
@Test public void testSyntheticAccess() { doTest("pkg/TestSyntheticAccess"); }
protected void doTest(String testFile, String... companionFiles) { private void doTest(String testFile, String... companionFiles) {
ConsoleDecompiler decompiler = fixture.getDecompiler(); ConsoleDecompiler decompiler = fixture.getDecompiler();
File classFile = new File(fixture.getTestDataDir(), "/classes/" + testFile + ".class"); File classFile = new File(fixture.getTestDataDir(), "/classes/" + testFile + ".class");

@ -0,0 +1,85 @@
package pkg;
class TestSyntheticAccess {
private static int s;
private int i;
private class Assigner {
void assignI(int newValue) {
TestSyntheticAccess.this.i = newValue;// 32
}// 33
void assignS(int newValue) {
TestSyntheticAccess.s = newValue;// 36
}// 37
}
private class Incrementer {
void incrementI() {
TestSyntheticAccess.this.i++;// 14
}// 15
void decrementI() {
--TestSyntheticAccess.this.i;// 18
}// 19
void incrementS() {
++TestSyntheticAccess.s;// 22 23
}
void decrementS() {
TestSyntheticAccess.s--;// 26
}// 27
}
}
class 'pkg/TestSyntheticAccess$Assigner' {
method 'assignI (I)V' {
3 8
9 9
}
method 'assignS (I)V' {
2 12
5 13
}
}
class 'pkg/TestSyntheticAccess$Incrementer' {
method 'incrementI ()V' {
2 18
7 18
8 19
}
method 'decrementI ()V' {
2 22
6 22
8 23
}
method 'incrementS ()V' {
0 26
4 26
}
method 'decrementS ()V' {
0 30
4 31
5 30
}
}
Lines mapping:
14 <-> 19
15 <-> 20
18 <-> 23
19 <-> 24
22 <-> 27
23 <-> 27
26 <-> 31
27 <-> 32
32 <-> 9
33 <-> 10
36 <-> 13
37 <-> 14

@ -0,0 +1,44 @@
package pkg;
/**
* @author Alexandru-Constantin Bledea
* @since March 20, 2016
*/
class TestSyntheticAccess {
private static int s;
private int i;
private class Incrementer {
void orI() {
i|=1;
}
void incrementI() {
i++;
}
void decrementI() {
--i;
}
void incrementS() {
++s;
}
void decrementS() {
s--;
}
}
private class Assigner {
void assignI(int newValue) {
i = newValue;
}
void assignS(int newValue) {
s = newValue;
}
}
}
Loading…
Cancel
Save