Skip to content

Commit

Permalink
Support mapping annotation values
Browse files Browse the repository at this point in the history
  • Loading branch information
LexManos committed Dec 2, 2024
1 parent f298a56 commit dfe56fd
Showing 1 changed file with 40 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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<MClass.MMethod> 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
Expand Down Expand Up @@ -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<MClass> 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.
Expand Down Expand Up @@ -142,6 +145,7 @@ private class MClass {
private final Collection<Optional<MField>> fieldsView = Collections.unmodifiableCollection(fields.values());
private final Map<String, Optional<MMethod>> methods = new ConcurrentHashMap<>();
private final Collection<Optional<MMethod>> methodsView = Collections.unmodifiableCollection(methods.values());
private final Map<String, Optional<List<MMethod>>> methodsByName = new ConcurrentHashMap<>();

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

Optional<List<MMethod>> getMethods(String name) {
return this.methodsByName.computeIfAbsent(name, k -> {
List<MMethod> mtds = new ArrayList<>();
for (Optional<MMethod> opt : this.getMethods()) {
MMethod mtd = opt.orElse(null);
if (mtd == null || !k.equals(mtd.getName()))
continue;
mtds.add(mtd);
}
return mtds.isEmpty() ? Optional.<List<MMethod>>empty() : Optional.of(mtds);
});
}

@Override
public String toString() {
return getName();
Expand Down

0 comments on commit dfe56fd

Please sign in to comment.