diff --git a/src/main/java/net/minecraftforge/fart/internal/EnhancedRemapper.java b/src/main/java/net/minecraftforge/fart/internal/EnhancedRemapper.java index a4eef31..47aa0ac 100644 --- a/src/main/java/net/minecraftforge/fart/internal/EnhancedRemapper.java +++ b/src/main/java/net/minecraftforge/fart/internal/EnhancedRemapper.java @@ -14,8 +14,6 @@ import java.util.function.Consumer; import org.jetbrains.annotations.Nullable; -import org.objectweb.asm.Handle; -import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import org.objectweb.asm.commons.Remapper; @@ -40,7 +38,32 @@ public EnhancedRemapper(ClassProvider classProvider, IMappingFile map, Consumer< } @Override public String mapModuleName(final String name) { return name; } // TODO? None of the mapping formats support this. - @Override public String mapAnnotationAttributeName(final String descriptor, final String name) { return name; } // TODO: Is this just methods? + @Override + public String mapAnnotationAttributeName(final String descriptor, final String name) { + Type type = Type.getType(descriptor); + if (type.getSort() != Type.OBJECT) + return name; + + MClass cls = getClass(type.getInternalName()).orElse(null); + if (cls == null) + return name; + + List lst = cls.getMethods(name).orElse(null); + if (lst == null) + return name; + + // You should not be able to specify conflicting annotation value names + // As annotation attributes can't have parameters, and the bytecode doesn't store the descriptor + // But renamers can be weird so log instead of doing weird things. + if (lst.size() != 1) { + for (MClass.MMethod mtd : lst) + log.accept("Duplicate Annotation name: " + cls.getName() + " " + mtd.getName() + mtd.getDescriptor() + " -> " + cls.getMapped() + " " + mtd.getName()); + return name; + } + + return lst.get(0).getMapped(); + } + @Override public String mapInvokeDynamicMethodName(final String name, final String descriptor) { return name; } // TODO: Lookup how the JVM resolves this and attempt to resolve it to get the owner? @Override @@ -81,26 +104,6 @@ public String mapParameterName(final String owner, final String methodName, fina .orElse(paramName); } - @Override - public Object mapValue(final Object value) { - if (value instanceof Handle) { - // Backport of ASM!327 https://gitlab.ow2.org/asm/asm/-/merge_requests/327 - final Handle handle = (Handle) value; - final boolean isFieldHandle = handle.getTag() <= Opcodes.H_PUTSTATIC; - - return new Handle( - handle.getTag(), - this.mapType(handle.getOwner()), - isFieldHandle - ? this.mapFieldName(handle.getOwner(), handle.getName(), handle.getDesc()) - : this.mapMethodName(handle.getOwner(), handle.getName(), handle.getDesc()), - isFieldHandle ? this.mapDesc(handle.getDesc()) : this.mapMethodDesc(handle.getDesc()), - handle.isInterface()); - } else { - return super.mapValue(value); - } - } - private Optional getClass(String cls) { if (cls == null || cls.charAt(0) == '[') // Enums values() function invokes 'clone' on the array type. return Optional.empty(); // I'm pretty sure that i'd require stupid hacky JVM to allow native array methods to be remapped. @@ -142,6 +145,7 @@ private class MClass { private final Collection> fieldsView = Collections.unmodifiableCollection(fields.values()); private final Map> methods = new ConcurrentHashMap<>(); private final Collection> methodsView = Collections.unmodifiableCollection(methods.values()); + private final Map>> methodsByName = new ConcurrentHashMap<>(); MClass(IClassInfo icls, IMappingFile.IClass mcls) { if (icls == null && mcls == null) @@ -329,6 +333,19 @@ public Optional getMethod(String name, String desc) { return this.methods.computeIfAbsent(name + desc, k -> Optional.empty()); } + Optional> getMethods(String name) { + return this.methodsByName.computeIfAbsent(name, k -> { + List mtds = new ArrayList<>(); + for (Optional opt : this.getMethods()) { + MMethod mtd = opt.orElse(null); + if (mtd == null || !k.equals(mtd.getName())) + continue; + mtds.add(mtd); + } + return mtds.isEmpty() ? Optional.>empty() : Optional.of(mtds); + }); + } + @Override public String toString() { return getName();