mirror of
https://github.com/zaaarf/lillero-processor.git
synced 2024-11-25 01:14:52 +01:00
Compare commits
9 commits
4f8bde4ce2
...
8d26063266
Author | SHA1 | Date | |
---|---|---|---|
8d26063266 | |||
9cc6ed16d3 | |||
d98eab7e7d | |||
bf32e56a86 | |||
3dd86a4187 | |||
30f8e080ae | |||
8e3284a904 | |||
3f730c69d3 | |||
ed70355a86 |
11 changed files with 164 additions and 414 deletions
|
@ -4,7 +4,7 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
archivesBaseName = 'processor'
|
archivesBaseName = 'processor'
|
||||||
version = gitVersion().split('-').getAt(0).replace('dirty', '')
|
version = versionDetails().lastTag
|
||||||
|
|
||||||
java {
|
java {
|
||||||
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_1_8
|
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
@ -27,5 +27,6 @@ repositories {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'com.squareup:javapoet:1.13.0'
|
implementation 'com.squareup:javapoet:1.13.0'
|
||||||
implementation 'org.ow2.asm:asm-commons:9.5'
|
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'
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -8,10 +8,9 @@ import ftbsc.lll.IInjector;
|
||||||
import ftbsc.lll.exceptions.AmbiguousDefinitionException;
|
import ftbsc.lll.exceptions.AmbiguousDefinitionException;
|
||||||
import ftbsc.lll.exceptions.OrphanElementException;
|
import ftbsc.lll.exceptions.OrphanElementException;
|
||||||
import ftbsc.lll.processor.annotations.*;
|
import ftbsc.lll.processor.annotations.*;
|
||||||
import ftbsc.lll.processor.tools.ProcessorOptions;
|
import ftbsc.lll.processor.containers.ClassContainer;
|
||||||
import ftbsc.lll.processor.tools.containers.ClassContainer;
|
import ftbsc.lll.processor.containers.InjectorInfo;
|
||||||
import ftbsc.lll.processor.tools.containers.InjectorInfo;
|
import ftbsc.lll.processor.containers.MethodContainer;
|
||||||
import ftbsc.lll.processor.tools.containers.MethodContainer;
|
|
||||||
import ftbsc.lll.proxies.ProxyType;
|
import ftbsc.lll.proxies.ProxyType;
|
||||||
import ftbsc.lll.proxies.impl.TypeProxy;
|
import ftbsc.lll.proxies.impl.TypeProxy;
|
||||||
|
|
||||||
|
@ -29,8 +28,8 @@ import java.io.PrintWriter;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static ftbsc.lll.processor.tools.ASTUtils.*;
|
import static ftbsc.lll.processor.utils.ASTUtils.*;
|
||||||
import static ftbsc.lll.processor.tools.JavaPoetUtils.*;
|
import static ftbsc.lll.processor.utils.JavaPoetUtils.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The actual annotation processor behind the magic.
|
* 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.
|
* 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.
|
* Method overriding default implementation to manually pass supported options.
|
||||||
|
@ -59,6 +58,16 @@ public class LilleroProcessor extends AbstractProcessor {
|
||||||
return ProcessorOptions.SUPPORTED;
|
return ProcessorOptions.SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
* Where the actual processing happens.
|
||||||
* It filters through whatever annotated class it's fed, and checks whether it contains
|
* It filters through whatever annotated class it's fed, and checks whether it contains
|
||||||
|
@ -90,7 +99,7 @@ public class LilleroProcessor extends AbstractProcessor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!this.options.noServiceProvider && !this.injectors.isEmpty()) {
|
if (!this.getProcessorOptions().noServiceProvider && !this.injectors.isEmpty()) {
|
||||||
generateServiceProvider();
|
generateServiceProvider();
|
||||||
return true;
|
return true;
|
||||||
} else return false;
|
} else return false;
|
||||||
|
@ -134,7 +143,7 @@ public class LilleroProcessor extends AbstractProcessor {
|
||||||
//find class information
|
//find class information
|
||||||
Patch patchAnn = cl.getAnnotation(Patch.class);
|
Patch patchAnn = cl.getAnnotation(Patch.class);
|
||||||
ClassContainer targetClass = ClassContainer.from(
|
ClassContainer targetClass = ClassContainer.from(
|
||||||
patchAnn, Patch::value, patchAnn.innerName(), this.options
|
patchAnn, Patch::value, patchAnn.innerName(), this.getProcessorOptions()
|
||||||
);
|
);
|
||||||
//find package information
|
//find package information
|
||||||
Element packageElement = cl.getEnclosingElement();
|
Element packageElement = cl.getEnclosingElement();
|
||||||
|
@ -156,7 +165,7 @@ public class LilleroProcessor extends AbstractProcessor {
|
||||||
//take care of TypeProxies and FieldProxies first
|
//take care of TypeProxies and FieldProxies first
|
||||||
for(VariableElement proxyVar : finders) {
|
for(VariableElement proxyVar : finders) {
|
||||||
ProxyType type = getProxyType(proxyVar);
|
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
|
//methods without a specified name will be handled later
|
||||||
methodFinders.add(proxyVar);
|
methodFinders.add(proxyVar);
|
||||||
continue;
|
continue;
|
||||||
|
@ -165,17 +174,17 @@ public class LilleroProcessor extends AbstractProcessor {
|
||||||
if(type == ProxyType.TYPE) {
|
if(type == ProxyType.TYPE) {
|
||||||
//find and validate
|
//find and validate
|
||||||
ClassContainer clazz = ClassContainer.findOrFallback(
|
ClassContainer clazz = ClassContainer.findOrFallback(
|
||||||
ClassContainer.from(cl, this.options),
|
ClassContainer.from(cl, this.getProcessorOptions()),
|
||||||
patchAnn,
|
patchAnn,
|
||||||
proxyVar.getAnnotation(Find.class),
|
proxyVar.getAnnotation(Find.class),
|
||||||
this.options
|
this.getProcessorOptions()
|
||||||
);
|
);
|
||||||
//types can be generated with a single instruction
|
//types can be generated with a single instruction
|
||||||
constructorBuilder.addStatement(
|
constructorBuilder.addStatement(
|
||||||
"super.$L = $T.from($S, 0, $L)",
|
"super.$L = $T.from($S, 0, $L)",
|
||||||
proxyVar.getSimpleName().toString(),
|
proxyVar.getSimpleName().toString(),
|
||||||
TypeProxy.class,
|
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())
|
clazz.elem == null ? 0 : mapModifiers(clazz.elem.getModifiers())
|
||||||
);
|
);
|
||||||
} else if(type == ProxyType.FIELD)
|
} else if(type == ProxyType.FIELD)
|
||||||
|
@ -184,7 +193,7 @@ public class LilleroProcessor extends AbstractProcessor {
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
constructorBuilder,
|
constructorBuilder,
|
||||||
this.options
|
this.getProcessorOptions()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,11 +224,11 @@ public class LilleroProcessor extends AbstractProcessor {
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
//throw exception if user is a moron and defined a finder and an injector with the same name
|
//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(
|
throw new AmbiguousDefinitionException(
|
||||||
String.format("Target specified user %s, but name was used by both a finder and injector.", targetAnn.of())
|
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,
|
processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING,
|
||||||
String.format(
|
String.format(
|
||||||
"Found orphan @Target annotation on method %s.%s pointing at method %s, it will be ignored!",
|
"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()
|
targetAnn.of()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
else if(finderCandidates.size() == 0 && injectorCandidates.size() != 1)
|
else if(finderCandidates.isEmpty() && injectorCandidates.size() != 1)
|
||||||
throw new AmbiguousDefinitionException(
|
throw new AmbiguousDefinitionException(
|
||||||
String.format("Found multiple candidate injectors for target %s::%s!", cl.getSimpleName(), tg.getSimpleName())
|
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(
|
throw new AmbiguousDefinitionException(
|
||||||
String.format("Found multiple candidate finders for target %s::%s!", cl.getSimpleName(), tg.getSimpleName())
|
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);
|
matchedInjectors.add(injector);
|
||||||
toGenerate.put(
|
toGenerate.put(
|
||||||
String.format("%sInjector%d", cl.getSimpleName(), iterationNumber),
|
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
|
iterationNumber++; //increment is only used by injectors
|
||||||
} else {
|
} else {
|
||||||
|
@ -255,7 +264,7 @@ public class LilleroProcessor extends AbstractProcessor {
|
||||||
tg,
|
tg,
|
||||||
targetAnn,
|
targetAnn,
|
||||||
constructorBuilder,
|
constructorBuilder,
|
||||||
this.options
|
this.getProcessorOptions()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -280,9 +289,13 @@ public class LilleroProcessor extends AbstractProcessor {
|
||||||
.addMethod(constructorBuilder.build())
|
.addMethod(constructorBuilder.build())
|
||||||
.addMethod(buildStringReturnMethod("name", injName))
|
.addMethod(buildStringReturnMethod("name", injName))
|
||||||
.addMethod(buildStringReturnMethod("reason", toGenerate.get(injName).reason))
|
.addMethod(buildStringReturnMethod("reason", toGenerate.get(injName).reason))
|
||||||
.addMethod(buildStringReturnMethod("targetClass", this.options.obfuscateInjectorMetadata ? targetClass.fqnObf : targetClass.fqn))
|
.addMethod(buildStringReturnMethod("targetClass", this.getProcessorOptions().obfuscateInjectorMetadata
|
||||||
.addMethod(buildStringReturnMethod("methodName", this.options.obfuscateInjectorMetadata ? target.nameObf : target.name))
|
? targetClass.data.nameMapped.replace('/', '.')
|
||||||
.addMethod(buildStringReturnMethod("methodDesc", this.options.obfuscateInjectorMetadata ? target.descriptorObf : target.descriptor))
|
: 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))
|
.addMethods(generateDummies(cl))
|
||||||
.addMethod(generateInjector(toGenerate.get(injName), this.processingEnv))
|
.addMethod(generateInjector(toGenerate.get(injName), this.processingEnv))
|
||||||
.build();
|
.build();
|
||||||
|
|
|
@ -1,16 +1,13 @@
|
||||||
package ftbsc.lll.processor.tools;
|
package ftbsc.lll.processor;
|
||||||
|
|
||||||
import ftbsc.lll.IInjector;
|
import ftbsc.lll.IInjector;
|
||||||
import ftbsc.lll.exceptions.InvalidResourceException;
|
import ftbsc.lll.mapper.MapperProvider;
|
||||||
import ftbsc.lll.processor.tools.obfuscation.ObfuscationMapper;
|
import ftbsc.lll.mapper.tools.Mapper;
|
||||||
|
|
||||||
import javax.annotation.processing.ProcessingEnvironment;
|
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.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,10 +30,10 @@ public class ProcessorOptions {
|
||||||
public final ProcessingEnvironment env;
|
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.
|
* 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
|
* Whether the processor should issue warnings when compiling code anonymous
|
||||||
|
@ -62,29 +59,10 @@ public class ProcessorOptions {
|
||||||
public ProcessorOptions(ProcessingEnvironment env) {
|
public ProcessorOptions(ProcessingEnvironment env) {
|
||||||
this.env = env;
|
this.env = env;
|
||||||
String location = env.getOptions().get("mappingsFile");
|
String location = env.getOptions().get("mappingsFile");
|
||||||
if(location == null)
|
if(location != null) {
|
||||||
this.mapper = null;
|
List<String> lines = MapperProvider.fetchFromLocalOrRemote(location);
|
||||||
else {
|
this.mapper = MapperProvider.getMapper(lines).getMapper(lines, true);
|
||||||
InputStream targetStream;
|
} else this.mapper = null;
|
||||||
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());
|
|
||||||
}
|
|
||||||
this.anonymousClassWarning = parseBooleanArg(env.getOptions().get("anonymousClassWarning"), true);
|
this.anonymousClassWarning = parseBooleanArg(env.getOptions().get("anonymousClassWarning"), true);
|
||||||
this.obfuscateInjectorMetadata = parseBooleanArg(env.getOptions().get("obfuscateInjectorMetadata"), true);
|
this.obfuscateInjectorMetadata = parseBooleanArg(env.getOptions().get("obfuscateInjectorMetadata"), true);
|
||||||
this.noServiceProvider = parseBooleanArg(env.getOptions().get("noServiceProvider"), false);
|
this.noServiceProvider = parseBooleanArg(env.getOptions().get("noServiceProvider"), false);
|
|
@ -1,9 +1,10 @@
|
||||||
package ftbsc.lll.processor.tools.containers;
|
package ftbsc.lll.processor.containers;
|
||||||
|
|
||||||
import ftbsc.lll.exceptions.TargetNotFoundException;
|
import ftbsc.lll.exceptions.TargetNotFoundException;
|
||||||
|
import ftbsc.lll.mapper.tools.data.ClassData;
|
||||||
import ftbsc.lll.processor.annotations.Find;
|
import ftbsc.lll.processor.annotations.Find;
|
||||||
import ftbsc.lll.processor.annotations.Patch;
|
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.Element;
|
||||||
import javax.lang.model.element.TypeElement;
|
import javax.lang.model.element.TypeElement;
|
||||||
|
@ -11,7 +12,7 @@ import javax.tools.Diagnostic;
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.util.function.Function;
|
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.
|
* Container for information about a class.
|
||||||
|
@ -20,15 +21,9 @@ import static ftbsc.lll.processor.tools.ASTUtils.*;
|
||||||
*/
|
*/
|
||||||
public class ClassContainer {
|
public class ClassContainer {
|
||||||
/**
|
/**
|
||||||
* The fully-qualified name of the class.
|
* The {@link ClassData} for the class represented by this container.
|
||||||
*/
|
*/
|
||||||
public final String fqn;
|
public final ClassData data;
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link Element} corresponding to the class.
|
* The {@link Element} corresponding to the class.
|
||||||
|
@ -84,8 +79,7 @@ public class ClassContainer {
|
||||||
throw new TargetNotFoundException("class", inner);
|
throw new TargetNotFoundException("class", inner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.fqn = fqnBuilder.toString();
|
this.data = getClassData(fqnBuilder.toString(), options.mapper);
|
||||||
this.fqnObf = findClassName(this.fqn, options);
|
|
||||||
this.elem = elem;
|
this.elem = elem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,6 +125,6 @@ public class ClassContainer {
|
||||||
public static ClassContainer findOrFallback(ClassContainer fallback, Patch p, Find f, ProcessorOptions options) {
|
public static ClassContainer findOrFallback(ClassContainer fallback, Patch p, Find f, ProcessorOptions options) {
|
||||||
if(f == null) return ClassContainer.from(p, Patch::value, p.innerName(), options);
|
if(f == null) return ClassContainer.from(p, Patch::value, p.innerName(), options);
|
||||||
ClassContainer cl = ClassContainer.from(f, Find::value, f.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;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,9 +1,11 @@
|
||||||
package ftbsc.lll.processor.tools.containers;
|
package ftbsc.lll.processor.containers;
|
||||||
|
|
||||||
import ftbsc.lll.exceptions.AmbiguousDefinitionException;
|
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.Find;
|
||||||
import ftbsc.lll.processor.annotations.Patch;
|
import ftbsc.lll.processor.annotations.Patch;
|
||||||
import ftbsc.lll.processor.tools.ProcessorOptions;
|
import ftbsc.lll.processor.ProcessorOptions;
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
|
|
||||||
import javax.lang.model.element.TypeElement;
|
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.TypeKind;
|
||||||
import javax.lang.model.type.TypeMirror;
|
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.
|
* Container for information about a field.
|
||||||
|
@ -20,21 +22,15 @@ import static ftbsc.lll.processor.tools.ASTUtils.*;
|
||||||
*/
|
*/
|
||||||
public class FieldContainer {
|
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.
|
* The descriptor of the field.
|
||||||
*/
|
*/
|
||||||
public final String descriptor;
|
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.
|
* 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, then this will be identical to {@link #descriptor}.
|
||||||
|
@ -66,15 +62,15 @@ public class FieldContainer {
|
||||||
if(descriptor == null)
|
if(descriptor == null)
|
||||||
throw new AmbiguousDefinitionException("Cannot use name-based lookups for fields of unverifiable classes!");
|
throw new AmbiguousDefinitionException("Cannot use name-based lookups for fields of unverifiable classes!");
|
||||||
this.elem = null;
|
this.elem = null;
|
||||||
this.name = name;
|
|
||||||
this.descriptor = descriptor;
|
this.descriptor = descriptor;
|
||||||
} else {
|
} else {
|
||||||
this.elem = (VariableElement) findMember(parent, name, descriptor, descriptor != null, true, options.env);
|
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);
|
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.data = getFieldData(parent.data.name, name, options.mapper);
|
||||||
this.nameObf = findMemberName(parent.fqn, this.name, null, 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
|
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;
|
String descriptor;
|
||||||
TypeMirror fieldType = getTypeFromAnnotation(f, Find::type, options.env);
|
TypeMirror fieldType = getTypeFromAnnotation(f, Find::type, options.env);
|
||||||
if(fieldType.toString().equals("java.lang.Object")) {
|
if(fieldType.toString().equals("java.lang.Object")) {
|
||||||
|
@ -104,7 +100,7 @@ public class FieldContainer {
|
||||||
descriptor = //jank af but this is temporary anyway
|
descriptor = //jank af but this is temporary anyway
|
||||||
"L" + ClassContainer.from(
|
"L" + ClassContainer.from(
|
||||||
f, Find::type, f.typeInner(), options
|
f, Find::type, f.typeInner(), options
|
||||||
).fqnObf.replace('.', '/') + ";";
|
).data.nameMapped + ";";
|
||||||
else descriptor = descriptorFromType(fieldType, options.env);
|
else descriptor = descriptorFromType(fieldType, options.env);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.Injector;
|
||||||
import ftbsc.lll.processor.annotations.Target;
|
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.ExecutableElement;
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
package ftbsc.lll.processor.tools.containers;
|
package ftbsc.lll.processor.containers;
|
||||||
|
|
||||||
import ftbsc.lll.exceptions.AmbiguousDefinitionException;
|
import ftbsc.lll.exceptions.AmbiguousDefinitionException;
|
||||||
import ftbsc.lll.exceptions.TargetNotFoundException;
|
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.Find;
|
||||||
import ftbsc.lll.processor.annotations.Patch;
|
import ftbsc.lll.processor.annotations.Patch;
|
||||||
import ftbsc.lll.processor.annotations.Target;
|
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.ExecutableElement;
|
||||||
import javax.lang.model.element.TypeElement;
|
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.
|
* Container for information about a method.
|
||||||
|
@ -19,24 +21,14 @@ import static ftbsc.lll.processor.tools.ASTUtils.*;
|
||||||
*/
|
*/
|
||||||
public class MethodContainer {
|
public class MethodContainer {
|
||||||
/**
|
/**
|
||||||
* The name of the method.
|
* The {@link MethodData} for the method represented by this container.
|
||||||
*/
|
*/
|
||||||
public final String name;
|
public final MethodData data;
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The obfuscated descriptor of the field.
|
* 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;
|
public final String descriptorObf;
|
||||||
|
|
||||||
|
@ -68,18 +60,17 @@ public class MethodContainer {
|
||||||
if(descriptor == null)
|
if(descriptor == null)
|
||||||
throw new AmbiguousDefinitionException("Cannot use name-based lookups for methods of unverifiable classes!");
|
throw new AmbiguousDefinitionException("Cannot use name-based lookups for methods of unverifiable classes!");
|
||||||
this.elem = null;
|
this.elem = null;
|
||||||
this.name = name;
|
|
||||||
this.descriptor = descriptor;
|
|
||||||
} else {
|
} else {
|
||||||
ExecutableElement tmp = (ExecutableElement) findMember(
|
ExecutableElement tmp = (ExecutableElement) findMember(
|
||||||
parent, name, descriptor, descriptor != null && strict,false, options.env
|
parent, name, descriptor, descriptor != null && strict,false, options.env
|
||||||
);
|
);
|
||||||
this.elem = bridge ? findSyntheticBridge((TypeElement) this.parent.elem, tmp, options.env) : tmp;
|
this.elem = bridge ? findSyntheticBridge((TypeElement) this.parent.elem, tmp, options.env) : tmp;
|
||||||
this.name = this.elem.getSimpleName().toString();
|
name = this.elem.getSimpleName().toString();
|
||||||
this.descriptor = descriptorFromExecutableElement(this.elem, options.env);
|
descriptor = descriptorFromExecutableElement(this.elem, options.env);
|
||||||
}
|
}
|
||||||
this.descriptorObf = options.mapper == null ? this.descriptor : options.mapper.obfuscateMethodDescriptor(this.descriptor);
|
this.data = getMethodData(parent.data.name, name, descriptor, options.mapper);
|
||||||
this.nameObf = findMemberName(parent.fqn, this.name, this.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 parent = ClassContainer.findOrFallback(
|
||||||
ClassContainer.from((TypeElement) stub.getEnclosingElement(), options), patchAnn, f, options
|
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
|
? t.methodName() //name was specified in target
|
||||||
: stub.getSimpleName().toString();
|
: stub.getSimpleName().toString();
|
||||||
String descriptor = t.strict()
|
String descriptor = t.strict()
|
|
@ -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()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +1,15 @@
|
||||||
package ftbsc.lll.processor.tools;
|
package ftbsc.lll.processor.utils;
|
||||||
|
|
||||||
import ftbsc.lll.exceptions.AmbiguousDefinitionException;
|
import ftbsc.lll.exceptions.AmbiguousDefinitionException;
|
||||||
import ftbsc.lll.exceptions.MappingNotFoundException;
|
import ftbsc.lll.exceptions.MappingNotFoundException;
|
||||||
import ftbsc.lll.exceptions.NotAProxyException;
|
import ftbsc.lll.exceptions.NotAProxyException;
|
||||||
import ftbsc.lll.exceptions.TargetNotFoundException;
|
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.annotations.Target;
|
||||||
import ftbsc.lll.processor.tools.containers.ClassContainer;
|
import ftbsc.lll.processor.containers.ClassContainer;
|
||||||
import ftbsc.lll.processor.tools.obfuscation.ObfuscationMapper;
|
|
||||||
import ftbsc.lll.proxies.ProxyType;
|
import ftbsc.lll.proxies.ProxyType;
|
||||||
|
|
||||||
import javax.annotation.processing.ProcessingEnvironment;
|
import javax.annotation.processing.ProcessingEnvironment;
|
||||||
|
@ -210,35 +213,59 @@ public class ASTUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the class name and maps it to the correct format.
|
* Gets the {@link ClassData} corresponding to the given fully-qualified name,
|
||||||
* @param name the fully qualified name of the class to convert
|
* or creates a false one with the same, non-obfuscated name twice.
|
||||||
* @param options the {@link ProcessorOptions} to be used
|
* @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
|
* @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 {
|
try {
|
||||||
return options.mapper == null ? name : options.mapper.obfuscateClass(name).replace('/', '.');
|
name = name.replace('.', '/'); //just in case
|
||||||
} catch(MappingNotFoundException e) {
|
if(mapper != null)
|
||||||
return name;
|
return mapper.getClassData(name);
|
||||||
}
|
} catch(MappingNotFoundException ignored) {}
|
||||||
|
return new ClassData(name, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the member name and maps it to the correct format.
|
* Gets the {@link MethodData} corresponding to the method matching the given
|
||||||
* @param parentFQN the unobfuscated FQN of the parent class
|
* name, parent and descriptor, or creates a dummy one with fake data if no
|
||||||
* @param memberName the name of the member
|
* valid mapping is found.
|
||||||
* @param methodDescriptor the descriptor of the method, may be null
|
* @param parent the internal name of the parent class
|
||||||
* @param mapper the {@link ObfuscationMapper} to use, may be null
|
* @param name the name of the member
|
||||||
* @return the internal class name
|
* @param descriptor the descriptor of the method
|
||||||
* @since 0.3.0
|
* @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 {
|
try {
|
||||||
return mapper == null ? memberName : mapper.obfuscateMember(parentFQN, memberName, methodDescriptor);
|
name = name.replace('.', '/'); //just in case
|
||||||
} catch(MappingNotFoundException e) {
|
if(mapper != null)
|
||||||
return memberName;
|
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,
|
ClassContainer parent, String name, String descr,
|
||||||
boolean strict, boolean field, ProcessingEnvironment env) {
|
boolean strict, boolean field, ProcessingEnvironment env) {
|
||||||
if(parent.elem == null)
|
if(parent.elem == null)
|
||||||
throw new TargetNotFoundException("parent class", parent.fqn);
|
throw new TargetNotFoundException("parent class", parent.data.name);
|
||||||
//try to find by name
|
//try to find by name
|
||||||
List<Element> candidates = parent.elem.getEnclosedElements()
|
List<Element> candidates = parent.elem.getEnclosedElements()
|
||||||
.stream()
|
.stream()
|
||||||
|
@ -266,36 +293,37 @@ public class ASTUtils {
|
||||||
.filter(e -> e.getSimpleName().contentEquals(name))
|
.filter(e -> e.getSimpleName().contentEquals(name))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
if(candidates.size() == 0)
|
if(candidates.isEmpty())
|
||||||
throw new TargetNotFoundException(field ? "field" : "method", name, parent.fqn);
|
throw new TargetNotFoundException(field ? "field" : "method", name, parent.data.name);
|
||||||
|
|
||||||
if(candidates.size() == 1 && (!strict || descr == null))
|
if(candidates.size() == 1 && (!strict || descr == null))
|
||||||
return candidates.get(0);
|
return candidates.get(0);
|
||||||
|
|
||||||
if(descr == null) {
|
if(descr == null) {
|
||||||
throw new AmbiguousDefinitionException(
|
throw new AmbiguousDefinitionException(String.format(
|
||||||
String.format("Found %d members named %s in class %s!", candidates.size(), name, parent.fqn)
|
"Found %d members named %s in class %s!", candidates.size(), name, parent.data.name));
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
if(field) {
|
if(field) {
|
||||||
//fields can verify the signature for extra safety
|
//fields can verify the signature for extra safety
|
||||||
//but there can only be 1 field with a given name
|
//but there can only be 1 field with a given name
|
||||||
if(!descriptorFromType(candidates.get(0).asType(), env).equals(descr))
|
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 {
|
} else {
|
||||||
candidates = candidates.stream()
|
candidates = candidates.stream()
|
||||||
.map(e -> (ExecutableElement) e)
|
.map(e -> (ExecutableElement) e)
|
||||||
.filter(strict
|
.filter(strict
|
||||||
? c -> descr.equals(descriptorFromExecutableElement(c, env))
|
? 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());
|
).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
if(candidates.size() == 0)
|
if(candidates.isEmpty())
|
||||||
throw new TargetNotFoundException("method", String.format("%s %s", name, descr), parent.fqn);
|
throw new TargetNotFoundException("method", String.format(
|
||||||
|
"%s %s", name, descr), parent.data.name);
|
||||||
if(candidates.size() > 1)
|
if(candidates.size() > 1)
|
||||||
throw new AmbiguousDefinitionException(
|
throw new AmbiguousDefinitionException(String.format(
|
||||||
String.format("Found %d methods named %s in class %s!", candidates.size(), name, parent.fqn)
|
"Found %d methods named %s in class %s!", candidates.size(), name, parent.data.name));
|
||||||
);
|
|
||||||
return candidates.get(0);
|
return candidates.get(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,12 +1,13 @@
|
||||||
package ftbsc.lll.processor.tools;
|
package ftbsc.lll.processor.utils;
|
||||||
|
|
||||||
import com.squareup.javapoet.*;
|
import com.squareup.javapoet.*;
|
||||||
|
import ftbsc.lll.processor.ProcessorOptions;
|
||||||
import ftbsc.lll.processor.annotations.Find;
|
import ftbsc.lll.processor.annotations.Find;
|
||||||
import ftbsc.lll.processor.annotations.Target;
|
import ftbsc.lll.processor.annotations.Target;
|
||||||
import ftbsc.lll.processor.tools.containers.ClassContainer;
|
import ftbsc.lll.processor.containers.ClassContainer;
|
||||||
import ftbsc.lll.processor.tools.containers.FieldContainer;
|
import ftbsc.lll.processor.containers.FieldContainer;
|
||||||
import ftbsc.lll.processor.tools.containers.InjectorInfo;
|
import ftbsc.lll.processor.containers.InjectorInfo;
|
||||||
import ftbsc.lll.processor.tools.containers.MethodContainer;
|
import ftbsc.lll.processor.containers.MethodContainer;
|
||||||
import ftbsc.lll.proxies.ProxyType;
|
import ftbsc.lll.proxies.ProxyType;
|
||||||
import ftbsc.lll.proxies.impl.FieldProxy;
|
import ftbsc.lll.proxies.impl.FieldProxy;
|
||||||
import ftbsc.lll.proxies.impl.MethodProxy;
|
import ftbsc.lll.proxies.impl.MethodProxy;
|
||||||
|
@ -15,8 +16,8 @@ import javax.annotation.processing.ProcessingEnvironment;
|
||||||
import javax.lang.model.element.*;
|
import javax.lang.model.element.*;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
|
||||||
import static ftbsc.lll.processor.tools.ASTUtils.getProxyType;
|
import static ftbsc.lll.processor.utils.ASTUtils.getProxyType;
|
||||||
import static ftbsc.lll.processor.tools.ASTUtils.mapModifiers;
|
import static ftbsc.lll.processor.utils.ASTUtils.mapModifiers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collection of static utils that rely on JavaPoet to function.
|
* Collection of static utils that rely on JavaPoet to function.
|
||||||
|
@ -65,13 +66,13 @@ public class JavaPoetUtils {
|
||||||
if(isMethod) {
|
if(isMethod) {
|
||||||
MethodContainer mc = MethodContainer.from(stub, t, f, options);
|
MethodContainer mc = MethodContainer.from(stub, t, f, options);
|
||||||
descriptorObf = mc.descriptorObf;
|
descriptorObf = mc.descriptorObf;
|
||||||
nameObf = mc.nameObf;
|
nameObf = mc.data.nameMapped;
|
||||||
parent = mc.parent;
|
parent = mc.parent;
|
||||||
target = mc.elem;
|
target = mc.elem;
|
||||||
} else {
|
} else {
|
||||||
FieldContainer fc = FieldContainer.from(var, options);
|
FieldContainer fc = FieldContainer.from(var, options);
|
||||||
descriptorObf = fc.descriptorObf;
|
descriptorObf = fc.descriptorObf;
|
||||||
nameObf = fc.nameObf;
|
nameObf = fc.data.nameMapped;
|
||||||
parent = fc.parent;
|
parent = fc.parent;
|
||||||
target = fc.elem;
|
target = fc.elem;
|
||||||
}
|
}
|
||||||
|
@ -88,7 +89,7 @@ public class JavaPoetUtils {
|
||||||
con.addStatement(
|
con.addStatement(
|
||||||
"$L.setParent($S, $L)",
|
"$L.setParent($S, $L)",
|
||||||
builderName,
|
builderName,
|
||||||
parent.fqnObf,
|
parent.data.nameMapped.replace('/', '.'),
|
||||||
parent.elem == null ? 0 : mapModifiers(parent.elem.getModifiers())
|
parent.elem == null ? 0 : mapModifiers(parent.elem.getModifiers())
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in a new issue