/*
- * 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.
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 {
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>();
}
}
+ 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;
}
}
-
if (type == METHOD_ACCESS_METHOD) { // FIXME: check for private flag of the method
type = METHOD_ACCESS_NORMAL;
}
private Exprent replaceAccessExprent(ClassNode caller, MethodWrapper methdest, InvocationExprent invexpr) {
-
ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(invexpr.getClassname());
MethodWrapper methsource = null;
}
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();
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;
+ }
}
@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");
return files;
}
-}
\ No newline at end of file
+}
--- /dev/null
+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