@@ -740,13 +740,18 @@ public class InsnGen {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!arg.getType().equals(origType)) {
|
||||
code.add('(');
|
||||
useType(code, origType);
|
||||
code.add(") ");
|
||||
return true;
|
||||
ArgType argType = arg.getType();
|
||||
if (argType.equals(origType)) {
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
|
||||
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.dx.io.OpcodeInfo;
|
||||
import com.android.dx.io.Opcodes;
|
||||
@@ -10,10 +14,8 @@ import com.android.dx.io.instructions.FillArrayDataPayloadDecodedInstruction;
|
||||
import com.android.dx.io.instructions.PackedSwitchPayloadDecodedInstruction;
|
||||
import com.android.dx.io.instructions.ShortArrayCodeInput;
|
||||
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.MethodInfo;
|
||||
import jadx.core.dex.instructions.args.ArgType;
|
||||
@@ -119,9 +121,13 @@ public class InsnDecoder {
|
||||
return constStrInsn;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
case Opcodes.MOVE:
|
||||
case Opcodes.MOVE_16:
|
||||
|
||||
@@ -83,7 +83,7 @@ public abstract class ArgType {
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -326,7 +326,7 @@ public class LoopRegionVisitor extends AbstractVisitor implements IRegionVisitor
|
||||
return true;
|
||||
}
|
||||
// TODO: add checks
|
||||
iterableType = ArgType.generic(iterableType.getObject(), new ArgType[]{varType});
|
||||
iterableType = ArgType.generic(iterableType.getObject(), varType);
|
||||
iterableArg.setType(iterableType);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ public class TypeCompareTest {
|
||||
|
||||
ArgType keyType = ArgType.genericType("K");
|
||||
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(mapCls, mapGeneric, TypeCompareEnum.WIDER_BY_GENERIC);
|
||||
|
||||
@@ -43,12 +43,12 @@ class SignatureParserTest {
|
||||
@Test
|
||||
public void testGenerics() {
|
||||
checkType("TD;", genericType("D"));
|
||||
checkType("La<TV;Lb;>;", generic("La;", new ArgType[]{genericType("V"), object("b")}));
|
||||
checkType("La<Lb<Lc;>;>;", generic("La;", new ArgType[]{generic("Lb;", new ArgType[]{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<TD;>.c;", genericInner(generic("La;", new ArgType[]{genericType("D")}), "c", null));
|
||||
checkType("La<TD;>.c/d;", genericInner(generic("La;", new ArgType[]{genericType("D")}), "c.d", null));
|
||||
checkType("La<Lb;>.c<TV;>;", genericInner(generic("La;", new ArgType[]{object("Lb;")}), "c", new ArgType[]{genericType("V")}));
|
||||
checkType("La<TV;Lb;>;", generic("La;", genericType("V"), object("b")));
|
||||
checkType("La<Lb<Lc;>;>;", generic("La;", generic("Lb;", object("Lc;"))));
|
||||
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;", genericType("D")), "c", null));
|
||||
checkType("La<TD;>.c/d;", genericInner(generic("La;", genericType("D")), "c.d", null));
|
||||
checkType("La<Lb;>.c<TV;>;", genericInner(generic("La;", object("Lb;")), "c", new ArgType[]{genericType("V")}));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -107,7 +107,7 @@ class SignatureParserTest {
|
||||
List<ArgType> argTypes = new SignatureParser("(Ljava/util/List<*>;)V").consumeMethodArgs();
|
||||
|
||||
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
|
||||
@@ -117,7 +117,7 @@ class SignatureParserTest {
|
||||
assertThat(argTypes, hasSize(1));
|
||||
ArgType argType = argTypes.get(0);
|
||||
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
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
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);"));
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -55,7 +55,7 @@ public class TestCastInOverloadedInvoke extends IntegrationTest {
|
||||
ClassNode cls = getClassNode(TestCls.class);
|
||||
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((String) obj);"));
|
||||
|
||||
Reference in New Issue
Block a user