package xapi.javac.dev.processor;
import com.sun.source.util.Trees;
import xapi.annotation.compile.MagicMethod;
import xapi.annotation.compile.Reference;
import xapi.javac.dev.api.JavacService;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author James X. Nelson (james@wetheinter.net)
* Created on 3/13/16.
*/
@SupportedAnnotationTypes({
"xapi.annotation.compile.MagicMethod"
})
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class MagicMethodAnnotationProcessor extends AbstractProcessor {
private Elements elements;
private Filer filer;
private Types types;
private Messager log;
private JavacService service;
private Trees trees;
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
elements = processingEnv.getElementUtils();
filer = processingEnv.getFiler();
log = processingEnv.getMessager();
types = processingEnv.getTypeUtils();
service = JavacService.instanceFor(processingEnv);
trees = Trees.instance(processingEnv);
}
@Override
public boolean process(
Set<? extends TypeElement> annotations, RoundEnvironment roundEnv
) {
annotations.forEach(annotation->roundEnv.getElementsAnnotatedWith(annotation).forEach(element->{
MagicMethod magicMethod = element.getAnnotation(MagicMethod.class);
final Reference generator = magicMethod.generator();
final TypeElement annoType = elements.getTypeElement(MagicMethod.class.getCanonicalName());
final TypeElement useName = elements.getTypeElement(Reference.UseTypeName.class.getCanonicalName());
final List<AnnotationMirror> results = element.getAnnotationMirrors()
.stream()
.filter(mirror -> {
final DeclaredType type = mirror.getAnnotationType();
if (annoType.equals(type)) {
final ExecutableElement reference = findMethod(element, "generator");
final AnnotationMirror value = (AnnotationMirror) mirror.getElementValues().get(reference).getValue();
final ExecutableElement stringType = findMethod(value.getAnnotationType().asElement(), "typeName");
final ExecutableElement classType = findMethod(value.getAnnotationType().asElement(), "type");
final Object classValue = value.getElementValues().get(classType).getValue();
String stringValue;
stringValue = String.valueOf(classValue);
if (useName.equals(classValue)) {
stringValue = (String) value.getElementValues().get(stringType).getValue();
} else {
}
return true;
}
return false;
})
.collect(Collectors.toList());
}));
if (roundEnv.processingOver()) {
}
return true;
}
private ExecutableElement findMethod(Element type, String methodName) {
final Optional<? extends Element> maybe = type.getEnclosedElements()
.stream()
.filter(exe -> exe instanceof ExecutableElement)
.filter(exe -> exe.getSimpleName().contentEquals(methodName))
.findFirst();
if (!maybe.isPresent()) {
throw new UnsupportedOperationException("Cannot find method " + methodName +" in type " + type);
}
return (ExecutableElement) maybe.get();
}
}