JavacRoundEnvironment.java revision 2601:8e638f046bf0
19313Ssos/*
2230132Suqs * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
39313Ssos * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
49313Ssos *
59313Ssos * This code is free software; you can redistribute it and/or modify it
69313Ssos * under the terms of the GNU General Public License version 2 only, as
79313Ssos * published by the Free Software Foundation.  Oracle designates this
89313Ssos * particular file as subject to the "Classpath" exception as provided
9111798Sdes * by Oracle in the LICENSE file that accompanied this code.
109313Ssos *
119313Ssos * This code is distributed in the hope that it will be useful, but WITHOUT
129313Ssos * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
139313Ssos * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
149313Ssos * version 2 for more details (a copy is included in the LICENSE file that
1597748Sschweikh * accompanied this code).
169313Ssos *
179313Ssos * You should have received a copy of the GNU General Public License version
189313Ssos * 2 along with this work; if not, write to the Free Software Foundation,
199313Ssos * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
209313Ssos *
219313Ssos * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
229313Ssos * or visit www.oracle.com if you need additional information or have any
239313Ssos * questions.
249313Ssos */
259313Ssos
269313Ssospackage com.sun.tools.javac.processing;
279313Ssos
289313Ssosimport java.lang.annotation.Annotation;
29116173Sobrienimport javax.annotation.processing.*;
30116173Sobrienimport javax.lang.model.element.*;
31116173Sobrienimport javax.lang.model.util.*;
32156874Sruimport java.util.*;
3331784Seivind
349313Ssosimport com.sun.tools.javac.util.DefinedBy;
359313Ssosimport com.sun.tools.javac.util.DefinedBy.Api;
36263233Srwatson
3776166Smarkm/**
3876166Smarkm * Object providing state about a prior round of annotation processing.
399313Ssos *
409313Ssos * <p>The methods in this class do not take type annotations into account,
419313Ssos * as target types, not java elements.
4231561Sbde *
439313Ssos * <p><b>This is NOT part of any supported API.
4472538Sjlemon * If you write code that depends on this, you do so at your own risk.
4576166Smarkm * This code and its internal interfaces are subject to change or
46168014Sjulian * deletion without notice.</b>
4776166Smarkm */
48162201Snetchildpublic class JavacRoundEnvironment implements RoundEnvironment {
49166085Skib    // Default equals and hashCode methods are okay.
50102814Siedowse
5176166Smarkm    private final boolean processingOver;
5214331Speter    private final boolean errorRaised;
53162585Snetchild    private final ProcessingEnvironment processingEnv;
5476166Smarkm
5512458Sbde    // Caller must pass in an immutable set
56140214Sobrien    private final Set<? extends Element> rootElements;
57140214Sobrien
58140214Sobrien    JavacRoundEnvironment(boolean processingOver,
59140214Sobrien                          boolean errorRaised,
6064905Smarcel                          Set<? extends Element> rootElements,
6168583Smarcel                          ProcessingEnvironment processingEnv) {
62133816Stjr        this.processingOver = processingOver;
63246085Sjhb        this.errorRaised = errorRaised;
6464905Smarcel        this.rootElements = rootElements;
65177997Skib        this.processingEnv = processingEnv;
669313Ssos    }
67315376Sdchagin
68315376Sdchagin    public String toString() {
69315376Sdchagin        return String.format("[errorRaised=%b, rootElements=%s, processingOver=%b]",
70315376Sdchagin                             errorRaised,
719313Ssos                             rootElements,
7283366Sjulian                             processingOver);
739313Ssos    }
74300411Sdchagin
75300411Sdchagin    @DefinedBy(Api.ANNOTATION_PROCESSING)
769313Ssos    public boolean processingOver() {
77300411Sdchagin        return processingOver;
789313Ssos    }
7972543Sjlemon
80102814Siedowse    /**
819313Ssos     * Returns {@code true} if an error was raised in the prior round
82300411Sdchagin     * of processing; returns {@code false} otherwise.
83300411Sdchagin     *
84300411Sdchagin     * @return {@code true} if an error was raised in the prior round
85300411Sdchagin     * of processing; returns {@code false} otherwise.
869313Ssos     */
879313Ssos    @DefinedBy(Api.ANNOTATION_PROCESSING)
88168014Sjulian    public boolean errorRaised() {
89168014Sjulian        return errorRaised;
90177997Skib    }
919313Ssos
92300411Sdchagin    /**
93300411Sdchagin     * Returns the type elements specified by the prior round.
94300411Sdchagin     *
95300411Sdchagin     * @return the types elements specified by the prior round, or an
96300411Sdchagin     * empty set if there were none
9714331Speter     */
98300411Sdchagin    @DefinedBy(Api.ANNOTATION_PROCESSING)
99300411Sdchagin    public Set<? extends Element> getRootElements() {
100300411Sdchagin        return rootElements;
101300411Sdchagin    }
102300411Sdchagin
103300411Sdchagin    private static final String NOT_AN_ANNOTATION_TYPE =
104300411Sdchagin        "The argument does not represent an annotation type: ";
105300411Sdchagin
106300411Sdchagin    /**
107300411Sdchagin     * Returns the elements annotated with the given annotation type.
108300411Sdchagin     * Only type elements <i>included</i> in this round of annotation
109300411Sdchagin     * processing, or declarations of members, parameters, or type
110300411Sdchagin     * parameters declared within those, are returned.  Included type
111300411Sdchagin     * elements are {@linkplain #getRootElements specified
112300411Sdchagin     * types} and any types nested within them.
113300411Sdchagin     *
114300411Sdchagin     * @param a  annotation type being requested
115300411Sdchagin     * @return the elements annotated with the given annotation type,
116300411Sdchagin     * or an empty set if there are none
117300411Sdchagin     */
118300411Sdchagin    @DefinedBy(Api.ANNOTATION_PROCESSING)
119300411Sdchagin    public Set<? extends Element> getElementsAnnotatedWith(TypeElement a) {
120300411Sdchagin        Set<Element> result = Collections.emptySet();
121300411Sdchagin        if (a.getKind() != ElementKind.ANNOTATION_TYPE)
122300411Sdchagin            throw new IllegalArgumentException(NOT_AN_ANNOTATION_TYPE + a);
123300411Sdchagin
124300411Sdchagin        ElementScanner9<Set<Element>, TypeElement> scanner =
125300411Sdchagin            new AnnotationSetScanner(result);
126300411Sdchagin
127300411Sdchagin        for (Element element : rootElements)
128300411Sdchagin            result = scanner.scan(element, a);
129300411Sdchagin
130300411Sdchagin        return result;
131300411Sdchagin    }
132300411Sdchagin
133300411Sdchagin    // Could be written as a local class inside getElementsAnnotatedWith
1349313Ssos    private class AnnotationSetScanner extends
135300411Sdchagin        ElementScanner9<Set<Element>, TypeElement> {
136300411Sdchagin        // Insertion-order preserving set
137300411Sdchagin        Set<Element> annotatedElements = new LinkedHashSet<>();
138300411Sdchagin
139300411Sdchagin        AnnotationSetScanner(Set<Element> defaultSet) {
140178036Srdivacky            super(defaultSet);
141300411Sdchagin        }
142300411Sdchagin
143300411Sdchagin        @Override @DefinedBy(Api.LANGUAGE_MODEL)
144300411Sdchagin        public Set<Element> visitType(TypeElement e, TypeElement p) {
145300411Sdchagin            // Type parameters are not considered to be enclosed by a type
146300411Sdchagin            scan(e.getTypeParameters(), p);
147300411Sdchagin            return super.visitType(e, p);
148300411Sdchagin        }
149300411Sdchagin
150300411Sdchagin        @Override @DefinedBy(Api.LANGUAGE_MODEL)
151300411Sdchagin        public Set<Element> visitExecutable(ExecutableElement e, TypeElement p) {
152300411Sdchagin            // Type parameters are not considered to be enclosed by an executable
153300411Sdchagin            scan(e.getTypeParameters(), p);
154300411Sdchagin            return super.visitExecutable(e, p);
155300411Sdchagin        }
156300411Sdchagin
157300411Sdchagin        @Override @DefinedBy(Api.LANGUAGE_MODEL)
158300411Sdchagin        public Set<Element> scan(Element e, TypeElement p) {
159300411Sdchagin            java.util.List<? extends AnnotationMirror> annotationMirrors =
160300411Sdchagin                processingEnv.getElementUtils().getAllAnnotationMirrors(e);
161300411Sdchagin            for (AnnotationMirror annotationMirror : annotationMirrors) {
162300411Sdchagin                if (p.equals(annotationMirror.getAnnotationType().asElement()))
163300411Sdchagin                    annotatedElements.add(e);
164300411Sdchagin            }
165300411Sdchagin            e.accept(this, p);
166281726Strasz            return annotatedElements;
167281726Strasz        }
16814331Speter    }
169300411Sdchagin
170300411Sdchagin    /**
17114331Speter     * {@inheritdoc}
172300411Sdchagin     */
173300411Sdchagin    @DefinedBy(Api.ANNOTATION_PROCESSING)
1749313Ssos    public Set<? extends Element> getElementsAnnotatedWith(Class<? extends Annotation> a) {
1759313Ssos        if (!a.isAnnotation())
1769313Ssos            throw new IllegalArgumentException(NOT_AN_ANNOTATION_TYPE + a);
177168014Sjulian        String name = a.getCanonicalName();
178168014Sjulian        if (name == null)
179177997Skib            return Collections.emptySet();
180177997Skib        else {
181168014Sjulian            TypeElement annotationType = processingEnv.getElementUtils().getTypeElement(name);
182177997Skib            if (annotationType == null)
183177997Skib                return Collections.emptySet();
184177997Skib            else
185177997Skib                return getElementsAnnotatedWith(annotationType);
186177997Skib        }
187168014Sjulian    }
188168014Sjulian}
189168014Sjulian