001: package soot.dava.toolkits.base.AST.transformations;
002:
003: import java.util.ArrayList;
004: import java.util.Iterator;
005: import java.util.List;
006:
007: import soot.Body;
008: import soot.SootClass;
009: import soot.SootMethod;
010: import soot.dava.DavaBody;
011: import soot.dava.internal.AST.ASTMethodNode;
012: import soot.dava.internal.AST.ASTNode;
013: import soot.util.Chain;
014:
015: /*
016: * It has been seen that Dava's output contains the default constructor with just the invocation
017: * to super()
018: *
019: * According to the java specs the default constructor is not needed unless the constructor has been
020: * overloaded.
021: *
022: * The analysis checks whether there is only one constructor in the class being decompiled.
023: * If this is true and the constructor IS THE DEFAULT CONSTRUCTOR i.e. no arguments
024: * and has an empty body (there will always be a call to super
025: * but that is invoked automatically....) we can remove the constructor from the code
026: * also check tht the call to super has no arguments i.e. default super
027: */
028: public class RemoveEmptyBodyDefaultConstructor {
029: public static boolean DEBUG = false;
030:
031: public static void checkAndRemoveDefault(SootClass s) {
032: debug("\n\nRemoveEmptyBodyDefaultConstructor----" + s.getName());
033: List methods = s.getMethods();
034: Iterator it = methods.iterator();
035: List<SootMethod> constructors = new ArrayList<SootMethod>();
036:
037: while (it.hasNext()) {
038: SootMethod method = (SootMethod) it.next();
039: debug("method name is" + method.getName());
040: if (method.getName().indexOf("<init>") > -1) {
041: //constructor add to constructor list
042: constructors.add(method);
043: }
044: }
045:
046: if (constructors.size() != 1) {
047: //cant do anything since there are more than one constructors
048: debug("class has more than one constructors cant do anything");
049: return;
050: }
051:
052: //only one constructor check its default (no arguments)
053: SootMethod constructor = constructors.get(0);
054: if (constructor.getParameterCount() != 0) {
055: //can only deal with default constructors
056: debug("constructor is not the default constructor");
057: return;
058: }
059:
060: debug("Check that the body is empty....and call to super contains no arguments and delete");
061:
062: if (!constructor.hasActiveBody()) {
063: debug("No active body found for the default constructor");
064: return;
065: }
066:
067: Body body = constructor.getActiveBody();
068: Chain units = ((DavaBody) body).getUnits();
069:
070: if (units.size() != 1) {
071: debug(" DavaBody AST does not have single root");
072: return;
073: }
074:
075: ASTNode AST = (ASTNode) units.getFirst();
076: if (!(AST instanceof ASTMethodNode))
077: throw new RuntimeException(
078: "Starting node of DavaBody AST is not an ASTMethodNode");
079:
080: ASTMethodNode methodNode = (ASTMethodNode) AST;
081: debug("got methodnode check body is empty and super has nothing in it");
082:
083: List<Object> subBodies = methodNode.get_SubBodies();
084: if (subBodies.size() != 1) {
085: debug("Method node does not have one subBody!!!");
086: return;
087: }
088:
089: List methodBody = (List) subBodies.get(0);
090: if (methodBody.size() != 0) {
091: debug("Method body size is greater than 1 so cant do nothing");
092: return;
093: }
094:
095: debug("Method body is empty...check super call is empty");
096:
097: if (((DavaBody) body).get_ConstructorExpr().getArgCount() != 0) {
098: debug("call to super not empty");
099: return;
100: }
101:
102: debug("REMOVE METHOD");
103: s.removeMethod(constructor);
104: }
105:
106: public static void debug(String debug) {
107: if (DEBUG)
108: System.out.println("DEBUG: " + debug);
109: }
110:
111: }
|