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. 215
      jode/jode/decompiler/ClassAnalyzer.java

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

Loading…
Cancel
Save