Commit 01da127c authored by Ahmed Ashour's avatar Ahmed Ashour Committed by skylot

fix: remove generics cast when object types match (#591) (PR #592)

parent ccb9c460
...@@ -740,13 +740,18 @@ public class InsnGen { ...@@ -740,13 +740,18 @@ public class InsnGen {
return false; return false;
} }
} }
if (!arg.getType().equals(origType)) { ArgType argType = arg.getType();
code.add('('); if (argType.equals(origType)) {
useType(code, origType); return false;
code.add(") ");
return true;
} }
return false; if (origType.isGeneric()
&& origType.getObject().equals(argType.getObject())) {
return false;
}
code.add('(');
useType(code, origType);
code.add(") ");
return true;
} }
/** /**
......
...@@ -2,6 +2,10 @@ package jadx.core.dex.instructions; ...@@ -2,6 +2,10 @@ package jadx.core.dex.instructions;
import java.io.EOFException; import java.io.EOFException;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.android.dex.Code; import com.android.dex.Code;
import com.android.dx.io.OpcodeInfo; import com.android.dx.io.OpcodeInfo;
import com.android.dx.io.Opcodes; import com.android.dx.io.Opcodes;
...@@ -10,10 +14,8 @@ import com.android.dx.io.instructions.FillArrayDataPayloadDecodedInstruction; ...@@ -10,10 +14,8 @@ import com.android.dx.io.instructions.FillArrayDataPayloadDecodedInstruction;
import com.android.dx.io.instructions.PackedSwitchPayloadDecodedInstruction; import com.android.dx.io.instructions.PackedSwitchPayloadDecodedInstruction;
import com.android.dx.io.instructions.ShortArrayCodeInput; import com.android.dx.io.instructions.ShortArrayCodeInput;
import com.android.dx.io.instructions.SparseSwitchPayloadDecodedInstruction; import com.android.dx.io.instructions.SparseSwitchPayloadDecodedInstruction;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.core.Consts;
import jadx.core.dex.info.FieldInfo; import jadx.core.dex.info.FieldInfo;
import jadx.core.dex.info.MethodInfo; import jadx.core.dex.info.MethodInfo;
import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.ArgType;
...@@ -119,9 +121,13 @@ public class InsnDecoder { ...@@ -119,9 +121,13 @@ public class InsnDecoder {
return constStrInsn; return constStrInsn;
case Opcodes.CONST_CLASS: case Opcodes.CONST_CLASS:
InsnNode constClsInsn = new ConstClassNode(dex.getType(insn.getIndex())); {
constClsInsn.setResult(InsnArg.reg(insn, 0, ArgType.CLASS)); ArgType clsType = dex.getType(insn.getIndex());
InsnNode constClsInsn = new ConstClassNode(clsType);
constClsInsn.setResult(
InsnArg.reg(insn, 0, ArgType.generic(Consts.CLASS_CLASS, clsType)));
return constClsInsn; return constClsInsn;
}
case Opcodes.MOVE: case Opcodes.MOVE:
case Opcodes.MOVE_16: case Opcodes.MOVE_16:
......
...@@ -83,7 +83,7 @@ public abstract class ArgType { ...@@ -83,7 +83,7 @@ public abstract class ArgType {
return new SignatureParser(sign).consumeType(); return new SignatureParser(sign).consumeType();
} }
public static ArgType generic(String obj, ArgType[] generics) { public static ArgType generic(String obj, ArgType... generics) {
return new GenericObject(obj, generics); return new GenericObject(obj, generics);
} }
......
...@@ -326,7 +326,7 @@ public class LoopRegionVisitor extends AbstractVisitor implements IRegionVisitor ...@@ -326,7 +326,7 @@ public class LoopRegionVisitor extends AbstractVisitor implements IRegionVisitor
return true; return true;
} }
// TODO: add checks // TODO: add checks
iterableType = ArgType.generic(iterableType.getObject(), new ArgType[]{varType}); iterableType = ArgType.generic(iterableType.getObject(), varType);
iterableArg.setType(iterableType); iterableArg.setType(iterableType);
return true; return true;
} }
......
...@@ -76,7 +76,7 @@ public class TypeCompareTest { ...@@ -76,7 +76,7 @@ public class TypeCompareTest {
ArgType keyType = ArgType.genericType("K"); ArgType keyType = ArgType.genericType("K");
ArgType valueType = ArgType.genericType("V"); ArgType valueType = ArgType.genericType("V");
ArgType mapGeneric = ArgType.generic(mapCls.getObject(), new ArgType[]{keyType, valueType}); ArgType mapGeneric = ArgType.generic(mapCls.getObject(), keyType, valueType);
check(mapGeneric, mapCls, TypeCompareEnum.NARROW_BY_GENERIC); check(mapGeneric, mapCls, TypeCompareEnum.NARROW_BY_GENERIC);
check(mapCls, mapGeneric, TypeCompareEnum.WIDER_BY_GENERIC); check(mapCls, mapGeneric, TypeCompareEnum.WIDER_BY_GENERIC);
......
...@@ -43,12 +43,12 @@ class SignatureParserTest { ...@@ -43,12 +43,12 @@ class SignatureParserTest {
@Test @Test
public void testGenerics() { public void testGenerics() {
checkType("TD;", genericType("D")); checkType("TD;", genericType("D"));
checkType("La<TV;Lb;>;", generic("La;", new ArgType[]{genericType("V"), object("b")})); checkType("La<TV;Lb;>;", generic("La;", genericType("V"), object("b")));
checkType("La<Lb<Lc;>;>;", generic("La;", new ArgType[]{generic("Lb;", new ArgType[]{object("Lc;")})})); checkType("La<Lb<Lc;>;>;", generic("La;", generic("Lb;", object("Lc;"))));
checkType("La/b/C<Ld/E<Lf/G;>;>;", generic("La/b/C;", new ArgType[]{generic("Ld/E;", new ArgType[]{object("Lf/G;")})})); checkType("La/b/C<Ld/E<Lf/G;>;>;", generic("La/b/C;", generic("Ld/E;", object("Lf/G;"))));
checkType("La<TD;>.c;", genericInner(generic("La;", new ArgType[]{genericType("D")}), "c", null)); checkType("La<TD;>.c;", genericInner(generic("La;", genericType("D")), "c", null));
checkType("La<TD;>.c/d;", genericInner(generic("La;", new ArgType[]{genericType("D")}), "c.d", null)); checkType("La<TD;>.c/d;", genericInner(generic("La;", genericType("D")), "c.d", null));
checkType("La<Lb;>.c<TV;>;", genericInner(generic("La;", new ArgType[]{object("Lb;")}), "c", new ArgType[]{genericType("V")})); checkType("La<Lb;>.c<TV;>;", genericInner(generic("La;", object("Lb;")), "c", new ArgType[]{genericType("V")}));
} }
@Test @Test
...@@ -107,7 +107,7 @@ class SignatureParserTest { ...@@ -107,7 +107,7 @@ class SignatureParserTest {
List<ArgType> argTypes = new SignatureParser("(Ljava/util/List<*>;)V").consumeMethodArgs(); List<ArgType> argTypes = new SignatureParser("(Ljava/util/List<*>;)V").consumeMethodArgs();
assertThat(argTypes, hasSize(1)); assertThat(argTypes, hasSize(1));
assertThat(argTypes.get(0), is(generic("Ljava/util/List;", new ArgType[]{wildcard()}))); assertThat(argTypes.get(0), is(generic("Ljava/util/List;", wildcard())));
} }
@Test @Test
...@@ -117,7 +117,7 @@ class SignatureParserTest { ...@@ -117,7 +117,7 @@ class SignatureParserTest {
assertThat(argTypes, hasSize(1)); assertThat(argTypes, hasSize(1));
ArgType argType = argTypes.get(0); ArgType argType = argTypes.get(0);
assertThat(argType.getObject().indexOf('/'), is(-1)); assertThat(argType.getObject().indexOf('/'), is(-1));
assertThat(argType, is(genericInner(generic("La/b/C;", new ArgType[]{genericType("T")}), "d.E", null))); assertThat(argType, is(genericInner(generic("La/b/C;", genericType("T")), "d.E", (ArgType[]) null)));
} }
@Test @Test
......
package jadx.tests.integration.generics;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import org.junit.jupiter.api.Test;
import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.IntegrationTest;
public class TestGenerics7 extends IntegrationTest {
public static class TestCls {
public void test() {
declare(String.class);
}
public <T> T declare(Class<T> cls) {
return null;
}
public void declare(Object cls) {
}
}
@Test
public void test() {
ClassNode cls = getClassNode(TestCls.class);
String code = cls.getCode().toString();
assertThat(code, containsString("declare(String.class);"));
}
}
...@@ -55,7 +55,7 @@ public class TestCastInOverloadedInvoke extends IntegrationTest { ...@@ -55,7 +55,7 @@ public class TestCastInOverloadedInvoke extends IntegrationTest {
ClassNode cls = getClassNode(TestCls.class); ClassNode cls = getClassNode(TestCls.class);
String code = cls.getCode().toString(); String code = cls.getCode().toString();
assertThat(code, containsOne("call((ArrayList<String>) new ArrayList());")); assertThat(code, containsOne("call(new ArrayList());"));
assertThat(code, containsOne("call((List<String>) new ArrayList());")); assertThat(code, containsOne("call((List<String>) new ArrayList());"));
assertThat(code, containsOne("call((String) obj);")); assertThat(code, containsOne("call((String) obj);"));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment