JavacRoundEnvironment.java revision 3434:487e6d33c635
1122580Sanholt/*
2145132Sanholt * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
3122580Sanholt * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4145132Sanholt *
5122580Sanholt * This code is free software; you can redistribute it and/or modify it
695584Sanholt * under the terms of the GNU General Public License version 2 only, as
7122580Sanholt * published by the Free Software Foundation.  Oracle designates this
8122580Sanholt * particular file as subject to the "Classpath" exception as provided
9122580Sanholt * by Oracle in the LICENSE file that accompanied this code.
10122580Sanholt *
11139749Simp * This code is distributed in the hope that it will be useful, but WITHOUT
1295584Sanholt * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1395584Sanholt * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1495584Sanholt * version 2 for more details (a copy is included in the LICENSE file that
1595584Sanholt * accompanied this code).
1695584Sanholt *
1795584Sanholt * You should have received a copy of the GNU General Public License version
1895584Sanholt * 2 along with this work; if not, write to the Free Software Foundation,
1995584Sanholt * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2095584Sanholt *
2195584Sanholt * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2295584Sanholt * or visit www.oracle.com if you need additional information or have any
2395584Sanholt * questions.
2495584Sanholt */
2595584Sanholt
2695584Sanholtpackage com.sun.tools.javac.processing;
2795584Sanholt
2895584Sanholtimport java.lang.annotation.Annotation;
2995584Sanholtimport javax.annotation.processing.*;
3095584Sanholtimport javax.lang.model.element.*;
3195584Sanholtimport javax.lang.model.util.*;
3295584Sanholtimport java.util.*;
3395584Sanholt
3495584Sanholtimport com.sun.tools.javac.util.DefinedBy;
3595584Sanholtimport com.sun.tools.javac.util.DefinedBy.Api;
36152909Sanholt
37152909Sanholt/**
38152909Sanholt * Object providing state about a prior round of annotation processing.
39145132Sanholt *
40145132Sanholt * <p>The methods in this class do not take type annotations into account,
41145132Sanholt * as target types, not java elements.
42145132Sanholt *
43145132Sanholt * <p><b>This is NOT part of any supported API.
44145132Sanholt * If you write code that depends on this, you do so at your own risk.
45145132Sanholt * This code and its internal interfaces are subject to change or
46145132Sanholt * deletion without notice.</b>
47145132Sanholt */
48145132Sanholtpublic class JavacRoundEnvironment implements RoundEnvironment {
49145132Sanholt    // Default equals and hashCode methods are okay.
50145132Sanholt
51145132Sanholt    private final boolean processingOver;
52145132Sanholt    private final boolean errorRaised;
53145132Sanholt    private final ProcessingEnvironment processingEnv;
54145132Sanholt    private final Elements eltUtils;
55145132Sanholt
56145132Sanholt    // Caller must pass in an immutable set
57145132Sanholt    private final Set<? extends Element> rootElements;
58145132Sanholt
59145132Sanholt    JavacRoundEnvironment(boolean processingOver,
60122580Sanholt                          boolean errorRaised,
6195584Sanholt                          Set<? extends Element> rootElements,
6295584Sanholt                          ProcessingEnvironment processingEnv) {
6395584Sanholt        this.processingOver = processingOver;
64145132Sanholt        this.errorRaised = errorRaised;
65145132Sanholt        this.rootElements = rootElements;
66145132Sanholt        this.processingEnv = processingEnv;
67182080Srnoland        this.eltUtils = processingEnv.getElementUtils();
68182080Srnoland    }
69182080Srnoland
70145132Sanholt    public String toString() {
71152909Sanholt        return String.format("[errorRaised=%b, rootElements=%s, processingOver=%b]",
72152909Sanholt                             errorRaised,
73152909Sanholt                             rootElements,
74152909Sanholt                             processingOver);
75152909Sanholt    }
76152909Sanholt
77112015Sanholt    @DefinedBy(Api.ANNOTATION_PROCESSING)
7895584Sanholt    public boolean processingOver() {
79112015Sanholt        return processingOver;
80112015Sanholt    }
81112015Sanholt
82112015Sanholt    /**
83112015Sanholt     * Returns {@code true} if an error was raised in the prior round
84112015Sanholt     * of processing; returns {@code false} otherwise.
85158683Sanholt     *
8695584Sanholt     * @return {@code true} if an error was raised in the prior round
87112015Sanholt     * of processing; returns {@code false} otherwise.
88112015Sanholt     */
89112015Sanholt    @DefinedBy(Api.ANNOTATION_PROCESSING)
90112015Sanholt    public boolean errorRaised() {
91112015Sanholt        return errorRaised;
92112015Sanholt    }
93112015Sanholt
9495584Sanholt    /**
95122580Sanholt     * Returns the type elements specified by the prior round.
96122580Sanholt     *
97122580Sanholt     * @return the types elements specified by the prior round, or an
98122580Sanholt     * empty set if there were none
99122580Sanholt     */
100122580Sanholt    @DefinedBy(Api.ANNOTATION_PROCESSING)
101157617Sanholt    public Set<? extends Element> getRootElements() {
102182080Srnoland        return rootElements;
103122580Sanholt    }
104122580Sanholt
105122580Sanholt    /**
106122580Sanholt     * Returns the elements annotated with the given annotation type.
10795584Sanholt     * Only type elements <i>included</i> in this round of annotation
108145132Sanholt     * processing, or declarations of members, parameters, or type
109145132Sanholt     * parameters declared within those, are returned.  Included type
11095584Sanholt     * elements are {@linkplain #getRootElements specified
11195584Sanholt     * types} and any types nested within them.
11295584Sanholt     *
11395584Sanholt     * @param a  annotation type being requested
114152909Sanholt     * @return the elements annotated with the given annotation type,
115152909Sanholt     * or an empty set if there are none
116152909Sanholt     */
117182080Srnoland    @DefinedBy(Api.ANNOTATION_PROCESSING)
118145132Sanholt    public Set<? extends Element> getElementsAnnotatedWith(TypeElement a) {
119152909Sanholt        throwIfNotAnnotation(a);
120145132Sanholt
121145132Sanholt        Set<Element> result = Collections.emptySet();
122145132Sanholt        ElementScanner9<Set<Element>, TypeElement> scanner =
123122580Sanholt            new AnnotationSetScanner(result);
124122580Sanholt
125122580Sanholt        for (Element element : rootElements)
126145132Sanholt            result = scanner.scan(element, a);
127145132Sanholt
128122580Sanholt        return result;
129122580Sanholt    }
130122580Sanholt
131112015Sanholt    @DefinedBy(Api.ANNOTATION_PROCESSING)
132112015Sanholt    public Set<? extends Element> getElementsAnnotatedWithAny(TypeElement... annotations) {
133182080Srnoland        // Don't bother to special-case annotations.length == 1 as
134145132Sanholt        // return getElementsAnnotatedWith(annotations[0]);
135145132Sanholt
136145132Sanholt        Set<TypeElement> annotationSet = new LinkedHashSet<>(annotations.length);
137145132Sanholt        for (TypeElement annotation : annotations) {
138182080Srnoland            throwIfNotAnnotation(annotation);
13995584Sanholt            annotationSet.add(annotation);
140122580Sanholt        }
141122580Sanholt
142122580Sanholt        Set<Element> result = Collections.emptySet();
143182080Srnoland        ElementScanner9<Set<Element>, Set<TypeElement>> scanner =
144145132Sanholt            new AnnotationSetMultiScanner(result);
145145132Sanholt
146145132Sanholt        for (Element element : rootElements)
147145132Sanholt            result = scanner.scan(element, annotationSet);
148145132Sanholt
149182080Srnoland        return result;
15095584Sanholt    }
151130331Sanholt
152130331Sanholt    // Could be written as a local class inside getElementsAnnotatedWith
153130331Sanholt    private class AnnotationSetScanner extends
154130331Sanholt        ElementScanningIncludingTypeParameters<Set<Element>, TypeElement> {
155130331Sanholt        // Insertion-order preserving set
156130331Sanholt        private Set<Element> annotatedElements = new LinkedHashSet<>();
157130331Sanholt
158182080Srnoland        AnnotationSetScanner(Set<Element> defaultSet) {
159130331Sanholt            super(defaultSet);
160145132Sanholt        }
161182080Srnoland
162122580Sanholt        @Override @DefinedBy(Api.LANGUAGE_MODEL)
163145132Sanholt        public Set<Element> scan(Element e, TypeElement annotation) {
164145132Sanholt            for (AnnotationMirror annotMirror :  eltUtils.getAllAnnotationMirrors(e)) {
165145132Sanholt                if (annotation.equals(mirrorAsElement(annotMirror))) {
166145132Sanholt                    annotatedElements.add(e);
167145132Sanholt                    break;
168145132Sanholt                }
169145132Sanholt            }
170145132Sanholt            e.accept(this, annotation);
171130331Sanholt            return annotatedElements;
172145132Sanholt        }
173145132Sanholt    }
174145132Sanholt
175145132Sanholt    // Could be written as a local class inside getElementsAnnotatedWithAny
176145132Sanholt    private class AnnotationSetMultiScanner extends
177145132Sanholt        ElementScanningIncludingTypeParameters<Set<Element>, Set<TypeElement>> {
178145132Sanholt        // Insertion-order preserving set
179122580Sanholt        private Set<Element> annotatedElements = new LinkedHashSet<>();
180122580Sanholt
181145132Sanholt        AnnotationSetMultiScanner(Set<Element> defaultSet) {
182122580Sanholt            super(defaultSet);
183122580Sanholt        }
184182080Srnoland
185145132Sanholt        @Override @DefinedBy(Api.LANGUAGE_MODEL)
186145132Sanholt        public Set<Element> scan(Element e, Set<TypeElement> annotations) {
187145132Sanholt            for (AnnotationMirror annotMirror : eltUtils.getAllAnnotationMirrors(e)) {
188145132Sanholt                if (annotations.contains(mirrorAsElement(annotMirror))) {
189145132Sanholt                    annotatedElements.add(e);
190145132Sanholt                    break;
191145132Sanholt                }
192145132Sanholt            }
193145132Sanholt            e.accept(this, annotations);
194182080Srnoland            return annotatedElements;
19595584Sanholt        }
196122580Sanholt    }
197122580Sanholt
198122580Sanholt    private static abstract class ElementScanningIncludingTypeParameters<R, P>
199122580Sanholt        extends ElementScanner9<R, P> {
200122580Sanholt
201182080Srnoland        protected ElementScanningIncludingTypeParameters(R defaultValue) {
202145132Sanholt            super(defaultValue);
203145132Sanholt        }
204182080Srnoland
20595584Sanholt        @Override @DefinedBy(Api.LANGUAGE_MODEL)
206145132Sanholt        public R visitType(TypeElement e, P p) {
207122580Sanholt            // Type parameters are not considered to be enclosed by a type
208182080Srnoland            scan(e.getTypeParameters(), p);
209145132Sanholt            return super.visitType(e, p);
210182080Srnoland        }
211182080Srnoland
21295584Sanholt        @Override @DefinedBy(Api.LANGUAGE_MODEL)
213182080Srnoland        public R visitExecutable(ExecutableElement e, P p) {
214145132Sanholt            // Type parameters are not considered to be enclosed by an executable
215182080Srnoland            scan(e.getTypeParameters(), p);
21695584Sanholt            return super.visitExecutable(e, p);
217122580Sanholt        }
218122580Sanholt    }
219122580Sanholt
220122580Sanholt    /**
221122580Sanholt     * {@inheritDoc}
222182080Srnoland     */
22395584Sanholt    @DefinedBy(Api.ANNOTATION_PROCESSING)
22495584Sanholt    public Set<? extends Element> getElementsAnnotatedWith(Class<? extends Annotation> a) {
22595584Sanholt        throwIfNotAnnotation(a);
22695584Sanholt        String name = a.getCanonicalName();
22795584Sanholt        if (name == null)
228145132Sanholt            return Collections.emptySet();
229145132Sanholt        else {
230182080Srnoland            TypeElement annotationType = eltUtils.getTypeElement(name);
23195584Sanholt            if (annotationType == null)
232122580Sanholt                return Collections.emptySet();
233122580Sanholt            else
234122580Sanholt                return getElementsAnnotatedWith(annotationType);
235182080Srnoland        }
236145132Sanholt    }
237145132Sanholt
238145132Sanholt    @DefinedBy(Api.ANNOTATION_PROCESSING)
239145132Sanholt    public Set<? extends Element> getElementsAnnotatedWithAny(Set<Class<? extends Annotation>> annotations) {
240145132Sanholt        List<TypeElement> annotationsAsElements = new ArrayList<>(annotations.size());
241182080Srnoland
242182080Srnoland        for (Class<? extends Annotation> annotation : annotations) {
243182080Srnoland            throwIfNotAnnotation(annotation);
24495584Sanholt            String name = annotation.getCanonicalName();
245122580Sanholt            if (name == null)
246122580Sanholt                continue;
247122580Sanholt            annotationsAsElements.add(eltUtils.getTypeElement(name));
248182080Srnoland        }
249145132Sanholt
250145132Sanholt        return getElementsAnnotatedWithAny(annotationsAsElements.toArray(new TypeElement[0]));
251145132Sanholt    }
252145132Sanholt
253122580Sanholt    private Element mirrorAsElement(AnnotationMirror annotationMirror) {
254145132Sanholt        return annotationMirror.getAnnotationType().asElement();
255182080Srnoland    }
256182080Srnoland
257182080Srnoland    private static final String NOT_AN_ANNOTATION_TYPE =
25895584Sanholt        "The argument does not represent an annotation type: ";
259182080Srnoland
260145132Sanholt    private void throwIfNotAnnotation(Class<? extends Annotation> a) {
261145132Sanholt        if (!a.isAnnotation())
262182080Srnoland            throw new IllegalArgumentException(NOT_AN_ANNOTATION_TYPE + a);
26395584Sanholt    }
264122580Sanholt
265122580Sanholt    private void throwIfNotAnnotation(TypeElement a) {
266122580Sanholt        if (a.getKind() != ElementKind.ANNOTATION_TYPE)
267122580Sanholt            throw new IllegalArgumentException(NOT_AN_ANNOTATION_TYPE + a);
268122580Sanholt    }
269122580Sanholt}
270182080Srnoland