diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/PrimitiveType.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/PrimitiveType.java index 9a293cc31..da4a5874a 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/PrimitiveType.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/PrimitiveType.java @@ -29,22 +29,6 @@ public enum PrimitiveType { return longName; } - public static PrimitiveType getWidest(PrimitiveType a, PrimitiveType b) { - if (a.ordinal() > b.ordinal()) { - return a; - } else { - return b; - } - } - - public static PrimitiveType getSmaller(PrimitiveType a, PrimitiveType b) { - if (a.ordinal() < b.ordinal()) { - return a; - } else { - return b; - } - } - @Override public String toString() { return longName; diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/RegisterArg.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/RegisterArg.java index f035224f0..cbeb8fcfb 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/RegisterArg.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/RegisterArg.java @@ -7,6 +7,7 @@ import org.jetbrains.annotations.Nullable; import jadx.core.dex.attributes.AFlag; import jadx.core.dex.nodes.InsnNode; +import jadx.core.dex.nodes.MethodNode; import jadx.core.utils.exceptions.JadxRuntimeException; public class RegisterArg extends InsnArg implements Named { @@ -127,15 +128,17 @@ public class RegisterArg extends InsnArg implements Named { @Override public RegisterArg duplicate() { - return duplicate(getRegNum(), sVar); + return duplicate(getRegNum(), getInitType(), sVar); } public RegisterArg duplicate(ArgType initType) { return duplicate(getRegNum(), initType, sVar); } - public RegisterArg duplicate(@Nullable SSAVar ssaVar) { - return duplicate(getRegNum(), ssaVar); + public RegisterArg duplicateWithNewSSAVar(MethodNode mth) { + RegisterArg duplicate = duplicate(regNum, getInitType(), null); + mth.makeNewSVar(duplicate); + return duplicate; } public RegisterArg duplicate(int regNum, @Nullable SSAVar sVar) { diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java index b062702df..245bc6605 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java @@ -201,23 +201,27 @@ public class ModVisitor extends AbstractVisitor { if (castArg.getType() == ArgType.BOOLEAN) { ArgType type = insn.getResult().getType(); if (type.isPrimitive()) { - InsnArg zero = new LiteralArg(0, type); - long litVal = 1; - if (type == ArgType.DOUBLE) { - litVal = DOUBLE_TO_BITS; - } else if (type == ArgType.FLOAT) { - litVal = FLOAT_TO_BITS; - } - InsnArg one = new LiteralArg(litVal, type); - - IfNode ifNode = new IfNode(IfOp.EQ, -1, castArg, LiteralArg.TRUE); - IfCondition condition = IfCondition.fromIfNode(ifNode); - TernaryInsn ternary = new TernaryInsn(condition, insn.getResult(), one, zero); + TernaryInsn ternary = makeBooleanConvertInsn(insn.getResult(), castArg, type); replaceInsn(mth, block, i, ternary); } } } + public static TernaryInsn makeBooleanConvertInsn(RegisterArg result, InsnArg castArg, ArgType type) { + InsnArg zero = new LiteralArg(0, type); + long litVal = 1; + if (type == ArgType.DOUBLE) { + litVal = DOUBLE_TO_BITS; + } else if (type == ArgType.FLOAT) { + litVal = FLOAT_TO_BITS; + } + InsnArg one = new LiteralArg(litVal, type); + + IfNode ifNode = new IfNode(IfOp.EQ, -1, castArg, LiteralArg.TRUE); + IfCondition condition = IfCondition.fromIfNode(ifNode); + return new TernaryInsn(condition, result, one, zero); + } + private void replaceConstInAnnotations(ClassNode cls) { if (cls.root().getArgs().isReplaceConsts()) { replaceConstsInAnnotationForAttrNode(cls, cls); diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeCompare.java b/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeCompare.java index 45480b9f5..941fd3099 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeCompare.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeCompare.java @@ -84,8 +84,13 @@ public class TypeCompare { } } if (firstPrimitive && secondPrimitive) { - int comparePrimitives = first.getPrimitiveType().compareTo(second.getPrimitiveType()); - return comparePrimitives > 0 ? WIDER : NARROW; + PrimitiveType firstPrimitiveType = first.getPrimitiveType(); + PrimitiveType secondPrimitiveType = second.getPrimitiveType(); + if (firstPrimitiveType == PrimitiveType.BOOLEAN + || secondPrimitiveType == PrimitiveType.BOOLEAN) { + return CONFLICT; + } + return firstPrimitiveType.compareTo(secondPrimitiveType) > 0 ? WIDER : NARROW; } LOG.warn("Type compare function not complete, can't compare {} and {}", first, second); diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeInferenceVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeInferenceVisitor.java index c408f0634..863eebbd0 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeInferenceVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeInferenceVisitor.java @@ -1,11 +1,13 @@ package jadx.core.dex.visitors.typeinference; import java.util.ArrayList; +import java.util.Arrays; import java.util.LinkedHashSet; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.function.Function; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; @@ -23,12 +25,12 @@ import jadx.core.dex.instructions.InvokeNode; import jadx.core.dex.instructions.InvokeType; import jadx.core.dex.instructions.PhiInsn; import jadx.core.dex.instructions.args.ArgType; -import jadx.core.dex.instructions.args.CodeVar; import jadx.core.dex.instructions.args.InsnArg; import jadx.core.dex.instructions.args.LiteralArg; import jadx.core.dex.instructions.args.PrimitiveType; import jadx.core.dex.instructions.args.RegisterArg; import jadx.core.dex.instructions.args.SSAVar; +import jadx.core.dex.instructions.mods.TernaryInsn; import jadx.core.dex.nodes.BlockNode; import jadx.core.dex.nodes.IMethodDetails; import jadx.core.dex.nodes.InsnNode; @@ -40,9 +42,11 @@ import jadx.core.dex.visitors.AttachMethodDetails; import jadx.core.dex.visitors.ConstInlineVisitor; import jadx.core.dex.visitors.InitCodeVariables; import jadx.core.dex.visitors.JadxVisitor; +import jadx.core.dex.visitors.ModVisitor; import jadx.core.dex.visitors.blocksmaker.BlockSplitter; import jadx.core.dex.visitors.ssa.SSATransform; import jadx.core.utils.BlockUtils; +import jadx.core.utils.InsnList; import jadx.core.utils.InsnUtils; import jadx.core.utils.Utils; @@ -60,11 +64,20 @@ public final class TypeInferenceVisitor extends AbstractVisitor { private RootNode root; private TypeUpdate typeUpdate; + private List> resolvers; @Override public void init(RootNode root) { this.root = root; this.typeUpdate = root.getTypeUpdate(); + this.resolvers = Arrays.asList( + this::runTypePropagation, + this::tryDeduceTypes, + this::trySplitConstInsns, + this::tryToFixIncompatiblePrimitives, + this::tryInsertAdditionalMove, + this::runMultiVariableSearch, + this::tryRemoveGenerics); } @Override @@ -75,30 +88,24 @@ public final class TypeInferenceVisitor extends AbstractVisitor { if (Consts.DEBUG_TYPE_INFERENCE) { LOG.info("Start type inference in method: {}", mth); } - if (resolveTypes(mth)) { - for (SSAVar var : new ArrayList<>(mth.getSVars())) { - processIncompatiblePrimitives(mth, var); + for (Function resolver : resolvers) { + if (resolver.apply(mth) && checkTypes(mth)) { + return; } } } - private boolean resolveTypes(MethodNode mth) { - if (runTypePropagation(mth)) { - return true; + /** + * Check if all types resolved + */ + private boolean checkTypes(MethodNode mth) { + for (SSAVar var : mth.getSVars()) { + ArgType type = var.getTypeInfo().getType(); + if (!type.isTypeKnown()) { + return false; + } } - if (trySplitConstInsns(mth)) { - return true; - } - if (tryInsertAdditionalMove(mth)) { - return true; - } - if (runMultiVariableSearch(mth)) { - return true; - } - if (tryRemoveGenerics(mth)) { - return true; - } - return false; + return true; } /** @@ -114,23 +121,12 @@ public final class TypeInferenceVisitor extends AbstractVisitor { // start initial type propagation ssaVars.forEach(var -> setImmutableType(mth, var)); ssaVars.forEach(var -> setBestType(mth, var)); - - // try other types if type is still unknown - boolean resolved = true; - for (SSAVar var : ssaVars) { - ArgType type = var.getTypeInfo().getType(); - if (!type.isTypeKnown() - && !var.isTypeImmutable() - && !tryDeduceType(mth, var, type)) { - resolved = false; - } - } - return resolved; + return true; } private boolean runMultiVariableSearch(MethodNode mth) { - TypeSearch typeSearch = new TypeSearch(mth); try { + TypeSearch typeSearch = new TypeSearch(mth); if (!typeSearch.run()) { mth.addWarnComment("Multi-variable type inference failed"); } @@ -359,13 +355,30 @@ public final class TypeInferenceVisitor extends AbstractVisitor { return list; } - private boolean tryDeduceType(MethodNode mth, SSAVar var, @Nullable ArgType type) { + private boolean tryDeduceTypes(MethodNode mth) { + boolean fixed = false; + for (SSAVar ssaVar : mth.getSVars()) { + if (deduceType(mth, ssaVar)) { + fixed = true; + } + } + return fixed; + } + + private boolean deduceType(MethodNode mth, SSAVar var) { + if (var.isTypeImmutable()) { + return false; + } + ArgType type = var.getTypeInfo().getType(); + if (type.isTypeKnown()) { + return false; + } // try best type from bounds again if (setBestType(mth, var)) { return true; } // try all possible types (useful for primitives) - if (type != null && tryPossibleTypes(mth, var, type)) { + if (tryPossibleTypes(mth, var, type)) { return true; } // for objects try super types @@ -379,7 +392,8 @@ public final class TypeInferenceVisitor extends AbstractVisitor { boolean resolved = true; for (SSAVar var : mth.getSVars()) { ArgType type = var.getTypeInfo().getType(); - if (!type.isTypeKnown() && !var.isTypeImmutable() + if (!type.isTypeKnown() + && !var.isTypeImmutable() && !tryRawType(mth, var)) { resolved = false; } @@ -462,44 +476,47 @@ public final class TypeInferenceVisitor extends AbstractVisitor { } private boolean tryInsertAdditionalMove(MethodNode mth) { - boolean moveAdded = false; + int insnsAdded = 0; for (SSAVar var : new ArrayList<>(mth.getSVars())) { - if (tryInsertAdditionalInsn(mth, var)) { - moveAdded = true; - } + insnsAdded += tryInsertAdditionalInsn(mth, var); } - if (!moveAdded) { + if (insnsAdded == 0) { return false; } + mth.addDebugComment("Additional " + insnsAdded + " move instruction added to help type inference"); + InitCodeVariables.rerun(mth); - return runTypePropagation(mth); + if (runTypePropagation(mth) && checkTypes(mth)) { + return true; + } + return tryDeduceTypes(mth); } /** * Add MOVE instruction before PHI in bound blocks to make 'soft' type link. * This allows to use different types in blocks merged by PHI. */ - private boolean tryInsertAdditionalInsn(MethodNode mth, SSAVar var) { + private int tryInsertAdditionalInsn(MethodNode mth, SSAVar var) { if (var.getTypeInfo().getType().isTypeKnown()) { - return false; + return 0; } List usedInPhiList = var.getUsedInPhi(); if (usedInPhiList.isEmpty()) { - return false; + return 0; } InsnNode assignInsn = var.getAssign().getAssignInsn(); if (assignInsn != null) { InsnType assignType = assignInsn.getType(); if (assignType == InsnType.CONST) { - return false; + return 0; } if (assignType == InsnType.MOVE && var.getUseCount() == 1) { - return false; + return 0; } } for (PhiInsn phiInsn : usedInPhiList) { if (!insertMoveForPhi(mth, phiInsn, var, false)) { - return false; + return 0; } } @@ -507,8 +524,7 @@ public final class TypeInferenceVisitor extends AbstractVisitor { for (PhiInsn phiInsn : usedInPhiList) { insertMoveForPhi(mth, phiInsn, var, true); } - mth.addComment("JADX INFO: additional move instructions added (" + usedInPhiList.size() + ") to help type inference"); - return true; + return usedInPhiList.size(); } private boolean insertMoveForPhi(MethodNode mth, PhiInsn phiInsn, SSAVar var, boolean apply) { @@ -583,42 +599,87 @@ public final class TypeInferenceVisitor extends AbstractVisitor { return false; } - private void processIncompatiblePrimitives(MethodNode mth, SSAVar var) { - if (var.getTypeInfo().getType() == ArgType.BOOLEAN) { - for (ITypeBound bound : var.getTypeInfo().getBounds()) { - if (bound.getBound() == BoundEnum.USE - && bound.getType().isPrimitive() - && bound.getType() != ArgType.BOOLEAN - && bound.getArg() != null) { - InsnNode insn = bound.getArg().getParentInsn(); - if (insn == null || insn.getType() == InsnType.CAST) { - continue; - } - - IndexInsnNode castNode = new IndexInsnNode(InsnType.CAST, bound.getType(), 1); - castNode.addArg(bound.getArg()); - castNode.setResult(InsnArg.reg(bound.getArg().getRegNum(), bound.getType())); - - SSAVar newVar = mth.makeNewSVar(castNode.getResult()); - CodeVar codeVar = new CodeVar(); - codeVar.setType(bound.getType()); - newVar.setCodeVar(codeVar); - newVar.getTypeInfo().setType(bound.getType()); - - for (int i = insn.getArgsCount() - 1; i >= 0; i--) { - if (insn.getArg(i) == bound.getArg()) { - insn.setArg(i, castNode.getResult().duplicate()); - break; - } - } - - BlockNode blockNode = BlockUtils.getBlockByInsn(mth, insn); - if (blockNode != null) { - List insnList = blockNode.getInstructions(); - insnList.add(insnList.indexOf(insn), castNode); - } - } + private boolean tryToFixIncompatiblePrimitives(MethodNode mth) { + boolean fixed = false; + for (SSAVar var : new ArrayList<>(mth.getSVars())) { + if (processIncompatiblePrimitives(mth, var)) { + fixed = true; } } + if (!fixed) { + return false; + } + InitCodeVariables.rerun(mth); + return runTypePropagation(mth); + } + + private boolean processIncompatiblePrimitives(MethodNode mth, SSAVar var) { + TypeInfo typeInfo = var.getTypeInfo(); + if (typeInfo.getType().isTypeKnown()) { + return false; + } + boolean boolAssign = false; + for (ITypeBound bound : typeInfo.getBounds()) { + if (bound.getBound() == BoundEnum.ASSIGN && bound.getType().equals(ArgType.BOOLEAN)) { + boolAssign = true; + break; + } + } + if (!boolAssign) { + return false; + } + + boolean fixed = false; + for (ITypeBound bound : typeInfo.getBounds()) { + if (bound.getBound() == BoundEnum.USE + && fixBooleanUsage(mth, bound)) { + fixed = true; + } + } + return fixed; + } + + private boolean fixBooleanUsage(MethodNode mth, ITypeBound bound) { + ArgType boundType = bound.getType(); + if (!boundType.isPrimitive() || boundType == ArgType.BOOLEAN) { + return false; + } + RegisterArg boundArg = bound.getArg(); + if (boundArg == null) { + return false; + } + InsnNode insn = boundArg.getParentInsn(); + if (insn == null) { + return false; + } + BlockNode blockNode = BlockUtils.getBlockByInsn(mth, insn); + if (blockNode == null) { + return false; + } + List insnList = blockNode.getInstructions(); + int insnIndex = InsnList.getIndex(insnList, insn); + if (insnIndex == -1) { + return false; + } + if (insn.getType() == InsnType.CAST) { + // replace cast + ArgType type = (ArgType) ((IndexInsnNode) insn).getIndex(); + TernaryInsn convertInsn = prepareBooleanConvertInsn(insn.getResult(), boundArg, type); + BlockUtils.replaceInsn(mth, blockNode, insnIndex, convertInsn); + } else { + // insert before insn + RegisterArg resultArg = boundArg.duplicateWithNewSSAVar(mth); + TernaryInsn convertInsn = prepareBooleanConvertInsn(resultArg, boundArg, boundType); + insnList.add(insnIndex, convertInsn); + insn.replaceArg(bound.getArg(), convertInsn.getResult().duplicate()); + } + return true; + } + + private TernaryInsn prepareBooleanConvertInsn(RegisterArg resultArg, RegisterArg boundArg, ArgType useType) { + RegisterArg useArg = boundArg.getSVar().getAssign().duplicate(); + TernaryInsn convertInsn = ModVisitor.makeBooleanConvertInsn(resultArg, useArg, useType); + convertInsn.add(AFlag.SYNTHETIC); + return convertInsn; } } diff --git a/jadx-core/src/test/java/jadx/core/dex/visitors/typeinference/TypeCompareTest.java b/jadx-core/src/test/java/jadx/core/dex/visitors/typeinference/TypeCompareTest.java index 220f30c61..378c587d9 100644 --- a/jadx-core/src/test/java/jadx/core/dex/visitors/typeinference/TypeCompareTest.java +++ b/jadx-core/src/test/java/jadx/core/dex/visitors/typeinference/TypeCompareTest.java @@ -23,6 +23,7 @@ import static jadx.core.dex.instructions.args.ArgType.INT; import static jadx.core.dex.instructions.args.ArgType.NARROW; import static jadx.core.dex.instructions.args.ArgType.NARROW_INTEGRAL; import static jadx.core.dex.instructions.args.ArgType.OBJECT; +import static jadx.core.dex.instructions.args.ArgType.SHORT; import static jadx.core.dex.instructions.args.ArgType.STRING; import static jadx.core.dex.instructions.args.ArgType.UNKNOWN; import static jadx.core.dex.instructions.args.ArgType.UNKNOWN_ARRAY; @@ -52,8 +53,6 @@ public class TypeCompareTest { public void compareTypes() { firstIsNarrow(INT, UNKNOWN); - firstIsNarrow(BOOLEAN, INT); - firstIsNarrow(array(UNKNOWN), UNKNOWN); firstIsNarrow(array(UNKNOWN), NARROW); } @@ -62,7 +61,9 @@ public class TypeCompareTest { public void comparePrimitives() { check(INT, UNKNOWN_OBJECT, TypeCompareEnum.CONFLICT); check(INT, OBJECT, TypeCompareEnum.CONFLICT); + check(INT, BOOLEAN, TypeCompareEnum.CONFLICT); check(INT, CHAR, TypeCompareEnum.WIDER); + check(INT, SHORT, TypeCompareEnum.WIDER); firstIsNarrow(CHAR, NARROW_INTEGRAL); firstIsNarrow(array(CHAR), UNKNOWN_OBJECT); diff --git a/jadx-core/src/test/java/jadx/tests/integration/conditions/TestBooleanToByte.java b/jadx-core/src/test/java/jadx/tests/integration/conditions/TestBooleanToByte.java index 016e452b1..dd2602b81 100644 --- a/jadx-core/src/test/java/jadx/tests/integration/conditions/TestBooleanToByte.java +++ b/jadx-core/src/test/java/jadx/tests/integration/conditions/TestBooleanToByte.java @@ -2,16 +2,14 @@ package jadx.tests.integration.conditions; import org.junit.jupiter.api.Test; -import jadx.core.dex.nodes.ClassNode; import jadx.tests.api.SmaliTest; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; +import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat; public class TestBooleanToByte extends SmaliTest { // @formatter:off - /** + /* private boolean showConsent; public void write(byte b) { @@ -24,9 +22,8 @@ public class TestBooleanToByte extends SmaliTest { // @formatter:on @Test public void test() { - ClassNode cls = getClassNodeFromSmaliWithPath("conditions", "TestBooleanToByte"); - String code = cls.getCode().toString(); - - assertThat(code, containsString("write(this.showConsent ? (byte) 1 : 0);")); + assertThat(getClassNodeFromSmali()) + .code() + .containsOne("write(this.showConsent ? (byte) 1 : 0);"); } } diff --git a/jadx-core/src/test/java/jadx/tests/integration/conditions/TestBooleanToChar.java b/jadx-core/src/test/java/jadx/tests/integration/conditions/TestBooleanToChar.java index d9c03f28c..f13060e59 100644 --- a/jadx-core/src/test/java/jadx/tests/integration/conditions/TestBooleanToChar.java +++ b/jadx-core/src/test/java/jadx/tests/integration/conditions/TestBooleanToChar.java @@ -2,16 +2,14 @@ package jadx.tests.integration.conditions; import org.junit.jupiter.api.Test; -import jadx.core.dex.nodes.ClassNode; import jadx.tests.api.SmaliTest; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; +import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat; public class TestBooleanToChar extends SmaliTest { // @formatter:off - /** + /* private boolean showConsent; public void write(char b) { @@ -20,13 +18,12 @@ public class TestBooleanToChar extends SmaliTest { public void writeToParcel(TestBooleanToChar testBooleanToChar) { testBooleanToChar.write(this.showConsent ? (char) 1 : 0); } - */ + */ // @formatter:on @Test public void test() { - ClassNode cls = getClassNodeFromSmaliWithPath("conditions", "TestBooleanToChar"); - String code = cls.getCode().toString(); - - assertThat(code, containsString("write(this.showConsent ? (char) 1 : 0);")); + assertThat(getClassNodeFromSmali()) + .code() + .containsOne("write(this.showConsent ? (char) 1 : 0);"); } } diff --git a/jadx-core/src/test/java/jadx/tests/integration/conditions/TestBooleanToDouble.java b/jadx-core/src/test/java/jadx/tests/integration/conditions/TestBooleanToDouble.java index 33deaa9ce..7c77b0ee8 100644 --- a/jadx-core/src/test/java/jadx/tests/integration/conditions/TestBooleanToDouble.java +++ b/jadx-core/src/test/java/jadx/tests/integration/conditions/TestBooleanToDouble.java @@ -2,16 +2,14 @@ package jadx.tests.integration.conditions; import org.junit.jupiter.api.Test; -import jadx.core.dex.nodes.ClassNode; import jadx.tests.api.SmaliTest; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; +import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat; public class TestBooleanToDouble extends SmaliTest { // @formatter:off - /** + /* private boolean showConsent; public void write(double d) { @@ -24,9 +22,8 @@ public class TestBooleanToDouble extends SmaliTest { // @formatter:on @Test public void test() { - ClassNode cls = getClassNodeFromSmaliWithPath("conditions", "TestBooleanToDouble"); - String code = cls.getCode().toString(); - - assertThat(code, containsString("write(this.showConsent ? 1.0d : 0.0d);")); + assertThat(getClassNodeFromSmali()) + .code() + .containsOne("write(this.showConsent ? 1.0d : 0.0d);"); } } diff --git a/jadx-core/src/test/java/jadx/tests/integration/conditions/TestBooleanToFloat.java b/jadx-core/src/test/java/jadx/tests/integration/conditions/TestBooleanToFloat.java index d53cc5ce0..a395265c5 100644 --- a/jadx-core/src/test/java/jadx/tests/integration/conditions/TestBooleanToFloat.java +++ b/jadx-core/src/test/java/jadx/tests/integration/conditions/TestBooleanToFloat.java @@ -2,16 +2,14 @@ package jadx.tests.integration.conditions; import org.junit.jupiter.api.Test; -import jadx.core.dex.nodes.ClassNode; import jadx.tests.api.SmaliTest; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; +import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat; public class TestBooleanToFloat extends SmaliTest { // @formatter:off - /** + /* private boolean showConsent; public void write(float f) { @@ -24,9 +22,8 @@ public class TestBooleanToFloat extends SmaliTest { // @formatter:on @Test public void test() { - ClassNode cls = getClassNodeFromSmaliWithPath("conditions", "TestBooleanToFloat"); - String code = cls.getCode().toString(); - - assertThat(code, containsString("write(this.showConsent ? 1.0f : 0.0f);")); + assertThat(getClassNodeFromSmali()) + .code() + .containsOne("write(this.showConsent ? 1.0f : 0.0f);"); } } diff --git a/jadx-core/src/test/java/jadx/tests/integration/conditions/TestBooleanToInt.java b/jadx-core/src/test/java/jadx/tests/integration/conditions/TestBooleanToInt.java index ee75fc9f4..440f6e246 100644 --- a/jadx-core/src/test/java/jadx/tests/integration/conditions/TestBooleanToInt.java +++ b/jadx-core/src/test/java/jadx/tests/integration/conditions/TestBooleanToInt.java @@ -2,16 +2,14 @@ package jadx.tests.integration.conditions; import org.junit.jupiter.api.Test; -import jadx.core.dex.nodes.ClassNode; import jadx.tests.api.SmaliTest; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; +import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat; public class TestBooleanToInt extends SmaliTest { - //@formatter:off - /** + // @formatter:off + /* private boolean showConsent; public void write(int b) { @@ -21,12 +19,11 @@ public class TestBooleanToInt extends SmaliTest { testBooleanToInt.write(this.showConsent ? 1 : 0); } */ - //@formatter:on + // @formatter:on @Test public void test() { - ClassNode cls = getClassNodeFromSmaliWithPath("conditions", "TestBooleanToInt"); - String code = cls.getCode().toString(); - - assertThat(code, containsString("write(this.showConsent ? 1 : 0);")); + assertThat(getClassNodeFromSmali()) + .code() + .containsOne("write(this.showConsent ? 1 : 0);"); } } diff --git a/jadx-core/src/test/java/jadx/tests/integration/conditions/TestBooleanToLong.java b/jadx-core/src/test/java/jadx/tests/integration/conditions/TestBooleanToLong.java index 7df5b9994..263db0aff 100644 --- a/jadx-core/src/test/java/jadx/tests/integration/conditions/TestBooleanToLong.java +++ b/jadx-core/src/test/java/jadx/tests/integration/conditions/TestBooleanToLong.java @@ -2,16 +2,14 @@ package jadx.tests.integration.conditions; import org.junit.jupiter.api.Test; -import jadx.core.dex.nodes.ClassNode; import jadx.tests.api.SmaliTest; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; +import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat; public class TestBooleanToLong extends SmaliTest { // @formatter:off - /** + /* private boolean showConsent; public void write(long j) { @@ -24,9 +22,8 @@ public class TestBooleanToLong extends SmaliTest { // @formatter:on @Test public void test() { - ClassNode cls = getClassNodeFromSmaliWithPath("conditions", "TestBooleanToLong"); - String code = cls.getCode().toString(); - - assertThat(code, containsString("write(this.showConsent ? 1 : 0);")); + assertThat(getClassNodeFromSmali()) + .code() + .containsOne("write(this.showConsent ? 1 : 0);"); } } diff --git a/jadx-core/src/test/java/jadx/tests/integration/conditions/TestBooleanToShort.java b/jadx-core/src/test/java/jadx/tests/integration/conditions/TestBooleanToShort.java index e2fd2afff..a330c196c 100644 --- a/jadx-core/src/test/java/jadx/tests/integration/conditions/TestBooleanToShort.java +++ b/jadx-core/src/test/java/jadx/tests/integration/conditions/TestBooleanToShort.java @@ -2,16 +2,14 @@ package jadx.tests.integration.conditions; import org.junit.jupiter.api.Test; -import jadx.core.dex.nodes.ClassNode; import jadx.tests.api.SmaliTest; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; +import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat; public class TestBooleanToShort extends SmaliTest { // @formatter:off - /** + /* private boolean showConsent; public void write(short b) { @@ -24,9 +22,8 @@ public class TestBooleanToShort extends SmaliTest { // @formatter:on @Test public void test() { - ClassNode cls = getClassNodeFromSmaliWithPath("conditions", "TestBooleanToShort"); - String code = cls.getCode().toString(); - - assertThat(code, containsString("write(this.showConsent ? (short) 1 : 0);")); + assertThat(getClassNodeFromSmali()) + .code() + .containsOne("write(this.showConsent ? (short) 1 : 0);"); } } diff --git a/jadx-core/src/test/java/jadx/tests/integration/others/TestIssue13a.java b/jadx-core/src/test/java/jadx/tests/integration/others/TestIssue13a.java index 0a32fc27b..c070f75dd 100644 --- a/jadx-core/src/test/java/jadx/tests/integration/others/TestIssue13a.java +++ b/jadx-core/src/test/java/jadx/tests/integration/others/TestIssue13a.java @@ -20,7 +20,7 @@ public class TestIssue13a extends IntegrationTest { private static final String TAG = "Parcel"; private static final Map>> M_CREATORS = new HashMap<>(); - @SuppressWarnings("unchecked") + @SuppressWarnings({ "unchecked", "ConstantConditions", "Java8MapApi", "rawtypes" }) public final T test(ClassLoader loader) { String name = readString(); if (name == null) { diff --git a/jadx-core/src/test/java/jadx/tests/integration/types/TestTypeResolver10.java b/jadx-core/src/test/java/jadx/tests/integration/types/TestTypeResolver10.java index feb797334..7a4510d20 100644 --- a/jadx-core/src/test/java/jadx/tests/integration/types/TestTypeResolver10.java +++ b/jadx-core/src/test/java/jadx/tests/integration/types/TestTypeResolver10.java @@ -12,7 +12,7 @@ import static org.hamcrest.Matchers.not; public class TestTypeResolver10 extends SmaliTest { - /** + /* * Method argument assigned with different types in separate branches */ diff --git a/jadx-core/src/test/smali/conditions/TestBooleanToByte.smali b/jadx-core/src/test/smali/conditions/TestBooleanToByte.smali index b1ec3d236..74b09f764 100644 --- a/jadx-core/src/test/smali/conditions/TestBooleanToByte.smali +++ b/jadx-core/src/test/smali/conditions/TestBooleanToByte.smali @@ -1,16 +1,16 @@ -.class public LTestBooleanToByte; +.class public Lconditions/TestBooleanToByte; .super Ljava/lang/Object; .field private showConsent:Z -.method public writeToParcel(LTestBooleanToByte;)V +.method public writeToParcel(Lconditions/TestBooleanToByte;)V .locals 0 - iget-boolean p1, p0, LTestBooleanToByte;->showConsent:Z + iget-boolean p1, p0, Lconditions/TestBooleanToByte;->showConsent:Z int-to-byte p1, p1 - invoke-virtual {p0, p1}, LTestBooleanToByte;->write(B)V + invoke-virtual {p0, p1}, Lconditions/TestBooleanToByte;->write(B)V return-void .end method diff --git a/jadx-core/src/test/smali/conditions/TestBooleanToChar.smali b/jadx-core/src/test/smali/conditions/TestBooleanToChar.smali index 5564b58f5..1743a24fc 100644 --- a/jadx-core/src/test/smali/conditions/TestBooleanToChar.smali +++ b/jadx-core/src/test/smali/conditions/TestBooleanToChar.smali @@ -1,16 +1,16 @@ -.class public LTestBooleanToChar; +.class public Lconditions/TestBooleanToChar; .super Ljava/lang/Object; .field private showConsent:Z -.method public writeToParcel(LTestBooleanToChar;)V +.method public writeToParcel(Lconditions/TestBooleanToChar;)V .locals 0 - iget-boolean p1, p0, LTestBooleanToChar;->showConsent:Z + iget-boolean p1, p0, Lconditions/TestBooleanToChar;->showConsent:Z int-to-char p1, p1 - invoke-virtual {p0, p1}, LTestBooleanToChar;->write(C)V + invoke-virtual {p0, p1}, Lconditions/TestBooleanToChar;->write(C)V return-void .end method diff --git a/jadx-core/src/test/smali/conditions/TestBooleanToDouble.smali b/jadx-core/src/test/smali/conditions/TestBooleanToDouble.smali index 2006cec2e..c828221b7 100644 --- a/jadx-core/src/test/smali/conditions/TestBooleanToDouble.smali +++ b/jadx-core/src/test/smali/conditions/TestBooleanToDouble.smali @@ -1,16 +1,16 @@ -.class public LTestBooleanToDouble; +.class public Lconditions/TestBooleanToDouble; .super Ljava/lang/Object; .field private showConsent:Z -.method public writeToParcel(LTestBooleanToDouble;)V +.method public writeToParcel(Lconditions/TestBooleanToDouble;)V .locals 0 - iget-boolean p1, p0, LTestBooleanToDouble;->showConsent:Z + iget-boolean p1, p0, Lconditions/TestBooleanToDouble;->showConsent:Z int-to-double p1, p1 - invoke-virtual {p0, p1}, LTestBooleanToDouble;->write(D)V + invoke-virtual {p0, p1}, Lconditions/TestBooleanToDouble;->write(D)V return-void .end method diff --git a/jadx-core/src/test/smali/conditions/TestBooleanToFloat.smali b/jadx-core/src/test/smali/conditions/TestBooleanToFloat.smali index 268e3984b..9d0ea9b6f 100644 --- a/jadx-core/src/test/smali/conditions/TestBooleanToFloat.smali +++ b/jadx-core/src/test/smali/conditions/TestBooleanToFloat.smali @@ -1,16 +1,16 @@ -.class public LTestBooleanToFloat; +.class public Lconditions/TestBooleanToFloat; .super Ljava/lang/Object; .field private showConsent:Z -.method public writeToParcel(LTestBooleanToFloat;)V +.method public writeToParcel(Lconditions/TestBooleanToFloat;)V .locals 0 - iget-boolean p1, p0, LTestBooleanToFloat;->showConsent:Z + iget-boolean p1, p0, Lconditions/TestBooleanToFloat;->showConsent:Z int-to-float p1, p1 - invoke-virtual {p0, p1}, LTestBooleanToFloat;->write(F)V + invoke-virtual {p0, p1}, Lconditions/TestBooleanToFloat;->write(F)V return-void .end method diff --git a/jadx-core/src/test/smali/conditions/TestBooleanToInt.smali b/jadx-core/src/test/smali/conditions/TestBooleanToInt.smali index 63caa05d2..e6d491dbb 100644 --- a/jadx-core/src/test/smali/conditions/TestBooleanToInt.smali +++ b/jadx-core/src/test/smali/conditions/TestBooleanToInt.smali @@ -1,14 +1,14 @@ -.class public LTestBooleanToInt; +.class public Lconditions/TestBooleanToInt; .super Ljava/lang/Object; .field private showConsent:Z -.method public writeToParcel(LTestBooleanToInt;)V +.method public writeToParcel(Lconditions/TestBooleanToInt;)V .locals 0 - iget-boolean p1, p0, LTestBooleanToInt;->showConsent:Z + iget-boolean p1, p0, Lconditions/TestBooleanToInt;->showConsent:Z - invoke-virtual {p0, p1}, LTestBooleanToInt;->write(I)V + invoke-virtual {p0, p1}, Lconditions/TestBooleanToInt;->write(I)V return-void .end method diff --git a/jadx-core/src/test/smali/conditions/TestBooleanToLong.smali b/jadx-core/src/test/smali/conditions/TestBooleanToLong.smali index f997fd49a..8b6a53569 100644 --- a/jadx-core/src/test/smali/conditions/TestBooleanToLong.smali +++ b/jadx-core/src/test/smali/conditions/TestBooleanToLong.smali @@ -1,16 +1,16 @@ -.class public LTestBooleanToLong; +.class public Lconditions/TestBooleanToLong; .super Ljava/lang/Object; .field private showConsent:Z -.method public writeToParcel(LTestBooleanToLong;)V +.method public writeToParcel(Lconditions/TestBooleanToLong;)V .locals 0 - iget-boolean p1, p0, LTestBooleanToLong;->showConsent:Z + iget-boolean p1, p0, Lconditions/TestBooleanToLong;->showConsent:Z int-to-long p1, p1 - invoke-virtual {p0, p1}, LTestBooleanToLong;->write(J)V + invoke-virtual {p0, p1}, Lconditions/TestBooleanToLong;->write(J)V return-void .end method diff --git a/jadx-core/src/test/smali/conditions/TestBooleanToShort.smali b/jadx-core/src/test/smali/conditions/TestBooleanToShort.smali index 901f8e4f0..e66d8e5c9 100644 --- a/jadx-core/src/test/smali/conditions/TestBooleanToShort.smali +++ b/jadx-core/src/test/smali/conditions/TestBooleanToShort.smali @@ -1,16 +1,16 @@ -.class public LTestBooleanToShort; +.class public Lconditions/TestBooleanToShort; .super Ljava/lang/Object; .field private showConsent:Z -.method public writeToParcel(LTestBooleanToShort;)V +.method public writeToParcel(Lconditions/TestBooleanToShort;)V .locals 0 - iget-boolean p1, p0, LTestBooleanToShort;->showConsent:Z + iget-boolean p1, p0, Lconditions/TestBooleanToShort;->showConsent:Z int-to-short p1, p1 - invoke-virtual {p0, p1}, LTestBooleanToShort;->write(S)V + invoke-virtual {p0, p1}, Lconditions/TestBooleanToShort;->write(S)V return-void .end method