transforms access methods

class.super() handling for inner classes
scope handling


git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@744 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent c0e9183459
commit 93244afa2c
  1. 203
      jode/jode/expr/InvokeOperator.java

@ -18,7 +18,9 @@
*/ */
package jode.expr; package jode.expr;
import jode.Decompiler;
import jode.decompiler.CodeAnalyzer; import jode.decompiler.CodeAnalyzer;
import jode.decompiler.MethodAnalyzer;
import jode.decompiler.ClassAnalyzer; import jode.decompiler.ClassAnalyzer;
import jode.decompiler.TabbedPrintWriter; import jode.decompiler.TabbedPrintWriter;
import jode.GlobalOptions; import jode.GlobalOptions;
@ -26,6 +28,7 @@ import jode.bytecode.*;
import jode.jvm.*; import jode.jvm.*;
import jode.type.*; import jode.type.*;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import jode.decompiler.Scope;
public final class InvokeOperator extends Operator public final class InvokeOperator extends Operator
implements MatchableOperator { implements MatchableOperator {
@ -34,7 +37,7 @@ public final class InvokeOperator extends Operator
boolean specialFlag; boolean specialFlag;
MethodType methodType; MethodType methodType;
String methodName; String methodName;
Type clazz; Type classType;
public InvokeOperator(CodeAnalyzer codeAnalyzer, public InvokeOperator(CodeAnalyzer codeAnalyzer,
boolean staticFlag, boolean specialFlag, boolean staticFlag, boolean specialFlag,
@ -42,13 +45,13 @@ public final class InvokeOperator extends Operator
super(Type.tUnknown, 0); super(Type.tUnknown, 0);
this.methodType = (MethodType) Type.tType(reference.getType()); this.methodType = (MethodType) Type.tType(reference.getType());
this.methodName = reference.getName(); this.methodName = reference.getName();
this.clazz = Type.tType(reference.getClazz()); this.classType = Type.tType(reference.getClazz());
this.type = methodType.getReturnType(); this.type = methodType.getReturnType();
this.codeAnalyzer = codeAnalyzer; this.codeAnalyzer = codeAnalyzer;
this.staticFlag = staticFlag; this.staticFlag = staticFlag;
this.specialFlag = specialFlag; this.specialFlag = specialFlag;
if (staticFlag) if (staticFlag)
codeAnalyzer.useType(clazz); codeAnalyzer.useType(classType);
} }
/** /**
@ -83,7 +86,7 @@ public final class InvokeOperator extends Operator
} }
public Type getClassType() { public Type getClassType() {
return clazz; return classType;
} }
public int getPriority() { public int getPriority() {
@ -111,26 +114,89 @@ public final class InvokeOperator extends Operator
return methodName.equals("<init>"); return methodName.equals("<init>");
} }
public ClassInfo getClassInfo() {
if (classType instanceof ClassInterfacesType)
return ((ClassInterfacesType) classType).getClassInfo();
return null;
}
/** /**
* Checks, whether this is a call of a method from this class. * Checks, whether this is a call of a method from this class.
* @XXX check, if this class implements the method and if not * @XXX check, if this class implements the method and if not
* allow super class * allow super class
*/ */
public boolean isThis() { public boolean isThis() {
if (clazz instanceof ClassInterfacesType) { return getClassInfo() == codeAnalyzer.getClazz();
return ((ClassInterfacesType) clazz).getClassInfo() }
== codeAnalyzer.getClazz();
public ClassInfo getOuterClass() {
ClassInfo clazz = getClassInfo();
if (clazz != null) {
InnerClassInfo[] outers = clazz.getOuterClasses();
if (outers != null && outers[0].outer != null
&& (Decompiler.options & Decompiler.OPTION_INNER) != 0)
return ClassInfo.forName(outers[0].outer);
}
return null;
}
/**
* Checks, whether this is a call of a method from this class or an
* outer instance.
*/
public boolean isOuter() {
if (classType instanceof ClassInterfacesType) {
ClassAnalyzer ana = codeAnalyzer.getClassAnalyzer();
while (true) {
if (((ClassInterfacesType) classType).getClassInfo()
== ana.getClazz())
return true;
if (ana.getParent() instanceof CodeAnalyzer
&& (Decompiler.options & Decompiler.OPTION_ANON) != 0)
ana = ((CodeAnalyzer) ana.getParent())
.getClassAnalyzer();
else if (ana.getParent() instanceof ConstructorOperator
&& (Decompiler.options & Decompiler.OPTION_ANON) != 0)
ana = ((ConstructorOperator) ana.getParent())
.getCodeAnalyzer().getClassAnalyzer();
else if (ana.getParent() instanceof ClassAnalyzer
&& (Decompiler.options
& Decompiler.OPTION_INNER) != 0)
ana = (ClassAnalyzer) ana.getParent();
else
return false;
}
} }
return false; return false;
} }
public MethodAnalyzer getMethodAnalyzer() {
if (classType instanceof ClassInterfacesType) {
ClassAnalyzer ana = codeAnalyzer.getClassAnalyzer();
while (true) {
if (((ClassInterfacesType) classType).getClassInfo()
== ana.getClazz()) {
return ana.getMethod(methodName, methodType);
}
if (ana.getParent() instanceof MethodAnalyzer)
ana = ((MethodAnalyzer) ana.getParent())
.getClassAnalyzer();
else if (ana.getParent() instanceof ClassAnalyzer)
ana = (ClassAnalyzer) ana.getParent();
else
return null;
}
}
return null;
}
/** /**
* Checks, whether this is a call of a method from the super class. * Checks, whether this is a call of a method from the super class.
* @XXX check, if its the first super class that implements the method. * @XXX check, if its the first super class that implements the method.
*/ */
public boolean isSuperOrThis() { public boolean isSuperOrThis() {
if (clazz instanceof ClassInterfacesType) { if (classType instanceof ClassInterfacesType) {
return ((ClassInterfacesType) clazz).getClassInfo() return ((ClassInterfacesType) classType).getClassInfo()
.superClassOf(codeAnalyzer.getClazz()); .superClassOf(codeAnalyzer.getClazz());
} }
return false; return false;
@ -139,16 +205,20 @@ public final class InvokeOperator extends Operator
public void dumpExpression(TabbedPrintWriter writer, public void dumpExpression(TabbedPrintWriter writer,
Expression[] operands) Expression[] operands)
throws java.io.IOException { throws java.io.IOException {
boolean opIsThis = boolean opIsThis = !staticFlag && operands[0] instanceof ThisOperator;
(!staticFlag
&& operands[0] instanceof LocalLoadOperator
&& !codeAnalyzer.getMethod().isStatic()
&& (((LocalLoadOperator) operands[0]).getLocalInfo()
.equals(codeAnalyzer.getParamInfo(0))));
int arg = 1; int arg = 1;
if (isConstructor()) {
ClassInfo outer = getOuterClass();
if (outer != null) {
operands[arg++].dumpExpression(writer, 0);
writer.print(".");
}
}
if (specialFlag) { if (specialFlag) {
if (opIsThis) { if (opIsThis
&& (((ThisOperator)operands[0]).getClassInfo()
== codeAnalyzer.getClazz())) {
if (isThis()) { if (isThis()) {
/* XXX check if this is a private or final method. */ /* XXX check if this is a private or final method. */
} else { } else {
@ -159,29 +229,42 @@ public final class InvokeOperator extends Operator
} }
} else { } else {
/* XXX check if this is a private or final method. */ /* XXX check if this is a private or final method. */
int minPriority = 950; /* field access */
if (!isThis()) { if (!isThis()) {
writer.print("(NON VIRTUAL "); writer.print("(NON VIRTUAL ");
writer.printType(clazz); writer.printType(classType);
writer.print(")"); writer.print(")");
minPriority = 700;
} }
operands[0].dumpExpression(writer, 950); operands[0].dumpExpression(writer, minPriority);
} }
} else if (staticFlag) { } else if (staticFlag) {
arg = 0; arg = 0;
if (isThis()) Scope scope = writer.getScope(getClassInfo(),
Scope.CLASSSCOPE);
if (scope != null
&& !writer.conflicts(methodName, scope, Scope.METHODNAME))
opIsThis = true; opIsThis = true;
else else
writer.printType(clazz); writer.printType(classType);
} else { } else {
if (!opIsThis) { if (opIsThis) {
int minPriority = 950; /* field access */ ThisOperator thisOp = (ThisOperator) operands[0];
Scope scope = writer.getScope(thisOp.getClassInfo(),
Scope.CLASSSCOPE);
if (writer.conflicts(methodName, scope, Scope.METHODNAME)) {
thisOp.dumpExpression(writer, 950);
writer.print(".");
}
} else {
if (operands[0].getType() instanceof NullType) { if (operands[0].getType() instanceof NullType) {
writer.print("("); writer.print("((");
writer.printType(clazz); writer.printType(classType);
writer.print(") "); writer.print(") ");
minPriority = 700; operands[0].dumpExpression(writer, 700);
} writer.print(")");
operands[0].dumpExpression(writer, minPriority); } else
operands[0].dumpExpression(writer, 950);
} }
} }
@ -194,9 +277,12 @@ public final class InvokeOperator extends Operator
writer.print(methodName); writer.print(methodName);
} }
writer.print("("); writer.print("(");
for (int i=0; i < methodType.getParameterTypes().length; i++) { boolean first = true;
if (i>0) while (arg < operands.length) {
if (!first)
writer.print(", "); writer.print(", ");
else
first = false;
operands[arg++].dumpExpression(writer, 0); operands[arg++].dumpExpression(writer, 0);
} }
writer.print(")"); writer.print(")");
@ -207,9 +293,12 @@ public final class InvokeOperator extends Operator
* @return true if this is the magic class$ method, false otherwise. * @return true if this is the magic class$ method, false otherwise.
*/ */
public boolean isGetClass() { public boolean isGetClass() {
return isThis() if (isThis()) {
&& codeAnalyzer.getClassAnalyzer() SyntheticAnalyzer synth = getMethodAnalyzer().getSynthetic();
.getMethod(methodName, methodType).isGetClass(); if (synth != null && synth.getKind() == SyntheticAnalyzer.GETCLASS)
return true;
}
return false;
} }
class Environment extends SimpleRuntimeEnvironment { class Environment extends SimpleRuntimeEnvironment {
@ -272,6 +361,56 @@ public final class InvokeOperator extends Operator
return new ConstOperator(result); return new ConstOperator(result);
} }
public Expression simplifyAccess(Expression[] subs) {
if (isOuter()) {
SyntheticAnalyzer synth = getMethodAnalyzer().getSynthetic();
if (synth != null) {
Operator op = null;
switch (synth.getKind()) {
case SyntheticAnalyzer.ACCESSGETFIELD:
op = new GetFieldOperator(codeAnalyzer, false,
synth.getReference());
break;
case SyntheticAnalyzer.ACCESSGETSTATIC:
op = new GetFieldOperator(codeAnalyzer, true,
synth.getReference());
break;
case SyntheticAnalyzer.ACCESSPUTFIELD:
op = new PutFieldOperator(codeAnalyzer, false,
synth.getReference());
break;
case SyntheticAnalyzer.ACCESSPUTSTATIC:
op = new PutFieldOperator(codeAnalyzer, true,
synth.getReference());
break;
case SyntheticAnalyzer.ACCESSMETHOD:
op = new InvokeOperator(codeAnalyzer, false,
false, synth.getReference());
break;
case SyntheticAnalyzer.ACCESSSTATICMETHOD:
op = new InvokeOperator(codeAnalyzer, true,
false, synth.getReference());
break;
}
if (op != null) {
if (subs == null)
return op;
return new ComplexExpression(op, subs);
}
}
}
return null;
}
public Expression simplify() {
Expression expr = simplifyAccess(null);
if (expr != null)
return expr.simplify();
return super.simplify();
}
/* Invokes never equals: they may return different values even if /* Invokes never equals: they may return different values even if
* they have the same parameters. * they have the same parameters.
*/ */

Loading…
Cancel
Save