replace increment / decrement synthetic access method, pull-request #373
This commit is contained in:
@@ -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");
|
||||
* 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.util.InterpreterUtil;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
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_SET = 3;
|
||||
private static final int METHOD_ACCESS_METHOD = 4;
|
||||
private static final int METHOD_ACCESS_FUNCTION = 5;
|
||||
|
||||
private boolean noSynthFlag;
|
||||
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;
|
||||
case Exprent.EXPRENT_INVOCATION:
|
||||
type = METHOD_ACCESS_METHOD;
|
||||
@@ -139,7 +147,6 @@ public class NestedMemberAccess {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (type == METHOD_ACCESS_METHOD) { // FIXME: check for private flag of the method
|
||||
|
||||
type = METHOD_ACCESS_NORMAL;
|
||||
@@ -323,7 +330,6 @@ public class NestedMemberAccess {
|
||||
}
|
||||
|
||||
private Exprent replaceAccessExprent(ClassNode caller, MethodWrapper methdest, InvocationExprent invexpr) {
|
||||
|
||||
ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(invexpr.getClassname());
|
||||
|
||||
MethodWrapper methsource = null;
|
||||
@@ -408,6 +414,9 @@ public class NestedMemberAccess {
|
||||
}
|
||||
retexprent = ret;
|
||||
break;
|
||||
case METHOD_ACCESS_FUNCTION:
|
||||
retexprent = replaceFunction(invexpr, source);
|
||||
break;
|
||||
case METHOD_ACCESS_METHOD:
|
||||
if (source.type == Exprent.EXPRENT_EXIT) {
|
||||
source = ((ExitExprent)source).getValue();
|
||||
@@ -446,4 +455,25 @@ public class NestedMemberAccess {
|
||||
|
||||
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 testStaticNameClash() { doTest("pkg/TestStaticNameClash"); }
|
||||
@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();
|
||||
|
||||
File classFile = new File(fixture.getTestDataDir(), "/classes/" + testFile + ".class");
|
||||
@@ -131,4 +132,4 @@ public class SingleClassesTest {
|
||||
|
||||
return files;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BIN
testData/classes/pkg/TestSyntheticAccess$Assigner.class
Normal file
BIN
testData/classes/pkg/TestSyntheticAccess$Assigner.class
Normal file
Binary file not shown.
BIN
testData/classes/pkg/TestSyntheticAccess$Incrementer.class
Normal file
BIN
testData/classes/pkg/TestSyntheticAccess$Incrementer.class
Normal file
Binary file not shown.
BIN
testData/classes/pkg/TestSyntheticAccess.class
Normal file
BIN
testData/classes/pkg/TestSyntheticAccess.class
Normal file
Binary file not shown.
85
testData/results/TestSyntheticAccess.dec
Normal file
85
testData/results/TestSyntheticAccess.dec
Normal file
@@ -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
|
||||
44
testData/src/pkg/TestSyntheticAccess.java
Normal file
44
testData/src/pkg/TestSyntheticAccess.java
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user