java-decompiler: cleanups and fixes

- duplicates eliminated
- immutable fields
- typos
- formatting
This commit is contained in:
Roman Shevchenko 2014-11-04 12:38:11 +01:00
parent 020f5c404b
commit 82a2939271
51 changed files with 1581 additions and 1845 deletions

View File

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

View File

@ -89,7 +89,7 @@ public class AssertProcessor {
if (initializer.type == Exprent.EXPRENT_FUNCTION) {
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) {
InvocationExprent invexpr = (InvocationExprent)fexpr.getLstOperands().get(0);
@ -101,7 +101,7 @@ public class AssertProcessor {
invexpr.getLstParameters().isEmpty()) {
ConstExprent cexpr = (ConstExprent)invexpr.getInstance();
if (VarType.VARTYPE_CLASS.equals(cexpr.getConsttype())) {
if (VarType.VARTYPE_CLASS.equals(cexpr.getConstType())) {
ClassNode nd = node;
while (nd != null) {
@ -173,7 +173,7 @@ public class AssertProcessor {
Exprent ascond = null, retcond = 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);
retcond = SecondaryFunctionsHelper.propagateBoolNot(ascond);
}
@ -245,9 +245,9 @@ public class AssertProcessor {
if (expr.type == Exprent.EXPRENT_EXIT) {
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();
if (CLASS_ASSERTION_ERROR.equals(nexpr.getNewtype()) && nexpr.getConstructor() != null) {
if (CLASS_ASSERTION_ERROR.equals(nexpr.getNewType()) && nexpr.getConstructor() != null) {
return nexpr.getConstructor();
}
}
@ -260,7 +260,7 @@ public class AssertProcessor {
if (exprent.type == Exprent.EXPRENT_FUNCTION) {
FunctionExprent fexpr = (FunctionExprent)exprent;
if (fexpr.getFunctype() == FunctionExprent.FUNCTION_CADD) {
if (fexpr.getFuncType() == FunctionExprent.FUNCTION_CADD) {
for (int i = 0; i < 2; i++) {
Exprent param = fexpr.getLstOperands().get(i);
@ -295,7 +295,7 @@ public class AssertProcessor {
if (exprent.type == Exprent.EXPRENT_FUNCTION) {
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) {
FieldExprent fdparam = (FieldExprent)fparam.getLstOperands().get(0);
if (classname.equals(fdparam.getClassname())

View File

@ -190,7 +190,7 @@ public class ClassReference14Processor {
CatchStatement cst = (CatchStatement)root.getFirst();
if (cst.getStats().size() == 2 && cst.getFirst().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 handler = (BasicBlockStatement)cst.getStats().get(1);
@ -247,13 +247,13 @@ public class ClassReference14Processor {
if (exprent.type == Exprent.EXPRENT_FUNCTION) {
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) {
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 &&
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);
ClassNode fieldnode = DecompilerContext.getClassProcessor().getMapRootClasses().get(field.getClassname());

View File

@ -136,7 +136,7 @@ public class ClassWriter {
firstParameter = false;
}
index += md_content.params[i].stack_size;
index += md_content.params[i].stackSize;
}
buffer.append(") ->");
@ -440,7 +440,7 @@ public class ClassWriter {
if (initializer != null) {
if (isEnum && initializer.type == Exprent.EXPRENT_NEW) {
NewExprent nexpr = (NewExprent)initializer;
nexpr.setEnumconst(true);
nexpr.setEnumConst(true);
buffer.append(nexpr.toJava(indent, tracer));
}
else {
@ -512,7 +512,7 @@ public class ClassWriter {
firstParameter = false;
}
index += md_content.params[i].stack_size;
index += md_content.params[i].stackSize;
}
buffer.append(") {").appendLineSeparator();
@ -692,16 +692,16 @@ public class ClassWriter {
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 ");
}
if (descriptor != null) {
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) {
parameterType.arraydim--;
parameterType = parameterType.decreaseArrayDim();
}
String typeName = GenericMain.getGenericCastTypeName(parameterType);
@ -717,11 +717,11 @@ public class ClassWriter {
}
}
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) {
parameterType.decArrayDim();
parameterType = parameterType.decreaseArrayDim();
}
String typeName = ExprProcessor.getCastTypeName(parameterType);
@ -745,7 +745,7 @@ public class ClassWriter {
paramCount++;
}
index += md.params[i].stack_size;
index += md.params[i].stackSize;
}
buffer.append(')');
@ -839,7 +839,7 @@ public class ClassWriter {
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
HashMap<Integer, Set<Integer>> lineStartOffsets = new HashMap<Integer, Set<Integer>>();
for (Map.Entry<Integer, Integer> entry : tracer.getMapping().entrySet()) {

View File

@ -103,7 +103,7 @@ public class EnumProcessor {
VarExprent instvar = (VarExprent)inv.getInstance();
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 (!wrapper.getClassStruct().qualifiedName.equals(inv.getClassname())) {

View File

@ -261,7 +261,7 @@ public class InitializerProcessor {
switch (expr.type) {
case Exprent.EXPRENT_VAR:
VarVersionPaar varpaar = new VarVersionPaar((VarExprent)expr);
if (!meth.varproc.getExternvars().contains(varpaar)) {
if (!meth.varproc.getExternalVars().contains(varpaar)) {
String varname = meth.varproc.getVarName(varpaar);
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();
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 (withThis || !wrapper.getClassStruct().qualifiedName.equals(inv.getClassname())) {

View File

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

View File

@ -127,7 +127,7 @@ public class NestedClassProcessor {
// this pointer
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");
}
@ -146,7 +146,7 @@ public class NestedClassProcessor {
if (expr.type == Exprent.EXPRENT_NEW) {
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();
@ -165,7 +165,7 @@ public class NestedClassProcessor {
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);
// 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);
// }
}
@ -467,7 +467,7 @@ public class NestedClassProcessor {
varname = encmeth.varproc.getVarName(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)) {
@ -478,13 +478,13 @@ public class NestedClassProcessor {
else {
varname = parent.simpleName + ".this";
}
meth.varproc.getThisvars().put(newvar, parent.classStruct.qualifiedName);
meth.varproc.getThisVars().put(newvar, parent.classStruct.qualifiedName);
}
mapNewNames.put(newvar, varname);
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());
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)) {
@ -519,7 +519,7 @@ public class NestedClassProcessor {
else {
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);
@ -594,7 +594,7 @@ public class NestedClassProcessor {
int varindex = ((VarExprent)exprent).getIndex();
if (mapParamsToNewVars.containsKey(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);
}
}
@ -608,7 +608,7 @@ public class NestedClassProcessor {
//if(fexpr.getClassname().equals(child.classStruct.qualifiedName) &&
// mapFieldsToNewVars.containsKey(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);
}
}
@ -656,7 +656,7 @@ public class NestedClassProcessor {
for (int i = 0; i < md.params.length; i++) { // no static methods allowed
String keyField = getEnclosingVarField(cl, meth, graph, varindex);
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);
}
@ -671,7 +671,7 @@ public class NestedClassProcessor {
String field = "";
// 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;
}
@ -854,7 +854,7 @@ public class NestedClassProcessor {
VarExprent var = new VarExprent(meth.counter.getCounterAndIncrement(CounterContainer.VAR_COUNTER),
classtype, meth.varproc);
var.setDefinition(true);
var.setClassdef(true);
var.setClassDef(true);
lst.add(addindex, var);
}
@ -970,8 +970,8 @@ public class NestedClassProcessor {
switch (expr.type) {
case Exprent.EXPRENT_CONST:
ConstExprent cexpr = (ConstExprent)expr;
res = (VarType.VARTYPE_CLASS.equals(cexpr.getConsttype()) && classname.equals(cexpr.getValue()) ||
classtype.equals(cexpr.getConsttype()));
res = (VarType.VARTYPE_CLASS.equals(cexpr.getConstType()) && classname.equals(cexpr.getValue()) ||
classtype.equals(cexpr.getConstType()));
break;
case Exprent.EXPRENT_FIELD:
res = classname.equals(((FieldExprent)expr).getClassname());
@ -986,8 +986,8 @@ public class NestedClassProcessor {
case Exprent.EXPRENT_VAR:
VarExprent vexpr = (VarExprent)expr;
if (vexpr.isDefinition()) {
VarType vtype = vexpr.getVartype();
if (classtype.equals(vtype) || (vtype.arraydim > 0 && classtype.value.equals(vtype.value))) {
VarType vtype = vexpr.getVarType();
if (classtype.equals(vtype) || (vtype.arrayDim > 0 && classtype.value.equals(vtype.value))) {
res = true;
}
}

View File

@ -91,7 +91,7 @@ public class NestedMemberAccess {
if (exprent.type == Exprent.EXPRENT_EXIT) {
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();
}
}
@ -188,7 +188,7 @@ public class NestedMemberAccess {
if (((VarExprent)asexpr.getRight()).getIndex() == parcount - 1) {
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 &&
((VarExprent)asexpr.getRight()).getIndex() == parcount - 1) {
type = METHOD_ACCESS_FIELD_SET;
@ -375,7 +375,7 @@ public class NestedMemberAccess {
}
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);
retexprent = ret;

View File

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

View File

@ -255,7 +255,7 @@ public class ExitHelper {
Exprent expr = lstExpr.get(lstExpr.size() - 1);
if (expr.type == Exprent.EXPRENT_EXIT) {
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
lstExpr.remove(lstExpr.size() - 1);
res = true;
@ -292,7 +292,7 @@ public class ExitHelper {
Exprent expr = lstExpr.get(lstExpr.size() - 1);
if (expr.type == Exprent.EXPRENT_EXIT) {
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);
source.removeSuccessor(edge);

View File

@ -82,7 +82,7 @@ public class ExprProcessor implements CodeConstants {
// mapConsts.put(new Integer(opc_i2s), new
// 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_instanceof), new Integer(FunctionExprent.FUNCTION_INSTANCEOF));
}
@ -276,10 +276,14 @@ public class ExprProcessor implements CodeConstants {
private static PrimitiveExprsList copyVarExprents(PrimitiveExprsList data) {
ExprentStack stack = data.getStack();
copyEntries(stack);
return data;
}
public static void copyEntries(List<Exprent> stack) {
for (int i = 0; i < stack.size(); i++) {
stack.set(i, stack.get(i).copy());
}
return data;
}
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_anewarray:
case opc_multianewarray:
int arrdims = (instr.opcode == opc_new) ? 0 : (instr.opcode == opc_anewarray) ? 1 : instr.getOperand(1);
VarType arrtype = new VarType(pool.getPrimitiveConstant(instr.getOperand(0)).getString(), true);
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);
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;
case opc_newarray:
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);
break;
case opc_dup_x2:
if (stack.getByOffset(-2).getExprType().stack_size == 2) {
if (stack.getByOffset(-2).getExprType().stackSize == 2) {
insertByOffsetEx(-2, stack, exprlist, -1);
}
else {
@ -605,7 +609,7 @@ public class ExprProcessor implements CodeConstants {
}
break;
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());
}
else {
@ -614,7 +618,7 @@ public class ExprProcessor implements CodeConstants {
}
break;
case opc_dup2_x1:
if (stack.getByOffset(-1).getExprType().stack_size == 2) {
if (stack.getByOffset(-1).getExprType().stackSize == 2) {
insertByOffsetEx(-2, stack, exprlist, -1);
}
else {
@ -623,8 +627,8 @@ public class ExprProcessor implements CodeConstants {
}
break;
case opc_dup2_x2:
if (stack.getByOffset(-1).getExprType().stack_size == 2) {
if (stack.getByOffset(-2).getExprType().stack_size == 2) {
if (stack.getByOffset(-1).getExprType().stackSize == 2) {
if (stack.getByOffset(-2).getExprType().stackSize == 2) {
insertByOffsetEx(-2, stack, exprlist, -1);
}
else {
@ -632,7 +636,7 @@ public class ExprProcessor implements CodeConstants {
}
}
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, -1);
}
@ -732,7 +736,7 @@ public class ExprProcessor implements CodeConstants {
public static String getCastTypeName(VarType type, boolean getShort) {
String s = getTypeName(type, getShort);
int dim = type.arraydim;
int dim = type.arrayDim;
while (dim-- > 0) {
s += "[]";
}
@ -755,7 +759,7 @@ public class ExprProcessor implements CodeConstants {
type == Exprent.EXPRENT_MONITOR ||
type == Exprent.EXPRENT_IF ||
(type == Exprent.EXPRENT_VAR && ((VarExprent)expr)
.isClassdef()));
.isClassDef()));
}
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) {
TextBuffer content = expr.toJava(indent, tracer);
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.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
}
if (endsWithSemikolon(expr)) {
@ -836,7 +840,7 @@ public class ExprProcessor implements CodeConstants {
public static ConstExprent getDefaultArrayValue(VarType arrtype) {
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);
}
else if (arrtype.type == CodeConstants.TYPE_FLOAT) {
@ -899,7 +903,7 @@ public class ExprProcessor implements CodeConstants {
if (exprent.type == Exprent.EXPRENT_CONST) {
ConstExprent cexpr = (ConstExprent)exprent;
switch (cexpr.getConsttype().type) {
switch (cexpr.getConstType().type) {
case CodeConstants.TYPE_BYTE:
case CodeConstants.TYPE_BYTECHAR:
case CodeConstants.TYPE_SHORT:

View File

@ -269,7 +269,7 @@ public class FinallyProcessor {
found = false;
if (exprent.type == Exprent.EXPRENT_EXIT) {
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;
}
}
@ -305,7 +305,7 @@ public class FinallyProcessor {
boolean found = false;
if (next != null && next.type == Exprent.EXPRENT_EXIT) {
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())) {
found = true;
}

View File

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

View File

@ -252,7 +252,7 @@ public class IfHelper {
List<Exprent> lstOperands = new ArrayList<Exprent>();
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));
statexpr.setCondition(new FunctionExprent(FunctionExprent.FUNCTION_CADD, lstOperands, null));
statexpr.addBytecodeOffsets(ifchild.getHeadexprent().bytecode);
@ -310,7 +310,7 @@ public class IfHelper {
lstOperands.add(firstif.getHeadexprent().getCondition());
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));
}
@ -361,7 +361,7 @@ public class IfHelper {
// negate the if condition
IfExprent statexpr = firstif.getHeadexprent();
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;
}
@ -556,7 +556,7 @@ public class IfHelper {
// negate the if condition
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) {
StatEdge ifedge = ifstat.getIfEdge();

View File

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

View File

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

View File

@ -229,8 +229,7 @@ public class SimplifyExprentsHelper {
if (init.type == Exprent.EXPRENT_CONST) {
ConstExprent cinit = (ConstExprent)init;
VarType arrtype = newex.getNewtype().copy();
arrtype.decArrayDim();
VarType arrtype = newex.getNewType().decreaseArrayDim();
ConstExprent defaultval = ExprProcessor.getDefaultArrayValue(arrtype);
@ -243,7 +242,7 @@ public class SimplifyExprentsHelper {
if (tempexpr.type == Exprent.EXPRENT_NEW) {
NewExprent tempnewex = (NewExprent)tempexpr;
int dims = newex.getNewtype().arraydim;
int dims = newex.getNewType().arrayDim;
if (dims > 1 && !tempnewex.getLstArrayElements().isEmpty()) {
tempnewex.setDirectArrayInit(true);
}
@ -274,7 +273,7 @@ public class SimplifyExprentsHelper {
if (as.getRight().type == Exprent.EXPRENT_NEW && as.getLeft().type == Exprent.EXPRENT_VAR) {
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) {
int size = ((Integer)((ConstExprent)newex.getLstDims().get(0)).getValue()).intValue();
@ -326,8 +325,7 @@ public class SimplifyExprentsHelper {
List<Exprent> lstRet = new ArrayList<Exprent>();
VarType arrtype = newex.getNewtype().copy();
arrtype.decArrayDim();
VarType arrtype = newex.getNewType().decreaseArrayDim();
ConstExprent defaultval = ExprProcessor.getDefaultArrayValue(arrtype);
@ -335,7 +333,7 @@ public class SimplifyExprentsHelper {
lstRet.add(defaultval.copy());
}
int dims = newex.getNewtype().arraydim;
int dims = newex.getNewType().arrayDim;
for (Entry<Integer, Exprent> ent : mapInit.entrySet()) {
Exprent tempexpr = ent.getValue();
lstRet.set(ent.getKey(), tempexpr);
@ -433,13 +431,13 @@ public class SimplifyExprentsHelper {
if (as.getRight().type == Exprent.EXPRENT_FUNCTION) {
FunctionExprent func = (FunctionExprent)as.getRight();
if (func.getFunctype() == FunctionExprent.FUNCTION_ADD ||
func.getFunctype() == FunctionExprent.FUNCTION_SUB) {
if (func.getFuncType() == FunctionExprent.FUNCTION_ADD ||
func.getFuncType() == FunctionExprent.FUNCTION_SUB) {
Exprent econd = func.getLstOperands().get(0);
Exprent econst = func.getLstOperands().get(1);
if (econst.type != Exprent.EXPRENT_CONST && econd.type == Exprent.EXPRENT_CONST &&
func.getFunctype() == FunctionExprent.FUNCTION_ADD) {
func.getFuncType() == FunctionExprent.FUNCTION_ADD) {
econd = econst;
econst = func.getLstOperands().get(0);
}
@ -449,7 +447,7 @@ public class SimplifyExprentsHelper {
if (left.type != Exprent.EXPRENT_VAR && left.equals(econd)) {
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);
ret.setImplicitType(VarType.VARTYPE_INT);
return ret;
@ -468,14 +466,14 @@ public class SimplifyExprentsHelper {
AssignmentExprent as = (AssignmentExprent)first;
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())) {
if (in.getFunctype() == FunctionExprent.FUNCTION_MMI) {
in.setFunctype(FunctionExprent.FUNCTION_IMM);
if (in.getFuncType() == FunctionExprent.FUNCTION_MMI) {
in.setFuncType(FunctionExprent.FUNCTION_IMM);
}
else {
in.setFunctype(FunctionExprent.FUNCTION_IPP);
in.setFuncType(FunctionExprent.FUNCTION_IPP);
}
as.setRight(in);
@ -489,7 +487,7 @@ public class SimplifyExprentsHelper {
private static boolean isMonitorExit(Exprent first) {
if (first.type == Exprent.EXPRENT_MONITOR) {
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()) {
return true;
}
@ -515,7 +513,7 @@ public class SimplifyExprentsHelper {
if (nexpr.getConstructor() != null && !nexpr.getConstructor().getLstParameters().isEmpty() &&
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);
if (node != null && node.type != ClassNode.CLASS_ROOT) {
return true;
@ -539,10 +537,10 @@ public class SimplifyExprentsHelper {
// if(as.getLeft().type == Exprent.EXPRENT_VAR && as.getRight().type == Exprent.EXPRENT_NEW) {
//
// NewExprent newexpr = (NewExprent)as.getRight();
// VarType newtype = newexpr.getNewtype();
// VarType newtype = newexpr.getNewType();
// 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) {
//
// Set<VarVersionPaar> setChangedVars = new HashSet<VarVersionPaar>();
@ -553,7 +551,7 @@ public class SimplifyExprentsHelper {
// if(remote.type == Exprent.EXPRENT_INVOCATION) {
// 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())) {
//
// Set<VarVersionPaar> setVars = remote.getAllVariables();
@ -613,8 +611,8 @@ public class SimplifyExprentsHelper {
//// }
//// } else if(remote.type == Exprent.EXPRENT_FUNCTION) {
//// FunctionExprent fexpr = (FunctionExprent)remote;
//// if(fexpr.getFunctype() == FunctionExprent.FUNCTION_IPP || fexpr.getFunctype() == FunctionExprent.FUNCTION_IMM
//// || fexpr.getFunctype() == FunctionExprent.FUNCTION_PPI || fexpr.getFunctype() == FunctionExprent.FUNCTION_MMI) {
//// if(fexpr.getFuncType() == FunctionExprent.FUNCTION_IPP || fexpr.getFuncType() == FunctionExprent.FUNCTION_IMM
//// || fexpr.getFuncType() == FunctionExprent.FUNCTION_PPI || fexpr.getFuncType() == FunctionExprent.FUNCTION_MMI) {
//// if(fexpr.getLstOperands().get(0).type == Exprent.EXPRENT_VAR) {
//// setChangedVars.add(new VarVersionPaar((VarExprent)fexpr.getLstOperands().get(0)));
//// isTempAssignment = true;
@ -649,10 +647,10 @@ public class SimplifyExprentsHelper {
if (as.getLeft().type == Exprent.EXPRENT_VAR && as.getRight().type == Exprent.EXPRENT_NEW) {
NewExprent newexpr = (NewExprent)as.getRight();
VarType newtype = newexpr.getNewtype();
VarType newtype = newexpr.getNewType();
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++) {
Exprent remote = list.get(i);
@ -819,12 +817,12 @@ public class SimplifyExprentsHelper {
ExitExprent ifex = (ExitExprent)ifexpr;
ExitExprent elseex = (ExitExprent)elseexpr;
if (ifex.getExittype() == elseex.getExittype() && ifex.getValue() != null && elseex.getValue() != null &&
ifex.getExittype() == ExitExprent.EXIT_RETURN) {
if (ifex.getExitType() == elseex.getExitType() && ifex.getValue() != null && elseex.getValue() != null &&
ifex.getExitType() == ExitExprent.EXIT_RETURN) {
// 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
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!
return false;
}
@ -832,11 +830,11 @@ public class SimplifyExprentsHelper {
List<Exprent> data = new ArrayList<Exprent>();
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(
stif.getHeadexprent().getCondition(),
ifex.getValue(),
elseex.getValue()), ifheadexpr_bytecode), ifex.getRettype(), ifheadexpr_bytecode));
elseex.getValue()), ifheadexpr_bytecode), ifex.getRetType(), ifheadexpr_bytecode));
stif.setExprents(data);
StatEdge retedge = ifstat.getAllSuccessorEdges().get(0);

View File

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

View File

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

View File

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

View File

@ -15,26 +15,22 @@
*/
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.collectors.BytecodeMappingTracer;
import java.util.List;
public class AssertExprent extends Exprent {
private List<Exprent> parameters;
{
this.type = EXPRENT_ASSERT;
}
private final List<Exprent> parameters;
public AssertExprent(List<Exprent> parameters) {
super(EXPRENT_ASSERT);
this.parameters = parameters;
}
@Override
public TextBuffer toJava(int indent, BytecodeMappingTracer tracer) {
TextBuffer buffer = new TextBuffer();
buffer.append("assert ");

View File

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

View File

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

View File

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

View File

@ -15,12 +15,6 @@
*/
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.TextBuffer;
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.struct.gen.VarType;
import java.util.*;
public class Exprent {
@ -36,7 +31,6 @@ public class Exprent {
public static final int SIDE_EFFECTS_FREE = 2;
public static final int BOTH_FLAGS = 3;
public static final int EXPRENT_ARRAY = 1;
public static final int EXPRENT_ASSIGNMENT = 2;
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_ASSERT = 14;
public int type;
public final int type;
public final int id;
public final Set<Integer> bytecode = new HashSet<Integer>(); // offsets of bytecode instructions decompiled to this exprent
public int id;
//offsets of bytecode instructions decompiled to this exprent
public Set<Integer> bytecode = new HashSet<Integer>();
{
// set exprent id
id = DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.EXPRENT_COUNTER);
public Exprent(int type) {
this.type = type;
this.id = DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.EXPRENT_COUNTER);
}
public int getPrecedence() {
@ -81,12 +72,11 @@ public class Exprent {
}
public boolean containsExprent(Exprent exprent) {
List<Exprent> listTemp = new ArrayList<Exprent>(getAllExprents(true));
listTemp.add(this);
for (Exprent lstexpr : listTemp) {
if (lstexpr.equals(exprent)) {
for (Exprent lstExpr : listTemp) {
if (lstExpr.equals(exprent)) {
return true;
}
}
@ -96,29 +86,24 @@ public class Exprent {
public List<Exprent> getAllExprents(boolean recursive) {
List<Exprent> lst = getAllExprents();
if (recursive) {
for (int i = lst.size() - 1; i >= 0; i--) {
lst.addAll(lst.get(i).getAllExprents(true));
}
}
return lst;
}
public Set<VarVersionPaar> getAllVariables() {
HashSet<VarVersionPaar> set = new HashSet<VarVersionPaar>();
List<Exprent> lstAllExprents = getAllExprents(true);
lstAllExprents.add(this);
Set<VarVersionPaar> set = new HashSet<VarVersionPaar>();
for (Exprent expr : lstAllExprents) {
if (expr.type == EXPRENT_VAR) {
set.add(new VarVersionPaar((VarExprent)expr));
}
}
return set;
}
@ -134,12 +119,11 @@ public class Exprent {
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) {
if(bytecode_offsets != null) {
bytecode.addAll(bytecode_offsets);
public void addBytecodeOffsets(Collection<Integer> bytecodeOffsets) {
if (bytecodeOffsets != null) {
bytecode.addAll(bytecodeOffsets);
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -15,11 +15,6 @@
*/
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.main.ClassWriter;
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.ListStack;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
public class NewExprent extends Exprent {
private InvocationExprent constructor;
private VarType newtype;
private VarType newType;
private List<Exprent> lstDims = new ArrayList<Exprent>();
private List<Exprent> lstArrayElements = new ArrayList<Exprent>();
private boolean directArrayInit;
private boolean anonymous;
private boolean lambda;
private boolean enumConst;
private boolean enumconst;
{
this.type = EXPRENT_NEW;
public NewExprent(VarType newType, ListStack<Exprent> stack, int arrayDim, Set<Integer> bytecodeOffsets) {
this(newType, getDimensions(arrayDim, stack), bytecodeOffsets);
}
public NewExprent(VarType newtype, ListStack<Exprent> stack, int arraydim, Set<Integer> bytecode_offsets) {
this.newtype = newtype;
for (int i = 0; i < arraydim; i++) {
lstDims.add(0, stack.pop());
}
addBytecodeOffsets(bytecode_offsets);
setAnonymous();
}
public NewExprent(VarType newtype, List<Exprent> lstDims, Set<Integer> bytecode_offsets) {
this.newtype = newtype;
public NewExprent(VarType newType, List<Exprent> lstDims, Set<Integer> bytecodeOffsets) {
super(EXPRENT_NEW);
this.newType = newType;
this.lstDims = lstDims;
addBytecodeOffsets(bytecode_offsets);
setAnonymous();
}
private void setAnonymous() {
anonymous = false;
lambda = false;
if (newtype.type == CodeConstants.TYPE_OBJECT && newtype.arraydim == 0) {
ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(newtype.value);
if (newType.type == CodeConstants.TYPE_OBJECT && newType.arrayDim == 0) {
ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(newType.value);
if (node != null && (node.type == ClassNode.CLASS_ANONYMOUS || node.type == ClassNode.CLASS_LAMBDA)) {
anonymous = true;
if (node.type == ClassNode.CLASS_LAMBDA) {
lambda = true;
}
}
}
addBytecodeOffsets(bytecodeOffsets);
}
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) {
ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(newtype.value);
return node.anonymousClassType;
return DecompilerContext.getClassProcessor().getMapRootClasses().get(newType.value).anonymousClassType;
}
else {
return newtype;
return newType;
}
}
@Override
public CheckTypesResult checkExprTypeBounds() {
CheckTypesResult result = new CheckTypesResult();
if (newtype.arraydim != 0) {
if (newType.arrayDim != 0) {
for (Exprent dim : lstDims) {
result.addMinTypeExprent(dim, VarType.VARTYPE_BYTECHAR);
result.addMaxTypeExprent(dim, VarType.VARTYPE_INT);
}
if (newtype.arraydim == 1) {
VarType leftType = newtype.copy();
leftType.decArrayDim();
if (newType.arrayDim == 1) {
VarType leftType = newType.decreaseArrayDim();
for (Exprent element : lstArrayElements) {
result.addMinTypeExprent(element, VarType.getMinTypeInFamily(leftType.type_family));
result.addMinTypeExprent(element, VarType.getMinTypeInFamily(leftType.typeFamily));
result.addMaxTypeExprent(element, leftType);
}
}
@ -134,9 +115,10 @@ public class NewExprent extends Exprent {
return result;
}
@Override
public List<Exprent> getAllExprents() {
List<Exprent> lst = new ArrayList<Exprent>();
if (newtype.arraydim == 0) {
if (newType.arrayDim == 0) {
if (constructor != null) {
Exprent constructor_instance = constructor.getInstance();
@ -162,15 +144,16 @@ public class NewExprent extends Exprent {
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.setLstArrayElements(lstArrayElements);
ret.setDirectArrayInit(directArrayInit);
ret.setAnonymous(anonymous);
ret.setEnumconst(enumconst);
ret.setEnumConst(enumConst);
return ret;
}
@Override
public int getPrecedence() {
return 1; // precedence of new
}
@ -181,7 +164,7 @@ public class NewExprent extends Exprent {
if (anonymous) {
ClassNode child = DecompilerContext.getClassProcessor().getMapRootClasses().get(newtype.value);
ClassNode child = DecompilerContext.getClassProcessor().getMapRootClasses().get(newType.value);
buf.append("(");
@ -207,7 +190,7 @@ public class NewExprent extends Exprent {
boolean firstpar = true;
int start = 0, end = invsuper.getLstParameters().size();
if (enumconst) {
if (enumConst) {
start += 2;
end -= 1;
}
@ -234,7 +217,7 @@ public class NewExprent extends Exprent {
}
}
if (!enumconst) {
if (!enumConst) {
String enclosing = null;
if (!lambda && constructor != null) {
enclosing = getQualifiedNewInstance(child.anonymousClassType.value, constructor.getLstParameters(), indent, tracer);
@ -260,7 +243,7 @@ public class NewExprent extends Exprent {
buf.append(")");
if (enumconst && buf.length() == 2) {
if (enumConst && buf.length() == 2) {
buf.setLength(0);
}
@ -278,9 +261,7 @@ public class NewExprent extends Exprent {
}
}
else if (directArrayInit) {
VarType leftType = newtype.copy();
leftType.decArrayDim();
VarType leftType = newType.decreaseArrayDim();
buf.append("{");
for (int i = 0; i < lstArrayElements.size(); i++) {
if (i > 0) {
@ -291,7 +272,7 @@ public class NewExprent extends Exprent {
buf.append("}");
}
else {
if (newtype.arraydim == 0) {
if (newType.arrayDim == 0) {
if (constructor != null) {
@ -313,8 +294,8 @@ public class NewExprent extends Exprent {
}
}
int start = enumconst ? 2 : 0;
if (!enumconst || start < lstParameters.size()) {
int start = enumConst ? 2 : 0;
if (!enumConst || start < lstParameters.size()) {
buf.append("(");
boolean firstParam = true;
@ -346,16 +327,16 @@ public class NewExprent extends Exprent {
}
}
if (!enumconst) {
if (!enumConst) {
String enclosing = 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) {
ClassNode newNode = DecompilerContext.getClassProcessor().getMapRootClasses().get(newtype.value);
ClassNode newNode = DecompilerContext.getClassProcessor().getMapRootClasses().get(newType.value);
if (newNode != null) {
typename = newNode.simpleName;
}
@ -371,10 +352,10 @@ public class NewExprent extends Exprent {
}
}
else {
buf.append("new ").append(ExprProcessor.getTypeName(newtype));
buf.append("new ").append(ExprProcessor.getTypeName(newType));
if (lstArrayElements.isEmpty()) {
for (int i = 0; i < newtype.arraydim; i++) {
for (int i = 0; i < newType.arrayDim; i++) {
buf.append("[");
if (i < lstDims.size()) {
buf.append(lstDims.get(i).toJava(indent, tracer));
@ -383,13 +364,11 @@ public class NewExprent extends Exprent {
}
}
else {
for (int i = 0; i < newtype.arraydim; i++) {
for (int i = 0; i < newType.arrayDim; i++) {
buf.append("[]");
}
VarType leftType = newtype.copy();
leftType.decArrayDim();
VarType leftType = newType.decreaseArrayDim();
buf.append("{");
for (int i = 0; i < lstArrayElements.size(); i++) {
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) {
ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(classname);
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;
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)) {
isQualifiedNew = true;
@ -440,40 +418,42 @@ public class NewExprent extends Exprent {
return null;
}
@Override
public void replaceExprent(Exprent oldExpr, Exprent newExpr) {
if (oldExpr == constructor) {
constructor = (InvocationExprent)newExpr;
}
if (constructor != null) {
constructor.replaceExprent(oldExpr, newExpr);
}
for (int i = 0; i < lstDims.size(); i++) {
if (oldExpr == lstDims.get(i)) {
lstDims.set(i, newExpr);
}
}
for (int i = 0; i < lstArrayElements.size(); i++) {
if (oldExpr == lstArrayElements.get(i)) {
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()) &&
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) {
constructor.replaceExprent(oldexpr, newexpr);
}
for (int i = 0; i < lstDims.size(); i++) {
if (oldexpr == lstDims.get(i)) {
lstDims.set(i, newexpr);
}
}
for (int i = 0; i < lstArrayElements.size(); i++) {
if (oldexpr == lstArrayElements.get(i)) {
lstArrayElements.set(i, newexpr);
}
}
}
public InvocationExprent getConstructor() {
return constructor;
}
@ -486,8 +466,8 @@ public class NewExprent extends Exprent {
return lstDims;
}
public VarType getNewtype() {
return newtype;
public VarType getNewType() {
return newType;
}
public List<Exprent> getLstArrayElements() {
@ -498,10 +478,6 @@ public class NewExprent extends Exprent {
this.lstArrayElements = lstArrayElements;
}
public boolean isDirectArrayInit() {
return directArrayInit;
}
public void setDirectArrayInit(boolean directArrayInit) {
this.directArrayInit = directArrayInit;
}
@ -518,11 +494,7 @@ public class NewExprent extends Exprent {
this.anonymous = anonymous;
}
public boolean isEnumconst() {
return enumconst;
}
public void setEnumconst(boolean enumconst) {
this.enumconst = enumconst;
public void setEnumConst(boolean enumConst) {
this.enumConst = enumConst;
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -135,7 +135,7 @@ public class SwitchStatement extends Statement {
}
else {
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();
tracer.incrementCurrentSourceLine();

View File

@ -75,18 +75,18 @@ public class VarDefinitionHelper {
varindex++;
}
else {
varindex += md.params[i - 1].stack_size;
varindex += md.params[i - 1].stackSize;
}
}
else {
varindex += md.params[i].stack_size;
varindex += md.params[i].stackSize;
}
}
if (thisvar) {
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");
vc.addName("this");
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -15,6 +15,8 @@
*/
package org.jetbrains.java.decompiler.struct.gen;
import org.jetbrains.java.decompiler.code.CodeConstants;
public class FieldDescriptor {
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 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) {
FieldDescriptor fd = new FieldDescriptor();
fd.type = new VarType(descr);
fd.descriptorString = descr;
return fd;
public static FieldDescriptor parseDescriptor(String descriptor) {
return new FieldDescriptor(descriptor);
}
public String getDescriptor() {
return type.toString();
public String buildNewDescriptor(NewClassNameBuilder builder) {
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

View File

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

View File

@ -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);
}

View File

@ -20,7 +20,7 @@ import org.jetbrains.java.decompiler.util.InterpreterUtil;
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_INT = new VarType(CodeConstants.TYPE_INT);
@ -35,312 +35,80 @@ public class VarType { // TODO: optimize switch
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_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_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_VOID = new VarType(CodeConstants.TYPE_VOID);
public int type;
public int type_family;
public int arraydim;
public String value;
public int stack_size;
public int convinfo;
public final int type;
public final int arrayDim;
public final String value;
public final int typeFamily;
public final int stackSize;
public final boolean falseBoolean;
public VarType(int type) {
this(type, 0);
}
public VarType(int type, int arrayDim) {
this(type, arrayDim, getChar(type));
}
public VarType(int type, int arrayDim, String value) {
this(type, arrayDim, value, getFamily(type, arrayDim), getStackSize(type, arrayDim), false);
}
private VarType(int type, int arrayDim, String value, int typeFamily, int stackSize, boolean falseBoolean) {
this.type = type;
this.arraydim = 0;
value = getChar(type);
setStackSize(type);
setFamily();
}
public VarType(int type, int arraydim) {
this(type);
this.arraydim = arraydim;
setFamily();
}
public VarType(int type, int arraydim, String value) {
this(type);
this.arraydim = arraydim;
this.arrayDim = arrayDim;
this.value = value;
setFamily();
this.typeFamily = typeFamily;
this.stackSize = stackSize;
this.falseBoolean = falseBoolean;
}
public VarType(String strtype) {
this(strtype, false);
public VarType(String signature) {
this(signature, false);
}
public VarType(String strtype, boolean cltype) {
parseTypeString(strtype, cltype);
setStackSize(type);
setFamily();
}
public VarType(String signature, boolean clType) {
int type = 0;
int arrayDim = 0;
String value = null;
public void decArrayDim() {
if (arraydim > 0) {
arraydim--;
setFamily();
}
else {
// throw new RuntimeException("array dimension equals 0!"); FIXME: investigate this case
}
}
public String toString() {
String res = "";
for (int i = 0; i < arraydim; i++) {
res += "[";
}
if (type == CodeConstants.TYPE_OBJECT) {
res += "L" + value + ";";
}
else {
res += value;
}
return res;
}
public VarType copy() {
VarType v = new VarType(type, arraydim, value);
v.convinfo = convinfo;
return v;
}
public boolean isFalseBoolean() {
return (convinfo & FALSEBOOLEAN) != 0;
}
public boolean isSuperset(VarType val) {
return this.equals(val) || this.isStrictSuperset(val);
}
public boolean isStrictSuperset(VarType val) {
int valtype = val.type;
if (valtype == CodeConstants.TYPE_UNKNOWN && type != CodeConstants.TYPE_UNKNOWN) {
return true;
}
if (val.arraydim > 0) {
return this.equals(VARTYPE_OBJECT);
}
else if (arraydim > 0) {
return (valtype == CodeConstants.TYPE_NULL);
}
boolean res = false;
switch (type) {
case CodeConstants.TYPE_INT:
res |= (valtype == CodeConstants.TYPE_SHORT ||
valtype == CodeConstants.TYPE_CHAR);
case CodeConstants.TYPE_SHORT:
res |= (valtype == CodeConstants.TYPE_BYTE);
case CodeConstants.TYPE_CHAR:
res |= (valtype == CodeConstants.TYPE_SHORTCHAR);
case CodeConstants.TYPE_BYTE:
case CodeConstants.TYPE_SHORTCHAR:
res |= (valtype == CodeConstants.TYPE_BYTECHAR);
case CodeConstants.TYPE_BYTECHAR:
res |= (valtype == CodeConstants.TYPE_BOOLEAN);
break;
case CodeConstants.TYPE_OBJECT:
if (valtype == CodeConstants.TYPE_NULL) {
return true;
}
else if (this.equals(VARTYPE_OBJECT)) {
return valtype == CodeConstants.TYPE_OBJECT &&
!val.equals(VARTYPE_OBJECT);
}
}
return res;
}
// type1 and type2 must not be null
public static VarType getCommonMinType(VarType type1, VarType type2) {
if (type1.type == CodeConstants.TYPE_BOOLEAN && type2.type == CodeConstants.TYPE_BOOLEAN) { // special case booleans
return type1.isFalseBoolean() ? type2 : type1;
}
if (type1.isSuperset(type2)) {
return type2;
}
else if (type2.isSuperset(type1)) {
return type1;
}
else if (type1.type_family == type2.type_family) {
switch (type1.type_family) {
case CodeConstants.TYPE_FAMILY_INTEGER:
if ((type1.type == CodeConstants.TYPE_CHAR && type2.type == CodeConstants.TYPE_SHORT)
|| (type1.type == CodeConstants.TYPE_SHORT && type2.type == CodeConstants.TYPE_CHAR)) {
return VARTYPE_SHORTCHAR;
}
else {
return VARTYPE_BYTECHAR;
}
case CodeConstants.TYPE_FAMILY_OBJECT:
return VARTYPE_NULL;
}
}
return null;
}
// type1 and type2 must not be null
public static VarType getCommonSupertype(VarType type1, VarType type2) {
if (type1.type == CodeConstants.TYPE_BOOLEAN && type2.type == CodeConstants.TYPE_BOOLEAN) { // special case booleans
return type1.isFalseBoolean() ? type1 : type2;
}
if (type1.isSuperset(type2)) {
return type1;
}
else if (type2.isSuperset(type1)) {
return type2;
}
else if (type1.type_family == type2.type_family) {
switch (type1.type_family) {
case CodeConstants.TYPE_FAMILY_INTEGER:
if ((type1.type == CodeConstants.TYPE_SHORTCHAR && type2.type == CodeConstants.TYPE_BYTE)
|| (type1.type == CodeConstants.TYPE_BYTE && type2.type == CodeConstants.TYPE_SHORTCHAR)) {
return VARTYPE_SHORT;
}
else {
return VARTYPE_INT;
}
case CodeConstants.TYPE_FAMILY_OBJECT:
return VARTYPE_OBJECT;
}
}
return null;
}
public static VarType getMinTypeInFamily(int family) {
switch (family) {
case CodeConstants.TYPE_FAMILY_BOOLEAN:
return VARTYPE_BOOLEAN;
case CodeConstants.TYPE_FAMILY_INTEGER:
return VARTYPE_BYTECHAR;
case CodeConstants.TYPE_FAMILY_OBJECT:
return VARTYPE_NULL;
case CodeConstants.TYPE_FAMILY_FLOAT:
return VARTYPE_FLOAT;
case CodeConstants.TYPE_FAMILY_LONG:
return VARTYPE_LONG;
case CodeConstants.TYPE_FAMILY_DOUBLE:
return VARTYPE_DOUBLE;
case CodeConstants.TYPE_FAMILY_UNKNOWN:
return VARTYPE_UNKNOWN;
default:
throw new RuntimeException("invalid type 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)) {
loop:
for (int i = 0; i < signature.length(); i++) {
switch (signature.charAt(i)) {
case '[':
arraydim++;
arrayDim++;
break;
case 'L':
if (strtype.charAt(strtype.length() - 1) == ';') {
if (signature.charAt(signature.length() - 1) == ';') {
type = CodeConstants.TYPE_OBJECT;
value = strtype.substring(i + 1, strtype.length() - 1);
return;
value = signature.substring(i + 1, signature.length() - 1);
break loop;
}
default:
value = strtype.substring(i, strtype.length());
if ((cltype && i == 0) || value.length() > 1) {
value = signature.substring(i, signature.length());
if ((clType && i == 0) || value.length() > 1) {
type = CodeConstants.TYPE_OBJECT;
}
else {
type = getType(value.charAt(0));
}
return;
break loop;
}
}
}
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) {
switch (c) {
case 'B':
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");
}
this.type = type;
this.arrayDim = arrayDim;
this.value = value;
this.typeFamily = getFamily(type, arrayDim);
this.stackSize = getStackSize(type, arrayDim);
this.falseBoolean = false;
}
private static String getChar(int type) {
@ -383,11 +151,26 @@ public class VarType { // TODO: optimize switch
}
}
public void setFamily() {
private static int getStackSize(int type, int arrayDim) {
if (arrayDim > 0) {
return 1;
}
if (arraydim > 0) {
this.type_family = CodeConstants.TYPE_FAMILY_OBJECT;
return;
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;
}
}
private static int getFamily(int type, int arrayDim) {
if (arrayDim > 0) {
return CodeConstants.TYPE_FAMILY_OBJECT;
}
switch (type) {
@ -397,26 +180,239 @@ public class VarType { // TODO: optimize switch
case CodeConstants.TYPE_CHAR:
case CodeConstants.TYPE_SHORT:
case CodeConstants.TYPE_INT:
this.type_family = CodeConstants.TYPE_FAMILY_INTEGER;
break;
return CodeConstants.TYPE_FAMILY_INTEGER;
case CodeConstants.TYPE_DOUBLE:
this.type_family = CodeConstants.TYPE_FAMILY_DOUBLE;
break;
return CodeConstants.TYPE_FAMILY_DOUBLE;
case CodeConstants.TYPE_FLOAT:
this.type_family = CodeConstants.TYPE_FAMILY_FLOAT;
break;
return CodeConstants.TYPE_FAMILY_FLOAT;
case CodeConstants.TYPE_LONG:
this.type_family = CodeConstants.TYPE_FAMILY_LONG;
break;
return CodeConstants.TYPE_FAMILY_LONG;
case CodeConstants.TYPE_BOOLEAN:
this.type_family = CodeConstants.TYPE_FAMILY_BOOLEAN;
break;
return CodeConstants.TYPE_FAMILY_BOOLEAN;
case CodeConstants.TYPE_NULL:
case CodeConstants.TYPE_OBJECT:
this.type_family = CodeConstants.TYPE_FAMILY_OBJECT;
break;
return CodeConstants.TYPE_FAMILY_OBJECT;
default:
this.type_family = CodeConstants.TYPE_FAMILY_UNKNOWN;
return CodeConstants.TYPE_FAMILY_UNKNOWN;
}
}
public VarType decreaseArrayDim() {
if (arrayDim > 0) {
return new VarType(type, arrayDim - 1, value);
}
else {
//throw new RuntimeException("array dimension equals 0!"); FIXME: investigate this case
return this;
}
}
public VarType resizeArrayDim(int newArrayDim) {
return new VarType(type, newArrayDim, value, typeFamily, stackSize, falseBoolean);
}
public VarType copy() {
return copy(false);
}
public VarType copy(boolean forceFalseBoolean) {
return new VarType(type, arrayDim, value, typeFamily, stackSize, falseBoolean || forceFalseBoolean);
}
public boolean isFalseBoolean() {
return falseBoolean;
}
public boolean isSuperset(VarType val) {
return this.equals(val) || this.isStrictSuperset(val);
}
public boolean isStrictSuperset(VarType val) {
int valType = val.type;
if (valType == CodeConstants.TYPE_UNKNOWN && type != CodeConstants.TYPE_UNKNOWN) {
return true;
}
if (val.arrayDim > 0) {
return this.equals(VARTYPE_OBJECT);
}
else if (arrayDim > 0) {
return (valType == CodeConstants.TYPE_NULL);
}
boolean res = false;
switch (type) {
case CodeConstants.TYPE_INT:
res = (valType == CodeConstants.TYPE_SHORT || valType == CodeConstants.TYPE_CHAR);
case CodeConstants.TYPE_SHORT:
res |= (valType == CodeConstants.TYPE_BYTE);
case CodeConstants.TYPE_CHAR:
res |= (valType == CodeConstants.TYPE_SHORTCHAR);
case CodeConstants.TYPE_BYTE:
case CodeConstants.TYPE_SHORTCHAR:
res |= (valType == CodeConstants.TYPE_BYTECHAR);
case CodeConstants.TYPE_BYTECHAR:
res |= (valType == CodeConstants.TYPE_BOOLEAN);
break;
case CodeConstants.TYPE_OBJECT:
if (valType == CodeConstants.TYPE_NULL) {
return true;
}
else if (this.equals(VARTYPE_OBJECT)) {
return valType == CodeConstants.TYPE_OBJECT && !val.equals(VARTYPE_OBJECT);
}
}
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
public static VarType getCommonMinType(VarType type1, VarType type2) {
if (type1.type == CodeConstants.TYPE_BOOLEAN && type2.type == CodeConstants.TYPE_BOOLEAN) { // special case booleans
return type1.isFalseBoolean() ? type2 : type1;
}
if (type1.isSuperset(type2)) {
return type2;
}
else if (type2.isSuperset(type1)) {
return type1;
}
else if (type1.typeFamily == type2.typeFamily) {
switch (type1.typeFamily) {
case CodeConstants.TYPE_FAMILY_INTEGER:
if ((type1.type == CodeConstants.TYPE_CHAR && type2.type == CodeConstants.TYPE_SHORT)
|| (type1.type == CodeConstants.TYPE_SHORT && type2.type == CodeConstants.TYPE_CHAR)) {
return VARTYPE_SHORTCHAR;
}
else {
return VARTYPE_BYTECHAR;
}
case CodeConstants.TYPE_FAMILY_OBJECT:
return VARTYPE_NULL;
}
}
return null;
}
// type1 and type2 must not be null
public static VarType getCommonSupertype(VarType type1, VarType type2) {
if (type1.type == CodeConstants.TYPE_BOOLEAN && type2.type == CodeConstants.TYPE_BOOLEAN) { // special case booleans
return type1.isFalseBoolean() ? type1 : type2;
}
if (type1.isSuperset(type2)) {
return type1;
}
else if (type2.isSuperset(type1)) {
return type2;
}
else if (type1.typeFamily == type2.typeFamily) {
switch (type1.typeFamily) {
case CodeConstants.TYPE_FAMILY_INTEGER:
if ((type1.type == CodeConstants.TYPE_SHORTCHAR && type2.type == CodeConstants.TYPE_BYTE)
|| (type1.type == CodeConstants.TYPE_BYTE && type2.type == CodeConstants.TYPE_SHORTCHAR)) {
return VARTYPE_SHORT;
}
else {
return VARTYPE_INT;
}
case CodeConstants.TYPE_FAMILY_OBJECT:
return VARTYPE_OBJECT;
}
}
return null;
}
public static VarType getMinTypeInFamily(int family) {
switch (family) {
case CodeConstants.TYPE_FAMILY_BOOLEAN:
return VARTYPE_BOOLEAN;
case CodeConstants.TYPE_FAMILY_INTEGER:
return VARTYPE_BYTECHAR;
case CodeConstants.TYPE_FAMILY_OBJECT:
return VARTYPE_NULL;
case CodeConstants.TYPE_FAMILY_FLOAT:
return VARTYPE_FLOAT;
case CodeConstants.TYPE_FAMILY_LONG:
return VARTYPE_LONG;
case CodeConstants.TYPE_FAMILY_DOUBLE:
return VARTYPE_DOUBLE;
case CodeConstants.TYPE_FAMILY_UNKNOWN:
return VARTYPE_UNKNOWN;
default:
throw new IllegalArgumentException("Invalid type family: " + family);
}
}
public static int getType(char c) {
switch (c) {
case 'B':
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 IllegalArgumentException("Invalid type: " + c);
}
}
}

View File

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

View File

@ -16,6 +16,7 @@
package org.jetbrains.java.decompiler.struct.gen.generics;
import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.struct.gen.VarType;
import java.util.ArrayList;
import java.util.List;
@ -27,66 +28,59 @@ public class GenericType {
public static final int WILDCARD_UNBOUND = 3;
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;
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) {
public GenericType(int type, int arrayDim, String value) {
this.type = type;
this.arraydim = arraydim;
this.arrayDim = arrayDim;
this.value = value;
}
public GenericType(String strtype) {
parseSignature(strtype);
}
private void parseSignature(String sig) {
public GenericType(String signature) {
int type = 0;
int arrayDim = 0;
String value = null;
int index = 0;
while (index < sig.length()) {
switch (sig.charAt(index)) {
loop:
while (index < signature.length()) {
switch (signature.charAt(index)) {
case '[':
arraydim++;
arrayDim++;
break;
case 'T':
type = CodeConstants.TYPE_GENVAR;
value = sig.substring(index + 1, sig.length() - 1);
return;
value = signature.substring(index + 1, signature.length() - 1);
break loop;
case 'L':
type = CodeConstants.TYPE_OBJECT;
sig = sig.substring(index + 1, sig.length() - 1);
signature = signature.substring(index + 1, signature.length() - 1);
while (true) {
String cl = getNextClassSignature(sig);
String cl = getNextClassSignature(signature);
String name = cl;
String args = null;
int argfrom = cl.indexOf("<");
if (argfrom >= 0) {
name = cl.substring(0, argfrom);
args = cl.substring(argfrom + 1, cl.length() - 1);
int argStart = cl.indexOf("<");
if (argStart >= 0) {
name = cl.substring(0, argStart);
args = cl.substring(argStart + 1, cl.length() - 1);
}
if (cl.length() < sig.length()) {
sig = sig.substring(cl.length() + 1); // skip '.'
GenericType type = new GenericType(CodeConstants.TYPE_OBJECT, 0, name);
parseArgumentsList(args, type);
enclosingClasses.add(type);
if (cl.length() < signature.length()) {
signature = signature.substring(cl.length() + 1); // skip '.'
GenericType type11 = new GenericType(CodeConstants.TYPE_OBJECT, 0, name);
parseArgumentsList(args, type11);
enclosingClasses.add(type11);
}
else {
value = name;
@ -95,18 +89,22 @@ public class GenericType {
}
}
return;
break loop;
default:
value = sig.substring(index, index + 1);
type = getType(value.charAt(0));
value = signature.substring(index, index + 1);
type = VarType.getType(value.charAt(0));
}
index++;
}
this.type = type;
this.arrayDim = arrayDim;
this.value = value;
}
private static String getNextClassSignature(String value) {
int counter = 0;
int index = 0;
@ -132,18 +130,16 @@ public class GenericType {
}
private static void parseArgumentsList(String value, GenericType type) {
if (value == null) {
return;
}
while (value.length() > 0) {
String tstr = getNextType(value);
int len = tstr.length();
String typeStr = getNextType(value);
int len = typeStr.length();
int wildcard = WILDCARD_NO;
switch (tstr.charAt(0)) {
switch (typeStr.charAt(0)) {
case '*':
wildcard = WILDCARD_UNBOUND;
break;
@ -158,41 +154,40 @@ public class GenericType {
type.getWildcards().add(wildcard);
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);
}
}
public static String getNextType(String value) {
int counter = 0;
int index = 0;
boolean contmode = false;
boolean contMode = false;
loop:
while (index < value.length()) {
switch (value.charAt(index)) {
case '*':
if (!contmode) {
if (!contMode) {
break loop;
}
break;
case 'L':
case 'T':
if (!contmode) {
contmode = true;
if (!contMode) {
contMode = true;
}
case '[':
case '+':
case '-':
break;
default:
if (!contmode) {
if (!contMode) {
break loop;
}
break;
@ -214,54 +209,19 @@ public class GenericType {
return value.substring(0, index + 1);
}
private static int getType(char c) {
switch (c) {
case 'B':
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 GenericType decreaseArrayDim() {
assert arrayDim > 0 : this;
return new GenericType(type, arrayDim - 1, value);
}
public List<GenericType> getArguments() {
return arguments;
}
public List<GenericType> getEnclosingClasses() {
return enclosingClasses;
}
public List<Integer> getWildcards() {
return wildcards;
}

View File

@ -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");
}
}