--- old/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacRoundEnvironment.java 2016-05-24 01:12:30.802924962 -0700 +++ new/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacRoundEnvironment.java 2016-05-24 01:12:30.718966962 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,6 +51,7 @@ private final boolean processingOver; private final boolean errorRaised; private final ProcessingEnvironment processingEnv; + private final Elements eltUtils; // Caller must pass in an immutable set private final Set rootElements; @@ -63,6 +64,7 @@ this.errorRaised = errorRaised; this.rootElements = rootElements; this.processingEnv = processingEnv; + this.eltUtils = processingEnv.getElementUtils(); } public String toString() { @@ -100,9 +102,6 @@ return rootElements; } - private static final String NOT_AN_ANNOTATION_TYPE = - "The argument does not represent an annotation type: "; - /** * Returns the elements annotated with the given annotation type. * Only type elements included in this round of annotation @@ -117,10 +116,9 @@ */ @DefinedBy(Api.ANNOTATION_PROCESSING) public Set getElementsAnnotatedWith(TypeElement a) { - Set result = Collections.emptySet(); - if (a.getKind() != ElementKind.ANNOTATION_TYPE) - throw new IllegalArgumentException(NOT_AN_ANNOTATION_TYPE + a); + throwIfNotAnnotation(a); + Set result = Collections.emptySet(); ElementScanner9, TypeElement> scanner = new AnnotationSetScanner(result); @@ -130,41 +128,93 @@ return result; } + @DefinedBy(Api.ANNOTATION_PROCESSING) + public Set getElementsAnnotatedWithAny(TypeElement... annotations) { + // Don't bother to special-case annotations.length == 1 as + // return getElementsAnnotatedWith(annotations[0]); + + Set annotationSet = new LinkedHashSet<>(annotations.length); + for (TypeElement annotation : annotations) { + throwIfNotAnnotation(annotation); + annotationSet.add(annotation); + } + + Set result = Collections.emptySet(); + ElementScanner9, Set> scanner = + new AnnotationSetMultiScanner(result); + + for (Element element : rootElements) + result = scanner.scan(element, annotationSet); + + return result; + } + // Could be written as a local class inside getElementsAnnotatedWith private class AnnotationSetScanner extends - ElementScanner9, TypeElement> { + ElementScanningIncludingTypeParameters, TypeElement> { // Insertion-order preserving set - Set annotatedElements = new LinkedHashSet<>(); + private Set annotatedElements = new LinkedHashSet<>(); AnnotationSetScanner(Set defaultSet) { super(defaultSet); } @Override @DefinedBy(Api.LANGUAGE_MODEL) - public Set visitType(TypeElement e, TypeElement p) { + public Set scan(Element e, TypeElement annotation) { + for (AnnotationMirror annotMirror : eltUtils.getAllAnnotationMirrors(e)) { + if (annotation.equals(mirrorAsElement(annotMirror))) { + annotatedElements.add(e); + break; + } + } + e.accept(this, annotation); + return annotatedElements; + } + } + + // Could be written as a local class inside getElementsAnnotatedWithAny + private class AnnotationSetMultiScanner extends + ElementScanningIncludingTypeParameters, Set> { + // Insertion-order preserving set + private Set annotatedElements = new LinkedHashSet<>(); + + AnnotationSetMultiScanner(Set defaultSet) { + super(defaultSet); + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Set scan(Element e, Set annotations) { + for (AnnotationMirror annotMirror : eltUtils.getAllAnnotationMirrors(e)) { + if (annotations.contains(mirrorAsElement(annotMirror))) { + annotatedElements.add(e); + break; + } + } + e.accept(this, annotations); + return annotatedElements; + } + } + + private static abstract class ElementScanningIncludingTypeParameters + extends ElementScanner9 { + + protected ElementScanningIncludingTypeParameters(R defaultValue) { + super(defaultValue); + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public R visitType(TypeElement e, P p) { // Type parameters are not considered to be enclosed by a type scan(e.getTypeParameters(), p); return super.visitType(e, p); } @Override @DefinedBy(Api.LANGUAGE_MODEL) - public Set visitExecutable(ExecutableElement e, TypeElement p) { + public R visitExecutable(ExecutableElement e, P p) { // Type parameters are not considered to be enclosed by an executable scan(e.getTypeParameters(), p); return super.visitExecutable(e, p); } - - @Override @DefinedBy(Api.LANGUAGE_MODEL) - public Set scan(Element e, TypeElement p) { - java.util.List annotationMirrors = - processingEnv.getElementUtils().getAllAnnotationMirrors(e); - for (AnnotationMirror annotationMirror : annotationMirrors) { - if (p.equals(annotationMirror.getAnnotationType().asElement())) - annotatedElements.add(e); - } - e.accept(this, p); - return annotatedElements; - } } /** @@ -172,17 +222,48 @@ */ @DefinedBy(Api.ANNOTATION_PROCESSING) public Set getElementsAnnotatedWith(Class a) { - if (!a.isAnnotation()) - throw new IllegalArgumentException(NOT_AN_ANNOTATION_TYPE + a); + throwIfNotAnnotation(a); String name = a.getCanonicalName(); if (name == null) return Collections.emptySet(); else { - TypeElement annotationType = processingEnv.getElementUtils().getTypeElement(name); + TypeElement annotationType = eltUtils.getTypeElement(name); if (annotationType == null) return Collections.emptySet(); else return getElementsAnnotatedWith(annotationType); } } + + @DefinedBy(Api.ANNOTATION_PROCESSING) + public Set getElementsAnnotatedWithAny(Set> annotations) { + List annotationsAsElements = new ArrayList<>(annotations.size()); + + for (Class annotation : annotations) { + throwIfNotAnnotation(annotation); + String name = annotation.getCanonicalName(); + if (name == null) + continue; + annotationsAsElements.add(eltUtils.getTypeElement(name)); + } + + return getElementsAnnotatedWithAny(annotationsAsElements.toArray(new TypeElement[0])); + } + + private Element mirrorAsElement(AnnotationMirror annotationMirror) { + return annotationMirror.getAnnotationType().asElement(); + } + + private static final String NOT_AN_ANNOTATION_TYPE = + "The argument does not represent an annotation type: "; + + private void throwIfNotAnnotation(Class a) { + if (!a.isAnnotation()) + throw new IllegalArgumentException(NOT_AN_ANNOTATION_TYPE + a); + } + + private void throwIfNotAnnotation(TypeElement a) { + if (a.getKind() != ElementKind.ANNOTATION_TYPE) + throw new IllegalArgumentException(NOT_AN_ANNOTATION_TYPE + a); + } }