|
|
|
@ -26,12 +26,13 @@ import jode.bytecode.MethodInfo; |
|
|
|
|
import jode.bytecode.InnerClassInfo; |
|
|
|
|
import jode.bytecode.ConstantPool; |
|
|
|
|
import jode.expr.Expression; |
|
|
|
|
import jode.expr.ThisOperator; |
|
|
|
|
import jode.expr.ConstructorOperator; |
|
|
|
|
import jode.flow.TransformConstructors; |
|
|
|
|
import java.util.NoSuchElementException; |
|
|
|
|
import java.lang.reflect.Modifier; |
|
|
|
|
|
|
|
|
|
public class ClassAnalyzer implements Analyzer, Scope { |
|
|
|
|
public class ClassAnalyzer implements Analyzer, Scope, Declarable { |
|
|
|
|
ImportHandler imports; |
|
|
|
|
ClassInfo clazz; |
|
|
|
|
Object parent; |
|
|
|
@ -45,20 +46,23 @@ public class ClassAnalyzer implements Analyzer, Scope { |
|
|
|
|
MethodAnalyzer staticConstructor; |
|
|
|
|
MethodAnalyzer[] constructors; |
|
|
|
|
|
|
|
|
|
Expression[] outerValues; |
|
|
|
|
|
|
|
|
|
public ClassAnalyzer(Object parent, |
|
|
|
|
ClassInfo clazz, ImportHandler imports) |
|
|
|
|
ClassInfo clazz, ImportHandler imports, |
|
|
|
|
Expression[] outerValues) |
|
|
|
|
{ |
|
|
|
|
clazz.loadInfo(clazz.FULLINFO); |
|
|
|
|
this.parent = parent; |
|
|
|
|
this.clazz = clazz; |
|
|
|
|
this.imports = imports; |
|
|
|
|
this.outerValues = outerValues; |
|
|
|
|
modifiers = clazz.getModifiers(); |
|
|
|
|
name = clazz.getName(); |
|
|
|
|
|
|
|
|
|
if (parent != null) { |
|
|
|
|
InnerClassInfo[] outerInfos = clazz.getOuterClasses(); |
|
|
|
|
if (outerInfos[0].outer == null) { |
|
|
|
|
if (outerInfos[0].outer == null || outerInfos[0].name == null) { |
|
|
|
|
if (parent instanceof ClassAnalyzer) |
|
|
|
|
throw new jode.AssertError |
|
|
|
|
("ClassInfo Attributes are inconsistent: " |
|
|
|
@ -82,6 +86,12 @@ public class ClassAnalyzer implements Analyzer, Scope { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public ClassAnalyzer(Object parent, |
|
|
|
|
ClassInfo clazz, ImportHandler imports) |
|
|
|
|
{ |
|
|
|
|
this(parent, clazz, imports, null); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public ClassAnalyzer(ClassInfo clazz, ImportHandler imports) |
|
|
|
|
{ |
|
|
|
|
this(null, clazz, imports); |
|
|
|
@ -118,6 +128,10 @@ public class ClassAnalyzer implements Analyzer, Scope { |
|
|
|
|
return clazz; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public Expression[] getOuterValues() { |
|
|
|
|
return outerValues; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void analyze() { |
|
|
|
|
FieldInfo[] finfos = clazz.getFields(); |
|
|
|
|
MethodInfo[] minfos = clazz.getMethods(); |
|
|
|
@ -132,11 +146,18 @@ public class ClassAnalyzer implements Analyzer, Scope { |
|
|
|
|
|
|
|
|
|
if ((Decompiler.options & Decompiler.OPTION_INNER) != 0 |
|
|
|
|
&& innerInfos != null) { |
|
|
|
|
Expression[] outerThis = new Expression[] { |
|
|
|
|
new ThisOperator(clazz) |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
int innerCount = innerInfos.length; |
|
|
|
|
inners = new ClassAnalyzer[innerCount]; |
|
|
|
|
for (int i=0; i < innerCount; i++) { |
|
|
|
|
ClassInfo ci = ClassInfo.forName(innerInfos[i].inner); |
|
|
|
|
inners[i] = new ClassAnalyzer |
|
|
|
|
(this, ClassInfo.forName(innerInfos[i].inner), imports); |
|
|
|
|
(this, ci, imports, |
|
|
|
|
Modifier.isStatic(innerInfos[i].modifiers) |
|
|
|
|
? null : outerThis); |
|
|
|
|
} |
|
|
|
|
} else |
|
|
|
|
inners = new ClassAnalyzer[0]; |
|
|
|
@ -164,30 +185,33 @@ public class ClassAnalyzer implements Analyzer, Scope { |
|
|
|
|
|
|
|
|
|
// now analyze constructors:
|
|
|
|
|
constructors = new MethodAnalyzer[constrVector.size()]; |
|
|
|
|
if (constructors.length > 0) { |
|
|
|
|
if (constructors.length > 0) { |
|
|
|
|
constrVector.copyInto(constructors); |
|
|
|
|
for (int j=0; j< constructors.length; j++) |
|
|
|
|
constructors[j].analyze(); |
|
|
|
|
TransformConstructors.transform |
|
|
|
|
(this, false, parent instanceof ClassAnalyzer, |
|
|
|
|
parent instanceof ConstructorOperator, constructors); |
|
|
|
|
|
|
|
|
|
TransformConstructors.transform(this, false, constructors); |
|
|
|
|
} |
|
|
|
|
if (staticConstructor != null) { |
|
|
|
|
staticConstructor.analyze(); |
|
|
|
|
TransformConstructors.transform(this, true, false, false, |
|
|
|
|
new MethodAnalyzer[] |
|
|
|
|
{ staticConstructor }); |
|
|
|
|
TransformConstructors.transform |
|
|
|
|
(this, true, new MethodAnalyzer[] { staticConstructor }); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Now analyze remaining methods.
|
|
|
|
|
for (int j=0; j < methods.length; j++) { |
|
|
|
|
if (!methods[j].isConstructor()) |
|
|
|
|
if (!methods[j].isConstructor() |
|
|
|
|
&& !methods[j].isJikesConstructor) |
|
|
|
|
methods[j].analyze(); |
|
|
|
|
} |
|
|
|
|
// Now analyze the inner classes.
|
|
|
|
|
for (int j=0; j < inners.length; j++) |
|
|
|
|
inners[j].analyze(); |
|
|
|
|
|
|
|
|
|
// Now analyze the method scoped classes.
|
|
|
|
|
for (int j=0; j < methods.length; j++) |
|
|
|
|
methods[j].analyzeAnonymousClasses(); |
|
|
|
|
|
|
|
|
|
imports.useClass(clazz); |
|
|
|
|
if (clazz.getSuperclass() != null) |
|
|
|
|
imports.useClass(clazz.getSuperclass()); |
|
|
|
@ -204,6 +228,36 @@ public class ClassAnalyzer implements Analyzer, Scope { |
|
|
|
|
this.name = name; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void dumpDeclaration(TabbedPrintWriter writer) |
|
|
|
|
throws java.io.IOException |
|
|
|
|
{ |
|
|
|
|
dumpSource(writer); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void dumpBlock(TabbedPrintWriter writer) throws java.io.IOException |
|
|
|
|
{ |
|
|
|
|
boolean needNewLine = false; |
|
|
|
|
for (int i=0; i< fields.length; i++) { |
|
|
|
|
if (fields[i].skipWriting()) |
|
|
|
|
continue; |
|
|
|
|
fields[i].dumpSource(writer); |
|
|
|
|
needNewLine = true; |
|
|
|
|
} |
|
|
|
|
for (int i=0; i< inners.length; i++) { |
|
|
|
|
if (needNewLine) |
|
|
|
|
writer.println(""); |
|
|
|
|
inners[i].dumpSource(writer); |
|
|
|
|
} |
|
|
|
|
for (int i=0; i< methods.length; i++) { |
|
|
|
|
if (methods[i].skipWriting()) |
|
|
|
|
continue; |
|
|
|
|
if (needNewLine) |
|
|
|
|
writer.println(""); |
|
|
|
|
methods[i].dumpSource(writer); |
|
|
|
|
needNewLine = true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void dumpSource(TabbedPrintWriter writer) throws java.io.IOException |
|
|
|
|
{ |
|
|
|
|
if (fields == null) { |
|
|
|
@ -213,74 +267,50 @@ public class ClassAnalyzer implements Analyzer, Scope { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
writer.pushScope(this); |
|
|
|
|
|
|
|
|
|
int modifiedModifiers = modifiers & ~Modifier.SYNCHRONIZED; |
|
|
|
|
if (clazz.isInterface()) |
|
|
|
|
modifiedModifiers &= ~Modifier.ABSTRACT; |
|
|
|
|
if (parent instanceof CodeAnalyzer) { |
|
|
|
|
/* method scope classes are implicitly private */ |
|
|
|
|
modifiedModifiers &= ~Modifier.PRIVATE; |
|
|
|
|
/* anonymous classes are implicitly final */ |
|
|
|
|
if (name == null) |
|
|
|
|
modifiedModifiers &= ~Modifier.FINAL; |
|
|
|
|
} |
|
|
|
|
String modif = Modifier.toString(modifiedModifiers); |
|
|
|
|
if (modif.length() > 0) |
|
|
|
|
writer.print(modif + " "); |
|
|
|
|
/*interface is in modif*/ |
|
|
|
|
if (!clazz.isInterface()) |
|
|
|
|
writer.print("class "); |
|
|
|
|
if (parent != null && name == null) { |
|
|
|
|
/* This is an anonymous class */ |
|
|
|
|
ClassInfo superClazz = clazz.getSuperclass(); |
|
|
|
|
ClassInfo[] interfaces = clazz.getInterfaces(); |
|
|
|
|
if (interfaces.length == 1 |
|
|
|
|
&& (superClazz == null |
|
|
|
|
|| superClazz == ClassInfo.javaLangObject)) { |
|
|
|
|
writer.print(writer.getClassString(interfaces[0], |
|
|
|
|
Scope.CLASSNAME)); |
|
|
|
|
} else { |
|
|
|
|
if (interfaces.length > 0) { |
|
|
|
|
writer.print("/*too many supers*/ "); |
|
|
|
|
for (int i=0; i< interfaces.length; i++) |
|
|
|
|
writer.print(writer.getClassString |
|
|
|
|
(interfaces[i], Scope.CLASSNAME) + ","); |
|
|
|
|
} |
|
|
|
|
if (superClazz == null) |
|
|
|
|
writer.print(writer.getClassString |
|
|
|
|
(ClassInfo.javaLangObject, Scope.CLASSNAME)); |
|
|
|
|
else |
|
|
|
|
writer.print(writer.getClassString |
|
|
|
|
(superClazz, Scope.CLASSNAME)); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
writer.println(name); |
|
|
|
|
writer.tab(); |
|
|
|
|
ClassInfo superClazz = clazz.getSuperclass(); |
|
|
|
|
if (superClazz != null && |
|
|
|
|
superClazz != ClassInfo.javaLangObject) { |
|
|
|
|
writer.println("extends " + (writer.getClassString |
|
|
|
|
(superClazz, Scope.CLASSNAME))); |
|
|
|
|
} |
|
|
|
|
ClassInfo[] interfaces = clazz.getInterfaces(); |
|
|
|
|
if (interfaces.length > 0) { |
|
|
|
|
writer.print(clazz.isInterface() ? "extends " : "implements "); |
|
|
|
|
for (int i=0; i < interfaces.length; i++) { |
|
|
|
|
if (i > 0) |
|
|
|
|
writer.print(", "); |
|
|
|
|
writer.print(writer.getClassString |
|
|
|
|
(interfaces[i], Scope.CLASSNAME)); |
|
|
|
|
} |
|
|
|
|
writer.println(""); |
|
|
|
|
writer.println(name); |
|
|
|
|
writer.tab(); |
|
|
|
|
ClassInfo superClazz = clazz.getSuperclass(); |
|
|
|
|
if (superClazz != null && |
|
|
|
|
superClazz != ClassInfo.javaLangObject) { |
|
|
|
|
writer.println("extends " + (writer.getClassString |
|
|
|
|
(superClazz, Scope.CLASSNAME))); |
|
|
|
|
} |
|
|
|
|
ClassInfo[] interfaces = clazz.getInterfaces(); |
|
|
|
|
if (interfaces.length > 0) { |
|
|
|
|
writer.print(clazz.isInterface() ? "extends " : "implements "); |
|
|
|
|
for (int i=0; i < interfaces.length; i++) { |
|
|
|
|
if (i > 0) |
|
|
|
|
writer.print(", "); |
|
|
|
|
writer.print(writer.getClassString |
|
|
|
|
(interfaces[i], Scope.CLASSNAME)); |
|
|
|
|
} |
|
|
|
|
writer.untab(); |
|
|
|
|
writer.println(""); |
|
|
|
|
} |
|
|
|
|
writer.untab(); |
|
|
|
|
|
|
|
|
|
writer.openBrace(); |
|
|
|
|
writer.tab(); |
|
|
|
|
|
|
|
|
|
for (int i=0; i< fields.length; i++) |
|
|
|
|
fields[i].dumpSource(writer); |
|
|
|
|
for (int i=0; i< inners.length; i++) { |
|
|
|
|
writer.println(""); |
|
|
|
|
inners[i].dumpSource(writer); |
|
|
|
|
} |
|
|
|
|
for (int i=0; i< methods.length; i++) |
|
|
|
|
methods[i].dumpSource(writer); |
|
|
|
|
dumpBlock(writer); |
|
|
|
|
writer.untab(); |
|
|
|
|
if (parent != null && name == null) { |
|
|
|
|
/* This is an anonymous class */ |
|
|
|
|
if (parent instanceof CodeAnalyzer) { |
|
|
|
|
/* This is a method scope class */ |
|
|
|
|
writer.closeBraceNoSpace(); |
|
|
|
|
} else |
|
|
|
|
writer.closeBrace(); |
|
|
|
@ -303,6 +333,11 @@ public class ClassAnalyzer implements Analyzer, Scope { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int serialnr = 0; |
|
|
|
|
public void makeNameUnique() { |
|
|
|
|
name = name + "_" + serialnr++ + "_"; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public boolean conflicts(String name, int usageType) { |
|
|
|
|
ClassInfo info = clazz; |
|
|
|
|
while (info != null) { |
|
|
|
|