mirror of
https://github.com/skylot/jadx.git
synced 2024-11-23 12:50:02 +00:00
core: make methods arguments types immutable
This commit is contained in:
parent
d94087b939
commit
eec524ad85
@ -340,9 +340,6 @@ public class ClassGen {
|
||||
}
|
||||
|
||||
private String useClassInternal(ClassInfo useCls, ClassInfo classInfo) {
|
||||
if (parentGen != null) {
|
||||
return parentGen.useClassInternal(useCls, classInfo);
|
||||
}
|
||||
String clsStr = classInfo.getFullName();
|
||||
if (fallback) {
|
||||
return clsStr;
|
||||
@ -372,11 +369,19 @@ public class ClassGen {
|
||||
}
|
||||
}
|
||||
}
|
||||
imports.add(classInfo);
|
||||
addImport(classInfo);
|
||||
return shortName;
|
||||
}
|
||||
}
|
||||
|
||||
private void addImport(ClassInfo classInfo) {
|
||||
if (parentGen != null) {
|
||||
parentGen.addImport(classInfo);
|
||||
} else {
|
||||
imports.add(classInfo);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isClassInnerFor(ClassInfo inner, ClassInfo parent) {
|
||||
if (inner.isInner()) {
|
||||
ClassInfo p = inner.getParentClass();
|
||||
@ -393,9 +398,11 @@ public class ClassGen {
|
||||
return true;
|
||||
}
|
||||
ClassNode classNode = dex.resolveClass(useCls);
|
||||
for (ClassNode inner : classNode.getInnerClasses()) {
|
||||
if (inner.getShortName().equals(shortName)) {
|
||||
return true;
|
||||
if (classNode != null) {
|
||||
for (ClassNode inner : classNode.getInnerClasses()) {
|
||||
if (inner.getShortName().equals(shortName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return searchCollision(dex, useCls.getParentClass(), shortName);
|
||||
|
@ -101,7 +101,7 @@ public class InsnGen {
|
||||
return sfield(f.getField());
|
||||
} else {
|
||||
RegisterArg regArg = new RegisterArg(f.getRegNum());
|
||||
regArg.setTypedVar(f.getTypedVar());
|
||||
regArg.replaceTypedVar(f);
|
||||
return ifield(f.getField(), regArg);
|
||||
}
|
||||
} else {
|
||||
@ -281,13 +281,14 @@ public class InsnGen {
|
||||
|
||||
case INSTANCE_OF: {
|
||||
boolean wrap = state.contains(IGState.BODY_ONLY);
|
||||
if (wrap)
|
||||
code.add("(");
|
||||
if (wrap) {
|
||||
code.add('(');
|
||||
}
|
||||
code.add(arg(insn, 0));
|
||||
code.add(" instanceof ");
|
||||
code.add(useType((ArgType) ((IndexInsnNode) insn).getIndex()));
|
||||
if (wrap) {
|
||||
code.add(")");
|
||||
code.add(')');
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -218,13 +218,6 @@ public class MethodGen {
|
||||
return r;
|
||||
}
|
||||
|
||||
private void makeInitCode(CodeWriter code) throws CodegenException {
|
||||
InsnGen igen = new InsnGen(this, mth, fallback);
|
||||
// generate super call
|
||||
if (mth.getSuperCall() != null)
|
||||
igen.makeInsn(mth.getSuperCall(), code);
|
||||
}
|
||||
|
||||
public CodeWriter makeInstructions(int mthIndent) throws CodegenException {
|
||||
CodeWriter code = new CodeWriter(mthIndent + 1);
|
||||
|
||||
@ -252,7 +245,6 @@ public class MethodGen {
|
||||
LOG.debug(ErrorsCounter.formatErrorMsg(mth, " Inconsistent code"));
|
||||
// makeMethodDump(code, mth);
|
||||
}
|
||||
makeInitCode(code);
|
||||
code.add(insns);
|
||||
} else {
|
||||
makeFallbackMethod(code, mth);
|
||||
|
@ -21,18 +21,19 @@ public final class BlockRegState {
|
||||
}
|
||||
|
||||
public void assignReg(RegisterArg arg) {
|
||||
int rn = arg.getRegNum();
|
||||
regs[rn] = new RegisterArg(rn, arg.getType());
|
||||
use(arg);
|
||||
regs[arg.getRegNum()] = arg;
|
||||
arg.getTypedVar().getUseList().add(arg);
|
||||
}
|
||||
|
||||
public void use(RegisterArg arg) {
|
||||
TypedVar regType = regs[arg.getRegNum()].getTypedVar();
|
||||
RegisterArg reg = regs[arg.getRegNum()];
|
||||
TypedVar regType = reg.getTypedVar();
|
||||
if (regType == null) {
|
||||
regType = new TypedVar(arg.getType());
|
||||
regs[arg.getRegNum()].setTypedVar(regType);
|
||||
reg.forceSetTypedVar(regType);
|
||||
}
|
||||
regType.use(arg);
|
||||
arg.replaceTypedVar(reg);
|
||||
reg.getTypedVar().getUseList().add(arg);
|
||||
}
|
||||
|
||||
public RegisterArg getRegister(int r) {
|
||||
|
@ -2,13 +2,17 @@ package jadx.core.dex.instructions.args;
|
||||
|
||||
public class ImmutableTypedVar extends TypedVar {
|
||||
|
||||
public ImmutableTypedVar(ArgType initType) {
|
||||
super(initType);
|
||||
public ImmutableTypedVar(ArgType type) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean forceSetType(ArgType newType) {
|
||||
return false;
|
||||
public boolean isImmutable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forceSetType(ArgType newType) {
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -17,7 +21,7 @@ public class ImmutableTypedVar extends TypedVar {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean merge(ArgType mtype) {
|
||||
public boolean merge(ArgType type) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,12 @@ public abstract class InsnArg extends Typed {
|
||||
return reg(InsnUtils.getArg(insn, argNum), type);
|
||||
}
|
||||
|
||||
public static RegisterArg immutableReg(int regNum, ArgType type) {
|
||||
RegisterArg r = new RegisterArg(regNum);
|
||||
r.forceSetTypedVar(new ImmutableTypedVar(type));
|
||||
return r;
|
||||
}
|
||||
|
||||
public static LiteralArg lit(long literal, ArgType type) {
|
||||
return new LiteralArg(literal, type);
|
||||
}
|
||||
|
@ -88,13 +88,14 @@ public class RegisterArg extends InsnArg {
|
||||
public boolean isThis() {
|
||||
if (isRegister()) {
|
||||
String name = getTypedVar().getName();
|
||||
if (name != null && name.equals("this"))
|
||||
if (name != null && name.equals("this")) {
|
||||
return true;
|
||||
|
||||
}
|
||||
// maybe it was moved from 'this' register
|
||||
InsnNode ai = getAssignInsn();
|
||||
if (ai != null && ai.getType() == InsnType.MOVE) {
|
||||
if (ai.getArg(0).isThis()) {
|
||||
InsnArg arg = ai.getArg(0);
|
||||
if (arg != this && arg.isThis()) {
|
||||
// actually we need to remove this instruction but we can't
|
||||
// because of iterating on instructions list
|
||||
// so unbind insn and rely on code shrinker
|
||||
|
@ -1,17 +1,15 @@
|
||||
package jadx.core.dex.instructions.args;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class Typed {
|
||||
|
||||
protected TypedVar typedVar;
|
||||
TypedVar typedVar;
|
||||
|
||||
public TypedVar getTypedVar() {
|
||||
return typedVar;
|
||||
}
|
||||
|
||||
public void setTypedVar(TypedVar arg) {
|
||||
this.typedVar = arg;
|
||||
}
|
||||
|
||||
public ArgType getType() {
|
||||
return typedVar.getType();
|
||||
}
|
||||
@ -24,26 +22,50 @@ public abstract class Typed {
|
||||
return typedVar.merge(var);
|
||||
}
|
||||
|
||||
public void replace(Typed var) {
|
||||
replace(var.getTypedVar());
|
||||
public void forceSetTypedVar(TypedVar arg) {
|
||||
this.typedVar = arg;
|
||||
}
|
||||
|
||||
public void replace(TypedVar newVar) {
|
||||
if (typedVar == newVar)
|
||||
return;
|
||||
public void mergeDebugInfo(Typed arg) {
|
||||
merge(arg);
|
||||
mergeName(arg);
|
||||
}
|
||||
|
||||
if (typedVar != null) {
|
||||
newVar.merge(typedVar);
|
||||
for (InsnArg arg : typedVar.getUseList()) {
|
||||
if (arg != this)
|
||||
arg.setTypedVar(newVar);
|
||||
}
|
||||
newVar.getUseList().addAll(typedVar.getUseList());
|
||||
if (typedVar.getName() != null)
|
||||
newVar.setName(typedVar.getName());
|
||||
typedVar.getUseList().clear();
|
||||
protected void mergeName(Typed arg) {
|
||||
getTypedVar().mergeName(arg.getTypedVar());
|
||||
}
|
||||
|
||||
public boolean replaceTypedVar(Typed var) {
|
||||
TypedVar curVar = this.typedVar;
|
||||
TypedVar newVar = var.typedVar;
|
||||
if (curVar == newVar) {
|
||||
return false;
|
||||
}
|
||||
typedVar = newVar;
|
||||
if (curVar != null) {
|
||||
if (curVar.isImmutable()) {
|
||||
moveInternals(newVar, curVar);
|
||||
} else {
|
||||
newVar.merge(curVar);
|
||||
moveInternals(curVar, newVar);
|
||||
this.typedVar = newVar;
|
||||
}
|
||||
} else {
|
||||
this.typedVar = newVar;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void moveInternals(TypedVar from, TypedVar to) {
|
||||
List<InsnArg> curUseList = from.getUseList();
|
||||
if (curUseList.size() != 0) {
|
||||
for (InsnArg arg : curUseList) {
|
||||
if (arg != this) {
|
||||
arg.forceSetTypedVar(to);
|
||||
}
|
||||
}
|
||||
to.getUseList().addAll(curUseList);
|
||||
curUseList.clear();
|
||||
}
|
||||
to.mergeName(from);
|
||||
}
|
||||
}
|
||||
|
@ -20,13 +20,8 @@ public class TypedVar {
|
||||
/**
|
||||
* This method must be used very carefully
|
||||
*/
|
||||
public boolean forceSetType(ArgType newType) {
|
||||
if (!newType.equals(type)) {
|
||||
type = newType;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
public void forceSetType(ArgType newType) {
|
||||
type = newType;
|
||||
}
|
||||
|
||||
public boolean merge(TypedVar typedVar) {
|
||||
@ -43,11 +38,6 @@ public class TypedVar {
|
||||
}
|
||||
}
|
||||
|
||||
public void use(InsnArg arg) {
|
||||
arg.replace(this);
|
||||
useList.add(arg);
|
||||
}
|
||||
|
||||
public List<InsnArg> getUseList() {
|
||||
return useList;
|
||||
}
|
||||
@ -60,6 +50,19 @@ public class TypedVar {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void mergeName(TypedVar arg) {
|
||||
String name = arg.getName();
|
||||
if (name != null) {
|
||||
setName(name);
|
||||
} else if (getName() != null) {
|
||||
arg.setName(getName());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isImmutable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return type.hashCode() * 31 + (name == null ? 0 : name.hashCode());
|
||||
@ -69,7 +72,7 @@ public class TypedVar {
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (obj == null) return false;
|
||||
if (getClass() != obj.getClass()) return false;
|
||||
if (!(obj instanceof TypedVar)) return false;
|
||||
TypedVar other = (TypedVar) obj;
|
||||
if (!type.equals(other.type)) return false;
|
||||
if (name == null) {
|
||||
|
@ -291,6 +291,10 @@ public class ClassNode extends LineAttrNode implements ILoadable {
|
||||
innerClasses.add(cls);
|
||||
}
|
||||
|
||||
public boolean isEnum() {
|
||||
return getAccessFlags().isEnum() && getSuperClass().getFullName().equals(Consts.CLASS_ENUM);
|
||||
}
|
||||
|
||||
public boolean isAnonymous() {
|
||||
boolean simple = false;
|
||||
for (MethodNode m : methods) {
|
||||
|
@ -125,10 +125,11 @@ public class InsnNode extends LineAttrNode {
|
||||
|
||||
public void getRegisterArgs(List<RegisterArg> list) {
|
||||
for (InsnArg arg : this.getArguments()) {
|
||||
if (arg.isRegister())
|
||||
if (arg.isRegister()) {
|
||||
list.add((RegisterArg) arg);
|
||||
else if (arg.isInsnWrap())
|
||||
} else if (arg.isInsnWrap()) {
|
||||
((InsnWrapArg) arg).getWrapInsn().getRegisterArgs(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,6 @@ import jadx.core.dex.instructions.SwitchNode;
|
||||
import jadx.core.dex.instructions.args.ArgType;
|
||||
import jadx.core.dex.instructions.args.InsnArg;
|
||||
import jadx.core.dex.instructions.args.RegisterArg;
|
||||
import jadx.core.dex.instructions.mods.ConstructorInsn;
|
||||
import jadx.core.dex.nodes.parser.DebugInfoParser;
|
||||
import jadx.core.dex.trycatch.ExcHandlerAttr;
|
||||
import jadx.core.dex.trycatch.ExceptionHandler;
|
||||
@ -61,8 +60,6 @@ public class MethodNode extends LineAttrNode implements ILoadable {
|
||||
private BlockNode enterBlock;
|
||||
private List<BlockNode> exitBlocks;
|
||||
|
||||
private ConstructorInsn superCall;
|
||||
|
||||
private IContainer region;
|
||||
private List<ExceptionHandler> exceptionHandlers;
|
||||
private List<LoopAttr> loops = Collections.emptyList();
|
||||
@ -204,22 +201,19 @@ public class MethodNode extends LineAttrNode implements ILoadable {
|
||||
for (ArgType arg : args)
|
||||
pos -= arg.getRegCount();
|
||||
}
|
||||
|
||||
if (accFlags.isStatic()) {
|
||||
thisArg = null;
|
||||
} else {
|
||||
thisArg = InsnArg.reg(pos - 1, parentClass.getClassInfo().getType());
|
||||
thisArg = InsnArg.immutableReg(pos - 1, parentClass.getClassInfo().getType());
|
||||
thisArg.getTypedVar().setName("this");
|
||||
}
|
||||
|
||||
if (args.isEmpty()) {
|
||||
argsList = Collections.emptyList();
|
||||
return;
|
||||
}
|
||||
|
||||
argsList = new ArrayList<RegisterArg>(args.size());
|
||||
for (ArgType arg : args) {
|
||||
argsList.add(InsnArg.reg(pos, arg));
|
||||
argsList.add(InsnArg.immutableReg(pos, arg));
|
||||
pos += arg.getRegCount();
|
||||
}
|
||||
}
|
||||
@ -483,14 +477,6 @@ public class MethodNode extends LineAttrNode implements ILoadable {
|
||||
return accFlags;
|
||||
}
|
||||
|
||||
public void setSuperCall(ConstructorInsn insn) {
|
||||
this.superCall = insn;
|
||||
}
|
||||
|
||||
public ConstructorInsn getSuperCall() {
|
||||
return this.superCall;
|
||||
}
|
||||
|
||||
public IContainer getRegion() {
|
||||
return region;
|
||||
}
|
||||
|
@ -94,7 +94,6 @@ public class RootNode {
|
||||
|
||||
public ClassNode resolveClass(ClassInfo cls) {
|
||||
String fullName = cls.getFullName();
|
||||
ClassNode rCls = searchClassByName(fullName);
|
||||
return rCls;
|
||||
return searchClassByName(fullName);
|
||||
}
|
||||
}
|
||||
|
@ -211,8 +211,9 @@ public class DebugInfoParser {
|
||||
|
||||
private static void merge(InsnArg arg, LocalVar var) {
|
||||
if (arg != null && arg.isRegister()) {
|
||||
if (var.getRegNum() == ((RegisterArg) arg).getRegNum())
|
||||
arg.setTypedVar(var.getTypedVar());
|
||||
if (var.getRegNum() == ((RegisterArg) arg).getRegNum()) {
|
||||
arg.mergeDebugInfo(var);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ final class LocalVar extends RegisterArg {
|
||||
}
|
||||
TypedVar tv = new TypedVar(type);
|
||||
tv.setName(name);
|
||||
setTypedVar(tv);
|
||||
forceSetTypedVar(tv);
|
||||
}
|
||||
|
||||
public void start(int addr, int line) {
|
||||
|
@ -34,11 +34,9 @@ public class ClassModifier extends AbstractVisitor {
|
||||
if (af.isConstructor()
|
||||
&& af.isPublic()
|
||||
&& mth.getArguments(false).isEmpty()) {
|
||||
if (mth.getSuperCall() == null) {
|
||||
List<BlockNode> bb = mth.getBasicBlocks();
|
||||
if (bb.isEmpty() || allBlocksEmpty(bb)) {
|
||||
it.remove();
|
||||
}
|
||||
List<BlockNode> bb = mth.getBasicBlocks();
|
||||
if (bb.isEmpty() || allBlocksEmpty(bb)) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ public class CodeShrinker extends AbstractVisitor {
|
||||
InsnArg useInsnArg = selectOther(useList, result);
|
||||
InsnNode useInsn = useInsnArg.getParentInsn();
|
||||
if (useInsn == null) {
|
||||
LOG.debug("parent insn null in " + useInsnArg + " from " + insn + " mth: " + mth);
|
||||
LOG.debug("parent insn null: {}, mth: {}", insn, mth);
|
||||
} else if (useInsn != insn) {
|
||||
boolean wrap = false;
|
||||
// TODO
|
||||
@ -213,7 +213,7 @@ public class CodeShrinker extends AbstractVisitor {
|
||||
}
|
||||
RegisterArg fArg = new FieldArg(field, reg != null ? reg.getRegNum() : -1);
|
||||
if (reg != null) {
|
||||
fArg.setTypedVar(get.getArg(0).getTypedVar());
|
||||
fArg.replaceTypedVar(get.getArg(0));
|
||||
}
|
||||
if (wrapType == InsnType.ARITH) {
|
||||
ArithNode ar = (ArithNode) wrap;
|
||||
@ -269,9 +269,9 @@ public class CodeShrinker extends AbstractVisitor {
|
||||
|
||||
public static InsnArg inlineArgument(MethodNode mth, RegisterArg arg) {
|
||||
InsnNode assignInsn = arg.getAssignInsn();
|
||||
if (assignInsn == null)
|
||||
if (assignInsn == null) {
|
||||
return null;
|
||||
|
||||
}
|
||||
// recursively wrap all instructions
|
||||
List<RegisterArg> list = new ArrayList<RegisterArg>();
|
||||
List<RegisterArg> args = mth.getArguments(false);
|
||||
@ -281,17 +281,18 @@ public class CodeShrinker extends AbstractVisitor {
|
||||
assignInsn.getRegisterArgs(list);
|
||||
for (RegisterArg rarg : list) {
|
||||
InsnNode ai = rarg.getAssignInsn();
|
||||
if (ai != assignInsn && ai != null
|
||||
&& rarg.getParentInsn() != ai)
|
||||
if (ai != assignInsn && ai != null && ai != rarg.getParentInsn()) {
|
||||
rarg.wrapInstruction(ai);
|
||||
}
|
||||
}
|
||||
// remove method args
|
||||
if (list.size() != 0 && args.size() != 0) {
|
||||
list.removeAll(args);
|
||||
}
|
||||
i++;
|
||||
if (i > 1000)
|
||||
if (i > 1000) {
|
||||
throw new JadxRuntimeException("Can't inline arguments for: " + arg + " insn: " + assignInsn);
|
||||
}
|
||||
} while (!list.isEmpty());
|
||||
|
||||
return arg.wrapInstruction(assignInsn);
|
||||
|
@ -69,7 +69,6 @@ public class DotGraphVisitor extends AbstractVisitor {
|
||||
+ mth.getParentClass().getFullName() + "." + mth.getName()
|
||||
+ "(" + Utils.listToString(mth.getArguments(true)) + ") ")
|
||||
+ (attrs.length() == 0 ? "" : " | " + attrs)
|
||||
+ (mth.getSuperCall() != null ? "| Super call: " + escape(mth.getSuperCall().toString()) : "")
|
||||
+ "}\"];");
|
||||
|
||||
dot.startLine("MethodNode -> " + makeName(mth.getEnterBlock()) + ";");
|
||||
|
@ -30,8 +30,7 @@ public class EnumVisitor extends AbstractVisitor {
|
||||
|
||||
@Override
|
||||
public boolean visit(ClassNode cls) throws JadxException {
|
||||
if (!cls.getAccessFlags().isEnum()
|
||||
|| !cls.getSuperClass().getFullName().equals("java.lang.Enum"))
|
||||
if (!cls.isEnum())
|
||||
return true;
|
||||
|
||||
// collect enum fields, remove synthetic
|
||||
|
@ -52,6 +52,7 @@ public class ModVisitor extends AbstractVisitor {
|
||||
}
|
||||
|
||||
private void replaceStep(MethodNode mth) {
|
||||
ConstructorInsn superCall = null;
|
||||
for (BlockNode block : mth.getBasicBlocks()) {
|
||||
InstructionRemover remover = new InstructionRemover(block.getInstructions());
|
||||
|
||||
@ -75,14 +76,13 @@ public class ModVisitor extends AbstractVisitor {
|
||||
CodeShrinker.inlineArgument(mth, (RegisterArg) arg);
|
||||
}
|
||||
}
|
||||
if (!mth.getParentClass().getAccessFlags().isEnum())
|
||||
mth.setSuperCall(co);
|
||||
}
|
||||
remover.add(insn);
|
||||
} catch (JadxRuntimeException e) {
|
||||
// inline args into super fail
|
||||
LOG.warn("Can't inline args into super call: " + inv + ", mth: " + mth);
|
||||
replaceInsn(block, i, co);
|
||||
} finally {
|
||||
superCall = co;
|
||||
remover.add(insn);
|
||||
}
|
||||
} else if (co.isThis() && co.getArgsCount() == 0) {
|
||||
MethodNode defCo = mth.getParentClass()
|
||||
@ -138,6 +138,10 @@ public class ModVisitor extends AbstractVisitor {
|
||||
}
|
||||
remover.perform();
|
||||
}
|
||||
if (superCall != null && !mth.getParentClass().isEnum()) {
|
||||
List<InsnNode> insns = mth.getEnterBlock().getInstructions();
|
||||
insns.add(0, superCall);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -103,12 +103,12 @@ public class TypeResolver extends AbstractVisitor {
|
||||
|
||||
if (back) {
|
||||
if (er.getTypedVar() == null && sr.getTypedVar() != null) {
|
||||
er.replace(sr);
|
||||
er.replaceTypedVar(sr);
|
||||
changed = true;
|
||||
}
|
||||
} else {
|
||||
if (sr.getTypedVar() != null && er.getTypedVar() != null) {
|
||||
sr.replace(er);
|
||||
sr.replaceTypedVar(er);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import java.io.IOException;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static jadx.core.dex.instructions.args.ArgType.STRING;
|
||||
import static jadx.core.dex.instructions.args.ArgType.object;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@ -37,5 +38,7 @@ public class JadxClasspathTest {
|
||||
|
||||
assertFalse(ArgType.isCastNeeded(objExc, objThr));
|
||||
assertTrue(ArgType.isCastNeeded(objThr, objExc));
|
||||
|
||||
assertTrue(ArgType.isCastNeeded(ArgType.OBJECT, STRING));
|
||||
}
|
||||
}
|
||||
|
@ -9,8 +9,6 @@ import jadx.core.dex.nodes.MethodNode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
@ -25,11 +23,14 @@ public class TestDuplicateCast extends InternalJadxTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
//@Test
|
||||
public void test() {
|
||||
ClassNode cls = getClassNode(TestCls.class);
|
||||
MethodNode mth = getMethod(cls, "method");
|
||||
|
||||
String code = cls.getCode().toString();
|
||||
assertThat(code, containsString("return (int[]) o;"));
|
||||
|
||||
List<InsnNode> insns = mth.getBasicBlocks().get(1).getInstructions();
|
||||
assertEquals(insns.size(), 1);
|
||||
InsnNode insnNode = insns.get(0);
|
||||
@ -38,8 +39,5 @@ public class TestDuplicateCast extends InternalJadxTest {
|
||||
InsnNode wrapInsn = ((InsnWrapArg) insnNode.getArg(0)).getWrapInsn();
|
||||
assertEquals(InsnType.CHECK_CAST, wrapInsn.getType());
|
||||
assertFalse(wrapInsn.getArg(0).isInsnWrap());
|
||||
|
||||
String code = cls.getCode().toString();
|
||||
assertThat(code, containsString("return (int[]) o;"));
|
||||
}
|
||||
}
|
||||
|
@ -57,5 +57,10 @@ public class TestRedundantBrackets extends InternalJadxTest {
|
||||
|
||||
assertThat(code, containsString("a[1] = n * 2;"));
|
||||
assertThat(code, containsString("a[n - 1] = 1;"));
|
||||
|
||||
// argument type not changed to String
|
||||
assertThat(code, containsString("public int method2(Object obj) {"));
|
||||
// cast not eliminated
|
||||
assertThat(code, containsString("((String) obj).length()"));
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ public class TestTypeResolver extends AbstractTest {
|
||||
public static class TestTernaryInSuper extends TestTypeResolver {
|
||||
|
||||
public TestTernaryInSuper(int c) {
|
||||
super(c > 0 ? c : -c, 1);
|
||||
// super(c > 0 ? c : -c, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user