From ff47129cf3ac12817bf4ca9af8753592298f03e4 Mon Sep 17 00:00:00 2001 From: zaaarf Date: Tue, 21 Mar 2023 18:24:29 +0100 Subject: [PATCH] feat: restored flat descriptors, implemented primitive proxies --- .../java/ftbsc/lll/proxies/AbstractProxy.java | 36 +++---- .../java/ftbsc/lll/proxies/FieldProxy.java | 12 +-- .../java/ftbsc/lll/proxies/MethodProxy.java | 20 ++-- .../ftbsc/lll/proxies/QualifiableProxy.java | 6 +- .../{ClassProxy.java => TypeProxy.java} | 99 ++++++++++++------- .../lll/tools/nodes/FieldProxyInsnNode.java | 2 +- .../lll/tools/nodes/MethodProxyInsnNode.java | 2 +- .../lll/tools/nodes/TypeProxyInsnNode.java | 23 +++++ 8 files changed, 126 insertions(+), 74 deletions(-) rename src/main/java/ftbsc/lll/proxies/{ClassProxy.java => TypeProxy.java} (54%) create mode 100644 src/main/java/ftbsc/lll/tools/nodes/TypeProxyInsnNode.java diff --git a/src/main/java/ftbsc/lll/proxies/AbstractProxy.java b/src/main/java/ftbsc/lll/proxies/AbstractProxy.java index 93eaec8..d60f3d5 100644 --- a/src/main/java/ftbsc/lll/proxies/AbstractProxy.java +++ b/src/main/java/ftbsc/lll/proxies/AbstractProxy.java @@ -15,9 +15,9 @@ public abstract class AbstractProxy { public final String name; /** - * The {@link Type} corresponding to this element. + * The descriptor for this element. */ - public final Type type; + public final String descriptor; /** * The fully qualified name (i.e. java.lang.String) of @@ -34,13 +34,13 @@ public abstract class AbstractProxy { /** * The private constructor, should be called by all classes extending this in theirs. * @param name the name of the element - * @param type the {@link Type} for the element + * @param descriptor the descriptor for the element * @param modifiers the modifiers, as a packed int * @param parent the FQN of the parent class */ - protected AbstractProxy(String name, Type type, int modifiers, QualifiableProxy parent) { + protected AbstractProxy(String name, String descriptor, int modifiers, QualifiableProxy parent) { this.name = name; - this.type = type; + this.descriptor = descriptor; this.modifiers = modifiers; this.parent = parent; } @@ -57,7 +57,7 @@ public abstract class AbstractProxy { return p.parent.equals(this.parent) && p.name.equals(this.name) && p.modifiers == this.modifiers - && p.type.equals(this.type); + && p.descriptor.equals(this.descriptor); } else return false; } @@ -83,9 +83,9 @@ public abstract class AbstractProxy { protected QualifiableProxy parent; /** - * The {@link Type} corresponding to the element. + * The descriptor of the element. */ - protected Type type; + protected String descriptor; /** * The constructor. @@ -123,22 +123,22 @@ public abstract class AbstractProxy { return this; } - /** - * @param type the {@link Type} corresponding to the element - * @return the current state of the builder - */ - public Builder setType(Type type) { - this.type = type; - return this; - } - /** * Sets {@link Type} for this element from the descriptor, passed as a {@link String}. * @param descriptor the descriptor passed as a {@link String} * @return the builder's state after the change */ public Builder setDescriptor(String descriptor) { - return this.setType(Type.getType(descriptor)); + this.descriptor = descriptor; + return this; + } + + /** + * @param type the {@link Type} corresponding to the element + * @return the current state of the builder + */ + public Builder setType(Type type) { + return this.setDescriptor(type.getDescriptor()); } /** diff --git a/src/main/java/ftbsc/lll/proxies/FieldProxy.java b/src/main/java/ftbsc/lll/proxies/FieldProxy.java index 8855cd8..d374bf7 100644 --- a/src/main/java/ftbsc/lll/proxies/FieldProxy.java +++ b/src/main/java/ftbsc/lll/proxies/FieldProxy.java @@ -16,18 +16,18 @@ public class FieldProxy extends AbstractProxy { * @param f the {@link Field} object corresponding to this. */ public FieldProxy(Field f) { - super(f.getName(), Type.getType(f.getType()), f.getModifiers(), ClassProxy.from(f.getDeclaringClass())); + super(f.getName(), Type.getDescriptor(f.getType()), f.getModifiers(), TypeProxy.from(f.getDeclaringClass())); } /** * Protected constructor, called only from the builder. * @param name the name of the field - * @param type the {@link Type} of the field + * @param descriptor the descriptor of the field * @param modifiers the modifiers of the field * @param parent the {@link QualifiableProxy} for the parent */ - protected FieldProxy(String name, Type type, int modifiers, QualifiableProxy parent) { - super(name, type, modifiers, parent); + protected FieldProxy(String name, String descriptor, int modifiers, QualifiableProxy parent) { + super(name, descriptor, modifiers, parent); } /** @@ -68,7 +68,7 @@ public class FieldProxy extends AbstractProxy { * @return the builder's state after the change */ public Builder setParent(String parentFQN, int modifiers) { - super.setParent(ClassProxy.from(parentFQN, 0, modifiers)); + super.setParent(TypeProxy.from(parentFQN, 0, modifiers)); return this; } @@ -88,7 +88,7 @@ public class FieldProxy extends AbstractProxy { */ @Override public FieldProxy build() { - return new FieldProxy(this.name, this.type, this.modifiers, this.parent); + return new FieldProxy(this.name, this.descriptor, this.modifiers, this.parent); } } } diff --git a/src/main/java/ftbsc/lll/proxies/MethodProxy.java b/src/main/java/ftbsc/lll/proxies/MethodProxy.java index 5d014e9..b4c329a 100644 --- a/src/main/java/ftbsc/lll/proxies/MethodProxy.java +++ b/src/main/java/ftbsc/lll/proxies/MethodProxy.java @@ -17,14 +17,14 @@ import static ftbsc.lll.tools.DescriptorBuilder.nameToDescriptor; public class MethodProxy extends AbstractProxy { /** - * An array of {@link ClassProxy} each representing the parameters of the method. + * An array of {@link TypeProxy} each representing the parameters of the method. */ - public final ClassProxy[] parameters; + public final TypeProxy[] parameters; /** - * The {@link ClassProxy} for the return type of the method. + * The {@link TypeProxy} for the return type of the method. */ - public final ClassProxy returnType; + public final TypeProxy returnType; /** * A protected constructor, called only from the builder. @@ -35,11 +35,11 @@ public class MethodProxy extends AbstractProxy { * @param returnType the return type of the method */ protected MethodProxy(String name, int modifiers, QualifiableProxy parent, Type[] parameters, Type returnType) { - super(name, Type.getMethodType(returnType, parameters), modifiers, parent); + super(name, Type.getMethodDescriptor(returnType, parameters), modifiers, parent); this.parameters = Arrays.stream(parameters) - .map(t -> ClassProxy.from(t, 0)) - .toArray(ClassProxy[]::new); - this.returnType = ClassProxy.from(returnType, 0); + .map(t -> TypeProxy.from(t, 0)) + .toArray(TypeProxy[]::new); + this.returnType = TypeProxy.from(returnType, 0); } /** @@ -50,7 +50,7 @@ public class MethodProxy extends AbstractProxy { public MethodProxy(Method m) { this(m.getName(), m.getModifiers(), - ClassProxy.from(m.getDeclaringClass()), + TypeProxy.from(m.getDeclaringClass()), Type.getArgumentTypes(m), Type.getReturnType(m) ); @@ -142,7 +142,7 @@ public class MethodProxy extends AbstractProxy { * @return the builder's state after the change */ public Builder setParent(String parentFQN, int modifiers) { - super.setParent(ClassProxy.from(parentFQN, 0, modifiers)); + super.setParent(TypeProxy.from(parentFQN, 0, modifiers)); return this; } diff --git a/src/main/java/ftbsc/lll/proxies/QualifiableProxy.java b/src/main/java/ftbsc/lll/proxies/QualifiableProxy.java index 2efada8..adeb83d 100644 --- a/src/main/java/ftbsc/lll/proxies/QualifiableProxy.java +++ b/src/main/java/ftbsc/lll/proxies/QualifiableProxy.java @@ -4,7 +4,7 @@ import org.objectweb.asm.Type; /** * A container for information about an element which has a fully-qualified name. - * @see ClassProxy + * @see TypeProxy * @see PackageProxy * @since 0.4.0 */ @@ -27,8 +27,8 @@ public abstract class QualifiableProxy extends AbstractProxy { * @param parent the {@link QualifiableProxy} representing the parent of this element * @param fullyQualifiedName the FQN of the element */ - protected QualifiableProxy(Type type, int modifiers, QualifiableProxy parent, String fullyQualifiedName) { - super(extractSimpleNameFromFQN(fullyQualifiedName), type, modifiers, parent); + protected QualifiableProxy(String descriptor, int modifiers, QualifiableProxy parent, String fullyQualifiedName) { + super(extractSimpleNameFromFQN(fullyQualifiedName), descriptor, modifiers, parent); this.fullyQualifiedName = fullyQualifiedName; this.internalName = this.fullyQualifiedName.replace('.', '/'); } diff --git a/src/main/java/ftbsc/lll/proxies/ClassProxy.java b/src/main/java/ftbsc/lll/proxies/TypeProxy.java similarity index 54% rename from src/main/java/ftbsc/lll/proxies/ClassProxy.java rename to src/main/java/ftbsc/lll/proxies/TypeProxy.java index 41e9bb8..d621465 100644 --- a/src/main/java/ftbsc/lll/proxies/ClassProxy.java +++ b/src/main/java/ftbsc/lll/proxies/TypeProxy.java @@ -11,81 +11,93 @@ import static ftbsc.lll.tools.DescriptorBuilder.nameToDescriptor; * in ASM patching. * @since 0.4.0 */ -public class ClassProxy extends QualifiableProxy { +public class TypeProxy extends QualifiableProxy { + /** + * Whether this proxy represents a primitive. + */ + public final boolean primitive; + /** * Protected constructor, called only from the builder. * @param name the name of the class - * @param type the {@link Type} of the class + * @param descriptor the descriptor of the class * @param modifiers the modifiers of the class * @param parent the package containing this class */ - protected ClassProxy(String name, Type type, int modifiers, String parent) { - super(type, modifiers, PackageProxy.from(parent), String.format("%s.%s", name, parent)); + protected TypeProxy(String name, String descriptor, int modifiers, String parent, boolean primitive) { + super(descriptor, modifiers, PackageProxy.from(parent), String.format("%s.%s", name, parent)); + this.primitive = primitive; } /** * Protected constructor, called only from the builder. * @param name the name of the class - * @param type the {@link Type} of the class + * @param descriptor the descriptor of the element * @param modifiers the modifiers of the class * @param containerClass the FQN of the parent class of the class */ - protected ClassProxy(String name, Type type, int modifiers, QualifiableProxy containerClass) { - super(type, modifiers, containerClass, String.format("%s$%s", name, containerClass.fullyQualifiedName)); + protected TypeProxy(String name, String descriptor, int modifiers, QualifiableProxy containerClass, boolean primitive) { + super(descriptor, modifiers, containerClass, String.format("%s$%s", name, containerClass.fullyQualifiedName)); + this.primitive = primitive; } /** - * Builds a {@link ClassProxy} from a {@link Type} and modifiers. + * Builds a {@link TypeProxy} from a {@link Type} and modifiers. * @param type the {@link Type} representing this Class * @param modifiers the modifiers of the class */ - public static ClassProxy from(Type type, int modifiers) { + public static TypeProxy from(Type type, int modifiers) { + while(type.getSort() == Type.ARRAY) + type = type.getElementType(); String fqn = type.getInternalName().replace('/', '.'); String simpleName = extractSimpleNameFromFQN(fqn); String parent = extractParentFromFQN(fqn); + boolean primitive = type.getSort() < Type.ARRAY; if(fqn.contains("$")) - return new ClassProxy(simpleName, type, modifiers, from(parent, 0, Modifier.PUBLIC)); - else return new ClassProxy(simpleName, type, modifiers, parent); + return new TypeProxy(simpleName, type.getDescriptor(), modifiers, from(type, Modifier.PUBLIC), primitive); + else return new TypeProxy(simpleName, type.getDescriptor(), modifiers, parent, primitive); } /** - * Builds a {@link ClassProxy} given only the fully-qualified name and modifiers. + * Builds a {@link TypeProxy} given only the fully-qualified name and modifiers. * @param fqn the fully qualified name of the desired class * @param arrayLevel the array level for this type * @param modifiers the access modifiers of the desired class * @implNote If present, parent classes will be assumed to have {@code public} as * their only modifier. - * @return the built {@link ClassProxy} + * @return the built {@link TypeProxy} */ - protected static ClassProxy from(String fqn, int arrayLevel, int modifiers) { + protected static TypeProxy from(String fqn, int arrayLevel, int modifiers) { return from(Type.getObjectType(nameToDescriptor(fqn, arrayLevel)), modifiers); } /** - * Builds a {@link ClassProxy} from a {@link Class} object. + * Builds a {@link TypeProxy} from a {@link Class} object. * @param clazz the {@link Class} object representing the target class - * @return the built {@link ClassProxy} + * @return the built {@link TypeProxy} */ - public static ClassProxy from(Class clazz) { + public static TypeProxy from(Class clazz) { Class parentClass = clazz.getEnclosingClass(); if(parentClass == null) - return new ClassProxy( + return new TypeProxy( clazz.getSimpleName(), - Type.getType(clazz), + Type.getDescriptor(clazz), clazz.getModifiers(), - clazz.getPackage().getName() + clazz.getPackage().getName(), + clazz.isPrimitive() ); else - return new ClassProxy( + return new TypeProxy( clazz.getSimpleName(), - Type.getType(clazz), + Type.getDescriptor(clazz), clazz.getModifiers(), - from(parentClass) + from(parentClass), + clazz.isPrimitive() ); } /** - * Returns a new instance of {@link ClassProxy.Builder}. + * Returns a new instance of {@link TypeProxy.Builder}. * @param name the name of the class * @return the builder object for class proxies */ @@ -100,13 +112,18 @@ public class ClassProxy extends QualifiableProxy { */ @Override public boolean equals(Object obj) { - return obj instanceof ClassProxy && super.equals(obj); + return obj instanceof TypeProxy && super.equals(obj); } /** - * A builder object for {@link ClassProxy}. + * A builder object for {@link TypeProxy}. */ - public static class Builder extends AbstractProxy.Builder { + public static class Builder extends AbstractProxy.Builder { + + /** + * Whether the proxy represents a primitive. + */ + private boolean primitive; /** * The constructor of the builder, used only internally. @@ -114,6 +131,7 @@ public class ClassProxy extends QualifiableProxy { */ Builder(String name) { super(name); + this.primitive = false; } /** @@ -124,12 +142,12 @@ public class ClassProxy extends QualifiableProxy { * @return the builder's state after the change */ public Builder setParent(Class containerClass) { - super.setParent(ClassProxy.from(containerClass)); + super.setParent(TypeProxy.from(containerClass)); return this; } /** - * Sets this class as an inner class and builds a {@link ClassProxy} + * Sets this class as an inner class and builds a {@link TypeProxy} * from the given parent and modifiers. * @param parentFQN the fully qualified name of the parent * @param modifiers the modifiers of the parent (if it's a class) @@ -137,12 +155,12 @@ public class ClassProxy extends QualifiableProxy { * @return the builder's state after the change */ public Builder setParent(String parentFQN, int modifiers, boolean isParentPackage) { - super.setParent(isParentPackage ? PackageProxy.from(parentFQN) : ClassProxy.from(parentFQN, 0, modifiers)); + super.setParent(isParentPackage ? PackageProxy.from(parentFQN) : TypeProxy.from(parentFQN, 0, modifiers)); return this; } /** - * Sets this class as an inner class and builds a {@link ClassProxy} + * Sets this class as an inner class and builds a {@link TypeProxy} * from the given parent. * @param parentFQN the fully qualified name of the parent * @param isParentPackage whether this parent should be interpreted as a package or class @@ -153,12 +171,23 @@ public class ClassProxy extends QualifiableProxy { } /** - * Builds a {@link ClassProxy} of the given kind. - * @return the built {@link ClassProxy} + * Sets the primitive flag to true or false, to signal that the type here specified + * is a primitive. + * @param primitive the new state of the primitive flag + * @return the builder's state after the change + */ + public Builder setPrimitive(boolean primitive) { + this.primitive = primitive; + return this; + } + + /** + * Builds a {@link TypeProxy} of the given kind. + * @return the built {@link TypeProxy} */ @Override - public ClassProxy build() { - return new ClassProxy(this.name, this.type, this.modifiers, this.parent); + public TypeProxy build() { + return new TypeProxy(this.name, this.descriptor, this.modifiers, this.parent, this.primitive); } } } \ No newline at end of file diff --git a/src/main/java/ftbsc/lll/tools/nodes/FieldProxyInsnNode.java b/src/main/java/ftbsc/lll/tools/nodes/FieldProxyInsnNode.java index 479e651..068ade0 100644 --- a/src/main/java/ftbsc/lll/tools/nodes/FieldProxyInsnNode.java +++ b/src/main/java/ftbsc/lll/tools/nodes/FieldProxyInsnNode.java @@ -17,6 +17,6 @@ public class FieldProxyInsnNode extends FieldInsnNode { * @param f a {@link FieldProxy} representing the field to call */ public FieldProxyInsnNode(int opcode, FieldProxy f) { - super(opcode, f.parent.internalName, f.name, f.type.getDescriptor()); + super(opcode, f.parent.internalName, f.name, f.descriptor); } } diff --git a/src/main/java/ftbsc/lll/tools/nodes/MethodProxyInsnNode.java b/src/main/java/ftbsc/lll/tools/nodes/MethodProxyInsnNode.java index 4fb3b89..01549a8 100644 --- a/src/main/java/ftbsc/lll/tools/nodes/MethodProxyInsnNode.java +++ b/src/main/java/ftbsc/lll/tools/nodes/MethodProxyInsnNode.java @@ -18,6 +18,6 @@ public class MethodProxyInsnNode extends MethodInsnNode { * @param m a {@link MethodProxy} representing the method to call */ public MethodProxyInsnNode(int opcode, MethodProxy m) { - super(opcode, m.parent.internalName, m.name, m.type.getDescriptor()); + super(opcode, m.parent.internalName, m.name, m.descriptor); } } diff --git a/src/main/java/ftbsc/lll/tools/nodes/TypeProxyInsnNode.java b/src/main/java/ftbsc/lll/tools/nodes/TypeProxyInsnNode.java new file mode 100644 index 0000000..e5b5f2a --- /dev/null +++ b/src/main/java/ftbsc/lll/tools/nodes/TypeProxyInsnNode.java @@ -0,0 +1,23 @@ +package ftbsc.lll.tools.nodes; + +import ftbsc.lll.proxies.TypeProxy; +import org.objectweb.asm.tree.TypeInsnNode; + +/** + * Overrides the {@link TypeInsnNode} to add a constructor + * taking in a {@link TypeProxy}. + * @since 0.4.0 + */ +public class TypeProxyInsnNode extends TypeInsnNode { + /** + * Constructs a new {@link TypeInsnNode} starting from a + * {@link TypeProxy}. The user should ensure that the TypeInsnNode + * represents a declared type before calling this. + * @param opcode the opcode, must be one of NEW, ANEWARRAY, + * CHECKCAST or INSTANCEOF + * @param t a {@link TypeProxy} representing the type to call + */ + public TypeProxyInsnNode(int opcode, TypeProxy t) { + super(opcode, t.internalName); + } +}