refactor: use enum for wildcard bounds instead of int
This commit is contained in:
@@ -274,9 +274,9 @@ public class ClsSet {
|
||||
private static void writeArgType(DataOutputStream out, ArgType argType, Map<String, NClass> 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();
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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:
|
||||
* <ul>
|
||||
* <li>1 for upper bound (? extends A)</li>
|
||||
* <li>0 no bounds (?)</li>
|
||||
* <li>-1 for lower bound (? super A)</li>
|
||||
* </ul>
|
||||
*/
|
||||
@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);
|
||||
|
||||
@@ -38,7 +38,8 @@ public class SignatureParser {
|
||||
if (a == null) {
|
||||
return null;
|
||||
}
|
||||
return new SignatureParser(mergeSignature((List<String>) a.getDefaultValue()));
|
||||
String signature = mergeSignature((List<String>) 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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user