Annotation Type CanonicalOverwrite
-
@Documented @Retention(RUNTIME) @Target(METHOD) public @interface CanonicalOverwriteAbstract
TheCanonicalOverwriteis a micromixin-specific derivation of the traditionalOverwriteannotation. This annotation has the same behavioural semantics asOverwritein the absence of a remapper or refmaps. However, when a remapper is used, the handler method keeps its "canonical" name, and a new helper method is spawned to keep the semantics ofOverwrite. Hence, this method is in a sense of hybrid ofUnique(which makes a method keep it's name for public methods), andOverwrite.It may not be applied on non-public or static methods, see the illegal usecases for further details.
Semantic approximation
The semantic approximation is an approximation of how the behaviour of this annotation can be replicated using other annotations, but may not mirror the inner workings of the annotation behind the scenes.In it's purest form, the behaviour of this annotation can be replicated using a default/implicit overwrite + explicit
Overwritepair. Henceforth you get the following two methods:// Note: No annotation here! public void methodName() { // Method logic goes here. // This is the "canonical" part of the handler. } @Overwrite public void methodName() { ((MyInterface) this).methodName(); }The keen might realize that while this cannot be emulated with a single mixin class, this behaviour can be achieved using two or more mixin classes. This effect might make this annotation redundant, and it may be the only way to replicate the behaviour of
CanonicalOverwriteif the annotation is not guaranteed to be supported under a given environment (please check out the documentation of your environment and dependencies you rely on for hints about this support). That being said, this requires theOverwriteto be applied before the implicit overwrite. However, as the implicit overwrite does not have strongly defined behaviour, it is possible for this emulation to not work under certain environments. Further, the chance of mistakes is high and the intended behaviour might be obfuscated by the boilerplate, ultimately making maintenance more costly. Henceforth,CanonicalOverwriteshould be used for this exact usecase.Technical details
This paragraph is mostly specific to the implementation within micromixin-transformer, other implementations may derive slightly from the implementation details. However, the behaviour must be kept the same. This is especially crucial to overrides in conjunction with subclassing.Within the remapper process, the handler method may not be renamed. Instead, only
method()andtarget()are renamed. If neithermethod()nortarget()are defined, thentarget()will be set to correspond to the method's current name and descriptor, and the newtarget()value will be remapped from then on. The handler method's name stays constant as established earlier.Important limitations & words of warning
Usages of this annotation that are either discouraged or environments in which this annotation might show unintended behaviour (though this behaviour not being intended per-se but rather being a byproduct of other constraints).This annotation is unlikely to behave as intended outside of the stianloader toolchain. Especially, the remapping semantics described by this annotation are unlikely to be supported by tiny-remapper (although tiny-remapper could easily be extended to support this annotation) and are completely ignored when making use of the annotation processor and/or refmaps. In general, only micromixin-remapper can be reliably expected to process this annotation.
This annotation has the potential of polluting the target class if it is used too frequently for little reason. Use
Overwriteinstead whenever applicable. Do note that likeOverwrite,CanonicalOverwritecompletely overwrites the target method. Thus it should not be used when anOverwriteis inappropriate, that is,CanonicalOverwriteought not replace one or moreInject,ModifyArg, or similar. Further this annotation should not be used as an alternative toUnique.Illegal usecases
Usages of this annotation that are invalid and thus will raise either a remap-time failure or a runtime failure. Implementors are encouraged to check against these uses.Methods annotated with
CanonicalOverwriteMUST bepublic. All other visibility modifiers (such as protected, package-private or private) are considered illegal within the scope of this constraint. This constraint is at its core arbitrary, but is necessary to reduce the possibility of misuse of this annotation, as the ABI (application binary interface) guarantees provided are only relevant when this constraint is applied.A method annotated with
CanonicalOverwriteMUST implement a definition defined by at least one interface implemented in the target class. As a logical consequence, it is invalid to apply this annotation on astaticmethod. This constraint is at its core arbitrary, but is necessary to reduce the possibility of misuse of this annotation, as the ABI (application binary interface) guarantees provided are only relevant when this constraint is applied.The handler method (that is the method annotated with
CanonicalOverwrite) and the target method (that is the method that should be overwritten) must have the same descriptor. It is not valid for them to differ in the descriptor, which means that the return value and the argument types must match. However, the generic signatures may differ due to generic erasure (but do note that mismatches may be dangerous nonetheless).
-
-
Element Detail
-
method
java.lang.String method
The target selector string defining the method that should be overwritten. That is, the selected method will delegate all it's calls to the handler method.This parameter is mutually exclusive with
target(). Only one of the two may be defined. However, it is also valid for none of the elements to be set, in which case the overwritten method is assumed to have the same descriptor and name as the annotated handler method.Note: Like many other mixin annotations, the transformer can differ between explicitly setting the value to
""and not setting the value at all. This is because javac omits undefined element values and ignores the default value. The default value advertised here is only required due to how optional elements need to be defined in java source code but truth be told there is no such default value in practice.- Returns:
- The target selector string defining the method to overwrite.
- Default:
- ""
-
-
-
target
Desc target
The@Descdefinition referring to the method that should be overwritten. That is, the selected method will delegate all it's calls to the handler method.This parameter is mutually exclusive with
method(). Only one of the two may be defined. However, it is also valid for none of the elements to be set, in which case the overwritten method is assumed to have the same descriptor and name as the annotated handler method.Like in all other annotations, the default descriptor of the
Descis implicitly set tovoid.class. If a non-void method is overwritten, the descriptor must be explicitly set as a logical consequence of this constant (i.e. blind) default. The descriptor of the overwritten method and the descriptor of the target method must be the same, as defined by the illegal usecases ofCanonicalOverwrite.Note: Like many other mixin annotations, the transformer can differ between explicitly setting the value to
@Desc("")and not setting the value at all. This is because javac omits undefined element values and ignores the default value. The default value advertised here is only required due to how optional elements need to be defined in java source code but truth be told there is no such default value in practice.- Returns:
- The method to overwrite.
- Default:
- @org.spongepowered.asm.mixin.injection.Desc("")
-
-