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