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 25 years ago
parent c0e9183459
commit 93244afa2c
  1. 203
      jode/jode/expr/InvokeOperator.java

@ -18,7 +18,9 @@
*/
package jode.expr;
import jode.Decompiler;
import jode.decompiler.CodeAnalyzer;
import jode.decompiler.MethodAnalyzer;
import jode.decompiler.ClassAnalyzer;
import jode.decompiler.TabbedPrintWriter;
import jode.GlobalOptions;
@ -26,6 +28,7 @@ import jode.bytecode.*;
import jode.jvm.*;
import jode.type.*;
import java.lang.reflect.InvocationTargetException;
import jode.decompiler.Scope;
public final class InvokeOperator extends Operator
implements MatchableOperator {
@ -34,7 +37,7 @@ public final class InvokeOperator extends Operator
boolean specialFlag;
MethodType methodType;
String methodName;
Type clazz;
Type classType;
public InvokeOperator(CodeAnalyzer codeAnalyzer,
boolean staticFlag, boolean specialFlag,
@ -42,13 +45,13 @@ public final class InvokeOperator extends Operator
super(Type.tUnknown, 0);
this.methodType = (MethodType) Type.tType(reference.getType());
this.methodName = reference.getName();
this.clazz = Type.tType(reference.getClazz());
this.classType = Type.tType(reference.getClazz());
this.type = methodType.getReturnType();
this.codeAnalyzer = codeAnalyzer;
this.staticFlag = staticFlag;
this.specialFlag = specialFlag;
if (staticFlag)
codeAnalyzer.useType(clazz);
codeAnalyzer.useType(classType);
}
/**
@ -83,7 +86,7 @@ public final class InvokeOperator extends Operator
}
public Type getClassType() {
return clazz;
return classType;
}
public int getPriority() {
@ -111,26 +114,89 @@ public final class InvokeOperator extends Operator
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.
* @XXX check, if this class implements the method and if not
* allow super class
*/
public boolean isThis() {
if (clazz instanceof ClassInterfacesType) {
return ((ClassInterfacesType) clazz).getClassInfo()
== codeAnalyzer.getClazz();
return 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;
}
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.
* @XXX check, if its the first super class that implements the method.
*/
public boolean isSuperOrThis() {
if (clazz instanceof ClassInterfacesType) {
return ((ClassInterfacesType) clazz).getClassInfo()
if (classType instanceof ClassInterfacesType) {
return ((ClassInterfacesType) classType).getClassInfo()
.superClassOf(codeAnalyzer.getClazz());
}
return false;
@ -139,16 +205,20 @@ public final class InvokeOperator extends Operator
public void dumpExpression(TabbedPrintWriter writer,
Expression[] operands)
throws java.io.IOException {
boolean opIsThis =
(!staticFlag
&& operands[0] instanceof LocalLoadOperator
&& !codeAnalyzer.getMethod().isStatic()
&& (((LocalLoadOperator) operands[0]).getLocalInfo()
.equals(codeAnalyzer.getParamInfo(0))));
boolean opIsThis = !staticFlag && operands[0] instanceof ThisOperator;
int arg = 1;
if (isConstructor()) {
ClassInfo outer = getOuterClass();
if (outer != null) {
operands[arg++].dumpExpression(writer, 0);
writer.print(".");
}
}
if (specialFlag) {
if (opIsThis) {
if (opIsThis
&& (((ThisOperator)operands[0]).getClassInfo()
== codeAnalyzer.getClazz())) {
if (isThis()) {
/* XXX check if this is a private or final method. */
} else {
@ -159,29 +229,42 @@ public final class InvokeOperator extends Operator
}
} else {
/* XXX check if this is a private or final method. */
int minPriority = 950; /* field access */
if (!isThis()) {
writer.print("(NON VIRTUAL ");
writer.printType(clazz);
writer.printType(classType);
writer.print(")");
minPriority = 700;
}
operands[0].dumpExpression(writer, 950);
operands[0].dumpExpression(writer, minPriority);
}
} else if (staticFlag) {
arg = 0;
if (isThis())
Scope scope = writer.getScope(getClassInfo(),
Scope.CLASSSCOPE);
if (scope != null
&& !writer.conflicts(methodName, scope, Scope.METHODNAME))
opIsThis = true;
else
writer.printType(clazz);
writer.printType(classType);
} else {
if (!opIsThis) {
int minPriority = 950; /* field access */
if (opIsThis) {
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) {
writer.print("(");
writer.printType(clazz);
writer.print("((");
writer.printType(classType);
writer.print(") ");
minPriority = 700;
}
operands[0].dumpExpression(writer, minPriority);
operands[0].dumpExpression(writer, 700);
writer.print(")");
} else
operands[0].dumpExpression(writer, 950);
}
}
@ -194,9 +277,12 @@ public final class InvokeOperator extends Operator
writer.print(methodName);
}
writer.print("(");
for (int i=0; i < methodType.getParameterTypes().length; i++) {
if (i>0)
boolean first = true;
while (arg < operands.length) {
if (!first)
writer.print(", ");
else
first = false;
operands[arg++].dumpExpression(writer, 0);
}
writer.print(")");
@ -207,9 +293,12 @@ public final class InvokeOperator extends Operator
* @return true if this is the magic class$ method, false otherwise.
*/
public boolean isGetClass() {
return isThis()
&& codeAnalyzer.getClassAnalyzer()
.getMethod(methodName, methodType).isGetClass();
if (isThis()) {
SyntheticAnalyzer synth = getMethodAnalyzer().getSynthetic();
if (synth != null && synth.getKind() == SyntheticAnalyzer.GETCLASS)
return true;
}
return false;
}
class Environment extends SimpleRuntimeEnvironment {
@ -272,6 +361,56 @@ public final class InvokeOperator extends Operator
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
* they have the same parameters.
*/

Loading…
Cancel
Save