recipe-nope/src/main/java/dev/pfaff/recipe_nope/injector/UnconstrainedRedirect.java

144 lines
5.9 KiB
Java

package dev.pfaff.recipe_nope.injector;
import org.spongepowered.asm.mixin.MixinEnvironment;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Desc;
import org.spongepowered.asm.mixin.injection.Group;
import org.spongepowered.asm.mixin.injection.InjectionPoint;
import org.spongepowered.asm.mixin.injection.Slice;
import org.spongepowered.asm.mixin.injection.selectors.ITargetSelector;
import org.spongepowered.asm.mixin.injection.throwables.InjectionError;
import org.spongepowered.asm.mixin.injection.throwables.InvalidInjectionException;
import org.spongepowered.asm.util.ConstraintParser;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@SuppressWarnings("AnnotationOutsideOfMixin")
@Target({ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface UnconstrainedRedirect {
/**
* String representation of one or more
* {@link ITargetSelector target selectors} which identify the target
* methods.
*
* @return target method(s) for this injector
*/
String[] method() default {};
/**
* Literal representation of one or more {@link Desc @Desc} annotations
* which identify the target methods.
*
* @return target method(s) for this injector as descriptors
*/
Desc[] target() default {};
/**
* A {@link Slice} annotation which describes the method bisection used in
* the {@link #at} query for this injector.
*
* @return slice
*/
Slice slice() default @Slice;
/**
* An {@link At} annotation which describes the {@link InjectionPoint} in
* the target method. The specified {@link InjectionPoint} <i>must only</i>
* return {@link org.objectweb.asm.tree.MethodInsnNode} and an
* exception will be thrown if this is not the case.
*
* @return {@link At} which identifies the target method invocation
*/
At at();
/**
* By default, the annotation processor will attempt to locate an
* obfuscation mapping for all {@link org.spongepowered.asm.mixin.injection.Redirect} methods since it is
* anticipated that in general the target of a {@link org.spongepowered.asm.mixin.injection.Redirect} annotation
* will be an obfuscated 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 necessary to suppress the compiler error which would otherwise
* be generated. Setting this value to <em>false</em> will cause the
* annotation processor to skip this annotation when attempting to build the
* obfuscation table for the mixin.
*
* @return True to instruct the annotation processor to search for
* obfuscation mappings for this annotation
*/
boolean remap() default true;
/**
* In general, injectors are intended to "fail soft" in that a failure to
* locate the injection point in the target method is not considered an
* error condition. Another transformer may have changed the method
* structure or any number of reasons may cause an injection to fail. This
* also makes it possible to define several injections to achieve the same
* task given <em>expected</em> mutation of the target class and the
* injectors which fail are simply ignored.
*
* <p>However, this behaviour is not always desirable. For example, if your
* application depends on a particular injection succeeding you may wish to
* detect the injection failure as an error condition. This argument is thus
* provided to allow you to stipulate a <b>minimum</b> number of successful
* injections for this callback handler. If the number of injections
* specified is not achieved then an {@link InjectionError} is thrown at
* application time. Use this option with care.</p>
*
* @return Minimum required number of injected callbacks, default specified
* by the containing config
*/
int require() default -1;
/**
* Like {@link #require()} but only enabled if the
* {@link MixinEnvironment.Option#DEBUG_INJECTORS mixin.debug.countInjections} option is set
* to {@code true} and defaults to 1. Use this option during debugging to
* perform simple checking of your injectors. Causes the injector to throw
* a {@link InvalidInjectionException} if the expected number of injections
* is not realised.
*
* @return Minimum number of <em>expected</em> callbacks, default 1
*/
int expect() default 1;
/**
* Injection points are in general expected to match every candidate
* instruction in the target method or slice, except in cases where options
* such as {@link At#ordinal} are specified which naturally limit the number
* of results.
*
* <p>This option allows for sanity-checking to be performed on the results
* of an injection point by specifying a maximum allowed number of matches,
* similar to that afforded by {@link Group#max}. For example if your
* injection is expected to match 4 invocations of a target method, but
* instead matches 5, this can become a detectable tamper condition by
* setting this value to {@code 4}.
*
* <p>Setting any value 1 or greater is allowed. Values less than 1 or less
* than {@link #require} are ignored. {@link #require} supercedes this
* argument such that if {@code allow} is less than {@code require} the
* value of {@code require} is always used.</p>
*
* <p>Note that this option is not a <i>limit</i> on the query behaviour of
* this injection point. It is only a sanity check used to ensure that the
* number of matches is not too high
*
* @return Maximum allowed number of injections for this
*/
int allow() default -1;
/**
* Returns constraints which must be validated for this injector to
* succeed. See {@link ConstraintParser.Constraint} for details of constraint formats.
*
* @return Constraints for this annotation
*/
String constraints() default "";
}