java-decompiler: post-import cleanup (formatting and copyright)
This commit is contained in:
@@ -1,39 +1,26 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.jetbrains.java.decompiler.code.CodeConstants;
|
||||
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
|
||||
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
|
||||
import org.jetbrains.java.decompiler.main.rels.ClassWrapper;
|
||||
import org.jetbrains.java.decompiler.main.rels.MethodWrapper;
|
||||
import org.jetbrains.java.decompiler.modules.decompiler.exps.AssignmentExprent;
|
||||
import org.jetbrains.java.decompiler.modules.decompiler.exps.ConstExprent;
|
||||
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.FunctionExprent;
|
||||
import org.jetbrains.java.decompiler.modules.decompiler.exps.InvocationExprent;
|
||||
import org.jetbrains.java.decompiler.modules.decompiler.exps.NewExprent;
|
||||
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.stats.BasicBlockStatement;
|
||||
import org.jetbrains.java.decompiler.modules.decompiler.stats.CatchStatement;
|
||||
@@ -46,264 +33,272 @@ import org.jetbrains.java.decompiler.struct.gen.VarType;
|
||||
import org.jetbrains.java.decompiler.util.InterpreterUtil;
|
||||
import org.jetbrains.java.decompiler.util.VBStyleCollection;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class ClassReference14Processor {
|
||||
|
||||
public ExitExprent bodyexprent;
|
||||
|
||||
public ExitExprent handlerexprent;
|
||||
|
||||
|
||||
public ClassReference14Processor() {
|
||||
|
||||
InvocationExprent invfor = new InvocationExprent();
|
||||
invfor.setName("forName");
|
||||
invfor.setClassname("java/lang/Class");
|
||||
invfor.setStringDescriptor("(Ljava/lang/String;)Ljava/lang/Class;");
|
||||
invfor.setDescriptor(MethodDescriptor.parseDescriptor("(Ljava/lang/String;)Ljava/lang/Class;"));
|
||||
invfor.setStatic(true);
|
||||
invfor.setLstParameters(Arrays.asList(new Exprent[] {new VarExprent(0, VarType.VARTYPE_STRING, null)}));
|
||||
|
||||
bodyexprent = new ExitExprent(ExitExprent.EXIT_RETURN,
|
||||
invfor,
|
||||
VarType.VARTYPE_CLASS);
|
||||
public ExitExprent bodyexprent;
|
||||
|
||||
InvocationExprent constr = new InvocationExprent();
|
||||
constr.setName("<init>");
|
||||
constr.setClassname("java/lang/NoClassDefFoundError");
|
||||
constr.setStringDescriptor("()V");
|
||||
constr.setFunctype(InvocationExprent.TYP_INIT);
|
||||
constr.setDescriptor(MethodDescriptor.parseDescriptor("()V"));
|
||||
|
||||
NewExprent newexpr = new NewExprent(new VarType(CodeConstants.TYPE_OBJECT,0,"java/lang/NoClassDefFoundError"), new ArrayList<Exprent>());
|
||||
newexpr.setConstructor(constr);
|
||||
|
||||
InvocationExprent invcause = new InvocationExprent();
|
||||
invcause.setName("initCause");
|
||||
invcause.setClassname("java/lang/NoClassDefFoundError");
|
||||
invcause.setStringDescriptor("(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
|
||||
invcause.setDescriptor(MethodDescriptor.parseDescriptor("(Ljava/lang/Throwable;)Ljava/lang/Throwable;"));
|
||||
invcause.setInstance(newexpr);
|
||||
invcause.setLstParameters(Arrays.asList(new Exprent[] {new VarExprent(2, new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/ClassNotFoundException"), null)}));
|
||||
|
||||
handlerexprent = new ExitExprent(ExitExprent.EXIT_THROW,
|
||||
invcause,
|
||||
null);
|
||||
}
|
||||
|
||||
|
||||
public void processClassReferences(ClassNode node) {
|
||||
|
||||
ClassWrapper wrapper = node.wrapper;
|
||||
|
||||
// int major_version = wrapper.getClassStruct().major_version;
|
||||
// int minor_version = wrapper.getClassStruct().minor_version;
|
||||
//
|
||||
// if(major_version > 48 || (major_version == 48 && minor_version > 0)) {
|
||||
// // version 1.5 or above
|
||||
// return;
|
||||
// }
|
||||
public ExitExprent handlerexprent;
|
||||
|
||||
if(wrapper.getClassStruct().isVersionGE_1_5()) {
|
||||
// version 1.5 or above
|
||||
return;
|
||||
}
|
||||
|
||||
// find the synthetic method Class class$(String) if present
|
||||
HashMap<ClassWrapper, MethodWrapper> mapClassMeths = new HashMap<ClassWrapper, MethodWrapper>();
|
||||
findClassMethod(node, mapClassMeths);
|
||||
|
||||
if(mapClassMeths.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
HashSet<ClassWrapper> setFound = new HashSet<ClassWrapper>();
|
||||
processClassRec(node, mapClassMeths, setFound);
|
||||
|
||||
if(!setFound.isEmpty()) {
|
||||
for(ClassWrapper wrp : setFound) {
|
||||
StructMethod mt = mapClassMeths.get(wrp).methodStruct;
|
||||
wrp.getHideMembers().add(InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void processClassRec(ClassNode node, final HashMap<ClassWrapper, MethodWrapper> mapClassMeths, final HashSet<ClassWrapper> setFound) {
|
||||
|
||||
final ClassWrapper wrapper = node.wrapper;
|
||||
|
||||
// search code
|
||||
for(MethodWrapper meth : wrapper.getMethods()) {
|
||||
public ClassReference14Processor() {
|
||||
|
||||
RootStatement root = meth.root;
|
||||
if(root != null) {
|
||||
InvocationExprent invfor = new InvocationExprent();
|
||||
invfor.setName("forName");
|
||||
invfor.setClassname("java/lang/Class");
|
||||
invfor.setStringDescriptor("(Ljava/lang/String;)Ljava/lang/Class;");
|
||||
invfor.setDescriptor(MethodDescriptor.parseDescriptor("(Ljava/lang/String;)Ljava/lang/Class;"));
|
||||
invfor.setStatic(true);
|
||||
invfor.setLstParameters(Arrays.asList(new Exprent[]{new VarExprent(0, VarType.VARTYPE_STRING, null)}));
|
||||
|
||||
DirectGraph graph = meth.getOrBuildGraph();
|
||||
bodyexprent = new ExitExprent(ExitExprent.EXIT_RETURN,
|
||||
invfor,
|
||||
VarType.VARTYPE_CLASS);
|
||||
|
||||
graph.iterateExprents(new DirectGraph.ExprentIterator() {
|
||||
public int processExprent(Exprent exprent) {
|
||||
for(Entry<ClassWrapper, MethodWrapper> ent : mapClassMeths.entrySet()) {
|
||||
if(replaceInvocations(exprent, ent.getKey(), ent.getValue())) {
|
||||
setFound.add(ent.getKey());
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// search initializers
|
||||
for(int j=0;j<2;j++) {
|
||||
VBStyleCollection<Exprent, String> initializers = j==0?wrapper.getStaticFieldInitializers():wrapper.getDynamicFieldInitializers();
|
||||
|
||||
for(int i=0; i<initializers.size();i++) {
|
||||
for(Entry<ClassWrapper, MethodWrapper> ent : mapClassMeths.entrySet()) {
|
||||
Exprent exprent = initializers.get(i);
|
||||
if(replaceInvocations(exprent, ent.getKey(), ent.getValue())) {
|
||||
setFound.add(ent.getKey());
|
||||
}
|
||||
|
||||
String cl = isClass14Invocation(exprent, ent.getKey(), ent.getValue());
|
||||
if(cl != null) {
|
||||
initializers.set(i, new ConstExprent(VarType.VARTYPE_CLASS, cl.replace('.', '/')));
|
||||
setFound.add(ent.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
InvocationExprent constr = new InvocationExprent();
|
||||
constr.setName("<init>");
|
||||
constr.setClassname("java/lang/NoClassDefFoundError");
|
||||
constr.setStringDescriptor("()V");
|
||||
constr.setFunctype(InvocationExprent.TYP_INIT);
|
||||
constr.setDescriptor(MethodDescriptor.parseDescriptor("()V"));
|
||||
|
||||
// iterate nested classes
|
||||
for(ClassNode nd : node.nested) {
|
||||
processClassRec(nd, mapClassMeths, setFound);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void findClassMethod(ClassNode node, HashMap<ClassWrapper, MethodWrapper> mapClassMeths) {
|
||||
|
||||
boolean nosynthflag = DecompilerContext.getOption(IFernflowerPreferences.SYNTHETIC_NOT_SET);
|
||||
|
||||
ClassWrapper wrapper = node.wrapper;
|
||||
|
||||
for(MethodWrapper meth : wrapper.getMethods()) {
|
||||
StructMethod mt = meth.methodStruct;
|
||||
|
||||
if(((mt.getAccessFlags() & CodeConstants.ACC_SYNTHETIC) != 0 || mt.getAttributes().containsKey("Synthetic")
|
||||
|| nosynthflag) &&
|
||||
mt.getDescriptor().equals("(Ljava/lang/String;)Ljava/lang/Class;") &&
|
||||
(mt.getAccessFlags() & CodeConstants.ACC_STATIC) != 0) {
|
||||
|
||||
RootStatement root = meth.root;
|
||||
if(root != null) {
|
||||
if(root.getFirst().type == Statement.TYPE_TRYCATCH) {
|
||||
CatchStatement cst = (CatchStatement)root.getFirst();
|
||||
if(cst.getStats().size() == 2 && cst.getFirst().type == Statement.TYPE_BASICBLOCK &&
|
||||
cst.getStats().get(1).type == Statement.TYPE_BASICBLOCK &&
|
||||
cst.getVars().get(0).getVartype().equals(new VarType(CodeConstants.TYPE_OBJECT,0,"java/lang/ClassNotFoundException"))) {
|
||||
|
||||
BasicBlockStatement body = (BasicBlockStatement)cst.getFirst();
|
||||
BasicBlockStatement handler = (BasicBlockStatement)cst.getStats().get(1);
|
||||
|
||||
if(body.getExprents().size() == 1 && handler.getExprents().size() == 1) {
|
||||
if(bodyexprent.equals(body.getExprents().get(0)) &&
|
||||
handlerexprent.equals(handler.getExprents().get(0))) {
|
||||
mapClassMeths.put(wrapper, meth);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// iterate nested classes
|
||||
for(ClassNode nd : node.nested) {
|
||||
findClassMethod(nd, mapClassMeths);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private boolean replaceInvocations(Exprent exprent, ClassWrapper wrapper, MethodWrapper meth) {
|
||||
|
||||
boolean res = false;
|
||||
|
||||
for(;;) {
|
||||
NewExprent newexpr =
|
||||
new NewExprent(new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/NoClassDefFoundError"), new ArrayList<Exprent>());
|
||||
newexpr.setConstructor(constr);
|
||||
|
||||
boolean found = false;
|
||||
|
||||
for(Exprent expr : exprent.getAllExprents()) {
|
||||
String cl = isClass14Invocation(expr, wrapper, meth);
|
||||
if(cl != null) {
|
||||
exprent.replaceExprent(expr, new ConstExprent(VarType.VARTYPE_CLASS, cl.replace('.', '/')));
|
||||
found = true;
|
||||
res = true;
|
||||
break;
|
||||
}
|
||||
|
||||
res |= replaceInvocations(expr, wrapper, meth);
|
||||
}
|
||||
|
||||
if(!found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private String isClass14Invocation(Exprent exprent, ClassWrapper wrapper, MethodWrapper meth) {
|
||||
|
||||
if(exprent.type == Exprent.EXPRENT_FUNCTION) {
|
||||
FunctionExprent fexpr = (FunctionExprent)exprent;
|
||||
if(fexpr.getFunctype() == FunctionExprent.FUNCTION_IIF) {
|
||||
if(fexpr.getLstOperands().get(0).type == Exprent.EXPRENT_FUNCTION) {
|
||||
FunctionExprent headexpr = (FunctionExprent)fexpr.getLstOperands().get(0);
|
||||
if(headexpr.getFunctype() == FunctionExprent.FUNCTION_EQ) {
|
||||
if(headexpr.getLstOperands().get(0).type == Exprent.EXPRENT_FIELD &&
|
||||
headexpr.getLstOperands().get(1).type == Exprent.EXPRENT_CONST &&
|
||||
((ConstExprent)headexpr.getLstOperands().get(1)).getConsttype().equals(VarType.VARTYPE_NULL)) {
|
||||
InvocationExprent invcause = new InvocationExprent();
|
||||
invcause.setName("initCause");
|
||||
invcause.setClassname("java/lang/NoClassDefFoundError");
|
||||
invcause.setStringDescriptor("(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
|
||||
invcause.setDescriptor(MethodDescriptor.parseDescriptor("(Ljava/lang/Throwable;)Ljava/lang/Throwable;"));
|
||||
invcause.setInstance(newexpr);
|
||||
invcause.setLstParameters(
|
||||
Arrays.asList(new Exprent[]{new VarExprent(2, new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/ClassNotFoundException"), null)}));
|
||||
|
||||
FieldExprent field = (FieldExprent)headexpr.getLstOperands().get(0);
|
||||
ClassNode fieldnode = DecompilerContext.getClassprocessor().getMapRootClasses().get(field.getClassname());
|
||||
|
||||
if(fieldnode != null && fieldnode.classStruct.qualifiedName.equals(wrapper.getClassStruct().qualifiedName)) { // source class
|
||||
StructField fd = wrapper.getClassStruct().getField(field.getName(), field.getDescriptor().descriptorString); // FIXME: can be null! why??
|
||||
|
||||
if(fd != null && (fd.access_flags & CodeConstants.ACC_STATIC) != 0 &&
|
||||
((fd.access_flags & CodeConstants.ACC_SYNTHETIC) != 0 || fd.getAttributes().containsKey("Synthetic")
|
||||
|| DecompilerContext.getOption(IFernflowerPreferences.SYNTHETIC_NOT_SET))) {
|
||||
|
||||
if(fexpr.getLstOperands().get(1).type == Exprent.EXPRENT_ASSIGNMENT && fexpr.getLstOperands().get(2).equals(field)) {
|
||||
AssignmentExprent asexpr = (AssignmentExprent)fexpr.getLstOperands().get(1);
|
||||
|
||||
if(asexpr.getLeft().equals(field) && asexpr.getRight().type == Exprent.EXPRENT_INVOCATION) {
|
||||
InvocationExprent invexpr = (InvocationExprent)asexpr.getRight();
|
||||
|
||||
if(invexpr.getClassname().equals(wrapper.getClassStruct().qualifiedName) &&
|
||||
invexpr.getName().equals(meth.methodStruct.getName()) &&
|
||||
invexpr.getStringDescriptor().equals(meth.methodStruct.getDescriptor())) {
|
||||
|
||||
if(invexpr.getLstParameters().get(0).type == Exprent.EXPRENT_CONST) {
|
||||
wrapper.getHideMembers().add(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor())); // hide synthetic field
|
||||
return ((ConstExprent)invexpr.getLstParameters().get(0)).getValue().toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
handlerexprent = new ExitExprent(ExitExprent.EXIT_THROW,
|
||||
invcause,
|
||||
null);
|
||||
}
|
||||
|
||||
|
||||
public void processClassReferences(ClassNode node) {
|
||||
|
||||
ClassWrapper wrapper = node.wrapper;
|
||||
|
||||
// int major_version = wrapper.getClassStruct().major_version;
|
||||
// int minor_version = wrapper.getClassStruct().minor_version;
|
||||
//
|
||||
// if(major_version > 48 || (major_version == 48 && minor_version > 0)) {
|
||||
// // version 1.5 or above
|
||||
// return;
|
||||
// }
|
||||
|
||||
if (wrapper.getClassStruct().isVersionGE_1_5()) {
|
||||
// version 1.5 or above
|
||||
return;
|
||||
}
|
||||
|
||||
// find the synthetic method Class class$(String) if present
|
||||
HashMap<ClassWrapper, MethodWrapper> mapClassMeths = new HashMap<ClassWrapper, MethodWrapper>();
|
||||
findClassMethod(node, mapClassMeths);
|
||||
|
||||
if (mapClassMeths.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
HashSet<ClassWrapper> setFound = new HashSet<ClassWrapper>();
|
||||
processClassRec(node, mapClassMeths, setFound);
|
||||
|
||||
if (!setFound.isEmpty()) {
|
||||
for (ClassWrapper wrp : setFound) {
|
||||
StructMethod mt = mapClassMeths.get(wrp).methodStruct;
|
||||
wrp.getHideMembers().add(InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processClassRec(ClassNode node,
|
||||
final HashMap<ClassWrapper, MethodWrapper> mapClassMeths,
|
||||
final HashSet<ClassWrapper> setFound) {
|
||||
|
||||
final ClassWrapper wrapper = node.wrapper;
|
||||
|
||||
// search code
|
||||
for (MethodWrapper meth : wrapper.getMethods()) {
|
||||
|
||||
RootStatement root = meth.root;
|
||||
if (root != null) {
|
||||
|
||||
DirectGraph graph = meth.getOrBuildGraph();
|
||||
|
||||
graph.iterateExprents(new DirectGraph.ExprentIterator() {
|
||||
public int processExprent(Exprent exprent) {
|
||||
for (Entry<ClassWrapper, MethodWrapper> ent : mapClassMeths.entrySet()) {
|
||||
if (replaceInvocations(exprent, ent.getKey(), ent.getValue())) {
|
||||
setFound.add(ent.getKey());
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// search initializers
|
||||
for (int j = 0; j < 2; j++) {
|
||||
VBStyleCollection<Exprent, String> initializers =
|
||||
j == 0 ? wrapper.getStaticFieldInitializers() : wrapper.getDynamicFieldInitializers();
|
||||
|
||||
for (int i = 0; i < initializers.size(); i++) {
|
||||
for (Entry<ClassWrapper, MethodWrapper> ent : mapClassMeths.entrySet()) {
|
||||
Exprent exprent = initializers.get(i);
|
||||
if (replaceInvocations(exprent, ent.getKey(), ent.getValue())) {
|
||||
setFound.add(ent.getKey());
|
||||
}
|
||||
|
||||
String cl = isClass14Invocation(exprent, ent.getKey(), ent.getValue());
|
||||
if (cl != null) {
|
||||
initializers.set(i, new ConstExprent(VarType.VARTYPE_CLASS, cl.replace('.', '/')));
|
||||
setFound.add(ent.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// iterate nested classes
|
||||
for (ClassNode nd : node.nested) {
|
||||
processClassRec(nd, mapClassMeths, setFound);
|
||||
}
|
||||
}
|
||||
|
||||
private void findClassMethod(ClassNode node, HashMap<ClassWrapper, MethodWrapper> mapClassMeths) {
|
||||
|
||||
boolean nosynthflag = DecompilerContext.getOption(IFernflowerPreferences.SYNTHETIC_NOT_SET);
|
||||
|
||||
ClassWrapper wrapper = node.wrapper;
|
||||
|
||||
for (MethodWrapper meth : wrapper.getMethods()) {
|
||||
StructMethod mt = meth.methodStruct;
|
||||
|
||||
if (((mt.getAccessFlags() & CodeConstants.ACC_SYNTHETIC) != 0 || mt.getAttributes().containsKey("Synthetic")
|
||||
|| nosynthflag) &&
|
||||
mt.getDescriptor().equals("(Ljava/lang/String;)Ljava/lang/Class;") &&
|
||||
(mt.getAccessFlags() & CodeConstants.ACC_STATIC) != 0) {
|
||||
|
||||
RootStatement root = meth.root;
|
||||
if (root != null) {
|
||||
if (root.getFirst().type == Statement.TYPE_TRYCATCH) {
|
||||
CatchStatement cst = (CatchStatement)root.getFirst();
|
||||
if (cst.getStats().size() == 2 && cst.getFirst().type == Statement.TYPE_BASICBLOCK &&
|
||||
cst.getStats().get(1).type == Statement.TYPE_BASICBLOCK &&
|
||||
cst.getVars().get(0).getVartype().equals(new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/ClassNotFoundException"))) {
|
||||
|
||||
BasicBlockStatement body = (BasicBlockStatement)cst.getFirst();
|
||||
BasicBlockStatement handler = (BasicBlockStatement)cst.getStats().get(1);
|
||||
|
||||
if (body.getExprents().size() == 1 && handler.getExprents().size() == 1) {
|
||||
if (bodyexprent.equals(body.getExprents().get(0)) &&
|
||||
handlerexprent.equals(handler.getExprents().get(0))) {
|
||||
mapClassMeths.put(wrapper, meth);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// iterate nested classes
|
||||
for (ClassNode nd : node.nested) {
|
||||
findClassMethod(nd, mapClassMeths);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean replaceInvocations(Exprent exprent, ClassWrapper wrapper, MethodWrapper meth) {
|
||||
|
||||
boolean res = false;
|
||||
|
||||
for (; ; ) {
|
||||
|
||||
boolean found = false;
|
||||
|
||||
for (Exprent expr : exprent.getAllExprents()) {
|
||||
String cl = isClass14Invocation(expr, wrapper, meth);
|
||||
if (cl != null) {
|
||||
exprent.replaceExprent(expr, new ConstExprent(VarType.VARTYPE_CLASS, cl.replace('.', '/')));
|
||||
found = true;
|
||||
res = true;
|
||||
break;
|
||||
}
|
||||
|
||||
res |= replaceInvocations(expr, wrapper, meth);
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
private String isClass14Invocation(Exprent exprent, ClassWrapper wrapper, MethodWrapper meth) {
|
||||
|
||||
if (exprent.type == Exprent.EXPRENT_FUNCTION) {
|
||||
FunctionExprent fexpr = (FunctionExprent)exprent;
|
||||
if (fexpr.getFunctype() == FunctionExprent.FUNCTION_IIF) {
|
||||
if (fexpr.getLstOperands().get(0).type == Exprent.EXPRENT_FUNCTION) {
|
||||
FunctionExprent headexpr = (FunctionExprent)fexpr.getLstOperands().get(0);
|
||||
if (headexpr.getFunctype() == FunctionExprent.FUNCTION_EQ) {
|
||||
if (headexpr.getLstOperands().get(0).type == Exprent.EXPRENT_FIELD &&
|
||||
headexpr.getLstOperands().get(1).type == Exprent.EXPRENT_CONST &&
|
||||
((ConstExprent)headexpr.getLstOperands().get(1)).getConsttype().equals(VarType.VARTYPE_NULL)) {
|
||||
|
||||
FieldExprent field = (FieldExprent)headexpr.getLstOperands().get(0);
|
||||
ClassNode fieldnode = DecompilerContext.getClassprocessor().getMapRootClasses().get(field.getClassname());
|
||||
|
||||
if (fieldnode != null && fieldnode.classStruct.qualifiedName.equals(wrapper.getClassStruct().qualifiedName)) { // source class
|
||||
StructField fd =
|
||||
wrapper.getClassStruct().getField(field.getName(), field.getDescriptor().descriptorString); // FIXME: can be null! why??
|
||||
|
||||
if (fd != null && (fd.access_flags & CodeConstants.ACC_STATIC) != 0 &&
|
||||
((fd.access_flags & CodeConstants.ACC_SYNTHETIC) != 0 || fd.getAttributes().containsKey("Synthetic")
|
||||
|| DecompilerContext.getOption(IFernflowerPreferences.SYNTHETIC_NOT_SET))) {
|
||||
|
||||
if (fexpr.getLstOperands().get(1).type == Exprent.EXPRENT_ASSIGNMENT && fexpr.getLstOperands().get(2).equals(field)) {
|
||||
AssignmentExprent asexpr = (AssignmentExprent)fexpr.getLstOperands().get(1);
|
||||
|
||||
if (asexpr.getLeft().equals(field) && asexpr.getRight().type == Exprent.EXPRENT_INVOCATION) {
|
||||
InvocationExprent invexpr = (InvocationExprent)asexpr.getRight();
|
||||
|
||||
if (invexpr.getClassname().equals(wrapper.getClassStruct().qualifiedName) &&
|
||||
invexpr.getName().equals(meth.methodStruct.getName()) &&
|
||||
invexpr.getStringDescriptor().equals(meth.methodStruct.getDescriptor())) {
|
||||
|
||||
if (invexpr.getLstParameters().get(0).type == Exprent.EXPRENT_CONST) {
|
||||
wrapper.getHideMembers()
|
||||
.add(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor())); // hide synthetic field
|
||||
return ((ConstExprent)invexpr.getLstParameters().get(0)).getValue().toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user