diff options
7 files changed, 101 insertions, 92 deletions
diff --git a/build.gradle b/build.gradle index 74794ea..2f83ee6 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ dependencies { implementation 'com.squareup:javapoet:1.13.0' implementation 'org.ow2.asm:asm-commons:9.5' implementation 'ftbsc:lll:0.4.2' - implementation 'ftbsc.lll:mapper:0.1.0' + implementation 'ftbsc.lll:mapper:0.2.0' } jar { diff --git a/src/main/java/ftbsc/lll/processor/LilleroProcessor.java b/src/main/java/ftbsc/lll/processor/LilleroProcessor.java index 0e170ee..55eb81f 100644 --- a/src/main/java/ftbsc/lll/processor/LilleroProcessor.java +++ b/src/main/java/ftbsc/lll/processor/LilleroProcessor.java @@ -166,7 +166,7 @@ public class LilleroProcessor extends AbstractProcessor { //take care of TypeProxies and FieldProxies first for(VariableElement proxyVar : finders) { ProxyType type = getProxyType(proxyVar); - if(type == ProxyType.METHOD && proxyVar.getAnnotation(Find.class).name().equals("")) { + if(type == ProxyType.METHOD && proxyVar.getAnnotation(Find.class).name().isEmpty()) { //methods without a specified name will be handled later methodFinders.add(proxyVar); continue; @@ -185,7 +185,7 @@ public class LilleroProcessor extends AbstractProcessor { "super.$L = $T.from($S, 0, $L)", proxyVar.getSimpleName().toString(), TypeProxy.class, - clazz.fqnObf, //use obf name, at runtime it will be obfuscated + clazz.data.nameMapped.replace('/', '.'), //use obf name, at runtime it will be obfuscated clazz.elem == null ? 0 : mapModifiers(clazz.elem.getModifiers()) ); } else if(type == ProxyType.FIELD) @@ -225,11 +225,11 @@ public class LilleroProcessor extends AbstractProcessor { .collect(Collectors.toList()); //throw exception if user is a moron and defined a finder and an injector with the same name - if(finderCandidates.size() != 0 && injectorCandidates.size() != 0) + if(!finderCandidates.isEmpty() && !injectorCandidates.isEmpty()) throw new AmbiguousDefinitionException( String.format("Target specified user %s, but name was used by both a finder and injector.", targetAnn.of()) ); - else if(finderCandidates.size() == 0 && injectorCandidates.size() == 0) + else if(finderCandidates.isEmpty() && injectorCandidates.isEmpty()) processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, String.format( "Found orphan @Target annotation on method %s.%s pointing at method %s, it will be ignored!", @@ -238,11 +238,11 @@ public class LilleroProcessor extends AbstractProcessor { targetAnn.of() ) ); - else if(finderCandidates.size() == 0 && injectorCandidates.size() != 1) + else if(finderCandidates.isEmpty() && injectorCandidates.size() != 1) throw new AmbiguousDefinitionException( String.format("Found multiple candidate injectors for target %s::%s!", cl.getSimpleName(), tg.getSimpleName()) ); - else if(injectorCandidates.size() == 0 && finderCandidates.size() != 1) + else if(injectorCandidates.isEmpty() && finderCandidates.size() != 1) throw new AmbiguousDefinitionException( String.format("Found multiple candidate finders for target %s::%s!", cl.getSimpleName(), tg.getSimpleName()) ); @@ -290,9 +290,13 @@ public class LilleroProcessor extends AbstractProcessor { .addMethod(constructorBuilder.build()) .addMethod(buildStringReturnMethod("name", injName)) .addMethod(buildStringReturnMethod("reason", toGenerate.get(injName).reason)) - .addMethod(buildStringReturnMethod("targetClass", this.getProcessorOptions().obfuscateInjectorMetadata ? targetClass.fqnObf : targetClass.fqn)) - .addMethod(buildStringReturnMethod("methodName", this.getProcessorOptions().obfuscateInjectorMetadata ? target.nameObf : target.name)) - .addMethod(buildStringReturnMethod("methodDesc", this.getProcessorOptions().obfuscateInjectorMetadata ? target.descriptorObf : target.descriptor)) + .addMethod(buildStringReturnMethod("targetClass", this.getProcessorOptions().obfuscateInjectorMetadata + ? targetClass.data.nameMapped.replace('/', '.') + : targetClass.data.name.replace('/', '.'))) + .addMethod(buildStringReturnMethod("methodName", this.getProcessorOptions().obfuscateInjectorMetadata + ? target.data.nameMapped : target.data.signature.name)) + .addMethod(buildStringReturnMethod("methodDesc", this.getProcessorOptions().obfuscateInjectorMetadata + ? target.descriptorObf : target.data.signature.name)) .addMethods(generateDummies(cl)) .addMethod(generateInjector(toGenerate.get(injName), this.processingEnv)) .build(); diff --git a/src/main/java/ftbsc/lll/processor/tools/ASTUtils.java b/src/main/java/ftbsc/lll/processor/tools/ASTUtils.java index b33a906..952abd1 100644 --- a/src/main/java/ftbsc/lll/processor/tools/ASTUtils.java +++ b/src/main/java/ftbsc/lll/processor/tools/ASTUtils.java @@ -4,6 +4,9 @@ import ftbsc.lll.exceptions.AmbiguousDefinitionException; import ftbsc.lll.exceptions.MappingNotFoundException; import ftbsc.lll.exceptions.NotAProxyException; import ftbsc.lll.exceptions.TargetNotFoundException; +import ftbsc.lll.mapper.tools.data.ClassData; +import ftbsc.lll.mapper.tools.data.FieldData; +import ftbsc.lll.mapper.tools.data.MethodData; import ftbsc.lll.processor.annotations.Target; import ftbsc.lll.processor.tools.containers.ClassContainer; import ftbsc.lll.mapper.IMapper; @@ -210,35 +213,59 @@ public class ASTUtils { } /** - * Finds the class name and maps it to the correct format. - * @param name the fully qualified name of the class to convert - * @param options the {@link ProcessorOptions} to be used + * Gets the {@link ClassData} corresponding to the given fully-qualified 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 IMapper} to use, may be null * @return the fully qualified class name - * @since 0.3.0 + * @since 0.6.1 */ - public static String findClassName(String name, ProcessorOptions options) { + public static ClassData getClassData(String name, IMapper mapper) { try { - return options.mapper == null ? name : options.mapper.obfuscateClass(name).replace('/', '.'); - } catch(MappingNotFoundException e) { - return name; - } + name = name.replace('.', '/'); //just in case + if(mapper != null) + return mapper.getClassData(name); + } catch(MappingNotFoundException ignored) {} + return new ClassData(name, name); } /** - * Finds the member name and maps it to the correct format. - * @param parentFQN the unobfuscated FQN of the parent class - * @param memberName the name of the member - * @param methodDescriptor the descriptor of the method, may be null + * Gets the {@link MethodData} corresponding to the method matching the given + * name, parent and descriptor, or creates a dummy one with fake data if no + * valid mapping is found. + * @param parent the internal name of the parent class + * @param name the name of the member + * @param descriptor the descriptor of the method * @param mapper the {@link IMapper} to use, may be null - * @return the internal class name - * @since 0.3.0 + * @return the fully qualified class name + * @since 0.6.1 */ - public static String findMemberName(String parentFQN, String memberName, String methodDescriptor, IMapper mapper) { + public static MethodData getMethodData(String parent, String name, String descriptor, IMapper mapper) { try { - return mapper == null ? memberName : mapper.obfuscateMember(parentFQN, memberName, methodDescriptor); - } catch(MappingNotFoundException e) { - return memberName; - } + name = name.replace('.', '/'); //just in case + if(mapper != null) + return mapper.getMethodData(parent, name, descriptor); + } catch(MappingNotFoundException ignored) {} + return new MethodData(getClassData(name, mapper), name, name, descriptor); + } + + /** + * Gets the {@link FieldData} corresponding to the field matching the given + * name and parent, or creates a dummy one with fake data if no valid + * mapping is found. + * @param parent the internal name of the parent class + * @param name the name of the member + * @param mapper the {@link IMapper} to use, may be null + * @return the fully qualified class name + * @since 0.6.1 + */ + public static FieldData getFieldData(String parent, String name, IMapper mapper) { + try { + name = name.replace('.', '/'); //just in case + if(mapper != null) + return mapper.getFieldData(parent, name); + } catch(MappingNotFoundException ignored) {} + return new FieldData(getClassData(name, mapper), name, name); } /** @@ -258,7 +285,7 @@ public class ASTUtils { ClassContainer parent, String name, String descr, boolean strict, boolean field, ProcessingEnvironment env) { if(parent.elem == null) - throw new TargetNotFoundException("parent class", parent.fqn); + throw new TargetNotFoundException("parent class", parent.data.name); //try to find by name List<Element> candidates = parent.elem.getEnclosedElements() .stream() @@ -266,36 +293,37 @@ public class ASTUtils { .filter(e -> e.getSimpleName().contentEquals(name)) .collect(Collectors.toList()); - if(candidates.size() == 0) - throw new TargetNotFoundException(field ? "field" : "method", name, parent.fqn); + if(candidates.isEmpty()) + throw new TargetNotFoundException(field ? "field" : "method", name, parent.data.name); if(candidates.size() == 1 && (!strict || descr == null)) return candidates.get(0); if(descr == null) { - throw new AmbiguousDefinitionException( - String.format("Found %d members named %s in class %s!", candidates.size(), name, parent.fqn) - ); + throw new AmbiguousDefinitionException(String.format( + "Found %d members named %s in class %s!", candidates.size(), name, parent.data.name)); } else { if(field) { //fields can verify the signature for extra safety //but there can only be 1 field with a given name if(!descriptorFromType(candidates.get(0).asType(), env).equals(descr)) - throw new TargetNotFoundException("field", String.format("%s with descriptor %s", name, descr), parent.fqn); + throw new TargetNotFoundException("field", String.format( + "%s with descriptor %s", name, descr), parent.data.name); } else { candidates = candidates.stream() .map(e -> (ExecutableElement) e) .filter(strict ? c -> descr.equals(descriptorFromExecutableElement(c, env)) - : c -> descr.split("\\)")[0].equalsIgnoreCase(descriptorFromExecutableElement(c, env).split("\\)")[0]) + : c -> descr.split("\\)")[0].equalsIgnoreCase( + descriptorFromExecutableElement(c, env).split("\\)")[0]) ).collect(Collectors.toList()); } - if(candidates.size() == 0) - throw new TargetNotFoundException("method", String.format("%s %s", name, descr), parent.fqn); + if(candidates.isEmpty()) + throw new TargetNotFoundException("method", String.format( + "%s %s", name, descr), parent.data.name); if(candidates.size() > 1) - throw new AmbiguousDefinitionException( - String.format("Found %d methods named %s in class %s!", candidates.size(), name, parent.fqn) - ); + throw new AmbiguousDefinitionException(String.format( + "Found %d methods named %s in class %s!", candidates.size(), name, parent.data.name)); return candidates.get(0); } } diff --git a/src/main/java/ftbsc/lll/processor/tools/JavaPoetUtils.java b/src/main/java/ftbsc/lll/processor/tools/JavaPoetUtils.java index 77bbc2b..5709574 100644 --- a/src/main/java/ftbsc/lll/processor/tools/JavaPoetUtils.java +++ b/src/main/java/ftbsc/lll/processor/tools/JavaPoetUtils.java @@ -65,13 +65,13 @@ public class JavaPoetUtils { if(isMethod) { MethodContainer mc = MethodContainer.from(stub, t, f, options); descriptorObf = mc.descriptorObf; - nameObf = mc.nameObf; + nameObf = mc.data.nameMapped; parent = mc.parent; target = mc.elem; } else { FieldContainer fc = FieldContainer.from(var, options); descriptorObf = fc.descriptorObf; - nameObf = fc.nameObf; + nameObf = fc.data.nameMapped; parent = fc.parent; target = fc.elem; } @@ -88,7 +88,7 @@ public class JavaPoetUtils { con.addStatement( "$L.setParent($S, $L)", builderName, - parent.fqnObf, + parent.data.nameMapped.replace('/', '.'), parent.elem == null ? 0 : mapModifiers(parent.elem.getModifiers()) ); diff --git a/src/main/java/ftbsc/lll/processor/tools/containers/ClassContainer.java b/src/main/java/ftbsc/lll/processor/tools/containers/ClassContainer.java index 2c10dd6..b145e71 100644 --- a/src/main/java/ftbsc/lll/processor/tools/containers/ClassContainer.java +++ b/src/main/java/ftbsc/lll/processor/tools/containers/ClassContainer.java @@ -1,6 +1,7 @@ package ftbsc.lll.processor.tools.containers; import ftbsc.lll.exceptions.TargetNotFoundException; +import ftbsc.lll.mapper.tools.data.ClassData; import ftbsc.lll.processor.annotations.Find; import ftbsc.lll.processor.annotations.Patch; import ftbsc.lll.processor.tools.ProcessorOptions; @@ -20,15 +21,9 @@ import static ftbsc.lll.processor.tools.ASTUtils.*; */ public class ClassContainer { /** - * The fully-qualified name of the class. + * The {@link ClassData} for the class represented by this container. */ - public final String fqn; - - /** - * The obfuscated fully-qualified name of the class. - * If the mapper passed is null, then this will be identical to {@link #fqn} - */ - public final String fqnObf; + public final ClassData data; /** * The {@link Element} corresponding to the class. @@ -84,8 +79,7 @@ public class ClassContainer { throw new TargetNotFoundException("class", inner); } } - this.fqn = fqnBuilder.toString(); - this.fqnObf = findClassName(this.fqn, options); + this.data = getClassData(fqnBuilder.toString(), options.mapper); this.elem = elem; } @@ -131,6 +125,6 @@ public class ClassContainer { public static ClassContainer findOrFallback(ClassContainer fallback, Patch p, Find f, ProcessorOptions options) { if(f == null) return ClassContainer.from(p, Patch::value, p.innerName(), options); ClassContainer cl = ClassContainer.from(f, Find::value, f.innerName(), options); - return cl.fqn.equals("java.lang.Object") ? fallback : cl; + return cl.data.name.equals("java/lang/Object") ? fallback : cl; } } diff --git a/src/main/java/ftbsc/lll/processor/tools/containers/FieldContainer.java b/src/main/java/ftbsc/lll/processor/tools/containers/FieldContainer.java index 9154193..6ef4741 100644 --- a/src/main/java/ftbsc/lll/processor/tools/containers/FieldContainer.java +++ b/src/main/java/ftbsc/lll/processor/tools/containers/FieldContainer.java @@ -2,6 +2,7 @@ package ftbsc.lll.processor.tools.containers; import ftbsc.lll.exceptions.AmbiguousDefinitionException; import ftbsc.lll.mapper.tools.MappingUtils; +import ftbsc.lll.mapper.tools.data.FieldData; import ftbsc.lll.processor.annotations.Find; import ftbsc.lll.processor.annotations.Patch; import ftbsc.lll.processor.tools.ProcessorOptions; @@ -21,9 +22,9 @@ import static ftbsc.lll.processor.tools.ASTUtils.*; */ public class FieldContainer { /** - * The name of the field. + * The {@link FieldData} for the field represented by this container. */ - public final String name; + public final FieldData data; /** * The descriptor of the field. @@ -31,12 +32,6 @@ public class FieldContainer { public final String descriptor; /** - * The obfuscated name of the field. - * If the mapper passed is null, then this will be identical to {@link #name}. - */ - public final String nameObf; - - /** * The obfuscated descriptor of the field. * If the mapper passed is null, then this will be identical to {@link #descriptor}. */ @@ -67,16 +62,15 @@ public class FieldContainer { if(descriptor == null) throw new AmbiguousDefinitionException("Cannot use name-based lookups for fields of unverifiable classes!"); this.elem = null; - this.name = name; this.descriptor = descriptor; } else { this.elem = (VariableElement) findMember(parent, name, descriptor, descriptor != null, true, options.env); - this.name = this.elem.getSimpleName().toString(); this.descriptor = descriptorFromType(this.elem.asType(), options.env); + name = this.elem.getSimpleName().toString(); } + this.data = getFieldData(parent.data.name, name, options.mapper); this.descriptorObf = options.mapper == null ? this.descriptor : MappingUtils.mapType(Type.getType(this.descriptor), options.mapper, false).getDescriptor(); - this.nameObf = findMemberName(parent.fqn, this.name, null, options.mapper); } /** @@ -96,7 +90,7 @@ public class FieldContainer { ClassContainer.from((TypeElement) finder.getEnclosingElement(), options), patchAnn, f, options ); - String name = f.name().equals("") ? finder.getSimpleName().toString() : f.name(); + String name = f.name().isEmpty() ? finder.getSimpleName().toString() : f.name(); String descriptor; TypeMirror fieldType = getTypeFromAnnotation(f, Find::type, options.env); if(fieldType.toString().equals("java.lang.Object")) { @@ -106,7 +100,7 @@ public class FieldContainer { descriptor = //jank af but this is temporary anyway "L" + ClassContainer.from( f, Find::type, f.typeInner(), options - ).fqnObf.replace('.', '/') + ";"; + ).data.nameMapped + ";"; else descriptor = descriptorFromType(fieldType, options.env); } diff --git a/src/main/java/ftbsc/lll/processor/tools/containers/MethodContainer.java b/src/main/java/ftbsc/lll/processor/tools/containers/MethodContainer.java index 2878ec6..266858d 100644 --- a/src/main/java/ftbsc/lll/processor/tools/containers/MethodContainer.java +++ b/src/main/java/ftbsc/lll/processor/tools/containers/MethodContainer.java @@ -3,6 +3,7 @@ package ftbsc.lll.processor.tools.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; @@ -20,24 +21,14 @@ import static ftbsc.lll.processor.tools.ASTUtils.*; */ public class MethodContainer { /** - * The name of the method. + * The {@link MethodData} for the method represented by this container. */ - public final String name; - - /** - * The descriptor of the method. - */ - public final String descriptor; - - /** - * The obfuscated name of the method. - * If the mapper passed is null, then this will be identical to {@link #name}. - */ - public final String nameObf; + public final MethodData data; /** * The obfuscated descriptor of the field. - * If the mapper passed is null, then this will be identical to {@link #descriptor}. + * If the mapper passed is null, this will be identical to the one inside + * {@link #data}. */ public final String descriptorObf; @@ -69,19 +60,17 @@ public class MethodContainer { if(descriptor == null) throw new AmbiguousDefinitionException("Cannot use name-based lookups for methods of unverifiable classes!"); this.elem = null; - this.name = name; - this.descriptor = descriptor; } 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; - this.name = this.elem.getSimpleName().toString(); - this.descriptor = descriptorFromExecutableElement(this.elem, options.env); + name = this.elem.getSimpleName().toString(); + descriptor = descriptorFromExecutableElement(this.elem, options.env); } - this.descriptorObf = options.mapper == null ? this.descriptor - : MappingUtils.mapMethodDescriptor(this.descriptor, options.mapper, false); - this.nameObf = findMemberName(parent.fqn, this.name, this.descriptor, options.mapper); + 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); } /** @@ -101,7 +90,7 @@ public class MethodContainer { ClassContainer parent = ClassContainer.findOrFallback( ClassContainer.from((TypeElement) stub.getEnclosingElement(), options), patchAnn, f, options ); - String name = !t.methodName().equals("") + String name = !t.methodName().isEmpty() ? t.methodName() //name was specified in target : stub.getSimpleName().toString(); String descriptor = t.strict() |