chore: implemented matching by name for finders, added OrphanExceptions to prevent ungraceful crashes in generated code

This commit is contained in:
zaaarf 2023-03-25 21:29:28 +01:00
parent c688b55fc3
commit d2fe55db7a
No known key found for this signature in database
GPG key ID: AD8563472FD43386
7 changed files with 55 additions and 22 deletions

View file

@ -1,17 +1,16 @@
package ftbsc.lll.exceptions; package ftbsc.lll.exceptions;
import ftbsc.lll.processor.annotations.Find; import ftbsc.lll.processor.annotations.Find;
import ftbsc.lll.proxies.impl.FieldProxy;
import ftbsc.lll.proxies.impl.MethodProxy;
/** /**
* Thrown when a method is annotated with {@link Find} but does not * Thrown when a method is annotated with {@link Find} but does not
* return a {@link MethodProxy} or a {@link FieldProxy} * return a known instance of {@link ftbsc.lll.proxies.AbstractProxy}.
* @since 0.5.0
*/ */
public class NotAProxyException extends RuntimeException { public class NotAProxyException extends RuntimeException {
/** /**
* Constructs a exception for the specified method. * Constructs an exception for the specified method.
* @param parent the FQN of the class containing the method * @param parent the FQN of the class containing the method
* @param method the name of the method wrongly annotated * @param method the name of the method wrongly annotated
*/ */

View file

@ -0,0 +1,25 @@
package ftbsc.lll.exceptions;
import javax.lang.model.element.Element;
import javax.lang.model.element.QualifiedNameable;
/**
* Thrown when an annotated element that needs to be paired with
* another does not match with any.
* @since 0.5.0
*/
public class OrphanElementException extends RuntimeException {
/**
* Constructs an exception for the specified method.
* @param element the orphan element
*/
public OrphanElementException(Element element) {
super(
String.format(
"Could not find a valid target for element %s.%s!",
((QualifiedNameable) element.getEnclosingElement()).getQualifiedName().toString(),
element.getSimpleName().toString()
)
);
}
}

View file

@ -4,6 +4,7 @@ import com.squareup.javapoet.*;
import ftbsc.lll.IInjector; import ftbsc.lll.IInjector;
import ftbsc.lll.exceptions.AmbiguousDefinitionException; import ftbsc.lll.exceptions.AmbiguousDefinitionException;
import ftbsc.lll.exceptions.InvalidResourceException; import ftbsc.lll.exceptions.InvalidResourceException;
import ftbsc.lll.exceptions.OrphanElementException;
import ftbsc.lll.processor.annotations.Find; import ftbsc.lll.processor.annotations.Find;
import ftbsc.lll.processor.annotations.Injector; import ftbsc.lll.processor.annotations.Injector;
import ftbsc.lll.processor.annotations.Patch; import ftbsc.lll.processor.annotations.Patch;
@ -159,7 +160,7 @@ public class LilleroProcessor extends AbstractProcessor {
&& processingEnv.getTypeUtils().isSameType(params.get(1), methodNodeType); && processingEnv.getTypeUtils().isSameType(params.get(1), methodNodeType);
})) return true; })) return true;
else { else {
processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, //TODO orphan targets processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING,
String.format("Missing valid @Injector method in @Patch class %s, skipping.", elem)); String.format("Missing valid @Injector method in @Patch class %s, skipping.", elem));
return false; return false;
} }
@ -224,6 +225,10 @@ public class LilleroProcessor extends AbstractProcessor {
//this will contain the classes to generate: the key is the class name //this will contain the classes to generate: the key is the class name
HashMap<String, InjectorInfo> toGenerate = new HashMap<>(); HashMap<String, InjectorInfo> toGenerate = new HashMap<>();
//these are needed for orphan checks
HashSet<ExecutableElement> matchedInjectors = new HashSet<>();
HashSet<VariableElement> matchedMethodFinders = new HashSet<>();
for(ExecutableElement tg : targets) { for(ExecutableElement tg : targets) {
Target[] mtgAnn = tg.getAnnotationsByType(Target.class); Target[] mtgAnn = tg.getAnnotationsByType(Target.class);
int iterationNumber = 1; int iterationNumber = 1;
@ -248,15 +253,19 @@ public class LilleroProcessor extends AbstractProcessor {
finderCandidates = new ArrayList<>(); //no candidates finderCandidates = new ArrayList<>(); //no candidates
injectorCandidates = new ArrayList<>(); injectorCandidates = new ArrayList<>();
injectorCandidates.add(injectors.get(0)); injectorCandidates.add(injectors.get(0));
} else { //todo match finders based on same name } else {
//case 3: try to match by injectTargetName //case 3: try to match by injectTargetName or same name for finers
finderCandidates = new ArrayList<>(); //no candidates
String inferredName = "inject" + tg.getSimpleName(); String inferredName = "inject" + tg.getSimpleName();
injectorCandidates = injectorCandidates =
injectorCandidates injectorCandidates
.stream() .stream()
.filter(t -> t.getSimpleName().toString().equalsIgnoreCase(inferredName)) .filter(t -> t.getSimpleName().toString().equalsIgnoreCase(inferredName))
.collect(Collectors.toList()); .collect(Collectors.toList());
finderCandidates =
finderCandidates
.stream()
.filter(t -> t.getSimpleName().contentEquals(tg.getSimpleName()))
.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
@ -278,16 +287,20 @@ public class LilleroProcessor extends AbstractProcessor {
else { else {
if(injectorCandidates.size() == 1) { if(injectorCandidates.size() == 1) {
//matched an injector! //matched an injector!
ExecutableElement injector = injectorCandidates.get(0);
matchedInjectors.add(injector);
toGenerate.put( toGenerate.put(
String.format("%sInjector%d", cl.getSimpleName(), iterationNumber), String.format("%sInjector%d", cl.getSimpleName(), iterationNumber),
new InjectorInfo(injectorCandidates.get(0), tg) new InjectorInfo(injector, tg)
); );
iterationNumber++; //increment is only used by injectors iterationNumber++; //increment is only used by injectors
} else { } else {
//matched a finder! //matched a finder!
VariableElement finder = finderCandidates.get(0);
matchedMethodFinders.add(finder);
appendMemberFinderDefinition( appendMemberFinderDefinition(
targetClass, targetClass,
finderCandidates.get(0), finder,
tg, tg,
constructorBuilder, constructorBuilder,
this.processingEnv, this.processingEnv,
@ -298,6 +311,14 @@ public class LilleroProcessor extends AbstractProcessor {
} }
} }
//find orphans, throw exception if any are found
for(ExecutableElement e : injectors)
if(!matchedInjectors.contains(e))
throw new OrphanElementException(e);
for(VariableElement e : methodFinders)
if(!matchedMethodFinders.contains(e))
throw new OrphanElementException(e);
//iterate over the map and generate the classes //iterate over the map and generate the classes
for(String injName : toGenerate.keySet()) { for(String injName : toGenerate.keySet()) {
String targetMethodDescriptor = descriptorFromExecutableElement(toGenerate.get(injName).target); String targetMethodDescriptor = descriptorFromExecutableElement(toGenerate.get(injName).target);

View file

@ -1,7 +1,6 @@
package ftbsc.lll.processor.annotations; package ftbsc.lll.processor.annotations;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;

View file

@ -1,7 +1,5 @@
package ftbsc.lll.processor.annotations; package ftbsc.lll.processor.annotations;
import ftbsc.lll.proxies.impl.TypeProxy;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;

View file

@ -14,12 +14,7 @@ import ftbsc.lll.proxies.ProxyType;
import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.*; import javax.lang.model.element.*;
import javax.lang.model.type.MirroredTypeException; import javax.lang.model.type.MirroredTypeException;
import javax.lang.model.type.MirroredTypesException;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.function.Function; import java.util.function.Function;

View file

@ -19,12 +19,8 @@ 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 javax.tools.Diagnostic; import javax.tools.Diagnostic;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import static ftbsc.lll.processor.tools.ASTUtils.*; import static ftbsc.lll.processor.tools.ASTUtils.*;