Package org.spongepowered.asm.mixin.injection

## Annotation Type ModifyArg

    @Documented
    @Retention(RUNTIME)
    @Target(METHOD)
    public @interface ModifyArg

The `ModifyArg` annotation allows to apply a function on a single argument used to call a method. More specifically, the mixin implementation will call the argument modifier handler with the original argument value. The handler will then return the modified value with whom the targeted method is called with.

A single `ModifyArg` handler can only modify a single argument. If multiple arguments are to be modified, multiple handlers are required. Alternatively, different (as of yet unimplemented) annotations can be used, for example ModifyArgs.

### Local variable use

The micromxin-transformer implementation tries to avoid usage of local variables when using ModifyArg. However this is not always possible. For the target descriptor (ICDLjava/lang/Object;I)V and an index of 2 the transformer will produce following bytecode:

> `ISTORE index0
> ASTORE index1
> DUP2_X2
> POP2
> ALOAD 0
> SWAP
> invokevirtual Clazz.handler(C)C
> DUP2_X2
> POP2
> ALOAD index1
> ILOAD index0
> invokeX Clazz.original(ICDLjava/lang/Object;I)V
> `

While micromixin-transformer uses opcodes such as DUP or POP aggressively, the spongeian implementation will use xSTORE/xLOAD everywhere.

### Signature and visibility modifiers

The `ModifyArg` handler (also known as the "argument modifier") MUST declare the same return type (subtypes are not supported) as its argument type (supertypes are not supported). If the targeted method is `static`, the handler MUST be `static` and `private`. For non-`static` targets the access modifiers are not of relevance, except for constructors where the handler must be `static` when not injecting immediately before the final return via `TAIL`.

Locals and argument capture is not supported when using `ModifyArg`.

### Required Element Summary

Required Elements
`At` `at` The injection point where the injection should occur.

### Optional Element Summary

Optional Elements
`int` `allow` The maximum amount of injection points that should be allowed.
`int` `expect` The expected amount of injection points.
`int` `index` The ordinal of the argument to capture for the argument modifier handler.
`java.lang.String[]` `method` The targeted method selectors.
`int` `require` The minimum amount of injection points.
`Slice` `slice` The slice to make use for the injection points defined by `at()`.
`Desc[]` `target` The targeted methods.

### Element Detail

#### at

    At at

The injection point where the injection should occur. If none of the injection points apply no exception is thrown by default (this default can be changed through `require()`), however transformation does not occur (Micromixin still copies the handler into the target class anyways though).

Note that contrary to other annotations provided by Mixins or MixinExtra, `ModifyArg` can only target a single `At`, however the spongeian mixin implementation as well as micromixin-transformer allows this single `At` to match multiple instructions (as would be the case when using RETURN).

The injection points of the `ModifyArg` MUST point to MethodInsnNodes. The current micromixin-transformer implementation as such forbids to target INVOKEDYNAMIC instructions with this annotation. Otherwise INVOKEVIRTUAL, INVOKESPECIAL, INVOKEINTERFACE and INVOKESTATIC are all valid targets.

Returns:
  The injection point.

#### allow

    int allow

The maximum amount of injection points that should be allowed. If the value of this element is below 1 or if the value is below the `minimum amount` of allowable injection points then the limit is not being enforced. However, `expect()` has no influence on `allow()`.

Furthermore this limit is only valid per target class. That is, if multiple target classes are defined as per `Mixin.value()` or `Mixin.targets()` then this limit is only applicable for all the injection points in the targeted class. This limitation is caused due to the fact that the targeted classes are not known until they are loaded in by the classloader, at which point all the injection logic occurs.

This limit is shared across all methods (as defined by `method()` or `target()`) targeted by the handler within a class.

Returns:
  The maximum amount targeted of injection points within the target class.

Default:
  -1

#### expect

    int expect

The expected amount of injection points. This behaves similar to `require()`, however while `require()` will cause a class file transformation failure, `expect()` is a weaker form of it. Under the spongeian implementation, this attribute behaves like `require()` if and only if the appropriate debug flags are activated. The micromixin transformer will meanwhile "just" unconditionally write a warning to the logger.

This attribute should be used to identify potentially outdated injectors.

Returns:
  The expected amount of injection points

Default:
  -1

#### index

    int index

The ordinal of the argument to capture for the argument modifier handler.

The index does not care about the computational type category of the arguments. That is both doubles and ints are both treated as having the size of 1.

A value of -1 means that the ordinal is automatically evaluated based on the argument type. Should multiple arguments match, an error is thrown.

Returns:
  The ordinal of the argument to capture, or -1 to automatically choose the ordinal

Default:
  -1

#### method

    java.lang.String[] method

The targeted method selectors. The amounts of methods that may match and are selected is not bound to any hard value and as such it should be limited by setting attributes such as `require()` or `expect()` as otherwise the injector might accidentally not match anything with no way of knowing what exactly went wrong.

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.

It is generally recommended to not be lazy when it comes to explicit selectors, the more information is provided the better. Information that is not supplied is comparable to a wildcard - the first matching method will be targeted, even if nonsense. It is especially not recommended to discard the method name, even if that is theoretically valid.

The spongeian implementation also supports schemes other than the explicit selectors. However the Micromixin implementation only supports explicit selectors as documented above. Where as the spongeian implementation supports quantifiers in explicit selectors, Micromixin does not support them (yet). As such, quantifiers are not included in the documentation.

It is rather advisable to use `target()` over `method()`, especially for beginners, since latter provides behaviour that can more easily be anticipated.

Returns:
  The target selectors that define the target method of the handler.

Default:
  {}

#### require

    int require

The minimum amount of injection points. If less injection points are found (as per `at()`). an exception is thrown during transformation. The default amount of required injection points can be set by mixin configuration file, but by default that is no minimum amount of required injection points.

Returns:
  The minimum amount of injection points

Default:
  -1

#### slice

    Slice slice

The slice to make use for the injection points defined by `at()`.

The id of the slice is ignored as per the spongeian documentation, but this behaviour may not be reflected by micromixin-transformer. It is as such not recommended to depend on this behaviour. See `At.slice()` and `Slice.id()` for further information.

Returns:
  The slice used to filter the possible instructions matched by injection points.

Default:
  @org.spongepowered.asm.mixin.injection.Slice

#### target

    Desc[] target

The targeted methods. Only one method is picked from the list of provided methods. As such the list should generally only be used to mark method aliases among others.

Returns:
  The target selectors that define the target method of the handler.

Default:
  {}