diff --git a/src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/HardTargetMixinMethodVisitor.java b/src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/HardTargetMixinMethodVisitor.java index f7937d01..c4ba2894 100644 --- a/src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/HardTargetMixinMethodVisitor.java +++ b/src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/HardTargetMixinMethodVisitor.java @@ -30,8 +30,6 @@ import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; import net.fabricmc.tinyremapper.extension.mixin.common.data.Constant; import net.fabricmc.tinyremapper.extension.mixin.common.data.MxMember; -import net.fabricmc.tinyremapper.extension.mixin.hard.annotation.AccessorAnnotationVisitor; -import net.fabricmc.tinyremapper.extension.mixin.hard.annotation.InvokerAnnotationVisitor; import net.fabricmc.tinyremapper.extension.mixin.hard.annotation.OverwriteAnnotationVisitor; import net.fabricmc.tinyremapper.extension.mixin.hard.annotation.ShadowAnnotationVisitor; @@ -57,10 +55,6 @@ public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { av = new ShadowAnnotationVisitor(data, av, method, targets); } else if (Annotation.OVERWRITE.equals(descriptor)) { av = new OverwriteAnnotationVisitor(data, av, method, targets); - } else if (Annotation.ACCESSOR.equals(descriptor)) { - av = new AccessorAnnotationVisitor(data, av, method, targets); - } else if (Annotation.INVOKER.equals(descriptor)) { - av = new InvokerAnnotationVisitor(data, av, method, targets); } return av; diff --git a/src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/annotation/AccessorAnnotationVisitor.java b/src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/annotation/AccessorAnnotationVisitor.java deleted file mode 100644 index 49fb5a49..00000000 --- a/src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/annotation/AccessorAnnotationVisitor.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2016, 2018, Player, asie - * Copyright (c) 2021, 2023, FabricMC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -package net.fabricmc.tinyremapper.extension.mixin.hard.annotation; - -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.function.Consumer; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.objectweb.asm.AnnotationVisitor; - -import net.fabricmc.tinyremapper.extension.mixin.common.data.AnnotationElement; -import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; -import net.fabricmc.tinyremapper.extension.mixin.common.data.Constant; -import net.fabricmc.tinyremapper.extension.mixin.common.data.MxMember; -import net.fabricmc.tinyremapper.extension.mixin.hard.util.CamelPrefixString; -import net.fabricmc.tinyremapper.extension.mixin.hard.util.ConvertibleMappable; -import net.fabricmc.tinyremapper.extension.mixin.hard.util.IConvertibleString; - -/** - * In case of multi-target, if a remap conflict is detected, - * an error message will show up and the behaviour is undefined. - * If after strip the prefix, all characters are UPPER_CASE, then - * do not lower the first character of the remaining part. - */ -public class AccessorAnnotationVisitor extends AnnotationVisitor { - private final Collection> tasks; - private final MxMember method; - private final List targets; - - private boolean isSoftTarget; - - public AccessorAnnotationVisitor(Collection> tasks, AnnotationVisitor delegate, MxMember method, List targets) { - super(Constant.ASM_VERSION, delegate); - - this.tasks = Objects.requireNonNull(tasks); - this.method = Objects.requireNonNull(method); - this.targets = Objects.requireNonNull(targets); - - this.isSoftTarget = false; - } - - @Override - public void visit(String name, Object value) { - if (name.equals(AnnotationElement.VALUE)) { - isSoftTarget = true; - } - - super.visit(name, value); - } - - @Override - public void visitEnd() { - if (!isSoftTarget) { - tasks.add(data -> new AccessorMappable(data, method, targets).result()); - } - - super.visitEnd(); - } - - private static class AccessorMappable extends ConvertibleMappable { - private final String prefix; - private final String fieldDesc; - - private static final Pattern GETTER_PATTERN = Pattern.compile("(?<=\\(\\)).*"); - private static final Pattern SETTER_PATTERN = Pattern.compile("(?<=\\().*(?=\\)V)"); - - AccessorMappable(CommonData data, MxMember self, Collection targets) { - super(data, self, targets); - - if (self.getName().startsWith("get")) { - this.prefix = "get"; - } else if (self.getName().startsWith("set")) { - this.prefix = "set"; - } else if (self.getName().startsWith("is")) { - this.prefix = "is"; - } else { - throw new RuntimeException(String.format("%s does not start with get, set or is.", self.getName())); - } - - Matcher getterMatcher = GETTER_PATTERN.matcher(self.getDesc()); - Matcher setterMatcher = SETTER_PATTERN.matcher(self.getDesc()); - - if (getterMatcher.find()) { - this.fieldDesc = getterMatcher.group(); - } else if (setterMatcher.find()) { - this.fieldDesc = setterMatcher.group(); - } else { - throw new RuntimeException(String.format("%s is not getter or setter descriptor", self.getDesc())); - } - } - - @Override - protected IConvertibleString getName() { - return new CamelPrefixString(prefix, self.getName()); - } - - @Override - protected String getDesc() { - return fieldDesc; - } - } -} diff --git a/src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/annotation/InvokerAnnotationVisitor.java b/src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/annotation/InvokerAnnotationVisitor.java deleted file mode 100644 index c3e835ea..00000000 --- a/src/main/java/net/fabricmc/tinyremapper/extension/mixin/hard/annotation/InvokerAnnotationVisitor.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2016, 2018, Player, asie - * Copyright (c) 2021, 2023, FabricMC - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -package net.fabricmc.tinyremapper.extension.mixin.hard.annotation; - -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.function.Consumer; - -import org.objectweb.asm.AnnotationVisitor; - -import net.fabricmc.tinyremapper.extension.mixin.common.data.AnnotationElement; -import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; -import net.fabricmc.tinyremapper.extension.mixin.common.data.Constant; -import net.fabricmc.tinyremapper.extension.mixin.common.data.MxMember; -import net.fabricmc.tinyremapper.extension.mixin.hard.util.CamelPrefixString; -import net.fabricmc.tinyremapper.extension.mixin.hard.util.ConvertibleMappable; -import net.fabricmc.tinyremapper.extension.mixin.hard.util.IConvertibleString; - -/** - * In case of multi-target, if a remap conflict is detected, - * an error message will show up and the behaviour is undefined. - * If after strip the prefix, all characters are UPPER_CASE, then - * do not lower the first character of the remaining part. - */ -public class InvokerAnnotationVisitor extends AnnotationVisitor { - private final Collection> tasks; - private final MxMember method; - private final List targets; - - private boolean isSoftTarget; - - public InvokerAnnotationVisitor(Collection> tasks, AnnotationVisitor delegate, MxMember method, List targets) { - super(Constant.ASM_VERSION, delegate); - - this.tasks = Objects.requireNonNull(tasks); - this.method = Objects.requireNonNull(method); - this.targets = Objects.requireNonNull(targets); - - this.isSoftTarget = false; - } - - @Override - public void visit(String name, Object value) { - if (name.equals(AnnotationElement.VALUE)) { - isSoftTarget = true; - } - - super.visit(name, value); - } - - @Override - public void visitEnd() { - if (!isSoftTarget) { - tasks.add(data -> new InvokerMappable(data, method, targets).result()); - } - - super.visitEnd(); - } - - private static class InvokerMappable extends ConvertibleMappable { - private final String prefix; - - InvokerMappable(CommonData data, MxMember self, Collection targets) { - super(data, self, targets); - - if (self.getName().startsWith("call")) { - this.prefix = "call"; - } else if (self.getName().startsWith("invoke")) { - this.prefix = "invoke"; - } else if (self.getName().startsWith("new")) { - this.prefix = "new"; - } else if (self.getName().startsWith("create")) { - this.prefix = "create"; - } else { - throw new RuntimeException(String.format("%s does not start with call or invoke.", self.getName())); - } - } - - @Override - protected IConvertibleString getName() { - return new CamelPrefixString(prefix, self.getName()); - } - - @Override - protected String getDesc() { - return self.getDesc(); - } - } -} diff --git a/src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/AccessorAnnotationVisitor.java b/src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/AccessorAnnotationVisitor.java index 52ed794b..fe31893e 100644 --- a/src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/AccessorAnnotationVisitor.java +++ b/src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/AccessorAnnotationVisitor.java @@ -25,6 +25,7 @@ import org.objectweb.asm.AnnotationVisitor; +import net.fabricmc.tinyremapper.extension.mixin.common.StringUtility; import net.fabricmc.tinyremapper.extension.mixin.common.data.AnnotationElement; import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; import net.fabricmc.tinyremapper.extension.mixin.common.data.Constant; @@ -38,9 +39,12 @@ public class AccessorAnnotationVisitor extends AnnotationVisitor { private final CommonData data; + private final MxMember method; private final List targets; private final String fieldDesc; + private boolean isSoftTarget; + private static final Pattern GETTER_PATTERN = Pattern.compile("(?<=\\(\\)).*"); private static final Pattern SETTER_PATTERN = Pattern.compile("(?<=\\().*(?=\\)V)"); @@ -50,6 +54,7 @@ public AccessorAnnotationVisitor(CommonData data, AnnotationVisitor delegate, Mx this.data = Objects.requireNonNull(data); Objects.requireNonNull(method); + this.method = method; this.targets = Objects.requireNonNull(targets); Matcher getterMatcher = GETTER_PATTERN.matcher(method.getDesc()); @@ -67,11 +72,41 @@ public AccessorAnnotationVisitor(CommonData data, AnnotationVisitor delegate, Mx @Override public void visit(String name, Object value) { if (name.equals(AnnotationElement.VALUE)) { + isSoftTarget = true; String fieldName = Objects.requireNonNull((String) value); - - value = new NamedMappable(data, fieldName, fieldDesc, targets).result(); + setAnnotationValue(fieldName); + return; } super.visit(name, value); } + + @Override + public void visitEnd() { + if (!isSoftTarget) { + setAnnotationValue(inferFieldName()); + } + + super.visitEnd(); + } + + private void setAnnotationValue(String fieldName) { + super.visit(AnnotationElement.VALUE, new NamedMappable(data, fieldName, fieldDesc, targets).result()); + } + + private String inferFieldName() { + String prefix; + + if (method.getName().startsWith("get")) { + prefix = "get"; + } else if (method.getName().startsWith("set")) { + prefix = "set"; + } else if (method.getName().startsWith("is")) { + prefix = "is"; + } else { + throw new RuntimeException(String.format("%s does not start with get, set or is.", method.getName())); + } + + return StringUtility.removeCamelPrefix(prefix, method.getName()); + } } diff --git a/src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/InvokerAnnotationVisitor.java b/src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/InvokerAnnotationVisitor.java index ead0c50b..d415a6df 100644 --- a/src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/InvokerAnnotationVisitor.java +++ b/src/main/java/net/fabricmc/tinyremapper/extension/mixin/soft/annotation/InvokerAnnotationVisitor.java @@ -23,6 +23,7 @@ import org.objectweb.asm.AnnotationVisitor; +import net.fabricmc.tinyremapper.extension.mixin.common.StringUtility; import net.fabricmc.tinyremapper.extension.mixin.common.data.AnnotationElement; import net.fabricmc.tinyremapper.extension.mixin.common.data.CommonData; import net.fabricmc.tinyremapper.extension.mixin.common.data.Constant; @@ -39,6 +40,8 @@ public class InvokerAnnotationVisitor extends AnnotationVisitor { private final List targets; + private boolean isSoftTarget; + public InvokerAnnotationVisitor(CommonData data, AnnotationVisitor delegate, MxMember method, List targets) { super(Constant.ASM_VERSION, Objects.requireNonNull(delegate)); @@ -51,12 +54,49 @@ public InvokerAnnotationVisitor(CommonData data, AnnotationVisitor delegate, MxM @Override public void visit(String name, Object value) { if (name.equals(AnnotationElement.VALUE)) { + isSoftTarget = true; String methodName = Objects.requireNonNull((String) value); - String methodDesc = method.getDesc(); - value = new NamedMappable(data, methodName, methodDesc, targets).result(); + setAnnotationValue(methodName); + return; } super.visit(name, value); } + + @Override + public void visitEnd() { + if (!isSoftTarget) { + String inferredName = inferMethodName(); + + if (inferredName != null) { + setAnnotationValue(inferredName); + } + } + + super.visitEnd(); + } + + private void setAnnotationValue(String methodName) { + super.visit(AnnotationElement.VALUE, new NamedMappable(data, methodName, method.getDesc(), targets).result()); + } + + private String inferMethodName() { + if (method.getName().startsWith("new") || method.getName().startsWith("create")) { + // The rest of the name isn't important, leave it as-is + return null; + } + + String prefix; + + if (method.getName().startsWith("call")) { + prefix = "call"; + } else if (method.getName().startsWith("invoke")) { + prefix = "invoke"; + } else { + throw new RuntimeException(String.format("%s does not start with call or invoke.", method.getName())); + } + + return StringUtility.removeCamelPrefix(prefix, method.getName()); + } }