From 06f26ef8f5603f42bc26a4935246bea632e366d1 Mon Sep 17 00:00:00 2001 From: Skylot Date: Thu, 15 Aug 2019 14:28:56 +0100 Subject: [PATCH] refactor: use enum for wildcard bounds instead of int --- .../src/main/java/jadx/core/clsp/ClsSet.java | 8 +- .../main/java/jadx/core/codegen/ClassGen.java | 7 +- .../core/dex/instructions/args/ArgType.java | 73 ++++++++++++------- .../dex/nodes/parser/SignatureParser.java | 7 +- .../core/dex/visitors/debuginfo/LocalVar.java | 2 +- .../visitors/regions/LoopRegionVisitor.java | 2 +- .../dex/instructions/args/ArgTypeTest.java | 11 +++ .../tests/functional/SignatureParserTest.java | 11 +-- 8 files changed, 76 insertions(+), 45 deletions(-) diff --git a/jadx-core/src/main/java/jadx/core/clsp/ClsSet.java b/jadx-core/src/main/java/jadx/core/clsp/ClsSet.java index 9bf4a3acc..426b8a8a7 100644 --- a/jadx-core/src/main/java/jadx/core/clsp/ClsSet.java +++ b/jadx-core/src/main/java/jadx/core/clsp/ClsSet.java @@ -274,9 +274,9 @@ public class ClsSet { private static void writeArgType(DataOutputStream out, ArgType argType, Map names) throws IOException { if (argType.getWildcardType() != null) { out.writeByte(TypeEnum.WILDCARD.ordinal()); - int bounds = argType.getWildcardBounds(); - out.writeByte(bounds); - if (bounds != 0) { + ArgType.WildcardBound bound = argType.getWildcardBound(); + out.writeByte(bound.getNum()); + if (bound != ArgType.WildcardBound.UNBOUND) { writeArgType(out, argType.getWildcardType(), names); } } else if (argType.isGeneric()) { @@ -415,7 +415,7 @@ public class ClsSet { int bounds = in.readByte(); return bounds == 0 ? ArgType.wildcard() - : ArgType.wildcard(readArgType(in), bounds); + : ArgType.wildcard(readArgType(in), ArgType.WildcardBound.getByNum(bounds)); case GENERIC: String obj = classes[in.readInt()].getName(); diff --git a/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java b/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java index fc21edf63..01942264a 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java @@ -470,10 +470,9 @@ public class ClassGen { ArgType gt = generics[i]; ArgType wt = gt.getWildcardType(); if (wt != null) { - code.add('?'); - int bounds = gt.getWildcardBounds(); - if (bounds != 0) { - code.add(bounds == -1 ? " super " : " extends "); + ArgType.WildcardBound bound = gt.getWildcardBound(); + code.add(bound.getStr()); + if (bound != ArgType.WildcardBound.UNBOUND) { useType(code, wt); } } else { diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/ArgType.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/ArgType.java index fc4f8704d..7f8a3cb32 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/ArgType.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/ArgType.java @@ -74,14 +74,14 @@ public abstract class ArgType { } public static ArgType wildcard() { - return new WildcardType(OBJECT, 0); + return new WildcardType(OBJECT, WildcardBound.UNBOUND); } - public static ArgType wildcard(ArgType obj, int bounds) { - return new WildcardType(obj, bounds); + public static ArgType wildcard(ArgType obj, WildcardBound bound) { + return new WildcardType(obj, bound); } - public static ArgType generic(String sign) { + public static ArgType parseGenericSignature(String sign) { return new SignatureParser(sign).consumeType(); } @@ -212,14 +212,40 @@ public abstract class ArgType { } } + public enum WildcardBound { + EXTENDS(1, "? extends "), // upper bound (? extends A) + UNBOUND(0, "?"), // no bounds (?) + SUPER(-1, "? super "); // lower bound (? super A) + + private final int num; + private final String str; + + WildcardBound(int val, String str) { + this.num = val; + this.str = str; + } + + public int getNum() { + return num; + } + + public String getStr() { + return str; + } + + public static WildcardBound getByNum(int num) { + return num == 0 ? UNBOUND : (num == 1 ? EXTENDS : SUPER); + } + } + private static final class WildcardType extends ObjectType { private final ArgType type; - private final int bounds; + private final WildcardBound bound; - public WildcardType(ArgType obj, int bounds) { + public WildcardType(ArgType obj, WildcardBound bound) { super(OBJECT.getObject()); this.type = obj; - this.bounds = bounds; + this.bound = bound; } @Override @@ -232,32 +258,24 @@ public abstract class ArgType { return type; } - /** - * Return wildcard bounds: - * - */ @Override - public int getWildcardBounds() { - return bounds; + public WildcardBound getWildcardBound() { + return bound; } @Override boolean internalEquals(Object obj) { return super.internalEquals(obj) - && bounds == ((WildcardType) obj).bounds + && bound == ((WildcardType) obj).bound && type.equals(((WildcardType) obj).type); } @Override public String toString() { - if (bounds == 0) { - return "?"; + if (bound == WildcardBound.UNBOUND) { + return bound.getStr(); } - return "? " + (bounds == -1 ? "super" : "extends") + ' ' + type; + return bound.getStr() + type; } } @@ -468,11 +486,8 @@ public abstract class ArgType { return null; } - /** - * @see WildcardType#getWildcardBounds() - */ - public int getWildcardBounds() { - return 0; + public WildcardBound getWildcardBound() { + return null; } public ArgType getOuterType() { @@ -629,6 +644,10 @@ public abstract class ArgType { if (isGenericType()) { return true; } + ArgType wildcardType = getWildcardType(); + if (wildcardType != null) { + return wildcardType.containsGenericType(); + } if (isGeneric()) { ArgType[] genericTypes = getGenericTypes(); if (genericTypes != null) { @@ -662,7 +681,7 @@ public abstract class ArgType { return new GenericObject(aliasFullName, type.getGenericTypes()); } if (type instanceof WildcardType) { - return new WildcardType(ArgType.object(aliasFullName), type.getWildcardBounds()); + return new WildcardType(ArgType.object(aliasFullName), type.getWildcardBound()); } } return ArgType.object(aliasFullName); diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/parser/SignatureParser.java b/jadx-core/src/main/java/jadx/core/dex/nodes/parser/SignatureParser.java index dfcc71e38..d9de3d247 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/parser/SignatureParser.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/parser/SignatureParser.java @@ -38,7 +38,8 @@ public class SignatureParser { if (a == null) { return null; } - return new SignatureParser(mergeSignature((List) a.getDefaultValue())); + String signature = mergeSignature((List) a.getDefaultValue()); + return new SignatureParser(signature); } private char next() { @@ -200,10 +201,10 @@ public class SignatureParser { type = ArgType.wildcard(); } else if (lookAhead('+')) { next(); - type = ArgType.wildcard(consumeType(), 1); + type = ArgType.wildcard(consumeType(), ArgType.WildcardBound.EXTENDS); } else if (lookAhead('-')) { next(); - type = ArgType.wildcard(consumeType(), -1); + type = ArgType.wildcard(consumeType(), ArgType.WildcardBound.SUPER); } else { type = consumeType(); } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/debuginfo/LocalVar.java b/jadx-core/src/main/java/jadx/core/dex/visitors/debuginfo/LocalVar.java index f20044a60..f25ca9b64 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/debuginfo/LocalVar.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/debuginfo/LocalVar.java @@ -31,7 +31,7 @@ public final class LocalVar { this.name = name; if (sign != null) { try { - ArgType gType = ArgType.generic(sign); + ArgType gType = ArgType.parseGenericSignature(sign); if (checkSignature(type, gType)) { type = gType; } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/LoopRegionVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/LoopRegionVisitor.java index 5c3ac51af..8e2b1e338 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/LoopRegionVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/LoopRegionVisitor.java @@ -327,7 +327,7 @@ public class LoopRegionVisitor extends AbstractVisitor implements IRegionVisitor } ArgType wildcardType = gType.getWildcardType(); if (wildcardType != null - && gType.getWildcardBounds() == 1 + && gType.getWildcardBound() == ArgType.WildcardBound.EXTENDS && ArgType.isInstanceOf(mth.root(), wildcardType, varType)) { return true; } diff --git a/jadx-core/src/test/java/jadx/core/dex/instructions/args/ArgTypeTest.java b/jadx-core/src/test/java/jadx/core/dex/instructions/args/ArgTypeTest.java index f56f5b7a3..fbc5d9f01 100644 --- a/jadx-core/src/test/java/jadx/core/dex/instructions/args/ArgTypeTest.java +++ b/jadx-core/src/test/java/jadx/core/dex/instructions/args/ArgTypeTest.java @@ -3,6 +3,7 @@ package jadx.core.dex.instructions.args; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; class ArgTypeTest { @@ -13,4 +14,14 @@ class ArgTypeTest { assertEquals(first, second); } + + @Test + void testContainsGenericType() { + ArgType wildcard = ArgType.wildcard(ArgType.genericType("T"), ArgType.WildcardBound.SUPER); + assertTrue(wildcard.containsGenericType()); + + ArgType type = ArgType.generic("java.lang.List", wildcard); + assertTrue(type.containsGenericType()); + + } } diff --git a/jadx-core/src/test/java/jadx/tests/functional/SignatureParserTest.java b/jadx-core/src/test/java/jadx/tests/functional/SignatureParserTest.java index b0a881746..5c59c1e76 100644 --- a/jadx-core/src/test/java/jadx/tests/functional/SignatureParserTest.java +++ b/jadx-core/src/test/java/jadx/tests/functional/SignatureParserTest.java @@ -6,6 +6,7 @@ import java.util.List; import org.junit.jupiter.api.Test; import jadx.core.dex.instructions.args.ArgType; +import jadx.core.dex.instructions.args.ArgType.WildcardBound; import jadx.core.dex.nodes.GenericInfo; import jadx.core.dex.nodes.parser.SignatureParser; @@ -60,10 +61,10 @@ class SignatureParserTest { @Test public void testWildcards() { checkWildcards("*", wildcard()); - checkWildcards("+Lb;", wildcard(object("b"), 1)); - checkWildcards("-Lb;", wildcard(object("b"), -1)); - checkWildcards("+TV;", wildcard(genericType("V"), 1)); - checkWildcards("-TV;", wildcard(genericType("V"), -1)); + checkWildcards("+Lb;", wildcard(object("b"), WildcardBound.EXTENDS)); + checkWildcards("-Lb;", wildcard(object("b"), WildcardBound.SUPER)); + checkWildcards("+TV;", wildcard(genericType("V"), WildcardBound.EXTENDS)); + checkWildcards("-TV;", wildcard(genericType("V"), WildcardBound.SUPER)); checkWildcards("**", wildcard(), wildcard()); checkWildcards("*Lb;", wildcard(), object("b")); @@ -116,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;", genericType("T")), "d.E", (ArgType[]) null))); + assertThat(argType, is(genericInner(generic("La/b/C;", genericType("T")), "d.E", null))); } @Test