Package org.spongepowered.asm.mixin.injection

## Annotation Type At

    @Documented
    @Retention(RUNTIME)
    public @interface At

The `At` annotation selects one or multiple instructions (depending on the circumstances no instructions can also be matched) based on the parameters it was given to. What the selected instruction mean depends on the context. For `Inject.at()` it is the instruction at which the injection should occur.

### Required Element Summary

Required Elements
`java.lang.String` `value` Defines the type of instructions that should be matched.

### Optional Element Summary

Optional Elements
`java.lang.String[]` `args` A list of arguments that can be consumed by the injection point provider.
`int` `by` Define by how many instructions the selection should be shifted by.
`Desc` `desc` The targeted signature.
`At.Shift` `shift` At times the injection point selector defined by `value()` points to an instruction adjacent to the instruction that should actually be targeted, yet in some circumstances it can be infeasible or even impossible to target the intended instruction directly.
`java.lang.String` `slice` The id of the `Slice` that should be passed to the injection point to narrow down the amount of resulting matched instructions.
`java.lang.String` `target` The target attribute is a discriminator with whom the chosen instructions can be constrained with more specific accuracy if the injection point isn't descriptive enough as-is.

### Element Detail

#### value

    java.lang.String value

Defines the type of instructions that should be matched. The following values are all valid types:

- `HEAD` - Before the first instruction
- `RETURN` - Before all RETURN (including ARETURN, DRETURN, etc.) instructions
- `TAIL` - Before the last RETURN (including ARETURN, DRETURN, etc.) instruction
- `INVOKE` - Before all matching INVOKESTATIC, INVOKEVIRTUAL or INVOKESPECIAL instructions
- `INVOKE_ASSIGN` - After all matching INVOKESTATIC, INVOKEVIRTUAL or INVOKESPECIAL instructions, where the return value is STORE'd immediately
- `FIELD` - Before all matching GETFIELD, PUTFIELD, GETSTATIC or PUTSTATIC instructions
- `NEW` - Before all matching NEW instructions
- `INVOKE_STRING` - Like INVOKE, but instruction must only take in a string and return void. Furthermore, the instruction must be preceded by an LDC which is checked for a match.
- `JUMP` - Before all matching jumping instructions (IFEQ, IFNE, IFLT, GOTO, JSR, etc. - if opcode is -1 it matches all)
- `CONSTANT` - Before all matching constant instructions (ICONST_0, BIPUSH, SIPUSH, LDC, etc.)

The spongeian implementation supports fully qualified names for custom injection points, however the micromixin implementation does not support such behaviour.

Most injection points require additional arguments in order to resolve to an instruction. These arguments are supplied alongside this argument and are to be specified in the `At` annotation.

Returns:
  The type of instructions to match

#### args

    java.lang.String[] args

A list of arguments that can be consumed by the injection point provider. These arguments are used if `target()` and `desc()` either do not apply or are not descriptive enough.

The probably most common use of this attribute is for use in the CONSTANT injection point. Examples of the syntax of this injection point are follows:

- `nullValue=true`
- `intValue=8`
- `stringValue=name`

Please be aware that the above examples may be a bit erroneous, but should still work for micromixin. However, it has not yet been investigated as to why that is the case. More specifically, micromixin-transformer supports the same keys as defined by the attributes of the `Constant` annotation.

The exact syntax of the arguments differ from injection point provider to injection point provider. The provider is defined via `value()`. Consult the manual of your injection point for further details.

Returns:
  The arguments to pass to the injection point provider for further discrimination.

Default:
  {}

#### by

    int by

Define by how many instructions the selection should be shifted by.

The exact effects are explained in `At.Shift.BY` but simplified, using `At.Shift.BY` for `shift()` results in arbitrary shifts by n instructions (for n > 0, the shift is forwards while for n < 0 the shift is backwards. For n = 0 no shift occurs). This n is defined using `by()` (default value for this property is 0).

Although permissible when using micromixin at this point in time, other mixin implementations (and potentially future iterations of micromixin) may produce warnings or application failures when using `At.Shift.BY` in combination with a `by()` that is a very large value. As a rule of thumb, an `by()` smaller than -3 or larger than 3 are to be avoided. Reason for this is that `by()` is rather blind, enabling the possibility of writing injection points that are more unstable than they actually need to be.

This annotation element has no effect if `shift()` is not set to `At.Shift.BY`. It is undefined whether it is an error to define an `by()` when `shift()` is not `At.Shift.BY`.

Returns:
  The amounts of instructions to shift the selection by.
See Also:
  `At.Shift.BY`

Default:
  0

