better handling of anonymous classes

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@869 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent 5dda632277
commit b562c98f05
  1. 184
      jode/jode/expr/ConstructorOperator.java

@ -43,7 +43,6 @@ public class ConstructorOperator extends Operator
MethodType methodType; MethodType methodType;
Type classType; Type classType;
CodeAnalyzer codeAnalyzer; CodeAnalyzer codeAnalyzer;
boolean removedCheckNull = false;
public ConstructorOperator(Type classType, MethodType methodType, public ConstructorOperator(Type classType, MethodType methodType,
CodeAnalyzer codeAna, boolean isVoid) { CodeAnalyzer codeAna, boolean isVoid) {
@ -113,21 +112,6 @@ public class ConstructorOperator extends Operator
} }
public Expression simplify() { public Expression simplify() {
InnerClassInfo outer = getOuterClassInfo();
if (outer != null && outer.outer != null && outer.name != null
&& !Modifier.isStatic(outer.modifiers)
&& (Decompiler.options & Decompiler.OPTION_INNER) != 0) {
if (subExpressions.length == 0) {
System.err.println("outer: "+outer.outer+","+outer.inner+","+outer.name);
}
if (subExpressions[0] instanceof CheckNullOperator) {
CheckNullOperator cno = (CheckNullOperator) subExpressions[0];
cno.removeLocal();
subExpressions[0] = cno.subExpressions[0];
removedCheckNull = true;
}
}
return super.simplify(); return super.simplify();
} }
@ -138,8 +122,7 @@ public class ConstructorOperator extends Operator
return null; return null;
} }
public InnerClassInfo getOuterClassInfo() { public InnerClassInfo getOuterClassInfo(ClassInfo ci) {
ClassInfo ci = getClassInfo();
if (ci != null && ci.getName().indexOf('$') >= 0) { if (ci != null && ci.getName().indexOf('$') >= 0) {
InnerClassInfo[] outers = ci.getOuterClasses(); InnerClassInfo[] outers = ci.getOuterClasses();
if (outers != null) if (outers != null)
@ -151,9 +134,9 @@ public class ConstructorOperator extends Operator
public void checkAnonymousClasses() { public void checkAnonymousClasses() {
if ((Decompiler.options & Decompiler.OPTION_ANON) == 0) if ((Decompiler.options & Decompiler.OPTION_ANON) == 0)
return; return;
InnerClassInfo outer = getOuterClassInfo();
if (outer != null && (outer.outer == null || outer.name == null)) {
ClassInfo clazz = getClassInfo(); ClassInfo clazz = getClassInfo();
InnerClassInfo outer = getOuterClassInfo(clazz);
if (outer != null && (outer.outer == null || outer.name == null)) {
codeAnalyzer.addAnonymousConstructor(this); codeAnalyzer.addAnonymousConstructor(this);
if (outer.name == null) { if (outer.name == null) {
@ -165,90 +148,155 @@ public class ConstructorOperator extends Operator
} }
} }
/**
* We add the named method scoped classes to the declarables, and
* only fillDeclarables on the parameters we will print.
*/
///#ifdef JDK12 ///#ifdef JDK12
/// public void fillDeclarables(Set used) { /// public void fillDeclarables(Set used) {
///#else ///#else
public void fillDeclarables(SimpleSet used) { public void fillDeclarables(SimpleSet used) {
///#endif ///#endif
if ((Decompiler.options & Decompiler.OPTION_ANON) == 0) ClassInfo clazz = getClassInfo();
return; InnerClassInfo outer = getOuterClassInfo(clazz);
InnerClassInfo outer = getOuterClassInfo(); ClassAnalyzer anonymousClass = null;
if (outer != null && outer.outer == null && outer.name != null) { int arg = 0;
ClassAnalyzer anonymousClass int length = subExpressions.length;
= codeAnalyzer.getAnonymousClass(getClassInfo()); boolean jikesAnonymousInner = false;
if ((Decompiler.options & Decompiler.OPTION_ANON) != 0
&& outer != null && (outer.outer == null || outer.name == null)) {
anonymousClass = codeAnalyzer.getAnonymousClass(clazz);
if (outer.name != null) {
/* This is a named method scope class, declare it */
used.add(anonymousClass); used.add(anonymousClass);
} else {
/* This is an anonymous class */
ClassInfo superClazz = clazz.getSuperclass();
ClassInfo[] interfaces = clazz.getInterfaces();
if (interfaces.length == 1
&& (superClazz == null
|| superClazz == ClassInfo.javaLangObject)) {
clazz = interfaces[0];
} else {
clazz = (superClazz != null
? superClazz : ClassInfo.javaLangObject);
} }
outer = getOuterClassInfo(clazz);
arg += anonymousClass.getOuterValues().length;
jikesAnonymousInner = anonymousClass.isJikesAnonymousInner();
} }
public void dumpExpression(TabbedPrintWriter writer)
throws java.io.IOException {
int arg = 0;
Type object = classType;
InnerClassInfo outer = getOuterClassInfo();
if (outer != null && outer.outer != null && outer.name != null
&& !Modifier.isStatic(outer.modifiers)
&& (Decompiler.options & Decompiler.OPTION_INNER) != 0) {
if (subExpressions.length == 0) {
System.err.println("outer: "+outer.outer+","+outer.inner+","+outer.name);
} }
if ((Decompiler.options & Decompiler.OPTION_INNER) != 0
&& outer != null && outer.outer != null && outer.name != null
&& !Modifier.isStatic(outer.modifiers)) {
Expression outExpr = subExpressions[arg++]; Expression outerExpr = jikesAnonymousInner
if (!removedCheckNull && !(outExpr instanceof ThisOperator)) ? subExpressions[--length]
writer.print("MISSING CHECKNULL"); : subExpressions[arg++];
if (outExpr instanceof ThisOperator) { if (outerExpr instanceof CheckNullOperator) {
Scope scope = writer.getScope CheckNullOperator cno = (CheckNullOperator) outerExpr;
(((ThisOperator) outExpr).getClassInfo(), outerExpr = cno.subExpressions[0];
Scope.CLASSSCOPE);
if (writer.conflicts(outer.name, scope, Scope.CLASSNAME)) {
outExpr.dumpExpression(writer, 950);
writer.print(".");
} }
} else { outerExpr.fillDeclarables(used);
int minPriority = 950; /* field access */
if (outExpr.getType() instanceof NullType) {
writer.print("((");
writer.printType(Type.tClass
(ClassInfo.forName(outer.outer)));
writer.print(") ");
outExpr.dumpExpression(writer, 700);
writer.print(")");
} else
outExpr.dumpExpression(writer, 950);
writer.print(".");
} }
for (int i=arg; i < length; i++)
subExpressions[i].fillDeclarables(used);
} }
public void dumpExpression(TabbedPrintWriter writer)
throws java.io.IOException {
int arg = 0;
int length = subExpressions.length;
boolean jikesAnonymousInner = false;
ClassInfo clazz = getClassInfo();
InnerClassInfo outer = getOuterClassInfo(clazz);
ClassAnalyzer anonymousClass = null; ClassAnalyzer anonymousClass = null;
boolean dumpBlock = false; boolean dumpBlock = false;
if ((Decompiler.options & Decompiler.OPTION_ANON) != 0 if ((Decompiler.options &
(Decompiler.OPTION_ANON | Decompiler.OPTION_CONTRAFO)) != 0
&& codeAnalyzer.hasAnalyzedAnonymous() && codeAnalyzer.hasAnalyzedAnonymous()
&& outer != null && (outer.outer == null || outer.name == null)) { && outer != null && (outer.outer == null || outer.name == null)) {
anonymousClass = codeAnalyzer.getAnonymousClass(getClassInfo()); anonymousClass = codeAnalyzer.getAnonymousClass(getClassInfo());
if (anonymousClass.getName() == null) { jikesAnonymousInner = anonymousClass.isJikesAnonymousInner();
if (outer.name == null) {
/* This is an anonymous class */ /* This is an anonymous class */
ClassInfo clazz = anonymousClass.getClazz();
ClassInfo superClazz = clazz.getSuperclass(); ClassInfo superClazz = clazz.getSuperclass();
ClassInfo[] interfaces = clazz.getInterfaces(); ClassInfo[] interfaces = clazz.getInterfaces();
if (interfaces.length == 1 if (interfaces.length == 1
&& (superClazz == null && (superClazz == null
|| superClazz == ClassInfo.javaLangObject)) { || superClazz == ClassInfo.javaLangObject)) {
object = Type.tClass(interfaces[0]); clazz = interfaces[0];
} else { } else {
if (interfaces.length > 0) { if (interfaces.length > 0) {
writer.print("too many supers in ANONYMOUS "); writer.print("too many supers in ANONYMOUS ");
} }
object = (superClazz != null clazz = (superClazz != null
? Type.tClass(superClazz) : Type.tObject); ? superClazz : ClassInfo.javaLangObject);
} }
outer = getOuterClassInfo(clazz);
dumpBlock = true; dumpBlock = true;
if (jikesAnonymousInner
&& outer.outer == null && outer.name != null) {
Expression thisExpr = subExpressions[--length];
if (thisExpr instanceof CheckNullOperator) {
CheckNullOperator cno = (CheckNullOperator) thisExpr;
thisExpr = cno.subExpressions[0];
}
if (!(thisExpr instanceof ThisOperator)
|| (((ThisOperator) thisExpr).getClassInfo()
!= codeAnalyzer.getClazz()))
writer.print("ILLEGAL ANON CONSTR");
}
} }
arg += anonymousClass.getOuterValues().length; arg += anonymousClass.getOuterValues().length;
} }
if (outer != null && outer.outer != null && outer.name != null
&& !Modifier.isStatic(outer.modifiers)
&& (Decompiler.options &
(Decompiler.OPTION_INNER | Decompiler.OPTION_CONTRAFO)) != 0) {
Expression outerExpr = jikesAnonymousInner
? subExpressions[--length]
: subExpressions[arg++];
if (outerExpr instanceof CheckNullOperator) {
CheckNullOperator cno = (CheckNullOperator) outerExpr;
outerExpr = cno.subExpressions[0];
} else if (!(outerExpr instanceof ThisOperator))
if (!jikesAnonymousInner)
// Bug in jikes: it doesn't do a check null.
// We don't complain here.
writer.print("MISSING CHECKNULL ");
if (outerExpr instanceof ThisOperator) {
Scope scope = writer.getScope
(((ThisOperator) outerExpr).getClassInfo(),
Scope.CLASSSCOPE);
if (writer.conflicts(outer.name, scope, Scope.CLASSNAME)) {
outerExpr.dumpExpression(writer, 950);
writer.print(".");
}
} else {
if (outerExpr.getType() instanceof NullType) {
writer.print("((");
writer.printType(Type.tClass
(ClassInfo.forName(outer.outer)));
writer.print(") ");
outerExpr.dumpExpression(writer, 700);
writer.print(")");
} else
outerExpr.dumpExpression(writer, 950);
writer.print(".");
}
}
writer.print("new "); writer.print("new ");
writer.printType(object); writer.printType(Type.tClass(clazz));
writer.print("("); writer.print("(");
for (int i = arg; i < methodType.getParameterTypes().length; i++) { for (int i = arg; i < length; i++) {
if (i>arg) if (i>arg)
writer.print(", "); writer.print(", ");
subExpressions[i].dumpExpression(writer, 0); subExpressions[i].dumpExpression(writer, 0);

Loading…
Cancel
Save