Class DynamicSelectorDesc
- All Implemented Interfaces:
ITargetSelector,ITargetSelectorByName,ITargetSelectorDynamic
Target Selector which matches candidates using
descriptors contained in @Desc annotations. The descriptor
annotations may be local, or may be applied to the method or even the owning
mixin using user-specified ids, or implicit coordinates based on the relative
location of the consumer. eg. an @At annotation and the @Desc
annotation itself, which might be on a parent element for convenience.
See @Desc for the specific syntax of descriptor
annotations.
Local Descriptors
Some annotations can use @Desc selectors directly,
namely @At (specified in @At.desc) and
all Injector annotations (specified in target - for example
@Inject.target). In these cases it is not
necessary to specify an id for the descriptor since the usage
is inferred from context.
Resolved Descriptors
Descriptors can also be placed as annotations on the mixin method or the
mixin class, thus allowing descriptors to be re-used by multiple consumers.
For example where several injectors target the same method, the descriptor
can be placed on the mixin itself and consumed by id. In this situation it is
necessary to specify an id for the descriptor and specify the
chosen id as a selector string:
@Mixin(TargetClass.class)
@Desc(id = "foo", value = "getFoo", args = { int.class })
abstract class MyMixin {
@Inject(target = "@Desc(foo)", at =
@At("RETURN"))
void myHandlerMethod(int arg, CallbackInfo ci) {
...
}
}
Note that the id string can be anything you wish, but is matched case-insensitively and must be non-empty, so feel free to be as descriptive as you wish.
Implicit coordinates
As an alternative to specifying an explicit descriptor id for
descriptors, it is also possible to use implicit coordinates generated using
the location of the consumer. To do so, use the selector "@Desc"
with no arguments and give the descriptor an id which
corresponds to the coordinate of the consumer:
In this example, the coordinate of the @At annotation,
"at" is used as the descriptor id.
@Desc(id = "at",
value = "theMethodName", args = { String.class }, ret = boolean.class)
@Inject(method = "targetMethod()V", at =
@At(value = "INVOKE" target = "@Desc"))
void myHandlerMethod(int arg, CallbackInfo ci) {
...
}
As the resolver widens its search it adds new components to the start of
the implicit coordinate which match the element, separated by dots. For
example @At annotations inside a @Slice
will first resolve as (local coordinate) from, followed by
slice.from, and finally handlerMethodName.slice.from. This
allows implicit coordinates to be used up to the mixin level as in the first
example.
@Mixin(TargetClass.class)
@Desc(id = "myHandlerMethod.at", value = "theMethodName",
args = { String.class }, ret = boolean.class)
@Desc(id = "myHandlerMethod.method", value = "getFoo", args =
{ int.class })
abstract class MyMixin {
@Inject(method = "@Desc", at = @At(value =
"INVOKE" target = "@Desc"))
void myHandlerMethod(int arg, CallbackInfo ci) {
...
}
To view the coordinates used to resolve the descriptor for a particular element, use the special id "?" in the selector:
@Inject(method = "@Desc", at = @At(value =
"INVOKE" target = "@Desc(?)"))
void myHandler(int arg, CallbackInfo ci) {
This will cause the resolver to pretty-print the considered coordinates and elements into the console:
/*****************************************************/ /* Coordinate Search Element Detail */ /*****************************************************/ /* at @At @At.desc */ /* at myHandler method */ /* myhandler.at mixins.json:MyMixin mixin */ /* myhandler.at @Redirect @Redirect.desc */ /* myhandler.at myhandler method */ /*****************************************************/
Don't worry that some combinations of coordinate and element are not possible (for example there is no member desc on @At). The resolver doesn't know that and scans each visited element for members it supports.
-
Nested Class Summary
Nested classes/interfaces inherited from interface org.spongepowered.asm.mixin.injection.selectors.ITargetSelector
ITargetSelector.ConfigureNested classes/interfaces inherited from interface org.spongepowered.asm.mixin.injection.selectors.ITargetSelectorDynamic
ITargetSelectorDynamic.SelectorAnnotation, ITargetSelectorDynamic.SelectorId -
Constructor Summary
ConstructorsModifierConstructorDescriptionprotectedDynamicSelectorDesc(InvalidSelectorException ex, String id, org.objectweb.asm.Type owner, String name, org.objectweb.asm.Type[] args, org.objectweb.asm.Type returnType, Quantifier matches, List<IAnnotationHandle> next, boolean disabled) -
Method Summary
Modifier and TypeMethodDescriptionattach(ISelectorContext context) Attach this selector to the specified context.configure(ITargetSelector.Configure request, String... args) Configure and return a modified version of this selector by consuming the supplied arguments.org.objectweb.asm.Type[]getArgs()getDesc()Get the member descriptor, can be nullgetId()intMaximum number of candidates this selector can matchintMinimum number of candidates this selector must matchgetName()Get the member name, can be nullgetOwner()Get the member owner, can be nullorg.objectweb.asm.Type<TNode> MatchResultmatch(ElementNode<TNode> node) Test whether this selector matches the supplied element nodeTest whether this selector matches the supplied values.next()Get the next target selector in this path (or null if this selector is the last selector in the chain.protected ITargetSelectornext(int index) static DynamicSelectorDescof(IResolvedDescriptor desc) Convert the supplied annotation into a selector instancestatic DynamicSelectorDescof(IAnnotationHandle desc, ISelectorContext context) Convert the supplied annotation into a selector instancestatic DynamicSelectorDescparse(String input, ISelectorContext context) Parse a descriptor selector from the supplied input.static DynamicSelectorDescparse(IAnnotationHandle desc, ISelectorContext context) Convert the supplied annotation into a selector instancestatic DynamicSelectorDescresolve(ISelectorContext context) Resolve a descriptor selector from the supplied context only, implicit coordinates are used.Get a representation of this selector as a complete descriptortoString()validate()Perform basic sanity-check validation of the selector, checks that the parsed out parameters are basically sane
-
Constructor Details
-
DynamicSelectorDesc
protected DynamicSelectorDesc(InvalidSelectorException ex, String id, org.objectweb.asm.Type owner, String name, org.objectweb.asm.Type[] args, org.objectweb.asm.Type returnType, Quantifier matches, List<IAnnotationHandle> next, boolean disabled)
-
-
Method Details
-
parse
Parse a descriptor selector from the supplied input. The input is treated as a descriptor id to be resolved, or if empty uses implicit coordinates from the selection context- Parameters:
input- ID string, can be emptycontext- Selector context- Returns:
- parsed selector
-
parse
Convert the supplied annotation into a selector instance- Parameters:
desc- Annotation to parsecontext- Selector context- Returns:
- selector
-
resolve
Resolve a descriptor selector from the supplied context only, implicit coordinates are used.- Parameters:
context- Selector context- Returns:
- parsed selector
-
of
Convert the supplied annotation into a selector instance- Parameters:
desc- Annotation to parsecontext- Selector context- Returns:
- selector
-
of
Convert the supplied annotation into a selector instance- Parameters:
desc- Resolved descriptor- Returns:
- selector
-
toString
-
getId
-
getOwner
Description copied from interface:ITargetSelectorByNameGet the member owner, can be null- Specified by:
getOwnerin interfaceITargetSelectorByName
-
getName
Description copied from interface:ITargetSelectorByNameGet the member name, can be null- Specified by:
getNamein interfaceITargetSelectorByName
-
getArgs
public org.objectweb.asm.Type[] getArgs() -
getReturnType
public org.objectweb.asm.Type getReturnType() -
getDesc
Description copied from interface:ITargetSelectorByNameGet the member descriptor, can be null- Specified by:
getDescin interfaceITargetSelectorByName
-
toDescriptor
Description copied from interface:ITargetSelectorByNameGet a representation of this selector as a complete descriptor- Specified by:
toDescriptorin interfaceITargetSelectorByName
-
validate
Description copied from interface:ITargetSelectorPerform basic sanity-check validation of the selector, checks that the parsed out parameters are basically sane- Specified by:
validatein interfaceITargetSelector- Returns:
- fluent (this selector)
- Throws:
InvalidSelectorException- if any sanity check fails
-
next
Description copied from interface:ITargetSelectorGet the next target selector in this path (or null if this selector is the last selector in the chain. Called at recurse points in the subject in order to match against the child subject.Can return null
- Specified by:
nextin interfaceITargetSelector
-
next
-
configure
Description copied from interface:ITargetSelectorConfigure and return a modified version of this selector by consuming the supplied arguments. Results from this method should be idempotent in terms of the configuration of the returned object, but do not have to necessarily return the same object if the callee already matches the supplied configuration, or if the requested mutation is not supported by the selector, though this is generally the case.In other words, calling configure(Configure.ORPHAN) when this object is already an orphan or does not support orphaning, may simply return this object, or might return an identically-configured copy.
Must not return null, defaults to returning unmodified selector.
- Specified by:
configurein interfaceITargetSelector- Parameters:
request- Requested operationargs- Configuration arguments- Returns:
- Configured selector, may return this selector if the specified condition is already satisfied
-
attach
Description copied from interface:ITargetSelectorAttach this selector to the specified context. Should return this selector unmodified if all is well, or a new selector to be used for further processing of the supplied context. If the supplied context is invalid, anInvalidSelectorExceptionis thrown.- Specified by:
attachin interfaceITargetSelector- Parameters:
context- Context to attach to- Returns:
- Attached selector
- Throws:
InvalidSelectorException
-
getMinMatchCount
public int getMinMatchCount()Description copied from interface:ITargetSelectorMinimum number of candidates this selector must match- Specified by:
getMinMatchCountin interfaceITargetSelector
-
getMaxMatchCount
public int getMaxMatchCount()Description copied from interface:ITargetSelectorMaximum number of candidates this selector can match- Specified by:
getMaxMatchCountin interfaceITargetSelector
-
matches
Description copied from interface:ITargetSelectorByNameTest whether this selector matches the supplied values. Null values are ignored.- Specified by:
matchesin interfaceITargetSelectorByName- Parameters:
owner- Owner to compare with, null to skipname- Name to compare with, null to skipdesc- Signature to compare with, null to skip- Returns:
- true if all non-null values in this reference match non-null arguments supplied to this method
-
match
Description copied from interface:ITargetSelectorTest whether this selector matches the supplied element node- Specified by:
matchin interfaceITargetSelector- Type Parameters:
TNode- node type- Parameters:
node- node node to test- Returns:
- true if this selector can match the supplied field
-