java-decompiler: cleanups and fixes

- duplicates eliminated
- immutable fields
- typos
- formatting
master
Roman Shevchenko 10 years ago
parent 020f5c404b
commit 82a2939271
  1. 16
      src/org/jetbrains/java/decompiler/code/interpreter/InstructionImpact.java
  2. 14
      src/org/jetbrains/java/decompiler/main/AssertProcessor.java
  3. 8
      src/org/jetbrains/java/decompiler/main/ClassReference14Processor.java
  4. 22
      src/org/jetbrains/java/decompiler/main/ClassWriter.java
  5. 2
      src/org/jetbrains/java/decompiler/main/EnumProcessor.java
  6. 4
      src/org/jetbrains/java/decompiler/main/InitializerProcessor.java
  7. 6
      src/org/jetbrains/java/decompiler/main/rels/ClassWrapper.java
  8. 36
      src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java
  9. 6
      src/org/jetbrains/java/decompiler/main/rels/NestedMemberAccess.java
  10. 4
      src/org/jetbrains/java/decompiler/modules/decompiler/ConcatenationHelper.java
  11. 4
      src/org/jetbrains/java/decompiler/modules/decompiler/ExitHelper.java
  12. 40
      src/org/jetbrains/java/decompiler/modules/decompiler/ExprProcessor.java
  13. 4
      src/org/jetbrains/java/decompiler/modules/decompiler/FinallyProcessor.java
  14. 16
      src/org/jetbrains/java/decompiler/modules/decompiler/IdeaNotNullHelper.java
  15. 8
      src/org/jetbrains/java/decompiler/modules/decompiler/IfHelper.java
  16. 12
      src/org/jetbrains/java/decompiler/modules/decompiler/PPandMMHelper.java
  17. 40
      src/org/jetbrains/java/decompiler/modules/decompiler/SecondaryFunctionsHelper.java
  18. 56
      src/org/jetbrains/java/decompiler/modules/decompiler/SimplifyExprentsHelper.java
  19. 6
      src/org/jetbrains/java/decompiler/modules/decompiler/StackVarsProcessor.java
  20. 67
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/AnnotationExprent.java
  21. 64
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/ArrayExprent.java
  22. 12
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/AssertExprent.java
  23. 103
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/AssignmentExprent.java
  24. 147
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/ConstExprent.java
  25. 91
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/ExitExprent.java
  26. 44
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/Exprent.java
  27. 89
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/FieldExprent.java
  28. 270
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/FunctionExprent.java
  29. 50
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/IfExprent.java
  30. 110
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/InvocationExprent.java
  31. 47
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/MonitorExprent.java
  32. 188
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/NewExprent.java
  33. 50
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/SwitchExprent.java
  34. 64
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/VarExprent.java
  35. 8
      src/org/jetbrains/java/decompiler/modules/decompiler/sforms/SSAConstructorSparseEx.java
  36. 14
      src/org/jetbrains/java/decompiler/modules/decompiler/sforms/SSAUConstructorSparseEx.java
  37. 2
      src/org/jetbrains/java/decompiler/modules/decompiler/stats/SwitchStatement.java
  38. 6
      src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarDefinitionHelper.java
  39. 80
      src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarProcessor.java
  40. 165
      src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarTypeProcessor.java
  41. 242
      src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarVersionsProcessor.java
  42. 176
      src/org/jetbrains/java/decompiler/modules/renamer/IdentifierConverter.java
  43. 64
      src/org/jetbrains/java/decompiler/struct/consts/ConstantPool.java
  44. 2
      src/org/jetbrains/java/decompiler/struct/gen/DataPoint.java
  45. 32
      src/org/jetbrains/java/decompiler/struct/gen/FieldDescriptor.java
  46. 132
      src/org/jetbrains/java/decompiler/struct/gen/MethodDescriptor.java
  47. 20
      src/org/jetbrains/java/decompiler/struct/gen/NewClassNameBuilder.java
  48. 404
      src/org/jetbrains/java/decompiler/struct/gen/VarType.java
  49. 2
      src/org/jetbrains/java/decompiler/struct/gen/generics/GenericMain.java
  50. 146
      src/org/jetbrains/java/decompiler/struct/gen/generics/GenericType.java
  51. 31
      src/org/jetbrains/java/decompiler/util/TextUtil.java

