Skip to content

Commit e29ab99

Browse files
committed
JoobyProcessorRoundEnvironment
Implemented JoobyProcessorRoundEnvironment class with support for inherited annotations. Based on jdk source code.
1 parent bf4cafb commit e29ab99

File tree

2 files changed

+100
-1
lines changed

2 files changed

+100
-1
lines changed

modules/jooby-apt/src/main/java/io/jooby/apt/JoobyProcessor.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,9 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
6767
* Do MVC handler: per each mvc method we create a Route.Handler.
6868
*/
6969
List<HandlerCompiler> result = new ArrayList<>();
70+
JoobyProcessorRoundEnvironment joobyRoundEnv = new JoobyProcessorRoundEnvironment(roundEnv, processingEnvironment);
7071
for (TypeElement httpMethod : annotations) {
71-
Set<? extends Element> methods = roundEnv.getElementsAnnotatedWith(httpMethod);
72+
Set<? extends Element> methods = joobyRoundEnv.getElementsAnnotatedWith(httpMethod);
7273
for (Element e : methods) {
7374
ExecutableElement method = (ExecutableElement) e;
7475
List<String> paths = path(httpMethod, method);
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package io.jooby.apt;
2+
3+
import com.sun.tools.javac.code.Symbol;
4+
5+
import javax.annotation.processing.ProcessingEnvironment;
6+
import javax.annotation.processing.RoundEnvironment;
7+
import javax.lang.model.element.*;
8+
import javax.lang.model.type.DeclaredType;
9+
import javax.lang.model.type.TypeKind;
10+
import javax.lang.model.type.TypeMirror;
11+
import javax.lang.model.util.ElementScanner8;
12+
import javax.lang.model.util.Elements;
13+
import javax.lang.model.util.Types;
14+
import java.lang.reflect.Field;
15+
import java.lang.reflect.Method;
16+
import java.util.*;
17+
18+
public class JoobyProcessorRoundEnvironment {
19+
20+
private final Elements eltUtils;
21+
private static Types typeUtils;
22+
private final Set<? extends Element> rootElements;
23+
24+
JoobyProcessorRoundEnvironment(RoundEnvironment roundEnv, ProcessingEnvironment processingEnv) {
25+
this.rootElements = roundEnv.getRootElements();
26+
this.eltUtils = processingEnv.getElementUtils();
27+
this.typeUtils = processingEnv.getTypeUtils();
28+
}
29+
30+
public Set<? extends Element> getElementsAnnotatedWith(TypeElement a) {
31+
32+
Set<Element> result = Collections.emptySet();
33+
ElementScanner8<Set<Element>, TypeElement> scanner = new AnnotationSetScanner(result);
34+
35+
for (Element element : rootElements)
36+
result = scanner.scan(element, a);
37+
38+
return result;
39+
}
40+
41+
// Could be written as a local class inside getElementsAnnotatedWith
42+
private class AnnotationSetScanner extends
43+
ElementScanningIncludingTypeParameters<Set<Element>, TypeElement> {
44+
// Insertion-order preserving set
45+
private Set<Element> annotatedElements = new LinkedHashSet<>();
46+
47+
AnnotationSetScanner(Set<Element> defaultSet) {
48+
super(defaultSet);
49+
}
50+
51+
@Override
52+
public Set<Element> scan(Element e, TypeElement annotation) {
53+
//System.out.println("\t\t" + e);
54+
for (AnnotationMirror annotMirror : eltUtils.getAllAnnotationMirrors(e)) {
55+
if (annotation.equals(mirrorAsElement(annotMirror))) {
56+
annotatedElements.add(e);
57+
break;
58+
}
59+
}
60+
e.accept(this, annotation);
61+
return annotatedElements;
62+
}
63+
64+
}
65+
66+
private static abstract class ElementScanningIncludingTypeParameters<R, P>
67+
extends ElementScanner8<R, P> {
68+
69+
protected ElementScanningIncludingTypeParameters(R defaultValue) {
70+
super(defaultValue);
71+
}
72+
73+
@Override
74+
public R visitType(TypeElement e, P p) {
75+
// Type parameters are not considered to be enclosed by a type
76+
if (e.getSuperclass().getKind() == TypeKind.DECLARED) {
77+
//System.out.println(e.getSimpleName() + " extends " + e.getSuperclass());
78+
TypeElement superElement = (TypeElement) ((DeclaredType) e.getSuperclass()).asElement();
79+
List<Element> clonedElements = new ArrayList<>();
80+
for(Element enclosedElement : superElement.getEnclosedElements()) {
81+
if (enclosedElement.getKind() == ElementKind.METHOD && enclosedElement.getAnnotationMirrors().size() > 0) {
82+
Symbol.MethodSymbol methodSymbol = ((Symbol.MethodSymbol)enclosedElement).clone((Symbol.ClassSymbol)e);
83+
methodSymbol.appendAttributes( ((Symbol.MethodSymbol)enclosedElement).getAnnotationMirrors() );
84+
//System.out.println("\t\t" + m.getEnclosingElement() + "::" + m + " #" + m.getAnnotationMirrors().size());
85+
clonedElements.add(methodSymbol);
86+
}
87+
}
88+
scan(clonedElements, p);
89+
}
90+
return super.visitType(e, p);
91+
}
92+
}
93+
94+
private Element mirrorAsElement(AnnotationMirror annotationMirror) {
95+
return annotationMirror.getAnnotationType().asElement();
96+
}
97+
98+
}

0 commit comments

Comments
 (0)