Package org.spongepowered.asm.mixin.injection

## Annotation Type Slice

-     @Target({})
      @Retention(RUNTIME)
      public @interface Slice

  A `Slice` identifies a section of a method to search for injection points.

  Using slices provides for a much more expressive way of identifying target injection points in a method, which has two advantages:

  1. Encoding assumptions about the structure of a method makes it easier to detect (and fail-fast) when a method has changed in an unexpected way.
  2. Injection points using slices are less brittle than points specified with large ordinals because they allow injection points to be specified with reference to characteristics of the method rather than arbitrary ordinal values.

  Consider the following example:

  >      private void foo(Bar bar) {
  >          bar.update();
  >          List<Thing> list = bar.getThings();
  >          for (Thing thing : list) {
  >              thing.processStuff();
  >          }

  >          Thing specialThing = bar.getSpecialThing();
  >          if (specialThing.isReady()) {
  >              specialThing.processStuff();
  >              bar.update();
  >          }

  >          bar.notifyFoo();
  >      }

  Let's assume we are interested in applying a `Redirect` to the `processStuff()` method call within the `if` block. Using `ordinal` we can achieve this as follows:

  >      @At(value = "INVOKE", target = "processStuff", ordinal = 1)

  This will work fine initially. However consider the case that in a future version of the target library the method is altered and an additional call to `processStuff()` is added:

  >      private void foo(Bar bar) {
  >          bar.update();
  >          List<Thing> list = bar.getThings();
  >          for (Thing thing : list) {
  >              thing.processStuff();
  >          }

  >          // A new call to processStuff, which now has the ordinal 1
  >          bar.getActiveThing().processStuff();

  >          Thing specialThing = bar.getSpecialThing();
  >          if (specialThing.isReady()) {
  >              specialThing.processStuff();
  >              bar.update();
  >          }

  >          bar.notifyFoo();
  >      }

  It's still pretty easy for a human to identify the correct point since the original `if` hasn't changed. However the use of ordinals means that the injection is now wrong and must be fixed by hand.

  We can make the injection point more expressive and reliable by using a `Slice`. We know in this example that the call to `processStuff()` we want is the one immediately after a call to `isReady()`. We can slice the method at the call to `isReady()` and modify the injector accordingly:

  >      @Inject(
  >          slice = @Slice(
  >              from = @At(value = "INVOKE", target = "isReady")
  >          )
  >          at = @At(value = "INVOKE", target = "processStuff", ordinal = 0)
  >      )

  The `ordinal` is specified as `0` because the scope of the injection point is now the region of the method defined by the slice .

  Slices can be specified using a `from()` point, a `to()` point, or both. `Callback Injectors` using multiple injection points can distinguish different slices using `id()` and then specify the slice to use in the `At.slice()` argument.

- - ### Optional Element Summary

    Optional Elements
    Modifier and Type | Optional Element | Description
    --- | --- | ---
    `At` | `from` | Injection point which specifies the start of the slice region.
    `java.lang.String` | `id` | The identifier for this slice, specified using the `At.slice()` value (if omitted, this slice becomes the default slice and applies to all undecorated `At` queries).
    `At` | `to` | Injection point which specifies the end of the slice region.

- - ### Element Detail

    - #### id

          java.lang.String id

      The identifier for this slice, specified using the `At.slice()` value (if omitted, this slice becomes the default slice and applies to all undecorated `At` queries).

      This value can be safely ignored for injector types which only accept a single query (eg. `Redirect` and others). However since `Inject` injectors can have multiple `At` queries, it may be desirable to have multiple slices as well. When specifying multiple slices, each should be designed a unique `id` which can then be referenced in the corresponding `At`.

      There are no specifications or restrictions for valid `id`s, however it is recommended that the `id` in some way describe the slice, thus allowing the `At` query to be read without necessarily reading the slice itself. For example, if the slice is selecting all instructions before the first call to some method `init`, then using an id `"beforeInit` makes sense. Using before, after and between prefixes as a loose standard is considered good practice.

      This value defaults to an empty string, the empty string is used as a default identifier throughout the injection subsystem, and any `At` which doesn't specify a slice explicitly will use this identifer. Specifying `id` or `slice` for injectors which only support a single slice is ignored internally, so you may use this field to give a descriptive name to the slice if you wish.

      Returns:
        The identifier for this slice
      Default:
        ""

  - - #### from

          At from

      Injection point which specifies the start of the slice region. `At`s supplied here should generally use a `InjectionPoint.Specifier` in order to identify which instruction should be used for queries which return multiple results. The specifier is supplied by appending the specifier type to the injection point type as follows:

      >     @At(value = "INVOKE:LAST", ... )

      If `from` is not supplied then `to()` must be supplied. It is allowed to specify both `from` and `to` as long as the points select a region with positive size (eg the insn returned by `to` must appear after that selected by `from` in the method body).

      Returns:
        the start point of the slice
      Default:
        @org.spongepowered.asm.mixin.injection.At("HEAD")

  - - #### to

          At to

      Injection point which specifies the end of the slice region. Like `from()`, `At`s supplied here should generally specify a `InjectionPoint.Specifier` in order to identify which instruction should be used for queries which return multiple results. The specifier is supplied by appending the specifier type to the injection point type as follows:

      >     @At(value = "INVOKE:LAST", ... )

      If `to` is not supplied then `from()` must be supplied. It is allowed to specify both `from` and `to` as long as the points select a region with positive size (eg the insn returned by `to` must appear after that selected by `from` in the method body).

      Returns:
        the start point of the slice
      Default:
        @org.spongepowered.asm.mixin.injection.At("TAIL")