@ -429,7 +429,7 @@ public class InstructionImpact {
break; break;
case CodeConstants.opc_aaload: case CodeConstants.opc_aaload:
var1 = stack.pop(2); var1 = stack.pop(2);
stack.push(new VarType(var1.type, var1.arraydim - 1, var1.value)); stack.push(new VarType(var1.type, var1.arrayDim - 1, var1.value));
break; break;
case CodeConstants.opc_astore: case CodeConstants.opc_astore:
data.setVariable(instr.getOperand(0), stack.pop()); data.setVariable(instr.getOperand(0), stack.pop());
@ -457,7 +457,7 @@ public class InstructionImpact {
ck = pool.getLinkConstant(instr.getOperand(0)); ck = pool.getLinkConstant(instr.getOperand(0));
var1 = new VarType(ck.descriptor); var1 = new VarType(ck.descriptor);
stack.push(var1); stack.push(var1);
if (var1.stack_size == 2) { if (var1.stackSize == 2) {
stack.push(new VarType(CodeConstants.TYPE_GROUP2EMPTY)); stack.push(new VarType(CodeConstants.TYPE_GROUP2EMPTY));
} }
break; break;
@ -466,7 +466,7 @@ public class InstructionImpact {
case CodeConstants.opc_putstatic: case CodeConstants.opc_putstatic:
ck = pool.getLinkConstant(instr.getOperand(0)); ck = pool.getLinkConstant(instr.getOperand(0));
var1 = new VarType(ck.descriptor); var1 = new VarType(ck.descriptor);
stack.pop(var1.stack_size); stack.pop(var1.stackSize);
break; break;
case CodeConstants.opc_invokevirtual: case CodeConstants.opc_invokevirtual:
case CodeConstants.opc_invokespecial: case CodeConstants.opc_invokespecial:
@ -478,11 +478,11 @@ public class InstructionImpact {
ck = pool.getLinkConstant(instr.getOperand(0)); ck = pool.getLinkConstant(instr.getOperand(0));
MethodDescriptor md = MethodDescriptor.parseDescriptor(ck.descriptor); MethodDescriptor md = MethodDescriptor.parseDescriptor(ck.descriptor);
for (int i = 0; i < md.params.length; i++) { for (int i = 0; i < md.params.length; i++) {
stack.pop(md.params[i].stack_size); stack.pop(md.params[i].stackSize);
} }
if (md.ret.type != CodeConstants.TYPE_VOID) { if (md.ret.type != CodeConstants.TYPE_VOID) {
stack.push(md.ret); stack.push(md.ret);
if (md.ret.stack_size == 2) { if (md.ret.stackSize == 2) {
stack.push(new VarType(CodeConstants.TYPE_GROUP2EMPTY)); stack.push(new VarType(CodeConstants.TYPE_GROUP2EMPTY));
} }
} }
@ -494,9 +494,7 @@ public class InstructionImpact {
break; break;
case CodeConstants.opc_newarray: case CodeConstants.opc_newarray:
stack.pop(); stack.pop();
var1 = new VarType(arr_type[instr.getOperand(0) - 4]); stack.push(new VarType(arr_type[instr.getOperand(0) - 4], 1).resizeArrayDim(1));
var1.arraydim = 1;
stack.push(var1);
break; break;
case CodeConstants.opc_athrow: case CodeConstants.opc_athrow:
var1 = stack.pop(); var1 = stack.pop();
@ -516,7 +514,7 @@ public class InstructionImpact {
cn = pool.getPrimitiveConstant(instr.getOperand(0)); cn = pool.getPrimitiveConstant(instr.getOperand(0));
if (cn.isArray) { if (cn.isArray) {
var1 = new VarType(CodeConstants.TYPE_OBJECT, 0, cn.getString()); var1 = new VarType(CodeConstants.TYPE_OBJECT, 0, cn.getString());
var1.arraydim += dimensions; var1 = var1.resizeArrayDim(var1.arrayDim + dimensions);
stack.push(var1); stack.push(var1);
} }
else { else {

@ -89,7 +89,7 @@ public class AssertProcessor {
if (initializer.type == Exprent.EXPRENT_FUNCTION) { if (initializer.type == Exprent.EXPRENT_FUNCTION) {
FunctionExprent fexpr = (FunctionExprent)initializer; FunctionExprent fexpr = (FunctionExprent)initializer;
if (fexpr.getFunctype() == FunctionExprent.FUNCTION_BOOLNOT && if (fexpr.getFuncType() == FunctionExprent.FUNCTION_BOOL_NOT &&
fexpr.getLstOperands().get(0).type == Exprent.EXPRENT_INVOCATION) { fexpr.getLstOperands().get(0).type == Exprent.EXPRENT_INVOCATION) {
InvocationExprent invexpr = (InvocationExprent)fexpr.getLstOperands().get(0); InvocationExprent invexpr = (InvocationExprent)fexpr.getLstOperands().get(0);
@ -101,7 +101,7 @@ public class AssertProcessor {
invexpr.getLstParameters().isEmpty()) { invexpr.getLstParameters().isEmpty()) {
ConstExprent cexpr = (ConstExprent)invexpr.getInstance(); ConstExprent cexpr = (ConstExprent)invexpr.getInstance();
if (VarType.VARTYPE_CLASS.equals(cexpr.getConsttype())) { if (VarType.VARTYPE_CLASS.equals(cexpr.getConstType())) {
ClassNode nd = node; ClassNode nd = node;
while (nd != null) { while (nd != null) {
@ -173,7 +173,7 @@ public class AssertProcessor {
Exprent ascond = null, retcond = null; Exprent ascond = null, retcond = null;
if (exprres[0] != null) { if (exprres[0] != null) {
ascond = new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT, ascond = new FunctionExprent(FunctionExprent.FUNCTION_BOOL_NOT,
Arrays.asList((Exprent)exprres[0]), throwError.bytecode); Arrays.asList((Exprent)exprres[0]), throwError.bytecode);
retcond = SecondaryFunctionsHelper.propagateBoolNot(ascond); retcond = SecondaryFunctionsHelper.propagateBoolNot(ascond);
} }
@ -245,9 +245,9 @@ public class AssertProcessor {
if (expr.type == Exprent.EXPRENT_EXIT) { if (expr.type == Exprent.EXPRENT_EXIT) {
ExitExprent exexpr = (ExitExprent)expr; ExitExprent exexpr = (ExitExprent)expr;
if (exexpr.getExittype() == ExitExprent.EXIT_THROW && exexpr.getValue().type == Exprent.EXPRENT_NEW) { if (exexpr.getExitType() == ExitExprent.EXIT_THROW && exexpr.getValue().type == Exprent.EXPRENT_NEW) {
NewExprent nexpr = (NewExprent)exexpr.getValue(); NewExprent nexpr = (NewExprent)exexpr.getValue();
if (CLASS_ASSERTION_ERROR.equals(nexpr.getNewtype()) && nexpr.getConstructor() != null) { if (CLASS_ASSERTION_ERROR.equals(nexpr.getNewType()) && nexpr.getConstructor() != null) {
return nexpr.getConstructor(); return nexpr.getConstructor();
} }
} }
@ -260,7 +260,7 @@ public class AssertProcessor {
if (exprent.type == Exprent.EXPRENT_FUNCTION) { if (exprent.type == Exprent.EXPRENT_FUNCTION) {
FunctionExprent fexpr = (FunctionExprent)exprent; FunctionExprent fexpr = (FunctionExprent)exprent;
if (fexpr.getFunctype() == FunctionExprent.FUNCTION_CADD) { if (fexpr.getFuncType() == FunctionExprent.FUNCTION_CADD) {
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
Exprent param = fexpr.getLstOperands().get(i); Exprent param = fexpr.getLstOperands().get(i);
@ -295,7 +295,7 @@ public class AssertProcessor {
if (exprent.type == Exprent.EXPRENT_FUNCTION) { if (exprent.type == Exprent.EXPRENT_FUNCTION) {
FunctionExprent fparam = (FunctionExprent)exprent; FunctionExprent fparam = (FunctionExprent)exprent;
if (fparam.getFunctype() == FunctionExprent.FUNCTION_BOOLNOT && if (fparam.getFuncType() == FunctionExprent.FUNCTION_BOOL_NOT &&
fparam.getLstOperands().get(0).type == Exprent.EXPRENT_FIELD) { fparam.getLstOperands().get(0).type == Exprent.EXPRENT_FIELD) {
FieldExprent fdparam = (FieldExprent)fparam.getLstOperands().get(0); FieldExprent fdparam = (FieldExprent)fparam.getLstOperands().get(0);
if (classname.equals(fdparam.getClassname()) if (classname.equals(fdparam.getClassname())

@ -190,7 +190,7 @@ public class ClassReference14Processor {
CatchStatement cst = (CatchStatement)root.getFirst(); CatchStatement cst = (CatchStatement)root.getFirst();
if (cst.getStats().size() == 2 && cst.getFirst().type == Statement.TYPE_BASICBLOCK && if (cst.getStats().size() == 2 && cst.getFirst().type == Statement.TYPE_BASICBLOCK &&
cst.getStats().get(1).type == Statement.TYPE_BASICBLOCK && cst.getStats().get(1).type == Statement.TYPE_BASICBLOCK &&
cst.getVars().get(0).getVartype().equals(new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/ClassNotFoundException"))) { cst.getVars().get(0).getVarType().equals(new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/ClassNotFoundException"))) {
BasicBlockStatement body = (BasicBlockStatement)cst.getFirst(); BasicBlockStatement body = (BasicBlockStatement)cst.getFirst();
BasicBlockStatement handler = (BasicBlockStatement)cst.getStats().get(1); BasicBlockStatement handler = (BasicBlockStatement)cst.getStats().get(1);
@ -247,13 +247,13 @@ public class ClassReference14Processor {
if (exprent.type == Exprent.EXPRENT_FUNCTION) { if (exprent.type == Exprent.EXPRENT_FUNCTION) {
FunctionExprent fexpr = (FunctionExprent)exprent; FunctionExprent fexpr = (FunctionExprent)exprent;
if (fexpr.getFunctype() == FunctionExprent.FUNCTION_IIF) { if (fexpr.getFuncType() == FunctionExprent.FUNCTION_IIF) {
if (fexpr.getLstOperands().get(0).type == Exprent.EXPRENT_FUNCTION) { if (fexpr.getLstOperands().get(0).type == Exprent.EXPRENT_FUNCTION) {
FunctionExprent headexpr = (FunctionExprent)fexpr.getLstOperands().get(0); FunctionExprent headexpr = (FunctionExprent)fexpr.getLstOperands().get(0);
if (headexpr.getFunctype() == FunctionExprent.FUNCTION_EQ) { if (headexpr.getFuncType() == FunctionExprent.FUNCTION_EQ) {
if (headexpr.getLstOperands().get(0).type == Exprent.EXPRENT_FIELD && if (headexpr.getLstOperands().get(0).type == Exprent.EXPRENT_FIELD &&
headexpr.getLstOperands().get(1).type == Exprent.EXPRENT_CONST && headexpr.getLstOperands().get(1).type == Exprent.EXPRENT_CONST &&
((ConstExprent)headexpr.getLstOperands().get(1)).getConsttype().equals(VarType.VARTYPE_NULL)) { ((ConstExprent)headexpr.getLstOperands().get(1)).getConstType().equals(VarType.VARTYPE_NULL)) {
FieldExprent field = (FieldExprent)headexpr.getLstOperands().get(0); FieldExprent field = (FieldExprent)headexpr.getLstOperands().get(0);
ClassNode fieldnode = DecompilerContext.getClassProcessor().getMapRootClasses().get(field.getClassname()); ClassNode fieldnode = DecompilerContext.getClassProcessor().getMapRootClasses().get(field.getClassname());

@ -136,7 +136,7 @@ public class ClassWriter {
firstParameter = false; firstParameter = false;
} }
index += md_content.params[i].stack_size; index += md_content.params[i].stackSize;
} }
buffer.append(") ->"); buffer.append(") ->");
@ -440,7 +440,7 @@ public class ClassWriter {
if (initializer != null) { if (initializer != null) {
if (isEnum && initializer.type == Exprent.EXPRENT_NEW) { if (isEnum && initializer.type == Exprent.EXPRENT_NEW) {
NewExprent nexpr = (NewExprent)initializer; NewExprent nexpr = (NewExprent)initializer;
nexpr.setEnumconst(true); nexpr.setEnumConst(true);
buffer.append(nexpr.toJava(indent, tracer)); buffer.append(nexpr.toJava(indent, tracer));
} }
else { else {
@ -512,7 +512,7 @@ public class ClassWriter {
firstParameter = false; firstParameter = false;
} }
index += md_content.params[i].stack_size; index += md_content.params[i].stackSize;
} }
buffer.append(") {").appendLineSeparator(); buffer.append(") {").appendLineSeparator();
@ -692,16 +692,16 @@ public class ClassWriter {
appendParameterAnnotations(buffer, mt, paramCount); appendParameterAnnotations(buffer, mt, paramCount);
if (methodWrapper.varproc.getVarFinal(new VarVersionPaar(index, 0)) == VarTypeProcessor.VAR_FINALEXPLICIT) { if (methodWrapper.varproc.getVarFinal(new VarVersionPaar(index, 0)) == VarTypeProcessor.VAR_EXPLICIT_FINAL) {
buffer.append("final "); buffer.append("final ");
} }
if (descriptor != null) { if (descriptor != null) {
GenericType parameterType = descriptor.params.get(i); GenericType parameterType = descriptor.params.get(i);
boolean isVarArg = (i == lastVisibleParameterIndex && mt.hasModifier(CodeConstants.ACC_VARARGS) && parameterType.arraydim > 0); boolean isVarArg = (i == lastVisibleParameterIndex && mt.hasModifier(CodeConstants.ACC_VARARGS) && parameterType.arrayDim > 0);
if (isVarArg) { if (isVarArg) {
parameterType.arraydim--; parameterType = parameterType.decreaseArrayDim();
} }
String typeName = GenericMain.getGenericCastTypeName(parameterType); String typeName = GenericMain.getGenericCastTypeName(parameterType);
@ -717,11 +717,11 @@ public class ClassWriter {
} }
} }
else { else {
VarType parameterType = md.params[i].copy(); VarType parameterType = md.params[i];
boolean isVarArg = (i == lastVisibleParameterIndex && mt.hasModifier(CodeConstants.ACC_VARARGS) && parameterType.arraydim > 0); boolean isVarArg = (i == lastVisibleParameterIndex && mt.hasModifier(CodeConstants.ACC_VARARGS) && parameterType.arrayDim > 0);
if (isVarArg) { if (isVarArg) {
parameterType.decArrayDim(); parameterType = parameterType.decreaseArrayDim();
} }
String typeName = ExprProcessor.getCastTypeName(parameterType); String typeName = ExprProcessor.getCastTypeName(parameterType);
@ -745,7 +745,7 @@ public class ClassWriter {
paramCount++; paramCount++;
} }
index += md.params[i].stack_size; index += md.params[i].stackSize;
} }
buffer.append(')'); buffer.append(')');
@ -839,7 +839,7 @@ public class ClassWriter {
return !hideMethod; return !hideMethod;
} }
private void mapLines(TextBuffer code, StructLineNumberTableAttribute table, BytecodeMappingTracer tracer, int startLine) { private static void mapLines(TextBuffer code, StructLineNumberTableAttribute table, BytecodeMappingTracer tracer, int startLine) {
// build line start offsets map // build line start offsets map
HashMap<Integer, Set<Integer>> lineStartOffsets = new HashMap<Integer, Set<Integer>>(); HashMap<Integer, Set<Integer>> lineStartOffsets = new HashMap<Integer, Set<Integer>>();
for (Map.Entry<Integer, Integer> entry : tracer.getMapping().entrySet()) { for (Map.Entry<Integer, Integer> entry : tracer.getMapping().entrySet()) {

@ -103,7 +103,7 @@ public class EnumProcessor {
VarExprent instvar = (VarExprent)inv.getInstance(); VarExprent instvar = (VarExprent)inv.getInstance();
VarVersionPaar varpaar = new VarVersionPaar(instvar); VarVersionPaar varpaar = new VarVersionPaar(instvar);
String classname = meth.varproc.getThisvars().get(varpaar); String classname = meth.varproc.getThisVars().get(varpaar);
if (classname != null) { // any this instance. TODO: Restrict to current class? if (classname != null) { // any this instance. TODO: Restrict to current class?
if (!wrapper.getClassStruct().qualifiedName.equals(inv.getClassname())) { if (!wrapper.getClassStruct().qualifiedName.equals(inv.getClassname())) {

@ -261,7 +261,7 @@ public class InitializerProcessor {
switch (expr.type) { switch (expr.type) {
case Exprent.EXPRENT_VAR: case Exprent.EXPRENT_VAR:
VarVersionPaar varpaar = new VarVersionPaar((VarExprent)expr); VarVersionPaar varpaar = new VarVersionPaar((VarExprent)expr);
if (!meth.varproc.getExternvars().contains(varpaar)) { if (!meth.varproc.getExternalVars().contains(varpaar)) {
String varname = meth.varproc.getVarName(varpaar); String varname = meth.varproc.getVarName(varpaar);
if (!varname.equals("this") && !varname.endsWith(".this")) { // FIXME: remove direct comparison with strings if (!varname.equals("this") && !varname.endsWith(".this")) { // FIXME: remove direct comparison with strings
@ -308,7 +308,7 @@ public class InitializerProcessor {
VarExprent instvar = (VarExprent)inv.getInstance(); VarExprent instvar = (VarExprent)inv.getInstance();
VarVersionPaar varpaar = new VarVersionPaar(instvar); VarVersionPaar varpaar = new VarVersionPaar(instvar);
String classname = meth.varproc.getThisvars().get(varpaar); String classname = meth.varproc.getThisVars().get(varpaar);
if (classname != null) { // any this instance. TODO: Restrict to current class? if (classname != null) { // any this instance. TODO: Restrict to current class?
if (withThis || !wrapper.getClassStruct().qualifiedName.equals(inv.getClassname())) { if (withThis || !wrapper.getClassStruct().qualifiedName.equals(inv.getClassname())) {

@ -124,7 +124,7 @@ public class ClassWrapper {
int paramcount = 0; int paramcount = 0;
if (thisvar) { if (thisvar) {
varproc.getThisvars().put(new VarVersionPaar(0, 0), classStruct.qualifiedName); varproc.getThisVars().put(new VarVersionPaar(0, 0), classStruct.qualifiedName);
paramcount = 1; paramcount = 1;
} }
paramcount += md.params.length; paramcount += md.params.length;
@ -138,11 +138,11 @@ public class ClassWrapper {
varindex++; varindex++;
} }
else { else {
varindex += md.params[i - 1].stack_size; varindex += md.params[i - 1].stackSize;
} }
} }
else { else {
varindex += md.params[i].stack_size; varindex += md.params[i].stackSize;
} }
} }
} }

@ -127,7 +127,7 @@ public class NestedClassProcessor {
// this pointer // this pointer
if (!is_static_lambda_content && DecompilerContext.getOption(IFernflowerPreferences.LAMBDA_TO_ANONYMOUS_CLASS)) { if (!is_static_lambda_content && DecompilerContext.getOption(IFernflowerPreferences.LAMBDA_TO_ANONYMOUS_CLASS)) {
meth.varproc.getThisvars().put(new VarVersionPaar(0, 0), parent_class_name); meth.varproc.getThisVars().put(new VarVersionPaar(0, 0), parent_class_name);
meth.varproc.setVarName(new VarVersionPaar(0, 0), parent.simpleName + ".this"); meth.varproc.setVarName(new VarVersionPaar(0, 0), parent.simpleName + ".this");
} }
@ -146,7 +146,7 @@ public class NestedClassProcessor {
if (expr.type == Exprent.EXPRENT_NEW) { if (expr.type == Exprent.EXPRENT_NEW) {
NewExprent new_expr = (NewExprent)expr; NewExprent new_expr = (NewExprent)expr;
if (new_expr.isLambda() && lambda_class_type.equals(new_expr.getNewtype())) { if (new_expr.isLambda() && lambda_class_type.equals(new_expr.getNewType())) {
InvocationExprent inv_dynamic = new_expr.getConstructor(); InvocationExprent inv_dynamic = new_expr.getConstructor();
@ -165,7 +165,7 @@ public class NestedClassProcessor {
mapNewNames.put(new VarVersionPaar(varindex, 0), enc_varname); mapNewNames.put(new VarVersionPaar(varindex, 0), enc_varname);
} }
varindex += md_content.params[i].stack_size; varindex += md_content.params[i].stackSize;
} }
} }
} }
@ -330,7 +330,7 @@ public class NestedClassProcessor {
VarVersionPaar varpaar = new VarVersionPaar((VarExprent)param); VarVersionPaar varpaar = new VarVersionPaar((VarExprent)param);
// FIXME: final flags of variables are wrong! Correct the entire final functionality. // FIXME: final flags of variables are wrong! Correct the entire final functionality.
// if(meth.varproc.getVarFinal(varpaar) != VarTypeProcessor.VAR_NONFINAL) { // if(meth.varproc.getVarFinal(varpaar) != VarTypeProcessor.VAR_NON_FINAL) {
pair = new VarFieldPair(mask.get(i).keyfield, varpaar); pair = new VarFieldPair(mask.get(i).keyfield, varpaar);
// } // }
} }
@ -467,7 +467,7 @@ public class NestedClassProcessor {
varname = encmeth.varproc.getVarName(paar); varname = encmeth.varproc.getVarName(paar);
vartype = encmeth.varproc.getVarType(paar); vartype = encmeth.varproc.getVarType(paar);
encmeth.varproc.setVarFinal(paar, VarTypeProcessor.VAR_FINALEXPLICIT); encmeth.varproc.setVarFinal(paar, VarTypeProcessor.VAR_EXPLICIT_FINAL);
} }
if (paar.var == -1 || "this".equals(varname)) { if (paar.var == -1 || "this".equals(varname)) {
@ -478,13 +478,13 @@ public class NestedClassProcessor {
else { else {
varname = parent.simpleName + ".this"; varname = parent.simpleName + ".this";
} }
meth.varproc.getThisvars().put(newvar, parent.classStruct.qualifiedName); meth.varproc.getThisVars().put(newvar, parent.classStruct.qualifiedName);
} }
mapNewNames.put(newvar, varname); mapNewNames.put(newvar, varname);
mapNewTypes.put(newvar, vartype); mapNewTypes.put(newvar, vartype);
} }
varindex += md.params[index++].stack_size; varindex += md.params[index++].stackSize;
} }
} }
@ -508,7 +508,7 @@ public class NestedClassProcessor {
varname = enclosing_method.varproc.getVarName(entr.getValue()); varname = enclosing_method.varproc.getVarName(entr.getValue());
vartype = enclosing_method.varproc.getVarType(entr.getValue()); vartype = enclosing_method.varproc.getVarType(entr.getValue());
enclosing_method.varproc.setVarFinal(entr.getValue(), VarTypeProcessor.VAR_FINALEXPLICIT); enclosing_method.varproc.setVarFinal(entr.getValue(), VarTypeProcessor.VAR_EXPLICIT_FINAL);
} }
if (entr.getValue().var == -1 || "this".equals(varname)) { if (entr.getValue().var == -1 || "this".equals(varname)) {
@ -519,7 +519,7 @@ public class NestedClassProcessor {
else { else {
varname = clnode.parent.simpleName + ".this"; varname = clnode.parent.simpleName + ".this";
} }
meth.varproc.getThisvars().put(newvar, clnode.parent.classStruct.qualifiedName); meth.varproc.getThisVars().put(newvar, clnode.parent.classStruct.qualifiedName);
} }
mapNewNames.put(newvar, varname); mapNewNames.put(newvar, varname);
@ -594,7 +594,7 @@ public class NestedClassProcessor {
int varindex = ((VarExprent)exprent).getIndex(); int varindex = ((VarExprent)exprent).getIndex();
if (mapParamsToNewVars.containsKey(varindex)) { if (mapParamsToNewVars.containsKey(varindex)) {
VarVersionPaar newvar = mapParamsToNewVars.get(varindex); VarVersionPaar newvar = mapParamsToNewVars.get(varindex);
meth.varproc.getExternvars().add(newvar); meth.varproc.getExternalVars().add(newvar);
return new VarExprent(newvar.var, meth.varproc.getVarType(newvar), meth.varproc); return new VarExprent(newvar.var, meth.varproc.getVarType(newvar), meth.varproc);
} }
} }
@ -608,7 +608,7 @@ public class NestedClassProcessor {
//if(fexpr.getClassname().equals(child.classStruct.qualifiedName) && //if(fexpr.getClassname().equals(child.classStruct.qualifiedName) &&
// mapFieldsToNewVars.containsKey(keyField)) { // mapFieldsToNewVars.containsKey(keyField)) {
VarVersionPaar newvar = mapFieldsToNewVars.get(keyField); VarVersionPaar newvar = mapFieldsToNewVars.get(keyField);
meth.varproc.getExternvars().add(newvar); meth.varproc.getExternalVars().add(newvar);
return new VarExprent(newvar.var, meth.varproc.getVarType(newvar), meth.varproc); return new VarExprent(newvar.var, meth.varproc.getVarType(newvar), meth.varproc);
} }
} }
@ -656,7 +656,7 @@ public class NestedClassProcessor {
for (int i = 0; i < md.params.length; i++) { // no static methods allowed for (int i = 0; i < md.params.length; i++) { // no static methods allowed
String keyField = getEnclosingVarField(cl, meth, graph, varindex); String keyField = getEnclosingVarField(cl, meth, graph, varindex);
fields.add(keyField == null ? null : new VarFieldPair(keyField, new VarVersionPaar(-1, 0))); // TODO: null? fields.add(keyField == null ? null : new VarFieldPair(keyField, new VarVersionPaar(-1, 0))); // TODO: null?
varindex += md.params[i].stack_size; varindex += md.params[i].stackSize;
} }
mapMasks.put(mt.getDescriptor(), fields); mapMasks.put(mt.getDescriptor(), fields);
} }
@ -671,7 +671,7 @@ public class NestedClassProcessor {
String field = ""; String field = "";
// parameter variable final // parameter variable final
if (meth.varproc.getVarFinal(new VarVersionPaar(index, 0)) == VarTypeProcessor.VAR_NONFINAL) { if (meth.varproc.getVarFinal(new VarVersionPaar(index, 0)) == VarTypeProcessor.VAR_NON_FINAL) {
return null; return null;
} }
@ -854,7 +854,7 @@ public class NestedClassProcessor {
VarExprent var = new VarExprent(meth.counter.getCounterAndIncrement(CounterContainer.VAR_COUNTER), VarExprent var = new VarExprent(meth.counter.getCounterAndIncrement(CounterContainer.VAR_COUNTER),
classtype, meth.varproc); classtype, meth.varproc);
var.setDefinition(true); var.setDefinition(true);
var.setClassdef(true); var.setClassDef(true);
lst.add(addindex, var); lst.add(addindex, var);
} }
@ -970,8 +970,8 @@ public class NestedClassProcessor {
switch (expr.type) { switch (expr.type) {
case Exprent.EXPRENT_CONST: case Exprent.EXPRENT_CONST:
ConstExprent cexpr = (ConstExprent)expr; ConstExprent cexpr = (ConstExprent)expr;
res = (VarType.VARTYPE_CLASS.equals(cexpr.getConsttype()) && classname.equals(cexpr.getValue()) || res = (VarType.VARTYPE_CLASS.equals(cexpr.getConstType()) && classname.equals(cexpr.getValue()) ||
classtype.equals(cexpr.getConsttype())); classtype.equals(cexpr.getConstType()));
break; break;
case Exprent.EXPRENT_FIELD: case Exprent.EXPRENT_FIELD:
res = classname.equals(((FieldExprent)expr).getClassname()); res = classname.equals(((FieldExprent)expr).getClassname());
@ -986,8 +986,8 @@ public class NestedClassProcessor {
case Exprent.EXPRENT_VAR: case Exprent.EXPRENT_VAR:
VarExprent vexpr = (VarExprent)expr; VarExprent vexpr = (VarExprent)expr;
if (vexpr.isDefinition()) { if (vexpr.isDefinition()) {
VarType vtype = vexpr.getVartype(); VarType vtype = vexpr.getVarType();
if (classtype.equals(vtype) || (vtype.arraydim > 0 && classtype.value.equals(vtype.value))) { if (classtype.equals(vtype) || (vtype.arrayDim > 0 && classtype.value.equals(vtype.value))) {
res = true; res = true;
} }
} }

@ -91,7 +91,7 @@ public class NestedMemberAccess {
if (exprent.type == Exprent.EXPRENT_EXIT) { if (exprent.type == Exprent.EXPRENT_EXIT) {
ExitExprent exexpr = (ExitExprent)exprent; ExitExprent exexpr = (ExitExprent)exprent;
if (exexpr.getExittype() == ExitExprent.EXIT_RETURN && exexpr.getValue() != null) { if (exexpr.getExitType() == ExitExprent.EXIT_RETURN && exexpr.getValue() != null) {
exprCore = exexpr.getValue(); exprCore = exexpr.getValue();
} }
} }
@ -188,7 +188,7 @@ public class NestedMemberAccess {
if (((VarExprent)asexpr.getRight()).getIndex() == parcount - 1) { if (((VarExprent)asexpr.getRight()).getIndex() == parcount - 1) {
ExitExprent exexpr = (ExitExprent)exprentSecond; ExitExprent exexpr = (ExitExprent)exprentSecond;
if (exexpr.getExittype() == ExitExprent.EXIT_RETURN && exexpr.getValue() != null) { if (exexpr.getExitType() == ExitExprent.EXIT_RETURN && exexpr.getValue() != null) {
if (exexpr.getValue().type == Exprent.EXPRENT_VAR && if (exexpr.getValue().type == Exprent.EXPRENT_VAR &&
((VarExprent)asexpr.getRight()).getIndex() == parcount - 1) { ((VarExprent)asexpr.getRight()).getIndex() == parcount - 1) {
type = METHOD_ACCESS_FIELD_SET; type = METHOD_ACCESS_FIELD_SET;
@ -375,7 +375,7 @@ public class NestedMemberAccess {
} }
int index = methdest.counter.getCounterAndIncrement(CounterContainer.VAR_COUNTER); int index = methdest.counter.getCounterAndIncrement(CounterContainer.VAR_COUNTER);
VarExprent ret = new VarExprent(index, var.getVartype(), methdest.varproc); VarExprent ret = new VarExprent(index, var.getVarType(), methdest.varproc);
methdest.varproc.setVarName(new VarVersionPaar(index, 0), varname); methdest.varproc.setVarName(new VarVersionPaar(index, 0), varname);
retexprent = ret; retexprent = ret;

@ -133,7 +133,7 @@ public class ConcatenationHelper {
List<Exprent> lstTmp = new ArrayList<Exprent>(); List<Exprent> lstTmp = new ArrayList<Exprent>();
lstTmp.add(func); lstTmp.add(func);
lstTmp.add(lstOperands.get(i)); lstTmp.add(lstOperands.get(i));
func = new FunctionExprent(FunctionExprent.FUNCTION_STRCONCAT, lstTmp, expr.bytecode); func = new FunctionExprent(FunctionExprent.FUNCTION_STR_CONCAT, lstTmp, expr.bytecode);
} }
return func; return func;
@ -168,7 +168,7 @@ public class ConcatenationHelper {
private static boolean isNewConcat(NewExprent expr, VarType cltype) { private static boolean isNewConcat(NewExprent expr, VarType cltype) {
if (expr.getNewtype().equals(cltype)) { if (expr.getNewType().equals(cltype)) {
VarType[] params = expr.getConstructor().getDescriptor().params; VarType[] params = expr.getConstructor().getDescriptor().params;
if (params.length == 0 || (params.length == 1 && if (params.length == 0 || (params.length == 1 &&
params[0].equals(VarType.VARTYPE_STRING))) { params[0].equals(VarType.VARTYPE_STRING))) {

@ -255,7 +255,7 @@ public class ExitHelper {
Exprent expr = lstExpr.get(lstExpr.size() - 1); Exprent expr = lstExpr.get(lstExpr.size() - 1);
if (expr.type == Exprent.EXPRENT_EXIT) { if (expr.type == Exprent.EXPRENT_EXIT) {
ExitExprent ex = (ExitExprent)expr; ExitExprent ex = (ExitExprent)expr;
if (ex.getExittype() == ExitExprent.EXIT_RETURN && ex.getValue() == null) { if (ex.getExitType() == ExitExprent.EXIT_RETURN && ex.getValue() == null) {
// remove redundant return // remove redundant return
lstExpr.remove(lstExpr.size() - 1); lstExpr.remove(lstExpr.size() - 1);
res = true; res = true;
@ -292,7 +292,7 @@ public class ExitHelper {
Exprent expr = lstExpr.get(lstExpr.size() - 1); Exprent expr = lstExpr.get(lstExpr.size() - 1);
if (expr.type == Exprent.EXPRENT_EXIT) { if (expr.type == Exprent.EXPRENT_EXIT) {
ExitExprent ex = (ExitExprent)expr; ExitExprent ex = (ExitExprent)expr;
if (ex.getExittype() == ExitExprent.EXIT_RETURN && ex.getValue() == null) { if (ex.getExitType() == ExitExprent.EXIT_RETURN && ex.getValue() == null) {
lstExpr.remove(lstExpr.size() - 1); lstExpr.remove(lstExpr.size() - 1);
source.removeSuccessor(edge); source.removeSuccessor(edge);

@ -82,7 +82,7 @@ public class ExprProcessor implements CodeConstants {
// mapConsts.put(new Integer(opc_i2s), new // mapConsts.put(new Integer(opc_i2s), new
// Integer(FunctionExprent.FUNCTION_I2S)); // Integer(FunctionExprent.FUNCTION_I2S));
mapConsts.put(new Integer(opc_arraylength), new Integer(FunctionExprent.FUNCTION_ARRAYLENGTH)); mapConsts.put(new Integer(opc_arraylength), new Integer(FunctionExprent.FUNCTION_ARRAY_LENGTH));
mapConsts.put(new Integer(opc_checkcast), new Integer(FunctionExprent.FUNCTION_CAST)); mapConsts.put(new Integer(opc_checkcast), new Integer(FunctionExprent.FUNCTION_CAST));
mapConsts.put(new Integer(opc_instanceof), new Integer(FunctionExprent.FUNCTION_INSTANCEOF)); mapConsts.put(new Integer(opc_instanceof), new Integer(FunctionExprent.FUNCTION_INSTANCEOF));
} }
@ -276,10 +276,14 @@ public class ExprProcessor implements CodeConstants {
private static PrimitiveExprsList copyVarExprents(PrimitiveExprsList data) { private static PrimitiveExprsList copyVarExprents(PrimitiveExprsList data) {
ExprentStack stack = data.getStack(); ExprentStack stack = data.getStack();
copyEntries(stack);
return data;
}
public static void copyEntries(List<Exprent> stack) {
for (int i = 0; i < stack.size(); i++) { for (int i = 0; i < stack.size(); i++) {
stack.set(i, stack.get(i).copy()); stack.set(i, stack.get(i).copy());
} }
return data;
} }
private static void collectCatchVars(Statement stat, FlattenStatementsHelper flatthelper, Map<String, VarExprent> map) { private static void collectCatchVars(Statement stat, FlattenStatementsHelper flatthelper, Map<String, VarExprent> map) {
@ -580,12 +584,12 @@ public class ExprProcessor implements CodeConstants {
case opc_new: case opc_new:
case opc_anewarray: case opc_anewarray:
case opc_multianewarray: case opc_multianewarray:
int arrdims = (instr.opcode == opc_new) ? 0 : (instr.opcode == opc_anewarray) ? 1 : instr.getOperand(1); int dimensions = (instr.opcode == opc_new) ? 0 : (instr.opcode == opc_anewarray) ? 1 : instr.getOperand(1);
VarType arrtype = new VarType(pool.getPrimitiveConstant(instr.getOperand(0)).getString(), true); VarType arrType = new VarType(pool.getPrimitiveConstant(instr.getOperand(0)).getString(), true);
if (instr.opcode != opc_multianewarray) { if (instr.opcode != opc_multianewarray) {
arrtype.arraydim += arrdims; arrType = arrType.resizeArrayDim(arrType.arrayDim + dimensions);
} }
pushEx(stack, exprlist, new NewExprent(arrtype, stack, arrdims, bytecode_offsets)); pushEx(stack, exprlist, new NewExprent(arrType, stack, dimensions, bytecode_offsets));
break; break;
case opc_newarray: case opc_newarray:
pushEx(stack, exprlist, new NewExprent(new VarType(arr_type[instr.getOperand(0) - 4], 1), stack, 1, bytecode_offsets)); pushEx(stack, exprlist, new NewExprent(new VarType(arr_type[instr.getOperand(0) - 4], 1), stack, 1, bytecode_offsets));
@ -597,7 +601,7 @@ public class ExprProcessor implements CodeConstants {
insertByOffsetEx(-2, stack, exprlist, -1); insertByOffsetEx(-2, stack, exprlist, -1);
break; break;
case opc_dup_x2: case opc_dup_x2:
if (stack.getByOffset(-2).getExprType().stack_size == 2) { if (stack.getByOffset(-2).getExprType().stackSize == 2) {
insertByOffsetEx(-2, stack, exprlist, -1); insertByOffsetEx(-2, stack, exprlist, -1);
} }
else { else {
@ -605,7 +609,7 @@ public class ExprProcessor implements CodeConstants {
} }
break; break;
case opc_dup2: case opc_dup2:
if (stack.getByOffset(-1).getExprType().stack_size == 2) { if (stack.getByOffset(-1).getExprType().stackSize == 2) {
pushEx(stack, exprlist, stack.getByOffset(-1).copy()); pushEx(stack, exprlist, stack.getByOffset(-1).copy());
} }
else { else {
@ -614,7 +618,7 @@ public class ExprProcessor implements CodeConstants {
} }
break; break;
case opc_dup2_x1: case opc_dup2_x1:
if (stack.getByOffset(-1).getExprType().stack_size == 2) { if (stack.getByOffset(-1).getExprType().stackSize == 2) {
insertByOffsetEx(-2, stack, exprlist, -1); insertByOffsetEx(-2, stack, exprlist, -1);
} }
else { else {
@ -623,8 +627,8 @@ public class ExprProcessor implements CodeConstants {
} }
break; break;
case opc_dup2_x2: case opc_dup2_x2:
if (stack.getByOffset(-1).getExprType().stack_size == 2) { if (stack.getByOffset(-1).getExprType().stackSize == 2) {
if (stack.getByOffset(-2).getExprType().stack_size == 2) { if (stack.getByOffset(-2).getExprType().stackSize == 2) {
insertByOffsetEx(-2, stack, exprlist, -1); insertByOffsetEx(-2, stack, exprlist, -1);
} }
else { else {
@ -632,7 +636,7 @@ public class ExprProcessor implements CodeConstants {
} }
} }
else { else {
if (stack.getByOffset(-3).getExprType().stack_size == 2) { if (stack.getByOffset(-3).getExprType().stackSize == 2) {
insertByOffsetEx(-3, stack, exprlist, -2); insertByOffsetEx(-3, stack, exprlist, -2);
insertByOffsetEx(-3, stack, exprlist, -1); insertByOffsetEx(-3, stack, exprlist, -1);
} }
@ -732,7 +736,7 @@ public class ExprProcessor implements CodeConstants {
public static String getCastTypeName(VarType type, boolean getShort) { public static String getCastTypeName(VarType type, boolean getShort) {
String s = getTypeName(type, getShort); String s = getTypeName(type, getShort);
int dim = type.arraydim; int dim = type.arrayDim;
while (dim-- > 0) { while (dim-- > 0) {
s += "[]"; s += "[]";
} }
@ -755,7 +759,7 @@ public class ExprProcessor implements CodeConstants {
type == Exprent.EXPRENT_MONITOR || type == Exprent.EXPRENT_MONITOR ||
type == Exprent.EXPRENT_IF || type == Exprent.EXPRENT_IF ||
(type == Exprent.EXPRENT_VAR && ((VarExprent)expr) (type == Exprent.EXPRENT_VAR && ((VarExprent)expr)
.isClassdef())); .isClassDef()));
} }
public static TextBuffer jmpWrapper(Statement stat, int indent, boolean semicolon, BytecodeMappingTracer tracer) { public static TextBuffer jmpWrapper(Statement stat, int indent, boolean semicolon, BytecodeMappingTracer tracer) {
@ -815,11 +819,11 @@ public class ExprProcessor implements CodeConstants {
for (Exprent expr : lst) { for (Exprent expr : lst) {
TextBuffer content = expr.toJava(indent, tracer); TextBuffer content = expr.toJava(indent, tracer);
if (content.length() > 0) { if (content.length() > 0) {
if (expr.type != Exprent.EXPRENT_VAR || !((VarExprent)expr).isClassdef()) { if (expr.type != Exprent.EXPRENT_VAR || !((VarExprent)expr).isClassDef()) {
buf.appendIndent(indent); buf.appendIndent(indent);
} }
buf.append(content); buf.append(content);
if (expr.type == Exprent.EXPRENT_MONITOR && ((MonitorExprent)expr).getMontype() == MonitorExprent.MONITOR_ENTER) { if (expr.type == Exprent.EXPRENT_MONITOR && ((MonitorExprent)expr).getMonType() == MonitorExprent.MONITOR_ENTER) {
buf.append("{}"); // empty synchronized block buf.append("{}"); // empty synchronized block
} }
if (endsWithSemikolon(expr)) { if (endsWithSemikolon(expr)) {
@ -836,7 +840,7 @@ public class ExprProcessor implements CodeConstants {
public static ConstExprent getDefaultArrayValue(VarType arrtype) { public static ConstExprent getDefaultArrayValue(VarType arrtype) {
ConstExprent defaultval; ConstExprent defaultval;
if (arrtype.type == CodeConstants.TYPE_OBJECT || arrtype.arraydim > 0) { if (arrtype.type == CodeConstants.TYPE_OBJECT || arrtype.arrayDim > 0) {
defaultval = new ConstExprent(VarType.VARTYPE_NULL, null, null); defaultval = new ConstExprent(VarType.VARTYPE_NULL, null, null);
} }
else if (arrtype.type == CodeConstants.TYPE_FLOAT) { else if (arrtype.type == CodeConstants.TYPE_FLOAT) {
@ -899,7 +903,7 @@ public class ExprProcessor implements CodeConstants {
if (exprent.type == Exprent.EXPRENT_CONST) { if (exprent.type == Exprent.EXPRENT_CONST) {
ConstExprent cexpr = (ConstExprent)exprent; ConstExprent cexpr = (ConstExprent)exprent;
switch (cexpr.getConsttype().type) { switch (cexpr.getConstType().type) {
case CodeConstants.TYPE_BYTE: case CodeConstants.TYPE_BYTE:
case CodeConstants.TYPE_BYTECHAR: case CodeConstants.TYPE_BYTECHAR:
case CodeConstants.TYPE_SHORT: case CodeConstants.TYPE_SHORT:

@ -269,7 +269,7 @@ public class FinallyProcessor {
found = false; found = false;
if (exprent.type == Exprent.EXPRENT_EXIT) { if (exprent.type == Exprent.EXPRENT_EXIT) {
ExitExprent exexpr = (ExitExprent)exprent; ExitExprent exexpr = (ExitExprent)exprent;
if (exexpr.getExittype() == ExitExprent.EXIT_THROW && exexpr.getValue().type == Exprent.EXPRENT_VAR) { if (exexpr.getExitType() == ExitExprent.EXIT_THROW && exexpr.getValue().type == Exprent.EXPRENT_VAR) {
found = true; found = true;
} }
} }
@ -305,7 +305,7 @@ public class FinallyProcessor {
boolean found = false; boolean found = false;
if (next != null && next.type == Exprent.EXPRENT_EXIT) { if (next != null && next.type == Exprent.EXPRENT_EXIT) {
ExitExprent exexpr = (ExitExprent)next; ExitExprent exexpr = (ExitExprent)next;
if (exexpr.getExittype() == ExitExprent.EXIT_THROW && exexpr.getValue().type == Exprent.EXPRENT_VAR if (exexpr.getExitType() == ExitExprent.EXIT_THROW && exexpr.getValue().type == Exprent.EXPRENT_VAR
&& assexpr.getLeft().equals(exexpr.getValue())) { && assexpr.getLeft().equals(exexpr.getValue())) {
found = true; found = true;
} }

@ -68,7 +68,7 @@ public class IdeaNotNullHelper {
// TODO: FUNCTION_NE also possible if reversed order (in theory) // TODO: FUNCTION_NE also possible if reversed order (in theory)
if (ifbranch != null && if (ifbranch != null &&
if_condition.type == Exprent.EXPRENT_FUNCTION && if_condition.type == Exprent.EXPRENT_FUNCTION &&
((FunctionExprent)if_condition).getFunctype() == FunctionExprent.FUNCTION_EQ && ((FunctionExprent)if_condition).getFuncType() == FunctionExprent.FUNCTION_EQ &&
ifbranch.type == Statement.TYPE_BASICBLOCK && ifbranch.type == Statement.TYPE_BASICBLOCK &&
ifbranch.getExprents().size() == 1 && ifbranch.getExprents().size() == 1 &&
ifbranch.getExprents().get(0).type == Exprent.EXPRENT_EXIT) { ifbranch.getExprents().get(0).type == Exprent.EXPRENT_EXIT) {
@ -107,7 +107,7 @@ public class IdeaNotNullHelper {
List<AnnotationExprent> annotations = param_annotations_lists.get(i - shift); List<AnnotationExprent> annotations = param_annotations_lists.get(i - shift);
for (AnnotationExprent ann : annotations) { for (AnnotationExprent ann : annotations) {
if (ann.getClassname().equals("org/jetbrains/annotations/NotNull")) { if (ann.getClassName().equals("org/jetbrains/annotations/NotNull")) {
is_notnull_check = true; is_notnull_check = true;
} }
} }
@ -116,7 +116,7 @@ public class IdeaNotNullHelper {
break; break;
} }
index += md.params[i].stack_size; index += md.params[i].stackSize;
} }
} }
} }
@ -183,7 +183,7 @@ public class IdeaNotNullHelper {
List<AnnotationExprent> annotations = attr.getAnnotations(); List<AnnotationExprent> annotations = attr.getAnnotations();
for (AnnotationExprent ann : annotations) { for (AnnotationExprent ann : annotations) {
if (ann.getClassname().equals("org/jetbrains/annotations/NotNull")) { if (ann.getClassName().equals("org/jetbrains/annotations/NotNull")) {
is_notnull_check = true; is_notnull_check = true;
} }
} }
@ -205,7 +205,7 @@ public class IdeaNotNullHelper {
Exprent exprent = stat.getExprents().get(0); Exprent exprent = stat.getExprents().get(0);
if (exprent.type == Exprent.EXPRENT_EXIT) { if (exprent.type == Exprent.EXPRENT_EXIT) {
ExitExprent exit_exprent = (ExitExprent)exprent; ExitExprent exit_exprent = (ExitExprent)exprent;
if (exit_exprent.getExittype() == ExitExprent.EXIT_RETURN) { if (exit_exprent.getExitType() == ExitExprent.EXIT_RETURN) {
Exprent exprent_value = exit_exprent.getValue(); Exprent exprent_value = exit_exprent.getValue();
//if(exprent_value.type == Exprent.EXPRENT_VAR) { //if(exprent_value.type == Exprent.EXPRENT_VAR) {
// VarExprent var_value = (VarExprent)exprent_value; // VarExprent var_value = (VarExprent)exprent_value;
@ -214,7 +214,7 @@ public class IdeaNotNullHelper {
Exprent if_condition = ifparent.getHeadexprent().getCondition(); Exprent if_condition = ifparent.getHeadexprent().getCondition();
if (ifparent.getElsestat() == stat && if_condition.type == Exprent.EXPRENT_FUNCTION && if (ifparent.getElsestat() == stat && if_condition.type == Exprent.EXPRENT_FUNCTION &&
((FunctionExprent)if_condition).getFunctype() == FunctionExprent.FUNCTION_EQ) { // TODO: reversed order possible (in theory) ((FunctionExprent)if_condition).getFuncType() == FunctionExprent.FUNCTION_EQ) { // TODO: reversed order possible (in theory)
FunctionExprent func = (FunctionExprent)if_condition; FunctionExprent func = (FunctionExprent)if_condition;
Exprent first_param = func.getLstOperands().get(0); Exprent first_param = func.getLstOperands().get(0);
@ -268,7 +268,7 @@ public class IdeaNotNullHelper {
Exprent exprent = stat.getExprents().get(0); Exprent exprent = stat.getExprents().get(0);
if (exprent.type == Exprent.EXPRENT_EXIT) { if (exprent.type == Exprent.EXPRENT_EXIT) {
ExitExprent exit_exprent = (ExitExprent)exprent; ExitExprent exit_exprent = (ExitExprent)exprent;
if (exit_exprent.getExittype() == ExitExprent.EXIT_RETURN) { if (exit_exprent.getExitType() == ExitExprent.EXIT_RETURN) {
Exprent exprent_value = exit_exprent.getValue(); Exprent exprent_value = exit_exprent.getValue();
SequenceStatement sequence = (SequenceStatement)parent; SequenceStatement sequence = (SequenceStatement)parent;
@ -282,7 +282,7 @@ public class IdeaNotNullHelper {
Exprent if_condition = ifstat.getHeadexprent().getCondition(); Exprent if_condition = ifstat.getHeadexprent().getCondition();
if (ifstat.iftype == IfStatement.IFTYPE_IF && if_condition.type == Exprent.EXPRENT_FUNCTION && if (ifstat.iftype == IfStatement.IFTYPE_IF && if_condition.type == Exprent.EXPRENT_FUNCTION &&
((FunctionExprent)if_condition).getFunctype() == FunctionExprent.FUNCTION_EQ) { // TODO: reversed order possible (in theory) ((FunctionExprent)if_condition).getFuncType() == FunctionExprent.FUNCTION_EQ) { // TODO: reversed order possible (in theory)
FunctionExprent func = (FunctionExprent)if_condition; FunctionExprent func = (FunctionExprent)if_condition;
Exprent first_param = func.getLstOperands().get(0); Exprent first_param = func.getLstOperands().get(0);

@ -252,7 +252,7 @@ public class IfHelper {
List<Exprent> lstOperands = new ArrayList<Exprent>(); List<Exprent> lstOperands = new ArrayList<Exprent>();
lstOperands.add(statexpr.getCondition()); lstOperands.add(statexpr.getCondition());
lstOperands.add(new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT, lstOperands.add(new FunctionExprent(FunctionExprent.FUNCTION_BOOL_NOT,
Arrays.asList(ifchild.getHeadexprent().getCondition()), null)); Arrays.asList(ifchild.getHeadexprent().getCondition()), null));
statexpr.setCondition(new FunctionExprent(FunctionExprent.FUNCTION_CADD, lstOperands, null)); statexpr.setCondition(new FunctionExprent(FunctionExprent.FUNCTION_CADD, lstOperands, null));
statexpr.addBytecodeOffsets(ifchild.getHeadexprent().bytecode); statexpr.addBytecodeOffsets(ifchild.getHeadexprent().bytecode);
@ -310,7 +310,7 @@ public class IfHelper {
lstOperands.add(firstif.getHeadexprent().getCondition()); lstOperands.add(firstif.getHeadexprent().getCondition());
if (path == 2) { if (path == 2) {
lstOperands.set(0, new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT, lstOperands.set(0, new FunctionExprent(FunctionExprent.FUNCTION_BOOL_NOT,
Arrays.asList(lstOperands.get(0)), null)); Arrays.asList(lstOperands.get(0)), null));
} }
@ -361,7 +361,7 @@ public class IfHelper {
// negate the if condition // negate the if condition
IfExprent statexpr = firstif.getHeadexprent(); IfExprent statexpr = firstif.getHeadexprent();
statexpr statexpr
.setCondition(new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT, Arrays.asList(statexpr.getCondition()), null)); .setCondition(new FunctionExprent(FunctionExprent.FUNCTION_BOOL_NOT, Arrays.asList(statexpr.getCondition()), null));
return true; return true;
} }
@ -556,7 +556,7 @@ public class IfHelper {
// negate the if condition // negate the if condition
IfExprent statexpr = ifstat.getHeadexprent(); IfExprent statexpr = ifstat.getHeadexprent();
statexpr.setCondition(new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT, Arrays.asList(statexpr.getCondition()), null)); statexpr.setCondition(new FunctionExprent(FunctionExprent.FUNCTION_BOOL_NOT, Arrays.asList(statexpr.getCondition()), null));
if (noelsestat) { if (noelsestat) {
StatEdge ifedge = ifstat.getIfEdge(); StatEdge ifedge = ifstat.getIfEdge();

@ -109,8 +109,8 @@ public class PPandMMHelper {
FunctionExprent func = (FunctionExprent)as.getRight(); FunctionExprent func = (FunctionExprent)as.getRight();
VarType midlayer = null; VarType midlayer = null;
if (func.getFunctype() >= FunctionExprent.FUNCTION_I2L && if (func.getFuncType() >= FunctionExprent.FUNCTION_I2L &&
func.getFunctype() <= FunctionExprent.FUNCTION_I2S) { func.getFuncType() <= FunctionExprent.FUNCTION_I2S) {
midlayer = func.getSimpleCastType(); midlayer = func.getSimpleCastType();
if (func.getLstOperands().get(0).type == Exprent.EXPRENT_FUNCTION) { if (func.getLstOperands().get(0).type == Exprent.EXPRENT_FUNCTION) {
func = (FunctionExprent)func.getLstOperands().get(0); func = (FunctionExprent)func.getLstOperands().get(0);
@ -120,13 +120,13 @@ public class PPandMMHelper {
} }
} }
if (func.getFunctype() == FunctionExprent.FUNCTION_ADD || if (func.getFuncType() == FunctionExprent.FUNCTION_ADD ||
func.getFunctype() == FunctionExprent.FUNCTION_SUB) { func.getFuncType() == FunctionExprent.FUNCTION_SUB) {
Exprent econd = func.getLstOperands().get(0); Exprent econd = func.getLstOperands().get(0);
Exprent econst = func.getLstOperands().get(1); Exprent econst = func.getLstOperands().get(1);
if (econst.type != Exprent.EXPRENT_CONST && econd.type == Exprent.EXPRENT_CONST && if (econst.type != Exprent.EXPRENT_CONST && econd.type == Exprent.EXPRENT_CONST &&
func.getFunctype() == FunctionExprent.FUNCTION_ADD) { func.getFuncType() == FunctionExprent.FUNCTION_ADD) {
econd = econst; econd = econst;
econst = func.getLstOperands().get(0); econst = func.getLstOperands().get(0);
} }
@ -137,7 +137,7 @@ public class PPandMMHelper {
VarType condtype = econd.getExprType(); VarType condtype = econd.getExprType();
if (left.equals(econd) && (midlayer == null || midlayer.equals(condtype))) { if (left.equals(econd) && (midlayer == null || midlayer.equals(condtype))) {
FunctionExprent ret = new FunctionExprent( FunctionExprent ret = new FunctionExprent(
func.getFunctype() == FunctionExprent.FUNCTION_ADD ? FunctionExprent.FUNCTION_PPI : FunctionExprent.FUNCTION_MMI, func.getFuncType() == FunctionExprent.FUNCTION_ADD ? FunctionExprent.FUNCTION_PPI : FunctionExprent.FUNCTION_MMI,
Arrays.asList(econd), func.bytecode); Arrays.asList(econd), func.bytecode);
ret.setImplicitType(condtype); ret.setImplicitType(condtype);

@ -142,8 +142,8 @@ public class SecondaryFunctionsHelper {
if (exprent.type == Exprent.EXPRENT_FUNCTION) { if (exprent.type == Exprent.EXPRENT_FUNCTION) {
FunctionExprent fexpr = (FunctionExprent)exprent; FunctionExprent fexpr = (FunctionExprent)exprent;
switch (fexpr.getFunctype()) { switch (fexpr.getFuncType()) {
case FunctionExprent.FUNCTION_BOOLNOT: case FunctionExprent.FUNCTION_BOOL_NOT:
Exprent retparam = propagateBoolNot(fexpr); Exprent retparam = propagateBoolNot(fexpr);
@ -170,14 +170,14 @@ public class SecondaryFunctionsHelper {
FunctionExprent funcexpr = (FunctionExprent)expr1; FunctionExprent funcexpr = (FunctionExprent)expr1;
ConstExprent cexpr = (ConstExprent)expr2; ConstExprent cexpr = (ConstExprent)expr2;
int functype = funcexpr.getFunctype(); int functype = funcexpr.getFuncType();
if (functype == FunctionExprent.FUNCTION_LCMP || functype == FunctionExprent.FUNCTION_FCMPG || if (functype == FunctionExprent.FUNCTION_LCMP || functype == FunctionExprent.FUNCTION_FCMPG ||
functype == FunctionExprent.FUNCTION_FCMPL || functype == FunctionExprent.FUNCTION_DCMPG || functype == FunctionExprent.FUNCTION_FCMPL || functype == FunctionExprent.FUNCTION_DCMPG ||
functype == FunctionExprent.FUNCTION_DCMPL) { functype == FunctionExprent.FUNCTION_DCMPL) {
int desttype = -1; int desttype = -1;
Integer[] destcons = mapNumComparisons.get(fexpr.getFunctype()); Integer[] destcons = mapNumComparisons.get(fexpr.getFuncType());
if (destcons != null) { if (destcons != null) {
int index = cexpr.getIntValue() + 1; int index = cexpr.getIntValue() + 1;
if (index >= 0 && index <= 2) { if (index >= 0 && index <= 2) {
@ -216,7 +216,7 @@ public class SecondaryFunctionsHelper {
FunctionExprent fexpr = (FunctionExprent)exprent; FunctionExprent fexpr = (FunctionExprent)exprent;
List<Exprent> lstOperands = fexpr.getLstOperands(); List<Exprent> lstOperands = fexpr.getLstOperands();
switch (fexpr.getFunctype()) { switch (fexpr.getFuncType()) {
case FunctionExprent.FUNCTION_XOR: case FunctionExprent.FUNCTION_XOR:
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
Exprent operand = lstOperands.get(i); Exprent operand = lstOperands.get(i);
@ -236,7 +236,7 @@ public class SecondaryFunctionsHelper {
if (val == -1) { if (val == -1) {
List<Exprent> lstBitNotOperand = new ArrayList<Exprent>(); List<Exprent> lstBitNotOperand = new ArrayList<Exprent>();
lstBitNotOperand.add(lstOperands.get(1 - i)); lstBitNotOperand.add(lstOperands.get(1 - i));
return new FunctionExprent(FunctionExprent.FUNCTION_BITNOT, lstBitNotOperand, fexpr.bytecode); return new FunctionExprent(FunctionExprent.FUNCTION_BIT_NOT, lstBitNotOperand, fexpr.bytecode);
} }
} }
} }
@ -250,20 +250,20 @@ public class SecondaryFunctionsHelper {
ConstExprent cexpr = (ConstExprent)lstOperands.get(i); ConstExprent cexpr = (ConstExprent)lstOperands.get(i);
int val = ((Integer)cexpr.getValue()).intValue(); int val = ((Integer)cexpr.getValue()).intValue();
if ((fexpr.getFunctype() == FunctionExprent.FUNCTION_EQ && val == 1) || if ((fexpr.getFuncType() == FunctionExprent.FUNCTION_EQ && val == 1) ||
(fexpr.getFunctype() == FunctionExprent.FUNCTION_NE && val == 0)) { (fexpr.getFuncType() == FunctionExprent.FUNCTION_NE && val == 0)) {
return lstOperands.get(1 - i); return lstOperands.get(1 - i);
} }
else { else {
List<Exprent> lstNotOperand = new ArrayList<Exprent>(); List<Exprent> lstNotOperand = new ArrayList<Exprent>();
lstNotOperand.add(lstOperands.get(1 - i)); lstNotOperand.add(lstOperands.get(1 - i));
return new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT, lstNotOperand, fexpr.bytecode); return new FunctionExprent(FunctionExprent.FUNCTION_BOOL_NOT, lstNotOperand, fexpr.bytecode);
} }
} }
} }
} }
break; break;
case FunctionExprent.FUNCTION_BOOLNOT: case FunctionExprent.FUNCTION_BOOL_NOT:
if (lstOperands.get(0).type == Exprent.EXPRENT_CONST) { if (lstOperands.get(0).type == Exprent.EXPRENT_CONST) {
int val = ((ConstExprent)lstOperands.get(0)).getIntValue(); int val = ((ConstExprent)lstOperands.get(0)).getIntValue();
if (val == 0) { if (val == 0) {
@ -286,7 +286,7 @@ public class SecondaryFunctionsHelper {
cexpr2.getExprType().type == CodeConstants.TYPE_BOOLEAN) { cexpr2.getExprType().type == CodeConstants.TYPE_BOOLEAN) {
if (cexpr1.getIntValue() == 0 && cexpr2.getIntValue() != 0) { if (cexpr1.getIntValue() == 0 && cexpr2.getIntValue() != 0) {
return new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT, Arrays.asList(lstOperands.get(0)), fexpr.bytecode); return new FunctionExprent(FunctionExprent.FUNCTION_BOOL_NOT, Arrays.asList(lstOperands.get(0)), fexpr.bytecode);
} }
else if (cexpr1.getIntValue() != 0 && cexpr2.getIntValue() == 0) { else if (cexpr1.getIntValue() != 0 && cexpr2.getIntValue() == 0) {
return lstOperands.get(0); return lstOperands.get(0);
@ -330,8 +330,8 @@ public class SecondaryFunctionsHelper {
FunctionExprent func = (FunctionExprent)right; FunctionExprent func = (FunctionExprent)right;
VarType midlayer = null; VarType midlayer = null;
if (func.getFunctype() >= FunctionExprent.FUNCTION_I2L && if (func.getFuncType() >= FunctionExprent.FUNCTION_I2L &&
func.getFunctype() <= FunctionExprent.FUNCTION_I2S) { func.getFuncType() <= FunctionExprent.FUNCTION_I2S) {
right = func.getLstOperands().get(0); right = func.getLstOperands().get(0);
midlayer = func.getSimpleCastType(); midlayer = func.getSimpleCastType();
if (right.type == Exprent.EXPRENT_FUNCTION) { if (right.type == Exprent.EXPRENT_FUNCTION) {
@ -346,7 +346,7 @@ public class SecondaryFunctionsHelper {
Exprent cond = null; Exprent cond = null;
switch (func.getFunctype()) { switch (func.getFuncType()) {
case FunctionExprent.FUNCTION_ADD: case FunctionExprent.FUNCTION_ADD:
case FunctionExprent.FUNCTION_AND: case FunctionExprent.FUNCTION_AND:
case FunctionExprent.FUNCTION_OR: case FunctionExprent.FUNCTION_OR:
@ -369,7 +369,7 @@ public class SecondaryFunctionsHelper {
if (cond != null && (midlayer == null || midlayer.equals(cond.getExprType()))) { if (cond != null && (midlayer == null || midlayer.equals(cond.getExprType()))) {
asexpr.setRight(cond); asexpr.setRight(cond);
asexpr.setCondtype(func.getFunctype()); asexpr.setCondType(func.getFuncType());
} }
} }
break; break;
@ -390,16 +390,16 @@ public class SecondaryFunctionsHelper {
if (exprent.type == Exprent.EXPRENT_FUNCTION) { if (exprent.type == Exprent.EXPRENT_FUNCTION) {
FunctionExprent fexpr = (FunctionExprent)exprent; FunctionExprent fexpr = (FunctionExprent)exprent;
if (fexpr.getFunctype() == FunctionExprent.FUNCTION_BOOLNOT) { if (fexpr.getFuncType() == FunctionExprent.FUNCTION_BOOL_NOT) {
Exprent param = fexpr.getLstOperands().get(0); Exprent param = fexpr.getLstOperands().get(0);
if (param.type == Exprent.EXPRENT_FUNCTION) { if (param.type == Exprent.EXPRENT_FUNCTION) {
FunctionExprent fparam = (FunctionExprent)param; FunctionExprent fparam = (FunctionExprent)param;
int ftype = fparam.getFunctype(); int ftype = fparam.getFuncType();
switch (ftype) { switch (ftype) {
case FunctionExprent.FUNCTION_BOOLNOT: case FunctionExprent.FUNCTION_BOOL_NOT:
Exprent newexpr = fparam.getLstOperands().get(0); Exprent newexpr = fparam.getLstOperands().get(0);
Exprent retexpr = propagateBoolNot(newexpr); Exprent retexpr = propagateBoolNot(newexpr);
return retexpr == null ? newexpr : retexpr; return retexpr == null ? newexpr : retexpr;
@ -407,7 +407,7 @@ public class SecondaryFunctionsHelper {
case FunctionExprent.FUNCTION_COR: case FunctionExprent.FUNCTION_COR:
List<Exprent> operands = fparam.getLstOperands(); List<Exprent> operands = fparam.getLstOperands();
for (int i = 0; i < operands.size(); i++) { for (int i = 0; i < operands.size(); i++) {
Exprent newparam = new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT, Exprent newparam = new FunctionExprent(FunctionExprent.FUNCTION_BOOL_NOT,
Arrays.asList(operands.get(i)), operands.get(i).bytecode); Arrays.asList(operands.get(i)), operands.get(i).bytecode);
Exprent retparam = propagateBoolNot(newparam); Exprent retparam = propagateBoolNot(newparam);
@ -419,7 +419,7 @@ public class SecondaryFunctionsHelper {
case FunctionExprent.FUNCTION_GE: case FunctionExprent.FUNCTION_GE:
case FunctionExprent.FUNCTION_GT: case FunctionExprent.FUNCTION_GT:
case FunctionExprent.FUNCTION_LE: case FunctionExprent.FUNCTION_LE:
fparam.setFunctype(funcsnot[ftype - FunctionExprent.FUNCTION_EQ]); fparam.setFuncType(funcsnot[ftype - FunctionExprent.FUNCTION_EQ]);
return fparam; return fparam;
} }
} }

@ -229,8 +229,7 @@ public class SimplifyExprentsHelper {
if (init.type == Exprent.EXPRENT_CONST) { if (init.type == Exprent.EXPRENT_CONST) {
ConstExprent cinit = (ConstExprent)init; ConstExprent cinit = (ConstExprent)init;
VarType arrtype = newex.getNewtype().copy(); VarType arrtype = newex.getNewType().decreaseArrayDim();
arrtype.decArrayDim();
ConstExprent defaultval = ExprProcessor.getDefaultArrayValue(arrtype); ConstExprent defaultval = ExprProcessor.getDefaultArrayValue(arrtype);
@ -243,7 +242,7 @@ public class SimplifyExprentsHelper {
if (tempexpr.type == Exprent.EXPRENT_NEW) { if (tempexpr.type == Exprent.EXPRENT_NEW) {
NewExprent tempnewex = (NewExprent)tempexpr; NewExprent tempnewex = (NewExprent)tempexpr;
int dims = newex.getNewtype().arraydim; int dims = newex.getNewType().arrayDim;
if (dims > 1 && !tempnewex.getLstArrayElements().isEmpty()) { if (dims > 1 && !tempnewex.getLstArrayElements().isEmpty()) {
tempnewex.setDirectArrayInit(true); tempnewex.setDirectArrayInit(true);
} }
@ -274,7 +273,7 @@ public class SimplifyExprentsHelper {
if (as.getRight().type == Exprent.EXPRENT_NEW && as.getLeft().type == Exprent.EXPRENT_VAR) { if (as.getRight().type == Exprent.EXPRENT_NEW && as.getLeft().type == Exprent.EXPRENT_VAR) {
NewExprent newex = (NewExprent)as.getRight(); NewExprent newex = (NewExprent)as.getRight();
if (newex.getExprType().arraydim > 0 && newex.getLstDims().size() == 1 && newex.getLstArrayElements().isEmpty() && if (newex.getExprType().arrayDim > 0 && newex.getLstDims().size() == 1 && newex.getLstArrayElements().isEmpty() &&
newex.getLstDims().get(0).type == Exprent.EXPRENT_CONST) { newex.getLstDims().get(0).type == Exprent.EXPRENT_CONST) {
int size = ((Integer)((ConstExprent)newex.getLstDims().get(0)).getValue()).intValue(); int size = ((Integer)((ConstExprent)newex.getLstDims().get(0)).getValue()).intValue();
@ -326,8 +325,7 @@ public class SimplifyExprentsHelper {
List<Exprent> lstRet = new ArrayList<Exprent>(); List<Exprent> lstRet = new ArrayList<Exprent>();
VarType arrtype = newex.getNewtype().copy(); VarType arrtype = newex.getNewType().decreaseArrayDim();
arrtype.decArrayDim();
ConstExprent defaultval = ExprProcessor.getDefaultArrayValue(arrtype); ConstExprent defaultval = ExprProcessor.getDefaultArrayValue(arrtype);
@ -335,7 +333,7 @@ public class SimplifyExprentsHelper {
lstRet.add(defaultval.copy()); lstRet.add(defaultval.copy());
} }
int dims = newex.getNewtype().arraydim; int dims = newex.getNewType().arrayDim;
for (Entry<Integer, Exprent> ent : mapInit.entrySet()) { for (Entry<Integer, Exprent> ent : mapInit.entrySet()) {
Exprent tempexpr = ent.getValue(); Exprent tempexpr = ent.getValue();
lstRet.set(ent.getKey(), tempexpr); lstRet.set(ent.getKey(), tempexpr);
@ -433,13 +431,13 @@ public class SimplifyExprentsHelper {
if (as.getRight().type == Exprent.EXPRENT_FUNCTION) { if (as.getRight().type == Exprent.EXPRENT_FUNCTION) {
FunctionExprent func = (FunctionExprent)as.getRight(); FunctionExprent func = (FunctionExprent)as.getRight();
if (func.getFunctype() == FunctionExprent.FUNCTION_ADD || if (func.getFuncType() == FunctionExprent.FUNCTION_ADD ||
func.getFunctype() == FunctionExprent.FUNCTION_SUB) { func.getFuncType() == FunctionExprent.FUNCTION_SUB) {
Exprent econd = func.getLstOperands().get(0); Exprent econd = func.getLstOperands().get(0);
Exprent econst = func.getLstOperands().get(1); Exprent econst = func.getLstOperands().get(1);
if (econst.type != Exprent.EXPRENT_CONST && econd.type == Exprent.EXPRENT_CONST && if (econst.type != Exprent.EXPRENT_CONST && econd.type == Exprent.EXPRENT_CONST &&
func.getFunctype() == FunctionExprent.FUNCTION_ADD) { func.getFuncType() == FunctionExprent.FUNCTION_ADD) {
econd = econst; econd = econst;
econst = func.getLstOperands().get(0); econst = func.getLstOperands().get(0);
} }
@ -449,7 +447,7 @@ public class SimplifyExprentsHelper {
if (left.type != Exprent.EXPRENT_VAR && left.equals(econd)) { if (left.type != Exprent.EXPRENT_VAR && left.equals(econd)) {
FunctionExprent ret = new FunctionExprent( FunctionExprent ret = new FunctionExprent(
func.getFunctype() == FunctionExprent.FUNCTION_ADD ? FunctionExprent.FUNCTION_PPI : FunctionExprent.FUNCTION_MMI, func.getFuncType() == FunctionExprent.FUNCTION_ADD ? FunctionExprent.FUNCTION_PPI : FunctionExprent.FUNCTION_MMI,
Arrays.asList(econd), func.bytecode); Arrays.asList(econd), func.bytecode);
ret.setImplicitType(VarType.VARTYPE_INT); ret.setImplicitType(VarType.VARTYPE_INT);
return ret; return ret;
@ -468,14 +466,14 @@ public class SimplifyExprentsHelper {
AssignmentExprent as = (AssignmentExprent)first; AssignmentExprent as = (AssignmentExprent)first;
FunctionExprent in = (FunctionExprent)second; FunctionExprent in = (FunctionExprent)second;
if ((in.getFunctype() == FunctionExprent.FUNCTION_MMI || in.getFunctype() == FunctionExprent.FUNCTION_PPI) && if ((in.getFuncType() == FunctionExprent.FUNCTION_MMI || in.getFuncType() == FunctionExprent.FUNCTION_PPI) &&
in.getLstOperands().get(0).equals(as.getRight())) { in.getLstOperands().get(0).equals(as.getRight())) {
if (in.getFunctype() == FunctionExprent.FUNCTION_MMI) { if (in.getFuncType() == FunctionExprent.FUNCTION_MMI) {
in.setFunctype(FunctionExprent.FUNCTION_IMM); in.setFuncType(FunctionExprent.FUNCTION_IMM);
} }
else { else {
in.setFunctype(FunctionExprent.FUNCTION_IPP); in.setFuncType(FunctionExprent.FUNCTION_IPP);
} }
as.setRight(in); as.setRight(in);
@ -489,7 +487,7 @@ public class SimplifyExprentsHelper {
private static boolean isMonitorExit(Exprent first) { private static boolean isMonitorExit(Exprent first) {
if (first.type == Exprent.EXPRENT_MONITOR) { if (first.type == Exprent.EXPRENT_MONITOR) {
MonitorExprent monexpr = (MonitorExprent)first; MonitorExprent monexpr = (MonitorExprent)first;
if (monexpr.getMontype() == MonitorExprent.MONITOR_EXIT && monexpr.getValue().type == Exprent.EXPRENT_VAR if (monexpr.getMonType() == MonitorExprent.MONITOR_EXIT && monexpr.getValue().type == Exprent.EXPRENT_VAR
&& !((VarExprent)monexpr.getValue()).isStack()) { && !((VarExprent)monexpr.getValue()).isStack()) {
return true; return true;
} }
@ -515,7 +513,7 @@ public class SimplifyExprentsHelper {
if (nexpr.getConstructor() != null && !nexpr.getConstructor().getLstParameters().isEmpty() && if (nexpr.getConstructor() != null && !nexpr.getConstructor().getLstParameters().isEmpty() &&
nexpr.getConstructor().getLstParameters().get(0).equals(invexpr.getInstance())) { nexpr.getConstructor().getLstParameters().get(0).equals(invexpr.getInstance())) {
String classname = nexpr.getNewtype().value; String classname = nexpr.getNewType().value;
ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(classname); ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(classname);
if (node != null && node.type != ClassNode.CLASS_ROOT) { if (node != null && node.type != ClassNode.CLASS_ROOT) {
return true; return true;
@ -539,10 +537,10 @@ public class SimplifyExprentsHelper {
// if(as.getLeft().type == Exprent.EXPRENT_VAR && as.getRight().type == Exprent.EXPRENT_NEW) { // if(as.getLeft().type == Exprent.EXPRENT_VAR && as.getRight().type == Exprent.EXPRENT_NEW) {
// //
// NewExprent newexpr = (NewExprent)as.getRight(); // NewExprent newexpr = (NewExprent)as.getRight();
// VarType newtype = newexpr.getNewtype(); // VarType newtype = newexpr.getNewType();
// VarVersionPaar leftPaar = new VarVersionPaar((VarExprent)as.getLeft()); // VarVersionPaar leftPaar = new VarVersionPaar((VarExprent)as.getLeft());
// //
// if(newtype.type == CodeConstants.TYPE_OBJECT && newtype.arraydim == 0 && // if(newtype.type == CodeConstants.TYPE_OBJECT && newtype.arrayDim == 0 &&
// newexpr.getConstructor() == null) { // newexpr.getConstructor() == null) {
// //
// Set<VarVersionPaar> setChangedVars = new HashSet<VarVersionPaar>(); // Set<VarVersionPaar> setChangedVars = new HashSet<VarVersionPaar>();
@ -553,7 +551,7 @@ public class SimplifyExprentsHelper {
// if(remote.type == Exprent.EXPRENT_INVOCATION) { // if(remote.type == Exprent.EXPRENT_INVOCATION) {
// InvocationExprent in = (InvocationExprent)remote; // InvocationExprent in = (InvocationExprent)remote;
// //
// if(in.getFunctype() == InvocationExprent.TYP_INIT && in.getInstance().type == Exprent.EXPRENT_VAR // if(in.getFuncType() == InvocationExprent.TYP_INIT && in.getInstance().type == Exprent.EXPRENT_VAR
// && as.getLeft().equals(in.getInstance())) { // && as.getLeft().equals(in.getInstance())) {
// //
// Set<VarVersionPaar> setVars = remote.getAllVariables(); // Set<VarVersionPaar> setVars = remote.getAllVariables();
@ -613,8 +611,8 @@ public class SimplifyExprentsHelper {
//// } //// }
//// } else if(remote.type == Exprent.EXPRENT_FUNCTION) { //// } else if(remote.type == Exprent.EXPRENT_FUNCTION) {
//// FunctionExprent fexpr = (FunctionExprent)remote; //// FunctionExprent fexpr = (FunctionExprent)remote;
//// if(fexpr.getFunctype() == FunctionExprent.FUNCTION_IPP || fexpr.getFunctype() == FunctionExprent.FUNCTION_IMM //// if(fexpr.getFuncType() == FunctionExprent.FUNCTION_IPP || fexpr.getFuncType() == FunctionExprent.FUNCTION_IMM
//// || fexpr.getFunctype() == FunctionExprent.FUNCTION_PPI || fexpr.getFunctype() == FunctionExprent.FUNCTION_MMI) { //// || fexpr.getFuncType() == FunctionExprent.FUNCTION_PPI || fexpr.getFuncType() == FunctionExprent.FUNCTION_MMI) {
//// if(fexpr.getLstOperands().get(0).type == Exprent.EXPRENT_VAR) { //// if(fexpr.getLstOperands().get(0).type == Exprent.EXPRENT_VAR) {
//// setChangedVars.add(new VarVersionPaar((VarExprent)fexpr.getLstOperands().get(0))); //// setChangedVars.add(new VarVersionPaar((VarExprent)fexpr.getLstOperands().get(0)));
//// isTempAssignment = true; //// isTempAssignment = true;
@ -649,10 +647,10 @@ public class SimplifyExprentsHelper {
if (as.getLeft().type == Exprent.EXPRENT_VAR && as.getRight().type == Exprent.EXPRENT_NEW) { if (as.getLeft().type == Exprent.EXPRENT_VAR && as.getRight().type == Exprent.EXPRENT_NEW) {
NewExprent newexpr = (NewExprent)as.getRight(); NewExprent newexpr = (NewExprent)as.getRight();
VarType newtype = newexpr.getNewtype(); VarType newtype = newexpr.getNewType();
VarVersionPaar leftPaar = new VarVersionPaar((VarExprent)as.getLeft()); VarVersionPaar leftPaar = new VarVersionPaar((VarExprent)as.getLeft());
if (newtype.type == CodeConstants.TYPE_OBJECT && newtype.arraydim == 0 && newexpr.getConstructor() == null) { if (newtype.type == CodeConstants.TYPE_OBJECT && newtype.arrayDim == 0 && newexpr.getConstructor() == null) {
for (int i = index + 1; i < list.size(); i++) { for (int i = index + 1; i < list.size(); i++) {
Exprent remote = list.get(i); Exprent remote = list.get(i);
@ -819,12 +817,12 @@ public class SimplifyExprentsHelper {
ExitExprent ifex = (ExitExprent)ifexpr; ExitExprent ifex = (ExitExprent)ifexpr;
ExitExprent elseex = (ExitExprent)elseexpr; ExitExprent elseex = (ExitExprent)elseexpr;
if (ifex.getExittype() == elseex.getExittype() && ifex.getValue() != null && elseex.getValue() != null && if (ifex.getExitType() == elseex.getExitType() && ifex.getValue() != null && elseex.getValue() != null &&
ifex.getExittype() == ExitExprent.EXIT_RETURN) { ifex.getExitType() == ExitExprent.EXIT_RETURN) {
// throw is dangerous, because of implicit casting to a common superclass // throw is dangerous, because of implicit casting to a common superclass
// e.g. throws IOException and throw true?new RuntimeException():new IOException(); won't work // e.g. throws IOException and throw true?new RuntimeException():new IOException(); won't work
if (ifex.getExittype() == ExitExprent.EXIT_THROW && if (ifex.getExitType() == ExitExprent.EXIT_THROW &&
!ifex.getValue().getExprType().equals(elseex.getValue().getExprType())) { // note: getExprType unreliable at this point! !ifex.getValue().getExprType().equals(elseex.getValue().getExprType())) { // note: getExprType unreliable at this point!
return false; return false;
} }
@ -832,11 +830,11 @@ public class SimplifyExprentsHelper {
List<Exprent> data = new ArrayList<Exprent>(); List<Exprent> data = new ArrayList<Exprent>();
data.addAll(stif.getFirst().getExprents()); data.addAll(stif.getFirst().getExprents());
data.add(new ExitExprent(ifex.getExittype(), new FunctionExprent(FunctionExprent.FUNCTION_IIF, data.add(new ExitExprent(ifex.getExitType(), new FunctionExprent(FunctionExprent.FUNCTION_IIF,
Arrays.asList( Arrays.asList(
stif.getHeadexprent().getCondition(), stif.getHeadexprent().getCondition(),
ifex.getValue(), ifex.getValue(),
elseex.getValue()), ifheadexpr_bytecode), ifex.getRettype(), ifheadexpr_bytecode)); elseex.getValue()), ifheadexpr_bytecode), ifex.getRetType(), ifheadexpr_bytecode));
stif.setExprents(data); stif.setExprents(data);
StatEdge retedge = ifstat.getAllSuccessorEdges().get(0); StatEdge retedge = ifstat.getAllSuccessorEdges().get(0);

@ -338,8 +338,8 @@ public class StackVarsProcessor {
if (right.type == Exprent.EXPRENT_NEW) { if (right.type == Exprent.EXPRENT_NEW) {
// new Object(); permitted // new Object(); permitted
NewExprent nexpr = (NewExprent)right; NewExprent nexpr = (NewExprent)right;
if (nexpr.isAnonymous() || nexpr.getNewtype().arraydim > 0 if (nexpr.isAnonymous() || nexpr.getNewType().arrayDim > 0
|| nexpr.getNewtype().type != CodeConstants.TYPE_OBJECT) { || nexpr.getNewType().type != CodeConstants.TYPE_OBJECT) {
return new int[]{-1, changed}; return new int[]{-1, changed};
} }
} }
@ -511,7 +511,7 @@ public class StackVarsProcessor {
boolean isHeadSynchronized = false; boolean isHeadSynchronized = false;
if (next == null && parent.type == Exprent.EXPRENT_MONITOR) { if (next == null && parent.type == Exprent.EXPRENT_MONITOR) {
MonitorExprent monexpr = (MonitorExprent)parent; MonitorExprent monexpr = (MonitorExprent)parent;
if (monexpr.getMontype() == MonitorExprent.MONITOR_ENTER && exprent.equals(monexpr.getValue())) { if (monexpr.getMonType() == MonitorExprent.MONITOR_ENTER && exprent.equals(monexpr.getValue())) {
isHeadSynchronized = true; isHeadSynchronized = true;
} }
} }

@ -23,28 +23,21 @@ import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.util.List; import java.util.List;
public class AnnotationExprent extends Exprent { public class AnnotationExprent extends Exprent {
public static final int ANNOTATION_NORMAL = 1; public static final int ANNOTATION_NORMAL = 1;
public static final int ANNOTATION_MARKER = 2; public static final int ANNOTATION_MARKER = 2;
public static final int ANNOTATION_SINGLE_ELEMENT = 3; public static final int ANNOTATION_SINGLE_ELEMENT = 3;
private final String className;
private final List<String> parNames;
private final List<Exprent> parValues;
private String classname; public AnnotationExprent(String className, List<String> parNames, List<Exprent> parValues) {
super(EXPRENT_ANNOTATION);
private List<String> parnames; this.className = className;
this.parNames = parNames;
private List<Exprent> parvalues; this.parValues = parValues;
{
this.type = EXPRENT_ANNOTATION;
}
public AnnotationExprent(String classname, List<String> parnames, List<Exprent> parvalues) {
this.classname = classname;
this.parnames = parnames;
this.parvalues = parvalues;
} }
@Override @Override
@ -53,21 +46,21 @@ public class AnnotationExprent extends Exprent {
buffer.appendIndent(indent); buffer.appendIndent(indent);
buffer.append("@"); buffer.append("@");
buffer.append(DecompilerContext.getImportCollector().getShortName(ExprProcessor.buildJavaClassName(classname))); buffer.append(DecompilerContext.getImportCollector().getShortName(ExprProcessor.buildJavaClassName(className)));
if (!parnames.isEmpty()) { if (!parNames.isEmpty()) {
buffer.append("("); buffer.append("(");
if (parnames.size() == 1 && "value".equals(parnames.get(0))) { if (parNames.size() == 1 && "value".equals(parNames.get(0))) {
buffer.append(parvalues.get(0).toJava(indent + 1, tracer)); buffer.append(parValues.get(0).toJava(indent + 1, tracer));
} }
else { else {
for (int i = 0; i < parnames.size(); i++) { for (int i = 0; i < parNames.size(); i++) {
buffer.appendLineSeparator().appendIndent(indent + 1); buffer.appendLineSeparator().appendIndent(indent + 1);
buffer.append(parnames.get(i)); buffer.append(parNames.get(i));
buffer.append(" = "); buffer.append(" = ");
buffer.append(parvalues.get(i).toJava(indent + 2, tracer)); buffer.append(parValues.get(i).toJava(indent + 2, tracer));
if (i < parnames.size() - 1) { if (i < parNames.size() - 1) {
buffer.append(","); buffer.append(",");
} }
} }
@ -80,32 +73,30 @@ public class AnnotationExprent extends Exprent {
return buffer; return buffer;
} }
public int getAnnotationType() { public String getClassName() {
return className;
}
if (parnames.isEmpty()) { public int getAnnotationType() {
if (parNames.isEmpty()) {
return ANNOTATION_MARKER; return ANNOTATION_MARKER;
} }
else if (parNames.size() == 1 && "value".equals(parNames.get(0))) {
return ANNOTATION_SINGLE_ELEMENT;
}
else { else {
if (parnames.size() == 1 && "value".equals(parnames.get(0))) { return ANNOTATION_NORMAL;
return ANNOTATION_SINGLE_ELEMENT;
}
else {
return ANNOTATION_NORMAL;
}
} }
} }
@Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (o == this) return true; if (o == this) return true;
if (o == null || !(o instanceof AnnotationExprent)) return false; if (o == null || !(o instanceof AnnotationExprent)) return false;
AnnotationExprent ann = (AnnotationExprent)o; AnnotationExprent ann = (AnnotationExprent)o;
return classname.equals(ann.classname) && return className.equals(ann.className) &&
InterpreterUtil.equalLists(parnames, ann.parnames) && InterpreterUtil.equalLists(parNames, ann.parNames) &&
InterpreterUtil.equalLists(parvalues, ann.parvalues); InterpreterUtil.equalLists(parValues, ann.parValues);
}
public String getClassname() {
return classname;
} }
} }

@ -16,8 +16,6 @@
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.TextBuffer;
import java.util.Set;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult; import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult;
@ -26,43 +24,37 @@ import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set;
public class ArrayExprent extends Exprent { public class ArrayExprent extends Exprent {
private Exprent array; private Exprent array;
private Exprent index; private Exprent index;
private final VarType hardType;
private VarType hardtype; public ArrayExprent(Exprent array, Exprent index, VarType hardType, Set<Integer> bytecodeOffsets) {
super(EXPRENT_ARRAY);
{
this.type = EXPRENT_ARRAY;
}
public ArrayExprent(Exprent array, Exprent index, VarType hardtype, Set<Integer> bytecode_offsets) {
this.array = array; this.array = array;
this.index = index; this.index = index;
this.hardtype = hardtype; this.hardType = hardType;
addBytecodeOffsets(bytecode_offsets); addBytecodeOffsets(bytecodeOffsets);
} }
@Override @Override
public Exprent copy() { public Exprent copy() {
return new ArrayExprent(array.copy(), index.copy(), hardtype, bytecode); return new ArrayExprent(array.copy(), index.copy(), hardType, bytecode);
} }
@Override
public VarType getExprType() { public VarType getExprType() {
VarType exprType = array.getExprType().copy(); VarType exprType = array.getExprType();
if (exprType.equals(VarType.VARTYPE_NULL)) { if (exprType.equals(VarType.VARTYPE_NULL)) {
exprType = hardtype.copy(); return hardType.copy();
} }
else { else {
exprType.decArrayDim(); return exprType.decreaseArrayDim();
} }
return exprType;
} }
public int getExprentUse() { public int getExprentUse() {
@ -71,10 +63,8 @@ public class ArrayExprent extends Exprent {
public CheckTypesResult checkExprTypeBounds() { public CheckTypesResult checkExprTypeBounds() {
CheckTypesResult result = new CheckTypesResult(); CheckTypesResult result = new CheckTypesResult();
result.addMinTypeExprent(index, VarType.VARTYPE_BYTECHAR); result.addMinTypeExprent(index, VarType.VARTYPE_BYTECHAR);
result.addMaxTypeExprent(index, VarType.VARTYPE_INT); result.addMaxTypeExprent(index, VarType.VARTYPE_INT);
return result; return result;
} }
@ -85,7 +75,6 @@ public class ArrayExprent extends Exprent {
return lst; return lst;
} }
@Override @Override
public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) {
TextBuffer res = array.toJava(indent, tracer); TextBuffer res = array.toJava(indent, tracer);
@ -94,12 +83,10 @@ public class ArrayExprent extends Exprent {
res.enclose("(", ")"); res.enclose("(", ")");
} }
VarType arrtype = array.getExprType(); VarType arrType = array.getExprType();
if (arrtype.arraydim == 0) { if (arrType.arrayDim == 0) {
VarType objarr = VarType.VARTYPE_OBJECT.copy(); VarType objArr = VarType.VARTYPE_OBJECT.resizeArrayDim(1); // type family does not change
objarr.arraydim = 1; // type family does not change res.enclose("((" + ExprProcessor.getCastTypeName(objArr) + ")", ")");
res.enclose("((" + ExprProcessor.getCastTypeName(objarr) + ")", ")");
} }
tracer.addMapping(bytecode); tracer.addMapping(bytecode);
@ -107,6 +94,17 @@ public class ArrayExprent extends Exprent {
return res.append("[").append(index.toJava(indent, tracer)).append("]"); return res.append("[").append(index.toJava(indent, tracer)).append("]");
} }
@Override
public void replaceExprent(Exprent oldExpr, Exprent newExpr) {
if (oldExpr == array) {
array = newExpr;
}
if (oldExpr == index) {
index = newExpr;
}
}
@Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (o == this) return true; if (o == this) return true;
if (o == null || !(o instanceof ArrayExprent)) return false; if (o == null || !(o instanceof ArrayExprent)) return false;
@ -116,16 +114,6 @@ public class ArrayExprent extends Exprent {
InterpreterUtil.equalObjects(index, arr.getIndex()); InterpreterUtil.equalObjects(index, arr.getIndex());
} }
public void replaceExprent(Exprent oldexpr, Exprent newexpr) {
if (oldexpr == array) {
array = newexpr;
}
if (oldexpr == index) {
index = newexpr;
}
}
public Exprent getArray() { public Exprent getArray() {
return array; return array;
} }

@ -15,26 +15,22 @@
*/ */
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import java.util.List;
import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.TextBuffer;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
public class AssertExprent extends Exprent { import java.util.List;
private List<Exprent> parameters; public class AssertExprent extends Exprent {
{ private final List<Exprent> parameters;
this.type = EXPRENT_ASSERT;
}
public AssertExprent(List<Exprent> parameters) { public AssertExprent(List<Exprent> parameters) {
super(EXPRENT_ASSERT);
this.parameters = parameters; this.parameters = parameters;
} }
@Override @Override
public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) {
TextBuffer buffer = new TextBuffer(); TextBuffer buffer = new TextBuffer();
buffer.append("assert "); buffer.append("assert ");

@ -15,84 +15,77 @@
*/ */
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.TextBuffer;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult; import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult;
import org.jetbrains.java.decompiler.struct.StructField; import org.jetbrains.java.decompiler.struct.StructField;
import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class AssignmentExprent extends Exprent { public class AssignmentExprent extends Exprent {
public static final int CONDITION_NONE = -1; public static final int CONDITION_NONE = -1;
private static final String[] funceq = new String[]{ private static final String[] OPERATORS = {
" += ", // FUNCTION_ADD " += ", // FUNCTION_ADD
" -= ", // FUNCTION_SUB " -= ", // FUNCTION_SUB
" *= ", // FUNCTION_MUL " *= ", // FUNCTION_MUL
" /= ", // FUNCTION_DIV " /= ", // FUNCTION_DIV
" &= ", // FUNCTION_AND " &= ", // FUNCTION_AND
" |= ", // FUNCTION_OR " |= ", // FUNCTION_OR
" ^= ", // FUNCTION_XOR " ^= ", // FUNCTION_XOR
" %= ", // FUNCTION_REM " %= ", // FUNCTION_REM
" <<= ", // FUNCTION_SHL " <<= ", // FUNCTION_SHL
" >>= ", // FUNCTION_SHR " >>= ", // FUNCTION_SHR
" >>>= " // FUNCTION_USHR " >>>= " // FUNCTION_USHR
}; };
private Exprent left; private Exprent left;
private Exprent right; private Exprent right;
private int condType = CONDITION_NONE;
private int condtype = CONDITION_NONE; public AssignmentExprent(Exprent left, Exprent right, Set<Integer> bytecodeOffsets) {
super(EXPRENT_ASSIGNMENT);
{
this.type = EXPRENT_ASSIGNMENT;
}
public AssignmentExprent(Exprent left, Exprent right, Set<Integer> bytecode_offsets) {
this.left = left; this.left = left;
this.right = right; this.right = right;
addBytecodeOffsets(bytecode_offsets); addBytecodeOffsets(bytecodeOffsets);
} }
@Override
public VarType getExprType() { public VarType getExprType() {
return left.getExprType(); return left.getExprType();
} }
@Override
public CheckTypesResult checkExprTypeBounds() { public CheckTypesResult checkExprTypeBounds() {
CheckTypesResult result = new CheckTypesResult(); CheckTypesResult result = new CheckTypesResult();
VarType typeleft = left.getExprType(); VarType typeLeft = left.getExprType();
VarType typeright = right.getExprType(); VarType typeRight = right.getExprType();
if (typeleft.type_family > typeright.type_family) { if (typeLeft.typeFamily > typeRight.typeFamily) {
result.addMinTypeExprent(right, VarType.getMinTypeInFamily(typeleft.type_family)); result.addMinTypeExprent(right, VarType.getMinTypeInFamily(typeLeft.typeFamily));
} }
else if (typeleft.type_family < typeright.type_family) { else if (typeLeft.typeFamily < typeRight.typeFamily) {
result.addMinTypeExprent(left, typeright); result.addMinTypeExprent(left, typeRight);
} }
else { else {
result.addMinTypeExprent(left, VarType.getCommonSupertype(typeleft, typeright)); result.addMinTypeExprent(left, VarType.getCommonSupertype(typeLeft, typeRight));
} }
return result; return result;
} }
@Override
public List<Exprent> getAllExprents() { public List<Exprent> getAllExprents() {
List<Exprent> lst = new ArrayList<Exprent>(); List<Exprent> lst = new ArrayList<Exprent>();
lst.add(left); lst.add(left);
@ -105,6 +98,7 @@ public class AssignmentExprent extends Exprent {
return new AssignmentExprent(left.copy(), right.copy(), bytecode); return new AssignmentExprent(left.copy(), right.copy(), bytecode);
} }
@Override
public int getPrecedence() { public int getPrecedence() {
return 13; return 13;
} }
@ -146,7 +140,7 @@ public class AssignmentExprent extends Exprent {
TextBuffer res = right.toJava(indent, tracer); TextBuffer res = right.toJava(indent, tracer);
if (condtype == CONDITION_NONE && if (condType == CONDITION_NONE &&
!leftType.isSuperset(rightType) && !leftType.isSuperset(rightType) &&
(rightType.equals(VarType.VARTYPE_OBJECT) || leftType.type != CodeConstants.TYPE_OBJECT)) { (rightType.equals(VarType.VARTYPE_OBJECT) || leftType.type != CodeConstants.TYPE_OBJECT)) {
if (right.getPrecedence() >= FunctionExprent.getPrecedence(FunctionExprent.FUNCTION_CAST)) { if (right.getPrecedence() >= FunctionExprent.getPrecedence(FunctionExprent.FUNCTION_CAST)) {
@ -156,13 +150,24 @@ public class AssignmentExprent extends Exprent {
res.prepend("(" + ExprProcessor.getCastTypeName(leftType) + ")"); res.prepend("(" + ExprProcessor.getCastTypeName(leftType) + ")");
} }
buffer.append(condtype == CONDITION_NONE ? " = " : funceq[condtype]).append(res); buffer.append(condType == CONDITION_NONE ? " = " : OPERATORS[condType]).append(res);
tracer.addMapping(bytecode); tracer.addMapping(bytecode);
return buffer; return buffer;
} }
@Override
public void replaceExprent(Exprent oldExpr, Exprent newExpr) {
if (oldExpr == left) {
left = newExpr;
}
if (oldExpr == right) {
right = newExpr;
}
}
@Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (o == this) return true; if (o == this) return true;
if (o == null || !(o instanceof AssignmentExprent)) return false; if (o == null || !(o instanceof AssignmentExprent)) return false;
@ -170,17 +175,7 @@ public class AssignmentExprent extends Exprent {
AssignmentExprent as = (AssignmentExprent)o; AssignmentExprent as = (AssignmentExprent)o;
return InterpreterUtil.equalObjects(left, as.getLeft()) && return InterpreterUtil.equalObjects(left, as.getLeft()) &&
InterpreterUtil.equalObjects(right, as.getRight()) && InterpreterUtil.equalObjects(right, as.getRight()) &&
condtype == as.getCondtype(); condType == as.getCondType();
}
public void replaceExprent(Exprent oldexpr, Exprent newexpr) {
if (oldexpr == left) {
left = newexpr;
}
if (oldexpr == right) {
right = newexpr;
}
} }
// ***************************************************************************** // *****************************************************************************
@ -203,11 +198,11 @@ public class AssignmentExprent extends Exprent {
this.right = right; this.right = right;
} }
public int getCondtype() { public int getCondType() {
return condtype; return condType;
} }
public void setCondtype(int condtype) { public void setCondType(int condType) {
this.condtype = condtype; this.condType = condType;
} }
} }

@ -15,11 +15,6 @@
*/ */
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.TextBuffer;
@ -30,82 +25,79 @@ import org.jetbrains.java.decompiler.struct.gen.FieldDescriptor;
import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.util.*;
public class ConstExprent extends Exprent { public class ConstExprent extends Exprent {
private static final HashMap<Integer, String> escapes = new HashMap<Integer, String>(); private static final Map<Integer, String> ESCAPES = new HashMap<Integer, String>() {{
put(new Integer(0x8), "\\b"); /* \u0008: backspace BS */
static { put(new Integer(0x9), "\\t"); /* \u0009: horizontal tab HT */
escapes.put(new Integer(0x8), "\\b"); /* \u0008: backspace BS */ put(new Integer(0xA), "\\n"); /* \u000a: linefeed LF */
escapes.put(new Integer(0x9), "\\t"); /* \u0009: horizontal tab HT */ put(new Integer(0xC), "\\f"); /* \u000c: form feed FF */
escapes.put(new Integer(0xA), "\\n"); /* \u000a: linefeed LF */ put(new Integer(0xD), "\\r"); /* \u000d: carriage return CR */
escapes.put(new Integer(0xC), "\\f"); /* \u000c: form feed FF */ put(new Integer(0x22), "\\\""); /* \u0022: double quote " */
escapes.put(new Integer(0xD), "\\r"); /* \u000d: carriage return CR */ put(new Integer(0x27), "\\\'"); /* \u0027: single quote ' */
escapes.put(new Integer(0x22), "\\\""); /* \u0022: double quote " */ put(new Integer(0x5C), "\\\\"); /* \u005c: backslash \ */
escapes.put(new Integer(0x27), "\\\'"); /* \u0027: single quote ' */ }};
escapes.put(new Integer(0x5C), "\\\\"); /* \u005c: backslash \ */
private VarType constType;
private final Object value;
private final boolean boolPermitted;
public ConstExprent(int val, boolean boolPermitted, Set<Integer> bytecodeOffsets) {
this(guessType(val, boolPermitted), new Integer(val), boolPermitted, bytecodeOffsets);
} }
public ConstExprent(VarType constType, Object value, Set<Integer> bytecodeOffsets) {
private VarType consttype; this(constType, value, false, bytecodeOffsets);
private Object value;
private boolean boolPermitted;
{
this.type = EXPRENT_CONST;
} }
public ConstExprent(int val, boolean boolPermitted, Set<Integer> bytecode_offsets) { private ConstExprent(VarType constType, Object value, boolean boolPermitted, Set<Integer> bytecodeOffsets) {
super(EXPRENT_CONST);
this.constType = constType;
this.value = value;
this.boolPermitted = boolPermitted; this.boolPermitted = boolPermitted;
addBytecodeOffsets(bytecodeOffsets);
}
private static VarType guessType(int val, boolean boolPermitted) {
if (boolPermitted) { if (boolPermitted) {
consttype = VarType.VARTYPE_BOOLEAN; VarType constType = VarType.VARTYPE_BOOLEAN;
if (val != 0 && val != 1) { if (val != 0 && val != 1) {
consttype = consttype.copy(); constType = constType.copy(true);
consttype.convinfo |= VarType.FALSEBOOLEAN;
} }
return constType;
}
else if (0 <= val && val <= 127) {
return VarType.VARTYPE_BYTECHAR;
}
else if (-128 <= val && val <= 127) {
return VarType.VARTYPE_BYTE;
}
else if (0 <= val && val <= 32767) {
return VarType.VARTYPE_SHORTCHAR;
}
else if (-32768 <= val && val <= 32767) {
return VarType.VARTYPE_SHORT;
}
else if (0 <= val && val <= 0xFFFF) {
return VarType.VARTYPE_CHAR;
} }
else { else {
if (0 <= val && val <= 127) { return VarType.VARTYPE_INT;
consttype = VarType.VARTYPE_BYTECHAR;
}
else if (-128 <= val && val <= 127) {
consttype = VarType.VARTYPE_BYTE;
}
else if (0 <= val && val <= 32767) {
consttype = VarType.VARTYPE_SHORTCHAR;
}
else if (-32768 <= val && val <= 32767) {
consttype = VarType.VARTYPE_SHORT;
}
else if (0 <= val && val <= 0xFFFF) {
consttype = VarType.VARTYPE_CHAR;
}
else {
consttype = VarType.VARTYPE_INT;
}
} }
value = new Integer(val);
addBytecodeOffsets(bytecode_offsets);
}
public ConstExprent(VarType consttype, Object value, Set<Integer> bytecode_offsets) {
this.consttype = consttype;
this.value = value;
addBytecodeOffsets(bytecode_offsets);
} }
@Override @Override
public Exprent copy() { public Exprent copy() {
return new ConstExprent(consttype, value, bytecode); return new ConstExprent(constType, value, bytecode);
} }
@Override
public VarType getExprType() { public VarType getExprType() {
return consttype; return constType;
} }
@Override
public int getExprentUse() { public int getExprentUse() {
return Exprent.MULTIPLE_USES | Exprent.SIDE_EFFECTS_FREE; return Exprent.MULTIPLE_USES | Exprent.SIDE_EFFECTS_FREE;
} }
@ -121,16 +113,16 @@ public class ConstExprent extends Exprent {
tracer.addMapping(bytecode); tracer.addMapping(bytecode);
if (consttype.type != CodeConstants.TYPE_NULL && value == null) { if (constType.type != CodeConstants.TYPE_NULL && value == null) {
return new TextBuffer(ExprProcessor.getCastTypeName(consttype)); return new TextBuffer(ExprProcessor.getCastTypeName(constType));
} }
else { else {
switch (consttype.type) { switch (constType.type) {
case CodeConstants.TYPE_BOOLEAN: case CodeConstants.TYPE_BOOLEAN:
return new TextBuffer(Boolean.toString(((Integer)value).intValue() != 0)); return new TextBuffer(Boolean.toString(((Integer)value).intValue() != 0));
case CodeConstants.TYPE_CHAR: case CodeConstants.TYPE_CHAR:
Integer val = (Integer)value; Integer val = (Integer)value;
String ret = escapes.get(val); String ret = ESCAPES.get(val);
if (ret == null) { if (ret == null) {
char c = (char)val.intValue(); char c = (char)val.intValue();
if (c >= 32 && c < 127 || !ascii && InterpreterUtil.isPrintableUnicode(c)) { if (c >= 32 && c < 127 || !ascii && InterpreterUtil.isPrintableUnicode(c)) {
@ -256,10 +248,10 @@ public class ConstExprent extends Exprent {
case CodeConstants.TYPE_NULL: case CodeConstants.TYPE_NULL:
return new TextBuffer("null"); return new TextBuffer("null");
case CodeConstants.TYPE_OBJECT: case CodeConstants.TYPE_OBJECT:
if (consttype.equals(VarType.VARTYPE_STRING)) { if (constType.equals(VarType.VARTYPE_STRING)) {
return new TextBuffer(convertStringToJava(value.toString(), ascii)).enclose("\"", "\""); return new TextBuffer(convertStringToJava(value.toString(), ascii)).enclose("\"", "\"");
} }
else if (consttype.equals(VarType.VARTYPE_CLASS)) { else if (constType.equals(VarType.VARTYPE_CLASS)) {
String strval = value.toString(); String strval = value.toString();
VarType classtype; VarType classtype;
@ -321,19 +313,18 @@ public class ConstExprent extends Exprent {
return buffer.toString(); return buffer.toString();
} }
@Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (o == this) return true; if (o == this) return true;
if (o == null || !(o instanceof ConstExprent)) return false; if (o == null || !(o instanceof ConstExprent)) return false;
ConstExprent cn = (ConstExprent)o; ConstExprent cn = (ConstExprent)o;
return InterpreterUtil.equalObjects(consttype, cn.getConsttype()) && return InterpreterUtil.equalObjects(constType, cn.getConstType()) &&
InterpreterUtil.equalObjects(value, cn.getValue()); InterpreterUtil.equalObjects(value, cn.getValue());
} }
public boolean hasBooleanValue() { public boolean hasBooleanValue() {
switch (constType.type) {
switch (consttype.type) {
case CodeConstants.TYPE_BOOLEAN: case CodeConstants.TYPE_BOOLEAN:
case CodeConstants.TYPE_CHAR: case CodeConstants.TYPE_CHAR:
case CodeConstants.TYPE_BYTE: case CodeConstants.TYPE_BYTE:
@ -350,8 +341,7 @@ public class ConstExprent extends Exprent {
} }
public boolean hasValueOne() { public boolean hasValueOne() {
switch (constType.type) {
switch (consttype.type) {
case CodeConstants.TYPE_BOOLEAN: case CodeConstants.TYPE_BOOLEAN:
case CodeConstants.TYPE_CHAR: case CodeConstants.TYPE_CHAR:
case CodeConstants.TYPE_BYTE: case CodeConstants.TYPE_BYTE:
@ -372,7 +362,6 @@ public class ConstExprent extends Exprent {
} }
public static ConstExprent getZeroConstant(int type) { public static ConstExprent getZeroConstant(int type) {
switch (type) { switch (type) {
case CodeConstants.TYPE_INT: case CodeConstants.TYPE_INT:
return new ConstExprent(VarType.VARTYPE_INT, new Integer(0), null); return new ConstExprent(VarType.VARTYPE_INT, new Integer(0), null);
@ -387,12 +376,12 @@ public class ConstExprent extends Exprent {
throw new RuntimeException("Invalid argument!"); throw new RuntimeException("Invalid argument!");
} }
public VarType getConsttype() { public VarType getConstType() {
return consttype; return constType;
} }
public void setConsttype(VarType consttype) { public void setConstType(VarType constType) {
this.consttype = consttype; this.constType = constType;
} }
public Object getValue() { public Object getValue() {
@ -406,8 +395,4 @@ public class ConstExprent extends Exprent {
public boolean isBoolPermitted() { public boolean isBoolPermitted() {
return boolPermitted; return boolPermitted;
} }
public void setBoolPermitted(boolean boolPermitted) {
this.boolPermitted = boolPermitted;
}
} }

@ -15,10 +15,6 @@
*/ */
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
@ -31,47 +27,46 @@ import org.jetbrains.java.decompiler.struct.attr.StructExceptionsAttribute;
import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class ExitExprent extends Exprent { public class ExitExprent extends Exprent {
public static final int EXIT_RETURN = 0; public static final int EXIT_RETURN = 0;
public static final int EXIT_THROW = 1; public static final int EXIT_THROW = 1;
// return or throw statement private final int exitType;
private int exittype;
private Exprent value; private Exprent value;
private final VarType retType;
private VarType rettype; public ExitExprent(int exitType, Exprent value, VarType retType, Set<Integer> bytecodeOffsets) {
super(EXPRENT_EXIT);
{ this.exitType = exitType;
this.type = EXPRENT_EXIT;
}
public ExitExprent(int exittype, Exprent value, VarType rettype, Set<Integer> bytecode_offsets) {
this.exittype = exittype;
this.value = value; this.value = value;
this.rettype = rettype; this.retType = retType;
addBytecodeOffsets(bytecode_offsets); addBytecodeOffsets(bytecodeOffsets);
} }
@Override @Override
public Exprent copy() { public Exprent copy() {
return new ExitExprent(exittype, value == null ? null : value.copy(), rettype, bytecode); return new ExitExprent(exitType, value == null ? null : value.copy(), retType, bytecode);
} }
@Override
public CheckTypesResult checkExprTypeBounds() { public CheckTypesResult checkExprTypeBounds() {
CheckTypesResult result = new CheckTypesResult(); CheckTypesResult result = new CheckTypesResult();
if (exittype == EXIT_RETURN && rettype.type != CodeConstants.TYPE_VOID) { if (exitType == EXIT_RETURN && retType.type != CodeConstants.TYPE_VOID) {
result.addMinTypeExprent(value, VarType.getMinTypeInFamily(rettype.type_family)); result.addMinTypeExprent(value, VarType.getMinTypeInFamily(retType.typeFamily));
result.addMaxTypeExprent(value, rettype); result.addMaxTypeExprent(value, retType);
} }
return result; return result;
} }
@Override
public List<Exprent> getAllExprents() { public List<Exprent> getAllExprents() {
List<Exprent> lst = new ArrayList<Exprent>(); List<Exprent> lst = new ArrayList<Exprent>();
if (value != null) { if (value != null) {
@ -82,47 +77,43 @@ public class ExitExprent extends Exprent {
@Override @Override
public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) {
tracer.addMapping(bytecode); tracer.addMapping(bytecode);
if (exittype == EXIT_RETURN) { if (exitType == EXIT_RETURN) {
TextBuffer buffer = new TextBuffer(); TextBuffer buffer = new TextBuffer();
if (rettype.type != CodeConstants.TYPE_VOID) { if (retType.type != CodeConstants.TYPE_VOID) {
buffer.append(" "); buffer.append(" ");
ExprProcessor.getCastedExprent(value, rettype, buffer, indent, false, tracer); ExprProcessor.getCastedExprent(value, retType, buffer, indent, false, tracer);
} }
return buffer.prepend("return"); return buffer.prepend("return");
} }
else { else {
MethodWrapper method = (MethodWrapper)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD_WRAPPER);
MethodWrapper meth = (MethodWrapper)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD_WRAPPER);
ClassNode node = ((ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE)); ClassNode node = ((ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE));
if (meth != null && node != null) { if (method != null && node != null) {
StructExceptionsAttribute attr = (StructExceptionsAttribute)meth.methodStruct.getAttributes().getWithKey("Exceptions"); StructExceptionsAttribute attr = (StructExceptionsAttribute)method.methodStruct.getAttributes().getWithKey("Exceptions");
if (attr != null) { if (attr != null) {
String classname = null; String classname = null;
for (int i = 0; i < attr.getThrowsExceptions().size(); i++) { for (int i = 0; i < attr.getThrowsExceptions().size(); i++) {
String excclassname = attr.getExcClassname(i, node.classStruct.getPool()); String exClassName = attr.getExcClassname(i, node.classStruct.getPool());
if ("java/lang/Throwable".equals(excclassname)) { if ("java/lang/Throwable".equals(exClassName)) {
classname = excclassname; classname = exClassName;
break; break;
} }
else if ("java/lang/Exception".equals(excclassname)) { else if ("java/lang/Exception".equals(exClassName)) {
classname = excclassname; classname = exClassName;
} }
} }
if (classname != null) { if (classname != null) {
VarType exctype = new VarType(classname, true); VarType exType = new VarType(classname, true);
TextBuffer buffer = new TextBuffer(); TextBuffer buffer = new TextBuffer();
ExprProcessor.getCastedExprent(value, exctype, buffer, indent, false, tracer); ExprProcessor.getCastedExprent(value, exType, buffer, indent, false, tracer);
return buffer.prepend("throw "); return buffer.prepend("throw ");
} }
} }
@ -132,30 +123,32 @@ public class ExitExprent extends Exprent {
} }
} }
@Override
public void replaceExprent(Exprent oldExpr, Exprent newExpr) {
if (oldExpr == value) {
value = newExpr;
}
}
@Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (o == this) return true; if (o == this) return true;
if (o == null || !(o instanceof ExitExprent)) return false; if (o == null || !(o instanceof ExitExprent)) return false;
ExitExprent et = (ExitExprent)o; ExitExprent et = (ExitExprent)o;
return exittype == et.getExittype() && return exitType == et.getExitType() &&
InterpreterUtil.equalObjects(value, et.getValue()); InterpreterUtil.equalObjects(value, et.getValue());
} }
public void replaceExprent(Exprent oldexpr, Exprent newexpr) { public int getExitType() {
if (oldexpr == value) { return exitType;
value = newexpr;
}
}
public int getExittype() {
return exittype;
} }
public Exprent getValue() { public Exprent getValue() {
return value; return value;
} }
public VarType getRettype() { public VarType getRetType() {
return rettype; return retType;
} }
} }

@ -15,12 +15,6 @@
*/ */
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.TextBuffer;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
@ -29,6 +23,7 @@ import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPaar; import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPaar;
import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.VarType;
import java.util.*;
public class Exprent { public class Exprent {
@ -36,7 +31,6 @@ public class Exprent {
public static final int SIDE_EFFECTS_FREE = 2; public static final int SIDE_EFFECTS_FREE = 2;
public static final int BOTH_FLAGS = 3; public static final int BOTH_FLAGS = 3;
public static final int EXPRENT_ARRAY = 1; public static final int EXPRENT_ARRAY = 1;
public static final int EXPRENT_ASSIGNMENT = 2; public static final int EXPRENT_ASSIGNMENT = 2;
public static final int EXPRENT_CONST = 3; public static final int EXPRENT_CONST = 3;
@ -52,16 +46,13 @@ public class Exprent {
public static final int EXPRENT_ANNOTATION = 13; public static final int EXPRENT_ANNOTATION = 13;
public static final int EXPRENT_ASSERT = 14; public static final int EXPRENT_ASSERT = 14;
public int type; public final int type;
public final int id;
public int id; public final Set<Integer> bytecode = new HashSet<Integer>(); // offsets of bytecode instructions decompiled to this exprent
//offsets of bytecode instructions decompiled to this exprent public Exprent(int type) {
public Set<Integer> bytecode = new HashSet<Integer>(); this.type = type;
this.id = DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.EXPRENT_COUNTER);
{
// set exprent id
id = DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.EXPRENT_COUNTER);
} }
public int getPrecedence() { public int getPrecedence() {
@ -81,12 +72,11 @@ public class Exprent {
} }
public boolean containsExprent(Exprent exprent) { public boolean containsExprent(Exprent exprent) {
List<Exprent> listTemp = new ArrayList<Exprent>(getAllExprents(true)); List<Exprent> listTemp = new ArrayList<Exprent>(getAllExprents(true));
listTemp.add(this); listTemp.add(this);
for (Exprent lstexpr : listTemp) { for (Exprent lstExpr : listTemp) {
if (lstexpr.equals(exprent)) { if (lstExpr.equals(exprent)) {
return true; return true;
} }
} }
@ -96,29 +86,24 @@ public class Exprent {
public List<Exprent> getAllExprents(boolean recursive) { public List<Exprent> getAllExprents(boolean recursive) {
List<Exprent> lst = getAllExprents(); List<Exprent> lst = getAllExprents();
if (recursive) { if (recursive) {
for (int i = lst.size() - 1; i >= 0; i--) { for (int i = lst.size() - 1; i >= 0; i--) {
lst.addAll(lst.get(i).getAllExprents(true)); lst.addAll(lst.get(i).getAllExprents(true));
} }
} }
return lst; return lst;
} }
public Set<VarVersionPaar> getAllVariables() { public Set<VarVersionPaar> getAllVariables() {
HashSet<VarVersionPaar> set = new HashSet<VarVersionPaar>();
List<Exprent> lstAllExprents = getAllExprents(true); List<Exprent> lstAllExprents = getAllExprents(true);
lstAllExprents.add(this); lstAllExprents.add(this);
Set<VarVersionPaar> set = new HashSet<VarVersionPaar>();
for (Exprent expr : lstAllExprents) { for (Exprent expr : lstAllExprents) {
if (expr.type == EXPRENT_VAR) { if (expr.type == EXPRENT_VAR) {
set.add(new VarVersionPaar((VarExprent)expr)); set.add(new VarVersionPaar((VarExprent)expr));
} }
} }
return set; return set;
} }
@ -134,12 +119,11 @@ public class Exprent {
throw new RuntimeException("not implemented"); throw new RuntimeException("not implemented");
} }
public void replaceExprent(Exprent oldexpr, Exprent newexpr) { public void replaceExprent(Exprent oldExpr, Exprent newExpr) { }
}
public void addBytecodeOffsets(Collection<Integer> bytecode_offsets) { public void addBytecodeOffsets(Collection<Integer> bytecodeOffsets) {
if(bytecode_offsets != null) { if (bytecodeOffsets != null) {
bytecode.addAll(bytecode_offsets); bytecode.addAll(bytecodeOffsets);
} }
} }
} }

@ -15,10 +15,6 @@
*/ */
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.DecompilerContext;
@ -27,67 +23,50 @@ import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.main.rels.MethodWrapper; import org.jetbrains.java.decompiler.main.rels.MethodWrapper;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPaar; import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPaar;
import org.jetbrains.java.decompiler.struct.StructClass;
import org.jetbrains.java.decompiler.struct.consts.LinkConstant; import org.jetbrains.java.decompiler.struct.consts.LinkConstant;
import org.jetbrains.java.decompiler.struct.gen.FieldDescriptor; import org.jetbrains.java.decompiler.struct.gen.FieldDescriptor;
import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
import org.jetbrains.java.decompiler.util.TextUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class FieldExprent extends Exprent { public class FieldExprent extends Exprent {
private String name; private final String name;
private final String classname;
private String classname; private final boolean isStatic;
private boolean isStatic;
private Exprent instance; private Exprent instance;
private final FieldDescriptor descriptor;
private FieldDescriptor descriptor; public FieldExprent(LinkConstant cn, Exprent instance, Set<Integer> bytecodeOffsets) {
this(cn.elementname, cn.classname, instance == null, instance, FieldDescriptor.parseDescriptor(cn.descriptor), bytecodeOffsets);
{
this.type = EXPRENT_FIELD;
}
public FieldExprent(LinkConstant cn, Exprent instance, Set<Integer> bytecode_offsets) {
this.instance = instance;
if (instance == null) {
isStatic = true;
}
classname = cn.classname;
name = cn.elementname;
descriptor = FieldDescriptor.parseDescriptor(cn.descriptor);
addBytecodeOffsets(bytecode_offsets);
} }
public FieldExprent(String name, String classname, boolean isStatic, Exprent instance, FieldDescriptor descriptor, Set<Integer> bytecode_offsets) { public FieldExprent(String name, String classname, boolean isStatic, Exprent instance, FieldDescriptor descriptor, Set<Integer> bytecodeOffsets) {
super(EXPRENT_FIELD);
this.name = name; this.name = name;
this.classname = classname; this.classname = classname;
this.isStatic = isStatic; this.isStatic = isStatic;
this.instance = instance; this.instance = instance;
this.descriptor = descriptor; this.descriptor = descriptor;
addBytecodeOffsets(bytecode_offsets); addBytecodeOffsets(bytecodeOffsets);
} }
@Override
public VarType getExprType() { public VarType getExprType() {
return descriptor.type; return descriptor.type;
} }
@Override
public int getExprentUse() { public int getExprentUse() {
if (instance == null) { return instance == null ? Exprent.MULTIPLE_USES : instance.getExprentUse() & Exprent.MULTIPLE_USES;
return Exprent.MULTIPLE_USES;
}
else {
return instance.getExprentUse() & Exprent.MULTIPLE_USES;
}
} }
@Override
public List<Exprent> getAllExprents() { public List<Exprent> getAllExprents() {
List<Exprent> lst = new ArrayList<Exprent>(); List<Exprent> lst = new ArrayList<Exprent>();
if (instance != null) { if (instance != null) {
@ -105,7 +84,6 @@ public class FieldExprent extends Exprent {
public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) {
TextBuffer buf = new TextBuffer(); TextBuffer buf = new TextBuffer();
if (isStatic) { if (isStatic) {
ClassNode node = (ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE); ClassNode node = (ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE);
if (node == null || !classname.equals(node.classStruct.qualifiedName)) { if (node == null || !classname.equals(node.classStruct.qualifiedName)) {
@ -114,17 +92,16 @@ public class FieldExprent extends Exprent {
} }
} }
else { else {
String super_qualifier = null; String super_qualifier = null;
if (instance != null && instance.type == Exprent.EXPRENT_VAR) { if (instance != null && instance.type == Exprent.EXPRENT_VAR) {
VarExprent instvar = (VarExprent)instance; VarExprent instVar = (VarExprent)instance;
VarVersionPaar varpaar = new VarVersionPaar(instvar); VarVersionPaar pair = new VarVersionPaar(instVar);
MethodWrapper current_meth = (MethodWrapper)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD_WRAPPER); MethodWrapper currentMethod = (MethodWrapper)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD_WRAPPER);
if (current_meth != null) { // FIXME: remove if (currentMethod != null) { // FIXME: remove
String this_classname = current_meth.varproc.getThisvars().get(varpaar); String this_classname = currentMethod.varproc.getThisVars().get(pair);
if (this_classname != null) { if (this_classname != null) {
if (!classname.equals(this_classname)) { // TODO: direct comparison to the super class? if (!classname.equals(this_classname)) { // TODO: direct comparison to the super class?
@ -135,13 +112,7 @@ public class FieldExprent extends Exprent {
} }
if (super_qualifier != null) { if (super_qualifier != null) {
StructClass current_class = ((ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE)).classStruct; TextUtil.writeQualifiedSuper(buf, super_qualifier);
if (!super_qualifier.equals(current_class.qualifiedName)) {
buf.append(DecompilerContext.getImportCollector().getShortName(ExprProcessor.buildJavaClassName(super_qualifier)));
buf.append(".");
}
buf.append("super");
} }
else { else {
TextBuffer buff = new TextBuffer(); TextBuffer buff = new TextBuffer();
@ -171,6 +142,14 @@ public class FieldExprent extends Exprent {
return buf; return buf;
} }
@Override
public void replaceExprent(Exprent oldExpr, Exprent newExpr) {
if (oldExpr == instance) {
instance = newExpr;
}
}
@Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (o == this) return true; if (o == this) return true;
if (o == null || !(o instanceof FieldExprent)) return false; if (o == null || !(o instanceof FieldExprent)) return false;
@ -183,12 +162,6 @@ public class FieldExprent extends Exprent {
InterpreterUtil.equalObjects(descriptor, ft.getDescriptor()); InterpreterUtil.equalObjects(descriptor, ft.getDescriptor());
} }
public void replaceExprent(Exprent oldexpr, Exprent newexpr) {
if (oldexpr == instance) {
instance = newexpr;
}
}
public String getClassname() { public String getClassname() {
return classname; return classname;
} }

@ -15,12 +15,6 @@
*/ */
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.TextBuffer;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
@ -30,6 +24,7 @@ import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
import org.jetbrains.java.decompiler.util.ListStack; import org.jetbrains.java.decompiler.util.ListStack;
import java.util.*;
public class FunctionExprent extends Exprent { public class FunctionExprent extends Exprent {
@ -48,8 +43,8 @@ public class FunctionExprent extends Exprent {
public static final int FUNCTION_SHR = 9; public static final int FUNCTION_SHR = 9;
public static final int FUNCTION_USHR = 10; public static final int FUNCTION_USHR = 10;
public static final int FUNCTION_BITNOT = 11; public static final int FUNCTION_BIT_NOT = 11;
public static final int FUNCTION_BOOLNOT = 12; public static final int FUNCTION_BOOL_NOT = 12;
public static final int FUNCTION_NEG = 13; public static final int FUNCTION_NEG = 13;
public final static int FUNCTION_I2L = 14; public final static int FUNCTION_I2L = 14;
@ -71,7 +66,7 @@ public class FunctionExprent extends Exprent {
public final static int FUNCTION_CAST = 29; public final static int FUNCTION_CAST = 29;
public final static int FUNCTION_INSTANCEOF = 30; public final static int FUNCTION_INSTANCEOF = 30;
public final static int FUNCTION_ARRAYLENGTH = 31; public final static int FUNCTION_ARRAY_LENGTH = 31;
public final static int FUNCTION_IMM = 32; public final static int FUNCTION_IMM = 32;
public final static int FUNCTION_MMI = 33; public final static int FUNCTION_MMI = 33;
@ -97,9 +92,9 @@ public class FunctionExprent extends Exprent {
public static final int FUNCTION_CADD = 48; public static final int FUNCTION_CADD = 48;
public static final int FUNCTION_COR = 49; public static final int FUNCTION_COR = 49;
public static final int FUNCTION_STRCONCAT = 50; public static final int FUNCTION_STR_CONCAT = 50;
private static final VarType[] types = new VarType[]{ private static final VarType[] TYPES = {
VarType.VARTYPE_LONG, VarType.VARTYPE_LONG,
VarType.VARTYPE_FLOAT, VarType.VARTYPE_FLOAT,
VarType.VARTYPE_DOUBLE, VarType.VARTYPE_DOUBLE,
@ -117,7 +112,7 @@ public class FunctionExprent extends Exprent {
VarType.VARTYPE_SHORT VarType.VARTYPE_SHORT
}; };
private static final String[] operators = new String[]{ private static final String[] OPERATORS = {
" + ", " + ",
" - ", " - ",
" * ", " * ",
@ -140,81 +135,74 @@ public class FunctionExprent extends Exprent {
" + " " + "
}; };
private static final int[] precedence = new int[]{ private static final int[] PRECEDENCE = {
3, // FUNCTION_ADD 3, // FUNCTION_ADD
3, // FUNCTION_SUB 3, // FUNCTION_SUB
2, // FUNCTION_MUL 2, // FUNCTION_MUL
2, // FUNCTION_DIV 2, // FUNCTION_DIV
7, // FUNCTION_AND 7, // FUNCTION_AND
9, // FUNCTION_OR 9, // FUNCTION_OR
8, // FUNCTION_XOR 8, // FUNCTION_XOR
2, // FUNCTION_REM 2, // FUNCTION_REM
4, // FUNCTION_SHL 4, // FUNCTION_SHL
4, // FUNCTION_SHR 4, // FUNCTION_SHR
4, // FUNCTION_USHR 4, // FUNCTION_USHR
1, // FUNCTION_BITNOT 1, // FUNCTION_BIT_NOT
1, // FUNCTION_BOOLNOT 1, // FUNCTION_BOOL_NOT
1, // FUNCTION_NEG 1, // FUNCTION_NEG
1, // FUNCTION_I2L 1, // FUNCTION_I2L
1, // FUNCTION_I2F 1, // FUNCTION_I2F
1, // FUNCTION_I2D 1, // FUNCTION_I2D
1, // FUNCTION_L2I 1, // FUNCTION_L2I
1, // FUNCTION_L2F 1, // FUNCTION_L2F
1, // FUNCTION_L2D 1, // FUNCTION_L2D
1, // FUNCTION_F2I 1, // FUNCTION_F2I
1, // FUNCTION_F2L 1, // FUNCTION_F2L
1, // FUNCTION_F2D 1, // FUNCTION_F2D
1, // FUNCTION_D2I 1, // FUNCTION_D2I
1, // FUNCTION_D2L 1, // FUNCTION_D2L
1, // FUNCTION_D2F 1, // FUNCTION_D2F
1, // FUNCTION_I2B 1, // FUNCTION_I2B
1, // FUNCTION_I2C 1, // FUNCTION_I2C
1, // FUNCTION_I2S 1, // FUNCTION_I2S
1, // FUNCTION_CAST 1, // FUNCTION_CAST
6, // FUNCTION_INSTANCEOF 6, // FUNCTION_INSTANCEOF
0, // FUNCTION_ARRAYLENGTH 0, // FUNCTION_ARRAY_LENGTH
1, // FUNCTION_IMM 1, // FUNCTION_IMM
1, // FUNCTION_MMI 1, // FUNCTION_MMI
1, // FUNCTION_IPP 1, // FUNCTION_IPP
1, // FUNCTION_PPI 1, // FUNCTION_PPI
12, // FUNCTION_IFF 12, // FUNCTION_IFF
-1, // FUNCTION_LCMP -1, // FUNCTION_LCMP
-1, // FUNCTION_FCMPL -1, // FUNCTION_FCMPL
-1, // FUNCTION_FCMPG -1, // FUNCTION_FCMPG
-1, // FUNCTION_DCMPL -1, // FUNCTION_DCMPL
-1, // FUNCTION_DCMPG -1, // FUNCTION_DCMPG
6, // FUNCTION_EQ = 41; 6, // FUNCTION_EQ = 41;
6, // FUNCTION_NE = 42; 6, // FUNCTION_NE = 42;
5, // FUNCTION_LT = 43; 5, // FUNCTION_LT = 43;
5, // FUNCTION_GE = 44; 5, // FUNCTION_GE = 44;
5, // FUNCTION_GT = 45; 5, // FUNCTION_GT = 45;
5, // FUNCTION_LE = 46; 5, // FUNCTION_LE = 46;
10, // FUNCTION_CADD = 47; 10, // FUNCTION_CADD = 47;
11, // FUNCTION_COR = 48; 11, // FUNCTION_COR = 48;
3 // FUNCTION_STRCONCAT = 49; 3 // FUNCTION_STR_CONCAT = 49;
}; };
private static final HashSet<Integer> associativity = private static final Set<Integer> ASSOCIATIVITY = new HashSet<Integer>(Arrays.asList(
new HashSet<Integer>(Arrays.asList(new Integer[]{FUNCTION_ADD, FUNCTION_MUL, FUNCTION_AND, FUNCTION_ADD, FUNCTION_MUL, FUNCTION_AND, FUNCTION_OR, FUNCTION_XOR, FUNCTION_CADD, FUNCTION_COR, FUNCTION_STR_CONCAT));
FUNCTION_OR, FUNCTION_XOR, FUNCTION_CADD, FUNCTION_COR, FUNCTION_STRCONCAT}));
private int functype;
private int funcType;
private VarType implicitType; private VarType implicitType;
private final List<Exprent> lstOperands;
private List<Exprent> lstOperands = new ArrayList<Exprent>(); public FunctionExprent(int funcType, ListStack<Exprent> stack, Set<Integer> bytecodeOffsets) {
this(funcType, new ArrayList<Exprent>(), bytecodeOffsets);
{
this.type = EXPRENT_FUNCTION;
}
public FunctionExprent(int functype, ListStack<Exprent> stack, Set<Integer> bytecode_offsets) { if (funcType >= FUNCTION_BIT_NOT && funcType <= FUNCTION_PPI && funcType != FUNCTION_CAST && funcType != FUNCTION_INSTANCEOF) {
this.functype = functype;
if (functype >= FUNCTION_BITNOT && functype <= FUNCTION_PPI && functype != FUNCTION_CAST
&& functype != FUNCTION_INSTANCEOF) {
lstOperands.add(stack.pop()); lstOperands.add(stack.pop());
} }
else if (functype == FUNCTION_IIF) { else if (funcType == FUNCTION_IIF) {
throw new RuntimeException("no direct instantiation possible"); throw new RuntimeException("no direct instantiation possible");
} }
else { else {
@ -222,22 +210,22 @@ public class FunctionExprent extends Exprent {
lstOperands.add(stack.pop()); lstOperands.add(stack.pop());
lstOperands.add(expr); lstOperands.add(expr);
} }
addBytecodeOffsets(bytecode_offsets);
} }
public FunctionExprent(int functype, List<Exprent> operands, Set<Integer> bytecode_offsets) { public FunctionExprent(int funcType, List<Exprent> operands, Set<Integer> bytecodeOffsets) {
this.functype = functype; super(EXPRENT_FUNCTION);
this.funcType = funcType;
this.lstOperands = operands; this.lstOperands = operands;
addBytecodeOffsets(bytecode_offsets); addBytecodeOffsets(bytecodeOffsets);
} }
@Override
public VarType getExprType() { public VarType getExprType() {
VarType exprType = null; VarType exprType = null;
if (functype <= FUNCTION_NEG || functype == FUNCTION_IPP || functype == FUNCTION_PPI if (funcType <= FUNCTION_NEG || funcType == FUNCTION_IPP || funcType == FUNCTION_PPI
|| functype == FUNCTION_IMM || functype == FUNCTION_MMI) { || funcType == FUNCTION_IMM || funcType == FUNCTION_MMI) {
VarType type1 = lstOperands.get(0).getExprType(); VarType type1 = lstOperands.get(0).getExprType();
VarType type2 = null; VarType type2 = null;
@ -245,20 +233,20 @@ public class FunctionExprent extends Exprent {
type2 = lstOperands.get(1).getExprType(); type2 = lstOperands.get(1).getExprType();
} }
switch (functype) { switch (funcType) {
case FUNCTION_IMM: case FUNCTION_IMM:
case FUNCTION_MMI: case FUNCTION_MMI:
case FUNCTION_IPP: case FUNCTION_IPP:
case FUNCTION_PPI: case FUNCTION_PPI:
exprType = implicitType; exprType = implicitType;
break; break;
case FUNCTION_BOOLNOT: case FUNCTION_BOOL_NOT:
exprType = VarType.VARTYPE_BOOLEAN; exprType = VarType.VARTYPE_BOOLEAN;
break; break;
case FUNCTION_SHL: case FUNCTION_SHL:
case FUNCTION_SHR: case FUNCTION_SHR:
case FUNCTION_USHR: case FUNCTION_USHR:
case FUNCTION_BITNOT: case FUNCTION_BIT_NOT:
case FUNCTION_NEG: case FUNCTION_NEG:
exprType = getMaxVarType(new VarType[]{type1}); exprType = getMaxVarType(new VarType[]{type1});
break; break;
@ -280,10 +268,10 @@ public class FunctionExprent extends Exprent {
} }
} }
} }
else if (functype == FUNCTION_CAST) { else if (funcType == FUNCTION_CAST) {
exprType = lstOperands.get(1).getExprType(); exprType = lstOperands.get(1).getExprType();
} }
else if (functype == FUNCTION_IIF) { else if (funcType == FUNCTION_IIF) {
Exprent param1 = lstOperands.get(1); Exprent param1 = lstOperands.get(1);
Exprent param2 = lstOperands.get(2); Exprent param2 = lstOperands.get(2);
VarType supertype = VarType.getCommonSupertype(param1.getExprType(), param2.getExprType()); VarType supertype = VarType.getCommonSupertype(param1.getExprType(), param2.getExprType());
@ -296,25 +284,25 @@ public class FunctionExprent extends Exprent {
exprType = supertype; exprType = supertype;
} }
} }
else if (functype == FUNCTION_STRCONCAT) { else if (funcType == FUNCTION_STR_CONCAT) {
exprType = VarType.VARTYPE_STRING; exprType = VarType.VARTYPE_STRING;
} }
else if (functype >= FUNCTION_EQ || functype == FUNCTION_INSTANCEOF) { else if (funcType >= FUNCTION_EQ || funcType == FUNCTION_INSTANCEOF) {
exprType = VarType.VARTYPE_BOOLEAN; exprType = VarType.VARTYPE_BOOLEAN;
} }
else if (functype >= FUNCTION_ARRAYLENGTH) { else if (funcType >= FUNCTION_ARRAY_LENGTH) {
exprType = VarType.VARTYPE_INT; exprType = VarType.VARTYPE_INT;
} }
else { else {
exprType = types[functype - FUNCTION_I2L]; exprType = TYPES[funcType - FUNCTION_I2L];
} }
return exprType; return exprType;
} }
@Override
public int getExprentUse() { public int getExprentUse() {
if (funcType >= FUNCTION_IMM && funcType <= FUNCTION_PPI) {
if (functype >= FUNCTION_IMM && functype <= FUNCTION_PPI) {
return 0; return 0;
} }
else { else {
@ -326,6 +314,7 @@ public class FunctionExprent extends Exprent {
} }
} }
@Override
public CheckTypesResult checkExprTypeBounds() { public CheckTypesResult checkExprTypeBounds() {
CheckTypesResult result = new CheckTypesResult(); CheckTypesResult result = new CheckTypesResult();
@ -339,15 +328,15 @@ public class FunctionExprent extends Exprent {
type2 = param2.getExprType(); type2 = param2.getExprType();
} }
switch (functype) { switch (funcType) {
case FUNCTION_IIF: case FUNCTION_IIF:
VarType supertype = getExprType(); VarType supertype = getExprType();
if (supertype == null) { if (supertype == null) {
supertype = getExprType(); supertype = getExprType();
} }
result.addMinTypeExprent(param1, VarType.VARTYPE_BOOLEAN); result.addMinTypeExprent(param1, VarType.VARTYPE_BOOLEAN);
result.addMinTypeExprent(param2, VarType.getMinTypeInFamily(supertype.type_family)); result.addMinTypeExprent(param2, VarType.getMinTypeInFamily(supertype.typeFamily));
result.addMinTypeExprent(lstOperands.get(2), VarType.getMinTypeInFamily(supertype.type_family)); result.addMinTypeExprent(lstOperands.get(2), VarType.getMinTypeInFamily(supertype.typeFamily));
break; break;
case FUNCTION_I2L: case FUNCTION_I2L:
case FUNCTION_I2F: case FUNCTION_I2F:
@ -378,8 +367,8 @@ public class FunctionExprent extends Exprent {
case FUNCTION_GT: case FUNCTION_GT:
case FUNCTION_LE: case FUNCTION_LE:
result.addMinTypeExprent(param2, VarType.VARTYPE_BYTECHAR); result.addMinTypeExprent(param2, VarType.VARTYPE_BYTECHAR);
case FUNCTION_BITNOT: case FUNCTION_BIT_NOT:
// case FUNCTION_BOOLNOT: // case FUNCTION_BOOL_NOT:
case FUNCTION_NEG: case FUNCTION_NEG:
result.addMinTypeExprent(param1, VarType.VARTYPE_BYTECHAR); result.addMinTypeExprent(param1, VarType.VARTYPE_BYTECHAR);
break; break;
@ -389,13 +378,10 @@ public class FunctionExprent extends Exprent {
case FUNCTION_EQ: case FUNCTION_EQ:
case FUNCTION_NE: { case FUNCTION_NE: {
if (type1.type == CodeConstants.TYPE_BOOLEAN) { if (type1.type == CodeConstants.TYPE_BOOLEAN) {
if (type2.isStrictSuperset(type1)) { if (type2.isStrictSuperset(type1)) {
result.addMinTypeExprent(param1, VarType.VARTYPE_BYTECHAR); result.addMinTypeExprent(param1, VarType.VARTYPE_BYTECHAR);
} }
else { // both are booleans else { // both are booleans
boolean param1_false_boolean = boolean param1_false_boolean =
type1.isFalseBoolean() || (param1.type == Exprent.EXPRENT_CONST && !((ConstExprent)param1).hasBooleanValue()); type1.isFalseBoolean() || (param1.type == Exprent.EXPRENT_CONST && !((ConstExprent)param1).hasBooleanValue());
boolean param2_false_boolean = boolean param2_false_boolean =
@ -408,7 +394,6 @@ public class FunctionExprent extends Exprent {
} }
} }
else if (type2.type == CodeConstants.TYPE_BOOLEAN) { else if (type2.type == CodeConstants.TYPE_BOOLEAN) {
if (type1.isStrictSuperset(type2)) { if (type1.isStrictSuperset(type2)) {
result.addMinTypeExprent(param2, VarType.VARTYPE_BYTECHAR); result.addMinTypeExprent(param2, VarType.VARTYPE_BYTECHAR);
} }
@ -419,6 +404,7 @@ public class FunctionExprent extends Exprent {
return result; return result;
} }
@Override
public List<Exprent> getAllExprents() { public List<Exprent> getAllExprents() {
List<Exprent> lst = new ArrayList<Exprent>(); List<Exprent> lst = new ArrayList<Exprent>();
lst.addAll(lstOperands); lst.addAll(lstOperands);
@ -431,64 +417,63 @@ public class FunctionExprent extends Exprent {
for (Exprent expr : lstOperands) { for (Exprent expr : lstOperands) {
lst.add(expr.copy()); lst.add(expr.copy());
} }
FunctionExprent func = new FunctionExprent(functype, lst, bytecode); FunctionExprent func = new FunctionExprent(funcType, lst, bytecode);
func.setImplicitType(implicitType); func.setImplicitType(implicitType);
return func; return func;
} }
@Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (o == this) return true; if (o == this) return true;
if (o == null || !(o instanceof FunctionExprent)) return false; if (o == null || !(o instanceof FunctionExprent)) return false;
FunctionExprent fe = (FunctionExprent)o; FunctionExprent fe = (FunctionExprent)o;
return functype == fe.getFunctype() && return funcType == fe.getFuncType() &&
InterpreterUtil.equalLists(lstOperands, fe.getLstOperands()); // TODO: order of operands insignificant InterpreterUtil.equalLists(lstOperands, fe.getLstOperands()); // TODO: order of operands insignificant
} }
public void replaceExprent(Exprent oldexpr, Exprent newexpr) { @Override
public void replaceExprent(Exprent oldExpr, Exprent newExpr) {
for (int i = 0; i < lstOperands.size(); i++) { for (int i = 0; i < lstOperands.size(); i++) {
if (oldexpr == lstOperands.get(i)) { if (oldExpr == lstOperands.get(i)) {
lstOperands.set(i, newexpr); lstOperands.set(i, newExpr);
} }
} }
} }
@Override @Override
public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) {
tracer.addMapping(bytecode); tracer.addMapping(bytecode);
if (functype <= FUNCTION_USHR) { if (funcType <= FUNCTION_USHR) {
return wrapOperandString(lstOperands.get(0), false, indent, tracer) return wrapOperandString(lstOperands.get(0), false, indent, tracer)
.append(operators[functype]) .append(OPERATORS[funcType])
.append(wrapOperandString(lstOperands.get(1), true, indent, tracer)); .append(wrapOperandString(lstOperands.get(1), true, indent, tracer));
} }
if (functype >= FUNCTION_EQ) { if (funcType >= FUNCTION_EQ) {
return wrapOperandString(lstOperands.get(0), false, indent, tracer) return wrapOperandString(lstOperands.get(0), false, indent, tracer)
.append(operators[functype - FUNCTION_EQ + 11]) .append(OPERATORS[funcType - FUNCTION_EQ + 11])
.append(wrapOperandString(lstOperands.get(1), true, indent, tracer)); .append(wrapOperandString(lstOperands.get(1), true, indent, tracer));
} }
switch (functype) { switch (funcType) {
case FUNCTION_BITNOT: case FUNCTION_BIT_NOT:
return wrapOperandString(lstOperands.get(0), true, indent, tracer).prepend("~"); return wrapOperandString(lstOperands.get(0), true, indent, tracer).prepend("~");
case FUNCTION_BOOLNOT: case FUNCTION_BOOL_NOT:
return wrapOperandString(lstOperands.get(0), true, indent, tracer).prepend("!"); return wrapOperandString(lstOperands.get(0), true, indent, tracer).prepend("!");
case FUNCTION_NEG: case FUNCTION_NEG:
return wrapOperandString(lstOperands.get(0), true, indent, tracer).prepend("-"); return wrapOperandString(lstOperands.get(0), true, indent, tracer).prepend("-");
case FUNCTION_CAST: case FUNCTION_CAST:
return lstOperands.get(1).toJava(indent, tracer).enclose("(", ")").append(wrapOperandString(lstOperands.get(0), true, indent, tracer)); return lstOperands.get(1).toJava(indent, tracer).enclose("(", ")").append(wrapOperandString(lstOperands.get(0), true, indent, tracer));
case FUNCTION_ARRAYLENGTH: case FUNCTION_ARRAY_LENGTH:
Exprent arr = lstOperands.get(0); Exprent arr = lstOperands.get(0);
TextBuffer res = wrapOperandString(arr, false, indent, tracer); TextBuffer res = wrapOperandString(arr, false, indent, tracer);
if (arr.getExprType().arraydim == 0) { if (arr.getExprType().arrayDim == 0) {
VarType objarr = VarType.VARTYPE_OBJECT.copy(); VarType objArr = VarType.VARTYPE_OBJECT.resizeArrayDim(1); // type family does not change
objarr.arraydim = 1; // type family does not change res.enclose("((" + ExprProcessor.getCastTypeName(objArr) + ")", ")");
res.enclose("((" + ExprProcessor.getCastTypeName(objarr) + ")", ")");
} }
return res.append(".length"); return res.append(".length");
case FUNCTION_IIF: case FUNCTION_IIF:
@ -534,28 +519,29 @@ public class FunctionExprent extends Exprent {
.append(")"); .append(")");
} }
if (functype <= FUNCTION_I2S) { if (funcType <= FUNCTION_I2S) {
return wrapOperandString(lstOperands.get(0), true, indent, tracer).prepend("(" + ExprProcessor.getTypeName(types[functype - FUNCTION_I2L]) + ")"); return wrapOperandString(lstOperands.get(0), true, indent, tracer).prepend("(" + ExprProcessor.getTypeName(
TYPES[funcType - FUNCTION_I2L]) + ")");
} }
// return "<unknown function>"; // return "<unknown function>";
throw new RuntimeException("invalid function"); throw new RuntimeException("invalid function");
} }
@Override
public int getPrecedence() { public int getPrecedence() {
return getPrecedence(functype); return getPrecedence(funcType);
} }
public static int getPrecedence(int func) { public static int getPrecedence(int func) {
return precedence[func]; return PRECEDENCE[func];
} }
public VarType getSimpleCastType() { public VarType getSimpleCastType() {
return types[functype - FUNCTION_I2L]; return TYPES[funcType - FUNCTION_I2L];
} }
private TextBuffer wrapOperandString(Exprent expr, boolean eq, int indent, BytecodeMappingTracer tracer) { private TextBuffer wrapOperandString(Exprent expr, boolean eq, int indent, BytecodeMappingTracer tracer) {
int myprec = getPrecedence(); int myprec = getPrecedence();
int exprprec = expr.getPrecedence(); int exprprec = expr.getPrecedence();
@ -564,8 +550,8 @@ public class FunctionExprent extends Exprent {
parentheses = (exprprec == myprec); parentheses = (exprprec == myprec);
if (parentheses) { if (parentheses) {
if (expr.type == Exprent.EXPRENT_FUNCTION && if (expr.type == Exprent.EXPRENT_FUNCTION &&
((FunctionExprent)expr).getFunctype() == functype) { ((FunctionExprent)expr).getFuncType() == funcType) {
parentheses = !associativity.contains(functype); parentheses = !ASSOCIATIVITY.contains(funcType);
} }
} }
} }
@ -580,7 +566,6 @@ public class FunctionExprent extends Exprent {
} }
private static VarType getMaxVarType(VarType[] arr) { private static VarType getMaxVarType(VarType[] arr) {
int[] types = new int[]{CodeConstants.TYPE_DOUBLE, CodeConstants.TYPE_FLOAT, CodeConstants.TYPE_LONG}; int[] types = new int[]{CodeConstants.TYPE_DOUBLE, CodeConstants.TYPE_FLOAT, CodeConstants.TYPE_LONG};
VarType[] vartypes = new VarType[]{VarType.VARTYPE_DOUBLE, VarType.VARTYPE_FLOAT, VarType.VARTYPE_LONG}; VarType[] vartypes = new VarType[]{VarType.VARTYPE_DOUBLE, VarType.VARTYPE_FLOAT, VarType.VARTYPE_LONG};
@ -599,28 +584,19 @@ public class FunctionExprent extends Exprent {
// getter and setter methods // getter and setter methods
// ***************************************************************************** // *****************************************************************************
public int getFunctype() { public int getFuncType() {
return functype; return funcType;
} }
public void setFunctype(int functype) { public void setFuncType(int funcType) {
this.functype = functype; this.funcType = funcType;
} }
public List<Exprent> getLstOperands() { public List<Exprent> getLstOperands() {
return lstOperands; return lstOperands;
} }
public void setLstOperands(List<Exprent> lstOperands) {
this.lstOperands = lstOperands;
}
public VarType getImplicitType() {
return implicitType;
}
public void setImplicitType(VarType implicitType) { public void setImplicitType(VarType implicitType) {
this.implicitType = implicitType; this.implicitType = implicitType;
} }
} }

@ -16,16 +16,12 @@
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.TextBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
import org.jetbrains.java.decompiler.util.ListStack; import org.jetbrains.java.decompiler.util.ListStack;
import java.util.*;
public class IfExprent extends Exprent { public class IfExprent extends Exprent {
@ -54,7 +50,7 @@ public class IfExprent extends Exprent {
public static final int IF_NOT = 18; public static final int IF_NOT = 18;
public static final int IF_VALUE = 19; public static final int IF_VALUE = 19;
private static final int[] functypes = new int[]{ private static final int[] FUNC_TYPES = {
FunctionExprent.FUNCTION_EQ, FunctionExprent.FUNCTION_EQ,
FunctionExprent.FUNCTION_NE, FunctionExprent.FUNCTION_NE,
FunctionExprent.FUNCTION_LT, FunctionExprent.FUNCTION_LT,
@ -73,39 +69,35 @@ public class IfExprent extends Exprent {
FunctionExprent.FUNCTION_NE, FunctionExprent.FUNCTION_NE,
FunctionExprent.FUNCTION_CADD, FunctionExprent.FUNCTION_CADD,
FunctionExprent.FUNCTION_COR, FunctionExprent.FUNCTION_COR,
FunctionExprent.FUNCTION_BOOLNOT, FunctionExprent.FUNCTION_BOOL_NOT,
-1 -1
}; };
private Exprent condition; private Exprent condition;
{ public IfExprent(int ifType, ListStack<Exprent> stack, Set<Integer> bytecodeOffsets) {
this.type = EXPRENT_IF; this(null, bytecodeOffsets);
}
public IfExprent(int iftype, ListStack<Exprent> stack, Set<Integer> bytecode_offsets) {
if (iftype <= IF_LE) { if (ifType <= IF_LE) {
stack.push(new ConstExprent(0, true, null)); stack.push(new ConstExprent(0, true, null));
} }
else if (iftype <= IF_NONNULL) { else if (ifType <= IF_NONNULL) {
stack.push(new ConstExprent(VarType.VARTYPE_NULL, null, null)); stack.push(new ConstExprent(VarType.VARTYPE_NULL, null, null));
} }
if (iftype == IF_VALUE) { if (ifType == IF_VALUE) {
condition = stack.pop(); condition = stack.pop();
} }
else { else {
condition = new FunctionExprent(functypes[iftype], stack, null); condition = new FunctionExprent(FUNC_TYPES[ifType], stack, null);
} }
addBytecodeOffsets(bytecode_offsets);
} }
private IfExprent(Exprent condition, Set<Integer> bytecode_offsets) { private IfExprent(Exprent condition, Set<Integer> bytecodeOffsets) {
super(EXPRENT_IF);
this.condition = condition; this.condition = condition;
addBytecodeOffsets(bytecode_offsets); addBytecodeOffsets(bytecodeOffsets);
} }
@Override @Override
@ -113,6 +105,7 @@ public class IfExprent extends Exprent {
return new IfExprent(condition.copy(), bytecode); return new IfExprent(condition.copy(), bytecode);
} }
@Override
public List<Exprent> getAllExprents() { public List<Exprent> getAllExprents() {
List<Exprent> lst = new ArrayList<Exprent>(); List<Exprent> lst = new ArrayList<Exprent>();
lst.add(condition); lst.add(condition);
@ -125,6 +118,14 @@ public class IfExprent extends Exprent {
return condition.toJava(indent, tracer).enclose("if(", ")"); return condition.toJava(indent, tracer).enclose("if(", ")");
} }
@Override
public void replaceExprent(Exprent oldExpr, Exprent newExpr) {
if (oldExpr == condition) {
condition = newExpr;
}
}
@Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (o == this) return true; if (o == this) return true;
if (o == null || !(o instanceof IfExprent)) return false; if (o == null || !(o instanceof IfExprent)) return false;
@ -133,15 +134,8 @@ public class IfExprent extends Exprent {
return InterpreterUtil.equalObjects(condition, ie.getCondition()); return InterpreterUtil.equalObjects(condition, ie.getCondition());
} }
public void replaceExprent(Exprent oldexpr, Exprent newexpr) {
if (oldexpr == condition) {
condition = newexpr;
}
}
public IfExprent negateIf() { public IfExprent negateIf() {
condition = new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT, condition = new FunctionExprent(FunctionExprent.FUNCTION_BOOL_NOT, Collections.singletonList(condition), condition.bytecode);
Arrays.asList(condition), condition.bytecode);
return this; return this;
} }

@ -33,10 +33,10 @@ import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor;
import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
import org.jetbrains.java.decompiler.util.ListStack; import org.jetbrains.java.decompiler.util.ListStack;
import org.jetbrains.java.decompiler.util.TextUtil;
import java.util.*; import java.util.*;
public class InvocationExprent extends Exprent { public class InvocationExprent extends Exprent {
public static final int INVOKE_SPECIAL = 1; public static final int INVOKE_SPECIAL = 1;
@ -49,40 +49,25 @@ public class InvocationExprent extends Exprent {
public static final int TYP_INIT = 2; public static final int TYP_INIT = 2;
public static final int TYP_CLINIT = 3; public static final int TYP_CLINIT = 3;
public static final int CONSTRUCTOR_NOT = 0;
public static final int CONSTRUCTOR_THIS = 1;
public static final int CONSTRUCTOR_SUPER = 2;
private static final BitSet EMPTY_BIT_SET = new BitSet(0); private static final BitSet EMPTY_BIT_SET = new BitSet(0);
private String name; private String name;
private String classname; private String classname;
private boolean isStatic; private boolean isStatic;
private int functype = TYP_GENERAL; private int functype = TYP_GENERAL;
private Exprent instance; private Exprent instance;
private MethodDescriptor descriptor; private MethodDescriptor descriptor;
private String stringDescriptor; private String stringDescriptor;
private String invokeDynamicClassSuffix;
private String invoke_dynamic_classsuffix;
private int invocationTyp = INVOKE_VIRTUAL; private int invocationTyp = INVOKE_VIRTUAL;
private List<Exprent> lstParameters = new ArrayList<Exprent>(); private List<Exprent> lstParameters = new ArrayList<Exprent>();
{
this.type = EXPRENT_INVOCATION;
}
public InvocationExprent() { public InvocationExprent() {
super(EXPRENT_INVOCATION);
} }
public InvocationExprent(int opcode, LinkConstant cn, ListStack<Exprent> stack, int dynamic_invokation_type, Set<Integer> bytecode_offsets) { public InvocationExprent(int opcode, LinkConstant cn, ListStack<Exprent> stack, int dynamicInvocationType, Set<Integer> bytecodeOffsets) {
this();
name = cn.elementname; name = cn.elementname;
classname = cn.classname; classname = cn.classname;
@ -104,7 +89,7 @@ public class InvocationExprent extends Exprent {
invocationTyp = INVOKE_DYNAMIC; invocationTyp = INVOKE_DYNAMIC;
classname = "java/lang/Class"; // dummy class name classname = "java/lang/Class"; // dummy class name
invoke_dynamic_classsuffix = "##Lambda_" + cn.index1 + "_" + cn.index2; invokeDynamicClassSuffix = "##Lambda_" + cn.index1 + "_" + cn.index2;
} }
if ("<init>".equals(name)) { if ("<init>".equals(name)) {
@ -117,17 +102,17 @@ public class InvocationExprent extends Exprent {
stringDescriptor = cn.descriptor; stringDescriptor = cn.descriptor;
descriptor = MethodDescriptor.parseDescriptor(cn.descriptor); descriptor = MethodDescriptor.parseDescriptor(cn.descriptor);
for (int i = 0; i < descriptor.params.length; i++) { for (VarType ignored : descriptor.params) {
lstParameters.add(0, stack.pop()); lstParameters.add(0, stack.pop());
} }
if (opcode == CodeConstants.opc_invokedynamic) { if (opcode == CodeConstants.opc_invokedynamic) {
if (dynamic_invokation_type == CodeConstants.CONSTANT_MethodHandle_REF_invokeStatic) { if (dynamicInvocationType == CodeConstants.CONSTANT_MethodHandle_REF_invokeStatic) {
isStatic = true; isStatic = true;
} }
else { else {
instance = lstParameters // FIXME: remove the first parameter completely from the list. It's the object type for a virtual lambda method.
.get(0); // FIXME: remove the first parameter completely from the list. It's the object type for a virtual lambda method. instance = lstParameters.get(0);
} }
} }
else if (opcode == CodeConstants.opc_invokestatic) { else if (opcode == CodeConstants.opc_invokestatic) {
@ -137,10 +122,12 @@ public class InvocationExprent extends Exprent {
instance = stack.pop(); instance = stack.pop();
} }
addBytecodeOffsets(bytecode_offsets); addBytecodeOffsets(bytecodeOffsets);
} }
private InvocationExprent(InvocationExprent expr) { private InvocationExprent(InvocationExprent expr) {
this();
name = expr.getName(); name = expr.getName();
classname = expr.getClassname(); classname = expr.getClassname();
isStatic = expr.isStatic(); isStatic = expr.isStatic();
@ -153,17 +140,17 @@ public class InvocationExprent extends Exprent {
stringDescriptor = expr.getStringDescriptor(); stringDescriptor = expr.getStringDescriptor();
descriptor = expr.getDescriptor(); descriptor = expr.getDescriptor();
lstParameters = new ArrayList<Exprent>(expr.getLstParameters()); lstParameters = new ArrayList<Exprent>(expr.getLstParameters());
for (int i = 0; i < lstParameters.size(); i++) { ExprProcessor.copyEntries(lstParameters);
lstParameters.set(i, lstParameters.get(i).copy());
}
bytecode.addAll(expr.bytecode);
}
addBytecodeOffsets(expr.bytecode);
}
@Override
public VarType getExprType() { public VarType getExprType() {
return descriptor.ret; return descriptor.ret;
} }
@Override
public CheckTypesResult checkExprTypeBounds() { public CheckTypesResult checkExprTypeBounds() {
CheckTypesResult result = new CheckTypesResult(); CheckTypesResult result = new CheckTypesResult();
@ -172,13 +159,14 @@ public class InvocationExprent extends Exprent {
VarType leftType = descriptor.params[i]; VarType leftType = descriptor.params[i];
result.addMinTypeExprent(parameter, VarType.getMinTypeInFamily(leftType.type_family)); result.addMinTypeExprent(parameter, VarType.getMinTypeInFamily(leftType.typeFamily));
result.addMaxTypeExprent(parameter, leftType); result.addMaxTypeExprent(parameter, leftType);
} }
return result; return result;
} }
@Override
public List<Exprent> getAllExprents() { public List<Exprent> getAllExprents() {
List<Exprent> lst = new ArrayList<Exprent>(); List<Exprent> lst = new ArrayList<Exprent>();
if (instance != null) { if (instance != null) {
@ -203,11 +191,11 @@ public class InvocationExprent extends Exprent {
tracer.addMapping(bytecode); tracer.addMapping(bytecode);
if (invocationTyp == INVOKE_DYNAMIC) { /*if (invocationTyp == INVOKE_DYNAMIC) {
// ClassNode node = (ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASSNODE); // ClassNode node = (ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASSNODE);
// //
// if(node != null) { // if(node != null) {
// ClassNode lambda_node = DecompilerContext.getClassprocessor().getMapRootClasses().get(node.classStruct.qualifiedName + invoke_dynamic_classsuffix); // ClassNode lambda_node = DecompilerContext.getClassprocessor().getMapRootClasses().get(node.classStruct.qualifiedName + invokeDynamicClassSuffix);
// if(lambda_node != null) { // if(lambda_node != null) {
// //
// String typename = ExprProcessor.getCastTypeName(lambda_node.anonimousClassType); // String typename = ExprProcessor.getCastTypeName(lambda_node.anonimousClassType);
@ -234,7 +222,7 @@ public class InvocationExprent extends Exprent {
// } // }
} }
else if (isStatic) { else*/ if (isStatic) {
ClassNode node = (ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE); ClassNode node = (ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE);
if (node == null || !classname.equals(node.classStruct.qualifiedName)) { if (node == null || !classname.equals(node.classStruct.qualifiedName)) {
@ -257,7 +245,7 @@ public class InvocationExprent extends Exprent {
String this_classname = null; String this_classname = null;
if (vproc != null) { if (vproc != null) {
this_classname = vproc.getThisvars().get(varpaar); this_classname = vproc.getThisVars().get(varpaar);
} }
if (this_classname != null) { if (this_classname != null) {
@ -273,15 +261,9 @@ public class InvocationExprent extends Exprent {
if (functype == TYP_GENERAL) { if (functype == TYP_GENERAL) {
if (super_qualifier != null) { if (super_qualifier != null) {
StructClass current_class = ((ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE)).classStruct; TextUtil.writeQualifiedSuper(buf, super_qualifier);
if (!super_qualifier.equals(current_class.qualifiedName)) {
buf.append(DecompilerContext.getImportCollector().getShortName(ExprProcessor.buildJavaClassName(super_qualifier)));
buf.append(".");
}
buf.append("super");
} }
else { else if (instance != null) {
TextBuffer res = instance.toJava(indent, tracer); TextBuffer res = instance.toJava(indent, tracer);
VarType rightType = instance.getExprType(); VarType rightType = instance.getExprType();
@ -332,9 +314,7 @@ public class InvocationExprent extends Exprent {
buf.append("this("); buf.append("this(");
} }
else { else {
buf.append(instance.toJava(indent, tracer)); throw new RuntimeException("Unrecognized invocation of <init>");
buf.append(".<init>(");
// throw new RuntimeException("Unrecognized invocation of <init>"); // FIXME: activate
} }
} }
@ -362,7 +342,7 @@ public class InvocationExprent extends Exprent {
boolean firstParameter = true; boolean firstParameter = true;
int start = isEnum ? 2 : 0; int start = isEnum ? 2 : 0;
for (int i = start; i < lstParameters.size(); i++) { for (int i = start; i < lstParameters.size(); i++) {
if (sigFields == null || sigFields.get(i) == null) { if (sigFields == null) {
if (!firstParameter) { if (!firstParameter) {
buf.append(", "); buf.append(", ");
} }
@ -393,7 +373,7 @@ public class InvocationExprent extends Exprent {
MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor()); MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor());
if (md.params.length == descriptor.params.length) { if (md.params.length == descriptor.params.length) {
for (int i = 0; i < md.params.length; i++) { for (int i = 0; i < md.params.length; i++) {
if (md.params[i].type_family != descriptor.params[i].type_family) { if (md.params[i].typeFamily != descriptor.params[i].typeFamily) {
continue nextMethod; continue nextMethod;
} }
} }
@ -433,6 +413,20 @@ public class InvocationExprent extends Exprent {
return ambiguous; return ambiguous;
} }
@Override
public void replaceExprent(Exprent oldExpr, Exprent newExpr) {
if (oldExpr == instance) {
instance = newExpr;
}
for (int i = 0; i < lstParameters.size(); i++) {
if (oldExpr == lstParameters.get(i)) {
lstParameters.set(i, newExpr);
}
}
}
@Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (o == this) return true; if (o == this) return true;
if (o == null || !(o instanceof InvocationExprent)) return false; if (o == null || !(o instanceof InvocationExprent)) return false;
@ -447,18 +441,6 @@ public class InvocationExprent extends Exprent {
InterpreterUtil.equalLists(lstParameters, it.getLstParameters()); InterpreterUtil.equalLists(lstParameters, it.getLstParameters());
} }
public void replaceExprent(Exprent oldexpr, Exprent newexpr) {
if (oldexpr == instance) {
instance = newexpr;
}
for (int i = 0; i < lstParameters.size(); i++) {
if (oldexpr == lstParameters.get(i)) {
lstParameters.set(i, newexpr);
}
}
}
public List<Exprent> getLstParameters() { public List<Exprent> getLstParameters() {
return lstParameters; return lstParameters;
} }
@ -527,11 +509,7 @@ public class InvocationExprent extends Exprent {
return invocationTyp; return invocationTyp;
} }
public void setInvocationTyp(int invocationTyp) {
this.invocationTyp = invocationTyp;
}
public String getInvokeDynamicClassSuffix() { public String getInvokeDynamicClassSuffix() {
return invoke_dynamic_classsuffix; return invokeDynamicClassSuffix;
} }
} }

@ -16,39 +16,35 @@
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.TextBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class MonitorExprent extends Exprent { public class MonitorExprent extends Exprent {
public static final int MONITOR_ENTER = 0; public static final int MONITOR_ENTER = 0;
public static final int MONITOR_EXIT = 1; public static final int MONITOR_EXIT = 1;
private int montype; private final int monType;
private Exprent value; private Exprent value;
{ public MonitorExprent(int monType, Exprent value, Set<Integer> bytecodeOffsets) {
this.type = EXPRENT_MONITOR; super(EXPRENT_MONITOR);
} this.monType = monType;
public MonitorExprent(int montype, Exprent value, Set<Integer> bytecode_offsets) {
this.montype = montype;
this.value = value; this.value = value;
addBytecodeOffsets(bytecode_offsets); addBytecodeOffsets(bytecodeOffsets);
} }
@Override @Override
public Exprent copy() { public Exprent copy() {
return new MonitorExprent(montype, value.copy(), bytecode); return new MonitorExprent(monType, value.copy(), bytecode);
} }
@Override
public List<Exprent> getAllExprents() { public List<Exprent> getAllExprents() {
List<Exprent> lst = new ArrayList<Exprent>(); List<Exprent> lst = new ArrayList<Exprent>();
lst.add(value); lst.add(value);
@ -57,10 +53,9 @@ public class MonitorExprent extends Exprent {
@Override @Override
public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) { public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) {
tracer.addMapping(bytecode); tracer.addMapping(bytecode);
if (montype == MONITOR_ENTER) { if (monType == MONITOR_ENTER) {
return value.toJava(indent, tracer).enclose("synchronized(", ")"); return value.toJava(indent, tracer).enclose("synchronized(", ")");
} }
else { else {
@ -68,23 +63,25 @@ public class MonitorExprent extends Exprent {
} }
} }
@Override
public void replaceExprent(Exprent oldExpr, Exprent newExpr) {
if (oldExpr == value) {
value = newExpr;
}
}
@Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (o == this) return true; if (o == this) return true;
if (o == null || !(o instanceof MonitorExprent)) return false; if (o == null || !(o instanceof MonitorExprent)) return false;
MonitorExprent me = (MonitorExprent)o; MonitorExprent me = (MonitorExprent)o;
return montype == me.getMontype() && return monType == me.getMonType() &&
InterpreterUtil.equalObjects(value, me.getValue()); InterpreterUtil.equalObjects(value, me.getValue());
} }
public void replaceExprent(Exprent oldexpr, Exprent newexpr) { public int getMonType() {
if (oldexpr == value) { return monType;
value = newexpr;
}
}
public int getMontype() {
return montype;
} }
public Exprent getValue() { public Exprent getValue() {

@ -15,11 +15,6 @@
*/ */
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.ClassWriter; import org.jetbrains.java.decompiler.main.ClassWriter;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
@ -35,92 +30,78 @@ import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
import org.jetbrains.java.decompiler.util.ListStack; import org.jetbrains.java.decompiler.util.ListStack;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
public class NewExprent extends Exprent { public class NewExprent extends Exprent {
private InvocationExprent constructor; private InvocationExprent constructor;
private VarType newType;
private VarType newtype;
private List<Exprent> lstDims = new ArrayList<Exprent>(); private List<Exprent> lstDims = new ArrayList<Exprent>();
private List<Exprent> lstArrayElements = new ArrayList<Exprent>(); private List<Exprent> lstArrayElements = new ArrayList<Exprent>();
private boolean directArrayInit; private boolean directArrayInit;
private boolean anonymous; private boolean anonymous;
private boolean lambda; private boolean lambda;
private boolean enumConst;
private boolean enumconst; public NewExprent(VarType newType, ListStack<Exprent> stack, int arrayDim, Set<Integer> bytecodeOffsets) {
this(newType, getDimensions(arrayDim, stack), bytecodeOffsets);
{
this.type = EXPRENT_NEW;
} }
public NewExprent(VarType newtype, ListStack<Exprent> stack, int arraydim, Set<Integer> bytecode_offsets) { public NewExprent(VarType newType, List<Exprent> lstDims, Set<Integer> bytecodeOffsets) {
this.newtype = newtype; super(EXPRENT_NEW);
for (int i = 0; i < arraydim; i++) { this.newType = newType;
lstDims.add(0, stack.pop());
}
addBytecodeOffsets(bytecode_offsets);
setAnonymous();
}
public NewExprent(VarType newtype, List<Exprent> lstDims, Set<Integer> bytecode_offsets) {
this.newtype = newtype;
this.lstDims = lstDims; this.lstDims = lstDims;
addBytecodeOffsets(bytecode_offsets);
setAnonymous();
}
private void setAnonymous() {
anonymous = false; anonymous = false;
lambda = false; lambda = false;
if (newType.type == CodeConstants.TYPE_OBJECT && newType.arrayDim == 0) {
if (newtype.type == CodeConstants.TYPE_OBJECT && newtype.arraydim == 0) { ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(newType.value);
ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(newtype.value);
if (node != null && (node.type == ClassNode.CLASS_ANONYMOUS || node.type == ClassNode.CLASS_LAMBDA)) { if (node != null && (node.type == ClassNode.CLASS_ANONYMOUS || node.type == ClassNode.CLASS_LAMBDA)) {
anonymous = true; anonymous = true;
if (node.type == ClassNode.CLASS_LAMBDA) { if (node.type == ClassNode.CLASS_LAMBDA) {
lambda = true; lambda = true;
} }
} }
} }
addBytecodeOffsets(bytecodeOffsets);
} }
public VarType getExprType() { private static List<Exprent> getDimensions(int arrayDim, ListStack<Exprent> stack) {
List<Exprent> lstDims = new ArrayList<Exprent>();
for (int i = 0; i < arrayDim; i++) {
lstDims.add(0, stack.pop());
}
return lstDims;
}
@Override
public VarType getExprType() {
if (anonymous) { if (anonymous) {
ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(newtype.value); return DecompilerContext.getClassProcessor().getMapRootClasses().get(newType.value).anonymousClassType;
return node.anonymousClassType;
} }
else { else {
return newtype; return newType;
} }
} }
@Override
public CheckTypesResult checkExprTypeBounds() { public CheckTypesResult checkExprTypeBounds() {
CheckTypesResult result = new CheckTypesResult(); CheckTypesResult result = new CheckTypesResult();
if (newtype.arraydim != 0) { if (newType.arrayDim != 0) {
for (Exprent dim : lstDims) { for (Exprent dim : lstDims) {
result.addMinTypeExprent(dim, VarType.VARTYPE_BYTECHAR); result.addMinTypeExprent(dim, VarType.VARTYPE_BYTECHAR);
result.addMaxTypeExprent(dim, VarType.VARTYPE_INT); result.addMaxTypeExprent(dim, VarType.VARTYPE_INT);
} }
if (newtype.arraydim == 1) { if (newType.arrayDim == 1) {
VarType leftType = newType.decreaseArrayDim();
VarType leftType = newtype.copy();
leftType.decArrayDim();
for (Exprent element : lstArrayElements) { for (Exprent element : lstArrayElements) {
result.addMinTypeExprent(element, VarType.getMinTypeInFamily(leftType.type_family)); result.addMinTypeExprent(element, VarType.getMinTypeInFamily(leftType.typeFamily));
result.addMaxTypeExprent(element, leftType); result.addMaxTypeExprent(element, leftType);
} }
} }
@ -134,9 +115,10 @@ public class NewExprent extends Exprent {
return result; return result;
} }
@Override
public List<Exprent> getAllExprents() { public List<Exprent> getAllExprents() {
List<Exprent> lst = new ArrayList<Exprent>(); List<Exprent> lst = new ArrayList<Exprent>();
if (newtype.arraydim == 0) { if (newType.arrayDim == 0) {
if (constructor != null) { if (constructor != null) {
Exprent constructor_instance = constructor.getInstance(); Exprent constructor_instance = constructor.getInstance();
@ -162,15 +144,16 @@ public class NewExprent extends Exprent {
lst.add(expr.copy()); lst.add(expr.copy());
} }
NewExprent ret = new NewExprent(newtype, lst, bytecode); NewExprent ret = new NewExprent(newType, lst, bytecode);
ret.setConstructor(constructor == null ? null : (InvocationExprent)constructor.copy()); ret.setConstructor(constructor == null ? null : (InvocationExprent)constructor.copy());
ret.setLstArrayElements(lstArrayElements); ret.setLstArrayElements(lstArrayElements);
ret.setDirectArrayInit(directArrayInit); ret.setDirectArrayInit(directArrayInit);
ret.setAnonymous(anonymous); ret.setAnonymous(anonymous);
ret.setEnumconst(enumconst); ret.setEnumConst(enumConst);
return ret; return ret;
} }
@Override
public int getPrecedence() { public int getPrecedence() {
return 1; // precedence of new return 1; // precedence of new
} }
@ -181,7 +164,7 @@ public class NewExprent extends Exprent {
if (anonymous) { if (anonymous) {
ClassNode child = DecompilerContext.getClassProcessor().getMapRootClasses().get(newtype.value); ClassNode child = DecompilerContext.getClassProcessor().getMapRootClasses().get(newType.value);
buf.append("("); buf.append("(");
@ -207,7 +190,7 @@ public class NewExprent extends Exprent {
boolean firstpar = true; boolean firstpar = true;
int start = 0, end = invsuper.getLstParameters().size(); int start = 0, end = invsuper.getLstParameters().size();
if (enumconst) { if (enumConst) {
start += 2; start += 2;
end -= 1; end -= 1;
} }
@ -234,7 +217,7 @@ public class NewExprent extends Exprent {
} }
} }
if (!enumconst) { if (!enumConst) {
String enclosing = null; String enclosing = null;
if (!lambda && constructor != null) { if (!lambda && constructor != null) {
enclosing = getQualifiedNewInstance(child.anonymousClassType.value, constructor.getLstParameters(), indent, tracer); enclosing = getQualifiedNewInstance(child.anonymousClassType.value, constructor.getLstParameters(), indent, tracer);
@ -260,7 +243,7 @@ public class NewExprent extends Exprent {
buf.append(")"); buf.append(")");
if (enumconst && buf.length() == 2) { if (enumConst && buf.length() == 2) {
buf.setLength(0); buf.setLength(0);
} }
@ -278,9 +261,7 @@ public class NewExprent extends Exprent {
} }
} }
else if (directArrayInit) { else if (directArrayInit) {
VarType leftType = newtype.copy(); VarType leftType = newType.decreaseArrayDim();
leftType.decArrayDim();
buf.append("{"); buf.append("{");
for (int i = 0; i < lstArrayElements.size(); i++) { for (int i = 0; i < lstArrayElements.size(); i++) {
if (i > 0) { if (i > 0) {
@ -291,7 +272,7 @@ public class NewExprent extends Exprent {
buf.append("}"); buf.append("}");
} }
else { else {
if (newtype.arraydim == 0) { if (newType.arrayDim == 0) {
if (constructor != null) { if (constructor != null) {
@ -313,8 +294,8 @@ public class NewExprent extends Exprent {
} }
} }
int start = enumconst ? 2 : 0; int start = enumConst ? 2 : 0;
if (!enumconst || start < lstParameters.size()) { if (!enumConst || start < lstParameters.size()) {
buf.append("("); buf.append("(");
boolean firstParam = true; boolean firstParam = true;
@ -346,16 +327,16 @@ public class NewExprent extends Exprent {
} }
} }
if (!enumconst) { if (!enumConst) {
String enclosing = null; String enclosing = null;
if (constructor != null) { if (constructor != null) {
enclosing = getQualifiedNewInstance(newtype.value, constructor.getLstParameters(), indent, tracer); enclosing = getQualifiedNewInstance(newType.value, constructor.getLstParameters(), indent, tracer);
} }
String typename = ExprProcessor.getTypeName(newtype); String typename = ExprProcessor.getTypeName(newType);
if (enclosing != null) { if (enclosing != null) {
ClassNode newNode = DecompilerContext.getClassProcessor().getMapRootClasses().get(newtype.value); ClassNode newNode = DecompilerContext.getClassProcessor().getMapRootClasses().get(newType.value);
if (newNode != null) { if (newNode != null) {
typename = newNode.simpleName; typename = newNode.simpleName;
} }
@ -371,10 +352,10 @@ public class NewExprent extends Exprent {
} }
} }
else { else {
buf.append("new ").append(ExprProcessor.getTypeName(newtype)); buf.append("new ").append(ExprProcessor.getTypeName(newType));
if (lstArrayElements.isEmpty()) { if (lstArrayElements.isEmpty()) {
for (int i = 0; i < newtype.arraydim; i++) { for (int i = 0; i < newType.arrayDim; i++) {
buf.append("["); buf.append("[");
if (i < lstDims.size()) { if (i < lstDims.size()) {
buf.append(lstDims.get(i).toJava(indent, tracer)); buf.append(lstDims.get(i).toJava(indent, tracer));
@ -383,13 +364,11 @@ public class NewExprent extends Exprent {
} }
} }
else { else {
for (int i = 0; i < newtype.arraydim; i++) { for (int i = 0; i < newType.arrayDim; i++) {
buf.append("[]"); buf.append("[]");
} }
VarType leftType = newtype.copy(); VarType leftType = newType.decreaseArrayDim();
leftType.decArrayDim();
buf.append("{"); buf.append("{");
for (int i = 0; i < lstArrayElements.size(); i++) { for (int i = 0; i < lstArrayElements.size(); i++) {
if (i > 0) { if (i > 0) {
@ -408,7 +387,6 @@ public class NewExprent extends Exprent {
} }
private static String getQualifiedNewInstance(String classname, List<Exprent> lstParams, int indent, BytecodeMappingTracer tracer) { private static String getQualifiedNewInstance(String classname, List<Exprent> lstParams, int indent, BytecodeMappingTracer tracer) {
ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(classname); ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(classname);
if (node != null && node.type != ClassNode.CLASS_ROOT && (node.access & CodeConstants.ACC_STATIC) == 0) { if (node != null && node.type != ClassNode.CLASS_ROOT && (node.access & CodeConstants.ACC_STATIC) == 0) {
@ -421,7 +399,7 @@ public class NewExprent extends Exprent {
VarExprent varEnclosing = (VarExprent)enclosing; VarExprent varEnclosing = (VarExprent)enclosing;
StructClass current_class = ((ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE)).classStruct; StructClass current_class = ((ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE)).classStruct;
String this_classname = varEnclosing.getProcessor().getThisvars().get(new VarVersionPaar(varEnclosing)); String this_classname = varEnclosing.getProcessor().getThisVars().get(new VarVersionPaar(varEnclosing));
if (!current_class.qualifiedName.equals(this_classname)) { if (!current_class.qualifiedName.equals(this_classname)) {
isQualifiedNew = true; isQualifiedNew = true;
@ -440,40 +418,42 @@ public class NewExprent extends Exprent {
return null; return null;
} }
public boolean equals(Object o) { @Override
if (o == this) return true; public void replaceExprent(Exprent oldExpr, Exprent newExpr) {
if (o == null || !(o instanceof NewExprent)) return false; if (oldExpr == constructor) {
constructor = (InvocationExprent)newExpr;
NewExprent ne = (NewExprent)o;
return InterpreterUtil.equalObjects(newtype, ne.getNewtype()) &&
InterpreterUtil.equalLists(lstDims, ne.getLstDims()) &&
InterpreterUtil.equalObjects(constructor, ne.getConstructor()) &&
directArrayInit == ne.directArrayInit &&
InterpreterUtil.equalLists(lstArrayElements, ne.getLstArrayElements());
}
public void replaceExprent(Exprent oldexpr, Exprent newexpr) {
if (oldexpr == constructor) {
constructor = (InvocationExprent)newexpr;
} }
if (constructor != null) { if (constructor != null) {
constructor.replaceExprent(oldexpr, newexpr); constructor.replaceExprent(oldExpr, newExpr);
} }
for (int i = 0; i < lstDims.size(); i++) { for (int i = 0; i < lstDims.size(); i++) {
if (oldexpr == lstDims.get(i)) { if (oldExpr == lstDims.get(i)) {
lstDims.set(i, newexpr); lstDims.set(i, newExpr);
} }
} }
for (int i = 0; i < lstArrayElements.size(); i++) { for (int i = 0; i < lstArrayElements.size(); i++) {
if (oldexpr == lstArrayElements.get(i)) { if (oldExpr == lstArrayElements.get(i)) {
lstArrayElements.set(i, newexpr); lstArrayElements.set(i, newExpr);
} }
} }
} }
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (o == null || !(o instanceof NewExprent)) return false;
NewExprent ne = (NewExprent)o;
return InterpreterUtil.equalObjects(newType, ne.getNewType()) &&
InterpreterUtil.equalLists(lstDims, ne.getLstDims()) &&
InterpreterUtil.equalObjects(constructor, ne.getConstructor()) &&
directArrayInit == ne.directArrayInit &&
InterpreterUtil.equalLists(lstArrayElements, ne.getLstArrayElements());
}
public InvocationExprent getConstructor() { public InvocationExprent getConstructor() {
return constructor; return constructor;
} }
@ -486,8 +466,8 @@ public class NewExprent extends Exprent {
return lstDims; return lstDims;
} }
public VarType getNewtype() { public VarType getNewType() {
return newtype; return newType;
} }
public List<Exprent> getLstArrayElements() { public List<Exprent> getLstArrayElements() {
@ -498,10 +478,6 @@ public class NewExprent extends Exprent {
this.lstArrayElements = lstArrayElements; this.lstArrayElements = lstArrayElements;
} }
public boolean isDirectArrayInit() {
return directArrayInit;
}
public void setDirectArrayInit(boolean directArrayInit) { public void setDirectArrayInit(boolean directArrayInit) {
this.directArrayInit = directArrayInit; this.directArrayInit = directArrayInit;
} }
@ -518,11 +494,7 @@ public class NewExprent extends Exprent {
this.anonymous = anonymous; this.anonymous = anonymous;
} }
public boolean isEnumconst() { public void setEnumConst(boolean enumConst) {
return enumconst; this.enumConst = enumConst;
}
public void setEnumconst(boolean enumconst) {
this.enumconst = enumconst;
} }
} }

@ -16,63 +16,60 @@
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import org.jetbrains.java.decompiler.main.TextBuffer; import org.jetbrains.java.decompiler.main.TextBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer; import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult; import org.jetbrains.java.decompiler.modules.decompiler.vars.CheckTypesResult;
import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class SwitchExprent extends Exprent { public class SwitchExprent extends Exprent {
private Exprent value; private Exprent value;
private List<List<ConstExprent>> caseValues = new ArrayList<List<ConstExprent>>(); private List<List<ConstExprent>> caseValues = new ArrayList<List<ConstExprent>>();
{ public SwitchExprent(Exprent value, Set<Integer> bytecodeOffsets) {
this.type = EXPRENT_SWITCH; super(EXPRENT_SWITCH);
}
public SwitchExprent(Exprent value, Set<Integer> bytecode_offsets) {
this.value = value; this.value = value;
addBytecodeOffsets(bytecode_offsets); addBytecodeOffsets(bytecodeOffsets);
} }
@Override @Override
public Exprent copy() { public Exprent copy() {
SwitchExprent swexpr = new SwitchExprent(value.copy(), bytecode); SwitchExprent swExpr = new SwitchExprent(value.copy(), bytecode);
List<List<ConstExprent>> lstCaseValues = new ArrayList<List<ConstExprent>>(); List<List<ConstExprent>> lstCaseValues = new ArrayList<List<ConstExprent>>();
for (List<ConstExprent> lst : caseValues) { for (List<ConstExprent> lst : caseValues) {
lstCaseValues.add(new ArrayList<ConstExprent>(lst)); lstCaseValues.add(new ArrayList<ConstExprent>(lst));
} }
swexpr.setCaseValues(lstCaseValues); swExpr.setCaseValues(lstCaseValues);
return swexpr; return swExpr;
} }
@Override
public VarType getExprType() { public VarType getExprType() {
return value.getExprType(); return value.getExprType();
} }
@Override
public CheckTypesResult checkExprTypeBounds() { public CheckTypesResult checkExprTypeBounds() {
CheckTypesResult result = new CheckTypesResult(); CheckTypesResult result = new CheckTypesResult();
result.addMinTypeExprent(value, VarType.VARTYPE_BYTECHAR); result.addMinTypeExprent(value, VarType.VARTYPE_BYTECHAR);
result.addMaxTypeExprent(value, VarType.VARTYPE_INT); result.addMaxTypeExprent(value, VarType.VARTYPE_INT);
VarType valtype = value.getExprType(); VarType valType = value.getExprType();
for (List<ConstExprent> lst : caseValues) { for (List<ConstExprent> lst : caseValues) {
for (ConstExprent expr : lst) { for (ConstExprent expr : lst) {
if (expr != null) { if (expr != null) {
VarType casetype = expr.getExprType(); VarType caseType = expr.getExprType();
if (!casetype.equals(valtype)) { if (!caseType.equals(valType)) {
valtype = VarType.getCommonSupertype(casetype, valtype); valType = VarType.getCommonSupertype(caseType, valType);
result.addMinTypeExprent(value, valtype); result.addMinTypeExprent(value, valType);
} }
} }
} }
@ -81,6 +78,7 @@ public class SwitchExprent extends Exprent {
return result; return result;
} }
@Override
public List<Exprent> getAllExprents() { public List<Exprent> getAllExprents() {
List<Exprent> lst = new ArrayList<Exprent>(); List<Exprent> lst = new ArrayList<Exprent>();
lst.add(value); lst.add(value);
@ -93,6 +91,14 @@ public class SwitchExprent extends Exprent {
return value.toJava(indent, tracer).enclose("switch(", ")"); return value.toJava(indent, tracer).enclose("switch(", ")");
} }
@Override
public void replaceExprent(Exprent oldExpr, Exprent newExpr) {
if (oldExpr == value) {
value = newExpr;
}
}
@Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (o == this) { if (o == this) {
return true; return true;
@ -106,12 +112,6 @@ public class SwitchExprent extends Exprent {
return InterpreterUtil.equalObjects(value, sw.getValue()); return InterpreterUtil.equalObjects(value, sw.getValue());
} }
public void replaceExprent(Exprent oldexpr, Exprent newexpr) {
if (oldexpr == value) {
value = newexpr;
}
}
public Exprent getValue() { public Exprent getValue() {
return value; return value;
} }

@ -15,9 +15,6 @@
*/ */
package org.jetbrains.java.decompiler.modules.decompiler.exps; package org.jetbrains.java.decompiler.modules.decompiler.exps;
import java.util.ArrayList;
import java.util.List;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.ClassWriter; import org.jetbrains.java.decompiler.main.ClassWriter;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
@ -31,54 +28,50 @@ import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPaar;
import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.util.ArrayList;
import java.util.List;
public class VarExprent extends Exprent { public class VarExprent extends Exprent {
public static final int STACK_BASE = 10000; public static final int STACK_BASE = 10000;
public static final String VAR_NAMELESS_ENCLOSURE = "<VAR_NAMELESS_ENCLOSURE>"; public static final String VAR_NAMELESS_ENCLOSURE = "<VAR_NAMELESS_ENCLOSURE>";
private int index; private int index;
private VarType varType;
private VarType vartype;
private boolean definition = false; private boolean definition = false;
private VarProcessor processor; private VarProcessor processor;
private int version = 0; private int version = 0;
private boolean classDef = false;
private boolean classdef = false;
private boolean stack = false; private boolean stack = false;
{ public VarExprent(int index, VarType varType, VarProcessor processor) {
this.type = EXPRENT_VAR; super(EXPRENT_VAR);
}
public VarExprent(int index, VarType vartype, VarProcessor processor) {
this.index = index; this.index = index;
this.vartype = vartype; this.varType = varType;
this.processor = processor; this.processor = processor;
} }
@Override
public VarType getExprType() { public VarType getExprType() {
return getVartype(); return getVarType();
} }
@Override
public int getExprentUse() { public int getExprentUse() {
return Exprent.MULTIPLE_USES | Exprent.SIDE_EFFECTS_FREE; return Exprent.MULTIPLE_USES | Exprent.SIDE_EFFECTS_FREE;
} }
@Override
public List<Exprent> getAllExprents() { public List<Exprent> getAllExprents() {
return new ArrayList<Exprent>(); return new ArrayList<Exprent>();
} }
@Override @Override
public Exprent copy() { public Exprent copy() {
VarExprent var = new VarExprent(index, getVartype(), processor); VarExprent var = new VarExprent(index, getVarType(), processor);
var.setDefinition(definition); var.setDefinition(definition);
var.setVersion(version); var.setVersion(version);
var.setClassdef(classdef); var.setClassDef(classDef);
var.setStack(stack); var.setStack(stack);
return var; return var;
} }
@ -89,8 +82,8 @@ public class VarExprent extends Exprent {
tracer.addMapping(bytecode); tracer.addMapping(bytecode);
if (classdef) { if (classDef) {
ClassNode child = DecompilerContext.getClassProcessor().getMapRootClasses().get(vartype.value); ClassNode child = DecompilerContext.getClassProcessor().getMapRootClasses().get(varType.value);
new ClassWriter().classToJava(child, buffer, indent, tracer); new ClassWriter().classToJava(child, buffer, indent, tracer);
} }
else { else {
@ -100,10 +93,10 @@ public class VarExprent extends Exprent {
} }
if (definition) { if (definition) {
if (processor != null && processor.getVarFinal(new VarVersionPaar(index, version)) == VarTypeProcessor.VAR_FINALEXPLICIT) { if (processor != null && processor.getVarFinal(new VarVersionPaar(index, version)) == VarTypeProcessor.VAR_EXPLICIT_FINAL) {
buffer.append("final "); buffer.append("final ");
} }
buffer.append(ExprProcessor.getCastTypeName(getVartype())).append(" "); buffer.append(ExprProcessor.getCastTypeName(getVarType())).append(" ");
} }
buffer.append(name == null ? ("var" + index + (version == 0 ? "" : "_" + version)) : name); buffer.append(name == null ? ("var" + index + (version == 0 ? "" : "_" + version)) : name);
} }
@ -111,6 +104,7 @@ public class VarExprent extends Exprent {
return buffer; return buffer;
} }
@Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (o == this) return true; if (o == this) return true;
if (o == null || !(o instanceof VarExprent)) return false; if (o == null || !(o instanceof VarExprent)) return false;
@ -118,7 +112,7 @@ public class VarExprent extends Exprent {
VarExprent ve = (VarExprent)o; VarExprent ve = (VarExprent)o;
return index == ve.getIndex() && return index == ve.getIndex() &&
version == ve.getVersion() && version == ve.getVersion() &&
InterpreterUtil.equalObjects(getVartype(), ve.getVartype()); // FIXME: vartype comparison redundant? InterpreterUtil.equalObjects(getVarType(), ve.getVarType()); // FIXME: varType comparison redundant?
} }
public int getIndex() { public int getIndex() {
@ -129,21 +123,21 @@ public class VarExprent extends Exprent {
this.index = index; this.index = index;
} }
public VarType getVartype() { public VarType getVarType() {
VarType vt = null; VarType vt = null;
if (processor != null) { if (processor != null) {
vt = processor.getVarType(new VarVersionPaar(index, version)); vt = processor.getVarType(new VarVersionPaar(index, version));
} }
if (vt == null || (vartype != null && vartype.type != CodeConstants.TYPE_UNKNOWN)) { if (vt == null || (varType != null && varType.type != CodeConstants.TYPE_UNKNOWN)) {
vt = vartype; vt = varType;
} }
return vt == null ? VarType.VARTYPE_UNKNOWN : vt; return vt == null ? VarType.VARTYPE_UNKNOWN : vt;
} }
public void setVartype(VarType vartype) { public void setVarType(VarType varType) {
this.vartype = vartype; this.varType = varType;
} }
public boolean isDefinition() { public boolean isDefinition() {
@ -170,12 +164,12 @@ public class VarExprent extends Exprent {
this.version = version; this.version = version;
} }
public boolean isClassdef() { public boolean isClassDef() {
return classdef; return classDef;
} }
public void setClassdef(boolean classdef) { public void setClassDef(boolean classDef) {
this.classdef = classdef; this.classDef = classDef;
} }
public boolean isStack() { public boolean isStack() {

@ -157,7 +157,7 @@ public class SSAConstructorSparseEx {
switch (expr.type) { switch (expr.type) {
case Exprent.EXPRENT_ASSIGNMENT: case Exprent.EXPRENT_ASSIGNMENT:
AssignmentExprent assexpr = (AssignmentExprent)expr; AssignmentExprent assexpr = (AssignmentExprent)expr;
if (assexpr.getCondtype() == AssignmentExprent.CONDITION_NONE) { if (assexpr.getCondType() == AssignmentExprent.CONDITION_NONE) {
Exprent dest = assexpr.getLeft(); Exprent dest = assexpr.getLeft();
if (dest.type == Exprent.EXPRENT_VAR) { if (dest.type == Exprent.EXPRENT_VAR) {
varassign = (VarExprent)dest; varassign = (VarExprent)dest;
@ -166,7 +166,7 @@ public class SSAConstructorSparseEx {
break; break;
case Exprent.EXPRENT_FUNCTION: case Exprent.EXPRENT_FUNCTION:
FunctionExprent func = (FunctionExprent)expr; FunctionExprent func = (FunctionExprent)expr;
switch (func.getFunctype()) { switch (func.getFuncType()) {
case FunctionExprent.FUNCTION_IIF: case FunctionExprent.FUNCTION_IIF:
processExprent(func.getLstOperands().get(0), varmaparr); processExprent(func.getLstOperands().get(0), varmaparr);
@ -508,11 +508,11 @@ public class SSAConstructorSparseEx {
varindex++; varindex++;
} }
else { else {
varindex += md.params[i - 1].stack_size; varindex += md.params[i - 1].stackSize;
} }
} }
else { else {
varindex += md.params[i].stack_size; varindex += md.params[i].stackSize;
} }
} }

@ -177,7 +177,7 @@ public class SSAUConstructorSparseEx {
switch (expr.type) { switch (expr.type) {
case Exprent.EXPRENT_ASSIGNMENT: case Exprent.EXPRENT_ASSIGNMENT:
AssignmentExprent assexpr = (AssignmentExprent)expr; AssignmentExprent assexpr = (AssignmentExprent)expr;
if (assexpr.getCondtype() == AssignmentExprent.CONDITION_NONE) { if (assexpr.getCondType() == AssignmentExprent.CONDITION_NONE) {
Exprent dest = assexpr.getLeft(); Exprent dest = assexpr.getLeft();
if (dest.type == Exprent.EXPRENT_VAR) { if (dest.type == Exprent.EXPRENT_VAR) {
varassign = (VarExprent)dest; varassign = (VarExprent)dest;
@ -186,7 +186,7 @@ public class SSAUConstructorSparseEx {
break; break;
case Exprent.EXPRENT_FUNCTION: case Exprent.EXPRENT_FUNCTION:
FunctionExprent func = (FunctionExprent)expr; FunctionExprent func = (FunctionExprent)expr;
switch (func.getFunctype()) { switch (func.getFuncType()) {
case FunctionExprent.FUNCTION_IIF: case FunctionExprent.FUNCTION_IIF:
processExprent(func.getLstOperands().get(0), varmaparr, stat, calcLiveVars); processExprent(func.getLstOperands().get(0), varmaparr, stat, calcLiveVars);
@ -271,7 +271,7 @@ public class SSAUConstructorSparseEx {
} }
else if (expr.type == Exprent.EXPRENT_INVOCATION || else if (expr.type == Exprent.EXPRENT_INVOCATION ||
(expr.type == Exprent.EXPRENT_ASSIGNMENT && ((AssignmentExprent)expr).getLeft().type == Exprent.EXPRENT_FIELD) || (expr.type == Exprent.EXPRENT_ASSIGNMENT && ((AssignmentExprent)expr).getLeft().type == Exprent.EXPRENT_FIELD) ||
(expr.type == Exprent.EXPRENT_NEW && ((NewExprent)expr).getNewtype().type == CodeConstants.TYPE_OBJECT) || (expr.type == Exprent.EXPRENT_NEW && ((NewExprent)expr).getNewType().type == CodeConstants.TYPE_OBJECT) ||
expr.type == Exprent.EXPRENT_FUNCTION) { expr.type == Exprent.EXPRENT_FUNCTION) {
boolean ismmpp = true; boolean ismmpp = true;
@ -281,7 +281,7 @@ public class SSAUConstructorSparseEx {
ismmpp = false; ismmpp = false;
FunctionExprent fexpr = (FunctionExprent)expr; FunctionExprent fexpr = (FunctionExprent)expr;
if (fexpr.getFunctype() >= FunctionExprent.FUNCTION_IMM && fexpr.getFunctype() <= FunctionExprent.FUNCTION_PPI) { if (fexpr.getFuncType() >= FunctionExprent.FUNCTION_IMM && fexpr.getFuncType() <= FunctionExprent.FUNCTION_PPI) {
if (fexpr.getLstOperands().get(0).type == Exprent.EXPRENT_FIELD) { if (fexpr.getLstOperands().get(0).type == Exprent.EXPRENT_FIELD) {
ismmpp = true; ismmpp = true;
} }
@ -320,7 +320,7 @@ public class SSAUConstructorSparseEx {
else if (expr.type == Exprent.EXPRENT_FUNCTION) { // MM or PP function else if (expr.type == Exprent.EXPRENT_FUNCTION) { // MM or PP function
FunctionExprent func = (FunctionExprent)expr; FunctionExprent func = (FunctionExprent)expr;
switch (func.getFunctype()) { switch (func.getFuncType()) {
case FunctionExprent.FUNCTION_IMM: case FunctionExprent.FUNCTION_IMM:
case FunctionExprent.FUNCTION_MMI: case FunctionExprent.FUNCTION_MMI:
case FunctionExprent.FUNCTION_IPP: case FunctionExprent.FUNCTION_IPP:
@ -777,11 +777,11 @@ public class SSAUConstructorSparseEx {
varindex++; varindex++;
} }
else { else {
varindex += md.params[i - 1].stack_size; varindex += md.params[i - 1].stackSize;
} }
} }
else { else {
varindex += md.params[i].stack_size; varindex += md.params[i].stackSize;
} }
} }

@ -135,7 +135,7 @@ public class SwitchStatement extends Statement {
} }
else { else {
ConstExprent value = (ConstExprent)values.get(j).copy(); ConstExprent value = (ConstExprent)values.get(j).copy();
value.setConsttype(switch_type); value.setConstType(switch_type);
buf.appendIndent(indent).append("case ").append(value.toJava(indent, tracer)).append(":").appendLineSeparator(); buf.appendIndent(indent).append("case ").append(value.toJava(indent, tracer)).append(":").appendLineSeparator();
tracer.incrementCurrentSourceLine(); tracer.incrementCurrentSourceLine();

@ -75,18 +75,18 @@ public class VarDefinitionHelper {
varindex++; varindex++;
} }
else { else {
varindex += md.params[i - 1].stack_size; varindex += md.params[i - 1].stackSize;
} }
} }
else { else {
varindex += md.params[i].stack_size; varindex += md.params[i].stackSize;
} }
} }
if (thisvar) { if (thisvar) {
StructClass current_class = (StructClass)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS); StructClass current_class = (StructClass)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS);
varproc.getThisvars().put(new VarVersionPaar(0, 0), current_class.qualifiedName); varproc.getThisVars().put(new VarVersionPaar(0, 0), current_class.qualifiedName);
varproc.setVarName(new VarVersionPaar(0, 0), "this"); varproc.setVarName(new VarVersionPaar(0, 0), "this");
vc.addName("this"); vc.addName("this");
} }

@ -25,54 +25,48 @@ import org.jetbrains.java.decompiler.struct.gen.VarType;
import java.util.*; import java.util.*;
import java.util.Map.Entry; import java.util.Map.Entry;
public class VarProcessor { public class VarProcessor {
private HashMap<VarVersionPaar, String> mapVarNames = new HashMap<VarVersionPaar, String>(); private Map<VarVersionPaar, String> mapVarNames = new HashMap<VarVersionPaar, String>();
private VarVersionsProcessor varVersions;
private VarVersionsProcessor varvers; private Map<VarVersionPaar, String> thisVars = new HashMap<VarVersionPaar, String>();
private Set<VarVersionPaar> externalVars = new HashSet<VarVersionPaar>();
private HashMap<VarVersionPaar, String> thisvars = new HashMap<VarVersionPaar, String>();
private HashSet<VarVersionPaar> externvars = new HashSet<VarVersionPaar>();
public void setVarVersions(RootStatement root) { public void setVarVersions(RootStatement root) {
varVersions = new VarVersionsProcessor();
varvers = new VarVersionsProcessor(); varVersions.setVarVersions(root);
varvers.setVarVersions(root);
} }
public void setVarDefinitions(Statement root) { public void setVarDefinitions(Statement root) {
mapVarNames = new HashMap<VarVersionPaar, String>(); mapVarNames = new HashMap<VarVersionPaar, String>();
VarDefinitionHelper defproc = new VarDefinitionHelper(root, StructMethod mt = (StructMethod)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD);
(StructMethod)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD), new VarDefinitionHelper(root, mt, this).setVarDefinitions();
this);
defproc.setVarDefinitions();
} }
public void setDebugVarNames(Map<Integer, String> mapDebugVarNames) { public void setDebugVarNames(Map<Integer, String> mapDebugVarNames) {
if (varvers == null) { if (varVersions == null) {
return; return;
} }
HashMap<Integer, Integer> mapOriginalVarIndices = varvers.getMapOriginalVarIndices(); Map<Integer, Integer> mapOriginalVarIndices = varVersions.getMapOriginalVarIndices();
List<VarVersionPaar> listVars = new ArrayList<VarVersionPaar>(mapVarNames.keySet()); List<VarVersionPaar> listVars = new ArrayList<VarVersionPaar>(mapVarNames.keySet());
Collections.sort(listVars, new Comparator<VarVersionPaar>() { Collections.sort(listVars, new Comparator<VarVersionPaar>() {
@Override
public int compare(VarVersionPaar o1, VarVersionPaar o2) { public int compare(VarVersionPaar o1, VarVersionPaar o2) {
return o1.var > o2.var ? 1 : (o1.var == o2.var ? 0 : -1); return o1.var - o2.var;
} }
}); });
HashMap<String, Integer> mapNames = new HashMap<String, Integer>(); Map<String, Integer> mapNames = new HashMap<String, Integer>();
for (VarVersionPaar varpaar : listVars) { for (VarVersionPaar pair : listVars) {
String name = mapVarNames.get(varpaar); String name = mapVarNames.get(pair);
Integer orindex = mapOriginalVarIndices.get(varpaar.var); Integer index = mapOriginalVarIndices.get(pair.var);
if (orindex != null && mapDebugVarNames.containsKey(orindex)) { if (index != null && mapDebugVarNames.containsKey(index)) {
name = mapDebugVarNames.get(orindex); name = mapDebugVarNames.get(index);
} }
Integer counter = mapNames.get(name); Integer counter = mapNames.get(name);
@ -82,48 +76,46 @@ public class VarProcessor {
name += String.valueOf(counter); name += String.valueOf(counter);
} }
mapVarNames.put(varpaar, name); mapVarNames.put(pair, name);
} }
} }
public void refreshVarNames(VarNamesCollector vc) { public void refreshVarNames(VarNamesCollector vc) {
Map<VarVersionPaar, String> tempVarNames = new HashMap<VarVersionPaar, String>(mapVarNames);
HashMap<VarVersionPaar, String> tempVarNames = new HashMap<VarVersionPaar, String>(mapVarNames);
for (Entry<VarVersionPaar, String> ent : tempVarNames.entrySet()) { for (Entry<VarVersionPaar, String> ent : tempVarNames.entrySet()) {
mapVarNames.put(ent.getKey(), vc.getFreeName(ent.getValue())); mapVarNames.put(ent.getKey(), vc.getFreeName(ent.getValue()));
} }
} }
public VarType getVarType(VarVersionPaar pair) {
public VarType getVarType(VarVersionPaar varpaar) { return varVersions == null ? null : varVersions.getVarType(pair);
return varvers == null ? null : varvers.getVarType(varpaar);
} }
public void setVarType(VarVersionPaar varpaar, VarType type) { public void setVarType(VarVersionPaar pair, VarType type) {
varvers.setVarType(varpaar, type); varVersions.setVarType(pair, type);
} }
public String getVarName(VarVersionPaar varpaar) { public String getVarName(VarVersionPaar pair) {
return mapVarNames == null ? null : mapVarNames.get(varpaar); return mapVarNames == null ? null : mapVarNames.get(pair);
} }
public void setVarName(VarVersionPaar varpaar, String name) { public void setVarName(VarVersionPaar pair, String name) {
mapVarNames.put(varpaar, name); mapVarNames.put(pair, name);
} }
public int getVarFinal(VarVersionPaar varpaar) { public int getVarFinal(VarVersionPaar pair) {
return varvers == null ? VarTypeProcessor.VAR_FINAL : varvers.getVarFinal(varpaar); return varVersions == null ? VarTypeProcessor.VAR_FINAL : varVersions.getVarFinal(pair);
} }
public void setVarFinal(VarVersionPaar varpaar, int finaltype) { public void setVarFinal(VarVersionPaar pair, int finalType) {
varvers.setVarFinal(varpaar, finaltype); varVersions.setVarFinal(pair, finalType);
} }
public HashMap<VarVersionPaar, String> getThisvars() { public Map<VarVersionPaar, String> getThisVars() {
return thisvars; return thisVars;
} }
public HashSet<VarVersionPaar> getExternvars() { public Set<VarVersionPaar> getExternalVars() {
return externvars; return externalVars;
} }
} }

@ -31,40 +31,37 @@ import org.jetbrains.java.decompiler.struct.gen.VarType;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map;
public class VarTypeProcessor { public class VarTypeProcessor {
public static final int VAR_NONFINAL = 1; public static final int VAR_NON_FINAL = 1;
public static final int VAR_FINALEXPLICIT = 2; public static final int VAR_EXPLICIT_FINAL = 2;
public static final int VAR_FINAL = 3; public static final int VAR_FINAL = 3;
private HashMap<VarVersionPaar, VarType> mapExprentMinTypes = new HashMap<VarVersionPaar, VarType>(); private Map<VarVersionPaar, VarType> mapExprentMinTypes = new HashMap<VarVersionPaar, VarType>();
private Map<VarVersionPaar, VarType> mapExprentMaxTypes = new HashMap<VarVersionPaar, VarType>();
private HashMap<VarVersionPaar, VarType> mapExprentMaxTypes = new HashMap<VarVersionPaar, VarType>(); private Map<VarVersionPaar, Integer> mapFinalVars = new HashMap<VarVersionPaar, Integer>();
private HashMap<VarVersionPaar, Integer> mapFinalVars = new HashMap<VarVersionPaar, Integer>();
private void setInitVars(RootStatement root) { private void setInitVars(RootStatement root) {
StructMethod mt = (StructMethod)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD); StructMethod mt = (StructMethod)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD);
// method descriptor boolean thisVar = !mt.hasModifier(CodeConstants.ACC_STATIC);
boolean thisvar = !mt.hasModifier(CodeConstants.ACC_STATIC);
MethodDescriptor md = (MethodDescriptor)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD_DESCRIPTOR); MethodDescriptor md = (MethodDescriptor)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD_DESCRIPTOR);
if (thisvar) { if (thisVar) {
VarType cltype = new VarType(CodeConstants.TYPE_OBJECT, 0, StructClass cl = (StructClass)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS);
((StructClass)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS)).qualifiedName); VarType clType = new VarType(CodeConstants.TYPE_OBJECT, 0, cl.qualifiedName);
mapExprentMinTypes.put(new VarVersionPaar(0, 1), cltype); mapExprentMinTypes.put(new VarVersionPaar(0, 1), clType);
mapExprentMaxTypes.put(new VarVersionPaar(0, 1), cltype); mapExprentMaxTypes.put(new VarVersionPaar(0, 1), clType);
} }
int varindex = 0; int varIndex = 0;
for (int i = 0; i < md.params.length; i++) { for (int i = 0; i < md.params.length; i++) {
mapExprentMinTypes.put(new VarVersionPaar(varindex + (thisvar ? 1 : 0), 1), md.params[i]); mapExprentMinTypes.put(new VarVersionPaar(varIndex + (thisVar ? 1 : 0), 1), md.params[i]);
mapExprentMaxTypes.put(new VarVersionPaar(varindex + (thisvar ? 1 : 0), 1), md.params[i]); mapExprentMaxTypes.put(new VarVersionPaar(varIndex + (thisVar ? 1 : 0), 1), md.params[i]);
varindex += md.params[i].stack_size; varIndex += md.params[i].stackSize;
} }
// catch variables // catch variables
@ -84,8 +81,8 @@ public class VarTypeProcessor {
if (lstVars != null) { if (lstVars != null) {
for (VarExprent var : lstVars) { for (VarExprent var : lstVars) {
mapExprentMinTypes.put(new VarVersionPaar(var.getIndex(), 1), var.getVartype()); mapExprentMinTypes.put(new VarVersionPaar(var.getIndex(), 1), var.getVarType());
mapExprentMaxTypes.put(new VarVersionPaar(var.getIndex(), 1), var.getVartype()); mapExprentMaxTypes.put(new VarVersionPaar(var.getIndex(), 1), var.getVarType());
} }
} }
@ -93,30 +90,30 @@ public class VarTypeProcessor {
} }
} }
public void calculateVarTypes(RootStatement root, DirectGraph dgraph) { public void calculateVarTypes(RootStatement root, DirectGraph graph) {
setInitVars(root); setInitVars(root);
resetExprentTypes(dgraph); resetExprentTypes(graph);
while (!processVarTypes(dgraph)) ; //noinspection StatementWithEmptyBody
while (!processVarTypes(graph)) ;
} }
private static void resetExprentTypes(DirectGraph dgraph) { private static void resetExprentTypes(DirectGraph graph) {
graph.iterateExprents(new DirectGraph.ExprentIterator() {
dgraph.iterateExprents(new DirectGraph.ExprentIterator() { @Override
public int processExprent(Exprent exprent) { public int processExprent(Exprent exprent) {
List<Exprent> lst = exprent.getAllExprents(true); List<Exprent> lst = exprent.getAllExprents(true);
lst.add(exprent); lst.add(exprent);
for (Exprent expr : lst) { for (Exprent expr : lst) {
if (expr.type == Exprent.EXPRENT_VAR) { if (expr.type == Exprent.EXPRENT_VAR) {
((VarExprent)expr).setVartype(VarType.VARTYPE_UNKNOWN); ((VarExprent)expr).setVarType(VarType.VARTYPE_UNKNOWN);
} }
else if (expr.type == Exprent.EXPRENT_CONST) { else if (expr.type == Exprent.EXPRENT_CONST) {
ConstExprent cexpr = (ConstExprent)expr; ConstExprent constExpr = (ConstExprent)expr;
if (cexpr.getConsttype().type_family == CodeConstants.TYPE_FAMILY_INTEGER) { if (constExpr.getConstType().typeFamily == CodeConstants.TYPE_FAMILY_INTEGER) {
cexpr.setConsttype(new ConstExprent(cexpr.getIntValue(), cexpr.isBoolPermitted(), null).getConsttype()); constExpr.setConstType(new ConstExprent(constExpr.getIntValue(), constExpr.isBoolPermitted(), null).getConstType());
} }
} }
} }
@ -125,16 +122,15 @@ public class VarTypeProcessor {
}); });
} }
private boolean processVarTypes(DirectGraph dgraph) { private boolean processVarTypes(DirectGraph graph) {
return graph.iterateExprents(new DirectGraph.ExprentIterator() {
return dgraph.iterateExprents(new DirectGraph.ExprentIterator() { @Override
public int processExprent(Exprent exprent) { public int processExprent(Exprent exprent) {
return checkTypeExprent(exprent) ? 0 : 1; return checkTypeExprent(exprent) ? 0 : 1;
} }
}); });
} }
private boolean checkTypeExprent(Exprent exprent) { private boolean checkTypeExprent(Exprent exprent) {
for (Exprent expr : exprent.getAllExprents()) { for (Exprent expr : exprent.getAllExprents()) {
@ -144,11 +140,11 @@ public class VarTypeProcessor {
} }
if (exprent.type == Exprent.EXPRENT_CONST) { if (exprent.type == Exprent.EXPRENT_CONST) {
ConstExprent cexpr = (ConstExprent)exprent; ConstExprent constExpr = (ConstExprent)exprent;
if (cexpr.getConsttype().type_family <= CodeConstants.TYPE_FAMILY_INTEGER) { // boolean or integer if (constExpr.getConstType().typeFamily <= CodeConstants.TYPE_FAMILY_INTEGER) { // boolean or integer
VarVersionPaar cpaar = new VarVersionPaar(cexpr.id, -1); VarVersionPaar pair = new VarVersionPaar(constExpr.id, -1);
if (!mapExprentMinTypes.containsKey(cpaar)) { if (!mapExprentMinTypes.containsKey(pair)) {
mapExprentMinTypes.put(cpaar, cexpr.getConsttype()); mapExprentMinTypes.put(pair, constExpr.getConstType());
} }
} }
} }
@ -156,7 +152,7 @@ public class VarTypeProcessor {
CheckTypesResult result = exprent.checkExprTypeBounds(); CheckTypesResult result = exprent.checkExprTypeBounds();
for (CheckTypesResult.ExprentTypePair entry : result.getLstMaxTypeExprents()) { for (CheckTypesResult.ExprentTypePair entry : result.getLstMaxTypeExprents()) {
if (entry.type.type_family != CodeConstants.TYPE_FAMILY_OBJECT) { if (entry.type.typeFamily != CodeConstants.TYPE_FAMILY_OBJECT) {
changeExprentType(entry.exprent, entry.type, 1); changeExprentType(entry.exprent, entry.type, 1);
} }
} }
@ -170,109 +166,112 @@ public class VarTypeProcessor {
} }
private boolean changeExprentType(Exprent exprent, VarType newtype, int minmax) { private boolean changeExprentType(Exprent exprent, VarType newType, int minMax) {
boolean res = true; boolean res = true;
switch (exprent.type) { switch (exprent.type) {
case Exprent.EXPRENT_CONST: case Exprent.EXPRENT_CONST:
ConstExprent cexpr = (ConstExprent)exprent; ConstExprent constExpr = (ConstExprent)exprent;
VarType consttype = cexpr.getConsttype(); VarType constType = constExpr.getConstType();
if (newtype.type_family > CodeConstants.TYPE_FAMILY_INTEGER || consttype.type_family > CodeConstants.TYPE_FAMILY_INTEGER) { if (newType.typeFamily > CodeConstants.TYPE_FAMILY_INTEGER || constType.typeFamily > CodeConstants.TYPE_FAMILY_INTEGER) {
return true; return true;
} }
else if (newtype.type_family == CodeConstants.TYPE_FAMILY_INTEGER) { else if (newType.typeFamily == CodeConstants.TYPE_FAMILY_INTEGER) {
VarType mininteger = new ConstExprent((Integer)((ConstExprent)exprent).getValue(), false, null).getConsttype(); VarType minInteger = new ConstExprent((Integer)constExpr.getValue(), false, null).getConstType();
if (mininteger.isStrictSuperset(newtype)) { if (minInteger.isStrictSuperset(newType)) {
newtype = mininteger; newType = minInteger;
} }
} }
case Exprent.EXPRENT_VAR: case Exprent.EXPRENT_VAR:
VarVersionPaar varpaar = null; VarVersionPaar pair = null;
if (exprent.type == Exprent.EXPRENT_CONST) { if (exprent.type == Exprent.EXPRENT_CONST) {
varpaar = new VarVersionPaar(((ConstExprent)exprent).id, -1); pair = new VarVersionPaar(((ConstExprent)exprent).id, -1);
} }
else if (exprent.type == Exprent.EXPRENT_VAR) { else if (exprent.type == Exprent.EXPRENT_VAR) {
varpaar = new VarVersionPaar((VarExprent)exprent); //noinspection ConstantConditions
pair = new VarVersionPaar((VarExprent)exprent);
} }
if (minmax == 0) { // min if (minMax == 0) { // min
VarType currentMinType = mapExprentMinTypes.get(varpaar); VarType currentMinType = mapExprentMinTypes.get(pair);
VarType newMinType; VarType newMinType;
if (currentMinType == null || newtype.type_family > currentMinType.type_family) { if (currentMinType == null || newType.typeFamily > currentMinType.typeFamily) {
newMinType = newtype; newMinType = newType;
} }
else if (newtype.type_family < currentMinType.type_family) { else if (newType.typeFamily < currentMinType.typeFamily) {
return true; return true;
} }
else { else {
newMinType = VarType.getCommonSupertype(currentMinType, newtype); newMinType = VarType.getCommonSupertype(currentMinType, newType);
} }
mapExprentMinTypes.put(varpaar, newMinType); mapExprentMinTypes.put(pair, newMinType);
if (exprent.type == Exprent.EXPRENT_CONST) { if (exprent.type == Exprent.EXPRENT_CONST) {
((ConstExprent)exprent).setConsttype(newMinType); //noinspection ConstantConditions
((ConstExprent)exprent).setConstType(newMinType);
} }
if (currentMinType != null && (newMinType.type_family > currentMinType.type_family || if (currentMinType != null && (newMinType.typeFamily > currentMinType.typeFamily || newMinType.isStrictSuperset(currentMinType))) {
newMinType.isStrictSuperset(currentMinType))) {
return false; return false;
} }
} }
else { // max else { // max
VarType currentMaxType = mapExprentMaxTypes.get(varpaar); VarType currentMaxType = mapExprentMaxTypes.get(pair);
VarType newMaxType; VarType newMaxType;
if (currentMaxType == null || newtype.type_family < currentMaxType.type_family) { if (currentMaxType == null || newType.typeFamily < currentMaxType.typeFamily) {
newMaxType = newtype; newMaxType = newType;
} }
else if (newtype.type_family > currentMaxType.type_family) { else if (newType.typeFamily > currentMaxType.typeFamily) {
return true; return true;
} }
else { else {
newMaxType = VarType.getCommonMinType(currentMaxType, newtype); newMaxType = VarType.getCommonMinType(currentMaxType, newType);
} }
mapExprentMaxTypes.put(varpaar, newMaxType); mapExprentMaxTypes.put(pair, newMaxType);
} }
break; break;
case Exprent.EXPRENT_ASSIGNMENT: case Exprent.EXPRENT_ASSIGNMENT:
return changeExprentType(((AssignmentExprent)exprent).getRight(), newtype, minmax); return changeExprentType(((AssignmentExprent)exprent).getRight(), newType, minMax);
case Exprent.EXPRENT_FUNCTION: case Exprent.EXPRENT_FUNCTION:
FunctionExprent func = (FunctionExprent)exprent; FunctionExprent func = (FunctionExprent)exprent;
switch (func.getFunctype()) { switch (func.getFuncType()) {
case FunctionExprent.FUNCTION_IIF: // FIXME: case FunctionExprent.FUNCTION_IIF: // FIXME:
res &= changeExprentType(func.getLstOperands().get(1), newtype, minmax); res = changeExprentType(func.getLstOperands().get(1), newType, minMax) &
res &= changeExprentType(func.getLstOperands().get(2), newtype, minmax); changeExprentType(func.getLstOperands().get(2), newType, minMax);
break; break;
case FunctionExprent.FUNCTION_AND: case FunctionExprent.FUNCTION_AND:
case FunctionExprent.FUNCTION_OR: case FunctionExprent.FUNCTION_OR:
case FunctionExprent.FUNCTION_XOR: case FunctionExprent.FUNCTION_XOR:
res &= changeExprentType(func.getLstOperands().get(0), newtype, minmax); res = changeExprentType(func.getLstOperands().get(0), newType, minMax) &
res &= changeExprentType(func.getLstOperands().get(1), newtype, minmax); changeExprentType(func.getLstOperands().get(1), newType, minMax);
break;
} }
} }
return res; return res;
} }
public HashMap<VarVersionPaar, VarType> getMapExprentMaxTypes() { public Map<VarVersionPaar, VarType> getMapExprentMaxTypes() {
return mapExprentMaxTypes; return mapExprentMaxTypes;
} }
public HashMap<VarVersionPaar, VarType> getMapExprentMinTypes() { public Map<VarVersionPaar, VarType> getMapExprentMinTypes() {
return mapExprentMinTypes; return mapExprentMinTypes;
} }
public HashMap<VarVersionPaar, Integer> getMapFinalVars() { public Map<VarVersionPaar, Integer> getMapFinalVars() {
return mapFinalVars; return mapFinalVars;
} }
public void setVarType(VarVersionPaar varpaar, VarType type) { public void setVarType(VarVersionPaar pair, VarType type) {
mapExprentMinTypes.put(varpaar, type); mapExprentMinTypes.put(pair, type);
} }
public VarType getVarType(VarVersionPaar varpaar) { public VarType getVarType(VarVersionPaar pair) {
return mapExprentMinTypes.get(varpaar); return mapExprentMinTypes.get(pair);
} }
} }

@ -34,52 +34,45 @@ import java.util.Map.Entry;
public class VarVersionsProcessor { public class VarVersionsProcessor {
private HashMap<Integer, Integer> mapOriginalVarIndices = new HashMap<Integer, Integer>(); private Map<Integer, Integer> mapOriginalVarIndices = new HashMap<Integer, Integer>();
private VarTypeProcessor typeProcessor;
private VarTypeProcessor typeproc;
public void setVarVersions(RootStatement root) { public void setVarVersions(RootStatement root) {
StructMethod mt = (StructMethod)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD); StructMethod mt = (StructMethod)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD);
SSAConstructorSparseEx ssa = new SSAConstructorSparseEx(); SSAConstructorSparseEx ssa = new SSAConstructorSparseEx();
ssa.splitVariables(root, mt); ssa.splitVariables(root, mt);
FlattenStatementsHelper flatthelper = new FlattenStatementsHelper(); FlattenStatementsHelper flattenHelper = new FlattenStatementsHelper();
DirectGraph dgraph = flatthelper.buildDirectGraph(root); DirectGraph graph = flattenHelper.buildDirectGraph(root);
// System.out.println("~~~~~~~~~~~~~~~~~~~~~~ \r\n"+root.toJava());
mergePhiVersions(ssa, dgraph); mergePhiVersions(ssa, graph);
// System.out.println("~~~~~~~~~~~~~~~~~~~~~~ \r\n"+root.toJava()); typeProcessor = new VarTypeProcessor();
typeProcessor.calculateVarTypes(root, graph);
typeproc = new VarTypeProcessor(); simpleMerge(typeProcessor, graph, mt);
typeproc.calculateVarTypes(root, dgraph);
simpleMerge(typeproc, dgraph, mt);
// FIXME: advanced merging // FIXME: advanced merging
eliminateNonJavaTypes(typeproc); eliminateNonJavaTypes(typeProcessor);
setNewVarIndices(typeproc, dgraph); setNewVarIndices(typeProcessor, graph);
} }
private static void mergePhiVersions(SSAConstructorSparseEx ssa, DirectGraph dgraph) { private static void mergePhiVersions(SSAConstructorSparseEx ssa, DirectGraph graph) {
// collect phi versions // collect phi versions
List<HashSet<VarVersionPaar>> lst = new ArrayList<HashSet<VarVersionPaar>>(); List<Set<VarVersionPaar>> lst = new ArrayList<Set<VarVersionPaar>>();
for (Entry<VarVersionPaar, FastSparseSet<Integer>> ent : ssa.getPhi().entrySet()) { for (Entry<VarVersionPaar, FastSparseSet<Integer>> ent : ssa.getPhi().entrySet()) {
HashSet<VarVersionPaar> set = new HashSet<VarVersionPaar>(); Set<VarVersionPaar> set = new HashSet<VarVersionPaar>();
set.add(ent.getKey()); set.add(ent.getKey());
for (Integer vers : ent.getValue()) { for (Integer version : ent.getValue()) {
set.add(new VarVersionPaar(ent.getKey().var, vers.intValue())); set.add(new VarVersionPaar(ent.getKey().var, version.intValue()));
} }
for (int i = lst.size() - 1; i >= 0; i--) { for (int i = lst.size() - 1; i >= 0; i--) {
HashSet<VarVersionPaar> tset = lst.get(i); Set<VarVersionPaar> tset = lst.get(i);
HashSet<VarVersionPaar> intersection = new HashSet<VarVersionPaar>(set); Set<VarVersionPaar> intersection = new HashSet<VarVersionPaar>(set);
intersection.retainAll(tset); intersection.retainAll(tset);
if (!intersection.isEmpty()) { if (!intersection.isEmpty()) {
@ -91,8 +84,8 @@ public class VarVersionsProcessor {
lst.add(set); lst.add(set);
} }
final HashMap<VarVersionPaar, Integer> phivers = new HashMap<VarVersionPaar, Integer>(); Map<VarVersionPaar, Integer> phiVersions = new HashMap<VarVersionPaar, Integer>();
for (HashSet<VarVersionPaar> set : lst) { for (Set<VarVersionPaar> set : lst) {
int min = Integer.MAX_VALUE; int min = Integer.MAX_VALUE;
for (VarVersionPaar paar : set) { for (VarVersionPaar paar : set) {
if (paar.version < min) { if (paar.version < min) {
@ -101,12 +94,16 @@ public class VarVersionsProcessor {
} }
for (VarVersionPaar paar : set) { for (VarVersionPaar paar : set) {
phivers.put(new VarVersionPaar(paar.var, paar.version), min); phiVersions.put(new VarVersionPaar(paar.var, paar.version), min);
} }
} }
updateVersions(graph, phiVersions);
}
dgraph.iterateExprents(new DirectGraph.ExprentIterator() { private static void updateVersions(DirectGraph graph, final Map<VarVersionPaar, Integer> versions) {
graph.iterateExprents(new DirectGraph.ExprentIterator() {
@Override
public int processExprent(Exprent exprent) { public int processExprent(Exprent exprent) {
List<Exprent> lst = exprent.getAllExprents(true); List<Exprent> lst = exprent.getAllExprents(true);
lst.add(exprent); lst.add(exprent);
@ -114,36 +111,36 @@ public class VarVersionsProcessor {
for (Exprent expr : lst) { for (Exprent expr : lst) {
if (expr.type == Exprent.EXPRENT_VAR) { if (expr.type == Exprent.EXPRENT_VAR) {
VarExprent var = (VarExprent)expr; VarExprent var = (VarExprent)expr;
Integer vers = phivers.get(new VarVersionPaar(var)); Integer version = versions.get(new VarVersionPaar(var));
if (vers != null) { if (version != null) {
var.setVersion(vers); var.setVersion(version);
} }
} }
} }
return 0; return 0;
} }
}); });
} }
private static void eliminateNonJavaTypes(VarTypeProcessor typeproc) { private static void eliminateNonJavaTypes(VarTypeProcessor typeProcessor) {
Map<VarVersionPaar, VarType> mapExprentMaxTypes = typeProcessor.getMapExprentMaxTypes();
HashMap<VarVersionPaar, VarType> mapExprentMaxTypes = typeproc.getMapExprentMaxTypes(); Map<VarVersionPaar, VarType> mapExprentMinTypes = typeProcessor.getMapExprentMinTypes();
HashMap<VarVersionPaar, VarType> mapExprentMinTypes = typeproc.getMapExprentMinTypes();
HashSet<VarVersionPaar> set = new HashSet<VarVersionPaar>(mapExprentMinTypes.keySet()); Set<VarVersionPaar> set = new HashSet<VarVersionPaar>(mapExprentMinTypes.keySet());
for (VarVersionPaar paar : set) { for (VarVersionPaar paar : set) {
VarType type = mapExprentMinTypes.get(paar); VarType type = mapExprentMinTypes.get(paar);
VarType maxtype = mapExprentMaxTypes.get(paar); VarType maxType = mapExprentMaxTypes.get(paar);
if (type.type == CodeConstants.TYPE_BYTECHAR || type.type == CodeConstants.TYPE_SHORTCHAR) { if (type.type == CodeConstants.TYPE_BYTECHAR || type.type == CodeConstants.TYPE_SHORTCHAR) {
if (maxtype != null && maxtype.type == CodeConstants.TYPE_CHAR) { if (maxType != null && maxType.type == CodeConstants.TYPE_CHAR) {
type = VarType.VARTYPE_CHAR; type = VarType.VARTYPE_CHAR;
} }
else { else {
type = type.type == CodeConstants.TYPE_BYTECHAR ? VarType.VARTYPE_BYTE : VarType.VARTYPE_SHORT; type = type.type == CodeConstants.TYPE_BYTECHAR ? VarType.VARTYPE_BYTE : VarType.VARTYPE_SHORT;
} }
mapExprentMinTypes.put(paar, type); mapExprentMinTypes.put(paar, type);
//} else if(type.type == CodeConstants.TYPE_CHAR && (maxtype == null || maxtype.type == CodeConstants.TYPE_INT)) { // when possible, lift char to int //} else if(type.type == CodeConstants.TYPE_CHAR && (maxType == null || maxType.type == CodeConstants.TYPE_INT)) { // when possible, lift char to int
// mapExprentMinTypes.put(paar, VarType.VARTYPE_INT); // mapExprentMinTypes.put(paar, VarType.VARTYPE_INT);
} }
else if (type.type == CodeConstants.TYPE_NULL) { else if (type.type == CodeConstants.TYPE_NULL) {
@ -152,67 +149,69 @@ public class VarVersionsProcessor {
} }
} }
private static void simpleMerge(VarTypeProcessor typeproc, DirectGraph dgraph, StructMethod mt) { private static void simpleMerge(VarTypeProcessor typeProcessor, DirectGraph graph, StructMethod mt) {
Map<VarVersionPaar, VarType> mapExprentMaxTypes = typeProcessor.getMapExprentMaxTypes();
HashMap<VarVersionPaar, VarType> mapExprentMaxTypes = typeproc.getMapExprentMaxTypes(); Map<VarVersionPaar, VarType> mapExprentMinTypes = typeProcessor.getMapExprentMinTypes();
HashMap<VarVersionPaar, VarType> mapExprentMinTypes = typeproc.getMapExprentMinTypes();
HashMap<Integer, HashSet<Integer>> mapVarVersions = new HashMap<Integer, HashSet<Integer>>(); Map<Integer, Set<Integer>> mapVarVersions = new HashMap<Integer, Set<Integer>>();
for (VarVersionPaar varpaar : mapExprentMinTypes.keySet()) { for (VarVersionPaar pair : mapExprentMinTypes.keySet()) {
if (varpaar.version >= 0) { // don't merge constants if (pair.version >= 0) { // don't merge constants
HashSet<Integer> set = mapVarVersions.get(varpaar.var); Set<Integer> set = mapVarVersions.get(pair.var);
if (set == null) { if (set == null) {
set = new HashSet<Integer>(); set = new HashSet<Integer>();
mapVarVersions.put(varpaar.var, set); mapVarVersions.put(pair.var, set);
} }
set.add(varpaar.version); set.add(pair.version);
} }
} }
boolean is_method_static = mt.hasModifier(CodeConstants.ACC_STATIC); boolean is_method_static = mt.hasModifier(CodeConstants.ACC_STATIC);
final HashMap<VarVersionPaar, Integer> mapMergedVersions = new HashMap<VarVersionPaar, Integer>(); Map<VarVersionPaar, Integer> mapMergedVersions = new HashMap<VarVersionPaar, Integer>();
for (Entry<Integer, HashSet<Integer>> ent : mapVarVersions.entrySet()) { for (Entry<Integer, Set<Integer>> ent : mapVarVersions.entrySet()) {
if (ent.getValue().size() > 1) { if (ent.getValue().size() > 1) {
List<Integer> lstVersions = new ArrayList<Integer>(ent.getValue()); List<Integer> lstVersions = new ArrayList<Integer>(ent.getValue());
Collections.sort(lstVersions); Collections.sort(lstVersions);
for (int i = 0; i < lstVersions.size(); i++) { for (int i = 0; i < lstVersions.size(); i++) {
VarVersionPaar firstpaar = new VarVersionPaar(ent.getKey(), lstVersions.get(i)); VarVersionPaar firstPair = new VarVersionPaar(ent.getKey(), lstVersions.get(i));
VarType firsttype = mapExprentMinTypes.get(firstpaar); VarType firstType = mapExprentMinTypes.get(firstPair);
if (firstpaar.var == 0 && firstpaar.version == 1 && !is_method_static) { if (firstPair.var == 0 && firstPair.version == 1 && !is_method_static) {
continue; // don't merge 'this' variable continue; // don't merge 'this' variable
} }
for (int j = i + 1; j < lstVersions.size(); j++) { for (int j = i + 1; j < lstVersions.size(); j++) {
VarVersionPaar secpaar = new VarVersionPaar(ent.getKey(), lstVersions.get(j)); VarVersionPaar secondPair = new VarVersionPaar(ent.getKey(), lstVersions.get(j));
VarType sectype = mapExprentMinTypes.get(secpaar); VarType secondType = mapExprentMinTypes.get(secondPair);
if (firsttype.equals(sectype) || (firsttype.equals(VarType.VARTYPE_NULL) && sectype.type == CodeConstants.TYPE_OBJECT) if (firstType.equals(secondType) ||
|| (sectype.equals(VarType.VARTYPE_NULL) && firsttype.type == CodeConstants.TYPE_OBJECT)) { (firstType.equals(VarType.VARTYPE_NULL) && secondType.type == CodeConstants.TYPE_OBJECT) ||
(secondType.equals(VarType.VARTYPE_NULL) && firstType.type == CodeConstants.TYPE_OBJECT)) {
VarType firstMaxType = mapExprentMaxTypes.get(firstpaar);
VarType secMaxType = mapExprentMaxTypes.get(secpaar); VarType firstMaxType = mapExprentMaxTypes.get(firstPair);
mapExprentMaxTypes.put(firstpaar, firstMaxType == null ? secMaxType : VarType secondMaxType = mapExprentMaxTypes.get(secondPair);
(secMaxType == null ? firstMaxType : VarType.getCommonMinType(firstMaxType, secMaxType))); VarType type = firstMaxType == null ? secondMaxType :
secondMaxType == null ? firstMaxType :
VarType.getCommonMinType(firstMaxType, secondMaxType);
mapMergedVersions.put(secpaar, firstpaar.version);
mapExprentMaxTypes.remove(secpaar); mapExprentMaxTypes.put(firstPair, type);
mapExprentMinTypes.remove(secpaar); mapMergedVersions.put(secondPair, firstPair.version);
mapExprentMaxTypes.remove(secondPair);
if (firsttype.equals(VarType.VARTYPE_NULL)) { mapExprentMinTypes.remove(secondPair);
mapExprentMinTypes.put(firstpaar, sectype);
firsttype = sectype; if (firstType.equals(VarType.VARTYPE_NULL)) {
mapExprentMinTypes.put(firstPair, secondType);
firstType = secondType;
} }
typeproc.getMapFinalVars().put(firstpaar, VarTypeProcessor.VAR_NONFINAL); typeProcessor.getMapFinalVars().put(firstPair, VarTypeProcessor.VAR_NON_FINAL);
lstVersions.remove(j); lstVersions.remove(j);
//noinspection AssignmentToForLoopParameter
j--; j--;
} }
} }
@ -221,79 +220,61 @@ public class VarVersionsProcessor {
} }
if (!mapMergedVersions.isEmpty()) { if (!mapMergedVersions.isEmpty()) {
dgraph.iterateExprents(new DirectGraph.ExprentIterator() { updateVersions(graph, mapMergedVersions);
public int processExprent(Exprent exprent) {
List<Exprent> lst = exprent.getAllExprents(true);
lst.add(exprent);
for (Exprent expr : lst) {
if (expr.type == Exprent.EXPRENT_VAR) {
VarExprent varex = (VarExprent)expr;
Integer newversion = mapMergedVersions.get(new VarVersionPaar(varex));
if (newversion != null) {
varex.setVersion(newversion);
}
}
}
return 0;
}
});
} }
} }
private void setNewVarIndices(VarTypeProcessor typeproc, DirectGraph dgraph) { private void setNewVarIndices(VarTypeProcessor typeProcessor, DirectGraph graph) {
final Map<VarVersionPaar, VarType> mapExprentMaxTypes = typeProcessor.getMapExprentMaxTypes();
Map<VarVersionPaar, VarType> mapExprentMinTypes = typeProcessor.getMapExprentMinTypes();
Map<VarVersionPaar, Integer> mapFinalVars = typeProcessor.getMapFinalVars();
final HashMap<VarVersionPaar, VarType> mapExprentMaxTypes = typeproc.getMapExprentMaxTypes(); CounterContainer counters = DecompilerContext.getCounterContainer();
HashMap<VarVersionPaar, VarType> mapExprentMinTypes = typeproc.getMapExprentMinTypes();
HashMap<VarVersionPaar, Integer> mapFinalVars = typeproc.getMapFinalVars();
CounterContainer ccon = DecompilerContext.getCounterContainer(); final Map<VarVersionPaar, Integer> mapVarPaar = new HashMap<VarVersionPaar, Integer>();
Map<Integer, Integer> mapOriginalVarIndices = new HashMap<Integer, Integer>();
final HashMap<VarVersionPaar, Integer> mapVarPaar = new HashMap<VarVersionPaar, Integer>(); // map var-version pairs on new var indexes
HashMap<Integer, Integer> mapOriginalVarIndices = new HashMap<Integer, Integer>(); Set<VarVersionPaar> set = new HashSet<VarVersionPaar>(mapExprentMinTypes.keySet());
for (VarVersionPaar pair : set) {
// map var-version paars on new var indexes if (pair.version >= 0) {
HashSet<VarVersionPaar> set = new HashSet<VarVersionPaar>(mapExprentMinTypes.keySet()); int newIndex = pair.version == 1 ? pair.var : counters.getCounterAndIncrement(CounterContainer.VAR_COUNTER);
for (VarVersionPaar vpaar : set) {
if (vpaar.version >= 0) { VarVersionPaar newVar = new VarVersionPaar(newIndex, 0);
int newindex = vpaar.version == 1 ? vpaar.var :
ccon.getCounterAndIncrement(CounterContainer.VAR_COUNTER);
VarVersionPaar newvar = new VarVersionPaar(newindex, 0); mapExprentMinTypes.put(newVar, mapExprentMinTypes.get(pair));
mapExprentMaxTypes.put(newVar, mapExprentMaxTypes.get(pair));
mapExprentMinTypes.put(newvar, mapExprentMinTypes.get(vpaar)); if (mapFinalVars.containsKey(pair)) {
mapExprentMaxTypes.put(newvar, mapExprentMaxTypes.get(vpaar)); mapFinalVars.put(newVar, mapFinalVars.remove(pair));
if (mapFinalVars.containsKey(vpaar)) {
mapFinalVars.put(newvar, mapFinalVars.remove(vpaar));
} }
mapVarPaar.put(vpaar, newindex); mapVarPaar.put(pair, newIndex);
mapOriginalVarIndices.put(newindex, vpaar.var); mapOriginalVarIndices.put(newIndex, pair.var);
} }
} }
// set new vars // set new vars
dgraph.iterateExprents(new DirectGraph.ExprentIterator() { graph.iterateExprents(new DirectGraph.ExprentIterator() {
@Override
public int processExprent(Exprent exprent) { public int processExprent(Exprent exprent) {
List<Exprent> lst = exprent.getAllExprents(true); List<Exprent> lst = exprent.getAllExprents(true);
lst.add(exprent); lst.add(exprent);
for (Exprent expr : lst) { for (Exprent expr : lst) {
if (expr.type == Exprent.EXPRENT_VAR) { if (expr.type == Exprent.EXPRENT_VAR) {
VarExprent varex = (VarExprent)expr; VarExprent newVar = (VarExprent)expr;
Integer newvarindex = mapVarPaar.get(new VarVersionPaar(varex)); Integer newVarIndex = mapVarPaar.get(new VarVersionPaar(newVar));
if (newvarindex != null) { if (newVarIndex != null) {
varex.setIndex(newvarindex); newVar.setIndex(newVarIndex);
varex.setVersion(0); newVar.setVersion(0);
} }
} }
else if (expr.type == Exprent.EXPRENT_CONST) { else if (expr.type == Exprent.EXPRENT_CONST) {
VarType maxType = mapExprentMaxTypes.get(new VarVersionPaar(expr.id, -1)); VarType maxType = mapExprentMaxTypes.get(new VarVersionPaar(expr.id, -1));
if (maxType != null && maxType.equals(VarType.VARTYPE_CHAR)) { if (maxType != null && maxType.equals(VarType.VARTYPE_CHAR)) {
((ConstExprent)expr).setConsttype(maxType); ((ConstExprent)expr).setConstType(maxType);
} }
} }
} }
@ -305,30 +286,29 @@ public class VarVersionsProcessor {
this.mapOriginalVarIndices = mapOriginalVarIndices; this.mapOriginalVarIndices = mapOriginalVarIndices;
} }
public VarType getVarType(VarVersionPaar varpaar) { public VarType getVarType(VarVersionPaar pair) {
return typeproc == null ? null : typeproc.getVarType(varpaar); return typeProcessor == null ? null : typeProcessor.getVarType(pair);
} }
public void setVarType(VarVersionPaar varpaar, VarType type) { public void setVarType(VarVersionPaar pair, VarType type) {
typeproc.setVarType(varpaar, type); typeProcessor.setVarType(pair, type);
} }
public int getVarFinal(VarVersionPaar varpaar) { public int getVarFinal(VarVersionPaar pair) {
int ret = VarTypeProcessor.VAR_FINAL; int ret = VarTypeProcessor.VAR_FINAL;
if (typeproc != null) { if (typeProcessor != null) {
Integer fin = typeproc.getMapFinalVars().get(varpaar); Integer fin = typeProcessor.getMapFinalVars().get(pair);
ret = fin == null ? VarTypeProcessor.VAR_FINAL : fin.intValue(); ret = fin == null ? VarTypeProcessor.VAR_FINAL : fin.intValue();
} }
return ret; return ret;
} }
public void setVarFinal(VarVersionPaar varpaar, int finaltype) { public void setVarFinal(VarVersionPaar pair, int finalType) {
typeproc.getMapFinalVars().put(varpaar, finaltype); typeProcessor.getMapFinalVars().put(pair, finalType);
} }
public HashMap<Integer, Integer> getMapOriginalVarIndices() { public Map<Integer, Integer> getMapOriginalVarIndices() {
return mapOriginalVarIndices; return mapOriginalVarIndices;
} }
} }

@ -25,28 +25,22 @@ import org.jetbrains.java.decompiler.struct.StructField;
import org.jetbrains.java.decompiler.struct.StructMethod; import org.jetbrains.java.decompiler.struct.StructMethod;
import org.jetbrains.java.decompiler.struct.gen.FieldDescriptor; import org.jetbrains.java.decompiler.struct.gen.FieldDescriptor;
import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor; import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor;
import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.NewClassNameBuilder;
import org.jetbrains.java.decompiler.util.VBStyleCollection; import org.jetbrains.java.decompiler.util.VBStyleCollection;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
public class IdentifierConverter { public class IdentifierConverter implements NewClassNameBuilder {
private StructContext context; private StructContext context;
private IIdentifierRenamer helper; private IIdentifierRenamer helper;
private PoolInterceptor interceptor; private PoolInterceptor interceptor;
private List<ClassWrapperNode> rootClasses = new ArrayList<ClassWrapperNode>(); private List<ClassWrapperNode> rootClasses = new ArrayList<ClassWrapperNode>();
private List<ClassWrapperNode> rootInterfaces = new ArrayList<ClassWrapperNode>(); private List<ClassWrapperNode> rootInterfaces = new ArrayList<ClassWrapperNode>();
private Map<String, Map<String, String>> interfaceNameMaps = new HashMap<String, Map<String, String>>();
private HashMap<String, HashMap<String, String>> interfaceNameMaps = new HashMap<String, HashMap<String, String>>();
public void rename(StructContext context) { public void rename(StructContext context) {
try { try {
this.context = context; this.context = context;
@ -55,9 +49,7 @@ public class IdentifierConverter {
try { try {
helper = (IIdentifierRenamer)IdentifierConverter.class.getClassLoader().loadClass(user_class).newInstance(); helper = (IIdentifierRenamer)IdentifierConverter.class.getClassLoader().loadClass(user_class).newInstance();
} }
catch (Exception ex) { catch (Exception ignored) { }
// ignore errors
}
} }
if (helper == null) { if (helper == null) {
@ -83,32 +75,29 @@ public class IdentifierConverter {
} }
private void renameClasses() { private void renameClasses() {
List<ClassWrapperNode> lstClasses = getReversePostOrderListIterative(rootClasses); List<ClassWrapperNode> lstClasses = getReversePostOrderListIterative(rootClasses);
Map<String, Map<String, String>> classNameMaps = new HashMap<String, Map<String, String>>();
HashMap<String, HashMap<String, String>> classNameMaps = new HashMap<String, HashMap<String, String>>();
for (ClassWrapperNode node : lstClasses) { for (ClassWrapperNode node : lstClasses) {
StructClass cl = node.getClassStruct(); StructClass cl = node.getClassStruct();
HashMap<String, String> names = new HashMap<String, String>(); Map<String, String> names = new HashMap<String, String>();
// merge informations on super class // merge information on super class
if (cl.superClass != null) { if (cl.superClass != null) {
HashMap<String, String> mapClass = classNameMaps.get(cl.superClass.getString()); Map<String, String> mapClass = classNameMaps.get(cl.superClass.getString());
if (mapClass != null) { if (mapClass != null) {
names.putAll(mapClass); names.putAll(mapClass);
} }
} }
// merge informations on interfaces // merge information on interfaces
for (String intrName : cl.getInterfaceNames()) { for (String ifName : cl.getInterfaceNames()) {
HashMap<String, String> mapInt = interfaceNameMaps.get(intrName); Map<String, String> mapInt = interfaceNameMaps.get(ifName);
if (mapInt != null) { if (mapInt != null) {
names.putAll(mapInt); names.putAll(mapInt);
} }
else { else {
StructClass clintr = context.getClass(intrName); StructClass clintr = context.getClass(ifName);
if (clintr != null) { if (clintr != null) {
names.putAll(processExternalInterface(clintr)); names.putAll(processExternalInterface(clintr));
} }
@ -123,18 +112,16 @@ public class IdentifierConverter {
} }
} }
private HashMap<String, String> processExternalInterface(StructClass cl) { private Map<String, String> processExternalInterface(StructClass cl) {
Map<String, String> names = new HashMap<String, String>();
HashMap<String, String> names = new HashMap<String, String>();
for (String intrName : cl.getInterfaceNames()) {
HashMap<String, String> mapInt = interfaceNameMaps.get(intrName); for (String ifName : cl.getInterfaceNames()) {
Map<String, String> mapInt = interfaceNameMaps.get(ifName);
if (mapInt != null) { if (mapInt != null) {
names.putAll(mapInt); names.putAll(mapInt);
} }
else { else {
StructClass clintr = context.getClass(intrName); StructClass clintr = context.getClass(ifName);
if (clintr != null) { if (clintr != null) {
names.putAll(processExternalInterface(clintr)); names.putAll(processExternalInterface(clintr));
} }
@ -147,20 +134,18 @@ public class IdentifierConverter {
} }
private void renameInterfaces() { private void renameInterfaces() {
List<ClassWrapperNode> lstInterfaces = getReversePostOrderListIterative(rootInterfaces); List<ClassWrapperNode> lstInterfaces = getReversePostOrderListIterative(rootInterfaces);
Map<String, Map<String, String>> interfaceNameMaps = new HashMap<String, Map<String, String>>();
HashMap<String, HashMap<String, String>> interfaceNameMaps = new HashMap<String, HashMap<String, String>>();
// rename methods and fields // rename methods and fields
for (ClassWrapperNode node : lstInterfaces) { for (ClassWrapperNode node : lstInterfaces) {
StructClass cl = node.getClassStruct(); StructClass cl = node.getClassStruct();
HashMap<String, String> names = new HashMap<String, String>(); Map<String, String> names = new HashMap<String, String>();
// merge informations on super interfaces // merge information on super interfaces
for (String intrName : cl.getInterfaceNames()) { for (String ifName : cl.getInterfaceNames()) {
HashMap<String, String> mapInt = interfaceNameMaps.get(intrName); Map<String, String> mapInt = interfaceNameMaps.get(ifName);
if (mapInt != null) { if (mapInt != null) {
names.putAll(mapInt); names.putAll(mapInt);
} }
@ -175,7 +160,6 @@ public class IdentifierConverter {
} }
private void renameAllClasses() { private void renameAllClasses() {
// order not important // order not important
List<ClassWrapperNode> lstAllClasses = new ArrayList<ClassWrapperNode>(getReversePostOrderListIterative(rootInterfaces)); List<ClassWrapperNode> lstAllClasses = new ArrayList<ClassWrapperNode>(getReversePostOrderListIterative(rootInterfaces));
lstAllClasses.addAll(getReversePostOrderListIterative(rootClasses)); lstAllClasses.addAll(getReversePostOrderListIterative(rootClasses));
@ -195,14 +179,13 @@ public class IdentifierConverter {
String classOldFullName = cl.qualifiedName; String classOldFullName = cl.qualifiedName;
// TODO: rename packages // TODO: rename packages
String clsimplename = ConverterHelper.getSimpleClassName(classOldFullName); String clSimpleName = ConverterHelper.getSimpleClassName(classOldFullName);
if (helper.toBeRenamed(IIdentifierRenamer.ELEMENT_CLASS, clsimplename, null, null)) { if (helper.toBeRenamed(IIdentifierRenamer.ELEMENT_CLASS, clSimpleName, null, null)) {
String classNewFullName; String classNewFullName;
do { do {
classNewFullName = ConverterHelper.replaceSimpleClassName(classOldFullName, String classname = helper.getNextClassname(classOldFullName, ConverterHelper.getSimpleClassName(classOldFullName));
helper.getNextClassname(classOldFullName, ConverterHelper classNewFullName = ConverterHelper.replaceSimpleClassName(classOldFullName, classname);
.getSimpleClassName(classOldFullName)));
} }
while (context.getClasses().containsKey(classNewFullName)); while (context.getClasses().containsKey(classNewFullName));
@ -210,8 +193,7 @@ public class IdentifierConverter {
} }
} }
private void renameClassIdentifiers(StructClass cl, HashMap<String, String> names) { private void renameClassIdentifiers(StructClass cl, Map<String, String> names) {
// all classes are already renamed // all classes are already renamed
String classOldFullName = cl.qualifiedName; String classOldFullName = cl.qualifiedName;
String classNewFullName = interceptor.getName(classOldFullName); String classNewFullName = interceptor.getName(classOldFullName);
@ -288,65 +270,29 @@ public class IdentifierConverter {
} }
} }
private String buildNewDescriptor(boolean isField, String descriptor) { @Override
public String buildNewClassname(String className) {
boolean updated = false; return interceptor.getName(className);
}
private String buildNewDescriptor(boolean isField, String descriptor) {
String newDescriptor;
if (isField) { if (isField) {
FieldDescriptor fd = FieldDescriptor.parseDescriptor(descriptor); newDescriptor = FieldDescriptor.parseDescriptor(descriptor).buildNewDescriptor(this);
VarType ftype = fd.type;
if (ftype.type == CodeConstants.TYPE_OBJECT) {
String newclname = interceptor.getName(ftype.value);
if (newclname != null) {
ftype.value = newclname;
updated = true;
}
}
if (updated) {
return fd.getDescriptor();
}
} }
else { else {
newDescriptor = MethodDescriptor.parseDescriptor(descriptor).buildNewDescriptor(this);
MethodDescriptor md = MethodDescriptor.parseDescriptor(descriptor);
// params
for (VarType partype : md.params) {
if (partype.type == CodeConstants.TYPE_OBJECT) {
String newclname = interceptor.getName(partype.value);
if (newclname != null) {
partype.value = newclname;
updated = true;
}
}
}
// return value
if (md.ret.type == CodeConstants.TYPE_OBJECT) {
String newclname = interceptor.getName(md.ret.value);
if (newclname != null) {
md.ret.value = newclname;
updated = true;
}
}
if (updated) {
return md.getDescriptor();
}
} }
return newDescriptor != null ? newDescriptor : descriptor;
return descriptor;
} }
private static List<ClassWrapperNode> getReversePostOrderListIterative(List<ClassWrapperNode> roots) { private static List<ClassWrapperNode> getReversePostOrderListIterative(List<ClassWrapperNode> roots) {
List<ClassWrapperNode> res = new ArrayList<ClassWrapperNode>(); List<ClassWrapperNode> res = new ArrayList<ClassWrapperNode>();
LinkedList<ClassWrapperNode> stackNode = new LinkedList<ClassWrapperNode>(); LinkedList<ClassWrapperNode> stackNode = new LinkedList<ClassWrapperNode>();
LinkedList<Integer> stackIndex = new LinkedList<Integer>(); LinkedList<Integer> stackIndex = new LinkedList<Integer>();
HashSet<ClassWrapperNode> setVisited = new HashSet<ClassWrapperNode>(); Set<ClassWrapperNode> setVisited = new HashSet<ClassWrapperNode>();
for (ClassWrapperNode root : roots) { for (ClassWrapperNode root : roots) {
stackNode.add(root); stackNode.add(root);
@ -354,7 +300,6 @@ public class IdentifierConverter {
} }
while (!stackNode.isEmpty()) { while (!stackNode.isEmpty()) {
ClassWrapperNode node = stackNode.getLast(); ClassWrapperNode node = stackNode.getLast();
int index = stackIndex.removeLast(); int index = stackIndex.removeLast();
@ -366,17 +311,14 @@ public class IdentifierConverter {
ClassWrapperNode sub = lstSubs.get(index); ClassWrapperNode sub = lstSubs.get(index);
if (!setVisited.contains(sub)) { if (!setVisited.contains(sub)) {
stackIndex.add(index + 1); stackIndex.add(index + 1);
stackNode.add(sub); stackNode.add(sub);
stackIndex.add(0); stackIndex.add(0);
break; break;
} }
} }
if (index == lstSubs.size()) { if (index == lstSubs.size()) {
res.add(0, node); res.add(0, node);
stackNode.removeLast(); stackNode.removeLast();
} }
} }
@ -384,9 +326,7 @@ public class IdentifierConverter {
return res; return res;
} }
private void buildInheritanceTree() { private void buildInheritanceTree() {
Map<String, ClassWrapperNode> nodes = new HashMap<String, ClassWrapperNode>(); Map<String, ClassWrapperNode> nodes = new HashMap<String, ClassWrapperNode>();
Map<String, StructClass> classes = context.getClasses(); Map<String, StructClass> classes = context.getClasses();
@ -394,29 +334,28 @@ public class IdentifierConverter {
List<ClassWrapperNode> rootInterfaces = new ArrayList<ClassWrapperNode>(); List<ClassWrapperNode> rootInterfaces = new ArrayList<ClassWrapperNode>();
for (StructClass cl : classes.values()) { for (StructClass cl : classes.values()) {
if (!cl.isOwn()) { if (!cl.isOwn()) {
continue; continue;
} }
LinkedList<StructClass> stack = new LinkedList<StructClass>(); LinkedList<StructClass> stack = new LinkedList<StructClass>();
LinkedList<ClassWrapperNode> stackSubnodes = new LinkedList<ClassWrapperNode>(); LinkedList<ClassWrapperNode> stackSubNodes = new LinkedList<ClassWrapperNode>();
stack.add(cl); stack.add(cl);
stackSubnodes.add(null); stackSubNodes.add(null);
while (!stack.isEmpty()) { while (!stack.isEmpty()) {
StructClass clStr = stack.removeFirst();
ClassWrapperNode child = stackSubNodes.removeFirst();
StructClass clstr = stack.removeFirst(); ClassWrapperNode node = nodes.get(clStr.qualifiedName);
ClassWrapperNode child = stackSubnodes.removeFirst();
ClassWrapperNode node = nodes.get(clstr.qualifiedName);
boolean isNewNode = (node == null); boolean isNewNode = (node == null);
if (isNewNode) { if (isNewNode) {
nodes.put(clstr.qualifiedName, node = new ClassWrapperNode(clstr)); nodes.put(clStr.qualifiedName, node = new ClassWrapperNode(clStr));
} }
//noinspection ConstantConditions
if (child != null) { if (child != null) {
node.addSubclass(child); node.addSubclass(child);
} }
@ -425,28 +364,25 @@ public class IdentifierConverter {
break; break;
} }
else { else {
boolean isInterface = clstr.hasModifier(CodeConstants.ACC_INTERFACE); boolean isInterface = clStr.hasModifier(CodeConstants.ACC_INTERFACE);
boolean found_parent = false; boolean found_parent = false;
if (isInterface) { if (isInterface) {
for (String intrName : clstr.getInterfaceNames()) { for (String ifName : clStr.getInterfaceNames()) {
StructClass clparent = classes.get(intrName); StructClass clParent = classes.get(ifName);
if (clparent != null) { if (clParent != null) {
stack.add(clparent); stack.add(clParent);
stackSubnodes.add(node); stackSubNodes.add(node);
found_parent = true; found_parent = true;
} }
} }
} }
else { else if (clStr.superClass != null) { // null iff java/lang/Object
if (clstr.superClass != null) { // null iff java/lang/Object StructClass clParent = classes.get(clStr.superClass.getString());
StructClass clparent = classes.get(clstr.superClass.getString()); if (clParent != null) {
stack.add(clParent);
if (clparent != null) { stackSubNodes.add(node);
stack.add(clparent); found_parent = true;
stackSubnodes.add(node);
found_parent = true;
}
} }
} }

@ -20,6 +20,7 @@ import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.modules.renamer.PoolInterceptor; import org.jetbrains.java.decompiler.modules.renamer.PoolInterceptor;
import org.jetbrains.java.decompiler.struct.gen.FieldDescriptor; import org.jetbrains.java.decompiler.struct.gen.FieldDescriptor;
import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor; import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor;
import org.jetbrains.java.decompiler.struct.gen.NewClassNameBuilder;
import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.DataInputFullStream; import org.jetbrains.java.decompiler.util.DataInputFullStream;
@ -28,7 +29,7 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class ConstantPool { public class ConstantPool implements NewClassNameBuilder {
public static final int FIELD = 1; public static final int FIELD = 1;
public static final int METHOD = 2; public static final int METHOD = 2;
@ -154,8 +155,7 @@ public class ConstantPool {
elementName = newElement.split(" ")[1]; elementName = newElement.split(" ")[1];
} }
int type = elementType == FIELD ? CodeConstants.CONSTANT_Fieldref : CodeConstants.CONSTANT_Methodref; String newDescriptor = buildNewDescriptor(elementType == FIELD, descriptor);
String newDescriptor = buildNewDescriptor(type, descriptor);
if (newDescriptor != null) { if (newDescriptor != null) {
descriptor = newDescriptor; descriptor = newDescriptor;
} }
@ -192,7 +192,7 @@ public class ConstantPool {
ln.type == CodeConstants.CONSTANT_InterfaceMethodref)) { ln.type == CodeConstants.CONSTANT_InterfaceMethodref)) {
String newClassName = buildNewClassname(ln.classname); String newClassName = buildNewClassname(ln.classname);
String newElement = interceptor.getName(ln.classname + " " + ln.elementname + " " + ln.descriptor); String newElement = interceptor.getName(ln.classname + " " + ln.elementname + " " + ln.descriptor);
String newDescriptor = buildNewDescriptor(ln.type, ln.descriptor); String newDescriptor = buildNewDescriptor(ln.type == CodeConstants.CONSTANT_Fieldref, ln.descriptor);
if (newClassName != null || newElement != null || newDescriptor != null) { if (newClassName != null || newElement != null || newDescriptor != null) {
String className = newClassName == null ? ln.classname : newClassName; String className = newClassName == null ? ln.classname : newClassName;
@ -205,15 +205,16 @@ public class ConstantPool {
return ln; return ln;
} }
private String buildNewClassname(String className) { @Override
public String buildNewClassname(String className) {
VarType vt = new VarType(className, true); VarType vt = new VarType(className, true);
String newName = interceptor.getName(vt.value); String newName = interceptor.getName(vt.value);
if (newName != null) { if (newName != null) {
StringBuilder buffer = new StringBuilder(); StringBuilder buffer = new StringBuilder();
if (vt.arraydim > 0) { if (vt.arrayDim > 0) {
for (int i = 0; i < vt.arraydim; i++) { for (int i = 0; i < vt.arrayDim; i++) {
buffer.append("["); buffer.append("[");
} }
@ -229,53 +230,12 @@ public class ConstantPool {
return null; return null;
} }
private String buildNewDescriptor(int type, String descriptor) { private String buildNewDescriptor(boolean isField, String descriptor) {
boolean updated = false; if (isField) {
return FieldDescriptor.parseDescriptor(descriptor).buildNewDescriptor(this);
if (type == CodeConstants.CONSTANT_Fieldref) {
FieldDescriptor fd = FieldDescriptor.parseDescriptor(descriptor);
VarType fType = fd.type;
if (fType.type == CodeConstants.TYPE_OBJECT) {
String newClassName = buildNewClassname(fType.value);
if (newClassName != null) {
fType.value = newClassName;
updated = true;
}
}
if (updated) {
return fd.getDescriptor();
}
} }
else { else {
MethodDescriptor md = MethodDescriptor.parseDescriptor(descriptor); return MethodDescriptor.parseDescriptor(descriptor).buildNewDescriptor(this);
// parameters
for (VarType paramType : md.params) {
if (paramType.type == CodeConstants.TYPE_OBJECT) {
String newClassName = buildNewClassname(paramType.value);
if (newClassName != null) {
paramType.value = newClassName;
updated = true;
}
}
}
// return value
if (md.ret.type == CodeConstants.TYPE_OBJECT) {
String newClassName = buildNewClassname(md.ret.value);
if (newClassName != null) {
md.ret.value = newClassName;
updated = true;
}
}
if (updated) {
return md.getDescriptor();
}
} }
return null;
} }
} }

@ -73,7 +73,7 @@ public class DataPoint {
VarType var = md.params[i]; VarType var = md.params[i];
point.setVariable(k++, var); point.setVariable(k++, var);
if (var.stack_size == 2) { if (var.stackSize == 2) {
point.setVariable(k++, new VarType(CodeConstants.TYPE_GROUP2EMPTY)); point.setVariable(k++, new VarType(CodeConstants.TYPE_GROUP2EMPTY));
} }
} }

@ -15,6 +15,8 @@
*/ */
package org.jetbrains.java.decompiler.struct.gen; package org.jetbrains.java.decompiler.struct.gen;
import org.jetbrains.java.decompiler.code.CodeConstants;
public class FieldDescriptor { public class FieldDescriptor {
public static final FieldDescriptor INTEGER_DESCRIPTOR = parseDescriptor("Ljava/lang/Integer;"); public static final FieldDescriptor INTEGER_DESCRIPTOR = parseDescriptor("Ljava/lang/Integer;");
@ -22,25 +24,27 @@ public class FieldDescriptor {
public static final FieldDescriptor FLOAT_DESCRIPTOR = parseDescriptor("Ljava/lang/Float;"); public static final FieldDescriptor FLOAT_DESCRIPTOR = parseDescriptor("Ljava/lang/Float;");
public static final FieldDescriptor DOUBLE_DESCRIPTOR = parseDescriptor("Ljava/lang/Double;"); public static final FieldDescriptor DOUBLE_DESCRIPTOR = parseDescriptor("Ljava/lang/Double;");
public VarType type; public final VarType type;
public final String descriptorString;
public String descriptorString;
private FieldDescriptor() { private FieldDescriptor(String descriptor) {
type = new VarType(descriptor);
descriptorString = descriptor;
} }
public static FieldDescriptor parseDescriptor(String descr) { public static FieldDescriptor parseDescriptor(String descriptor) {
return new FieldDescriptor(descriptor);
FieldDescriptor fd = new FieldDescriptor();
fd.type = new VarType(descr);
fd.descriptorString = descr;
return fd;
} }
public String getDescriptor() { public String buildNewDescriptor(NewClassNameBuilder builder) {
return type.toString(); if (type.type == CodeConstants.TYPE_OBJECT) {
String newClassName = builder.buildNewClassname(type.value);
if (newClassName != null) {
return new VarType(type.type, type.arrayDim, newClassName).toString();
}
}
return null;
} }
@Override @Override

@ -15,73 +15,115 @@
*/ */
package org.jetbrains.java.decompiler.struct.gen; package org.jetbrains.java.decompiler.struct.gen;
import org.jetbrains.java.decompiler.code.CodeConstants;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
public class MethodDescriptor { public class MethodDescriptor {
public VarType[] params; public final VarType[] params;
public final VarType ret;
public VarType ret;
public static MethodDescriptor parseDescriptor(String mdescr) { private MethodDescriptor(VarType[] params, VarType ret) {
this.params = params;
this.ret = ret;
}
MethodDescriptor md = new MethodDescriptor(); public static MethodDescriptor parseDescriptor(String descriptor) {
int parenth = descriptor.lastIndexOf(')');
if (descriptor.length() < 2 || parenth < 0 || descriptor.charAt(0) != '(') {
throw new IllegalArgumentException("Invalid descriptor: " + descriptor);
}
List<String> lst = new ArrayList<String>(); VarType[] params;
String[] pars = mdescr.split("[()]");
if (parenth > 1) {
String parameters = descriptor.substring(1, parenth);
List<String> lst = new ArrayList<String>();
int indexFrom = -1, ind, len = parameters.length(), index = 0;
while (index < len) {
switch (parameters.charAt(index)) {
case '[':
if (indexFrom < 0) {
indexFrom = index;
}
break;
case 'L':
ind = parameters.indexOf(";", index);
lst.add(parameters.substring(indexFrom < 0 ? index : indexFrom, ind + 1));
index = ind;
indexFrom = -1;
break;
default:
lst.add(parameters.substring(indexFrom < 0 ? index : indexFrom, index + 1));
indexFrom = -1;
}
index++;
}
String par = pars[1]; params = new VarType[lst.size()];
for (int i = 0; i < lst.size(); i++) {
params[i] = new VarType(lst.get(i));
}
}
else {
params = VarType.EMPTY_ARRAY;
}
int indexFrom = -1, ind, index = 0; VarType ret = new VarType(descriptor.substring(parenth + 1));
int len = par.length();
for (; index < len; index++) { return new MethodDescriptor(params, ret);
}
switch (par.charAt(index)) { public String buildNewDescriptor(NewClassNameBuilder builder) {
case '[': boolean updated = false;
if (indexFrom < 0) {
indexFrom = index; VarType[] newParams;
} if (params.length > 0) {
break; newParams = new VarType[params.length];
case 'L': System.arraycopy(params, 0, newParams, 0, params.length);
ind = par.indexOf(";", index); for (int i = 0; i < params.length; i++) {
lst.add(par.substring(indexFrom < 0 ? index : indexFrom, ind + 1)); VarType substitute = buildNewType(params[i], builder);
index = ind; if (substitute != null) {
indexFrom = -1; newParams[i] = substitute;
break; updated = true;
default: }
lst.add(par.substring(indexFrom < 0 ? index : indexFrom, index + 1));
indexFrom = -1;
} }
} }
else {
newParams = VarType.EMPTY_ARRAY;
}
lst.add(pars[2]); VarType newRet = ret;
VarType substitute = buildNewType(ret, builder);
if (substitute != null) {
md.params = new VarType[lst.size() - 1]; newRet = substitute;
updated = true;
}
int i = 0; if (updated) {
for (; i < lst.size() - 1; i++) { StringBuilder res = new StringBuilder("(");
md.params[i] = new VarType(lst.get(i)); for (VarType param : newParams) {
res.append(param);
}
res.append(")").append(newRet.toString());
return res.toString();
} }
md.ret = new VarType(lst.get(i));
return md; return null;
} }
public String getDescriptor() { private static VarType buildNewType(VarType type, NewClassNameBuilder builder) {
String res = "("; if (type.type == CodeConstants.TYPE_OBJECT) {
String newClassName = builder.buildNewClassname(type.value);
for (int j = 0; j < params.length; j++) { if (newClassName != null) {
res += params[j].toString(); return new VarType(type.type, type.arrayDim, newClassName);
}
} }
return null;
res += ")" + ret.toString();
return res;
} }
@Override @Override

@ -0,0 +1,20 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.java.decompiler.struct.gen;
public interface NewClassNameBuilder {
String buildNewClassname(String className);
}

@ -20,7 +20,7 @@ import org.jetbrains.java.decompiler.util.InterpreterUtil;
public class VarType { // TODO: optimize switch public class VarType { // TODO: optimize switch
public static final int FALSEBOOLEAN = 1; public static final VarType[] EMPTY_ARRAY = {};
public static final VarType VARTYPE_UNKNOWN = new VarType(CodeConstants.TYPE_UNKNOWN); public static final VarType VARTYPE_UNKNOWN = new VarType(CodeConstants.TYPE_UNKNOWN);
public static final VarType VARTYPE_INT = new VarType(CodeConstants.TYPE_INT); public static final VarType VARTYPE_INT = new VarType(CodeConstants.TYPE_INT);
@ -35,145 +35,271 @@ public class VarType { // TODO: optimize switch
public static final VarType VARTYPE_SHORTCHAR = new VarType(CodeConstants.TYPE_SHORTCHAR); public static final VarType VARTYPE_SHORTCHAR = new VarType(CodeConstants.TYPE_SHORTCHAR);
public static final VarType VARTYPE_NULL = new VarType(CodeConstants.TYPE_NULL, 0, null); public static final VarType VARTYPE_NULL = new VarType(CodeConstants.TYPE_NULL, 0, null);
public static final VarType VARTYPE_GROUP2EMPTY = new VarType(CodeConstants.TYPE_GROUP2EMPTY);
public static final VarType VARTYPE_STRING = new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/String"); public static final VarType VARTYPE_STRING = new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/String");
public static final VarType VARTYPE_CLASS = new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Class"); public static final VarType VARTYPE_CLASS = new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Class");
public static final VarType VARTYPE_OBJECT = new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Object"); public static final VarType VARTYPE_OBJECT = new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Object");
public static final VarType VARTYPE_VOID = new VarType(CodeConstants.TYPE_VOID); public static final VarType VARTYPE_VOID = new VarType(CodeConstants.TYPE_VOID);
public int type; public final int type;
public final int arrayDim;
public int type_family; public final String value;
public final int typeFamily;
public int arraydim; public final int stackSize;
public final boolean falseBoolean;
public String value;
public int stack_size;
public int convinfo;
public VarType(int type) { public VarType(int type) {
this.type = type; this(type, 0);
this.arraydim = 0; }
value = getChar(type); public VarType(int type, int arrayDim) {
setStackSize(type); this(type, arrayDim, getChar(type));
setFamily();
} }
public VarType(int type, int arraydim) { public VarType(int type, int arrayDim, String value) {
this(type); this(type, arrayDim, value, getFamily(type, arrayDim), getStackSize(type, arrayDim), false);
this.arraydim = arraydim;
setFamily();
} }
public VarType(int type, int arraydim, String value) { private VarType(int type, int arrayDim, String value, int typeFamily, int stackSize, boolean falseBoolean) {
this(type); this.type = type;
this.arraydim = arraydim; this.arrayDim = arrayDim;
this.value = value; this.value = value;
setFamily(); this.typeFamily = typeFamily;
this.stackSize = stackSize;
this.falseBoolean = falseBoolean;
}
public VarType(String signature) {
this(signature, false);
} }
public VarType(String strtype) { public VarType(String signature, boolean clType) {
this(strtype, false); int type = 0;
int arrayDim = 0;
String value = null;
loop:
for (int i = 0; i < signature.length(); i++) {
switch (signature.charAt(i)) {
case '[':
arrayDim++;
break;
case 'L':
if (signature.charAt(signature.length() - 1) == ';') {
type = CodeConstants.TYPE_OBJECT;
value = signature.substring(i + 1, signature.length() - 1);
break loop;
}
default:
value = signature.substring(i, signature.length());
if ((clType && i == 0) || value.length() > 1) {
type = CodeConstants.TYPE_OBJECT;
}
else {
type = getType(value.charAt(0));
}
break loop;
}
}
this.type = type;
this.arrayDim = arrayDim;
this.value = value;
this.typeFamily = getFamily(type, arrayDim);
this.stackSize = getStackSize(type, arrayDim);
this.falseBoolean = false;
} }
public VarType(String strtype, boolean cltype) { private static String getChar(int type) {
parseTypeString(strtype, cltype); switch (type) {
setStackSize(type); case CodeConstants.TYPE_BYTE:
setFamily(); return "B";
case CodeConstants.TYPE_CHAR:
return "C";
case CodeConstants.TYPE_DOUBLE:
return "D";
case CodeConstants.TYPE_FLOAT:
return "F";
case CodeConstants.TYPE_INT:
return "I";
case CodeConstants.TYPE_LONG:
return "J";
case CodeConstants.TYPE_SHORT:
return "S";
case CodeConstants.TYPE_BOOLEAN:
return "Z";
case CodeConstants.TYPE_VOID:
return "V";
case CodeConstants.TYPE_GROUP2EMPTY:
return "G";
case CodeConstants.TYPE_NOTINITIALIZED:
return "N";
case CodeConstants.TYPE_ADDRESS:
return "A";
case CodeConstants.TYPE_BYTECHAR:
return "X";
case CodeConstants.TYPE_SHORTCHAR:
return "Y";
case CodeConstants.TYPE_UNKNOWN:
return "U";
case CodeConstants.TYPE_NULL:
case CodeConstants.TYPE_OBJECT:
return null;
default:
throw new RuntimeException("Invalid type");
}
} }
public void decArrayDim() { private static int getStackSize(int type, int arrayDim) {
if (arraydim > 0) { if (arrayDim > 0) {
arraydim--; return 1;
setFamily();
} }
else {
// throw new RuntimeException("array dimension equals 0!"); FIXME: investigate this case switch (type) {
case CodeConstants.TYPE_DOUBLE:
case CodeConstants.TYPE_LONG:
return 2;
case CodeConstants.TYPE_VOID:
case CodeConstants.TYPE_GROUP2EMPTY:
return 0;
default:
return 1;
} }
} }
public String toString() { private static int getFamily(int type, int arrayDim) {
String res = ""; if (arrayDim > 0) {
return CodeConstants.TYPE_FAMILY_OBJECT;
}
for (int i = 0; i < arraydim; i++) { switch (type) {
res += "["; case CodeConstants.TYPE_BYTE:
case CodeConstants.TYPE_BYTECHAR:
case CodeConstants.TYPE_SHORTCHAR:
case CodeConstants.TYPE_CHAR:
case CodeConstants.TYPE_SHORT:
case CodeConstants.TYPE_INT:
return CodeConstants.TYPE_FAMILY_INTEGER;
case CodeConstants.TYPE_DOUBLE:
return CodeConstants.TYPE_FAMILY_DOUBLE;
case CodeConstants.TYPE_FLOAT:
return CodeConstants.TYPE_FAMILY_FLOAT;
case CodeConstants.TYPE_LONG:
return CodeConstants.TYPE_FAMILY_LONG;
case CodeConstants.TYPE_BOOLEAN:
return CodeConstants.TYPE_FAMILY_BOOLEAN;
case CodeConstants.TYPE_NULL:
case CodeConstants.TYPE_OBJECT:
return CodeConstants.TYPE_FAMILY_OBJECT;
default:
return CodeConstants.TYPE_FAMILY_UNKNOWN;
} }
}
if (type == CodeConstants.TYPE_OBJECT) { public VarType decreaseArrayDim() {
res += "L" + value + ";"; if (arrayDim > 0) {
return new VarType(type, arrayDim - 1, value);
} }
else { else {
res += value; //throw new RuntimeException("array dimension equals 0!"); FIXME: investigate this case
return this;
} }
}
return res; public VarType resizeArrayDim(int newArrayDim) {
return new VarType(type, newArrayDim, value, typeFamily, stackSize, falseBoolean);
} }
public VarType copy() { public VarType copy() {
VarType v = new VarType(type, arraydim, value); return copy(false);
v.convinfo = convinfo; }
return v;
public VarType copy(boolean forceFalseBoolean) {
return new VarType(type, arrayDim, value, typeFamily, stackSize, falseBoolean || forceFalseBoolean);
} }
public boolean isFalseBoolean() { public boolean isFalseBoolean() {
return (convinfo & FALSEBOOLEAN) != 0; return falseBoolean;
} }
public boolean isSuperset(VarType val) { public boolean isSuperset(VarType val) {
return this.equals(val) || this.isStrictSuperset(val); return this.equals(val) || this.isStrictSuperset(val);
} }
public boolean isStrictSuperset(VarType val) { public boolean isStrictSuperset(VarType val) {
int valType = val.type;
int valtype = val.type; if (valType == CodeConstants.TYPE_UNKNOWN && type != CodeConstants.TYPE_UNKNOWN) {
if (valtype == CodeConstants.TYPE_UNKNOWN && type != CodeConstants.TYPE_UNKNOWN) {
return true; return true;
} }
if (val.arraydim > 0) { if (val.arrayDim > 0) {
return this.equals(VARTYPE_OBJECT); return this.equals(VARTYPE_OBJECT);
} }
else if (arraydim > 0) { else if (arrayDim > 0) {
return (valtype == CodeConstants.TYPE_NULL); return (valType == CodeConstants.TYPE_NULL);
} }
boolean res = false; boolean res = false;
switch (type) { switch (type) {
case CodeConstants.TYPE_INT: case CodeConstants.TYPE_INT:
res |= (valtype == CodeConstants.TYPE_SHORT || res = (valType == CodeConstants.TYPE_SHORT || valType == CodeConstants.TYPE_CHAR);
valtype == CodeConstants.TYPE_CHAR);
case CodeConstants.TYPE_SHORT: case CodeConstants.TYPE_SHORT:
res |= (valtype == CodeConstants.TYPE_BYTE); res |= (valType == CodeConstants.TYPE_BYTE);
case CodeConstants.TYPE_CHAR: case CodeConstants.TYPE_CHAR:
res |= (valtype == CodeConstants.TYPE_SHORTCHAR); res |= (valType == CodeConstants.TYPE_SHORTCHAR);
case CodeConstants.TYPE_BYTE: case CodeConstants.TYPE_BYTE:
case CodeConstants.TYPE_SHORTCHAR: case CodeConstants.TYPE_SHORTCHAR:
res |= (valtype == CodeConstants.TYPE_BYTECHAR); res |= (valType == CodeConstants.TYPE_BYTECHAR);
case CodeConstants.TYPE_BYTECHAR: case CodeConstants.TYPE_BYTECHAR:
res |= (valtype == CodeConstants.TYPE_BOOLEAN); res |= (valType == CodeConstants.TYPE_BOOLEAN);
break; break;
case CodeConstants.TYPE_OBJECT: case CodeConstants.TYPE_OBJECT:
if (valtype == CodeConstants.TYPE_NULL) { if (valType == CodeConstants.TYPE_NULL) {
return true; return true;
} }
else if (this.equals(VARTYPE_OBJECT)) { else if (this.equals(VARTYPE_OBJECT)) {
return valtype == CodeConstants.TYPE_OBJECT && return valType == CodeConstants.TYPE_OBJECT && !val.equals(VARTYPE_OBJECT);
!val.equals(VARTYPE_OBJECT);
} }
} }
return res; return res;
} }
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (o == null || !(o instanceof VarType)) {
return false;
}
VarType vt = (VarType)o;
return type == vt.type && arrayDim == vt.arrayDim && InterpreterUtil.equalObjects(value, vt.value);
}
@Override
public String toString() {
StringBuilder res = new StringBuilder();
for (int i = 0; i < arrayDim; i++) {
res.append('[');
}
if (type == CodeConstants.TYPE_OBJECT) {
res.append('L').append(value).append(';');
}
else {
res.append(value);
}
return res.toString();
}
// type1 and type2 must not be null // type1 and type2 must not be null
public static VarType getCommonMinType(VarType type1, VarType type2) { public static VarType getCommonMinType(VarType type1, VarType type2) {
if (type1.type == CodeConstants.TYPE_BOOLEAN && type2.type == CodeConstants.TYPE_BOOLEAN) { // special case booleans if (type1.type == CodeConstants.TYPE_BOOLEAN && type2.type == CodeConstants.TYPE_BOOLEAN) { // special case booleans
return type1.isFalseBoolean() ? type2 : type1; return type1.isFalseBoolean() ? type2 : type1;
} }
@ -184,8 +310,8 @@ public class VarType { // TODO: optimize switch
else if (type2.isSuperset(type1)) { else if (type2.isSuperset(type1)) {
return type1; return type1;
} }
else if (type1.type_family == type2.type_family) { else if (type1.typeFamily == type2.typeFamily) {
switch (type1.type_family) { switch (type1.typeFamily) {
case CodeConstants.TYPE_FAMILY_INTEGER: case CodeConstants.TYPE_FAMILY_INTEGER:
if ((type1.type == CodeConstants.TYPE_CHAR && type2.type == CodeConstants.TYPE_SHORT) if ((type1.type == CodeConstants.TYPE_CHAR && type2.type == CodeConstants.TYPE_SHORT)
|| (type1.type == CodeConstants.TYPE_SHORT && type2.type == CodeConstants.TYPE_CHAR)) { || (type1.type == CodeConstants.TYPE_SHORT && type2.type == CodeConstants.TYPE_CHAR)) {
@ -204,7 +330,6 @@ public class VarType { // TODO: optimize switch
// type1 and type2 must not be null // type1 and type2 must not be null
public static VarType getCommonSupertype(VarType type1, VarType type2) { public static VarType getCommonSupertype(VarType type1, VarType type2) {
if (type1.type == CodeConstants.TYPE_BOOLEAN && type2.type == CodeConstants.TYPE_BOOLEAN) { // special case booleans if (type1.type == CodeConstants.TYPE_BOOLEAN && type2.type == CodeConstants.TYPE_BOOLEAN) { // special case booleans
return type1.isFalseBoolean() ? type1 : type2; return type1.isFalseBoolean() ? type1 : type2;
} }
@ -215,8 +340,8 @@ public class VarType { // TODO: optimize switch
else if (type2.isSuperset(type1)) { else if (type2.isSuperset(type1)) {
return type2; return type2;
} }
else if (type1.type_family == type2.type_family) { else if (type1.typeFamily == type2.typeFamily) {
switch (type1.type_family) { switch (type1.typeFamily) {
case CodeConstants.TYPE_FAMILY_INTEGER: case CodeConstants.TYPE_FAMILY_INTEGER:
if ((type1.type == CodeConstants.TYPE_SHORTCHAR && type2.type == CodeConstants.TYPE_BYTE) if ((type1.type == CodeConstants.TYPE_SHORTCHAR && type2.type == CodeConstants.TYPE_BYTE)
|| (type1.type == CodeConstants.TYPE_BYTE && type2.type == CodeConstants.TYPE_SHORTCHAR)) { || (type1.type == CodeConstants.TYPE_BYTE && type2.type == CodeConstants.TYPE_SHORTCHAR)) {
@ -250,63 +375,11 @@ public class VarType { // TODO: optimize switch
case CodeConstants.TYPE_FAMILY_UNKNOWN: case CodeConstants.TYPE_FAMILY_UNKNOWN:
return VARTYPE_UNKNOWN; return VARTYPE_UNKNOWN;
default: default:
throw new RuntimeException("invalid type family!"); throw new IllegalArgumentException("Invalid type family: " + family);
}
}
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (o == null || !(o instanceof VarType)) {
return false;
}
VarType vt = (VarType)o;
return type == vt.type && arraydim == vt.arraydim && InterpreterUtil.equalObjects(value, vt.value);
}
private void parseTypeString(String strtype, boolean cltype) {
for (int i = 0; i < strtype.length(); i++) {
switch (strtype.charAt(i)) {
case '[':
arraydim++;
break;
case 'L':
if (strtype.charAt(strtype.length() - 1) == ';') {
type = CodeConstants.TYPE_OBJECT;
value = strtype.substring(i + 1, strtype.length() - 1);
return;
}
default:
value = strtype.substring(i, strtype.length());
if ((cltype && i == 0) || value.length() > 1) {
type = CodeConstants.TYPE_OBJECT;
}
else {
type = getType(value.charAt(0));
}
return;
}
}
}
private void setStackSize(int type) {
if (arraydim > 0) {
stack_size = 1;
}
else {
stack_size = (type == CodeConstants.TYPE_DOUBLE ||
type == CodeConstants.TYPE_LONG) ? 2 :
((type == CodeConstants.TYPE_VOID ||
type == CodeConstants.TYPE_GROUP2EMPTY) ? 0 : 1);
} }
} }
private static int getType(char c) { public static int getType(char c) {
switch (c) { switch (c) {
case 'B': case 'B':
return CodeConstants.TYPE_BYTE; return CodeConstants.TYPE_BYTE;
@ -339,84 +412,7 @@ public class VarType { // TODO: optimize switch
case 'U': case 'U':
return CodeConstants.TYPE_UNKNOWN; return CodeConstants.TYPE_UNKNOWN;
default: default:
throw new RuntimeException("Invalid type"); throw new IllegalArgumentException("Invalid type: " + c);
}
}
private static String getChar(int type) {
switch (type) {
case CodeConstants.TYPE_BYTE:
return "B";
case CodeConstants.TYPE_CHAR:
return "C";
case CodeConstants.TYPE_DOUBLE:
return "D";
case CodeConstants.TYPE_FLOAT:
return "F";
case CodeConstants.TYPE_INT:
return "I";
case CodeConstants.TYPE_LONG:
return "J";
case CodeConstants.TYPE_SHORT:
return "S";
case CodeConstants.TYPE_BOOLEAN:
return "Z";
case CodeConstants.TYPE_VOID:
return "V";
case CodeConstants.TYPE_GROUP2EMPTY:
return "G";
case CodeConstants.TYPE_NOTINITIALIZED:
return "N";
case CodeConstants.TYPE_ADDRESS:
return "A";
case CodeConstants.TYPE_BYTECHAR:
return "X";
case CodeConstants.TYPE_SHORTCHAR:
return "Y";
case CodeConstants.TYPE_UNKNOWN:
return "U";
case CodeConstants.TYPE_NULL:
case CodeConstants.TYPE_OBJECT:
return null;
default:
throw new RuntimeException("Invalid type");
}
}
public void setFamily() {
if (arraydim > 0) {
this.type_family = CodeConstants.TYPE_FAMILY_OBJECT;
return;
}
switch (type) {
case CodeConstants.TYPE_BYTE:
case CodeConstants.TYPE_BYTECHAR:
case CodeConstants.TYPE_SHORTCHAR:
case CodeConstants.TYPE_CHAR:
case CodeConstants.TYPE_SHORT:
case CodeConstants.TYPE_INT:
this.type_family = CodeConstants.TYPE_FAMILY_INTEGER;
break;
case CodeConstants.TYPE_DOUBLE:
this.type_family = CodeConstants.TYPE_FAMILY_DOUBLE;
break;
case CodeConstants.TYPE_FLOAT:
this.type_family = CodeConstants.TYPE_FAMILY_FLOAT;
break;
case CodeConstants.TYPE_LONG:
this.type_family = CodeConstants.TYPE_FAMILY_LONG;
break;
case CodeConstants.TYPE_BOOLEAN:
this.type_family = CodeConstants.TYPE_FAMILY_BOOLEAN;
break;
case CodeConstants.TYPE_NULL:
case CodeConstants.TYPE_OBJECT:
this.type_family = CodeConstants.TYPE_FAMILY_OBJECT;
break;
default:
this.type_family = CodeConstants.TYPE_FAMILY_UNKNOWN;
} }
} }
} }

@ -173,7 +173,7 @@ public class GenericMain {
public static String getGenericCastTypeName(GenericType type) { public static String getGenericCastTypeName(GenericType type) {
String s = getTypeName(type); String s = getTypeName(type);
int dim = type.arraydim; int dim = type.arrayDim;
while (dim-- > 0) { while (dim-- > 0) {
s += "[]"; s += "[]";
} }

@ -16,6 +16,7 @@
package org.jetbrains.java.decompiler.struct.gen.generics; package org.jetbrains.java.decompiler.struct.gen.generics;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.struct.gen.VarType;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -27,66 +28,59 @@ public class GenericType {
public static final int WILDCARD_UNBOUND = 3; public static final int WILDCARD_UNBOUND = 3;
public static final int WILDCARD_NO = 4; public static final int WILDCARD_NO = 4;
public int type; public final int type;
public final int arrayDim;
public final String value;
public int arraydim; private final List<GenericType> enclosingClasses = new ArrayList<GenericType>();
private final List<GenericType> arguments = new ArrayList<GenericType>();
private final List<Integer> wildcards = new ArrayList<Integer>();
public String value; public GenericType(int type, int arrayDim, String value) {
private List<GenericType> enclosingClasses = new ArrayList<GenericType>();
private List<GenericType> arguments = new ArrayList<GenericType>();
private List<Integer> wildcards = new ArrayList<Integer>();
public GenericType(int type, int arraydim, String value) {
this.type = type; this.type = type;
this.arraydim = arraydim; this.arrayDim = arrayDim;
this.value = value; this.value = value;
} }
public GenericType(String signature) {
public GenericType(String strtype) { int type = 0;
int arrayDim = 0;
parseSignature(strtype); String value = null;
}
private void parseSignature(String sig) {
int index = 0; int index = 0;
while (index < sig.length()) { loop:
while (index < signature.length()) {
switch (sig.charAt(index)) { switch (signature.charAt(index)) {
case '[': case '[':
arraydim++; arrayDim++;
break; break;
case 'T': case 'T':
type = CodeConstants.TYPE_GENVAR; type = CodeConstants.TYPE_GENVAR;
value = sig.substring(index + 1, sig.length() - 1); value = signature.substring(index + 1, signature.length() - 1);
return; break loop;
case 'L': case 'L':
type = CodeConstants.TYPE_OBJECT; type = CodeConstants.TYPE_OBJECT;
sig = sig.substring(index + 1, sig.length() - 1); signature = signature.substring(index + 1, signature.length() - 1);
while (true) { while (true) {
String cl = getNextClassSignature(sig); String cl = getNextClassSignature(signature);
String name = cl; String name = cl;
String args = null; String args = null;
int argfrom = cl.indexOf("<"); int argStart = cl.indexOf("<");
if (argfrom >= 0) { if (argStart >= 0) {
name = cl.substring(0, argfrom); name = cl.substring(0, argStart);
args = cl.substring(argfrom + 1, cl.length() - 1); args = cl.substring(argStart + 1, cl.length() - 1);
} }
if (cl.length() < sig.length()) { if (cl.length() < signature.length()) {
sig = sig.substring(cl.length() + 1); // skip '.' signature = signature.substring(cl.length() + 1); // skip '.'
GenericType type = new GenericType(CodeConstants.TYPE_OBJECT, 0, name); GenericType type11 = new GenericType(CodeConstants.TYPE_OBJECT, 0, name);
parseArgumentsList(args, type); parseArgumentsList(args, type11);
enclosingClasses.add(type); enclosingClasses.add(type11);
} }
else { else {
value = name; value = name;
@ -95,18 +89,22 @@ public class GenericType {
} }
} }
return; break loop;
default: default:
value = sig.substring(index, index + 1); value = signature.substring(index, index + 1);
type = getType(value.charAt(0)); type = VarType.getType(value.charAt(0));
} }
index++; index++;
} }
this.type = type;
this.arrayDim = arrayDim;
this.value = value;
} }
private static String getNextClassSignature(String value) { private static String getNextClassSignature(String value) {
int counter = 0; int counter = 0;
int index = 0; int index = 0;
@ -132,18 +130,16 @@ public class GenericType {
} }
private static void parseArgumentsList(String value, GenericType type) { private static void parseArgumentsList(String value, GenericType type) {
if (value == null) { if (value == null) {
return; return;
} }
while (value.length() > 0) { while (value.length() > 0) {
String typeStr = getNextType(value);
String tstr = getNextType(value); int len = typeStr.length();
int len = tstr.length();
int wildcard = WILDCARD_NO; int wildcard = WILDCARD_NO;
switch (tstr.charAt(0)) { switch (typeStr.charAt(0)) {
case '*': case '*':
wildcard = WILDCARD_UNBOUND; wildcard = WILDCARD_UNBOUND;
break; break;
@ -158,41 +154,40 @@ public class GenericType {
type.getWildcards().add(wildcard); type.getWildcards().add(wildcard);
if (wildcard != WILDCARD_NO) { if (wildcard != WILDCARD_NO) {
tstr = tstr.substring(1); typeStr = typeStr.substring(1);
} }
type.getArguments().add(tstr.length() == 0 ? null : new GenericType(tstr)); type.getArguments().add(typeStr.length() == 0 ? null : new GenericType(typeStr));
value = value.substring(len); value = value.substring(len);
} }
} }
public static String getNextType(String value) { public static String getNextType(String value) {
int counter = 0; int counter = 0;
int index = 0; int index = 0;
boolean contmode = false; boolean contMode = false;
loop: loop:
while (index < value.length()) { while (index < value.length()) {
switch (value.charAt(index)) { switch (value.charAt(index)) {
case '*': case '*':
if (!contmode) { if (!contMode) {
break loop; break loop;
} }
break; break;
case 'L': case 'L':
case 'T': case 'T':
if (!contmode) { if (!contMode) {
contmode = true; contMode = true;
} }
case '[': case '[':
case '+': case '+':
case '-': case '-':
break; break;
default: default:
if (!contmode) { if (!contMode) {
break loop; break loop;
} }
break; break;
@ -214,54 +209,19 @@ public class GenericType {
return value.substring(0, index + 1); return value.substring(0, index + 1);
} }
private static int getType(char c) { public GenericType decreaseArrayDim() {
switch (c) { assert arrayDim > 0 : this;
case 'B': return new GenericType(type, arrayDim - 1, value);
return CodeConstants.TYPE_BYTE;
case 'C':
return CodeConstants.TYPE_CHAR;
case 'D':
return CodeConstants.TYPE_DOUBLE;
case 'F':
return CodeConstants.TYPE_FLOAT;
case 'I':
return CodeConstants.TYPE_INT;
case 'J':
return CodeConstants.TYPE_LONG;
case 'S':
return CodeConstants.TYPE_SHORT;
case 'Z':
return CodeConstants.TYPE_BOOLEAN;
case 'V':
return CodeConstants.TYPE_VOID;
case 'G':
return CodeConstants.TYPE_GROUP2EMPTY;
case 'N':
return CodeConstants.TYPE_NOTINITIALIZED;
case 'A':
return CodeConstants.TYPE_ADDRESS;
case 'X':
return CodeConstants.TYPE_BYTECHAR;
case 'Y':
return CodeConstants.TYPE_SHORTCHAR;
case 'U':
return CodeConstants.TYPE_UNKNOWN;
default:
throw new RuntimeException("Invalid type");
}
} }
public List<GenericType> getArguments() { public List<GenericType> getArguments() {
return arguments; return arguments;
} }
public List<GenericType> getEnclosingClasses() { public List<GenericType> getEnclosingClasses() {
return enclosingClasses; return enclosingClasses;
} }
public List<Integer> getWildcards() { public List<Integer> getWildcards() {
return wildcards; return wildcards;
} }

@ -0,0 +1,31 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.java.decompiler.util;
import org.jetbrains.java.decompiler.main.ClassesProcessor;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.TextBuffer;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
public class TextUtil {
public static void writeQualifiedSuper(TextBuffer buf, String qualifier) {
ClassesProcessor.ClassNode classNode = (ClassesProcessor.ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE);
if (!qualifier.equals(classNode.classStruct.qualifiedName)) {
buf.append(DecompilerContext.getImportCollector().getShortName(ExprProcessor.buildJavaClassName(qualifier))).append('.');
}
buf.append("super");
}
}
Loading…
Cancel
Save