Annotation Type Shadow


  • @Target({METHOD,FIELD})
    @Retention(RUNTIME)
    public @interface Shadow
    Used to indicate a Mixin class member which is acting as a placeholder for a method or field in the target class
    • Optional Element Summary

      Optional Elements 
      Modifier and Type Optional Element 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
      By default, the annotation processor will attempt to locate an obfuscation mapping for all 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.
    • Element Detail

      • prefix

        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.

        Returns:
        the shadow prefix
        Default:
        "shadow$"
      • remap

        boolean remap
        By default, the annotation processor will attempt to locate an obfuscation mapping for all 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.
        Returns:
        True to instruct the annotation processor to search for obfuscation mappings for this annotation
        Default:
        true
      • aliases

        java.lang.String[] aliases
        Supplies possible aliases for this shadow member. This should only be used in the following scenarios:
        • When shadowing a sythetic field or method which can have different names at development time because it is regenerated by the compiler.
        • When another mod or transformer is known to change the name of a field

        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.

        Returns:
        Aliases for this member
        Default:
        {}