use setExpression to propagate this/outerValues

handle anonymous/method scope classes


git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@844 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 25 years ago
parent ca17ed9fd1
commit ceb0ce32d5
  1. 132
      jode/jode/decompiler/MethodAnalyzer.java

@ -18,9 +18,12 @@
*/ */
package jode.decompiler; package jode.decompiler;
import jode.bytecode.ClassInfo;
import jode.bytecode.MethodInfo; import jode.bytecode.MethodInfo;
import jode.jvm.SyntheticAnalyzer; import jode.jvm.SyntheticAnalyzer;
import jode.type.*; import jode.type.*;
import jode.expr.Expression;
import jode.expr.ThisOperator;
import jode.AssertError; import jode.AssertError;
import jode.Decompiler; import jode.Decompiler;
import jode.GlobalOptions; import jode.GlobalOptions;
@ -41,7 +44,10 @@ public class MethodAnalyzer implements Analyzer {
Type[] exceptions; Type[] exceptions;
SyntheticAnalyzer synth; SyntheticAnalyzer synth;
boolean isJikesConstructor;
boolean isImplicitAnonymousConstructor;
public MethodAnalyzer(ClassAnalyzer cla, MethodInfo minfo, public MethodAnalyzer(ClassAnalyzer cla, MethodInfo minfo,
ImportHandler imports) { ImportHandler imports) {
this.classAnalyzer = cla; this.classAnalyzer = cla;
@ -95,6 +101,14 @@ public class MethodAnalyzer implements Analyzer {
return minfo.isSynthetic(); return minfo.isSynthetic();
} }
public final void setJikesConstructor(boolean value) {
isJikesConstructor = value;
}
public final void setAnonymousConstructor(boolean value) {
isImplicitAnonymousConstructor = value;
}
public final SyntheticAnalyzer getSynthetic() { public final SyntheticAnalyzer getSynthetic() {
return synth; return synth;
} }
@ -111,19 +125,19 @@ public class MethodAnalyzer implements Analyzer {
int offset = 0; int offset = 0;
if (!isStatic()) { if (!isStatic()) {
LocalInfo clazz = code.getParamInfo(0); ClassInfo classInfo = classAnalyzer.getClazz();
clazz.setType(Type.tClass(classAnalyzer.getClazz())); LocalInfo thisLocal = code.getParamInfo(0);
clazz.setName("this"); thisLocal.setExpression(new ThisOperator(classInfo, true));
offset++; offset++;
} }
if (isConstructor() if (isConstructor() && !isStatic()
&& classAnalyzer.getParent() instanceof ClassAnalyzer && classAnalyzer.outerValues != null) {
&& !classAnalyzer.isStatic()) { Expression[] outerValues = classAnalyzer.outerValues;
ClassAnalyzer parent = (ClassAnalyzer) classAnalyzer.getParent(); for (int i=0; i< outerValues.length; i++) {
LocalInfo clazz = code.getParamInfo(1); LocalInfo local = code.getParamInfo(offset+i);
clazz.setType(Type.tClass(parent.getClazz())); local.setExpression(outerValues[i]);
clazz.setName("this$-1"); }
} }
Type[] paramTypes = methodType.getParameterTypes(); Type[] paramTypes = methodType.getParameterTypes();
@ -146,31 +160,85 @@ public class MethodAnalyzer implements Analyzer {
GlobalOptions.err.println(""); GlobalOptions.err.println("");
} }
} }
public void dumpSource(TabbedPrintWriter writer) public LocalInfo getParamInfo(int i) {
throws IOException if (code == null)
return null;
return code.getParamInfo(i);
}
public void analyzeAnonymousClasses()
throws ClassFormatError
{ {
if (code == null)
return;
code.analyzeAnonymousClasses();
}
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?)
if (synth.getKind() == synth.GETCLASS) if (synth.getKind() == synth.GETCLASS)
return; return true;
if (synth.getKind() >= synth.ACCESSGETFIELD if (synth.getKind() >= synth.ACCESSGETFIELD
&& synth.getKind() <= synth.ACCESSSTATICMETHOD && synth.getKind() <= synth.ACCESSSTATICMETHOD
&& (Decompiler.options & Decompiler.OPTION_INNER) != 0 && (Decompiler.options & Decompiler.OPTION_INNER) != 0
&& (Decompiler.options & Decompiler.OPTION_ANON) != 0) && (Decompiler.options & Decompiler.OPTION_ANON) != 0)
return; return true;
} }
if (isConstructor && classAnalyzer.constructors.length == 1 if (isConstructor && isJikesConstructor) {
&& (methodType.getParameterTypes().length == 0 // This is the first empty part of a jikes constructor
|| (methodType.getParameterTypes().length == 1 return true;
&& classAnalyzer.parent instanceof ClassAnalyzer)) }
&& getMethodHeader() != null
&& getMethodHeader().getBlock() instanceof jode.flow.EmptyBlock boolean declareAsConstructor = isConstructor;
&& getMethodHeader().hasNoJumps()) int skipParams = 0;
if (isConstructor() && !isStatic()
&& classAnalyzer.outerValues != null)
skipParams = classAnalyzer.outerValues.length;
if (isJikesConstructor) {
// This is the real part of a jikes constructor
declareAsConstructor = true;
skipParams = 1;
}
if (declareAsConstructor
&& classAnalyzer.constructors.length == 1) {
// If this is the only constructor and it is empty and // If this is the only constructor and it is empty and
// takes no parameters, this is the default constructor. // takes no parameters, this is the default constructor.
return; if (methodType.getParameterTypes().length == skipParams
&& getMethodHeader() != null
&& getMethodHeader().getBlock() instanceof jode.flow.EmptyBlock
&& getMethodHeader().hasNoJumps())
return true;
// if this is an anonymous class and this is the only
// constructor and it only does a super call with the given
// parameters, this is constructor is implicit.
if (isImplicitAnonymousConstructor)
return true;
}
return false;
}
public void dumpSource(TabbedPrintWriter writer)
throws IOException
{
boolean declareAsConstructor = isConstructor;
int skipParams = 0;
if (isConstructor() && !isStatic()
&& classAnalyzer.outerValues != null)
skipParams = classAnalyzer.outerValues.length;
if (isJikesConstructor) {
// This is the real part of a jikes constructor
declareAsConstructor = true;
skipParams = 1;
}
if ((Decompiler.options & Decompiler.OPTION_IMMEDIATE) != 0 if ((Decompiler.options & Decompiler.OPTION_IMMEDIATE) != 0
&& code != null) { && code != null) {
@ -188,8 +256,6 @@ public class MethodAnalyzer implements Analyzer {
&& getMethodHeader().getBlock() instanceof jode.flow.EmptyBlock) && getMethodHeader().getBlock() instanceof jode.flow.EmptyBlock)
return; return;
writer.println();
if (minfo.isDeprecated()) { if (minfo.isDeprecated()) {
writer.println("/**"); writer.println("/**");
writer.println(" * @deprecated"); writer.println(" * @deprecated");
@ -203,7 +269,7 @@ public class MethodAnalyzer implements Analyzer {
if (isConstructor && isStatic()) if (isConstructor && isStatic())
writer.print(""); /* static block */ writer.print(""); /* static block */
else { else {
if (isConstructor) if (declareAsConstructor)
writer.print(classAnalyzer.getName()); writer.print(classAnalyzer.getName());
else { else {
writer.printType(getReturnType()); writer.printType(getReturnType());
@ -211,14 +277,8 @@ public class MethodAnalyzer implements Analyzer {
} }
writer.print("("); writer.print("(");
Type[] paramTypes = methodType.getParameterTypes(); Type[] paramTypes = methodType.getParameterTypes();
int offset = isStatic()?0:1; int offset = skipParams + (isStatic() ? 0 : 1);
int start = skipParams;
int start = 0;
if (isConstructor()
&& classAnalyzer.getParent() instanceof ClassAnalyzer) {
start++;
offset++;
}
LocalInfo[] param = new LocalInfo[paramTypes.length]; LocalInfo[] param = new LocalInfo[paramTypes.length];
for (int i=start; i<paramTypes.length; i++) { for (int i=start; i<paramTypes.length; i++) {

Loading…
Cancel
Save