Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
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;

import javax.annotation.processing.AbstractProcessor;
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;
Expand All @@ -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;

Expand All @@ -31,17 +38,34 @@ public class ClassIndexProcessor extends AbstractProcessor {
private SubtypesTypeWriter subtypesTypeWriter;
private ElementUtility elementUtility;

private Multimap<TypeMirror, Class<? extends Annotation>> boundAnnotations;

@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
filer = processingEnv.getFiler();
annotationTypeWriter = new AnnotationTypeWriter(filer);
subtypesTypeWriter = new SubtypesTypeWriter(filer);
elementUtility = new ElementUtility(processingEnv.getElementUtils(), processingEnv.getTypeUtils());
boundAnnotations = HashMultimap.create();
}

@Override
public boolean process(Set<? extends TypeElement> 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);
Expand Down Expand Up @@ -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(),
Expand All @@ -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));
}
Expand All @@ -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<Object> 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();
Expand Down
Original file line number Diff line number Diff line change
@@ -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();
}

Loading