fix: collect usage info in generic types
This commit is contained in:
@@ -148,15 +148,19 @@ public class UsageInfo implements IUsageInfoData {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit all class nodes found in subtypes of the provided type.
|
||||
*/
|
||||
private void processType(ArgType type, Consumer<ClassNode> consumer) {
|
||||
if (type == null) {
|
||||
if (type == null || type == ArgType.OBJECT) {
|
||||
return;
|
||||
}
|
||||
if (type.isArray()) {
|
||||
processType(type.getArrayRootElement(), consumer);
|
||||
return;
|
||||
}
|
||||
if (type.isObject() && !type.isGenericType()) {
|
||||
if (type.isObject()) {
|
||||
// TODO: support custom handlers via API
|
||||
ClspClass clsDetails = root.getClsp().getClsDetails(type);
|
||||
if (clsDetails != null && clsDetails.getSource() == ClspClassSource.APACHE_HTTP_LEGACY_CLIENT) {
|
||||
root.getGradleInfoStorage().setUseApacheHttpLegacy(true);
|
||||
@@ -166,19 +170,30 @@ public class UsageInfo implements IUsageInfoData {
|
||||
consumer.accept(clsNode);
|
||||
}
|
||||
List<ArgType> genericTypes = type.getGenericTypes();
|
||||
if (type.isGeneric() && notEmpty(genericTypes)) {
|
||||
if (notEmpty(genericTypes)) {
|
||||
for (ArgType argType : genericTypes) {
|
||||
processType(argType, consumer);
|
||||
}
|
||||
}
|
||||
List<ArgType> extendTypes = type.getExtendTypes();
|
||||
if (notEmpty(extendTypes)) {
|
||||
for (ArgType extendType : extendTypes) {
|
||||
processType(extendType, consumer);
|
||||
}
|
||||
}
|
||||
ArgType wildcardType = type.getWildcardType();
|
||||
if (wildcardType != null) {
|
||||
processType(wildcardType, consumer);
|
||||
}
|
||||
// TODO: process 'outer' types (check TestOuterGeneric test)
|
||||
}
|
||||
}
|
||||
|
||||
private static <T extends Comparable<T>> List<T> sortedList(Set<T> deps) {
|
||||
if (deps == null || deps.isEmpty()) {
|
||||
private static <T extends Comparable<T>> List<T> sortedList(Set<T> nodes) {
|
||||
if (nodes == null || nodes.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<T> list = new ArrayList<>(deps);
|
||||
List<T> list = new ArrayList<>(nodes);
|
||||
Collections.sort(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -88,12 +88,14 @@ public class UsageInfoVisitor extends AbstractVisitor {
|
||||
for (ArgType interfaceType : cls.getInterfaces()) {
|
||||
usageInfo.clsUse(cls, interfaceType);
|
||||
}
|
||||
for (ArgType genericTypeParameter : cls.getGenericTypeParameters()) {
|
||||
usageInfo.clsUse(cls, genericTypeParameter);
|
||||
}
|
||||
for (FieldNode fieldNode : cls.getFields()) {
|
||||
usageInfo.clsUse(cls, fieldNode.getType());
|
||||
processAnnotations(fieldNode, usageInfo);
|
||||
// TODO: process types from field 'constant value'
|
||||
}
|
||||
// TODO: process generics
|
||||
processAnnotations(cls, usageInfo);
|
||||
for (MethodNode methodNode : cls.getMethods()) {
|
||||
processMethod(methodNode, usageInfo);
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package jadx.tests.integration.generics;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.core.dex.nodes.MethodNode;
|
||||
import jadx.tests.api.IntegrationTest;
|
||||
|
||||
import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;
|
||||
|
||||
public class TestUsageInGenerics extends IntegrationTest {
|
||||
|
||||
public static class TestCls {
|
||||
|
||||
public static class A {
|
||||
}
|
||||
|
||||
public static class B<T extends A> {
|
||||
}
|
||||
|
||||
public static class C {
|
||||
public List<? extends A> list;
|
||||
}
|
||||
|
||||
public <T extends A> T test() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
ClassNode cls = getClassNode(TestCls.class);
|
||||
ClassNode testCls = searchCls(cls.getInnerClasses(), "A");
|
||||
ClassNode bCls = searchCls(cls.getInnerClasses(), "B");
|
||||
ClassNode cCls = searchCls(cls.getInnerClasses(), "C");
|
||||
MethodNode testMth = getMethod(cls, "test");
|
||||
|
||||
assertThat(testCls.getUseIn()).contains(cls, bCls, cCls);
|
||||
assertThat(testCls.getUseInMth()).contains(testMth);
|
||||
|
||||
assertThat(cls)
|
||||
.code()
|
||||
.containsOne("public <T extends A> T test() {");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user