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.IOException;
public class CodeAnalyzer implements Analyzer, Scope {
public class CodeAnalyzer implements Analyzer, Scope, ClassDeclarer {
FlowBlock methodHeader;
BytecodeInfo code;
@ -62,6 +62,7 @@ public class CodeAnalyzer implements Analyzer, Scope {
*/
Dictionary anonClasses = new SimpleDictionary();
Vector anonAnalyzers = new Vector();
Vector innerAnalyzers = new Vector();
LocalInfo[] param;
LocalVariableTable lvt;
@ -246,26 +247,6 @@ public class CodeAnalyzer implements Analyzer, Scope {
methodHeader.removeOnetimeLocals();
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)
@ -319,12 +300,13 @@ public class CodeAnalyzer implements Analyzer, Scope {
public void addAnonymousConstructor(ConstructorOperator cop) {
ClassInfo cinfo = cop.getClassInfo();
ConstructorOperator[] cops =
(ConstructorOperator[]) anonClasses.get(cinfo);
ConstructorOperator[] newCops;
if (cops == null)
if (cops == null) {
newCops = new ConstructorOperator[] { cop };
else {
} else {
newCops = new ConstructorOperator[cops.length + 1];
System.arraycopy(cops, 0, newCops, 0, cops.length);
newCops[cops.length] = cop;
@ -340,80 +322,132 @@ public class CodeAnalyzer implements Analyzer, Scope {
ClassInfo clazz = (ClassInfo) keys.nextElement();
ConstructorOperator[] cops =
(ConstructorOperator[]) elts.nextElement();
// System.err.println("aac: expr0 = "+cops[0]);
Expression[] subExprs1 = cops[0].getSubExpressions();
int maxOuter = subExprs1.length;
for (int i=1; i < cops.length; i++) {
// System.err.println("aac: expr"+i+" = "+cops[i]);
Expression[] subExprs2 = cops[i].getSubExpressions();
maxOuter = Math.min(subExprs2.length, maxOuter);
ClassAnalyzer anonAnalyzer = getParent().getClassAnalyzer(clazz);
int copsNr = 0;
Expression[] outerValues;
int maxOuter;
if (anonAnalyzer != null) {
outerValues = anonAnalyzer.getOuterValues();
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++) {
if (!subExprs2[j].equals(subExprs1[j])) {
maxOuter = j;
break;
Expression expr = subExprs1[j].simplify();
if (expr instanceof CheckNullOperator)
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);
}
}
Expression[] outerValues = new Expression[maxOuter];
for (int j=0; j < maxOuter; j++) {
Expression expr = subExprs1[j].simplify();
if (expr instanceof CheckNullOperator)
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);
for (int i=copsNr; i < cops.length; i++) {
Expression[] subExprs = cops[i].getSubExpressions();
for (j=0; j < maxOuter; j++) {
Expression expr = subExprs[j].simplify();
if (expr instanceof CheckNullOperator)
expr = ((CheckNullOperator) expr).getSubExpressions()[0];
if (expr instanceof ThisOperator
&& expr.equals(outerValues[j]))
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];
System.arraycopy(outerValues, 0, newOuter, 0, j);
outerValues = newOuter;
break;
}
ClassAnalyzer classAna = new ClassAnalyzer(this, clazz, imports,
outerValues);
anonAnalyzers.addElement(classAna);
if (anonAnalyzer == null)
anonAnalyzer = new ClassAnalyzer(this, clazz, imports,
outerValues);
else
anonAnalyzer.setOuterValues(outerValues);
anonAnalyzer.analyze();
anonAnalyzers.addElement(anonAnalyzer);
}
analyzedAnonymous = true;
}
public void analyzeAnonymousClasses() {
boolean hasAnonymous = false;
Enumeration enum = anonAnalyzers.elements();
while (enum.hasMoreElements()) {
ClassAnalyzer classAna = (ClassAnalyzer) enum.nextElement();
if (classAna.getName() == null)
hasAnonymous = true;
classAna.analyze();
createAnonymousClasses();
}
public void makeDeclaration() {
for (Enumeration enum = allLocals.elements();
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 */
}
}
}
if (hasAnonymous) {
/* We have to simplify again
* XXX This is because the ConstructorOperator should remove
* the CheckNullOperator, but where is only known after
* analyzing inner classes.
*/
methodHeader.simplify();
methodHeader.makeDeclaration(param);
methodHeader.simplify();
for (Enumeration enum = anonAnalyzers.elements();
enum.hasMoreElements(); ) {
ClassAnalyzer classAna = (ClassAnalyzer) enum.nextElement();
classAna.makeDeclaration();
addClassAnalyzer(classAna);
}
}
@ -421,19 +455,41 @@ public class CodeAnalyzer implements Analyzer, Scope {
return analyzedAnonymous;
}
public ClassAnalyzer getAnonymousClass(ClassInfo cinfo) {
Enumeration enum = anonAnalyzers.elements();
while (enum.hasMoreElements()) {
ClassAnalyzer classAna = (ClassAnalyzer) enum.nextElement();
if (classAna.getClazz().equals(cinfo))
return classAna;
}
throw new java.util.NoSuchElementException(cinfo.toString());
public LocalInfo getParamInfo(int nr) {
return param[nr];
}
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() {
@ -472,4 +528,8 @@ public class CodeAnalyzer implements Analyzer, Scope {
return findAnonClass(name) != null;
return false;
}
public ClassDeclarer getParent() {
return getClassAnalyzer();
}
}

@ -31,7 +31,7 @@ import jode.GlobalOptions;
import java.lang.reflect.Modifier;
import java.io.*;
public class MethodAnalyzer implements Analyzer {
public class MethodAnalyzer implements Analyzer, Scope, ClassDeclarer {
ImportHandler imports;
ClassAnalyzer classAnalyzer;
MethodInfo minfo;
@ -135,15 +135,6 @@ public class MethodAnalyzer implements Analyzer {
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();
for (int i=0; i< paramTypes.length; i++) {
code.getParamInfo(offset).setType(paramTypes[i]);
@ -180,6 +171,20 @@ public class MethodAnalyzer implements Analyzer {
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() {
if (synth != null) {
// We don't need this class anymore (hopefully?)
@ -268,11 +273,30 @@ public class MethodAnalyzer implements Analyzer {
}
if (minfo.isSynthetic())
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)
writer.print(modif+" ");
if (isConstructor && isStatic())
writer.print(""); /* static block */
if (isConstructor
&& (isStatic()
|| (classAnalyzer.getName() == null
&& skipParams == methodType.getParameterTypes().length)))
writer.print(""); /* static block or unnamed constructor */
else {
if (declareAsConstructor)
writer.print(classAnalyzer.getName());
@ -307,8 +331,7 @@ public class MethodAnalyzer implements Analyzer {
for (int i=start; i<paramTypes.length; i++) {
if (i>start)
writer.print(", ");
writer.printType(param[i].getType());
writer.print(" "+param[i].getName());
param[i].dumpDeclaration(writer);
}
writer.print(")");
}

Loading…
Cancel
Save