From e444ecb2c74869b7dfe23847d32f4c7559098734 Mon Sep 17 00:00:00 2001 From: Skylot Date: Mon, 17 Feb 2020 19:30:29 +0000 Subject: [PATCH] fix: improve wildcard types compare (#857) --- .../visitors/typeinference/TypeCompare.java | 23 ++++++++++++++++++- .../typeinference/TypeCompareTest.java | 22 +++++++++++++++--- 2 files changed, 41 insertions(+), 4 deletions(-) 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 3e7905695..cf05bec9b 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 @@ -169,7 +169,12 @@ public class TypeCompare { if (firstGeneric != secondGeneric) { return firstGeneric ? NARROW_BY_GENERIC : WIDER_BY_GENERIC; } - // both generics on same object, compare generics arrays + // both generics on same object + if (first.getWildcardBound() != null && second.getWildcardBound() != null) { + // both wildcards + return compareWildcardTypes(first, second); + } + // compare generics arrays ArgType[] firstGenericTypes = first.getGenericTypes(); ArgType[] secondGenericTypes = second.getGenericTypes(); int len = firstGenericTypes.length; @@ -198,6 +203,22 @@ public class TypeCompare { return TypeCompareEnum.CONFLICT; } + private TypeCompareEnum compareWildcardTypes(ArgType first, ArgType second) { + WildcardBound firstWildcardBound = first.getWildcardBound(); + WildcardBound secondWildcardBound = second.getWildcardBound(); + if (firstWildcardBound == WildcardBound.UNBOUND) { + return WIDER; + } + if (secondWildcardBound == WildcardBound.UNBOUND) { + return NARROW; + } + TypeCompareEnum wildcardCompare = compareTypes(first.getWildcardType(), second.getWildcardType()); + if (firstWildcardBound == secondWildcardBound) { + return wildcardCompare; + } + return CONFLICT; + } + private TypeCompareEnum compareGenericTypeWithObject(ArgType genericType, ArgType objType) { List extendTypes = genericType.getExtendTypes(); if (extendTypes == null || extendTypes.isEmpty()) { 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 356a46544..1660b3478 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 @@ -12,6 +12,7 @@ import jadx.NotYetImplemented; import jadx.NotYetImplementedExtension; import jadx.api.JadxArgs; import jadx.core.dex.instructions.args.ArgType; +import jadx.core.dex.instructions.args.ArgType.WildcardBound; import jadx.core.dex.nodes.RootNode; import static jadx.core.dex.instructions.args.ArgType.BOOLEAN; @@ -28,6 +29,7 @@ import static jadx.core.dex.instructions.args.ArgType.UNKNOWN_ARRAY; import static jadx.core.dex.instructions.args.ArgType.UNKNOWN_OBJECT; import static jadx.core.dex.instructions.args.ArgType.array; import static jadx.core.dex.instructions.args.ArgType.generic; +import static jadx.core.dex.instructions.args.ArgType.object; import static jadx.core.dex.instructions.args.ArgType.wildcard; import static org.assertj.core.api.Assertions.assertThat; @@ -83,7 +85,7 @@ public class TypeCompareTest { check(array(OBJECT), array(INT), TypeCompareEnum.CONFLICT); - ArgType integerType = ArgType.object("java.lang.Integer"); + ArgType integerType = object("java.lang.Integer"); check(array(OBJECT), array(integerType), TypeCompareEnum.WIDER); check(array(INT), array(integerType), TypeCompareEnum.CONFLICT); check(array(INT), array(INT), TypeCompareEnum.EQUAL); @@ -95,8 +97,8 @@ public class TypeCompareTest { @Test public void compareGenerics() { - ArgType mapCls = ArgType.object("java.util.Map"); - ArgType setCls = ArgType.object("java.util.Set"); + ArgType mapCls = object("java.util.Map"); + ArgType setCls = object("java.util.Set"); ArgType keyType = ArgType.genericType("K"); ArgType valueType = ArgType.genericType("V"); @@ -113,6 +115,20 @@ public class TypeCompareTest { // TODO implement compare for wildcard with bounds } + @Test + public void compareWildCards() { + ArgType clsWildcard = generic(CLASS.getObject(), wildcard()); + ArgType clsExtendedWildcard = generic(CLASS.getObject(), wildcard(STRING, WildcardBound.EXTENDS)); + check(clsWildcard, clsExtendedWildcard, TypeCompareEnum.WIDER); + + ArgType listWildcard = generic(CLASS.getObject(), wildcard(object("java.util.List"), WildcardBound.EXTENDS)); + ArgType collWildcard = generic(CLASS.getObject(), wildcard(object("java.util.Collection"), WildcardBound.EXTENDS)); + check(listWildcard, collWildcard, TypeCompareEnum.NARROW); + + ArgType collSuperWildcard = generic(CLASS.getObject(), wildcard(object("java.util.Collection"), WildcardBound.SUPER)); + check(collSuperWildcard, listWildcard, TypeCompareEnum.CONFLICT); + } + @Test public void compareGenericTypes() { ArgType vType = ArgType.genericType("V");