summaryrefslogtreecommitdiffstats
path: root/src/org/jetbrains/java/decompiler/main/rels/NestedMemberAccess.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/jetbrains/java/decompiler/main/rels/NestedMemberAccess.java')
-rw-r--r--src/org/jetbrains/java/decompiler/main/rels/NestedMemberAccess.java869
1 files changed, 433 insertions, 436 deletions
diff --git a/src/org/jetbrains/java/decompiler/main/rels/NestedMemberAccess.java b/src/org/jetbrains/java/decompiler/main/rels/NestedMemberAccess.java
index 3eda632..e81a69e 100644
--- a/src/org/jetbrains/java/decompiler/main/rels/NestedMemberAccess.java
+++ b/src/org/jetbrains/java/decompiler/main/rels/NestedMemberAccess.java
@@ -1,35 +1,27 @@
/*
- * Fernflower - The Analytical Java Decompiler
- * http://www.reversed-java.com
+ * Copyright 2000-2014 JetBrains s.r.o.
*
- * (C) 2008 - 2010, Stiver
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * This software is NEITHER public domain NOR free software
- * as per GNU License. See license.txt for more details.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * This software is distributed WITHOUT ANY WARRANTY; without
- * even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
-
package org.jetbrains.java.decompiler.main.rels;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-
import org.jetbrains.java.decompiler.code.CodeConstants;
-import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
+import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.collectors.CounterContainer;
import org.jetbrains.java.decompiler.main.collectors.VarNamesCollector;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
-import org.jetbrains.java.decompiler.modules.decompiler.exps.AssignmentExprent;
-import org.jetbrains.java.decompiler.modules.decompiler.exps.ExitExprent;
-import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent;
-import org.jetbrains.java.decompiler.modules.decompiler.exps.FieldExprent;
-import org.jetbrains.java.decompiler.modules.decompiler.exps.InvocationExprent;
-import org.jetbrains.java.decompiler.modules.decompiler.exps.VarExprent;
+import org.jetbrains.java.decompiler.modules.decompiler.exps.*;
import org.jetbrains.java.decompiler.modules.decompiler.sforms.DirectGraph;
import org.jetbrains.java.decompiler.modules.decompiler.sforms.DirectNode;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPaar;
@@ -37,421 +29,426 @@ 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;
+
public class NestedMemberAccess {
-
- private static final int METHOD_ACCESS_NORMAL = 1;
- private static final int METHOD_ACCESS_FIELDGET = 2;
- private static final int METHOD_ACCESS_FIELDSET = 3;
- private static final int METHOD_ACCESS_METHOD = 4;
-
- private boolean notSetSync;
-
- private HashMap<MethodWrapper, Integer> mapMethodType = new HashMap<MethodWrapper, Integer>();
-
-
- public void propagateMemberAccess(ClassNode root) {
-
- if(root.nested.isEmpty()) {
- return;
- }
-
- notSetSync = DecompilerContext.getOption(IFernflowerPreferences.SYNTHETIC_NOT_SET);
-
- computeMethodTypes(root);
-
- eliminateStaticAccess(root);
- }
-
-
- private void computeMethodTypes(ClassNode node) {
-
- if(node.type == ClassNode.CLASS_LAMBDA) {
- return;
- }
-
- for(ClassNode nd : node.nested) {
- computeMethodTypes(nd);
- }
-
- for(MethodWrapper meth : node.wrapper.getMethods()) {
- computeMethodType(node, meth);
- }
-
- }
-
- private void computeMethodType(ClassNode node, MethodWrapper meth) {
-
- int type = METHOD_ACCESS_NORMAL;
-
- if(meth.root != null) {
-
- DirectGraph graph = meth.getOrBuildGraph();
-
- int flags = meth.methodStruct.getAccessFlags();
- if(((flags & CodeConstants.ACC_SYNTHETIC) != 0 || meth.methodStruct.getAttributes().containsKey("Synthetic") || notSetSync) &&
- (flags & CodeConstants.ACC_STATIC) != 0) {
- if(graph.nodes.size() == 2) { // incl. dummy exit node
- if(graph.first.exprents.size() == 1) {
- Exprent exprent = graph.first.exprents.get(0);
-
- MethodDescriptor mtdesc = MethodDescriptor.parseDescriptor(meth.methodStruct.getDescriptor());
- int parcount = mtdesc.params.length;
-
- Exprent exprCore = exprent;
-
- if(exprent.type == Exprent.EXPRENT_EXIT) {
- ExitExprent exexpr = (ExitExprent)exprent;
- if(exexpr.getExittype() == ExitExprent.EXIT_RETURN && exexpr.getValue() != null) {
- exprCore = exexpr.getValue();
- }
- }
-
- switch(exprCore.type) {
- case Exprent.EXPRENT_FIELD:
- FieldExprent fexpr = (FieldExprent)exprCore;
- if((parcount == 1 && !fexpr.isStatic()) ||
- (parcount == 0 && fexpr.isStatic())) {
- if(fexpr.getClassname().equals(node.classStruct.qualifiedName)) { // FIXME: check for private flag of the field
- if(fexpr.isStatic() || (fexpr.getInstance().type == Exprent.EXPRENT_VAR && ((VarExprent)fexpr.getInstance()).getIndex() == 0)) {
- type = METHOD_ACCESS_FIELDGET;
- }
- }
- }
- break;
- case Exprent.EXPRENT_VAR: // qualified this
- if(parcount == 1) {
- // this or final variable
- if(((VarExprent)exprCore).getIndex() != 0) {
- type = METHOD_ACCESS_FIELDGET;
- }
- }
-
- break;
- case Exprent.EXPRENT_INVOCATION:
- type = METHOD_ACCESS_METHOD;
- break;
- case Exprent.EXPRENT_ASSIGNMENT:
- AssignmentExprent asexpr = (AssignmentExprent)exprCore;
- if(asexpr.getLeft().type == Exprent.EXPRENT_FIELD && asexpr.getRight().type == Exprent.EXPRENT_VAR) {
- FieldExprent fexpras = (FieldExprent)asexpr.getLeft();
- if((parcount == 2 && !fexpras.isStatic()) ||
- (parcount == 1 && fexpras.isStatic())) {
- if(fexpras.getClassname().equals(node.classStruct.qualifiedName)) { // FIXME: check for private flag of the field
- if(fexpras.isStatic() || (fexpras.getInstance().type == Exprent.EXPRENT_VAR && ((VarExprent)fexpras.getInstance()).getIndex() == 0)) {
- if(((VarExprent)asexpr.getRight()).getIndex() == parcount - 1) {
- type = METHOD_ACCESS_FIELDSET;
- }
- }
- }
- }
- }
- }
-
-
- if(type == METHOD_ACCESS_METHOD) { // FIXME: check for private flag of the method
-
- type = METHOD_ACCESS_NORMAL;
-
- InvocationExprent invexpr = (InvocationExprent)exprCore;
-
- if((invexpr.isStatic() && invexpr.getLstParameters().size() == parcount) || (!invexpr.isStatic() && invexpr.getInstance().type == Exprent.EXPRENT_VAR
- && ((VarExprent)invexpr.getInstance()).getIndex() == 0 && invexpr.getLstParameters().size() == parcount-1)) {
-
- boolean equalpars = true;
-
- for(int i=0;i<invexpr.getLstParameters().size();i++) {
- Exprent parexpr = invexpr.getLstParameters().get(i);
- if(parexpr.type != Exprent.EXPRENT_VAR ||
- ((VarExprent)parexpr).getIndex() != i + (invexpr.isStatic()?0:1)) {
- equalpars = false;
- break;
- }
- }
-
- if(equalpars) {
- type = METHOD_ACCESS_METHOD;
- }
- }
- }
- } else if(graph.first.exprents.size() == 2) {
- Exprent exprentFirst = graph.first.exprents.get(0);
- Exprent exprentSecond = graph.first.exprents.get(1);
-
- if(exprentFirst.type == Exprent.EXPRENT_ASSIGNMENT &&
- exprentSecond.type == Exprent.EXPRENT_EXIT) {
-
- MethodDescriptor mtdesc = MethodDescriptor.parseDescriptor(meth.methodStruct.getDescriptor());
- int parcount = mtdesc.params.length;
-
- AssignmentExprent asexpr = (AssignmentExprent)exprentFirst;
- if(asexpr.getLeft().type == Exprent.EXPRENT_FIELD && asexpr.getRight().type == Exprent.EXPRENT_VAR) {
- FieldExprent fexpras = (FieldExprent)asexpr.getLeft();
- if((parcount == 2 && !fexpras.isStatic()) ||
- (parcount == 1 && fexpras.isStatic())) {
- if(fexpras.getClassname().equals(node.classStruct.qualifiedName)) { // FIXME: check for private flag of the field
- if(fexpras.isStatic() || (fexpras.getInstance().type == Exprent.EXPRENT_VAR && ((VarExprent)fexpras.getInstance()).getIndex() == 0)) {
- if(((VarExprent)asexpr.getRight()).getIndex() == parcount - 1) {
-
- ExitExprent exexpr = (ExitExprent)exprentSecond;
- if(exexpr.getExittype() == ExitExprent.EXIT_RETURN && exexpr.getValue() != null) {
- if(exexpr.getValue().type == Exprent.EXPRENT_VAR &&
- ((VarExprent)asexpr.getRight()).getIndex() == parcount - 1) {
- type = METHOD_ACCESS_FIELDSET;
- }
- }
- }
- }
- }
- }
- }
- }
- }
-
-
- }
- }
- }
-
- if(type != METHOD_ACCESS_NORMAL) {
- mapMethodType.put(meth, type);
- } else {
- mapMethodType.remove(meth);
- }
- }
-
-
-
- private void eliminateStaticAccess(ClassNode node) {
-
- if(node.type == ClassNode.CLASS_LAMBDA) {
- return;
- }
-
- for(MethodWrapper meth : node.wrapper.getMethods()) {
-
- if(meth.root != null) {
-
- boolean replaced = false;
-
- DirectGraph graph = meth.getOrBuildGraph();
-
- HashSet<DirectNode> setVisited = new HashSet<DirectNode>();
- LinkedList<DirectNode> stack = new LinkedList<DirectNode>();
- stack.add(graph.first);
-
- while(!stack.isEmpty()) { // TODO: replace with interface iterator?
-
- DirectNode nd = stack.removeFirst();
-
- if(setVisited.contains(nd)) {
- continue;
- }
- setVisited.add(nd);
-
- for(int i=0;i<nd.exprents.size();i++) {
- Exprent exprent = nd.exprents.get(i);
-
- replaced |= replaceInvocations(node, meth, exprent);
-
- if(exprent.type == Exprent.EXPRENT_INVOCATION) {
- Exprent ret = replaceAccessExprent(node, meth, (InvocationExprent)exprent);
-
- if(ret != null) {
- nd.exprents.set(i, ret);
- replaced = true;
- }
- }
- }
-
- for(DirectNode ndx: nd.succs) {
- stack.add(ndx);
- }
- }
-
- if(replaced) {
- computeMethodType(node, meth);
- }
-
- }
- }
-
- for(ClassNode child : node.nested) {
- eliminateStaticAccess(child);
- }
-
- }
-
-
- private boolean replaceInvocations(ClassNode caller, MethodWrapper meth, Exprent exprent) {
-
- boolean res = false;
-
- for(Exprent expr : exprent.getAllExprents()) {
- res |= replaceInvocations(caller, meth, expr);
- }
-
- for(;;) {
-
- boolean found = false;
-
- for(Exprent expr : exprent.getAllExprents()) {
- if(expr.type == Exprent.EXPRENT_INVOCATION) {
- Exprent newexpr = replaceAccessExprent(caller, meth, (InvocationExprent)expr);
- if(newexpr != null) {
- exprent.replaceExprent(expr, newexpr);
- found = true;
- res = true;
- break;
- }
- }
- }
-
- if(!found) {
- break;
- }
- }
-
- return res;
- }
-
- private boolean sameTree(ClassNode caller, ClassNode callee) {
-
- if(caller.classStruct.qualifiedName.equals(callee.classStruct.qualifiedName)) {
- return false;
- }
-
- while(caller.parent != null) {
- caller = caller.parent;
- }
-
- while(callee.parent != null) {
- callee = callee.parent;
- }
-
- return caller == callee;
- }
-
- private Exprent replaceAccessExprent(ClassNode caller, MethodWrapper methdest, InvocationExprent invexpr) {
-
- ClassNode node = DecompilerContext.getClassprocessor().getMapRootClasses().get(invexpr.getClassname());
-
- MethodWrapper methsource = null;
- if(node != null && node.wrapper != null) {
- methsource = node.wrapper.getMethodWrapper(invexpr.getName(), invexpr.getStringDescriptor());
- }
-
- if(methsource == null || !mapMethodType.containsKey(methsource)) {
- return null;
- }
-
- // if same method, return
- if(node.classStruct.qualifiedName.equals(caller.classStruct.qualifiedName) &&
- methsource.methodStruct.getName().equals(methdest.methodStruct.getName()) &&
- methsource.methodStruct.getDescriptor().equals(methdest.methodStruct.getDescriptor())) {
- // no recursive invocations permitted!
- return null;
- }
-
- int type = mapMethodType.get(methsource);
-
-// // FIXME: impossible case. METHOD_ACCESS_NORMAL is not saved in the map
-// if(type == METHOD_ACCESS_NORMAL) {
-// return null;
-// }
-
- if(!sameTree(caller, node)) {
- return null;
- }
-
- DirectGraph graph = methsource.getOrBuildGraph();
- Exprent source = graph.first.exprents.get(0);
-
- Exprent retexprent = null;
-
- switch(type) {
- case METHOD_ACCESS_FIELDGET:
- ExitExprent exsource = (ExitExprent)source;
- if(exsource.getValue().type == Exprent.EXPRENT_VAR) { // qualified this
- VarExprent var = (VarExprent)exsource.getValue();
- String varname = methsource.varproc.getVarName(new VarVersionPaar(var));
-
- if(!methdest.setOuterVarNames.contains(varname)) {
- VarNamesCollector vnc = new VarNamesCollector();
- vnc.addName(varname);
-
- methdest.varproc.refreshVarNames(vnc);
- methdest.setOuterVarNames.add(varname);
- }
-
- int index = methdest.counter.getCounterAndIncrement(CounterContainer.VAR_COUNTER);
- VarExprent ret = new VarExprent(index, var.getVartype(), methdest.varproc);
- methdest.varproc.setVarName(new VarVersionPaar(index, 0), varname);
-
- retexprent = ret;
- } else { // field
- FieldExprent ret = (FieldExprent)exsource.getValue().copy();
- if(!ret.isStatic()) {
- ret.replaceExprent(ret.getInstance(), invexpr.getLstParameters().get(0));
- }
- retexprent = ret;
- }
- break;
- case METHOD_ACCESS_FIELDSET:
- AssignmentExprent ret;
- if(source.type == Exprent.EXPRENT_EXIT) {
- ExitExprent extex = (ExitExprent)source;
- ret = (AssignmentExprent)((AssignmentExprent)extex.getValue()).copy();
- } else {
- ret = (AssignmentExprent)((AssignmentExprent)source).copy();
- }
- FieldExprent fexpr = (FieldExprent)ret.getLeft();
-
- if(fexpr.isStatic()) {
- ret.replaceExprent(ret.getRight(), invexpr.getLstParameters().get(0));
- } else {
- ret.replaceExprent(ret.getRight(), invexpr.getLstParameters().get(1));
- fexpr.replaceExprent(fexpr.getInstance(), invexpr.getLstParameters().get(0));
- }
- retexprent = ret;
- break;
- case METHOD_ACCESS_METHOD:
- if(source.type == Exprent.EXPRENT_EXIT) {
- source = ((ExitExprent)source).getValue();
- }
-
- InvocationExprent invret = (InvocationExprent)source.copy();
-
- int index = 0;
- if(!invret.isStatic()) {
- invret.replaceExprent(invret.getInstance(), invexpr.getLstParameters().get(0));
- index = 1;
- }
-
- for(int i=0;i<invret.getLstParameters().size();i++) {
- invret.replaceExprent(invret.getLstParameters().get(i), invexpr.getLstParameters().get(i + index));
- }
-
- retexprent = invret;
- }
-
-
- if(retexprent != null) {
- // hide synthetic access method
- boolean hide = true;
-
- if(node.type == ClassNode.CLASS_ROOT || (node.access & CodeConstants.ACC_STATIC) != 0) {
- StructMethod mt = methsource.methodStruct;
- if((mt.getAccessFlags() & CodeConstants.ACC_SYNTHETIC) == 0 && !mt.getAttributes().containsKey("Synthetic")) {
- hide = false;
- }
- }
- if(hide) {
- node.wrapper.getHideMembers().add(InterpreterUtil.makeUniqueKey(invexpr.getName(), invexpr.getStringDescriptor()));
- }
- }
-
- return retexprent;
- }
-
-
+
+ private static final int METHOD_ACCESS_NORMAL = 1;
+ private static final int METHOD_ACCESS_FIELDGET = 2;
+ private static final int METHOD_ACCESS_FIELDSET = 3;
+ private static final int METHOD_ACCESS_METHOD = 4;
+
+ private boolean notSetSync;
+
+ private HashMap<MethodWrapper, Integer> mapMethodType = new HashMap<MethodWrapper, Integer>();
+
+
+ public void propagateMemberAccess(ClassNode root) {
+
+ if (root.nested.isEmpty()) {
+ return;
+ }
+
+ notSetSync = DecompilerContext.getOption(IFernflowerPreferences.SYNTHETIC_NOT_SET);
+
+ computeMethodTypes(root);
+
+ eliminateStaticAccess(root);
+ }
+
+
+ private void computeMethodTypes(ClassNode node) {
+
+ if (node.type == ClassNode.CLASS_LAMBDA) {
+ return;
+ }
+
+ for (ClassNode nd : node.nested) {
+ computeMethodTypes(nd);
+ }
+
+ for (MethodWrapper meth : node.wrapper.getMethods()) {
+ computeMethodType(node, meth);
+ }
+ }
+
+ private void computeMethodType(ClassNode node, MethodWrapper meth) {
+
+ int type = METHOD_ACCESS_NORMAL;
+
+ if (meth.root != null) {
+
+ DirectGraph graph = meth.getOrBuildGraph();
+
+ int flags = meth.methodStruct.getAccessFlags();
+ if (((flags & CodeConstants.ACC_SYNTHETIC) != 0 || meth.methodStruct.getAttributes().containsKey("Synthetic") || notSetSync) &&
+ (flags & CodeConstants.ACC_STATIC) != 0) {
+ if (graph.nodes.size() == 2) { // incl. dummy exit node
+ if (graph.first.exprents.size() == 1) {
+ Exprent exprent = graph.first.exprents.get(0);
+
+ MethodDescriptor mtdesc = MethodDescriptor.parseDescriptor(meth.methodStruct.getDescriptor());
+ int parcount = mtdesc.params.length;
+
+ Exprent exprCore = exprent;
+
+ if (exprent.type == Exprent.EXPRENT_EXIT) {
+ ExitExprent exexpr = (ExitExprent)exprent;
+ if (exexpr.getExittype() == ExitExprent.EXIT_RETURN && exexpr.getValue() != null) {
+ exprCore = exexpr.getValue();
+ }
+ }
+
+ switch (exprCore.type) {
+ case Exprent.EXPRENT_FIELD:
+ FieldExprent fexpr = (FieldExprent)exprCore;
+ if ((parcount == 1 && !fexpr.isStatic()) ||
+ (parcount == 0 && fexpr.isStatic())) {
+ if (fexpr.getClassname().equals(node.classStruct.qualifiedName)) { // FIXME: check for private flag of the field
+ if (fexpr.isStatic() ||
+ (fexpr.getInstance().type == Exprent.EXPRENT_VAR && ((VarExprent)fexpr.getInstance()).getIndex() == 0)) {
+ type = METHOD_ACCESS_FIELDGET;
+ }
+ }
+ }
+ break;
+ case Exprent.EXPRENT_VAR: // qualified this
+ if (parcount == 1) {
+ // this or final variable
+ if (((VarExprent)exprCore).getIndex() != 0) {
+ type = METHOD_ACCESS_FIELDGET;
+ }
+ }
+
+ break;
+ case Exprent.EXPRENT_INVOCATION:
+ type = METHOD_ACCESS_METHOD;
+ break;
+ case Exprent.EXPRENT_ASSIGNMENT:
+ AssignmentExprent asexpr = (AssignmentExprent)exprCore;
+ if (asexpr.getLeft().type == Exprent.EXPRENT_FIELD && asexpr.getRight().type == Exprent.EXPRENT_VAR) {
+ FieldExprent fexpras = (FieldExprent)asexpr.getLeft();
+ if ((parcount == 2 && !fexpras.isStatic()) ||
+ (parcount == 1 && fexpras.isStatic())) {
+ if (fexpras.getClassname().equals(node.classStruct.qualifiedName)) { // FIXME: check for private flag of the field
+ if (fexpras.isStatic() ||
+ (fexpras.getInstance().type == Exprent.EXPRENT_VAR && ((VarExprent)fexpras.getInstance()).getIndex() == 0)) {
+ if (((VarExprent)asexpr.getRight()).getIndex() == parcount - 1) {
+ type = METHOD_ACCESS_FIELDSET;
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ if (type == METHOD_ACCESS_METHOD) { // FIXME: check for private flag of the method
+
+ type = METHOD_ACCESS_NORMAL;
+
+ InvocationExprent invexpr = (InvocationExprent)exprCore;
+
+ if ((invexpr.isStatic() && invexpr.getLstParameters().size() == parcount) ||
+ (!invexpr.isStatic() && invexpr.getInstance().type == Exprent.EXPRENT_VAR
+ && ((VarExprent)invexpr.getInstance()).getIndex() == 0 && invexpr.getLstParameters().size() == parcount - 1)) {
+
+ boolean equalpars = true;
+
+ for (int i = 0; i < invexpr.getLstParameters().size(); i++) {
+ Exprent parexpr = invexpr.getLstParameters().get(i);
+ if (parexpr.type != Exprent.EXPRENT_VAR ||
+ ((VarExprent)parexpr).getIndex() != i + (invexpr.isStatic() ? 0 : 1)) {
+ equalpars = false;
+ break;
+ }
+ }
+
+ if (equalpars) {
+ type = METHOD_ACCESS_METHOD;
+ }
+ }
+ }
+ }
+ else if (graph.first.exprents.size() == 2) {
+ Exprent exprentFirst = graph.first.exprents.get(0);
+ Exprent exprentSecond = graph.first.exprents.get(1);
+
+ if (exprentFirst.type == Exprent.EXPRENT_ASSIGNMENT &&
+ exprentSecond.type == Exprent.EXPRENT_EXIT) {
+
+ MethodDescriptor mtdesc = MethodDescriptor.parseDescriptor(meth.methodStruct.getDescriptor());
+ int parcount = mtdesc.params.length;
+
+ AssignmentExprent asexpr = (AssignmentExprent)exprentFirst;
+ if (asexpr.getLeft().type == Exprent.EXPRENT_FIELD && asexpr.getRight().type == Exprent.EXPRENT_VAR) {
+ FieldExprent fexpras = (FieldExprent)asexpr.getLeft();
+ if ((parcount == 2 && !fexpras.isStatic()) ||
+ (parcount == 1 && fexpras.isStatic())) {
+ if (fexpras.getClassname().equals(node.classStruct.qualifiedName)) { // FIXME: check for private flag of the field
+ if (fexpras.isStatic() ||
+ (fexpras.getInstance().type == Exprent.EXPRENT_VAR && ((VarExprent)fexpras.getInstance()).getIndex() == 0)) {
+ if (((VarExprent)asexpr.getRight()).getIndex() == parcount - 1) {
+
+ ExitExprent exexpr = (ExitExprent)exprentSecond;
+ if (exexpr.getExittype() == ExitExprent.EXIT_RETURN && exexpr.getValue() != null) {
+ if (exexpr.getValue().type == Exprent.EXPRENT_VAR &&
+ ((VarExprent)asexpr.getRight()).getIndex() == parcount - 1) {
+ type = METHOD_ACCESS_FIELDSET;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (type != METHOD_ACCESS_NORMAL) {
+ mapMethodType.put(meth, type);
+ }
+ else {
+ mapMethodType.remove(meth);
+ }
+ }
+
+
+ private void eliminateStaticAccess(ClassNode node) {
+
+ if (node.type == ClassNode.CLASS_LAMBDA) {
+ return;
+ }
+
+ for (MethodWrapper meth : node.wrapper.getMethods()) {
+
+ if (meth.root != null) {
+
+ boolean replaced = false;
+
+ DirectGraph graph = meth.getOrBuildGraph();
+
+ HashSet<DirectNode> setVisited = new HashSet<DirectNode>();
+ LinkedList<DirectNode> stack = new LinkedList<DirectNode>();
+ stack.add(graph.first);
+
+ while (!stack.isEmpty()) { // TODO: replace with interface iterator?
+
+ DirectNode nd = stack.removeFirst();
+
+ if (setVisited.contains(nd)) {
+ continue;
+ }
+ setVisited.add(nd);
+
+ for (int i = 0; i < nd.exprents.size(); i++) {
+ Exprent exprent = nd.exprents.get(i);
+
+ replaced |= replaceInvocations(node, meth, exprent);
+
+ if (exprent.type == Exprent.EXPRENT_INVOCATION) {
+ Exprent ret = replaceAccessExprent(node, meth, (InvocationExprent)exprent);
+
+ if (ret != null) {
+ nd.exprents.set(i, ret);
+ replaced = true;
+ }
+ }
+ }
+
+ for (DirectNode ndx : nd.succs) {
+ stack.add(ndx);
+ }
+ }
+
+ if (replaced) {
+ computeMethodType(node, meth);
+ }
+ }
+ }
+
+ for (ClassNode child : node.nested) {
+ eliminateStaticAccess(child);
+ }
+ }
+
+
+ private boolean replaceInvocations(ClassNode caller, MethodWrapper meth, Exprent exprent) {
+
+ boolean res = false;
+
+ for (Exprent expr : exprent.getAllExprents()) {
+ res |= replaceInvocations(caller, meth, expr);
+ }
+
+ for (; ; ) {
+
+ boolean found = false;
+
+ for (Exprent expr : exprent.getAllExprents()) {
+ if (expr.type == Exprent.EXPRENT_INVOCATION) {
+ Exprent newexpr = replaceAccessExprent(caller, meth, (InvocationExprent)expr);
+ if (newexpr != null) {
+ exprent.replaceExprent(expr, newexpr);
+ found = true;
+ res = true;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ break;
+ }
+ }
+
+ return res;
+ }
+
+ private boolean sameTree(ClassNode caller, ClassNode callee) {
+
+ if (caller.classStruct.qualifiedName.equals(callee.classStruct.qualifiedName)) {
+ return false;
+ }
+
+ while (caller.parent != null) {
+ caller = caller.parent;
+ }
+
+ while (callee.parent != null) {
+ callee = callee.parent;
+ }
+
+ return caller == callee;
+ }
+
+ private Exprent replaceAccessExprent(ClassNode caller, MethodWrapper methdest, InvocationExprent invexpr) {
+
+ ClassNode node = DecompilerContext.getClassprocessor().getMapRootClasses().get(invexpr.getClassname());
+
+ MethodWrapper methsource = null;
+ if (node != null && node.wrapper != null) {
+ methsource = node.wrapper.getMethodWrapper(invexpr.getName(), invexpr.getStringDescriptor());
+ }
+
+ if (methsource == null || !mapMethodType.containsKey(methsource)) {
+ return null;
+ }
+
+ // if same method, return
+ if (node.classStruct.qualifiedName.equals(caller.classStruct.qualifiedName) &&
+ methsource.methodStruct.getName().equals(methdest.methodStruct.getName()) &&
+ methsource.methodStruct.getDescriptor().equals(methdest.methodStruct.getDescriptor())) {
+ // no recursive invocations permitted!
+ return null;
+ }
+
+ int type = mapMethodType.get(methsource);
+
+ // // FIXME: impossible case. METHOD_ACCESS_NORMAL is not saved in the map
+ // if(type == METHOD_ACCESS_NORMAL) {
+ // return null;
+ // }
+
+ if (!sameTree(caller, node)) {
+ return null;
+ }
+
+ DirectGraph graph = methsource.getOrBuildGraph();
+ Exprent source = graph.first.exprents.get(0);
+
+ Exprent retexprent = null;
+
+ switch (type) {
+ case METHOD_ACCESS_FIELDGET:
+ ExitExprent exsource = (ExitExprent)source;
+ if (exsource.getValue().type == Exprent.EXPRENT_VAR) { // qualified this
+ VarExprent var = (VarExprent)exsource.getValue();
+ String varname = methsource.varproc.getVarName(new VarVersionPaar(var));
+
+ if (!methdest.setOuterVarNames.contains(varname)) {
+ VarNamesCollector vnc = new VarNamesCollector();
+ vnc.addName(varname);
+
+ methdest.varproc.refreshVarNames(vnc);
+ methdest.setOuterVarNames.add(varname);
+ }
+
+ int index = methdest.counter.getCounterAndIncrement(CounterContainer.VAR_COUNTER);
+ VarExprent ret = new VarExprent(index, var.getVartype(), methdest.varproc);
+ methdest.varproc.setVarName(new VarVersionPaar(index, 0), varname);
+
+ retexprent = ret;
+ }
+ else { // field
+ FieldExprent ret = (FieldExprent)exsource.getValue().copy();
+ if (!ret.isStatic()) {
+ ret.replaceExprent(ret.getInstance(), invexpr.getLstParameters().get(0));
+ }
+ retexprent = ret;
+ }
+ break;
+ case METHOD_ACCESS_FIELDSET:
+ AssignmentExprent ret;
+ if (source.type == Exprent.EXPRENT_EXIT) {
+ ExitExprent extex = (ExitExprent)source;
+ ret = (AssignmentExprent)((AssignmentExprent)extex.getValue()).copy();
+ }
+ else {
+ ret = (AssignmentExprent)((AssignmentExprent)source).copy();
+ }
+ FieldExprent fexpr = (FieldExprent)ret.getLeft();
+
+ if (fexpr.isStatic()) {
+ ret.replaceExprent(ret.getRight(), invexpr.getLstParameters().get(0));
+ }
+ else {
+ ret.replaceExprent(ret.getRight(), invexpr.getLstParameters().get(1));
+ fexpr.replaceExprent(fexpr.getInstance(), invexpr.getLstParameters().get(0));
+ }
+ retexprent = ret;
+ break;
+ case METHOD_ACCESS_METHOD:
+ if (source.type == Exprent.EXPRENT_EXIT) {
+ source = ((ExitExprent)source).getValue();
+ }
+
+ InvocationExprent invret = (InvocationExprent)source.copy();
+
+ int index = 0;
+ if (!invret.isStatic()) {
+ invret.replaceExprent(invret.getInstance(), invexpr.getLstParameters().get(0));
+ index = 1;
+ }
+
+ for (int i = 0; i < invret.getLstParameters().size(); i++) {
+ invret.replaceExprent(invret.getLstParameters().get(i), invexpr.getLstParameters().get(i + index));
+ }
+
+ retexprent = invret;
+ }
+
+
+ if (retexprent != null) {
+ // hide synthetic access method
+ boolean hide = true;
+
+ if (node.type == ClassNode.CLASS_ROOT || (node.access & CodeConstants.ACC_STATIC) != 0) {
+ StructMethod mt = methsource.methodStruct;
+ if ((mt.getAccessFlags() & CodeConstants.ACC_SYNTHETIC) == 0 && !mt.getAttributes().containsKey("Synthetic")) {
+ hide = false;
+ }
+ }
+ if (hide) {
+ node.wrapper.getHideMembers().add(InterpreterUtil.makeUniqueKey(invexpr.getName(), invexpr.getStringDescriptor()));
+ }
+ }
+
+ return retexprent;
+ }
}