JavacRoundEnvironment.java revision 2981:d1e5707cd4eb
1214946Sthompsa/* 2214946Sthompsa * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. 3214946Sthompsa * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4214946Sthompsa * 5214946Sthompsa * This code is free software; you can redistribute it and/or modify it 6214946Sthompsa * under the terms of the GNU General Public License version 2 only, as 7214946Sthompsa * published by the Free Software Foundation. Oracle designates this 8214946Sthompsa * particular file as subject to the "Classpath" exception as provided 9214946Sthompsa * by Oracle in the LICENSE file that accompanied this code. 10214946Sthompsa * 11214946Sthompsa * This code is distributed in the hope that it will be useful, but WITHOUT 12214946Sthompsa * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13214946Sthompsa * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14214946Sthompsa * version 2 for more details (a copy is included in the LICENSE file that 15214946Sthompsa * accompanied this code). 16214946Sthompsa * 17214946Sthompsa * You should have received a copy of the GNU General Public License version 18214946Sthompsa * 2 along with this work; if not, write to the Free Software Foundation, 19214946Sthompsa * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20214946Sthompsa * 21214946Sthompsa * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22214946Sthompsa * or visit www.oracle.com if you need additional information or have any 23214946Sthompsa * questions. 24214946Sthompsa */ 25214946Sthompsa 26214946Sthompsapackage com.sun.tools.javac.processing; 27214946Sthompsa 28214946Sthompsaimport java.lang.annotation.Annotation; 29214946Sthompsaimport javax.annotation.processing.*; 30214946Sthompsaimport javax.lang.model.element.*; 31214946Sthompsaimport javax.lang.model.util.*; 32214946Sthompsaimport java.util.*; 33214946Sthompsa 34214946Sthompsaimport com.sun.tools.javac.util.DefinedBy; 35214946Sthompsaimport com.sun.tools.javac.util.DefinedBy.Api; 36214946Sthompsa 37214946Sthompsa/** 38214946Sthompsa * Object providing state about a prior round of annotation processing. 39214946Sthompsa * 40214946Sthompsa * <p>The methods in this class do not take type annotations into account, 41214946Sthompsa * as target types, not java elements. 42214946Sthompsa * 43214946Sthompsa * <p><b>This is NOT part of any supported API. 44214946Sthompsa * If you write code that depends on this, you do so at your own risk. 45214946Sthompsa * This code and its internal interfaces are subject to change or 46214946Sthompsa * deletion without notice.</b> 47214946Sthompsa */ 48214946Sthompsapublic class JavacRoundEnvironment implements RoundEnvironment { 49214946Sthompsa // Default equals and hashCode methods are okay. 50214946Sthompsa 51214946Sthompsa private final boolean processingOver; 52214946Sthompsa private final boolean errorRaised; 53214946Sthompsa private final ProcessingEnvironment processingEnv; 54214946Sthompsa 55214946Sthompsa // Caller must pass in an immutable set 56214946Sthompsa private final Set<? extends Element> rootElements; 57214946Sthompsa 58214946Sthompsa JavacRoundEnvironment(boolean processingOver, 59214946Sthompsa boolean errorRaised, 60214946Sthompsa Set<? extends Element> rootElements, 61214946Sthompsa ProcessingEnvironment processingEnv) { 62214946Sthompsa this.processingOver = processingOver; 63214946Sthompsa this.errorRaised = errorRaised; 64214946Sthompsa this.rootElements = rootElements; 65214946Sthompsa this.processingEnv = processingEnv; 66214946Sthompsa } 67214946Sthompsa 68214946Sthompsa public String toString() { 69214946Sthompsa return String.format("[errorRaised=%b, rootElements=%s, processingOver=%b]", 70214946Sthompsa errorRaised, 71214946Sthompsa rootElements, 72214946Sthompsa processingOver); 73214946Sthompsa } 74214946Sthompsa 75214946Sthompsa @DefinedBy(Api.ANNOTATION_PROCESSING) 76214946Sthompsa public boolean processingOver() { 77214946Sthompsa return processingOver; 78214946Sthompsa } 79214946Sthompsa 80214946Sthompsa /** 81214946Sthompsa * Returns {@code true} if an error was raised in the prior round 82214946Sthompsa * of processing; returns {@code false} otherwise. 83214946Sthompsa * 84214946Sthompsa * @return {@code true} if an error was raised in the prior round 85214946Sthompsa * of processing; returns {@code false} otherwise. 86214946Sthompsa */ 87214946Sthompsa @DefinedBy(Api.ANNOTATION_PROCESSING) 88214946Sthompsa public boolean errorRaised() { 89214946Sthompsa return errorRaised; 90214946Sthompsa } 91214946Sthompsa 92214946Sthompsa /** 93214946Sthompsa * Returns the type elements specified by the prior round. 94214946Sthompsa * 95214946Sthompsa * @return the types elements specified by the prior round, or an 96214946Sthompsa * empty set if there were none 97214946Sthompsa */ 98214946Sthompsa @DefinedBy(Api.ANNOTATION_PROCESSING) 99214946Sthompsa public Set<? extends Element> getRootElements() { 100214946Sthompsa return rootElements; 101214946Sthompsa } 102214946Sthompsa 103214946Sthompsa private static final String NOT_AN_ANNOTATION_TYPE = 104214946Sthompsa "The argument does not represent an annotation type: "; 105214946Sthompsa 106214946Sthompsa /** 107214946Sthompsa * Returns the elements annotated with the given annotation type. 108214946Sthompsa * Only type elements <i>included</i> in this round of annotation 109214946Sthompsa * processing, or declarations of members, parameters, or type 110214946Sthompsa * parameters declared within those, are returned. Included type 111214946Sthompsa * elements are {@linkplain #getRootElements specified 112214946Sthompsa * types} and any types nested within them. 113214946Sthompsa * 114214946Sthompsa * @param a annotation type being requested 115214946Sthompsa * @return the elements annotated with the given annotation type, 116214946Sthompsa * or an empty set if there are none 117214946Sthompsa */ 118214946Sthompsa @DefinedBy(Api.ANNOTATION_PROCESSING) 119214946Sthompsa public Set<? extends Element> getElementsAnnotatedWith(TypeElement a) { 120214946Sthompsa Set<Element> result = Collections.emptySet(); 121214946Sthompsa if (a.getKind() != ElementKind.ANNOTATION_TYPE) 122214946Sthompsa throw new IllegalArgumentException(NOT_AN_ANNOTATION_TYPE + a); 123214946Sthompsa 124214946Sthompsa ElementScanner9<Set<Element>, TypeElement> scanner = 125214946Sthompsa new AnnotationSetScanner(result); 126214946Sthompsa 127214946Sthompsa for (Element element : rootElements) 128214946Sthompsa result = scanner.scan(element, a); 129214946Sthompsa 130214946Sthompsa return result; 131214946Sthompsa } 132214946Sthompsa 133214946Sthompsa // Could be written as a local class inside getElementsAnnotatedWith 134214946Sthompsa private class AnnotationSetScanner extends 135214946Sthompsa ElementScanner9<Set<Element>, TypeElement> { 136214946Sthompsa // Insertion-order preserving set 137214946Sthompsa Set<Element> annotatedElements = new LinkedHashSet<>(); 138214946Sthompsa 139214946Sthompsa AnnotationSetScanner(Set<Element> defaultSet) { 140214946Sthompsa super(defaultSet); 141214946Sthompsa } 142214946Sthompsa 143214946Sthompsa @Override @DefinedBy(Api.LANGUAGE_MODEL) 144214946Sthompsa public Set<Element> visitType(TypeElement e, TypeElement p) { 145214946Sthompsa // Type parameters are not considered to be enclosed by a type 146214946Sthompsa scan(e.getTypeParameters(), p); 147214946Sthompsa return super.visitType(e, p); 148214946Sthompsa } 149214946Sthompsa 150214946Sthompsa @Override @DefinedBy(Api.LANGUAGE_MODEL) 151215319Sthompsa public Set<Element> visitExecutable(ExecutableElement e, TypeElement p) { 152214946Sthompsa // Type parameters are not considered to be enclosed by an executable 153214946Sthompsa scan(e.getTypeParameters(), p); 154214946Sthompsa return super.visitExecutable(e, p); 155214946Sthompsa } 156214946Sthompsa 157214946Sthompsa @Override @DefinedBy(Api.LANGUAGE_MODEL) 158214946Sthompsa public Set<Element> scan(Element e, TypeElement p) { 159214946Sthompsa java.util.List<? extends AnnotationMirror> annotationMirrors = 160214946Sthompsa processingEnv.getElementUtils().getAllAnnotationMirrors(e); 161215319Sthompsa for (AnnotationMirror annotationMirror : annotationMirrors) { 162214946Sthompsa if (p.equals(annotationMirror.getAnnotationType().asElement())) 163214946Sthompsa annotatedElements.add(e); 164214946Sthompsa } 165214946Sthompsa e.accept(this, p); 166214946Sthompsa return annotatedElements; 167214946Sthompsa } 168214946Sthompsa } 169214946Sthompsa 170214946Sthompsa /** 171214946Sthompsa * {@inheritDoc} 172214946Sthompsa */ 173214946Sthompsa @DefinedBy(Api.ANNOTATION_PROCESSING) 174214946Sthompsa public Set<? extends Element> getElementsAnnotatedWith(Class<? extends Annotation> a) { 175214946Sthompsa if (!a.isAnnotation()) 176214946Sthompsa throw new IllegalArgumentException(NOT_AN_ANNOTATION_TYPE + a); 177214946Sthompsa String name = a.getCanonicalName(); 178214946Sthompsa if (name == null) 179214946Sthompsa return Collections.emptySet(); 180214946Sthompsa else { 181214946Sthompsa TypeElement annotationType = processingEnv.getElementUtils().getTypeElement(name); 182214946Sthompsa if (annotationType == null) 183214946Sthompsa return Collections.emptySet(); 184214946Sthompsa else 185214946Sthompsa return getElementsAnnotatedWith(annotationType); 186214946Sthompsa } 187214946Sthompsa } 188214946Sthompsa} 189214946Sthompsa