summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author zaaarf <me@zaaarf.foo>2024-05-31 14:49:53 +0200
committer zaaarf <me@zaaarf.foo>2024-05-31 14:49:53 +0200
commit8d26063266b8cdbacd23ae9abdec4cf3810a2049 (patch)
treed8448bcacd54d1194c07e3f1f734e11eefe00cfc
parent4f8bde4ce277803ed7bed8034ea3d0c4df237e1b (diff)
parent9cc6ed16d37bff66b7d128a19abfcb497db6a66f (diff)
Merge branch 'feature/mapper-library' into dev0.6.1
-rw-r--r--build.gradle5
-rw-r--r--src/main/java/ftbsc/lll/exceptions/MappingNotFoundException.java27
-rw-r--r--src/main/java/ftbsc/lll/processor/LilleroProcessor.java59
-rw-r--r--src/main/java/ftbsc/lll/processor/ProcessorOptions.java (renamed from src/main/java/ftbsc/lll/processor/tools/ProcessorOptions.java)42
-rw-r--r--src/main/java/ftbsc/lll/processor/containers/ClassContainer.java (renamed from src/main/java/ftbsc/lll/processor/tools/containers/ClassContainer.java)22
-rw-r--r--src/main/java/ftbsc/lll/processor/containers/FieldContainer.java (renamed from src/main/java/ftbsc/lll/processor/tools/containers/FieldContainer.java)30
-rw-r--r--src/main/java/ftbsc/lll/processor/containers/InjectorInfo.java (renamed from src/main/java/ftbsc/lll/processor/tools/containers/InjectorInfo.java)6
-rw-r--r--src/main/java/ftbsc/lll/processor/containers/MethodContainer.java (renamed from src/main/java/ftbsc/lll/processor/tools/containers/MethodContainer.java)39
-rw-r--r--src/main/java/ftbsc/lll/processor/tools/obfuscation/ObfuscationMapper.java225
-rw-r--r--src/main/java/ftbsc/lll/processor/utils/ASTUtils.java (renamed from src/main/java/ftbsc/lll/processor/tools/ASTUtils.java)102
-rw-r--r--src/main/java/ftbsc/lll/processor/utils/JavaPoetUtils.java (renamed from src/main/java/ftbsc/lll/processor/tools/JavaPoetUtils.java)21
11 files changed, 164 insertions, 414 deletions
diff --git a/build.gradle b/build.gradle
index 0bebd2c..6ecc5eb 100644
--- a/build.gradle
+++ b/build.gradle
@@ -4,7 +4,7 @@ plugins {
}
archivesBaseName = 'processor'
-version = gitVersion().split('-').getAt(0).replace('dirty', '')
+version = versionDetails().lastTag
java {
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_1_8
@@ -27,5 +27,6 @@ repositories {
dependencies {
implementation 'com.squareup:javapoet:1.13.0'
implementation 'org.ow2.asm:asm-commons:9.5'
- implementation 'ftbsc:lll:0.4.1'
+ implementation 'ftbsc:lll:0.5.0'
+ implementation 'ftbsc.lll:mapper:0.3.0'
}
diff --git a/src/main/java/ftbsc/lll/exceptions/MappingNotFoundException.java b/src/main/java/ftbsc/lll/exceptions/MappingNotFoundException.java
deleted file mode 100644
index e943c01..0000000
--- a/src/main/java/ftbsc/lll/exceptions/MappingNotFoundException.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package ftbsc.lll.exceptions;
-
-import ftbsc.lll.processor.tools.obfuscation.ObfuscationMapper;
-
-/**
- * Thrown upon failure to find the requested mapping within a loaded {@link ObfuscationMapper}.
- */
-public class MappingNotFoundException extends RuntimeException {
-
- /**
- * Constructs a new mapping not found exception for the specified mapping.
- * @param mapping the relevant mapping
- */
- public MappingNotFoundException(String mapping) {
- super(String.format("Could not find mapping for %s!", mapping));
- }
-
- /**
- * Constructs a new mapping not found exception for the specified mapping
- * with the specified reason.
- * @param mapping the relevant mapping
- * @param reason the reason message
- */
- public MappingNotFoundException(String mapping, String reason) {
- this(mapping + ": " + reason);
- }
-}
diff --git a/src/main/java/ftbsc/lll/processor/LilleroProcessor.java b/src/main/java/ftbsc/lll/processor/LilleroProcessor.java
index b1d1f1e..b693592 100644
--- a/src/main/java/ftbsc/lll/processor/LilleroProcessor.java
+++ b/src/main/java/ftbsc/lll/processor/LilleroProcessor.java
@@ -8,10 +8,9 @@ import ftbsc.lll.IInjector;
import ftbsc.lll.exceptions.AmbiguousDefinitionException;
import ftbsc.lll.exceptions.OrphanElementException;
import ftbsc.lll.processor.annotations.*;
-import ftbsc.lll.processor.tools.ProcessorOptions;
-import ftbsc.lll.processor.tools.containers.ClassContainer;
-import ftbsc.lll.processor.tools.containers.InjectorInfo;
-import ftbsc.lll.processor.tools.containers.MethodContainer;
+import ftbsc.lll.processor.containers.ClassContainer;
+import ftbsc.lll.processor.containers.InjectorInfo;
+import ftbsc.lll.processor.containers.MethodContainer;
import ftbsc.lll.proxies.ProxyType;
import ftbsc.lll.proxies.impl.TypeProxy;
@@ -29,8 +28,8 @@ import java.io.PrintWriter;
import java.util.*;
import java.util.stream.Collectors;
-import static ftbsc.lll.processor.tools.ASTUtils.*;
-import static ftbsc.lll.processor.tools.JavaPoetUtils.*;
+import static ftbsc.lll.processor.utils.ASTUtils.*;
+import static ftbsc.lll.processor.utils.JavaPoetUtils.*;
/**
* The actual annotation processor behind the magic.
@@ -48,7 +47,7 @@ public class LilleroProcessor extends AbstractProcessor {
/**
* An object representing the various options passed to the processor.
*/
- public final ProcessorOptions options = new ProcessorOptions(processingEnv);
+ private ProcessorOptions options = null;
/**
* Method overriding default implementation to manually pass supported options.
@@ -60,6 +59,16 @@ public class LilleroProcessor extends AbstractProcessor {
}
/**
+ * Returns the {@link ProcessorOptions} for this instance, creating the object if
+ * it hasn't been already.
+ * @return the {@link ProcessorOptions} for this instance
+ */
+ public ProcessorOptions getProcessorOptions() {
+ if(this.options == null) this.options = new ProcessorOptions(this.processingEnv);
+ return this.options;
+ }
+
+ /**
* Where the actual processing happens.
* It filters through whatever annotated class it's fed, and checks whether it contains
* the required information. It then generates injectors and a service provider for every
@@ -90,7 +99,7 @@ public class LilleroProcessor extends AbstractProcessor {
}
}
}
- if (!this.options.noServiceProvider && !this.injectors.isEmpty()) {
+ if (!this.getProcessorOptions().noServiceProvider && !this.injectors.isEmpty()) {
generateServiceProvider();
return true;
} else return false;
@@ -134,7 +143,7 @@ public class LilleroProcessor extends AbstractProcessor {
//find class information
Patch patchAnn = cl.getAnnotation(Patch.class);
ClassContainer targetClass = ClassContainer.from(
- patchAnn, Patch::value, patchAnn.innerName(), this.options
+ patchAnn, Patch::value, patchAnn.innerName(), this.getProcessorOptions()
);
//find package information
Element packageElement = cl.getEnclosingElement();
@@ -156,7 +165,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;
@@ -165,17 +174,17 @@ public class LilleroProcessor extends AbstractProcessor {
if(type == ProxyType.TYPE) {
//find and validate
ClassContainer clazz = ClassContainer.findOrFallback(
- ClassContainer.from(cl, this.options),
+ ClassContainer.from(cl, this.getProcessorOptions()),
patchAnn,
proxyVar.getAnnotation(Find.class),
- this.options
+ this.getProcessorOptions()
);
//types can be generated with a single instruction
constructorBuilder.addStatement(
"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)
@@ -184,7 +193,7 @@ public class LilleroProcessor extends AbstractProcessor {
null,
null,
constructorBuilder,
- this.options
+ this.getProcessorOptions()
);
}
@@ -215,11 +224,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!",
@@ -228,11 +237,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())
);
@@ -243,7 +252,7 @@ public class LilleroProcessor extends AbstractProcessor {
matchedInjectors.add(injector);
toGenerate.put(
String.format("%sInjector%d", cl.getSimpleName(), iterationNumber),
- new InjectorInfo(injector, tg, targetAnn, this.options)
+ new InjectorInfo(injector, tg, targetAnn, this.getProcessorOptions())
);
iterationNumber++; //increment is only used by injectors
} else {
@@ -255,7 +264,7 @@ public class LilleroProcessor extends AbstractProcessor {
tg,
targetAnn,
constructorBuilder,
- this.options
+ this.getProcessorOptions()
);
}
}
@@ -280,9 +289,13 @@ public class LilleroProcessor extends AbstractProcessor {
.addMethod(constructorBuilder.build())
.addMethod(buildStringReturnMethod("name", injName))
.addMethod(buildStringReturnMethod("reason", toGenerate.get(injName).reason))
- .addMethod(buildStringReturnMethod("targetClass", this.options.obfuscateInjectorMetadata ? targetClass.fqnObf : targetClass.fqn))
- .addMethod(buildStringReturnMethod("methodName", this.options.obfuscateInjectorMetadata ? target.nameObf : target.name))
- .addMethod(buildStringReturnMethod("methodDesc", this.options.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/ProcessorOptions.java b/src/main/java/ftbsc/lll/processor/ProcessorOptions.java
index 0ef8a18..5972631 100644
--- a/src/main/java/ftbsc/lll/processor/tools/ProcessorOptions.java
+++ b/src/main/java/ftbsc/lll/processor/ProcessorOptions.java
@@ -1,16 +1,13 @@
-package ftbsc.lll.processor.tools;
+package ftbsc.lll.processor;
import ftbsc.lll.IInjector;
-import ftbsc.lll.exceptions.InvalidResourceException;
-import ftbsc.lll.processor.tools.obfuscation.ObfuscationMapper;
+import ftbsc.lll.mapper.MapperProvider;
+import ftbsc.lll.mapper.tools.Mapper;
import javax.annotation.processing.ProcessingEnvironment;
-import java.io.*;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
/**
@@ -33,10 +30,10 @@ public class ProcessorOptions {
public final ProcessingEnvironment env;
/**
- * The {@link ObfuscationMapper} used to convert classes and variables
+ * The {@link Mapper} used to convert classes and variables
* to their obfuscated equivalent. Will be null when no mapper is in use.
*/
- public final ObfuscationMapper mapper;
+ public final Mapper mapper;
/**
* Whether the processor should issue warnings when compiling code anonymous
@@ -62,29 +59,10 @@ public class ProcessorOptions {
public ProcessorOptions(ProcessingEnvironment env) {
this.env = env;
String location = env.getOptions().get("mappingsFile");
- if(location == null)
- this.mapper = null;
- else {
- InputStream targetStream;
- try {
- URI target = new URI(location);
- targetStream = target.toURL().openStream();
- } catch(URISyntaxException | IOException e) {
- //may be a local file path
- File f = new File(location);
- if(!f.exists())
- throw new InvalidResourceException(location);
- try {
- targetStream = new FileInputStream(f);
- } catch(FileNotFoundException ex) {
- throw new InvalidResourceException(location);
- }
- }
- //assuming its tsrg file
- //todo: replace crappy homebaked parser with actual library
- this.mapper = new ObfuscationMapper(new BufferedReader(new InputStreamReader(targetStream,
- StandardCharsets.UTF_8)).lines());
- }
+ if(location != null) {
+ List<String> lines = MapperProvider.fetchFromLocalOrRemote(location);
+ this.mapper = MapperProvider.getMapper(lines).getMapper(lines, true);
+ } else this.mapper = null;
this.anonymousClassWarning = parseBooleanArg(env.getOptions().get("anonymousClassWarning"), true);
this.obfuscateInjectorMetadata = parseBooleanArg(env.getOptions().get("obfuscateInjectorMetadata"), true);
this.noServiceProvider = parseBooleanArg(env.getOptions().get("noServiceProvider"), false);
diff --git a/src/main/java/ftbsc/lll/processor/tools/containers/ClassContainer.java b/src/main/java/ftbsc/lll/processor/containers/ClassContainer.java
index 2c10dd6..297349a 100644
--- a/src/main/java/ftbsc/lll/processor/tools/containers/ClassContainer.java
+++ b/src/main/java/ftbsc/lll/processor/containers/ClassContainer.java
@@ -1,9 +1,10 @@
-package ftbsc.lll.processor.tools.containers;
+package ftbsc.lll.processor.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;
+import ftbsc.lll.processor.ProcessorOptions;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
@@ -11,7 +12,7 @@ import javax.tools.Diagnostic;
import java.lang.annotation.Annotation;
import java.util.function.Function;
-import static ftbsc.lll.processor.tools.ASTUtils.*;
+import static ftbsc.lll.processor.utils.ASTUtils.*;
/**
* Container for information about a class.
@@ -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/containers/FieldContainer.java
index 2dd2ecb..2299c93 100644
--- a/src/main/java/ftbsc/lll/processor/tools/containers/FieldContainer.java
+++ b/src/main/java/ftbsc/lll/processor/containers/FieldContainer.java
@@ -1,9 +1,11 @@
-package ftbsc.lll.processor.tools.containers;
+package ftbsc.lll.processor.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;
+import ftbsc.lll.processor.ProcessorOptions;
import org.objectweb.asm.Type;
import javax.lang.model.element.TypeElement;
@@ -11,7 +13,7 @@ import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
-import static ftbsc.lll.processor.tools.ASTUtils.*;
+import static ftbsc.lll.processor.utils.ASTUtils.*;
/**
* Container for information about a field.
@@ -20,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.
@@ -30,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}.
*/
@@ -66,15 +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.descriptorObf = options.mapper == null ? this.descriptor : options.mapper.obfuscateType(Type.getType(this.descriptor)).getDescriptor();
- this.nameObf = findMemberName(parent.fqn, this.name, null, options.mapper);
+ 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();
}
/**
@@ -94,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")) {
@@ -104,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/InjectorInfo.java b/src/main/java/ftbsc/lll/processor/containers/InjectorInfo.java
index 460401b..d56d846 100644
--- a/src/main/java/ftbsc/lll/processor/tools/containers/InjectorInfo.java
+++ b/src/main/java/ftbsc/lll/processor/containers/InjectorInfo.java
@@ -1,8 +1,8 @@
-package ftbsc.lll.processor.tools.containers;
+package ftbsc.lll.processor.containers;
import ftbsc.lll.processor.annotations.Injector;
import ftbsc.lll.processor.annotations.Target;
-import ftbsc.lll.processor.tools.ProcessorOptions;
+import ftbsc.lll.processor.ProcessorOptions;
import javax.lang.model.element.ExecutableElement;
@@ -43,4 +43,4 @@ public class InjectorInfo {
this.reason = injector.getAnnotation(Injector.class).reason();
this.target = MethodContainer.from(targetStub, targetAnn, null, options);
}
-} \ No newline at end of file
+}
diff --git a/src/main/java/ftbsc/lll/processor/tools/containers/MethodContainer.java b/src/main/java/ftbsc/lll/processor/containers/MethodContainer.java
index 714ee54..7d15599 100644
--- a/src/main/java/ftbsc/lll/processor/tools/containers/MethodContainer.java
+++ b/src/main/java/ftbsc/lll/processor/containers/MethodContainer.java
@@ -1,16 +1,18 @@
-package ftbsc.lll.processor.tools.containers;
+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.tools.ProcessorOptions;
+import ftbsc.lll.processor.ProcessorOptions;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
-import static ftbsc.lll.processor.tools.ASTUtils.*;
+import static ftbsc.lll.processor.utils.ASTUtils.*;
/**
* Container for information about a method.
@@ -19,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;
@@ -68,18 +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 : options.mapper.obfuscateMethodDescriptor(this.descriptor);
- 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);
}
/**
@@ -99,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()
diff --git a/src/main/java/ftbsc/lll/processor/tools/obfuscation/ObfuscationMapper.java b/src/main/java/ftbsc/lll/processor/tools/obfuscation/ObfuscationMapper.java
deleted file mode 100644
index 5938de3..0000000
--- a/src/main/java/ftbsc/lll/processor/tools/obfuscation/ObfuscationMapper.java
+++ /dev/null
@@ -1,225 +0,0 @@
-package ftbsc.lll.processor.tools.obfuscation;
-
-import ftbsc.lll.exceptions.AmbiguousDefinitionException;
-import ftbsc.lll.exceptions.MappingNotFoundException;
-import ftbsc.lll.tools.DescriptorBuilder;
-import org.objectweb.asm.Type;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-/**
- * Parses a .tsrg file into a mapper capable of converting from
- * deobfuscated names to obfuscated ones.
- * Obviously, it may only be used at runtime if the .tsrg file is
- * included in the resources. However, in that case, I'd recommend
- * using the built-in Forge one and refrain from including an extra
- * resource for no good reason.
- * TODO: CSV format
- * @since 0.2.0
- */
-public class ObfuscationMapper {
-
- /**
- * A Map using the deobfuscated names as keys,
- * holding information for that class as value.
- */
- private final Map<String, ObfuscationData> mapper = new HashMap<>();
-
- /**
- * The public constructor.
- * Should be passed a {@link Stream} of Strings, one representing each line.
- * Whether they contain line endings or not is irrelevant.
- * @param str a {@link Stream} of strings
- */
- public ObfuscationMapper(Stream<String> str) {
- AtomicReference<String> currentClass = new AtomicReference<>("");
- str.forEach(l -> {
- if(l == null) return;
- if(l.startsWith("\t"))
- mapper.get(currentClass.get()).addMember(l);
- else {
- String[] sp = l.split(" ");
- ObfuscationData s = new ObfuscationData(sp[0], sp[1]);
- currentClass.set(s.unobf);
- mapper.put(s.unobf, s);
- }
- });
- }
-
- /**
- * Gets the obfuscated name of the class.
- * @param name the unobfuscated internal name of the desired class
- * @return the obfuscated name of the class
- * @throws MappingNotFoundException if no mapping is found
- */
- public String obfuscateClass(String name) {
- ObfuscationData data = mapper.get(name.replace('.', '/'));
- if(data == null)
- throw new MappingNotFoundException(name);
- else return data.obf;
- }
-
- /**
- * Gets the obfuscated name of a class member (field or method).
- * The method signature must be in this format: "methodName methodDescriptor",
- * with a space, because that's how it is in .tsrg files.
- * @param parentName the unobfuscated internal name of the parent class
- * @param memberName the field name or method signature
- * @param methodDescriptor the optional descriptor of the member, may be null or partial
- * @return the obfuscated name of the given member
- * @throws MappingNotFoundException if no mapping is found
- */
- public String obfuscateMember(String parentName, String memberName, String methodDescriptor) {
- ObfuscationData data = mapper.get(parentName.replace('.', '/'));
- if(data == null)
- throw new MappingNotFoundException(parentName + "::" + memberName);
- return data.get(memberName, methodDescriptor);
- }
-
- /**
- * Obfuscates a method descriptor, replacing its class references
- * with their obfuscated counterparts.
- * @param descriptor a {@link String} containing the descriptor
- * @return the obfuscated descriptor
- * @since 0.5.1
- */
- public String obfuscateMethodDescriptor(String descriptor) {
- Type method = Type.getMethodType(descriptor);
- Type[] arguments = method.getArgumentTypes();
- Type returnType = method.getReturnType();
-
- Type[] obfArguments = new Type[arguments.length];
- for(int i = 0; i < obfArguments.length; i++)
- obfArguments[i] = this.obfuscateType(arguments[i]);
-
- return Type.getMethodDescriptor(this.obfuscateType(returnType), obfArguments);
- }
-
- /**
- * Given a {@link Type} it returns its obfuscated counterpart.
- * @param type the type in question
- * @return the obfuscated type
- * @since 0.5.1
- */
- public Type obfuscateType(Type type) {
- //unwrap arrays
- Type unwrapped = type;
- int arrayLevel = 0;
- while(unwrapped.getSort() == org.objectweb.asm.Type.ARRAY) {
- unwrapped = unwrapped.getElementType();
- arrayLevel++;
- }
-
- //if it's a primitive no operation is needed
- if(type.getSort() < org.objectweb.asm.Type.ARRAY)
- return type;
-
- String internalName = type.getInternalName();
-
- String internalNameObf;
- try {
- internalNameObf = this.obfuscateClass(internalName);
- return Type.getType(DescriptorBuilder.nameToDescriptor(internalNameObf, arrayLevel));
- } catch(MappingNotFoundException e) {
- return type;
- }
- }
-
- /**
- * Private class used internally for storing information about each
- * class. It's private because there is no good reason anyone would
- * want to access this outside of this class.
- */
- private static class ObfuscationData {
- /**
- * The unobfuscated name (FQN with '/' instad of '.') of the class.
- */
- private final String unobf;
-
- /**
- * The obfuscated internal name (FQN with '/' instad of '.') of the class.
- */
- private final String obf;
-
- /**
- * A {@link Map} tying each member's name or signature to its
- * obfuscated counterpart.
- */
- private final Map<String, String> members;
-
- /**
- * The constructor. It takes in the names (obfuscated and non-obfuscated)
- * of a class.
- * @param unobf the unobfuscated name
- * @param obf the obfuscated name
- */
- private ObfuscationData(String unobf, String obf) {
- this.unobf = unobf;
- this.obf = obf;
- this.members = new HashMap<>();
- }
-
- /**
- * Adds a member to the target class.
- * For fields only the names are required; for methods,
- * this takes in the full signature ({@code name + " " + space}).
- * @param s the String representing the declaration line
- */
- public void addMember(String s) {
- String[] split = s.trim().split(" ");
- if(split.length == 2) //field
- members.put(split[0], split[1]);
- else if (split.length == 3) //method
- members.put(split[0] + " " + split[1], split[2]);
- }
-
- /**
- * Gets an obfuscated member given the method name and a method descriptor,
- * which may be partial (i.e. not include return type) or null if the member
- * is not a method.
- * @param memberName member name
- * @param methodDescriptor the method descriptor, or null if it's not a method
- * @return the requested obfuscated name, or null if nothing was found
- * @throws AmbiguousDefinitionException if not enough data was given to uniquely identify a mapping
- */
- public String get(String memberName, String methodDescriptor) {
-
- //find all keys that start with the name
- List<String> candidates = members.keySet().stream().filter(
- m -> m.split(" ")[0].equals(memberName)
- ).collect(Collectors.toList());
-
- if(methodDescriptor != null) {
- String signature = String.format("%s %s", memberName, methodDescriptor);
- candidates = candidates.stream().filter(
- m -> m.equals(signature)
- ).collect(Collectors.toList());
- }
-
- switch(candidates.size()) {
- case 0:
- throw new MappingNotFoundException(String.format(
- "%s.%s%s",
- this.unobf,
- memberName,
- methodDescriptor == null ? "" : "()"
- ));
- case 1:
- return members.get(candidates.get(0));
- default:
- throw new AmbiguousDefinitionException(String.format(
- "Mapper could not uniquely identify member %s.%s%s, found %d!",
- this.unobf,
- memberName,
- methodDescriptor == null ? "" : "()",
- candidates.size()
- ));
- }
- }
- }
-}
diff --git a/src/main/java/ftbsc/lll/processor/tools/ASTUtils.java b/src/main/java/ftbsc/lll/processor/utils/ASTUtils.java
index 0037886..04da70e 100644
--- a/src/main/java/ftbsc/lll/processor/tools/ASTUtils.java
+++ b/src/main/java/ftbsc/lll/processor/utils/ASTUtils.java
@@ -1,12 +1,15 @@
-package ftbsc.lll.processor.tools;
+package ftbsc.lll.processor.utils;
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.Mapper;
+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.processor.tools.obfuscation.ObfuscationMapper;
+import ftbsc.lll.processor.containers.ClassContainer;
import ftbsc.lll.proxies.ProxyType;
import javax.annotation.processing.ProcessingEnvironment;
@@ -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 Mapper} 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, Mapper 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
- * @param mapper the {@link ObfuscationMapper} to use, may be null
- * @return the internal class name
- * @since 0.3.0
+ * 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 Mapper} to use, may be null
+ * @return the fully qualified class name
+ * @since 0.6.1
*/
- public static String findMemberName(String parentFQN, String memberName, String methodDescriptor, ObfuscationMapper mapper) {
+ public static MethodData getMethodData(String parent, String name, String descriptor, Mapper 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 Mapper} to use, may be null
+ * @return the fully qualified class name
+ * @since 0.6.1
+ */
+ public static FieldData getFieldData(String parent, String name, Mapper 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/utils/JavaPoetUtils.java
index 77bbc2b..629f77a 100644
--- a/src/main/java/ftbsc/lll/processor/tools/JavaPoetUtils.java
+++ b/src/main/java/ftbsc/lll/processor/utils/JavaPoetUtils.java
@@ -1,12 +1,13 @@
-package ftbsc.lll.processor.tools;
+package ftbsc.lll.processor.utils;
import com.squareup.javapoet.*;
+import ftbsc.lll.processor.ProcessorOptions;
import ftbsc.lll.processor.annotations.Find;
import ftbsc.lll.processor.annotations.Target;
-import ftbsc.lll.processor.tools.containers.ClassContainer;
-import ftbsc.lll.processor.tools.containers.FieldContainer;
-import ftbsc.lll.processor.tools.containers.InjectorInfo;
-import ftbsc.lll.processor.tools.containers.MethodContainer;
+import ftbsc.lll.processor.containers.ClassContainer;
+import ftbsc.lll.processor.containers.FieldContainer;
+import ftbsc.lll.processor.containers.InjectorInfo;
+import ftbsc.lll.processor.containers.MethodContainer;
import ftbsc.lll.proxies.ProxyType;
import ftbsc.lll.proxies.impl.FieldProxy;
import ftbsc.lll.proxies.impl.MethodProxy;
@@ -15,8 +16,8 @@ import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.*;
import java.util.HashSet;
-import static ftbsc.lll.processor.tools.ASTUtils.getProxyType;
-import static ftbsc.lll.processor.tools.ASTUtils.mapModifiers;
+import static ftbsc.lll.processor.utils.ASTUtils.getProxyType;
+import static ftbsc.lll.processor.utils.ASTUtils.mapModifiers;
/**
* Collection of static utils that rely on JavaPoet to function.
@@ -65,13 +66,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 +89,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())
);