#### desc

    Desc desc

The targeted signature. Usage of `Desc` may result in better compile-time error and sanity checking, however depending on your tooling the difference between `desc()` and `target()` may be indistinguishable in this regard.

Warning: Fabric's tiny-remapper does not support remapping this annotation. Proceed with caution. For more information, see the PR that introduced Desc remapping in tiny-remapper.

Returns:
  The constraint to use as a `Desc` annotation.
See Also:
  `Inject.target()`, `target()`

Default:
  @org.spongepowered.asm.mixin.injection.Desc("")

#### shift

    At.Shift shift

At times the injection point selector defined by `value()` points to an instruction adjacent to the instruction that should actually be targeted, yet in some circumstances it can be infeasible or even impossible to target the intended instruction directly. In this case, the instruction targeted by the injection point selector defined by `value()` can be "shifted" by a limited amount.

This annotation element only modifies the selection of this `At`, but will not mutate the originally selected instruction, nor will it modify or move any other instruction. This annotation element is primarily used to inject code after an injection point selector, e.g. after an `INVOKEVIRTUAL` instruction matched by `INVOKE`.

By default, the instruction is not shifted. This corresponds to the behaviour of `At.Shift.NONE`.

It is not defined whether "virtual" instructions (for example LineInsnNodes, FrameInsnNodes and LabelNodes) are counted towards the shift or whether they are ignored. This behaviour may be subject to change depending on the behaviour of other mixin implementations as well as the (un-)intuitive semantics of such counting. The spongeian mixin documentation implicitly leaves this as an implementation detail.

Returns:
  The type of shift to perform.

Default:
  org.spongepowered.asm.mixin.injection.At.Shift.NONE

#### slice

    java.lang.String slice

The id of the `Slice` that should be passed to the injection point to narrow down the amount of resulting matched instructions. This should be the preferred way of selecting one specific instruction from a pool of otherwise similar instructions as this would be the least brittle option - provided the slices are not used carelessly.

Note that micromixin-transformer as well as the accompanying documentation only partly implements `Slice.id()` as well as `slice()`; significant derivations are to be expected between micromixin-transformer's behaviour (as well as the documented behaviour) and the spongeian transformer behaviour (as well as it's documentation). As such, usage of these attributes ought to be avoided in environments where usage of micromixin-transformer is expected and the spongeian documentation should be consulted before making use of this attribute.

Returns:
  The id of the `Slice` to use, as per `Slice.id()`.

Default:
  ""

#### target

    java.lang.String target

The target attribute is a discriminator with whom the chosen instructions can be constrained with more specific accuracy if the injection point isn't descriptive enough as-is.

This attribute should match to a method for `INVOKE`, `INVOKE_ASSIGN` and `INVOKE_STRING`. It should match to a field for `FIELD` and match to a class/descriptor (can be an array) for `NEW`.

The following are all valid formats of explicit target selectors:

- `targetMethod`
- `targetMethod(Lcom/example/Argument;)V`
- `(Lcom/example/Argument;)V`
- `targetMethod(I)Lcom/example/ReturnValue;`
- `targetMethod()Z`
- `Lcom/example/Target;targetMethod(Lcom/example/Argument;)V`
- `Lcom/example/Target;(Lcom/example/Argument;)V`
- `Lcom/example/Target;targetMethod(Lcom/example/Argument;) V`
- `Lcom/example/Target;target Method(Lcom/example/Argument;)V`
- `Lcom/example/Target;targetMethod(Lcom/exam ple/Argument;)V`

The parts of the explicit target selector (owner, name, descriptor) must always have the same order, but the individual parts must not necessarily be present.

While permissible, it is strongly discouraged to make use of whitespace in explicit target selectors. When they are used, the spongeian mixin implementation (and also micromixin) will discard all whitespace characters (tabs included). This is documented behaviour (in both micromixin and sponge's mixin) and is unlikely to change in the future. This discouragement exists as this feature may cause target selectors to be illegible.

Warning: Depending on your platform and tooling, not specifying a fully qualified reference may cause errors. On SLL there will be no issues at runtime (with either micromixin or the spongeian mixin implementation), however other platforms and tooling may not be so considerate. Especially remappers (which are recommended if not necessary in obfuscated environments) may struggle with incompletely qualified targets.

Hint: Usage of `desc()` should be preferred over `target()` if possible. However, beware that doing so may not be viable depending on your platform. Please heed the advice provided in the documentation of `desc()` and the documentation of your platform and other tooling.

Returns:
  A target selector to use as a constraint.
See Also:
  `Inject.method()`

Default:
  ""