1 /*
2 * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
34 import com.sun.tools.javac.util.DefinedBy;
35 import com.sun.tools.javac.util.DefinedBy.Api;
36
37 /**
38 * Object providing state about a prior round of annotation processing.
39 *
40 * <p>The methods in this class do not take type annotations into account,
41 * as target types, not java elements.
42 *
43 * <p><b>This is NOT part of any supported API.
44 * If you write code that depends on this, you do so at your own risk.
45 * This code and its internal interfaces are subject to change or
46 * deletion without notice.</b>
47 */
48 public class JavacRoundEnvironment implements RoundEnvironment {
49 // Default equals and hashCode methods are okay.
50
51 private final boolean processingOver;
52 private final boolean errorRaised;
53 private final ProcessingEnvironment processingEnv;
54
55 // Caller must pass in an immutable set
56 private final Set<? extends Element> rootElements;
57
58 JavacRoundEnvironment(boolean processingOver,
59 boolean errorRaised,
60 Set<? extends Element> rootElements,
61 ProcessingEnvironment processingEnv) {
62 this.processingOver = processingOver;
63 this.errorRaised = errorRaised;
64 this.rootElements = rootElements;
65 this.processingEnv = processingEnv;
66 }
67
68 public String toString() {
69 return String.format("[errorRaised=%b, rootElements=%s, processingOver=%b]",
70 errorRaised,
71 rootElements,
72 processingOver);
73 }
74
75 @DefinedBy(Api.ANNOTATION_PROCESSING)
76 public boolean processingOver() {
77 return processingOver;
78 }
79
80 /**
81 * Returns {@code true} if an error was raised in the prior round
82 * of processing; returns {@code false} otherwise.
83 *
84 * @return {@code true} if an error was raised in the prior round
85 * of processing; returns {@code false} otherwise.
86 */
87 @DefinedBy(Api.ANNOTATION_PROCESSING)
88 public boolean errorRaised() {
89 return errorRaised;
90 }
91
92 /**
93 * Returns the type elements specified by the prior round.
94 *
95 * @return the types elements specified by the prior round, or an
96 * empty set if there were none
97 */
98 @DefinedBy(Api.ANNOTATION_PROCESSING)
99 public Set<? extends Element> getRootElements() {
100 return rootElements;
101 }
102
103 private static final String NOT_AN_ANNOTATION_TYPE =
104 "The argument does not represent an annotation type: ";
105
106 /**
107 * Returns the elements annotated with the given annotation type.
108 * Only type elements <i>included</i> in this round of annotation
109 * processing, or declarations of members, parameters, or type
110 * parameters declared within those, are returned. Included type
111 * elements are {@linkplain #getRootElements specified
112 * types} and any types nested within them.
113 *
114 * @param a annotation type being requested
115 * @return the elements annotated with the given annotation type,
116 * or an empty set if there are none
117 */
118 @DefinedBy(Api.ANNOTATION_PROCESSING)
119 public Set<? extends Element> getElementsAnnotatedWith(TypeElement a) {
120 Set<Element> result = Collections.emptySet();
121 if (a.getKind() != ElementKind.ANNOTATION_TYPE)
122 throw new IllegalArgumentException(NOT_AN_ANNOTATION_TYPE + a);
123
124 ElementScanner9<Set<Element>, TypeElement> scanner =
125 new AnnotationSetScanner(result);
126
127 for (Element element : rootElements)
128 result = scanner.scan(element, a);
129
130 return result;
131 }
132
133 // Could be written as a local class inside getElementsAnnotatedWith
134 private class AnnotationSetScanner extends
135 ElementScanner9<Set<Element>, TypeElement> {
136 // Insertion-order preserving set
137 Set<Element> annotatedElements = new LinkedHashSet<>();
138
139 AnnotationSetScanner(Set<Element> defaultSet) {
140 super(defaultSet);
141 }
142
143 @Override @DefinedBy(Api.LANGUAGE_MODEL)
144 public Set<Element> visitType(TypeElement e, TypeElement p) {
145 // Type parameters are not considered to be enclosed by a type
146 scan(e.getTypeParameters(), p);
147 return super.visitType(e, p);
148 }
149
150 @Override @DefinedBy(Api.LANGUAGE_MODEL)
151 public Set<Element> visitExecutable(ExecutableElement e, TypeElement p) {
152 // Type parameters are not considered to be enclosed by an executable
153 scan(e.getTypeParameters(), p);
154 return super.visitExecutable(e, p);
155 }
156
157 @Override @DefinedBy(Api.LANGUAGE_MODEL)
158 public Set<Element> scan(Element e, TypeElement p) {
159 java.util.List<? extends AnnotationMirror> annotationMirrors =
160 processingEnv.getElementUtils().getAllAnnotationMirrors(e);
161 for (AnnotationMirror annotationMirror : annotationMirrors) {
162 if (p.equals(annotationMirror.getAnnotationType().asElement()))
163 annotatedElements.add(e);
164 }
165 e.accept(this, p);
166 return annotatedElements;
167 }
168 }
169
170 /**
171 * {@inheritDoc}
172 */
173 @DefinedBy(Api.ANNOTATION_PROCESSING)
174 public Set<? extends Element> getElementsAnnotatedWith(Class<? extends Annotation> a) {
175 if (!a.isAnnotation())
176 throw new IllegalArgumentException(NOT_AN_ANNOTATION_TYPE + a);
177 String name = a.getCanonicalName();
178 if (name == null)
179 return Collections.emptySet();
180 else {
181 TypeElement annotationType = processingEnv.getElementUtils().getTypeElement(name);
182 if (annotationType == null)
183 return Collections.emptySet();
184 else
185 return getElementsAnnotatedWith(annotationType);
186 }
187 }
188 }
|
1 /*
2 * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
34 import com.sun.tools.javac.util.DefinedBy;
35 import com.sun.tools.javac.util.DefinedBy.Api;
36
37 /**
38 * Object providing state about a prior round of annotation processing.
39 *
40 * <p>The methods in this class do not take type annotations into account,
41 * as target types, not java elements.
42 *
43 * <p><b>This is NOT part of any supported API.
44 * If you write code that depends on this, you do so at your own risk.
45 * This code and its internal interfaces are subject to change or
46 * deletion without notice.</b>
47 */
48 public class JavacRoundEnvironment implements RoundEnvironment {
49 // Default equals and hashCode methods are okay.
50
51 private final boolean processingOver;
52 private final boolean errorRaised;
53 private final ProcessingEnvironment processingEnv;
54 private final Elements eltUtils;
55
56 // Caller must pass in an immutable set
57 private final Set<? extends Element> rootElements;
58
59 JavacRoundEnvironment(boolean processingOver,
60 boolean errorRaised,
61 Set<? extends Element> rootElements,
62 ProcessingEnvironment processingEnv) {
63 this.processingOver = processingOver;
64 this.errorRaised = errorRaised;
65 this.rootElements = rootElements;
66 this.processingEnv = processingEnv;
67 this.eltUtils = processingEnv.getElementUtils();
68 }
69
70 public String toString() {
71 return String.format("[errorRaised=%b, rootElements=%s, processingOver=%b]",
72 errorRaised,
73 rootElements,
74 processingOver);
75 }
76
77 @DefinedBy(Api.ANNOTATION_PROCESSING)
78 public boolean processingOver() {
79 return processingOver;
80 }
81
82 /**
83 * Returns {@code true} if an error was raised in the prior round
84 * of processing; returns {@code false} otherwise.
85 *
86 * @return {@code true} if an error was raised in the prior round
87 * of processing; returns {@code false} otherwise.
88 */
89 @DefinedBy(Api.ANNOTATION_PROCESSING)
90 public boolean errorRaised() {
91 return errorRaised;
92 }
93
94 /**
95 * Returns the type elements specified by the prior round.
96 *
97 * @return the types elements specified by the prior round, or an
98 * empty set if there were none
99 */
100 @DefinedBy(Api.ANNOTATION_PROCESSING)
101 public Set<? extends Element> getRootElements() {
102 return rootElements;
103 }
104
105 /**
106 * Returns the elements annotated with the given annotation type.
107 * Only type elements <i>included</i> in this round of annotation
108 * processing, or declarations of members, parameters, or type
109 * parameters declared within those, are returned. Included type
110 * elements are {@linkplain #getRootElements specified
111 * types} and any types nested within them.
112 *
113 * @param a annotation type being requested
114 * @return the elements annotated with the given annotation type,
115 * or an empty set if there are none
116 */
117 @DefinedBy(Api.ANNOTATION_PROCESSING)
118 public Set<? extends Element> getElementsAnnotatedWith(TypeElement a) {
119 throwIfNotAnnotation(a);
120
121 Set<Element> result = Collections.emptySet();
122 ElementScanner9<Set<Element>, TypeElement> scanner =
123 new AnnotationSetScanner(result);
124
125 for (Element element : rootElements)
126 result = scanner.scan(element, a);
127
128 return result;
129 }
130
131 @DefinedBy(Api.ANNOTATION_PROCESSING)
132 public Set<? extends Element> getElementsAnnotatedWithAny(TypeElement... annotations) {
133 // Don't bother to special-case annotations.length == 1 as
134 // return getElementsAnnotatedWith(annotations[0]);
135
136 Set<TypeElement> annotationSet = new LinkedHashSet<>(annotations.length);
137 for (TypeElement annotation : annotations) {
138 throwIfNotAnnotation(annotation);
139 annotationSet.add(annotation);
140 }
141
142 Set<Element> result = Collections.emptySet();
143 ElementScanner9<Set<Element>, Set<TypeElement>> scanner =
144 new AnnotationSetMultiScanner(result);
145
146 for (Element element : rootElements)
147 result = scanner.scan(element, annotationSet);
148
149 return result;
150 }
151
152 // Could be written as a local class inside getElementsAnnotatedWith
153 private class AnnotationSetScanner extends
154 ElementScanningIncludingTypeParameters<Set<Element>, TypeElement> {
155 // Insertion-order preserving set
156 private Set<Element> annotatedElements = new LinkedHashSet<>();
157
158 AnnotationSetScanner(Set<Element> defaultSet) {
159 super(defaultSet);
160 }
161
162 @Override @DefinedBy(Api.LANGUAGE_MODEL)
163 public Set<Element> scan(Element e, TypeElement annotation) {
164 for (AnnotationMirror annotMirror : eltUtils.getAllAnnotationMirrors(e)) {
165 if (annotation.equals(mirrorAsElement(annotMirror))) {
166 annotatedElements.add(e);
167 break;
168 }
169 }
170 e.accept(this, annotation);
171 return annotatedElements;
172 }
173 }
174
175 // Could be written as a local class inside getElementsAnnotatedWithAny
176 private class AnnotationSetMultiScanner extends
177 ElementScanningIncludingTypeParameters<Set<Element>, Set<TypeElement>> {
178 // Insertion-order preserving set
179 private Set<Element> annotatedElements = new LinkedHashSet<>();
180
181 AnnotationSetMultiScanner(Set<Element> defaultSet) {
182 super(defaultSet);
183 }
184
185 @Override @DefinedBy(Api.LANGUAGE_MODEL)
186 public Set<Element> scan(Element e, Set<TypeElement> annotations) {
187 for (AnnotationMirror annotMirror : eltUtils.getAllAnnotationMirrors(e)) {
188 if (annotations.contains(mirrorAsElement(annotMirror))) {
189 annotatedElements.add(e);
190 break;
191 }
192 }
193 e.accept(this, annotations);
194 return annotatedElements;
195 }
196 }
197
198 private static abstract class ElementScanningIncludingTypeParameters<R, P>
199 extends ElementScanner9<R, P> {
200
201 protected ElementScanningIncludingTypeParameters(R defaultValue) {
202 super(defaultValue);
203 }
204
205 @Override @DefinedBy(Api.LANGUAGE_MODEL)
206 public R visitType(TypeElement e, P p) {
207 // Type parameters are not considered to be enclosed by a type
208 scan(e.getTypeParameters(), p);
209 return super.visitType(e, p);
210 }
211
212 @Override @DefinedBy(Api.LANGUAGE_MODEL)
213 public R visitExecutable(ExecutableElement e, P p) {
214 // Type parameters are not considered to be enclosed by an executable
215 scan(e.getTypeParameters(), p);
216 return super.visitExecutable(e, p);
217 }
218 }
219
220 /**
221 * {@inheritDoc}
222 */
223 @DefinedBy(Api.ANNOTATION_PROCESSING)
224 public Set<? extends Element> getElementsAnnotatedWith(Class<? extends Annotation> a) {
225 throwIfNotAnnotation(a);
226 String name = a.getCanonicalName();
227 if (name == null)
228 return Collections.emptySet();
229 else {
230 TypeElement annotationType = eltUtils.getTypeElement(name);
231 if (annotationType == null)
232 return Collections.emptySet();
233 else
234 return getElementsAnnotatedWith(annotationType);
235 }
236 }
237
238 @DefinedBy(Api.ANNOTATION_PROCESSING)
239 public Set<? extends Element> getElementsAnnotatedWithAny(Set<Class<? extends Annotation>> annotations) {
240 List<TypeElement> annotationsAsElements = new ArrayList<>(annotations.size());
241
242 for (Class<? extends Annotation> annotation : annotations) {
243 throwIfNotAnnotation(annotation);
244 String name = annotation.getCanonicalName();
245 if (name == null)
246 continue;
247 annotationsAsElements.add(eltUtils.getTypeElement(name));
248 }
249
250 return getElementsAnnotatedWithAny(annotationsAsElements.toArray(new TypeElement[0]));
251 }
252
253 private Element mirrorAsElement(AnnotationMirror annotationMirror) {
254 return annotationMirror.getAnnotationType().asElement();
255 }
256
257 private static final String NOT_AN_ANNOTATION_TYPE =
258 "The argument does not represent an annotation type: ";
259
260 private void throwIfNotAnnotation(Class<? extends Annotation> a) {
261 if (!a.isAnnotation())
262 throw new IllegalArgumentException(NOT_AN_ANNOTATION_TYPE + a);
263 }
264
265 private void throwIfNotAnnotation(TypeElement a) {
266 if (a.getKind() != ElementKind.ANNOTATION_TYPE)
267 throw new IllegalArgumentException(NOT_AN_ANNOTATION_TYPE + a);
268 }
269 }
|