handle anonymous / method scope classes

don't print nasty empty lines


git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@860 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 25 years ago
parent 288a4b2980
commit 4da464b464
  1. 167
      jode/jode/decompiler/ClassAnalyzer.java

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

Loading…
Cancel
Save