Skip to content

Commit dfe56fd

Browse files
committed
Support mapping annotation values
1 parent f298a56 commit dfe56fd

File tree

1 file changed

+40
-23
lines changed

1 file changed

+40
-23
lines changed

src/main/java/net/minecraftforge/fart/internal/EnhancedRemapper.java

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414
import java.util.function.Consumer;
1515

1616
import org.jetbrains.annotations.Nullable;
17-
import org.objectweb.asm.Handle;
18-
import org.objectweb.asm.Opcodes;
1917
import org.objectweb.asm.Type;
2018
import org.objectweb.asm.commons.Remapper;
2119

@@ -40,7 +38,32 @@ public EnhancedRemapper(ClassProvider classProvider, IMappingFile map, Consumer<
4038
}
4139

4240
@Override public String mapModuleName(final String name) { return name; } // TODO? None of the mapping formats support this.
43-
@Override public String mapAnnotationAttributeName(final String descriptor, final String name) { return name; } // TODO: Is this just methods?
41+
@Override
42+
public String mapAnnotationAttributeName(final String descriptor, final String name) {
43+
Type type = Type.getType(descriptor);
44+
if (type.getSort() != Type.OBJECT)
45+
return name;
46+
47+
MClass cls = getClass(type.getInternalName()).orElse(null);
48+
if (cls == null)
49+
return name;
50+
51+
List<MClass.MMethod> lst = cls.getMethods(name).orElse(null);
52+
if (lst == null)
53+
return name;
54+
55+
// You should not be able to specify conflicting annotation value names
56+
// As annotation attributes can't have parameters, and the bytecode doesn't store the descriptor
57+
// But renamers can be weird so log instead of doing weird things.
58+
if (lst.size() != 1) {
59+
for (MClass.MMethod mtd : lst)
60+
log.accept("Duplicate Annotation name: " + cls.getName() + " " + mtd.getName() + mtd.getDescriptor() + " -> " + cls.getMapped() + " " + mtd.getName());
61+
return name;
62+
}
63+
64+
return lst.get(0).getMapped();
65+
}
66+
4467
@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?
4568

4669
@Override
@@ -81,26 +104,6 @@ public String mapParameterName(final String owner, final String methodName, fina
81104
.orElse(paramName);
82105
}
83106

84-
@Override
85-
public Object mapValue(final Object value) {
86-
if (value instanceof Handle) {
87-
// Backport of ASM!327 https://gitlab.ow2.org/asm/asm/-/merge_requests/327
88-
final Handle handle = (Handle) value;
89-
final boolean isFieldHandle = handle.getTag() <= Opcodes.H_PUTSTATIC;
90-
91-
return new Handle(
92-
handle.getTag(),
93-
this.mapType(handle.getOwner()),
94-
isFieldHandle
95-
? this.mapFieldName(handle.getOwner(), handle.getName(), handle.getDesc())
96-
: this.mapMethodName(handle.getOwner(), handle.getName(), handle.getDesc()),
97-
isFieldHandle ? this.mapDesc(handle.getDesc()) : this.mapMethodDesc(handle.getDesc()),
98-
handle.isInterface());
99-
} else {
100-
return super.mapValue(value);
101-
}
102-
}
103-
104107
private Optional<MClass> getClass(String cls) {
105108
if (cls == null || cls.charAt(0) == '[') // Enums values() function invokes 'clone' on the array type.
106109
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 {
142145
private final Collection<Optional<MField>> fieldsView = Collections.unmodifiableCollection(fields.values());
143146
private final Map<String, Optional<MMethod>> methods = new ConcurrentHashMap<>();
144147
private final Collection<Optional<MMethod>> methodsView = Collections.unmodifiableCollection(methods.values());
148+
private final Map<String, Optional<List<MMethod>>> methodsByName = new ConcurrentHashMap<>();
145149

146150
MClass(IClassInfo icls, IMappingFile.IClass mcls) {
147151
if (icls == null && mcls == null)
@@ -329,6 +333,19 @@ public Optional<MMethod> getMethod(String name, String desc) {
329333
return this.methods.computeIfAbsent(name + desc, k -> Optional.empty());
330334
}
331335

336+
Optional<List<MMethod>> getMethods(String name) {
337+
return this.methodsByName.computeIfAbsent(name, k -> {
338+
List<MMethod> mtds = new ArrayList<>();
339+
for (Optional<MMethod> opt : this.getMethods()) {
340+
MMethod mtd = opt.orElse(null);
341+
if (mtd == null || !k.equals(mtd.getName()))
342+
continue;
343+
mtds.add(mtd);
344+
}
345+
return mtds.isEmpty() ? Optional.<List<MMethod>>empty() : Optional.of(mtds);
346+
});
347+
}
348+
332349
@Override
333350
public String toString() {
334351
return getName();

0 commit comments

Comments
 (0)