not working yet, I plan to merge it with MethodAnalyzer

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@876 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent 90beb1338f
commit 3a1455664a
  1. 238
      jode/jode/decompiler/CodeAnalyzer.java
  2. 53
      jode/jode/decompiler/MethodAnalyzer.java

@ -46,7 +46,7 @@ import java.io.DataInputStream;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
public class CodeAnalyzer implements Analyzer, Scope { public class CodeAnalyzer implements Analyzer, Scope, ClassDeclarer {
FlowBlock methodHeader; FlowBlock methodHeader;
BytecodeInfo code; BytecodeInfo code;
@ -62,6 +62,7 @@ public class CodeAnalyzer implements Analyzer, Scope {
*/ */
Dictionary anonClasses = new SimpleDictionary(); Dictionary anonClasses = new SimpleDictionary();
Vector anonAnalyzers = new Vector(); Vector anonAnalyzers = new Vector();
Vector innerAnalyzers = new Vector();
LocalInfo[] param; LocalInfo[] param;
LocalVariableTable lvt; LocalVariableTable lvt;
@ -246,26 +247,6 @@ public class CodeAnalyzer implements Analyzer, Scope {
methodHeader.removeOnetimeLocals(); methodHeader.removeOnetimeLocals();
methodHeader.mergeParams(param); methodHeader.mergeParams(param);
createAnonymousClasses();
Enumeration enum = allLocals.elements();
while (enum.hasMoreElements()) {
LocalInfo li = (LocalInfo)enum.nextElement();
if (!li.isShadow())
imports.useType(li.getType());
}
for (int i=0; i < param.length; i++) {
param[i].guessName();
for (int j=0; j < i; j++) {
if (param[j].getName().equals(param[i].getName())) {
/* A name conflict happened. */
param[i].makeNameUnique();
break; /* j */
}
}
}
methodHeader.makeDeclaration(param);
methodHeader.simplify();
} }
public void dumpSource(TabbedPrintWriter writer) public void dumpSource(TabbedPrintWriter writer)
@ -319,12 +300,13 @@ public class CodeAnalyzer implements Analyzer, Scope {
public void addAnonymousConstructor(ConstructorOperator cop) { public void addAnonymousConstructor(ConstructorOperator cop) {
ClassInfo cinfo = cop.getClassInfo(); ClassInfo cinfo = cop.getClassInfo();
ConstructorOperator[] cops = ConstructorOperator[] cops =
(ConstructorOperator[]) anonClasses.get(cinfo); (ConstructorOperator[]) anonClasses.get(cinfo);
ConstructorOperator[] newCops; ConstructorOperator[] newCops;
if (cops == null) if (cops == null) {
newCops = new ConstructorOperator[] { cop }; newCops = new ConstructorOperator[] { cop };
else { } else {
newCops = new ConstructorOperator[cops.length + 1]; newCops = new ConstructorOperator[cops.length + 1];
System.arraycopy(cops, 0, newCops, 0, cops.length); System.arraycopy(cops, 0, newCops, 0, cops.length);
newCops[cops.length] = cop; newCops[cops.length] = cop;
@ -340,80 +322,132 @@ public class CodeAnalyzer implements Analyzer, Scope {
ClassInfo clazz = (ClassInfo) keys.nextElement(); ClassInfo clazz = (ClassInfo) keys.nextElement();
ConstructorOperator[] cops = ConstructorOperator[] cops =
(ConstructorOperator[]) elts.nextElement(); (ConstructorOperator[]) elts.nextElement();
ClassAnalyzer anonAnalyzer = getParent().getClassAnalyzer(clazz);
// System.err.println("aac: expr0 = "+cops[0]); int copsNr = 0;
Expression[] subExprs1 = cops[0].getSubExpressions();
int maxOuter = subExprs1.length; Expression[] outerValues;
for (int i=1; i < cops.length; i++) { int maxOuter;
// System.err.println("aac: expr"+i+" = "+cops[i]); if (anonAnalyzer != null) {
Expression[] subExprs2 = cops[i].getSubExpressions(); outerValues = anonAnalyzer.getOuterValues();
maxOuter = Math.min(subExprs2.length, maxOuter); maxOuter = outerValues.length;
} else {
System.err.println("aac: expr0 = "+cops[0]);
outerValues = new Expression[maxOuter];
Expression[] subExprs1 = cops[copsNr++].getSubExpressions();
maxOuter = subExprs1.length;
for (int j=0; j < maxOuter; j++) { for (int j=0; j < maxOuter; j++) {
if (!subExprs2[j].equals(subExprs1[j])) { Expression expr = subExprs1[j].simplify();
maxOuter = j; if (expr instanceof CheckNullOperator)
break; expr = ((CheckNullOperator) expr).getSubExpressions()[0];
if (expr instanceof ThisOperator) {
outerValues[j] =
new ThisOperator(((ThisOperator)expr).getClassInfo());
continue;
} }
if (expr instanceof LocalLoadOperator) {
LocalLoadOperator llop = (LocalLoadOperator) expr;
LocalInfo li = llop.getLocalInfo();
for (int i=1; i < cops.length; i++) {
Expression expr2 =
cops[i].getSubExpressions()[j].simplify();
if (expr2 instanceof CheckNullOperator)
expr2 = ((CheckNullOperator) expr2)
.getSubExpressions()[0];
LocalInfo li2 =
((LocalLoadOperator) expr2).getLocalInfo();
li2.combineWith(li);
}
if (li.markFinal()) {
outerValues[j] = new OuterLocalOperator(li);
continue;
}
}
maxOuter = j;
System.err.println("new maxOuter: "+maxOuter+" ("+expr);
} }
} }
for (int i=copsNr; i < cops.length; i++) {
Expression[] outerValues = new Expression[maxOuter]; Expression[] subExprs = cops[i].getSubExpressions();
for (int j=0; j < maxOuter; j++) { for (j=0; j < maxOuter; j++) {
Expression expr = subExprs1[j].simplify(); Expression expr = subExprs[j].simplify();
if (expr instanceof CheckNullOperator) if (expr instanceof CheckNullOperator)
expr = ((CheckNullOperator) expr).getSubExpressions()[0]; expr = ((CheckNullOperator) expr).getSubExpressions()[0];
if (expr instanceof ThisOperator) { if (expr instanceof ThisOperator
outerValues[j] = && expr.equals(outerValues[j]))
new ThisOperator(((ThisOperator)expr).getClassInfo());
continue;
}
if (expr instanceof LocalLoadOperator) {
LocalLoadOperator llop = (LocalLoadOperator) expr;
LocalInfo li = llop.getLocalInfo();
for (int i=1; i < cops.length; i++) {
Expression expr2 =
cops[i].getSubExpressions()[j].simplify();
if (expr2 instanceof CheckNullOperator)
expr2 = ((CheckNullOperator) expr2)
.getSubExpressions()[0];
LocalInfo li2 =
((LocalLoadOperator) expr2).getLocalInfo();
li2.combineWith(li);
}
if (li.markFinal()) {
outerValues[j] = new OuterLocalOperator(li);
continue; continue;
if (expr instanceof LocalLoadOperator) {
// more thorough checks for constructors!
// combine locals!
// what else?
XXX
LocalLoadOperator llop = (LocalLoadOperator) expr;
LocalInfo li = llop.getLocalInfo();
for (int i=1; i < cops.length; i++) {
Expression expr2 =
cops[i].getSubExpressions()[j].simplify();
if (expr2 instanceof CheckNullOperator)
expr2 = ((CheckNullOperator) expr2)
.getSubExpressions()[0];
LocalInfo li2 =
((LocalLoadOperator) expr2).getLocalInfo();
li2.combineWith(li);
}
if (li.markFinal()) {
outerValues[j] = new OuterLocalOperator(li);
continue;
}
} }
maxOuter = j;
System.err.println("new maxOuter: "+maxOuter+" ("+expr);
} }
maxOuter = j; }
// System.err.println("new maxOuter: "+maxOuter+" ("+expr); if (maxOuter > outerValues.length) {
Expression[] newOuter = new Expression[j]; Expression[] newOuter = new Expression[j];
System.arraycopy(outerValues, 0, newOuter, 0, j); System.arraycopy(outerValues, 0, newOuter, 0, j);
outerValues = newOuter; outerValues = newOuter;
break; break;
} }
ClassAnalyzer classAna = new ClassAnalyzer(this, clazz, imports, if (anonAnalyzer == null)
outerValues); anonAnalyzer = new ClassAnalyzer(this, clazz, imports,
anonAnalyzers.addElement(classAna); outerValues);
else
anonAnalyzer.setOuterValues(outerValues);
anonAnalyzer.analyze();
anonAnalyzers.addElement(anonAnalyzer);
} }
analyzedAnonymous = true; analyzedAnonymous = true;
} }
public void analyzeAnonymousClasses() { public void analyzeAnonymousClasses() {
boolean hasAnonymous = false; createAnonymousClasses();
Enumeration enum = anonAnalyzers.elements(); }
while (enum.hasMoreElements()) {
ClassAnalyzer classAna = (ClassAnalyzer) enum.nextElement(); public void makeDeclaration() {
if (classAna.getName() == null) for (Enumeration enum = allLocals.elements();
hasAnonymous = true; enum.hasMoreElements(); ) {
classAna.analyze(); LocalInfo li = (LocalInfo)enum.nextElement();
if (!li.isShadow())
imports.useType(li.getType());
}
for (int i=0; i < param.length; i++) {
param[i].guessName();
for (int j=0; j < i; j++) {
if (param[j].getName().equals(param[i].getName())) {
/* A name conflict happened. */
param[i].makeNameUnique();
break; /* j */
}
}
} }
if (hasAnonymous) {
/* We have to simplify again methodHeader.makeDeclaration(param);
* XXX This is because the ConstructorOperator should remove methodHeader.simplify();
* the CheckNullOperator, but where is only known after for (Enumeration enum = anonAnalyzers.elements();
* analyzing inner classes. enum.hasMoreElements(); ) {
*/ ClassAnalyzer classAna = (ClassAnalyzer) enum.nextElement();
methodHeader.simplify(); classAna.makeDeclaration();
addClassAnalyzer(classAna);
} }
} }
@ -421,19 +455,41 @@ public class CodeAnalyzer implements Analyzer, Scope {
return analyzedAnonymous; return analyzedAnonymous;
} }
public ClassAnalyzer getAnonymousClass(ClassInfo cinfo) { public LocalInfo getParamInfo(int nr) {
Enumeration enum = anonAnalyzers.elements(); return param[nr];
while (enum.hasMoreElements()) {
ClassAnalyzer classAna = (ClassAnalyzer) enum.nextElement();
if (classAna.getClazz().equals(cinfo))
return classAna;
}
throw new java.util.NoSuchElementException(cinfo.toString());
} }
public void addClassAnalyzer(ClassAnalyzer clazzAna) {
if (innerAnalyzers == null)
innerAnalyzers = new Vector();
innerAnalyzers.addElement(clazzAna);
getParent().addClassAnalyzer(clazzAna);
}
public LocalInfo getParamInfo(int nr) {
return param[nr]; /**
* Get the class analyzer for the given class info. This searches
* the method scoped/anonymous classes in this method and all
* outer methods and the outer classes for the class analyzer.
* @param cinfo the classinfo for which the analyzer is searched.
* @return the class analyzer, or null if there is not an outer
* class that equals cinfo, and not a method scope/inner class in
* an outer method.
*/
public ClassAnalyzer getClassAnalyzer(ClassInfo cinfo) {
if (innerAnalyzers != null) {
Enumeration enum = innerAnalyzers.elements();
while (enum.hasMoreElements()) {
ClassAnalyzer classAna = (ClassAnalyzer) enum.nextElement();
if (classAna.getClazz().equals(cinfo)) {
if (classAna.getParent() != this) {
classAna.setParent(this);
}
return classAna;
}
}
}
return getParent().getClassAnalyzer(cinfo);
} }
public ClassAnalyzer getClassAnalyzer() { public ClassAnalyzer getClassAnalyzer() {
@ -472,4 +528,8 @@ public class CodeAnalyzer implements Analyzer, Scope {
return findAnonClass(name) != null; return findAnonClass(name) != null;
return false; return false;
} }
public ClassDeclarer getParent() {
return getClassAnalyzer();
}
} }

