Skip to content

Commit

Permalink
Flesh out Desc selector javadoc and functionality
Browse files Browse the repository at this point in the history
Mumfrey committed Feb 3, 2021
1 parent f9aeec8 commit ef6422f
Showing 31 changed files with 624 additions and 192 deletions.
Original file line number Diff line number Diff line change
@@ -147,7 +147,7 @@ public IAnnotationHandle getAnnotation(Class<? extends Annotation> annotationCla
}

@Override
public Object getSelectorAnnotation() {
public IAnnotationHandle getSelectorAnnotation() {
return this.getAnnotation();
}

Original file line number Diff line number Diff line change
@@ -54,7 +54,7 @@
/**
* A module for {@link AnnotatedMixin} which handles accessors
*/
public class AnnotatedMixinElementHandlerAccessor extends AnnotatedMixinElementHandler {
class AnnotatedMixinElementHandlerAccessor extends AnnotatedMixinElementHandler {

/**
* Accessor element
Original file line number Diff line number Diff line change
@@ -46,6 +46,7 @@
import org.spongepowered.asm.mixin.refmap.IMixinContext;
import org.spongepowered.asm.obfuscation.mapping.common.MappingField;
import org.spongepowered.asm.obfuscation.mapping.common.MappingMethod;
import org.spongepowered.asm.util.asm.IAnnotationHandle;
import org.spongepowered.tools.obfuscation.ReferenceManager.ReferenceConflictException;
import org.spongepowered.tools.obfuscation.ext.SpecialPackages;
import org.spongepowered.tools.obfuscation.interfaces.IMixinAnnotationProcessor;
@@ -126,7 +127,7 @@ public AnnotationHandle getAt() {
}

@Override
public Object getSelectorAnnotation() {
public IAnnotationHandle getSelectorAnnotation() {
return this.getAt();
}

Original file line number Diff line number Diff line change
@@ -43,7 +43,7 @@
/**
* A module for {@link AnnotatedMixin} whic handles soft-implements clauses
*/
public class AnnotatedMixinElementHandlerSoftImplements extends AnnotatedMixinElementHandler {
class AnnotatedMixinElementHandlerSoftImplements extends AnnotatedMixinElementHandler {

AnnotatedMixinElementHandlerSoftImplements(IMixinAnnotationProcessor ap, AnnotatedMixin mixin) {
super(ap, mixin);
Original file line number Diff line number Diff line change
@@ -40,7 +40,7 @@
/**
* Base class for mixin annotation processor modules
*/
public abstract class MixinObfuscationProcessor extends AbstractProcessor {
abstract class MixinObfuscationProcessor extends AbstractProcessor {

/**
* Mixin info manager
Original file line number Diff line number Diff line change
@@ -28,6 +28,7 @@
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -79,7 +80,7 @@ public MixinContainer(MixinPlatformManager manager, IContainerHandle handle) {
continue;
}

MixinContainer.logger.debug("{} {} container {}", simpleName, acceptAction.name().toLowerCase(), this.handle);
MixinContainer.logger.debug("{} {} container {}", simpleName, acceptAction.name().toLowerCase(Locale.ROOT), this.handle);
} catch (InstantiationException ex) {
Throwable cause = ex.getCause();
if (cause instanceof RuntimeException) {
Original file line number Diff line number Diff line change
@@ -73,7 +73,7 @@ protected final MethodNode createMethod(int maxLocals, int maxStack) {
MethodNode accessor = new MethodNode(ASM.API_VERSION, (method.access & ~Opcodes.ACC_ABSTRACT) | Opcodes.ACC_SYNTHETIC, method.name,
method.desc, null, null);
accessor.visibleAnnotations = new ArrayList<AnnotationNode>();
accessor.visibleAnnotations.add(this.info.getAnnotation());
accessor.visibleAnnotations.add(this.info.getAnnotationNode());
accessor.maxLocals = maxLocals;
accessor.maxStack = maxStack;
return accessor;
Original file line number Diff line number Diff line change
@@ -461,7 +461,7 @@ public boolean isStatic() {
@Override
public String toString() {
String typeString = this.type != null ? this.type.toString() : "UNPARSED_ACCESSOR";
return String.format("%s->@%s[%s]::%s%s", this.mixin, Bytecode.getSimpleName(this.annotation), typeString,
return String.format("%s->@%s[%s]::%s%s", this.mixin, Annotations.getSimpleName(this.annotation), typeString,
this.methodName, this.method.desc);
}

69 changes: 66 additions & 3 deletions src/main/java/org/spongepowered/asm/mixin/injection/Desc.java
Original file line number Diff line number Diff line change
@@ -30,22 +30,85 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.spongepowered.asm.mixin.injection.selectors.dynamic.DynamicSelectorDesc;
import org.spongepowered.asm.mixin.injection.struct.MemberInfo;

/**
* TODO Javadoc
* <p>A descriptor for matching a target element, for details of usage see
* {@link DynamicSelectorDesc}.</p>
*
* <p>Unlike {@link MemberInfo Explicit Target Selectors} which can match any
* element of a candidate member, <tt>&#064;Desc</tt> descriptors always match
* all elements of a target explicitly. Element defaults are as follows:</p>
*
* <blockquote><dl>
* <dt>{@link #owner}</dt>
* <dd>Defaults to the current target of the mixin if not specified</dd>
* <dt>{@link #ret}</dt>
* <dd>Defaults to <tt>void</tt></dd>
* <dt>{@link #args}</dt>
* <dd>Defaults to an empty array matching a target with <b>no arguments</b>,
* omitting this value does <em>not</em> mean "match any" signature and
* will explicitly match targets with no arguments. This value is ignored
* for fields.</dd>
* </dl></blockquote>
*
* <h4>Notes</h4>
*
* <ul>
* <li>It should be noted that specifying the only required value
* ({@link #value}) will therefore match elements with owner type equal to the
* current mixin target, taking no arguments and returning void.</li>
*
* <li>Note that when matching fields the value of {@link #args} is ignored.
* </li>
* </ul>
*/
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Descriptors.class)
public @interface Desc {

/**
* The identifier for this descriptor. Can be an implicit coordinate or a
* user-defined string. IDs are not case-sensitive but must be unique within
* a mixin or resolution scope. For more details on resolution for
* descriptors see {@link DynamicSelectorDesc}.
*/
public String id() default "";

public Class<?> owner() default Void.class;
/**
* The owner of the member to match. The "owner" is the class which declares
* the member <b>or, ocasionally</b> the type of class upon which a virtual
* call is being made. For example if a class <tt>SuperType</tt> defines a
* method <tt>doSomething</tt>, usually <tt>owner</tt> will be
* <tt>SuperType</tt>. However note that where a method retrieves a
* reference to a derived type <tt>DerivedType</tt> which overrides
* <tt>doSomething</tt>, it's possible the invocation will be made using
* that type. To ensure usage of the correct type, inspect the disassembled
* bytecode for your target.
*
* <p>When <tt>owner</tt> is not specified, it defaults to the <em>current
* </em> target of the mixin.</p>
*/
public Class<?> owner() default void.class;

/**
* The name of the member to match. Must be specified. Matched
* case-sensitively against targets.
*/
public String value();

public Class<?> ret() default Void.class;
/**
* The return type of a method to match, or the declared type of a field.
* Defaults to <tt>void</tt>.
*/
public Class<?> ret() default void.class;

/**
* The argument types of a method to match, ignored for fields. Note that
* failing to specify this value <b>matches a target with no arguments</b>.
*/
public Class<?>[] args() default { };

}
Original file line number Diff line number Diff line change
@@ -44,13 +44,6 @@ public interface IInjectionPointContext extends IMessageSink, ISelectorContext {
/**
* Get the parent annotation (eg. the &#064;Inject annotation)
*/
@Override
public abstract AnnotationNode getAnnotation();

/**
* Get the selector annotation (eg. the &#064;At annotation)
*/
@Override
public abstract AnnotationNode getSelectorAnnotation();
public abstract AnnotationNode getAnnotationNode();

}
Original file line number Diff line number Diff line change
@@ -38,6 +38,7 @@
import java.util.LinkedHashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
@@ -58,7 +59,6 @@
import org.spongepowered.asm.mixin.struct.AnnotatedMethodInfo;
import org.spongepowered.asm.mixin.transformer.MixinTargetContext;
import org.spongepowered.asm.util.Annotations;
import org.spongepowered.asm.util.Bytecode;
import org.spongepowered.asm.util.IMessageSink;

import com.google.common.base.Joiner;
@@ -715,7 +715,7 @@ public static InjectionPoint parse(IInjectionPointContext context, String at, At
@SuppressWarnings("unchecked")
private static Class<? extends InjectionPoint> findClass(IMixinContext context, InjectionPointData data) {
String type = data.getType();
Class<? extends InjectionPoint> ipClass = InjectionPoint.types.get(type);
Class<? extends InjectionPoint> ipClass = InjectionPoint.types.get(type.toUpperCase(Locale.ROOT));
if (ipClass == null) {
if (type.matches("^([A-Za-z_][A-Za-z0-9_]*\\.)+[A-Za-z_][A-Za-z0-9_]*$")) {
try {
@@ -761,7 +761,7 @@ private static InjectionPoint shift(IInjectionPointContext context, InjectionPoi
} else if (shift == At.Shift.AFTER) {
return InjectionPoint.after(point);
} else if (shift == At.Shift.BY) {
InjectionPoint.validateByValue(context.getMixin(), context.getMethod(), context.getAnnotation(), point, by);
InjectionPoint.validateByValue(context.getMixin(), context.getMethod(), context.getAnnotationNode(), point, by);
return InjectionPoint.shift(point, by);
}
}
@@ -793,7 +793,7 @@ private static void validateByValue(IMixinContext context, MethodNode method, An
allowed = InjectionPoint.MAX_ALLOWED_SHIFT_BY;
}

String message = String.format("@%s(%s) Shift.BY=%d on %s::%s exceeds %s%d. %s", Bytecode.getSimpleName(parent), point,
String message = String.format("@%s(%s) Shift.BY=%d on %s::%s exceeds %s%d. %s", Annotations.getSimpleName(parent), point,
by, context, method.name, limitBreached, allowed, advice);

if (err == ShiftByViolationBehaviour.WARN && allowed < InjectionPoint.MAX_ALLOWED_SHIFT_BY) {
@@ -806,7 +806,7 @@ private static void validateByValue(IMixinContext context, MethodNode method, An

protected String getAtCode() {
AtCode code = this.getClass().<AtCode>getAnnotation(AtCode.class);
return code == null ? this.getClass().getName() : code.value();
return code == null ? this.getClass().getName() : code.value().toUpperCase();
}

/**
@@ -846,9 +846,9 @@ public static void register(Class<? extends InjectionPoint> type, String namespa
code.value(), type.getName());
}

String id = code.value();
String id = code.value().toUpperCase(Locale.ROOT);
if (!Strings.isNullOrEmpty(namespace)) {
id = namespace + ":" + code.value();
id = namespace.toUpperCase(Locale.ROOT) + ":" + id;
}

InjectionPoint.types.put(id, type);
@@ -861,7 +861,9 @@ public static void register(Class<? extends InjectionPoint> type, String namespa
* @param type injection point type to register
*/
private static void registerBuiltIn(Class<? extends InjectionPoint> type) {
InjectionPoint.types.put(type.<AtCode>getAnnotation(AtCode.class).value(), type);
String code = type.<AtCode>getAnnotation(AtCode.class).value().toUpperCase(Locale.ROOT);
InjectionPoint.types.put(code, type);
InjectionPoint.types.put("MIXIN:" + code, type);
}

}
Original file line number Diff line number Diff line change
@@ -44,7 +44,6 @@
import org.spongepowered.asm.mixin.injection.throwables.InjectionError;
import org.spongepowered.asm.mixin.injection.throwables.InvalidSliceException;
import org.spongepowered.asm.util.Annotations;
import org.spongepowered.asm.util.Bytecode;

import com.google.common.base.Strings;

@@ -433,7 +432,7 @@ private String describe(String description) {
}

private static String describeSlice(String description, ISliceContext owner) {
String annotation = Bytecode.getSimpleName(owner.getAnnotation());
String annotation = Annotations.getSimpleName(owner.getAnnotationNode());
MethodNode method = owner.getMethod();
return String.format("%s->%s(%s)::%s%s", owner.getMixin(), annotation, description, method.name, method.desc);
}
Original file line number Diff line number Diff line change
@@ -99,7 +99,7 @@ public String toString() {
public static MethodSlices parse(InjectionInfo info) {
MethodSlices slices = new MethodSlices(info);

AnnotationNode annotation = info.getAnnotation();
AnnotationNode annotation = info.getAnnotationNode();
if (annotation != null) {
for (AnnotationNode node : Annotations.<AnnotationNode>getValue(annotation, "slice", true)) {
MethodSlice slice = MethodSlice.parse(info, node);
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@
package org.spongepowered.asm.mixin.injection.selectors;

import org.spongepowered.asm.mixin.refmap.IMixinContext;
import org.spongepowered.asm.util.asm.IAnnotationHandle;

/**
* Context passed to a {@link ITargetSelector Target Selector} in order to
@@ -55,12 +56,12 @@ public interface ISelectorContext {
* Get the root annotation for the selector, for example the injector or
* accessor annotation
*/
public abstract Object getAnnotation();
public abstract IAnnotationHandle getAnnotation();

/**
* Get the annotation for this selector, for example the &#064;At annotation
*/
public abstract Object getSelectorAnnotation();
public abstract IAnnotationHandle getSelectorAnnotation();

/**
* Get the coordinate for this selector. This is the local coordinate of the
Original file line number Diff line number Diff line change
@@ -26,7 +26,6 @@

import org.objectweb.asm.tree.AbstractInsnNode;
import org.spongepowered.asm.mixin.injection.struct.MemberInfo;
import org.spongepowered.asm.mixin.injection.struct.MemberMatcher;
import org.spongepowered.asm.util.asm.ElementNode;

/**
@@ -56,17 +55,17 @@
* the selector string starts with "<tt>&#064;</tt>":</p>
*
* <blockquote><pre>
* // Built-in dynamic selector without argument string
* <del>// Built-in dynamic selector without argument string</del>
* &#064;SelectorId
*
* // Built-in dynamic selector with empty argument string
* <del>// Built-in dynamic selector with empty argument string</del>
* &#064;SelectorId()
*
* // Built-in dynamic selector with argument
* <del>// Built-in dynamic selector with argument</del>
* &#064;SelectorId(custom,argument,string,in,any,format)
*
* // User-provided dynamic selector with argument. Note that user-provided
* // dynamic selectors are namespaced to avoid conflicts.
* <del>// User-provided dynamic selector with argument. Note that
* // user-provided dynamic selectors are namespaced to avoid conflicts.</del>
* &#064;Namespace:SelectorId(some arguments)</pre>
* </blockquote>
*
Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.spongepowered.asm.mixin.injection.struct;
package org.spongepowered.asm.mixin.injection.selectors;

import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -31,10 +31,6 @@
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.spongepowered.asm.mixin.injection.selectors.ISelectorContext;
import org.spongepowered.asm.mixin.injection.selectors.ITargetSelector;
import org.spongepowered.asm.mixin.injection.selectors.InvalidSelectorException;
import org.spongepowered.asm.mixin.injection.selectors.MatchResult;
import org.spongepowered.asm.util.asm.ElementNode;

/**
@@ -56,20 +52,20 @@
*
* <p>Some examples:</p>
* <blockquote><pre>
* // Matches candidates starting with "foo"
* <del>// Matches candidates starting with "foo"</del>
* /^foo/
*
* // Matches candidates ending with "Bar" and which take a single integer
* /bar$/ desc=/^\\(I\\)/
* <del>// Matches candidates ending with "Bar" and which take a single int
*</del> /bar$/ desc=/^\\(I\\)/
*
* // The same example but with "name" explicitly specified (optional)
* name=/bar$/ desc=/^\\(I\\)/
* <del>// The same example but with "name" explicitly specified (optional)
*</del> name=/bar$/ desc=/^\\(I\\)/
*
* // Matches candidates whose name contains "Entity"
* <del>// Matches candidates whose name contains "Entity"</del>
* /Entity/
*
* // Matches candidates whose owner contains "/google/", note the escaping of
* // the forward slash symbols
* <del>// Matches candidates whose owner contains "/google/", note the
* // escaping of the forward slash symbols</del>
* owner=/\\/google\\//</pre>
* </blockquote>
*
Loading

0 comments on commit ef6422f

Please sign in to comment.