提交 2acc14b0 编写于 作者: S Skylot

fix: resolve generic type vars for instance field get instruction (#918)

上级 1f1efb0e
......@@ -61,6 +61,9 @@ public class TypeUtils {
}
private void expandTypeVar(NotificationAttrNode node, ArgType type, Collection<ArgType> typeVars) {
if (typeVars.isEmpty()) {
return;
}
boolean allExtendsEmpty = true;
for (ArgType argType : typeVars) {
if (notEmpty(argType.getExtendTypes())) {
......
package jadx.core.dex.visitors.typeinference;
import jadx.core.dex.info.FieldInfo;
import jadx.core.dex.instructions.IndexInsnNode;
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.nodes.RootNode;
/**
* Dynamic bound for instance field get of generic type.
* Bound type calculated using instance generic type.
*/
public final class TypeBoundFieldGetAssign implements ITypeBoundDynamic {
private final RootNode root;
private final IndexInsnNode getNode;
private final FieldInfo fieldInfo;
private final ArgType initType;
public TypeBoundFieldGetAssign(RootNode root, IndexInsnNode getNode, ArgType initType) {
this.root = root;
this.getNode = getNode;
this.fieldInfo = ((FieldInfo) getNode.getIndex());
this.initType = initType;
}
@Override
public BoundEnum getBound() {
return BoundEnum.ASSIGN;
}
@Override
public ArgType getType(TypeUpdateInfo updateInfo) {
return getResultType(updateInfo.getType(getInstanceArg()));
}
@Override
public ArgType getType() {
return getResultType(getInstanceArg().getType());
}
private ArgType getResultType(ArgType instanceType) {
ArgType resultGeneric = root.getTypeUtils().replaceClassGenerics(instanceType, initType);
if (resultGeneric != null && !resultGeneric.isWildcard()) {
return resultGeneric;
}
return initType; // TODO: check if this type is allowed in current scope
}
private InsnArg getInstanceArg() {
return getNode.getArg(0);
}
@Override
public RegisterArg getArg() {
return getNode.getResult();
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
TypeBoundFieldGetAssign that = (TypeBoundFieldGetAssign) o;
return getNode.equals(that.getNode);
}
@Override
public int hashCode() {
return getNode.hashCode();
}
@Override
public String toString() {
return "FieldGetAssign{" + fieldInfo
+ ", type=" + getType()
+ ", instanceArg=" + getInstanceArg()
+ '}';
}
}
......@@ -293,6 +293,10 @@ public final class TypeInferenceVisitor extends AbstractVisitor {
addBound(typeInfo, makeAssignInvokeBound((InvokeNode) insn));
break;
case IGET:
addBound(typeInfo, makeAssignFieldGetBound((IndexInsnNode) insn));
break;
case CHECK_CAST:
addBound(typeInfo, new TypeBoundCheckCastAssign(root, (IndexInsnNode) insn));
break;
......@@ -304,6 +308,14 @@ public final class TypeInferenceVisitor extends AbstractVisitor {
}
}
private ITypeBound makeAssignFieldGetBound(IndexInsnNode insn) {
ArgType initType = insn.getResult().getInitType();
if (initType.containsTypeVariable()) {
return new TypeBoundFieldGetAssign(root, insn, initType);
}
return new TypeBoundConst(BoundEnum.ASSIGN, initType);
}
private ITypeBound makeAssignInvokeBound(InvokeNode invokeNode) {
ArgType boundType = invokeNode.getCallMth().getReturnType();
ArgType genericReturnType = root.getMethodUtils().getMethodGenericReturnType(invokeNode);
......
package jadx.tests.integration.generics;
import org.junit.jupiter.api.Test;
import jadx.tests.api.IntegrationTest;
import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;
public class TestGenericFields extends IntegrationTest {
public static class TestCls {
public static class Summary {
Value<Amount> price;
}
public static class Value<T> {
T value;
}
public static class Amount {
String cur;
int val;
}
public String test(Summary summary) {
Amount amount = summary.price.value;
return amount.val + " " + amount.cur;
}
}
@Test
public void test() {
noDebugInfo();
assertThat(getClassNode(TestCls.class))
.code()
.doesNotContain("T t = ")
.containsOne("Amount amount =");
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册