Package org.spongepowered.asm.mixin.injection.selectors.dynamic

## Class DynamicSelectorDesc

- java.lang.Object
- - org.spongepowered.asm.mixin.injection.selectors.dynamic.DynamicSelectorDesc

- All Implemented Interfaces:
    `ITargetSelector`, `ITargetSelectorByName`, `ITargetSelectorDynamic`

      public class DynamicSelectorDesc
      extends java.lang.Object
      implements ITargetSelectorDynamic, ITargetSelectorByName

  A `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.Configure`

    - ### Nested classes/interfaces inherited from interface org.spongepowered.asm.mixin.injection.selectors.ITargetSelectorDynamic

      `ITargetSelectorDynamic.SelectorAnnotation, ITargetSelectorDynamic.SelectorId`

  - ### Constructor Summary

    Constructors
    Modifier | Constructor | Description
    --- | --- | ---
    `protected` | `DynamicSelectorDesc​(InvalidSelectorException ex, java.lang.String id, org.objectweb.asm.Type owner, java.lang.String name, org.objectweb.asm.Type[] args, org.objectweb.asm.Type returnType, Quantifier matches, java.util.List<IAnnotationHandle> next, boolean disabled)` |

  - ### Method Summary

    All Methods Static Methods Instance Methods Concrete Methods
    Modifier and Type | Method | Description
    --- | --- | ---
    `ITargetSelector` | `attach​(ISelectorContext context)` | Attach this selector to the specified context.
    `ITargetSelector` | `configure​(ITargetSelector.Configure request, java.lang.String... args)` | Configure and return a modified version of this selector by consuming the supplied arguments.
    `org.objectweb.asm.Type[]` | `getArgs()` |
    `java.lang.String` | `getDesc()` | Get the member descriptor, can be null
    `java.lang.String` | `getId()` |
    `int` | `getMaxMatchCount()` | Maximum number of candidates this selector can match
    `int` | `getMinMatchCount()` | Minimum number of candidates this selector must match
    `java.lang.String` | `getName()` | Get the member name, can be null
    `java.lang.String` | `getOwner()` | Get the member owner, can be null
    `org.objectweb.asm.Type` | `getReturnType()` |
    `<TNode> MatchResult` | `match​(ElementNode<TNode> node)` | Test whether this selector matches the supplied element node
    `MatchResult` | `matches​(java.lang.String owner, java.lang.String name, java.lang.String desc)` | Test whether this selector matches the supplied values.
    `ITargetSelector` | `next()` | Get the next target selector in this path (or `null` if this selector is the last selector in the chain.
    `protected ITargetSelector` | `next​(int index)` |
    `static DynamicSelectorDesc` | `of​(IResolvedDescriptor desc)` | Convert the supplied annotation into a selector instance
    `static DynamicSelectorDesc` | `of​(IAnnotationHandle desc, ISelectorContext context)` | Convert the supplied annotation into a selector instance
    `static DynamicSelectorDesc` | `parse​(java.lang.String input, ISelectorContext context)` | Parse a descriptor selector from the supplied input.
    `static DynamicSelectorDesc` | `parse​(IAnnotationHandle desc, ISelectorContext context)` | Convert the supplied annotation into a selector instance
    `static DynamicSelectorDesc` | `resolve​(ISelectorContext context)` | Resolve a descriptor selector from the supplied context only, implicit coordinates are used.
    `java.lang.String` | `toDescriptor()` | Get a representation of this selector as a complete descriptor
    `java.lang.String` | `toString()` |
    `ITargetSelector` | `validate()` | Perform basic sanity-check validation of the selector, checks that the parsed out parameters are basically sane

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait`

- - ### Constructor Detail

    - #### DynamicSelectorDesc

          protected DynamicSelectorDesc​(InvalidSelectorException ex,
                                        java.lang.String id,
                                        org.objectweb.asm.Type owner,
                                        java.lang.String name,
                                        org.objectweb.asm.Type[] args,
                                        org.objectweb.asm.Type returnType,
                                        Quantifier matches,
                                        java.util.List<IAnnotationHandle> next,
                                        boolean disabled)

  - ### Method Detail

    - #### parse

          public static DynamicSelectorDesc parse​(java.lang.String input,
                                                  ISelectorContext context)

      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 empty
        `context` - Selector context
      Returns:
        parsed selector

    - #### parse

          public static DynamicSelectorDesc parse​(IAnnotationHandle desc,
                                                  ISelectorContext context)

      Convert the supplied annotation into a selector instance
      Parameters:
        `context` - Selector context
        `desc` - Annotation to parse
      Returns:
        selector

    - #### resolve

          public static DynamicSelectorDesc resolve​(ISelectorContext context)

      Resolve a descriptor selector from the supplied context only, implicit coordinates are used.
      Parameters:
        `context` - Selector context
      Returns:
        parsed selector

    - #### of

          public static DynamicSelectorDesc of​(IAnnotationHandle desc,
                                               ISelectorContext context)

      Convert the supplied annotation into a selector instance
      Parameters:
        `desc` - Annotation to parse
        `context` - Selector context
      Returns:
        selector

    - #### of

          public static DynamicSelectorDesc of​(IResolvedDescriptor desc)

      Convert the supplied annotation into a selector instance
      Parameters:
        `desc` - Resolved descriptor
      Returns:
        selector

    - #### toString

          public java.lang.String toString()

      Overrides:
        `toString` in class `java.lang.Object`

    - #### getId

          public java.lang.String getId()

    - #### getOwner

          public java.lang.String getOwner()

      Description copied from interface: `ITargetSelectorByName`
      Get the member owner, can be null
      Specified by:
        `getOwner` in interface `ITargetSelectorByName`

    - #### getName

          public java.lang.String getName()

      Description copied from interface: `ITargetSelectorByName`
      Get the member name, can be null
      Specified by:
        `getName` in interface `ITargetSelectorByName`

    - #### getArgs

          public org.objectweb.asm.Type[] getArgs()

    - #### getReturnType

          public org.objectweb.asm.Type getReturnType()

    - #### getDesc

          public java.lang.String getDesc()

      Description copied from interface: `ITargetSelectorByName`
      Get the member descriptor, can be null
      Specified by:
        `getDesc` in interface `ITargetSelectorByName`

    - #### toDescriptor

          public java.lang.String toDescriptor()

      Description copied from interface: `ITargetSelectorByName`
      Get a representation of this selector as a complete descriptor
      Specified by:
        `toDescriptor` in interface `ITargetSelectorByName`

    - #### validate

          public ITargetSelector validate()
                                   throws InvalidSelectorException

      Description copied from interface: `ITargetSelector`
      Perform basic sanity-check validation of the selector, checks that the parsed out parameters are basically sane
      Specified by:
        `validate` in interface `ITargetSelector`
      Returns:
        fluent (this selector)
      Throws:
        `InvalidSelectorException` - if any sanity check fails

    - #### next

          public ITargetSelector next()

      Description copied from interface: `ITargetSelector`
      Get 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:
        `next` in interface `ITargetSelector`

    - #### next

          protected ITargetSelector next​(int index)

    - #### configure

          public ITargetSelector configure​(ITargetSelector.Configure request,
                                           java.lang.String... args)

      Description copied from interface: `ITargetSelector`
      Configure 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:
        `configure` in interface `ITargetSelector`
      Parameters:
        `request` - Requested operation
        `args` - Configuration arguments
      Returns:
        Configured selector, may return this selector if the specified condition is already satisfied

    - #### attach

          public ITargetSelector attach​(ISelectorContext context)
                                 throws InvalidSelectorException

      Description copied from interface: `ITargetSelector`
      Attach 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, an `InvalidSelectorException` is thrown.
      Specified by:
        `attach` in interface `ITargetSelector`
      Parameters:
        `context` - Context to attach to
      Returns:
        Attached selector
      Throws:
        `InvalidSelectorException`

    - #### getMinMatchCount

          public int getMinMatchCount()

      Description copied from interface: `ITargetSelector`
      Minimum number of candidates this selector must match
      Specified by:
        `getMinMatchCount` in interface `ITargetSelector`

    - #### getMaxMatchCount

          public int getMaxMatchCount()

      Description copied from interface: `ITargetSelector`
      Maximum number of candidates this selector can match
      Specified by:
        `getMaxMatchCount` in interface `ITargetSelector`

    - #### matches

          public MatchResult matches​(java.lang.String owner,
                                     java.lang.String name,
                                     java.lang.String desc)

      Description copied from interface: `ITargetSelectorByName`
      Test whether this selector matches the supplied values. Null values are ignored.
      Specified by:
        `matches` in interface `ITargetSelectorByName`
      Parameters:
        `owner` - Owner to compare with, null to skip
        `name` - Name to compare with, null to skip
        `desc` - 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

          public <TNode> MatchResult match​(ElementNode<TNode> node)

      Description copied from interface: `ITargetSelector`
      Test whether this selector matches the supplied element node
      Specified by:
        `match` in interface `ITargetSelector`
      Type Parameters:
        `TNode` - node type
      Parameters:
        `node` - node node to test
      Returns:
        true if this selector can match the supplied field