@Target(value={METHOD,FIELD})
@Retention(value=RUNTIME)
public @interface Shadow
| Modifier and Type | Optional Element and Description |
|---|---|
java.lang.String[] |
aliases
Supplies possible aliases for this shadow member.
|
java.lang.String |
prefix
In general, shadow methods can be declared using their name in the
target class as you would expect, however we run into a problem when we
want to mix in a method with the same name and arguments, but a different
return type to the shadow method.
|
boolean |
remap
|
public abstract java.lang.String prefix
In general, shadow methods can be declared using their name in the target class as you would expect, however we run into a problem when we want to mix in a method with the same name and arguments, but a different return type to the shadow method. While the JVM itself will happily support methods with signatures that differ only on return type, the compiler itself does not. This poses a problem, since we have no way to leverage this behaviour since our mixin class will not compile.
To circumvent this compiler limitation, the prefix option can be used. By specifying a prefix for the shadow method, it is subsequently possible to compile the mixin class, the specified prefix will then be stripped from the method name prior to applying the mixin, and everything will work as expected. You may either use the default prefix: "shadow$", or you may specify your own. It is good practice to specify the prefix if you are using it, regardless of whether you use the default or not. For example consider the intrinsic readability of the following snippets
:
@Shadow abstract void someMethod(int arg1, int arg2);
@Shadow abstract void shadow$someMethod(int arg1, int arg2);
@Shadow(prefix = "shadow$") abstract void shadow$someMethod(int arg1, int arg2);
@Shadow(prefix = "foo$") abstract void foo$someMethod(int arg1, int arg2);
All of these declarations are semantically equivalent, however the third and fourth are the most expressive in terms of making their intentions clear, and thus specifying prefix is recommended, since it aids readability and maintainability.
Note that specifying a prefix does not enforce use of
the prefix, the behaviour of prefix is such that the prefix will
be stripped from the start of the method name as long as the method
name actually starts with the prefix! This has important
repercussions since if the annotation value does not match the method
prefix then no renaming will take place likey resulting in a
failure state indicated by an InvalidMixinException at run
time.
Prefixes on shadow fields are considered an error condition and don't have any purpose either way, since the scenario described above cannot actually occur with fields.
public abstract boolean remap
Shadow methods since it is
anticipated that in general the target of a Shadow annotation
will be an obfuscated field or 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 desirable to suppress the compiler warning 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.public abstract java.lang.String[] aliases
Only private members may be given aliases. This is because aliases can only be calculated when the mixin is applied and thus would otherwise invalidate the calculated class metadata if another mixin had already been applied in the hierarchy.