From f93c7b9e169eedeaf6caaa860cbc45cd8f2ffb2a Mon Sep 17 00:00:00 2001 From: zaaarf Date: Sun, 2 Jun 2024 21:30:10 +0200 Subject: fix: map overridden methods using top-level's name --- .../lll/processor/containers/ClassContainer.java | 8 ++++---- .../lll/processor/containers/MethodContainer.java | 23 ++++++++++++++++++++-- .../java/ftbsc/lll/processor/utils/ASTUtils.java | 12 +++++------ 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/main/java/ftbsc/lll/processor/containers/ClassContainer.java b/src/main/java/ftbsc/lll/processor/containers/ClassContainer.java index f19c0c4..047bc47 100644 --- a/src/main/java/ftbsc/lll/processor/containers/ClassContainer.java +++ b/src/main/java/ftbsc/lll/processor/containers/ClassContainer.java @@ -6,7 +6,6 @@ import ftbsc.lll.processor.annotations.Find; import ftbsc.lll.processor.annotations.Patch; import ftbsc.lll.processor.ProcessorOptions; -import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import javax.tools.Diagnostic; import java.lang.annotation.Annotation; @@ -26,11 +25,11 @@ public class ClassContainer { public final ClassData data; /** - * The {@link Element} corresponding to the class. + * The {@link TypeElement} corresponding to the class. * May only be null intentionally i.e. when the associated element is * an anonymous class or a child of an anonymous class. */ - public final Element elem; + public final TypeElement elem; /** * Private constructor, called from {@link #from(Annotation, Function, String, ProcessorOptions)}. @@ -40,7 +39,7 @@ public class ClassContainer { */ private ClassContainer(String fqn, String[] innerNames, ProcessorOptions options) { //find and validate - Element elem = options.env.getElementUtils().getTypeElement(fqn); + TypeElement elem = options.env.getElementUtils().getTypeElement(fqn); if(elem == null) throw new TargetNotFoundException("class", fqn); @@ -71,6 +70,7 @@ public class ClassContainer { .getEnclosedElements() .stream() .filter(e -> e instanceof TypeElement) + .map(e -> (TypeElement) e) .filter(e -> e.getSimpleName().contentEquals(inner)) .findFirst() .orElse(null); diff --git a/src/main/java/ftbsc/lll/processor/containers/MethodContainer.java b/src/main/java/ftbsc/lll/processor/containers/MethodContainer.java index 78c5a5a..e8b0892 100644 --- a/src/main/java/ftbsc/lll/processor/containers/MethodContainer.java +++ b/src/main/java/ftbsc/lll/processor/containers/MethodContainer.java @@ -2,6 +2,7 @@ package ftbsc.lll.processor.containers; import ftbsc.lll.exceptions.AmbiguousDefinitionException; import ftbsc.lll.exceptions.TargetNotFoundException; +import ftbsc.lll.mapper.data.ClassData; import ftbsc.lll.mapper.utils.MappingUtils; import ftbsc.lll.mapper.data.MethodData; import ftbsc.lll.processor.annotations.Find; @@ -56,7 +57,7 @@ public class MethodContainer { */ private MethodContainer(ClassContainer parent, String name, String descriptor, boolean strict, boolean bridge, ProcessorOptions options) { this.parent = parent; - if(parent.elem == null) { //unverified + if(parent.elem == null) { // unverified if(descriptor == null) throw new AmbiguousDefinitionException("Cannot use name-based lookups for methods of unverifiable classes!"); this.elem = null; @@ -68,7 +69,25 @@ public class MethodContainer { name = this.elem.getSimpleName().toString(); descriptor = descriptorFromExecutableElement(this.elem, options.env); } - this.data = getMethodData(parent.data.name, name, descriptor, options.mapper); + + // some mapping formats omit methods if they are overriding a parent's method + // since there is no drawback but efficiency, let's use the top parent's name for that (when possible) + String mappedName = null; + if(this.parent.elem != null) { + ExecutableElement top = findOverloadedMethod(this.parent.elem, this.elem, options.env); + ClassData topParentData = getClassData( + internalNameFromType(top.getEnclosingElement().asType(), options.env), + options.mapper + ); + MethodData topData = getMethodData(topParentData.name, name, descriptor, options.mapper); + this.data = new MethodData( + parent.data, + topData.signature.name, + topData.signature.descriptor, + topData.nameMapped + ); + } else this.data = getMethodData(parent.data.name, name, descriptor, options.mapper); + this.descriptorObf = options.mapper == null ? this.data.signature.descriptor : MappingUtils.mapMethodDescriptor(this.data.signature.descriptor, options.mapper, false); } diff --git a/src/main/java/ftbsc/lll/processor/utils/ASTUtils.java b/src/main/java/ftbsc/lll/processor/utils/ASTUtils.java index e75d5e9..6989e5e 100644 --- a/src/main/java/ftbsc/lll/processor/utils/ASTUtils.java +++ b/src/main/java/ftbsc/lll/processor/utils/ASTUtils.java @@ -116,14 +116,14 @@ public class ASTUtils { } /** - * Gets the internal name from an {@link TypeMirror}. + * Gets the internal name from a {@link TypeMirror}. * @param type the {@link TypeMirror} in question * @param env the {@link ProcessingEnvironment} to perform the operation in * @return the internal name at compile time, or null if it wasn't a qualifiable * @since 0.5.1 */ public static String internalNameFromType(TypeMirror type, ProcessingEnvironment env) { - //needed to actually turn elem into a TypeVariable, find it ignoring generics + // needed to actually turn elem into a TypeVariable, find it ignoring generics Element elem = env.getTypeUtils().asElement(env.getTypeUtils().erasure(type)); StringBuilder fqnBuilder = new StringBuilder(); while(elem.getEnclosingElement() != null && elem.getEnclosingElement().getKind() != ElementKind.PACKAGE) { @@ -213,7 +213,7 @@ public class ASTUtils { } /** - * Gets the {@link ClassData} corresponding to the given fully-qualified name, + * Gets the {@link ClassData} corresponding to the given internal name, * or creates a false one with the same, non-obfuscated name twice. * @param name the internal name of the class to convert * @param mapper the {@link Mapper} to use, may be null @@ -222,7 +222,7 @@ public class ASTUtils { */ public static ClassData getClassData(String name, Mapper mapper) { try { - name = name.replace('.', '/'); //just in case + name = name.replace('.', '/'); // just in case if(mapper != null) return mapper.getClassData(name); } catch(MappingNotFoundException ignored) {} @@ -242,7 +242,7 @@ public class ASTUtils { */ public static MethodData getMethodData(String parent, String name, String descriptor, Mapper mapper) { try { - name = name.replace('.', '/'); //just in case + parent = parent.replace('.', '/'); // just in case if(mapper != null) return mapper.getMethodData(parent, name, descriptor); } catch(MappingNotFoundException ignored) {} @@ -360,7 +360,7 @@ public class ASTUtils { /** * Tries to find the "synthetic bridge" generated by the compiler for a certain overridden - * method. A "bridge" only exists in cases where type erasure is involved (i.e. when the + * methods. A "bridge" only exists in cases where type erasure is involved (i.e. when the * method being overridden uses a generic parameter that is not preserved in the overriding * method). * @param context the {@link TypeElement} representing the parent class -- cgit v1.2.3-56-ga3b1