diff --git a/src/main/java/run/slicer/vf/impl/ClassSource.java b/src/main/java/run/slicer/vf/impl/ClassSource.java index 44ea2e3..5b32f07 100644 --- a/src/main/java/run/slicer/vf/impl/ClassSource.java +++ b/src/main/java/run/slicer/vf/impl/ClassSource.java @@ -93,7 +93,16 @@ private static Map resources(String[] names, String[] reso return res; } - private record DependencyAnalyzer(Map data, Function source) { + private static final class DependencyAnalyzer { + private final Map data; + private final Function source; + private final Set checkedSuper = new HashSet<>(); + + DependencyAnalyzer(Map data, Function source) { + this.data = data; + this.source = source; + } + void analyze() { for (final ResourceData resource : new ArrayList<>(data.values())) { if (resource == null) { @@ -117,7 +126,7 @@ void analyze() { if (name.charAt(0) == '[') { addType(name); } else { - addName(name); + addSuperTypes(name); } } case PooledConstant.CONSTANT_NameAndType -> { @@ -138,6 +147,40 @@ void analyze() { } } + private void addSuperTypes(String className) { + if (!checkedSuper.add(className)) { + return; // already visited + } + + addName(className); + ResourceData resource = data.get(className); + if (resource == null) { + return; + } + final var is = new DataInputFullStream(resource.data()); + try { + is.discard(8); // skip magic and version + final var cp = new ConstantPool(is); + is.discard(4); //skip access flags and this class + int superclassIndex = is.readUnsignedShort(); + if (superclassIndex == 0) { + return; + } + PooledConstant superclass = cp.getConstant(superclassIndex); + String superclassName = ((PrimitiveConstant) superclass).getString(); + addSuperTypes(superclassName); + int interfacesCount = is.readUnsignedShort(); + for (int i = 0; i < interfacesCount; i++) { + int interfaceIndex = is.readUnsignedShort(); + PooledConstant interfaceConstant = cp.getConstant(interfaceIndex); + String str = ((PrimitiveConstant) interfaceConstant).getString(); + addSuperTypes(str); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + private void addMethodType(String descriptor) { if (descriptor == null || descriptor.isEmpty()) { return;