diff --git a/src/main/java/ftbsc/lll/exceptions/NotAProxyException.java b/src/main/java/ftbsc/lll/exceptions/NotAProxyException.java index 1ce3c0f..f3e40a7 100644 --- a/src/main/java/ftbsc/lll/exceptions/NotAProxyException.java +++ b/src/main/java/ftbsc/lll/exceptions/NotAProxyException.java @@ -1,17 +1,16 @@ package ftbsc.lll.exceptions; 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 - * 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 { /** - * 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 method the name of the method wrongly annotated */ diff --git a/src/main/java/ftbsc/lll/exceptions/OrphanElementException.java b/src/main/java/ftbsc/lll/exceptions/OrphanElementException.java new file mode 100644 index 0000000..17c1180 --- /dev/null +++ b/src/main/java/ftbsc/lll/exceptions/OrphanElementException.java @@ -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() + ) + ); + } +} diff --git a/src/main/java/ftbsc/lll/processor/LilleroProcessor.java b/src/main/java/ftbsc/lll/processor/LilleroProcessor.java index 0f5b656..39f680a 100644 --- a/src/main/java/ftbsc/lll/processor/LilleroProcessor.java +++ b/src/main/java/ftbsc/lll/processor/LilleroProcessor.java @@ -4,6 +4,7 @@ import com.squareup.javapoet.*; import ftbsc.lll.IInjector; import ftbsc.lll.exceptions.AmbiguousDefinitionException; import ftbsc.lll.exceptions.InvalidResourceException; +import ftbsc.lll.exceptions.OrphanElementException; import ftbsc.lll.processor.annotations.Find; import ftbsc.lll.processor.annotations.Injector; import ftbsc.lll.processor.annotations.Patch; @@ -159,7 +160,7 @@ public class LilleroProcessor extends AbstractProcessor { && processingEnv.getTypeUtils().isSameType(params.get(1), methodNodeType); })) return true; 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)); return false; } @@ -224,6 +225,10 @@ public class LilleroProcessor extends AbstractProcessor { //this will contain the classes to generate: the key is the class name HashMap toGenerate = new HashMap<>(); + //these are needed for orphan checks + HashSet matchedInjectors = new HashSet<>(); + HashSet matchedMethodFinders = new HashSet<>(); + for(ExecutableElement tg : targets) { Target[] mtgAnn = tg.getAnnotationsByType(Target.class); int iterationNumber = 1; @@ -248,15 +253,19 @@ public class LilleroProcessor extends AbstractProcessor { finderCandidates = new ArrayList<>(); //no candidates injectorCandidates = new ArrayList<>(); injectorCandidates.add(injectors.get(0)); - } else { //todo match finders based on same name - //case 3: try to match by injectTargetName - finderCandidates = new ArrayList<>(); //no candidates + } else { + //case 3: try to match by injectTargetName or same name for finers String inferredName = "inject" + tg.getSimpleName(); injectorCandidates = injectorCandidates .stream() .filter(t -> t.getSimpleName().toString().equalsIgnoreCase(inferredName)) .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 @@ -278,16 +287,20 @@ public class LilleroProcessor extends AbstractProcessor { else { if(injectorCandidates.size() == 1) { //matched an injector! + ExecutableElement injector = injectorCandidates.get(0); + matchedInjectors.add(injector); toGenerate.put( String.format("%sInjector%d", cl.getSimpleName(), iterationNumber), - new InjectorInfo(injectorCandidates.get(0), tg) + new InjectorInfo(injector, tg) ); iterationNumber++; //increment is only used by injectors } else { //matched a finder! + VariableElement finder = finderCandidates.get(0); + matchedMethodFinders.add(finder); appendMemberFinderDefinition( targetClass, - finderCandidates.get(0), + finder, tg, constructorBuilder, 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 for(String injName : toGenerate.keySet()) { String targetMethodDescriptor = descriptorFromExecutableElement(toGenerate.get(injName).target); diff --git a/src/main/java/ftbsc/lll/processor/annotations/Injector.java b/src/main/java/ftbsc/lll/processor/annotations/Injector.java index 8cebd24..d9d3b09 100644 --- a/src/main/java/ftbsc/lll/processor/annotations/Injector.java +++ b/src/main/java/ftbsc/lll/processor/annotations/Injector.java @@ -1,7 +1,6 @@ package ftbsc.lll.processor.annotations; import java.lang.annotation.ElementType; -import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/src/main/java/ftbsc/lll/processor/annotations/Patch.java b/src/main/java/ftbsc/lll/processor/annotations/Patch.java index bac3f6a..e0472da 100644 --- a/src/main/java/ftbsc/lll/processor/annotations/Patch.java +++ b/src/main/java/ftbsc/lll/processor/annotations/Patch.java @@ -1,7 +1,5 @@ package ftbsc.lll.processor.annotations; -import ftbsc.lll.proxies.impl.TypeProxy; - import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/src/main/java/ftbsc/lll/processor/tools/ASTUtils.java b/src/main/java/ftbsc/lll/processor/tools/ASTUtils.java index 7d3ef9f..2eeb450 100644 --- a/src/main/java/ftbsc/lll/processor/tools/ASTUtils.java +++ b/src/main/java/ftbsc/lll/processor/tools/ASTUtils.java @@ -14,12 +14,7 @@ import ftbsc.lll.proxies.ProxyType; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.*; 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.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.function.Function; diff --git a/src/main/java/ftbsc/lll/processor/tools/JavaPoetUtils.java b/src/main/java/ftbsc/lll/processor/tools/JavaPoetUtils.java index 4a103a6..5245116 100644 --- a/src/main/java/ftbsc/lll/processor/tools/JavaPoetUtils.java +++ b/src/main/java/ftbsc/lll/processor/tools/JavaPoetUtils.java @@ -19,12 +19,8 @@ import javax.lang.model.element.VariableElement; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; import javax.tools.Diagnostic; - import java.util.Collection; import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; import static ftbsc.lll.processor.tools.ASTUtils.*;