replace increment / decrement synthetic access method, pull-request #373
authorEgor.Ushakov <egor.ushakov@jetbrains.com>
Mon, 28 Mar 2016 10:57:29 +0000 (13:57 +0300)
committerEgor.Ushakov <egor.ushakov@jetbrains.com>
Mon, 28 Mar 2016 11:00:25 +0000 (14:00 +0300)
plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/rels/NestedMemberAccess.java
plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java
plugins/java-decompiler/engine/testData/classes/pkg/TestSyntheticAccess$Assigner.class [new file with mode: 0644]
plugins/java-decompiler/engine/testData/classes/pkg/TestSyntheticAccess$Incrementer.class [new file with mode: 0644]
plugins/java-decompiler/engine/testData/classes/pkg/TestSyntheticAccess.class [new file with mode: 0644]
plugins/java-decompiler/engine/testData/results/TestSyntheticAccess.dec [new file with mode: 0644]
plugins/java-decompiler/engine/testData/src/pkg/TestSyntheticAccess.java [new file with mode: 0644]

index 3fa8128a4e7f607770d592033588e716f49f12f0..2ea32bdf44915c1027f2c20cf8d20fe8138dc570 100644 (file)
@@ -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;
+  }
 }
index 100deeba62822138941192403262855a0e232cb1..5bdbdc58bec4e1fa72ee0af54669d814edf13b4f 100644 (file)
@@ -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;
   }
-}
\ No newline at end of file
+}
diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestSyntheticAccess$Assigner.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestSyntheticAccess$Assigner.class
new file mode 100644 (file)
index 0000000..c15e644
Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/pkg/TestSyntheticAccess$Assigner.class differ
diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestSyntheticAccess$Incrementer.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestSyntheticAccess$Incrementer.class
new file mode 100644 (file)
index 0000000..631d437
Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/pkg/TestSyntheticAccess$Incrementer.class differ
diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestSyntheticAccess.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestSyntheticAccess.class
new file mode 100644 (file)
index 0000000..b4e05e6
Binary files /dev/null and b/plugins/java-decompiler/engine/testData/classes/pkg/TestSyntheticAccess.class differ
diff --git a/plugins/java-decompiler/engine/testData/results/TestSyntheticAccess.dec b/plugins/java-decompiler/engine/testData/results/TestSyntheticAccess.dec
new file mode 100644 (file)
index 0000000..1f8a5d5
--- /dev/null
@@ -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
diff --git a/plugins/java-decompiler/engine/testData/src/pkg/TestSyntheticAccess.java b/plugins/java-decompiler/engine/testData/src/pkg/TestSyntheticAccess.java
new file mode 100644 (file)
index 0000000..0c4e3ea
--- /dev/null
@@ -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;
+    }
+  }
+
+}