Package org.spongepowered.asm.mixin.injection

## Annotation Type Redirect

-     @Target(METHOD)
      @Retention(RUNTIME)
      public @interface Redirect

  Specifies that this mixin method should redirect the specified method call, field access or object construction (via the `new` keyword) to the method decorated with this annotation.

  ### Method Redirect Mode

  The handler method signature must match the hooked method precisely but prepended with an arg of the owning object's type to accept the object instance the method was going to be invoked on. For example when hooking the following call:

  >     public void baz(int someInt, String someString) {
  >         int abc = 0;
  >         int def = 1;
  >         Foo someObject = new Foo();

  >         // Hooking this method
  >         boolean xyz = someObject.bar(abc, def);
  >     }

  The signature of the redirected method should be:

  > `public boolean barProxy(Foo someObject, int abc, int def)`

  For obvious reasons this does not apply for static methods, for static methods it is sufficient that the signature simply match the redirected method.

  It is also possible to capture the arguments of the target method in addition to the arguments being passed to the method call (for example in the code above this would be the someInt and someString arguments) by appending the arguments to the method signature:

  > `public boolean barProxy(Foo someObject, int abc, int def, int someInt, String someString)`

  All arguments of a method redirect handler, and the return type, can be decorated with `Coerce` if - for example - a package-private class needs to be coerced to a duck interface or to (for example) `Object`.

  ### Field Access Redirect Mode

  The handler method signature varies depending on whether the redirector is handling a field write (`PUTFIELD`, `PUTSTATIC`) or a field read (`GETFIELD`, `GETSTATIC`).

  Operation (OPCODE) | Handler signature
  --- | ---
  Read static field (`GETSTATIC`) | `private static FieldType getFieldValue()`
  Read instance field (`GETFIELD`) | `private FieldType getFieldValue(OwnerType owner)`
  Write static field (`PUTSTATIC`) | `private static void setFieldValue(FieldType value)`
  Write instance field (`PUTFIELD`) | `private void setFieldValue(OwnerType owner, FieldType value)`

  It is also possible to capture the arguments of the target method in addition to the arguments being passed to the method call (for example in the code above this would be the someInt and someString arguments) by appending the arguments to the method signature.

  All arguments of a field redirect handler, including the field type itself, can be decorated with `Coerce` if - for example - a package-private class needs to be coerced to a duck interface or to (for example) `Object`.

  ### Array Element Access Redirect Mode

  For fields of an array type, it is possible to redirect the access to the actual array field itself using the behaviour above. However it is also possible to redirect access to individual array elements. Consider the following example:

  >     private String[] strings = { "foo", "bar", "baz" };

  >     public void print(int index) {
  >         System.err.println(this.strings[index]);
  >     }

  It may be desirable to redirect the access to this array element. To do so, declare a redirect handler which takes the array and the index (or indices, for multi-dimensional arrays) and returns the element type (in this case `String`) as follows:

  Operation | Handler signature
  --- | ---
  Read element | `private ElementType getElement(ElementType[] array, int index)`
  Write element | `private void setElement(ElementType[] array, int index, ElementType value)`

  The handler receives a reference to the array itself (read from the field) and the indices being accessed. See the `BeforeFieldAccess args` for details on matching array accesses using the `FIELD` injection point.

  ### Array Length Redirect Mode

  For fields of an array type, it is possible to redirect the call to the builtin pseudo-property `length`. To do so, specify the argument `array=length` and configure your handler signature to return `int` and consume the array as an argument:

  > `private int getLength(ElementType[] array)`

  -

  For multi-dimensional arrays, provide one `int` argument for each additional dimension of the array:

  > `// Multidimensional array
  > private ElementType[][] array;
  > // Handler signature:
  > private int getLength(ElementType[][] array, int baseDim)`

  ### New Object Redirect Mode (Factory Mode)

  Redirecting object creation requires redirection of the `NEW` operation and constructor call. Your handler method should target the `NEW` opcode using the `BeforeNew` Injection Point and construct an appropriate object. The factory method must return a new object and must not return `null` since the contract of the `new` opcode does not allow for the possibility of `null`. Your factory may throw an exception however.

  Note that `BeforeNew` differs from `BeforeInvoke` in that the shape of `target` should contain only an `owner` (to target any ctor of the specified class) or only a `descriptor` consisting of the constructor descriptor with the return type changed from `void` (`V`) to the type of object being constructed. In other words to redirect an object creation for an object `Foo`:

  >     package baz.bar;

  >     class Foo {
  >         private final int x, y;

  >         // ctor we wish to hook
  >         Foo(int x, int y) {
  >             this.x = x;
  >             this.y = y;
  >         }
  >     }

  Valid signatures for this ctor would be:

  - `Lbaz/bar/Foo;` - valid because Foo only has one ctor
  - `(II)Lbaz/bar/Foo;` - includes signature of specific ctor

  The handler method signature must match the constructor being redirected and the return type must match the type of object being constructed. For example to redirect the following object creation call:

  >     public void exampleFunc(String someString, int dx, int dy) {
  >         // Hooking this constructor
  >         Foo someFoo = new Foo(dx * 10, dy * 10);
  >     }

  The signature of the handler method should be:

  > `public Foo constructFoo(int x, int y)`

  Note that like other redirectors, it is possible to capture the target method's arguments by appending them to the handler method's signature:

  > `public Foo constructFoo(int x, int y, String someString, int dx, int dy)`

  ### `instanceof` Redirect Mode

  An `instanceof` check is a boolean operation where an object on the stack is compared with a class literal compiled directly into the bytecode. The check can be redirected in one of two ways: logic redirection or class type redirection. For the following example code:

  >     if (reference instanceof Foo) {

  To perform a logic redirection, use a handler with the following signature returning `boolean`:

  >     public boolean onInstanceOf(Object reference, Class clFoo) {
  >         return reference instanceof ADifferentClass;
  >     }

  Note that the entire check is moved into the redirect method, and the `boolean` return value is used in place of the previous `instanceof` check. To perform a class type redirection instead, construct your handler as follows:

  >     public Class onInstanceOf(Object reference, Class clFoo) {
  >         return ADifferentClass.class;
  >     }

  Note that this results in the injected code being less efficient, because the `instanceof` opcode is replaced with discrete code similar to `reference != null && yourClass.isAssignableFrom(reference.getClass())` in the target method body.

  The arguments to an `instanceof` redirect handler must always be `Object, Class` even if the variable type is known. This is because the type of variable on the stack cannot be determined without relatively expensive analysis, which is redundant given the redirect handler's role. If you need to cast-down the reference then you should do so inside your handler method.

  ### A note on `static` modifiers for handler methods

  In general, when declaring a redirect handler the `static` modifier of the handler method must always match the target method. The exception to this rule is application of `@Redirect` to instructions which are effectively before the call to `super()` in a constructor.

  Consider the following code:

  >     class Foo : Bar {
  >         Foo(int arg) {
  >             super(Foo.isEven(arg));
  >         }

  >         static int isEven(int arg) {
  >             return arg % 2 == 0;
  >         }
  >     }

  In this example, the inline call to `Foo.isEven` takes place before the call to `super()` and (per Java rules) this method must be static (because the instance (`this`) is unavailable until the initialiser is complete. Thus if you wish to `@Redirect` the call to `isEven` then the handler method must also be `static`. The injection subsystem will raise an exception for non-static handlers in this situation to indicate that the staticness of the handler is incorrect.

- - ### Required Element Summary

    Required Elements
    Modifier and Type | Required Element | Description
    --- | --- | ---
    `At` | `at` | An `At` annotation which describes the `InjectionPoint` in the target method.

  - ### Optional Element Summary

    Optional Elements
    Modifier and Type | Optional Element | Description
    --- | --- | ---
    `int` | `allow` | Injection points are in general expected to match every candidate instruction in the target method or slice, except in cases where options such as `At.ordinal()` are specified which naturally limit the number of results.
    `java.lang.String` | `constraints` | Returns constraints which must be validated for this injector to succeed.
    `int` | `expect` | Like `require()` but only enabled if the `mixin.debug.countInjections` option is set to `true` and defaults to 1.
    `java.lang.String[]` | `method` | String representation of one or more `target selectors` which identify the target methods.
    `int` | `order` | By default almost all injectors for a target class apply their injections at the same time.
    `boolean` | `remap` | By default, the annotation processor will attempt to locate an obfuscation mapping for all `Redirect` methods since it is anticipated that in general the target of a `Redirect` annotation will be an obfuscated method in the target class.
    `int` | `require` | In general, injectors are intended to "fail soft" in that a failure to locate the injection point in the target method is not considered an error condition.
    `Slice` | `slice` | A `Slice` annotation which describes the method bisection used in the `at()` query for this injector.
    `Desc[]` | `target` | Literal representation of one or more `@Desc` annotations which identify the target methods.

- - ### Element Detail

    - #### at

          At at

      An `At` annotation which describes the `InjectionPoint` in the target method. The specified `InjectionPoint` must only return `MethodInsnNode` and an exception will be thrown if this is not the case.
      Returns:
        `At` which identifies the target method invocation

  - - #### method

          java.lang.String[] method

      String representation of one or more `target selectors` which identify the target methods.
      Returns:
        target method(s) for this injector
      Default:
        {}

  - - #### target

          Desc[] target

      Literal representation of one or more `@Desc` annotations which identify the target methods.
      Returns:
        target method(s) for this injector as descriptors
      Default:
        {}

  - - #### slice

          Slice slice

      A `Slice` annotation which describes the method bisection used in the `at()` query for this injector.
      Returns:
        slice
      Default:
        @org.spongepowered.asm.mixin.injection.Slice

  - - #### remap

          boolean remap

      By default, the annotation processor will attempt to locate an obfuscation mapping for all `Redirect` methods since it is anticipated that in general the target of a `Redirect` annotation will be an obfuscated method in the target class. However since it is possible to also apply mixins to non-obfuscated targets (or non- obfuscated methods in obfuscated targets, such as methods added by Forge) it may be necessary to suppress the compiler error which would otherwise be generated. Setting this value to false will cause the annotation processor to skip this annotation when attempting to build the obfuscation table for the mixin.
      Returns:
        True to instruct the annotation processor to search for obfuscation mappings for this annotation
      Default:
        true

  - - #### require

          int require

      In general, injectors are intended to "fail soft" in that a failure to locate the injection point in the target method is not considered an error condition. Another transformer may have changed the method structure or any number of reasons may cause an injection to fail. This also makes it possible to define several injections to achieve the same task given expected mutation of the target class and the injectors which fail are simply ignored.

      However, this behaviour is not always desirable. For example, if your application depends on a particular injection succeeding you may wish to detect the injection failure as an error condition. This argument is thus provided to allow you to stipulate a minimum number of successful injections for this callback handler. If the number of injections specified is not achieved then an `InjectionError` is thrown at application time. Use this option with care.

      Returns:
        Minimum required number of injected callbacks, default specified by the containing config
      Default:
        -1

  - - #### expect

          int expect

      Like `require()` but only enabled if the `mixin.debug.countInjections` option is set to `true` and defaults to 1. Use this option during debugging to perform simple checking of your injectors. Causes the injector to throw a `InvalidInjectionException` if the expected number of injections is not realised.
      Returns:
        Minimum number of expected callbacks, default 1
      Default:
        1

  - - #### allow

          int allow

      Injection points are in general expected to match every candidate instruction in the target method or slice, except in cases where options such as `At.ordinal()` are specified which naturally limit the number of results.

      This option allows for sanity-checking to be performed on the results of an injection point by specifying a maximum allowed number of matches, similar to that afforded by `Group.max()`. For example if your injection is expected to match 4 invocations of a target method, but instead matches 5, this can become a detectable tamper condition by setting this value to `4`.

      Setting any value 1 or greater is allowed. Values less than 1 or less than `require()` are ignored. `require()` supercedes this argument such that if `allow` is less than `require` the value of `require` is always used.

      Note that this option is not a limit on the query behaviour of this injection point. It is only a sanity check used to ensure that the number of matches is not too high

      Returns:
        Maximum allowed number of injections for this
      Default:
        -1

  - - #### constraints

          java.lang.String constraints

      Returns constraints which must be validated for this injector to succeed. See `ConstraintParser.Constraint` for details of constraint formats.
      Returns:
        Constraints for this annotation
      Default:
        ""

  - - #### order

          int order

      By default almost all injectors for a target class apply their injections at the same time. In other words, if multiple mixins target the same class then injectors are applied in priority order (since the mixins themselves are merged in priority order, and injectors run in the order they were merged). Redirect injectors apply in a later pass.

      The default order for redirect injectors is `10000`, and all other injectors use `1000`.

      Specifying a value for `order` alters this default behaviour and causes the injector to inject either earlier or later than it normally would. For example specifying `9900` will cause the injector to apply before others, while `11000` will apply later. Injectors with the same `order` will still apply in order of their mixin's `priority`.

      Returns:
        the application order for this injector, uses default REDIRECT order (10000) if not specified
      Default:
        10000