diff --git a/src/main/java/org/spongepowered/asm/mixin/Overwrite.java b/src/main/java/org/spongepowered/asm/mixin/Overwrite.java index 70bff267..d5f1e715 100644 --- a/src/main/java/org/spongepowered/asm/mixin/Overwrite.java +++ b/src/main/java/org/spongepowered/asm/mixin/Overwrite.java @@ -53,5 +53,21 @@ import java.lang.annotation.Target; @Target({ ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) public @interface Overwrite { + + /** + * Supplies possible aliases for this method. This should only + * be used in the following scenarios: + * + * + * + * @return Aliases for this member + */ + public String[] aliases() default { }; } diff --git a/src/main/java/org/spongepowered/asm/mixin/transformer/MixinPreProcessor.java b/src/main/java/org/spongepowered/asm/mixin/transformer/MixinPreProcessor.java index cdf6cc05..ff16854f 100644 --- a/src/main/java/org/spongepowered/asm/mixin/transformer/MixinPreProcessor.java +++ b/src/main/java/org/spongepowered/asm/mixin/transformer/MixinPreProcessor.java @@ -24,6 +24,7 @@ */ package org.spongepowered.asm.mixin.transformer; +import java.lang.annotation.Annotation; import java.util.Deque; import java.util.Iterator; import java.util.LinkedList; @@ -37,6 +38,7 @@ import org.objectweb.asm.tree.FieldInsnNode; import org.objectweb.asm.tree.FieldNode; import org.objectweb.asm.tree.MethodInsnNode; import org.objectweb.asm.tree.MethodNode; +import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.transformer.ClassInfo.Field; import org.spongepowered.asm.mixin.transformer.ClassInfo.Method; @@ -154,33 +156,53 @@ class MixinPreProcessor { private void attachMethods(MixinTargetContext context) { for (MethodNode mixinMethod : this.classNode.methods) { - AnnotationNode shadowAnnotation = ASMHelper.getVisibleAnnotation(mixinMethod, Shadow.class); - if (shadowAnnotation == null) { + if (this.processMethod(context, mixinMethod, Shadow.class, true, true)) { continue; } - - Method method = this.mixin.getClassInfo().findMethod(mixinMethod, true); - MethodNode target = MixinPreProcessor.findMethod(context.getTargetClass(), mixinMethod, shadowAnnotation); - - if (target == null) { - throw new InvalidMixinException(this.mixin, "Shadow method " + mixinMethod.name + " was not located in the target class"); - } - - if (Constants.INIT.equals(target.name)) { - throw new InvalidMixinException(this.mixin, "Nice try! Cannot alias a constructor!"); - } - - if (!target.name.equals(mixinMethod.name)) { - if ((target.access & Opcodes.ACC_PRIVATE) == 0) { - throw new InvalidMixinException(this.mixin, "Non-private method cannot be aliased. Found " + target.name); - } - - mixinMethod.name = target.name; - method.renameTo(target.name); - } + + this.processMethod(context, mixinMethod, Overwrite.class, false, false); } } + private boolean processMethod(MixinTargetContext context, MethodNode mixinMethod, Class annotationType, + boolean mustExist, boolean mustBePrivate) { + AnnotationNode annotation = ASMHelper.getVisibleAnnotation(mixinMethod, annotationType); + if (annotation == null) { + return false; + } + + Method method = this.mixin.getClassInfo().findMethod(mixinMethod, true); + MethodNode target = MixinPreProcessor.findMethod(context.getTargetClass(), mixinMethod, annotation); + + if (target == null) { + if (!mustExist) { + return false; + } + + throw new InvalidMixinException(this.mixin, annotationType.getSimpleName() + " method " + mixinMethod.name + + " was not located in the target class"); + } + + if (Constants.INIT.equals(target.name)) { + throw new InvalidMixinException(this.mixin, "Nice try! Cannot alias a constructor!"); + } + + if (!target.name.equals(mixinMethod.name)) { + if (mustBePrivate && (target.access & Opcodes.ACC_PRIVATE) == 0) { + throw new InvalidMixinException(this.mixin, "Non-private method cannot be aliased. Found " + target.name); + } + + System.err.printf("=================================================================================\n"); + System.err.printf("Renaming %s -> %s\n", mixinMethod.name, target.name); + System.err.printf("=================================================================================\n"); + + mixinMethod.name = target.name; + method.renameTo(target.name); + } + + return true; + } + private void attachFields(MixinTargetContext context) { for (Iterator iter = this.classNode.fields.iterator(); iter.hasNext();) { FieldNode mixinField = iter.next(); @@ -273,11 +295,11 @@ class MixinPreProcessor { } } - private static MethodNode findMethod(ClassNode classNode, MethodNode method, AnnotationNode shadow) { + private static MethodNode findMethod(ClassNode classNode, MethodNode method, AnnotationNode annotation) { Deque aliases = new LinkedList(); aliases.add(method.name); - if (shadow != null) { - List aka = ASMHelper.>getAnnotationValue(shadow, "aliases"); + if (annotation != null) { + List aka = ASMHelper.>getAnnotationValue(annotation, "aliases"); if (aka != null) { aliases.addAll(aka); }