feat: implemented srg conversion (maybe)

This commit is contained in:
zaaarf 2023-02-26 18:56:20 +01:00
parent aab3d58afb
commit eca2d1f312
No known key found for this signature in database
GPG key ID: 82240E075E31FA4C

View file

@ -6,10 +6,6 @@ import ftbsc.lll.processor.annotations.Injector;
import ftbsc.lll.processor.annotations.Patch; import ftbsc.lll.processor.annotations.Patch;
import ftbsc.lll.tools.DescriptorBuilder; import ftbsc.lll.tools.DescriptorBuilder;
import ftbsc.lll.tools.SrgMapper; import ftbsc.lll.tools.SrgMapper;
import org.gradle.internal.impldep.org.objectweb.asm.Type;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
import javax.annotation.processing.*; import javax.annotation.processing.*;
import javax.lang.model.SourceVersion; import javax.lang.model.SourceVersion;
import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.ExecutableElement;
@ -70,7 +66,7 @@ public class LilleroProcessor extends AbstractProcessor {
/** /**
* This checks whether a given class contains the requirements to be parsed into a Lillero injector. * This checks whether a given class contains the requirements to be parsed into a Lillero injector.
* It must have at least one method annotated with {@link Target}, and one method annotated with {@link Injector} * It must have at least one method annotated with {@link Target}, and one method annotated with {@link Injector}
* that must be public, static and take in a {@link ClassNode} and a {@link MethodNode}. * that must be public, static and take in a ClassNode and a MethodNode from the ObjectWeb library.
* @param elem the element to check. * @param elem the element to check.
* @return whether it can be converted into a valid {@link IInjector}. * @return whether it can be converted into a valid {@link IInjector}.
*/ */
@ -89,7 +85,7 @@ public class LilleroProcessor extends AbstractProcessor {
}); });
} }
private MethodSpec findAnnotatedMethod(TypeElement cl, Class<? extends Annotation> ann) { private static MethodSpec findAnnotatedMethod(TypeElement cl, Class<? extends Annotation> ann) {
return MethodSpec.overriding( return MethodSpec.overriding(
(ExecutableElement) cl.getEnclosedElements() (ExecutableElement) cl.getEnclosedElements()
.stream() .stream()
@ -99,21 +95,49 @@ public class LilleroProcessor extends AbstractProcessor {
).build(); ).build();
} }
private String getClassOrString(TypeName n) { //jank but fuck you private static String getClassOrString(TypeName n) { //jank but fuck you
return n.isPrimitive() ? n + ".class" : "\"" + n + "\""; return n.isPrimitive() ? n + ".class" : "\"" + n + "\"";
} }
private String generateDescriptorBuilderString(MethodSpec m) { private static String descriptorFromType(TypeName type) {
StringBuilder sb = new StringBuilder(); StringBuilder desc = new StringBuilder();
sb.append("new $T().setReturnType("); //add array brackets
sb.append(getClassOrString(m.returnType)).append(")"); while(type instanceof ArrayTypeName) {
m.parameters.forEach(p -> sb.append(".addParameter(").append(getClassOrString(p.type)).append(")")); desc.append("[");
sb.append(".build();"); type = ((ArrayTypeName) type).componentType;
return sb.toString(); }
if(type instanceof ClassName) { //todo maybe?
ClassName var = (ClassName) type;
desc.append(DescriptorBuilder.nameToDescriptor(var.canonicalName(), 0));
desc.append(";");
} else {
if(TypeName.BOOLEAN.equals(type))
desc.append("Z");
else if(TypeName.CHAR.equals(type))
desc.append("C");
else if(TypeName.BYTE.equals(type))
desc.append("B");
else if(TypeName.SHORT.equals(type))
desc.append("S");
else if(TypeName.INT.equals(type))
desc.append("I");
else if(TypeName.FLOAT.equals(type))
desc.append("F");
else if(TypeName.LONG.equals(type))
desc.append("J");
else if(TypeName.DOUBLE.equals(type))
desc.append("D");
}
return desc.toString();
} }
private String getSrgMethodName(MethodSpec m) { public static String descriptorFromMethodSpec(MethodSpec m) {
return m.name; //TODO; StringBuilder methodSignature = new StringBuilder();
methodSignature.append("(");
m.parameters.forEach(p -> methodSignature.append(descriptorFromType(p.type)));
methodSignature.append(")");
methodSignature.append(descriptorFromType(m.returnType));
return methodSignature.toString();
} }
private void generateInjector(TypeElement cl) { private void generateInjector(TypeElement cl) {
@ -144,26 +168,29 @@ public class LilleroProcessor extends AbstractProcessor {
MethodSpec targetClass = MethodSpec.methodBuilder("targetClass") MethodSpec targetClass = MethodSpec.methodBuilder("targetClass")
.addModifiers(Modifier.PUBLIC) .addModifiers(Modifier.PUBLIC)
.returns(String.class) .returns(String.class)
.addStatement("return $S", mapper.getMcpClass(Type.getInternalName(ann.value()))) .addStatement("return $S", mapper.getMcpClass(ClassName.get(ann.value()).canonicalName().replace('.', '/')))
.build(); .build();
String targetMethodDescriptor = descriptorFromMethodSpec(targetMethod);
MethodSpec methodName = MethodSpec.methodBuilder("methodName") MethodSpec methodName = MethodSpec.methodBuilder("methodName")
.addModifiers(Modifier.PUBLIC) .addModifiers(Modifier.PUBLIC)
.returns(String.class) .returns(String.class)
.addStatement("return $S", getSrgMethodName(targetMethod)) .addStatement("return $S", mapper.getSrgMember(
.build(); ann.value().getName(), targetMethod.name + " " + targetMethodDescriptor)
).build();
MethodSpec methodDesc = MethodSpec.methodBuilder("methodDesc") MethodSpec methodDesc = MethodSpec.methodBuilder("methodDesc")
.addModifiers(Modifier.PUBLIC) .addModifiers(Modifier.PUBLIC)
.returns(String.class) .returns(String.class)
.addCode(generateDescriptorBuilderString(targetMethod), DescriptorBuilder.class) .addCode("return $S", targetMethodDescriptor)
.build(); .build();
MethodSpec inject = MethodSpec.methodBuilder("inject") MethodSpec inject = MethodSpec.methodBuilder("inject")
.addModifiers(Modifier.PUBLIC) .addModifiers(Modifier.PUBLIC)
.returns(void.class) .returns(void.class)
.addParameter(ParameterSpec.builder(ClassNode.class, "clazz").build()) .addParameter(ParameterSpec.builder((TypeName) processingEnv.getElementUtils().getTypeElement("org.objectweb.asm.tree.ClassNode").asType(), "clazz").build())
.addParameter(ParameterSpec.builder(MethodNode.class, "main").build()) .addParameter(ParameterSpec.builder((TypeName) processingEnv.getElementUtils().getTypeElement("org.objectweb.asm.tree.MethodNode").asType(), "main").build())
.addStatement("$S.$S(clazz, main)", className, injectorMethod.name) .addStatement("$S.$S(clazz, main)", className, injectorMethod.name)
.build(); .build();
@ -184,7 +211,7 @@ public class LilleroProcessor extends AbstractProcessor {
JavaFile javaFile = JavaFile.builder(packageName, injectorClass).build(); JavaFile javaFile = JavaFile.builder(packageName, injectorClass).build();
javaFile.writeTo(out); javaFile.writeTo(out);
out.close(); out.close();
} catch(IOException e) {} } catch(IOException e) {} //todo
} }
private void generateServiceProvider(Set<TypeElement> inj) { private void generateServiceProvider(Set<TypeElement> inj) {
@ -193,6 +220,6 @@ public class LilleroProcessor extends AbstractProcessor {
PrintWriter out = new PrintWriter(serviceProvider.openWriter()); PrintWriter out = new PrintWriter(serviceProvider.openWriter());
inj.forEach(i -> out.println(i.getQualifiedName() + "Injector")); inj.forEach(i -> out.println(i.getQualifiedName() + "Injector"));
out.close(); out.close();
} catch(IOException e) {} } catch(IOException e) {} //todo
} }
} }