diff --git a/jode/jode/expr/ConstructorOperator.java b/jode/jode/expr/ConstructorOperator.java index 60da3e9..1b3446a 100644 --- a/jode/jode/expr/ConstructorOperator.java +++ b/jode/jode/expr/ConstructorOperator.java @@ -19,25 +19,41 @@ package jode.expr; import jode.type.Type; +import jode.type.NullType; +import jode.type.ClassInterfacesType; import jode.type.MethodType; +import jode.bytecode.ClassInfo; +import jode.bytecode.InnerClassInfo; +import jode.Decompiler; +import jode.decompiler.CodeAnalyzer; +import jode.decompiler.ClassAnalyzer; import jode.decompiler.TabbedPrintWriter; +import jode.decompiler.Scope; public class ConstructorOperator extends Operator implements MatchableOperator { MethodType methodType; Type classType; - - public ConstructorOperator(Type type, MethodType methodType, - boolean isVoid) { - super(isVoid ? Type.tVoid : type, 0); - this.classType = type; - this.methodType = methodType; + CodeAnalyzer codeAnalyzer; + ClassAnalyzer anonymousClass = null; + boolean removedCheckNull = false; + + public ConstructorOperator(InvokeOperator invoke, boolean isVoid) { + super(isVoid ? Type.tVoid : invoke.getClassType(), 0); + this.classType = invoke.getClassType(); + this.methodType = invoke.getMethodType(); + this.codeAnalyzer = invoke.codeAnalyzer; + checkAnonymousClasses(); } public MethodType getMethodType() { return methodType; } + public CodeAnalyzer getCodeAnalyzer() { + return codeAnalyzer; + } + /** * Checks if the value of the given expression can change, due to * side effects in this expression. If this returns false, the @@ -85,14 +101,84 @@ public class ConstructorOperator extends Operator ? EMPTYSTRING : null; } + public ClassInfo getClassInfo() { + if (classType instanceof ClassInterfacesType) { + return ((ClassInterfacesType) classType).getClassInfo(); + } + return null; + } + + public InnerClassInfo getOuterClassInfo() { + ClassInfo ci = getClassInfo(); + if (ci != null && ci.getName().indexOf('$') >= 0) { + InnerClassInfo[] outers = ci.getOuterClasses(); + if (outers != null) + return outers[0]; + } + return null; + } + + public void checkAnonymousClasses() { + if ((Decompiler.options & Decompiler.OPTION_ANON) == 0) + return; + InnerClassInfo outer = getOuterClassInfo(); + if (outer != null && outer.outer == null) { + ClassInfo clazz = getClassInfo(); + anonymousClass = codeAnalyzer.addAnonymousClass(clazz); + + if (anonymousClass.getName() == null) { + if (clazz.getInterfaces().length > 0) + type = Type.tClass(clazz.getInterfaces()[0]); + else + type = Type.tClass(clazz.getSuperclass()); + } + } + } + public void dumpExpression(TabbedPrintWriter writer, Expression[] operands) throws java.io.IOException { + + int arg = 0; + if (anonymousClass != null) { + writer.print("new "); + anonymousClass.dumpSource(writer); + return; + } + InnerClassInfo outer = getOuterClassInfo(); + if (outer != null && outer.name != null) { + Expression outExpr = operands[arg++]; + if (!removedCheckNull && !(outExpr instanceof ThisOperator)) + writer.print("MISSING CHECKNULL"); + if (outExpr instanceof ThisOperator) { + Scope scope = writer.getScope + (((ThisOperator) outExpr).getClassInfo(), + Scope.CLASSSCOPE); + if (writer.conflicts(outer.name, scope, Scope.CLASSNAME)) { + outExpr.dumpExpression(writer, 950); + writer.print("."); + } + } else { + int minPriority = 950; /* field access */ + if (outExpr.getType() instanceof NullType) { + writer.print("(("); + writer.printType(classType); + writer.print(") "); + outExpr.dumpExpression(writer, 700); + writer.print(")"); + } else + outExpr.dumpExpression(writer, 950); + writer.print("."); + } + } writer.print("new "); - writer.printType(classType); + if (outer != null && outer.name != null) + writer.print(outer.name); + else + writer.printType(classType); writer.print("("); - for (int i=0; i < methodType.getParameterTypes().length; i++) { - if (i>0) + for (int i = arg; i < methodType.getParameterTypes().length; i++) { + if (i>arg) writer.print(", "); operands[i].dumpExpression(writer, 0); }