inner class handling

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@731 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent 5408e78f7c
commit 6b7635aca7
  1. 219
      jode/jode/decompiler/ClassAnalyzer.java

@ -18,33 +18,106 @@
*/
package jode.decompiler;
import jode.Decompiler;
import jode.type.*;
import jode.bytecode.ClassInfo;
import jode.bytecode.FieldInfo;
import jode.bytecode.MethodInfo;
import jode.bytecode.InnerClassInfo;
import jode.bytecode.ConstantPool;
import jode.expr.Expression;
import jode.expr.ConstructorOperator;
import jode.flow.TransformConstructors;
import java.util.NoSuchElementException;
import java.lang.reflect.Modifier;
public class ClassAnalyzer implements Analyzer {
public class ClassAnalyzer implements Analyzer, Scope {
ImportHandler imports;
ClassInfo clazz;
Object parent;
String name;
FieldAnalyzer[] fields;
MethodAnalyzer[] methods;
ClassAnalyzer[] inners;
MethodAnalyzer staticConstructor;
MethodAnalyzer[] constructors;
ClassInfo clazz;
ClassAnalyzer parent;
public ClassAnalyzer(ClassAnalyzer parent, ClassInfo clazz,
ImportHandler imports)
public boolean isScopeOf(Object obj, int scopeType) {
if (clazz.equals(obj) && scopeType == CLASSSCOPE)
return true;
return false;
}
public boolean conflicts(String name, int usageType) {
ClassInfo info = clazz;
while (info != null) {
if (usageType == METHODNAME) {
MethodInfo[] minfos = info.getMethods();
for (int i = 0; i< minfos.length; i++)
if (minfos[i].getName().equals(name))
return true;
}
if (usageType == FIELDNAME || usageType == AMBIGUOUSNAME) {
FieldInfo[] finfos = info.getFields();
for (int i=0; i < finfos.length; i++) {
if (finfos[i].getName().equals(name))
return true;
}
}
if (usageType == CLASSNAME || usageType == AMBIGUOUSNAME) {
InnerClassInfo[] iinfos = info.getInnerClasses();
if (iinfos != null) {
for (int i=0; i < iinfos.length; i++) {
if (iinfos[i].name.equals(name))
return true;
}
}
}
info = info.getSuperclass();
}
return false;
}
public ClassAnalyzer(Object parent,
ClassInfo clazz, ImportHandler imports)
{
clazz.loadInfo(clazz.FULLINFO);
this.parent = parent;
this.clazz = clazz;
this.imports = imports;
name = clazz.getName();
if (parent != null) {
InnerClassInfo[] outerInfos = clazz.getOuterClasses();
if (outerInfos[0].outer == null) {
if (parent instanceof ClassAnalyzer)
throw new jode.AssertError
("ClassInfo Attributes are inconsistent: "
+ clazz.getName());
} else {
if (!(parent instanceof ClassAnalyzer)
|| !(((ClassAnalyzer) parent).clazz.getName()
.equals(outerInfos[0].outer))
|| outerInfos[0].name == null)
throw new jode.AssertError
("ClassInfo Attributes are inconsistent: "
+ clazz.getName());
}
name = outerInfos[0].name;
} else {
name = clazz.getName();
int dot = name.lastIndexOf('.');
if (dot >= 0)
name = name.substring(dot+1);
}
}
public ClassAnalyzer(ClassInfo clazz, ImportHandler imports)
{
this(null, clazz, imports);
}
public FieldAnalyzer getField(String fieldName, Type fieldType) {
@ -67,6 +140,10 @@ public class ClassAnalyzer implements Analyzer {
("Method "+methodType+" "+clazz.getName()+"."+methodName);
}
public Object getParent() {
return parent;
}
public ClassInfo getClazz() {
return clazz;
}
@ -74,6 +151,8 @@ public class ClassAnalyzer implements Analyzer {
public void analyze() {
FieldInfo[] finfos = clazz.getFields();
MethodInfo[] minfos = clazz.getMethods();
InnerClassInfo[] innerInfos = clazz.getInnerClasses();
if (finfos == null) {
/* This means that the class could not be loaded.
* give up.
@ -81,12 +160,21 @@ public class ClassAnalyzer implements Analyzer {
return;
}
if ((Decompiler.options & Decompiler.OPTION_INNER) != 0
&& innerInfos != null) {
int innerCount = innerInfos.length;
inners = new ClassAnalyzer[innerCount];
for (int i=0; i < innerCount; i++) {
inners[i] = new ClassAnalyzer
(this, ClassInfo.forName(innerInfos[i].inner), imports);
}
} else
inners = new ClassAnalyzer[0];
fields = new FieldAnalyzer[finfos.length];
methods = new MethodAnalyzer[minfos.length];
for (int j=0; j < finfos.length; j++) {
for (int j=0; j < finfos.length; j++)
fields[j] = new FieldAnalyzer(this, finfos[j], imports);
fields[j].analyze();
}
staticConstructor = null;
java.util.Vector constrVector = new java.util.Vector();
@ -99,23 +187,36 @@ public class ClassAnalyzer implements Analyzer {
else
constrVector.addElement(methods[j]);
}
// First analyze only synthetic methods.
if (methods[j].isSynthetic())
methods[j].analyze();
}
for (int j=0; j < methods.length; j++) {
// Now analyze the remaining methods
if (!methods[j].isSynthetic())
methods[j].analyze();
}
// First analyze fields
for (int j=0; j < fields.length; j++)
fields[j].analyze();
// now analyze constructors:
constructors = new MethodAnalyzer[constrVector.size()];
if (constructors.length > 0) {
constrVector.copyInto(constructors);
TransformConstructors.transform(this, false, constructors);
for (int j=0; j< constructors.length; j++)
constructors[j].analyze();
TransformConstructors.transform
(this, false, parent instanceof ClassAnalyzer,
parent instanceof ConstructorOperator, constructors);
}
if (staticConstructor != null)
TransformConstructors.transform(this, true, new MethodAnalyzer[]
{ staticConstructor });
if (staticConstructor != null) {
staticConstructor.analyze();
TransformConstructors.transform(this, true, false, false,
new MethodAnalyzer[]
{ staticConstructor });
}
// Now analyze remaining methods.
for (int j=0; j < methods.length; j++) {
if (!methods[j].isConstructor())
methods[j].analyze();
}
// Now analyze the inner classes.
for (int j=0; j < inners.length; j++)
inners[j].analyze();
imports.useClass(clazz);
if (clazz.getSuperclass() != null)
@ -125,6 +226,14 @@ public class ClassAnalyzer implements Analyzer {
imports.useClass(interfaces[j]);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void dumpSource(TabbedPrintWriter writer) throws java.io.IOException
{
if (fields == null) {
@ -133,6 +242,7 @@ public class ClassAnalyzer implements Analyzer {
*/
return;
}
writer.pushScope(this);
int modifiedModifiers = clazz.getModifiers() & ~Modifier.SYNCHRONIZED;
if (clazz.isInterface())
modifiedModifiers &= ~Modifier.ABSTRACT;
@ -142,33 +252,64 @@ public class ClassAnalyzer implements Analyzer {
/*interface is in modif*/
if (!clazz.isInterface())
writer.print("class ");
writer.println(imports.getClassString(clazz));
writer.tab();
ClassInfo superClazz = clazz.getSuperclass();
if (superClazz != null &&
superClazz != ClassInfo.javaLangObject) {
writer.println("extends "+imports.getClassString(superClazz));
}
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(imports.getClassString(interfaces[i]));
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]));
} else {
if (interfaces.length > 0) {
writer.print("/*too many supers*/ ");
for (int i=0; i< interfaces.length; i++)
writer.print(writer.getClassString(interfaces[i])+",");
}
if (superClazz == null)
writer.print(writer.getClassString
(ClassInfo.javaLangObject));
else
writer.print(writer.getClassString(superClazz));
}
writer.println("");
} else {
writer.println(name);
writer.tab();
ClassInfo superClazz = clazz.getSuperclass();
if (superClazz != null &&
superClazz != ClassInfo.javaLangObject) {
writer.println("extends "+writer.getClassString(superClazz));
}
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]));
}
writer.println("");
}
writer.untab();
}
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);
writer.untab();
writer.closeBrace();
if (parent != null && name == null) {
/* This is an anonymous class */
writer.closeBraceNoSpace();
} else
writer.closeBrace();
writer.popScope();
}
public String getTypeString(Type type) {

Loading…
Cancel
Save