From d585e9397f7f5684562b1db16f9ab3ce1bb0519e Mon Sep 17 00:00:00 2001 From: DarkWeird Date: Wed, 9 Jun 2021 11:44:54 +0300 Subject: [PATCH] feature(gradle-test): provide ablity for indexes provides by third party lib. --- .../processing/ClassIndexProcessor.java | 49 ++++++++++++++++++- .../context/annotation/BindAnnotationFor.java | 18 +++++++ 2 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 gestalt-inject/src/main/java/org/terasology/context/annotation/BindAnnotationFor.java diff --git a/gestalt-inject-java/src/main/java/org/terasology/gestalt/annotation/processing/ClassIndexProcessor.java b/gestalt-inject-java/src/main/java/org/terasology/gestalt/annotation/processing/ClassIndexProcessor.java index 3a4e4f31..ca7e4648 100644 --- a/gestalt-inject-java/src/main/java/org/terasology/gestalt/annotation/processing/ClassIndexProcessor.java +++ b/gestalt-inject-java/src/main/java/org/terasology/gestalt/annotation/processing/ClassIndexProcessor.java @@ -1,6 +1,9 @@ package org.terasology.gestalt.annotation.processing; +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; import com.google.common.collect.Queues; +import org.terasology.context.annotation.BindAnnotationFor; import org.terasology.context.annotation.Index; import org.terasology.context.annotation.IndexInherited; @@ -8,6 +11,7 @@ import javax.annotation.processing.Filer; import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.PackageElement; @@ -19,8 +23,11 @@ import javax.tools.StandardLocation; import java.io.IOException; import java.io.Writer; +import java.lang.annotation.Annotation; import java.util.Arrays; import java.util.Collections; +import java.util.Map; +import java.util.Optional; import java.util.Queue; import java.util.Set; @@ -31,6 +38,8 @@ public class ClassIndexProcessor extends AbstractProcessor { private SubtypesTypeWriter subtypesTypeWriter; private ElementUtility elementUtility; + private Multimap> boundAnnotations; + @Override public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); @@ -38,10 +47,25 @@ public synchronized void init(ProcessingEnvironment processingEnv) { annotationTypeWriter = new AnnotationTypeWriter(filer); subtypesTypeWriter = new SubtypesTypeWriter(filer); elementUtility = new ElementUtility(processingEnv.getElementUtils(), processingEnv.getTypeUtils()); + boundAnnotations = HashMultimap.create(); } @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { + for (TypeElement annotation : annotations) { + if (annotation.asType().toString().equals(BindAnnotationFor.class.getName())) { + for (Element type : roundEnv.getElementsAnnotatedWith(annotation)) { + TypeMirror foreighElement = getBindAnnotationFor(type); + if (elementUtility.hasStereotype(type, Collections.singletonList(IndexInherited.class.getName()))) { + boundAnnotations.put(foreighElement, IndexInherited.class); + } + if (elementUtility.hasStereotype(type, Collections.singletonList(Index.class.getName()))) { + boundAnnotations.put(foreighElement, Index.class); + } + } + } + } + for (TypeElement annotation : annotations) { // Annotation Index processAnnotationIndex(roundEnv, annotation); @@ -71,7 +95,7 @@ private void processSubtypeIndexInReverseWay(Element type) { TypeMirror candidate = supers.poll(); if (candidate.getKind() != TypeKind.NONE) { if (elementUtility.hasStereotype(elementUtility.getTypes().asElement(candidate), - Collections.singletonList(IndexInherited.class.getName()))) { + Collections.singletonList(IndexInherited.class.getName())) || boundAnnotations.containsEntry(candidate, IndexInherited.class)) { TypeElement candidateElement = (TypeElement) elementUtility.getTypes().asElement(elementUtility.getTypes().erasure(candidate)); TypeElement erasedType = (TypeElement) elementUtility.getTypes().asElement(elementUtility.getTypes().erasure(type.asType())); subtypesTypeWriter.writeSubType(elementUtility.getElements().getBinaryName(candidateElement).toString(), @@ -94,7 +118,7 @@ private void processSubtypeIndexByDirectMarked(RoundEnvironment roundEnv, TypeEl TypeMirror candidate = supers.poll(); if (candidate.getKind() != TypeKind.NONE) { if (elementUtility.hasStereotype(elementUtility.getTypes().asElement(candidate), - Collections.singletonList(IndexInherited.class.getName()))) + Collections.singletonList(IndexInherited.class.getName())) || boundAnnotations.containsEntry(candidate, IndexInherited.class)) subtypesTypeWriter.writeSubType(elementUtility.getTypes().erasure(candidate).toString(), elementUtility.getTypes().erasure(type.asType()).toString()); supers.addAll(elementUtility.getTypes().directSupertypes(candidate)); } @@ -117,6 +141,27 @@ private void processAnnotationIndex(RoundEnvironment roundEnv, TypeElement annot } } + private TypeMirror getBindAnnotationFor(Element element) { + return (TypeMirror) getAnnotationValue(element, BindAnnotationFor.class, "value").orElse(null); + } + + private Optional getAnnotationValue(Element element, Class annotation, String fieldName) { + return element + .getAnnotationMirrors() + .stream() + .filter(am -> am.getAnnotationType().toString().equals(annotation.getName())) + .map(am -> am.getElementValues() + .entrySet() + .stream() + .filter(kv -> kv.getKey().getSimpleName().toString().equals(fieldName)) + .map(Map.Entry::getValue) + .findFirst()) + .filter(Optional::isPresent) + .map(Optional::get) + .map(AnnotationValue::getValue) + .findFirst(); + } + private void writeIndexes() { try { annotationTypeWriter.finish(); diff --git a/gestalt-inject/src/main/java/org/terasology/context/annotation/BindAnnotationFor.java b/gestalt-inject/src/main/java/org/terasology/context/annotation/BindAnnotationFor.java new file mode 100644 index 00000000..e88c62ff --- /dev/null +++ b/gestalt-inject/src/main/java/org/terasology/context/annotation/BindAnnotationFor.java @@ -0,0 +1,18 @@ +package org.terasology.context.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Provides binding gestalt-di's annotation for foreigh classes notated at `value`. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +@Documented +public @interface BindAnnotationFor { + Class value(); +} +