From 6b7635aca72fc92aa49d5a70b7a1d0446f8ac3a6 Mon Sep 17 00:00:00 2001 From: jochen Date: Mon, 3 May 1999 10:50:45 +0000 Subject: [PATCH] inner class handling git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@731 379699f6-c40d-0410-875b-85095c16579e --- jode/jode/decompiler/ClassAnalyzer.java | 219 +++++++++++++++++++----- 1 file changed, 180 insertions(+), 39 deletions(-) diff --git a/jode/jode/decompiler/ClassAnalyzer.java b/jode/jode/decompiler/ClassAnalyzer.java index 64dd131..46ce7de 100644 --- a/jode/jode/decompiler/ClassAnalyzer.java +++ b/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) {