diff options
author | zaaarf <me@zaaarf.foo> | 2024-01-24 17:21:42 +0100 |
---|---|---|
committer | zaaarf <me@zaaarf.foo> | 2024-01-24 17:21:42 +0100 |
commit | bf32e56a863e83b82efe9732c585979afb0e62c3 (patch) | |
tree | 19ffb009b3159665b6f457f5df34855a96101153 /src/main/java/ftbsc/lll/processor/containers/MethodContainer.java | |
parent | 3dd86a41872585b7cbba4f6b4e1407316bf889c3 (diff) |
chore: internal reorganisation
Diffstat (limited to 'src/main/java/ftbsc/lll/processor/containers/MethodContainer.java')
-rw-r--r-- | src/main/java/ftbsc/lll/processor/containers/MethodContainer.java | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/src/main/java/ftbsc/lll/processor/containers/MethodContainer.java b/src/main/java/ftbsc/lll/processor/containers/MethodContainer.java new file mode 100644 index 0000000..7d15599 --- /dev/null +++ b/src/main/java/ftbsc/lll/processor/containers/MethodContainer.java @@ -0,0 +1,102 @@ +package ftbsc.lll.processor.containers; + +import ftbsc.lll.exceptions.AmbiguousDefinitionException; +import ftbsc.lll.exceptions.TargetNotFoundException; +import ftbsc.lll.mapper.tools.MappingUtils; +import ftbsc.lll.mapper.tools.data.MethodData; +import ftbsc.lll.processor.annotations.Find; +import ftbsc.lll.processor.annotations.Patch; +import ftbsc.lll.processor.annotations.Target; +import ftbsc.lll.processor.ProcessorOptions; + +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; + +import static ftbsc.lll.processor.utils.ASTUtils.*; + +/** + * Container for information about a method. + * Used internally for efficiency reasons. + * @since 0.5.0 + */ +public class MethodContainer { + /** + * The {@link MethodData} for the method represented by this container. + */ + public final MethodData data; + + /** + * The obfuscated descriptor of the field. + * If the mapper passed is null, this will be identical to the one inside + * {@link #data}. + */ + public final String descriptorObf; + + /** + * The {@link ClassContainer} representing the parent of this method. + */ + public final ClassContainer parent; + + /** + * The {@link ExecutableElement} corresponding to the method. + * May only be null intentionally i.e. when the method is + * a child of an anonymous class. + */ + public final ExecutableElement elem; + + /** + * Private constructor, called from + * {@link #from(ExecutableElement, Target, Find, ProcessorOptions)}. + * @param parent the {@link ClassContainer} representing the parent + * @param name the fully-qualified name of the target method + * @param descriptor the descriptor of the target method + * @param strict whether the matching should be strict (see {@link Target#strict()} for more info) + * @param bridge whether the "bridge" should be matched instead (see {@link Target#bridge()} for more info) + * @param options the {@link ProcessorOptions} to be used + */ + private MethodContainer(ClassContainer parent, String name, String descriptor, boolean strict, boolean bridge, ProcessorOptions options) { + this.parent = parent; + if(parent.elem == null) { //unverified + if(descriptor == null) + throw new AmbiguousDefinitionException("Cannot use name-based lookups for methods of unverifiable classes!"); + this.elem = null; + } else { + ExecutableElement tmp = (ExecutableElement) findMember( + parent, name, descriptor, descriptor != null && strict,false, options.env + ); + this.elem = bridge ? findSyntheticBridge((TypeElement) this.parent.elem, tmp, options.env) : tmp; + name = this.elem.getSimpleName().toString(); + descriptor = descriptorFromExecutableElement(this.elem, options.env); + } + 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); + } + + /** + * Builds the {@link MethodContainer} corresponding to a stub annotated with {@link Target}. + * @param stub the {@link ExecutableElement} for the stub + * @param t the {@link Target} annotation relevant to this case + * @param f the {@link Find} annotation containing fallback data, may be null + * @param options the {@link ProcessorOptions} to be used + * @return the {@link MethodContainer} corresponding to the method + * @throws AmbiguousDefinitionException if it finds more than one candidate + * @throws TargetNotFoundException if it finds no valid candidate + * @since 0.3.0 + */ + public static MethodContainer from(ExecutableElement stub, Target t, Find f, ProcessorOptions options) { + //the parent always has a @Patch annotation + Patch patchAnn = stub.getEnclosingElement().getAnnotation(Patch.class); + ClassContainer parent = ClassContainer.findOrFallback( + ClassContainer.from((TypeElement) stub.getEnclosingElement(), options), patchAnn, f, options + ); + String name = !t.methodName().isEmpty() + ? t.methodName() //name was specified in target + : stub.getSimpleName().toString(); + String descriptor = t.strict() + ? descriptorFromExecutableElement(stub, options.env) + : null; + + return new MethodContainer(parent, name, descriptor, t.strict(), t.bridge(), options); + } +} |