Decompiler, JodeApplet and JodeWindow moved into decompile package

makeDeclaration now transmits the done set over class borders


git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@1202 379699f6-c40d-0410-875b-85095c16579e
branch_1_1
jochen 25 years ago
parent c5b840847b
commit 915439b1ff
  1. 4
      jode/jode/expr/Expression.java.in
  2. 26
      jode/jode/expr/FieldOperator.java.in
  3. 154
      jode/jode/expr/InvokeOperator.java.in
  4. 10
      jode/jode/expr/Operator.java.in
  5. 5
      jode/jode/expr/StoreInstruction.java
  6. 16
      jode/jode/flow/FlowBlock.java.in
  7. 15
      jode/jode/flow/IfThenElseBlock.java.in
  8. 16
      jode/jode/flow/InstructionContainer.java.in
  9. 50
      jode/jode/flow/LoopBlock.java.in
  10. 1
      jode/jode/flow/SpecialBlock.java
  11. 50
      jode/jode/flow/StructuredBlock.java.in
  12. 12
      jode/jode/flow/TransformConstructors.java

@ -23,6 +23,7 @@ import jode.GlobalOptions;
import jode.decompiler.TabbedPrintWriter; import jode.decompiler.TabbedPrintWriter;
import @COLLECTIONS@.Collection; import @COLLECTIONS@.Collection;
import @COLLECTIONS@.Set;
public abstract class Expression { public abstract class Expression {
protected Type type; protected Type type;
@ -230,6 +231,9 @@ public abstract class Expression {
public void fillDeclarables(Collection used) { public void fillDeclarables(Collection used) {
} }
public void makeDeclaration(Set done) {
}
public abstract void dumpExpression(TabbedPrintWriter writer) public abstract void dumpExpression(TabbedPrintWriter writer)
throws java.io.IOException; throws java.io.IOException;

@ -29,9 +29,9 @@ import jode.decompiler.MethodAnalyzer;
import jode.decompiler.ClassAnalyzer; import jode.decompiler.ClassAnalyzer;
import jode.decompiler.MethodAnalyzer; import jode.decompiler.MethodAnalyzer;
import jode.decompiler.FieldAnalyzer; import jode.decompiler.FieldAnalyzer;
import jode.decompiler.Options;
import jode.decompiler.TabbedPrintWriter; import jode.decompiler.TabbedPrintWriter;
import jode.decompiler.Scope; import jode.decompiler.Scope;
import jode.Decompiler;
import @COLLECTIONS@.Collection; import @COLLECTIONS@.Collection;
@ -157,21 +157,19 @@ public abstract class FieldOperator extends Operator {
InnerClassInfo outer = getOuterClassInfo(clazz); InnerClassInfo outer = getOuterClassInfo(clazz);
ClassAnalyzer clazzAna = methodAnalyzer.getClassAnalyzer(clazz); ClassAnalyzer clazzAna = methodAnalyzer.getClassAnalyzer(clazz);
if ((Decompiler.options & Decompiler.OPTION_ANON) != 0 if ((Options.options & Options.OPTION_ANON) != 0
&& outer != null && outer.outer == null && outer.name != null
&& clazzAna != null && clazzAna != null
&& outer != null && (outer.outer == null || outer.name == null)) { && clazzAna.getParent() == methodAnalyzer) {
if (outer.name != null) { /* This is a named method scope class, declare it.
if (clazzAna.getParent() == methodAnalyzer) { * But first declare all method scoped classes,
/* This is a named method scope class, declare it. * that are used inside; order does matter.
* But first declare all method scoped classes, */
* that are used inside; order does matter. clazzAna.fillDeclarables(used);
*/ used.add(clazzAna);
clazzAna.fillDeclarables(used);
used.add(clazzAna);
}
}
} }
super.fillDeclarables(used);
} }
public void dumpExpression(TabbedPrintWriter writer) public void dumpExpression(TabbedPrintWriter writer)

@ -20,17 +20,17 @@
package jode.expr; package jode.expr;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import jode.Decompiler;
import jode.decompiler.MethodAnalyzer; import jode.decompiler.MethodAnalyzer;
import jode.decompiler.MethodAnalyzer; import jode.decompiler.MethodAnalyzer;
import jode.decompiler.ClassAnalyzer; import jode.decompiler.ClassAnalyzer;
import jode.decompiler.TabbedPrintWriter; import jode.decompiler.TabbedPrintWriter;
import jode.decompiler.Options;
import jode.decompiler.OuterValues; import jode.decompiler.OuterValues;
import jode.decompiler.Scope;
import jode.GlobalOptions; import jode.GlobalOptions;
import jode.bytecode.*; import jode.bytecode.*;
import jode.jvm.*; import jode.jvm.*;
import jode.type.*; import jode.type.*;
import jode.decompiler.Scope;
import jode.util.SimpleMap; import jode.util.SimpleMap;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
@ -39,6 +39,7 @@ import @COLLECTIONS@.Collections;
import @COLLECTIONS@.Collection; import @COLLECTIONS@.Collection;
import @COLLECTIONS@.Map; import @COLLECTIONS@.Map;
import @COLLECTIONS@.Iterator; import @COLLECTIONS@.Iterator;
import @COLLECTIONS@.Set;
public final class InvokeOperator extends Operator public final class InvokeOperator extends Operator
implements MatchableOperator { implements MatchableOperator {
@ -175,7 +176,7 @@ public final class InvokeOperator extends Operator
public void checkAnonymousClasses() { public void checkAnonymousClasses() {
if (methodFlag != CONSTRUCTOR if (methodFlag != CONSTRUCTOR
|| (Decompiler.options & Decompiler.OPTION_ANON) == 0) || (Options.options & Options.OPTION_ANON) == 0)
return; return;
InnerClassInfo outer = getOuterClassInfo(getClassInfo()); InnerClassInfo outer = getOuterClassInfo(getClassInfo());
if (outer != null && (outer.outer == null || outer.name == null)) { if (outer != null && (outer.outer == null || outer.name == null)) {
@ -251,8 +252,8 @@ public final class InvokeOperator extends Operator
* inside the same base class as the caller class, null otherwise. * inside the same base class as the caller class, null otherwise.
*/ */
public ClassAnalyzer getClassAnalyzer() { public ClassAnalyzer getClassAnalyzer() {
if ((Decompiler.options & if ((Options.options &
(Decompiler.OPTION_ANON | Decompiler.OPTION_INNER)) == 0) (Options.OPTION_ANON | Options.OPTION_INNER)) == 0)
return null; return null;
ClassInfo callee = getClassInfo(); ClassInfo callee = getClassInfo();
@ -261,7 +262,7 @@ public final class InvokeOperator extends Operator
int nested = 0; int nested = 0;
InnerClassInfo[] outers = callee.getOuterClasses(); InnerClassInfo[] outers = callee.getOuterClasses();
if ((Decompiler.options & Decompiler.OPTION_INNER) != 0 if ((Options.options & Options.OPTION_INNER) != 0
&& outers != null) { && outers != null) {
/* If the callee class is an inner class we take its /* If the callee class is an inner class we take its
* (outermost) parent instead. This will assure that we * (outermost) parent instead. This will assure that we
@ -288,12 +289,12 @@ public final class InvokeOperator extends Operator
if (ana.getParent() == null) if (ana.getParent() == null)
return null; return null;
if (ana.getParent() instanceof MethodAnalyzer if (ana.getParent() instanceof MethodAnalyzer
&& (Decompiler.options & Decompiler.OPTION_ANON) != 0) && (Options.options & Options.OPTION_ANON) != 0)
ana = ((MethodAnalyzer) ana.getParent()) ana = ((MethodAnalyzer) ana.getParent())
.getClassAnalyzer(); .getClassAnalyzer();
else if (ana.getParent() instanceof ClassAnalyzer else if (ana.getParent() instanceof ClassAnalyzer
&& (Decompiler.options && (Options.options
& Decompiler.OPTION_INNER) != 0) & Options.OPTION_INNER) != 0)
ana = (ClassAnalyzer) ana.getParent(); ana = (ClassAnalyzer) ana.getParent();
else else
throw new jode.AssertError throw new jode.AssertError
@ -325,12 +326,12 @@ public final class InvokeOperator extends Operator
if (ana.getParent() == null) if (ana.getParent() == null)
break; break;
if (ana.getParent() instanceof MethodAnalyzer if (ana.getParent() instanceof MethodAnalyzer
&& (Decompiler.options & Decompiler.OPTION_ANON) != 0) && (Options.options & Options.OPTION_ANON) != 0)
ana = ((MethodAnalyzer) ana.getParent()) ana = ((MethodAnalyzer) ana.getParent())
.getClassAnalyzer(); .getClassAnalyzer();
else if (ana.getParent() instanceof ClassAnalyzer else if (ana.getParent() instanceof ClassAnalyzer
&& (Decompiler.options && (Options.options
& Decompiler.OPTION_INNER) != 0) & Options.OPTION_INNER) != 0)
ana = (ClassAnalyzer) ana.getParent(); ana = (ClassAnalyzer) ana.getParent();
else else
throw new jode.AssertError throw new jode.AssertError
@ -367,7 +368,7 @@ public final class InvokeOperator extends Operator
} }
public boolean isConstant() { public boolean isConstant() {
if ((Decompiler.options & Decompiler.OPTION_ANON) == 0) if ((Options.options & Options.OPTION_ANON) == 0)
return super.isConstant(); return super.isConstant();
ClassInfo clazz = getClassInfo(); ClassInfo clazz = getClassInfo();
@ -545,7 +546,7 @@ public final class InvokeOperator extends Operator
result.addOperand(right); result.addOperand(right);
result.addOperand(subExpressions[0].simplify()); result.addOperand(subExpressions[0].simplify());
} }
else if ((Decompiler.options & Decompiler.OPTION_DECRYPT) != 0 else if ((Options.options & Options.OPTION_DECRYPT) != 0
&& isThis() && isStatic() && isThis() && isStatic()
&& methodType.getParameterTypes().length == 1 && methodType.getParameterTypes().length == 1
&& methodType.getParameterTypes()[0].equals(Type.tString) && methodType.getParameterTypes()[0].equals(Type.tString)
@ -700,63 +701,68 @@ public final class InvokeOperator extends Operator
InnerClassInfo outer = getOuterClassInfo(clazz); InnerClassInfo outer = getOuterClassInfo(clazz);
ClassAnalyzer clazzAna = methodAnalyzer.getClassAnalyzer(clazz); ClassAnalyzer clazzAna = methodAnalyzer.getClassAnalyzer(clazz);
if ((Options.options & Options.OPTION_ANON) != 0
&& outer != null && outer.outer == null && outer.name != null
&& clazzAna != null
&& clazzAna.getParent() == methodAnalyzer) {
/* This is a named method scope class, declare it.
* But first declare all method scoped classes,
* that are used inside; order does matter.
*/
clazzAna.fillDeclarables(used);
used.add(clazzAna);
}
if (!isConstructor() || isStatic()) {
super.fillDeclarables(used);
return;
}
int arg = 1; int arg = 1;
int length = subExpressions.length; int length = subExpressions.length;
boolean jikesAnonymousInner = false; boolean jikesAnonymousInner = false;
if ((Decompiler.options & Decompiler.OPTION_ANON) != 0 if ((Options.options & Options.OPTION_ANON) != 0
&& clazzAna != null && clazzAna != null
&& outer != null && (outer.outer == null || outer.name == null)) { && outer != null && (outer.outer == null || outer.name == null)) {
if (outer.name != null) {
if (clazzAna.getParent() == methodAnalyzer) {
/* This is a named method scope class, declare it.
* But first declare all method scoped classes,
* that are used inside; order does matter.
*/
clazzAna.fillDeclarables(used);
used.add(clazzAna);
}
}
if (isConstructor()) {
OuterValues ov = clazzAna.getOuterValues();
arg += ov.getCount();
jikesAnonymousInner = ov.isJikesAnonymousInner();
for (int i=1; i< arg; i++) { OuterValues ov = clazzAna.getOuterValues();
Expression expr = subExpressions[i]; arg += ov.getCount();
if (expr instanceof CheckNullOperator) { jikesAnonymousInner = ov.isJikesAnonymousInner();
CheckNullOperator cno = (CheckNullOperator) expr;
for (int i=1; i< arg; i++) {
Expression expr = subExpressions[i];
if (expr instanceof CheckNullOperator) {
CheckNullOperator cno = (CheckNullOperator) expr;
expr = cno.subExpressions[0]; expr = cno.subExpressions[0];
}
expr.fillDeclarables(used);
} }
expr.fillDeclarables(used);
if (outer.name == null) { }
/* This is an anonymous class */
ClassInfo superClazz = clazz.getSuperclass(); if (outer.name == null) {
ClassInfo[] interfaces = clazz.getInterfaces(); /* This is an anonymous class */
if (interfaces.length == 1 ClassInfo superClazz = clazz.getSuperclass();
&& (superClazz == null ClassInfo[] interfaces = clazz.getInterfaces();
|| superClazz == ClassInfo.javaLangObject)) { if (interfaces.length == 1
clazz = interfaces[0]; && (superClazz == null
} else { || superClazz == ClassInfo.javaLangObject)) {
clazz = (superClazz != null clazz = interfaces[0];
? superClazz : ClassInfo.javaLangObject); } else {
} clazz = (superClazz != null
outer = getOuterClassInfo(clazz); ? superClazz : ClassInfo.javaLangObject);
} }
outer = getOuterClassInfo(clazz);
} }
} }
if (isConstructor()
&& (Decompiler.options & Decompiler.OPTION_INNER) != 0 if ((Options.options & Options.OPTION_INNER) != 0
&& outer != null && outer.outer != null && outer.name != null && outer != null && outer.outer != null && outer.name != null
&& !Modifier.isStatic(outer.modifiers)) { && !Modifier.isStatic(outer.modifiers)) {
Expression outerExpr = jikesAnonymousInner Expression outerExpr = jikesAnonymousInner
? subExpressions[--length] ? subExpressions[--length]
: subExpressions[arg++]; : subExpressions[arg++];
if (outerExpr instanceof CheckNullOperator) { if (outerExpr instanceof CheckNullOperator) {
CheckNullOperator cno = (CheckNullOperator) outerExpr; CheckNullOperator cno = (CheckNullOperator) outerExpr;
outerExpr = cno.subExpressions[0]; outerExpr = cno.subExpressions[0];
@ -767,6 +773,27 @@ public final class InvokeOperator extends Operator
subExpressions[i].fillDeclarables(used); subExpressions[i].fillDeclarables(used);
} }
/**
* We add the named method scoped classes to the declarables, and
* only fillDeclarables on the parameters we will print.
*/
public void makeDeclaration(Set done) {
super.makeDeclaration(done);
if (isConstructor() && !isStatic()
&& (Options.options & Options.OPTION_ANON) != 0) {
ClassInfo clazz = getClassInfo();
InnerClassInfo outer = getOuterClassInfo(clazz);
ClassAnalyzer clazzAna = methodAnalyzer.getClassAnalyzer(clazz);
if (clazzAna != null && outer != null && outer.name == null) {
/* call makeDeclaration on the anonymous class, since
* _we_ will declare the anonymous class. */
clazzAna.makeDeclaration(done);
}
}
}
/* 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.
*/ */
@ -798,8 +825,8 @@ public final class InvokeOperator extends Operator
if (outer != null && outer.name == null) if (outer != null && outer.name == null)
anonymousNew = true; anonymousNew = true;
clazzAna = methodAnalyzer.getClassAnalyzer(clazz); clazzAna = methodAnalyzer.getClassAnalyzer(clazz);
if ((~Decompiler.options & if ((~Options.options &
(Decompiler.OPTION_ANON | Decompiler.OPTION_CONTRAFO)) == 0 (Options.OPTION_ANON | Options.OPTION_CONTRAFO)) == 0
&& clazzAna != null && clazzAna != null
&& outer != null && outer != null
&& (outer.outer == null || outer.name == null)) { && (outer.outer == null || outer.name == null)) {
@ -846,9 +873,9 @@ public final class InvokeOperator extends Operator
*/ */
if (outer != null && outer.outer != null && outer.name != null if (outer != null && outer.outer != null && outer.name != null
&& !Modifier.isStatic(outer.modifiers) && !Modifier.isStatic(outer.modifiers)
&& (~Decompiler.options & && (~Options.options &
(Decompiler.OPTION_INNER (Options.OPTION_INNER
| Decompiler.OPTION_CONTRAFO)) == 0) { | Options.OPTION_CONTRAFO)) == 0) {
Expression outerExpr = jikesAnonymousInner Expression outerExpr = jikesAnonymousInner
? subExpressions[--length] ? subExpressions[--length]
@ -914,10 +941,7 @@ public final class InvokeOperator extends Operator
break; break;
} }
case SPECIAL: case SPECIAL:
if (subExpressions[0] instanceof ThisOperator if (isSuperOrThis()) {
&& (((ThisOperator)subExpressions[0]).getClassInfo()
== methodAnalyzer.getClazz())) {
if (!isThis()) { if (!isThis()) {
/* We don't have to check if this is the real super /* We don't have to check if this is the real super
* class, as long as ACC_SUPER is set. * class, as long as ACC_SUPER is set.

@ -23,6 +23,7 @@ import jode.GlobalOptions;
import jode.decompiler.TabbedPrintWriter; import jode.decompiler.TabbedPrintWriter;
import @COLLECTIONS@.Collection; import @COLLECTIONS@.Collection;
import @COLLECTIONS@.Set;
public abstract class Operator extends Expression { public abstract class Operator extends Expression {
/* Don't reorder these constants unless you know what you are doing! */ /* Don't reorder these constants unless you know what you are doing! */
@ -172,13 +173,16 @@ public abstract class Operator extends Expression {
} }
public void fillDeclarables(Collection used) { public void fillDeclarables(Collection used) {
if (this instanceof LocalVarOperator) {
used.add(((LocalVarOperator) this).getLocalInfo());
}
for (int i=0; i< subExpressions.length; i++) for (int i=0; i< subExpressions.length; i++)
subExpressions[i].fillDeclarables(used); subExpressions[i].fillDeclarables(used);
} }
public void makeDeclaration(Set done) {
for (int i=0; i< subExpressions.length; i++)
subExpressions[i].makeDeclaration(done);
}
/** /**
* Checks if the value of the given expression can change, due to * Checks if the value of the given expression can change, due to
* side effects in this expression. If this returns false, the * side effects in this expression. If this returns false, the

@ -89,8 +89,9 @@ public class StoreInstruction extends Operator
ConstOperator one = (ConstOperator) subExpressions[1]; ConstOperator one = (ConstOperator) subExpressions[1];
if ((getOperatorIndex() == OPASSIGN_OP+ADD_OP || if ((getOperatorIndex() == OPASSIGN_OP+ADD_OP ||
getOperatorIndex() == OPASSIGN_OP+SUB_OP) && getOperatorIndex() == OPASSIGN_OP+SUB_OP)
((Number)one.getValue()).doubleValue() == 1.0) { && one.getValue() instanceof Number
&& ((Number)one.getValue()).doubleValue() == 1.0) {
int op = (getOperatorIndex() == OPASSIGN_OP+ADD_OP) int op = (getOperatorIndex() == OPASSIGN_OP+ADD_OP)
? INC_OP : DEC_OP; ? INC_OP : DEC_OP;

@ -1612,23 +1612,13 @@ public class FlowBlock {
/** /**
* Make declarations. It will determine, where in each block the * Make declarations. It will determine, where in each block the
* * variables and method scoped classes must be declared.
*/ */
public void makeDeclaration() { public void makeDeclaration(Set done) {
block.propagateUsage(); block.propagateUsage();
Set done = new SimpleSet();
done.addAll(in);
block.makeDeclaration(done); block.makeDeclaration(done);
if (nextByAddr != null) if (nextByAddr != null)
nextByAddr.makeDeclaration(); nextByAddr.makeDeclaration(done);
}
/**
* Make declarations. It will determine, where in each block the
*
*/
public void makeDeclaration(LocalInfo[] param) {
makeDeclaration();
} }
/** /**

@ -140,6 +140,21 @@ public class IfThenElseBlock extends StructuredBlock {
return used; return used;
} }
/**
* Make the declarations, i.e. initialize the declare variable
* to correct values. This will declare every variable that
* is marked as used, but not done.<br>
*
* This will now also combine locals, that use the same slot, have
* compatible types and are declared in the same block. <br>
*
* @param done The set of the already declare variables.
*/
public void makeDeclaration(Set done) {
cond.makeDeclaration(done);
super.makeDeclaration(done);
}
/** /**
* Print the source code for this structured block. This may be * Print the source code for this structured block. This may be
* called only once, because it remembers which local variables * called only once, because it remembers which local variables

@ -44,6 +44,22 @@ public abstract class InstructionContainer extends StructuredBlock {
setJump(jump); setJump(jump);
} }
/**
* Make the declarations, i.e. initialize the declare variable
* to correct values. This will declare every variable that
* is marked as used, but not done.<br>
*
* This will now also combine locals, that use the same slot, have
* compatible types and are declared in the same block. <br>
*
* @param done The set of the already declare variables.
*/
public void makeDeclaration(Set done) {
if (instr != null)
instr.makeDeclaration(done);
super.makeDeclaration(done);
}
/** /**
* This method should remove local variables that are only written * This method should remove local variables that are only written
* and read one time directly after another. <br> * and read one time directly after another. <br>

@ -199,6 +199,28 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
this.type = type; this.type = type;
} }
/**
* Replaces the given sub block with a new block.
* @param oldBlock the old sub block.
* @param newBlock the new sub block.
* @return false, if oldBlock wasn't a direct sub block.
*/
public boolean replaceSubBlock(StructuredBlock oldBlock,
StructuredBlock newBlock) {
if (bodyBlock == oldBlock)
bodyBlock = newBlock;
else
return false;
return true;
}
/**
* Returns all sub block of this structured block.
*/
public StructuredBlock[] getSubBlocks() {
return new StructuredBlock[] { bodyBlock };
}
/** /**
* Remove all variables from set, that we can declare inside the * Remove all variables from set, that we can declare inside the
* loop-block. This is the initializer for for-blocks. * loop-block. This is the initializer for for-blocks.
@ -225,28 +247,6 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
return used; return used;
} }
/**
* Replaces the given sub block with a new block.
* @param oldBlock the old sub block.
* @param newBlock the new sub block.
* @return false, if oldBlock wasn't a direct sub block.
*/
public boolean replaceSubBlock(StructuredBlock oldBlock,
StructuredBlock newBlock) {
if (bodyBlock == oldBlock)
bodyBlock = newBlock;
else
return false;
return true;
}
/**
* Returns all sub block of this structured block.
*/
public StructuredBlock[] getSubBlocks() {
return new StructuredBlock[] { bodyBlock };
}
/** /**
* Check if this is an local store instruction to a not yet declared * Check if this is an local store instruction to a not yet declared
* variable. In that case mark this as declaration and return the * variable. In that case mark this as declaration and return the
@ -278,6 +278,12 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
* @param done The set of the already declare variables. * @param done The set of the already declare variables.
*/ */
public void makeDeclaration(Set done) { public void makeDeclaration(Set done) {
if (type == FOR) {
if (initInstr != null)
initInstr.makeDeclaration(done);
incrInstr.makeDeclaration(done);
}
cond.makeDeclaration(done);
super.makeDeclaration(done); super.makeDeclaration(done);
if (type == FOR && initInstr != null) if (type == FOR && initInstr != null)
checkDeclaration(declare); checkDeclaration(declare);

@ -19,7 +19,6 @@
package jode.flow; package jode.flow;
import jode.decompiler.TabbedPrintWriter; import jode.decompiler.TabbedPrintWriter;
import jode.Decompiler;
import jode.expr.*; import jode.expr.*;
/** /**

@ -23,6 +23,7 @@ import jode.GlobalOptions;
import jode.decompiler.TabbedPrintWriter; import jode.decompiler.TabbedPrintWriter;
import jode.decompiler.LocalInfo; import jode.decompiler.LocalInfo;
import jode.decompiler.Declarable; import jode.decompiler.Declarable;
import jode.decompiler.ClassAnalyzer;
import jode.util.SimpleSet; import jode.util.SimpleSet;
import @COLLECTIONS@.Collections; import @COLLECTIONS@.Collections;
@ -464,31 +465,27 @@ public abstract class StructuredBlock {
if (!(previous instanceof LocalInfo)) if (!(previous instanceof LocalInfo))
continue; continue;
LocalInfo prevLocal = (LocalInfo) previous; LocalInfo prevLocal = (LocalInfo) previous;
if (prevLocal.getSlot() == local.getSlot()) { /* We only merge locals living in the same
* method and having the same slot.
/* XXX - I have to think about this... *
* there may be a case where this leads to type errors. * We don't want to merge variables, whose names
* TODO: Give a formal proof ;-) * are not generated by us and differ. And we
* One bad thing that may happen is that the name * don't want to merge special locals that have a
* of prevLocal (it has already a name) doesn't match * constant expression, e.g. this.
* the intersected type. */
* if (prevLocal.getMethodAnalyzer()
* We don't want to merge variables, whose names == local.getMethodAnalyzer()
* are not generated by us and differ. And we && prevLocal.getSlot() == local.getSlot()
* don't want to merge special locals that have a && prevLocal.getType().isOfType(local.getType())
* constant expression, e.g. this. && (prevLocal.isNameGenerated()
*/ || local.isNameGenerated()
if (prevLocal.getType().isOfType(local.getType()) || localName.equals(prevLocal.getName()))
&& (prevLocal.isNameGenerated() && !prevLocal.isFinal()
|| local.isNameGenerated() && !local.isFinal()
|| localName.equals(prevLocal.getName())) && prevLocal.getExpression() == null
&& !prevLocal.isFinal() && local.getExpression() == null) {
&& !local.isFinal() local.combineWith(prevLocal);
&& prevLocal.getExpression() == null continue next_used;
&& local.getExpression() == null) {
local.combineWith(prevLocal);
continue next_used;
}
} }
} }
} }
@ -500,11 +497,14 @@ public abstract class StructuredBlock {
if (declarable.getName().equals(previous.getName())) { if (declarable.getName().equals(previous.getName())) {
/* A name conflict happened. */ /* A name conflict happened. */
declarable.makeNameUnique(); declarable.makeNameUnique();
break;
} }
} }
} }
done.add(declarable); done.add(declarable);
declare.add(declarable); declare.add(declarable);
if (declare instanceof ClassAnalyzer)
((ClassAnalyzer) declare).makeDeclaration(done);
} }
StructuredBlock[] subs = getSubBlocks(); StructuredBlock[] subs = getSubBlocks();
for (int i=0; i<subs.length; i++) for (int i=0; i<subs.length; i++)

@ -20,12 +20,12 @@
package jode.flow; package jode.flow;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import jode.GlobalOptions; import jode.GlobalOptions;
import jode.Decompiler;
import jode.decompiler.Analyzer; import jode.decompiler.Analyzer;
import jode.decompiler.ClassAnalyzer; import jode.decompiler.ClassAnalyzer;
import jode.decompiler.MethodAnalyzer; import jode.decompiler.MethodAnalyzer;
import jode.decompiler.FieldAnalyzer; import jode.decompiler.FieldAnalyzer;
import jode.decompiler.MethodAnalyzer; import jode.decompiler.MethodAnalyzer;
import jode.decompiler.Options;
import jode.decompiler.OuterValues; import jode.decompiler.OuterValues;
import jode.decompiler.OuterValueListener; import jode.decompiler.OuterValueListener;
import jode.expr.*; import jode.expr.*;
@ -241,7 +241,7 @@ public class TransformConstructors {
InvokeOperator superCall = (InvokeOperator) expr; InvokeOperator superCall = (InvokeOperator) expr;
Expression[] subExpr = superCall.getSubExpressions(); Expression[] subExpr = superCall.getSubExpressions();
/* An anonymous constructor may also give locals /* An anonymous constructor may only give locals
* to its super constructor. * to its super constructor.
*/ */
for (int i = 1; i < subExpr.length; i++) { for (int i = 1; i < subExpr.length; i++) {
@ -577,7 +577,7 @@ public class TransformConstructors {
return null; return null;
} }
if (outerValues != null if (outerValues != null
&& (Decompiler.options & Decompiler.OPTION_CONTRAFO) != 0) { && (Options.options & Options.OPTION_CONTRAFO) != 0) {
int slot = ((LocalLoadOperator)expr).getLocalInfo().getSlot(); int slot = ((LocalLoadOperator)expr).getLocalInfo().getSlot();
Expression outExpr = outerValues.getValueBySlot(slot); Expression outExpr = outerValues.getValueBySlot(slot);
if (outExpr != null) if (outExpr != null)
@ -604,7 +604,7 @@ public class TransformConstructors {
} }
public void removeSynthInitializers() { public void removeSynthInitializers() {
if ((Decompiler.options & Decompiler.OPTION_CONTRAFO) == 0 if ((Options.options & Options.OPTION_CONTRAFO) == 0
|| isStatic || type01Count == 0) || isStatic || type01Count == 0)
return; return;
@ -852,7 +852,7 @@ public class TransformConstructors {
InnerClassInfo[] outers = superClazz.getOuterClasses(); InnerClassInfo[] outers = superClazz.getOuterClasses();
int superParamCount = superInvoke.getSubExpressions().length - 1; int superParamCount = superInvoke.getSubExpressions().length - 1;
if ((Decompiler.options & Decompiler.OPTION_INNER) != 0 if ((Options.options & Options.OPTION_INNER) != 0
&& outers != null && outers != null
&& outers[0].outer != null && outers[0].outer != null
&& outers[0].name != null && outers[0].name != null
@ -995,7 +995,7 @@ public class TransformConstructors {
* outerValue - locals). * outerValue - locals).
*/ */
public void transform() { public void transform() {
if ((Decompiler.options & Decompiler.OPTION_CONTRAFO) == 0 if ((Options.options & Options.OPTION_CONTRAFO) == 0
|| cons.length == 0) || cons.length == 0)
return; return;

Loading…
Cancel
Save