From 663631f0456fcc245dd835889f86541d75161c53 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Thu, 28 Aug 2014 20:52:43 +0400 Subject: java-decompiler: post-import cleanup (classes moved) --- .../java/decompiler/main/EnumProcessor.java | 159 +++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 src/org/jetbrains/java/decompiler/main/EnumProcessor.java (limited to 'src/org/jetbrains/java/decompiler/main/EnumProcessor.java') diff --git a/src/org/jetbrains/java/decompiler/main/EnumProcessor.java b/src/org/jetbrains/java/decompiler/main/EnumProcessor.java new file mode 100644 index 0000000..7537596 --- /dev/null +++ b/src/org/jetbrains/java/decompiler/main/EnumProcessor.java @@ -0,0 +1,159 @@ +/* + * Fernflower - The Analytical Java Decompiler + * http://www.reversed-java.com + * + * (C) 2008 - 2010, Stiver + * + * This software is NEITHER public domain NOR free software + * as per GNU License. See license.txt for more details. + * + * This software is distributed WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. + */ + +package org.jetbrains.java.decompiler.main; + +import org.jetbrains.java.decompiler.code.CodeConstants; +import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; +import org.jetbrains.java.decompiler.main.rels.ClassWrapper; +import org.jetbrains.java.decompiler.main.rels.MethodWrapper; +import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent; +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.stats.Statement; +import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPaar; +import org.jetbrains.java.decompiler.struct.StructClass; +import org.jetbrains.java.decompiler.struct.StructField; +import org.jetbrains.java.decompiler.struct.StructMethod; +import org.jetbrains.java.decompiler.struct.gen.FieldDescriptor; +import org.jetbrains.java.decompiler.struct.gen.VarType; +import org.jetbrains.java.decompiler.util.InterpreterUtil; + +public class EnumProcessor { + + public static void clearEnum(ClassWrapper wrapper) { + + StructClass cl = wrapper.getClassStruct(); + + // hide values() and valueOf() + for(StructMethod meth : cl.getMethods()) { + + String name = meth.getName(); + int flag = 0; + + if("values".equals(name)) { + flag = 1; + } else if("valueOf".equals(name)) { + flag = 2; + } + + if(flag>0) { + String[] arr = meth.getDescriptor().split("[()]"); + String par = arr[1]; + + if((flag == 1 && par.length() == 0) || + flag == 2 && "Ljava/lang/String;".equals(par)) { + wrapper.getHideMembers().add(InterpreterUtil.makeUniqueKey(name, meth.getDescriptor())); + } + } + } + + // hide all super invocations + for(MethodWrapper meth : wrapper.getMethods()) { + if("".equals(meth.methodStruct.getName())) { + Statement firstdata = findFirstData(meth.root); + if(firstdata == null || firstdata.getExprents().isEmpty()) { + return; + } + + Exprent exprent = firstdata.getExprents().get(0); + if(exprent.type == Exprent.EXPRENT_INVOCATION) { + InvocationExprent invexpr = (InvocationExprent)exprent; + if(isInvocationSuperConstructor(invexpr, meth, wrapper)) { + firstdata.getExprents().remove(0); + } + } + } + } + + // hide dummy synthetic fields of enum constants + for(StructField fd: cl.getFields()) { + if((fd.access_flags & CodeConstants.ACC_ENUM) != 0) { + Exprent initializer = wrapper.getStaticFieldInitializers().getWithKey(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor())); + if(initializer != null && initializer.type == Exprent.EXPRENT_NEW) { + NewExprent nexpr = (NewExprent)initializer; + if(nexpr.isAnonymous()) { + ClassNode child = DecompilerContext.getClassprocessor().getMapRootClasses().get(nexpr.getNewtype().value); + hideDummyFieldInConstant(child.wrapper); + } + } + } + } + + + + } + + private static void hideDummyFieldInConstant(ClassWrapper wrapper) { + + StructClass cl = wrapper.getClassStruct(); + for(StructField fd: cl.getFields()) { + if((fd.access_flags & CodeConstants.ACC_SYNTHETIC) != 0) { + FieldDescriptor descr = FieldDescriptor.parseDescriptor(fd.getDescriptor()); + VarType ret = descr.type; + + if(ret.type == CodeConstants.TYPE_OBJECT && ret.arraydim == 1 && cl.qualifiedName.equals(ret.value)) { + wrapper.getHideMembers().add(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor())); + } + } + } + + } + + // FIXME: move to a util class (see also InitializerProcessor) + private static Statement findFirstData(Statement stat) { + + if(stat.getExprents() != null) { + return stat; + } else { + if(stat.isLabeled()) { + return null; + } + + switch(stat.type) { + case Statement.TYPE_SEQUENCE: + case Statement.TYPE_IF: + case Statement.TYPE_ROOT: + case Statement.TYPE_SWITCH: + case Statement.TYPE_SYNCRONIZED: + return findFirstData(stat.getFirst()); + default: + return null; + } + } + } + + // FIXME: move to util class (see also InitializerProcessor) + private static boolean isInvocationSuperConstructor(InvocationExprent inv, MethodWrapper meth, ClassWrapper wrapper) { + + if(inv.getFunctype() == InvocationExprent.TYP_INIT) { + if(inv.getInstance().type == Exprent.EXPRENT_VAR) { + VarExprent instvar = (VarExprent)inv.getInstance(); + VarVersionPaar varpaar = new VarVersionPaar(instvar); + + String classname = meth.varproc.getThisvars().get(varpaar); + + if(classname!=null) { // any this instance. TODO: Restrict to current class? + if(!wrapper.getClassStruct().qualifiedName.equals(inv.getClassname())) { + return true; + } + } + } + } + + return false; + } + +} -- cgit v1.2.3