@ -31,7 +31,7 @@ import jode.GlobalOptions;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.io.*; import java.io.*;
public class MethodAnalyzer implements Analyzer { public class MethodAnalyzer implements Analyzer, Scope, ClassDeclarer {
ImportHandler imports; ImportHandler imports;
ClassAnalyzer classAnalyzer; ClassAnalyzer classAnalyzer;
MethodInfo minfo; MethodInfo minfo;
@ -135,15 +135,6 @@ public class MethodAnalyzer implements Analyzer {
offset++; offset++;
} }
// if (isConstructor() && !isStatic()
// && classAnalyzer.outerValues != null) {
// Expression[] outerValues = classAnalyzer.outerValues;
// for (int i=0; i< outerValues.length; i++) {
// LocalInfo local = code.getParamInfo(offset+i);
// local.setExpression(outerValues[i]);
// }
// }
Type[] paramTypes = methodType.getParameterTypes(); Type[] paramTypes = methodType.getParameterTypes();
for (int i=0; i< paramTypes.length; i++) { for (int i=0; i< paramTypes.length; i++) {
code.getParamInfo(offset).setType(paramTypes[i]); code.getParamInfo(offset).setType(paramTypes[i]);
@ -180,6 +171,20 @@ public class MethodAnalyzer implements Analyzer {
code.analyzeAnonymousClasses(); code.analyzeAnonymousClasses();
} }
public void makeDeclaration() {
if (isConstructor() && !isStatic()
&& classAnalyzer.outerValues != null) {
Expression[] outerValues = classAnalyzer.outerValues;
for (int i=0; i< outerValues.length; i++) {
LocalInfo local = code.getParamInfo(1+i);
local.setExpression(outerValues[i]);
}
}
if (code != null)
code.makeDeclaration();
}
public boolean skipWriting() { public boolean skipWriting() {
if (synth != null) { if (synth != null) {
// We don't need this class anymore (hopefully?) // We don't need this class anymore (hopefully?)
@ -268,11 +273,30 @@ public class MethodAnalyzer implements Analyzer {
} }
if (minfo.isSynthetic()) if (minfo.isSynthetic())
writer.print("/*synthetic*/ "); writer.print("/*synthetic*/ ");
String modif = Modifier.toString(minfo.getModifiers()); int modifiedModifiers = minfo.getModifiers();
/*
* JLS-1.0, section 9.4:
*
* For compatibility with older versions of Java, it is
* permitted but discouraged, as a matter of style, to
* redundantly specify the abstract modifier for methods
* declared in interfaces.
*
* Every method declaration in the body of an interface is
* implicitly public. It is permitted, but strongly
* discouraged as a matter of style, to redundantly specify
* the public modifier for interface methods.
*/
if (classAnalyzer.getClazz().isInterface())
modifiedModifiers &= ~(Modifier.PUBLIC | Modifier.ABSTRACT);
String modif = Modifier.toString(modifiedModifiers);
if (modif.length() > 0) if (modif.length() > 0)
writer.print(modif+" "); writer.print(modif+" ");
if (isConstructor && isStatic()) if (isConstructor
writer.print(""); /* static block */ && (isStatic()
|| (classAnalyzer.getName() == null
&& skipParams == methodType.getParameterTypes().length)))
writer.print(""); /* static block or unnamed constructor */
else { else {
if (declareAsConstructor) if (declareAsConstructor)
writer.print(classAnalyzer.getName()); writer.print(classAnalyzer.getName());
@ -307,8 +331,7 @@ public class MethodAnalyzer implements Analyzer {
for (int i=start; i<paramTypes.length; i++) { for (int i=start; i<paramTypes.length; i++) {
if (i>start) if (i>start)
writer.print(", "); writer.print(", ");
writer.printType(param[i].getType()); param[i].dumpDeclaration(writer);
writer.print(" "+param[i].getName());
} }
writer.print(")"); writer.print(")");
} }

Loading…
Cancel
Save