8190886: package-info handling in RoundEnvironment.getElementsAnnotatedWith

Reviewed-by: vromero, jlahoda
This commit is contained in:
Joe Darcy 2018-07-25 12:32:59 -07:00
parent 6602e30cec
commit ac5685e827
18 changed files with 308 additions and 27 deletions

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2018, 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
@ -170,6 +170,18 @@ public class JavacRoundEnvironment implements RoundEnvironment {
e.accept(this, annotation);
return annotatedElements;
}
@Override @DefinedBy(Api.LANGUAGE_MODEL)
public Set<Element> visitModule(ModuleElement e, TypeElement annotation) {
// Do not scan a module
return annotatedElements;
}
@Override @DefinedBy(Api.LANGUAGE_MODEL)
public Set<Element> visitPackage(PackageElement e, TypeElement annotation) {
// Do not scan a package
return annotatedElements;
}
}
// Could be written as a local class inside getElementsAnnotatedWithAny
@ -193,6 +205,18 @@ public class JavacRoundEnvironment implements RoundEnvironment {
e.accept(this, annotations);
return annotatedElements;
}
@Override @DefinedBy(Api.LANGUAGE_MODEL)
public Set<Element> visitModule(ModuleElement e, Set<TypeElement> annotations) {
// Do not scan a module
return annotatedElements;
}
@Override @DefinedBy(Api.LANGUAGE_MODEL)
public Set<Element> visitPackage(PackageElement e, Set<TypeElement> annotations) {
// Do not scan a package
return annotatedElements;
}
}
private static abstract class ElementScanningIncludingTypeParameters<R, P>
@ -224,10 +248,12 @@ public class JavacRoundEnvironment implements RoundEnvironment {
public Set<? extends Element> getElementsAnnotatedWith(Class<? extends Annotation> a) {
throwIfNotAnnotation(a);
String name = a.getCanonicalName();
if (name == null)
return Collections.emptySet();
else {
TypeElement annotationType = eltUtils.getTypeElement(name);
TypeElement annotationType = annotationToElement(a);
if (annotationType == null)
return Collections.emptySet();
else
@ -244,12 +270,29 @@ public class JavacRoundEnvironment implements RoundEnvironment {
String name = annotation.getCanonicalName();
if (name == null)
continue;
annotationsAsElements.add(eltUtils.getTypeElement(name));
annotationsAsElements.add(annotationToElement(annotation));
}
return getElementsAnnotatedWithAny(annotationsAsElements.toArray(new TypeElement[0]));
}
private TypeElement annotationToElement(Class<? extends Annotation> annotation) {
// First, try an element lookup based on the annotation's
// canonical name. If that fails or is ambiguous, try a lookup
// using a particular module, perhaps an unnamed one. This
// offers more compatibility for compiling in single-module
// mode where the runtime module of an annotation type may
// differ from the single module being compiled.
String name = annotation.getCanonicalName();
TypeElement annotationElement = eltUtils.getTypeElement(name);
if (annotationElement != null)
return annotationElement;
else {
String moduleName = Objects.requireNonNullElse(annotation.getModule().getName(), "");
return eltUtils.getTypeElement(eltUtils.getModuleElement(moduleName), name);
}
}
private Element mirrorAsElement(AnnotationMirror annotationMirror) {
return annotationMirror.getAnnotationType().asElement();
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2018, 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
@ -21,6 +21,8 @@
* questions.
*/
import annot.AnnotatedElementInfo;
/**
* Class to hold annotations for TestElementsAnnotatedWith.
*/

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2018, 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
@ -21,6 +21,8 @@
* questions.
*/
import annot.AnnotatedElementInfo;
@AnnotatedElementInfo(annotationName="InheritedAnnotation",
expectedSize=1,
names="C2")

@ -2,6 +2,8 @@
* Class to hold annotations for TestElementsAnnotatedWith.
*/
import annot.AnnotatedElementInfo;
@AnnotatedElementInfo(annotationName="java.lang.SuppressWarnings",
expectedSize=0,
names={})

@ -1,3 +1,3 @@
ErroneousAnnotations.java:8:2: compiler.err.cant.resolve: kindname.class, Undefined, ,
ErroneousAnnotations.java:10:6: compiler.err.cant.resolve.location: kindname.class, Undefined, , , (compiler.misc.location: kindname.class, ErroneousAnnotations, null)
ErroneousAnnotations.java:10:2: compiler.err.cant.resolve: kindname.class, Undefined, ,
ErroneousAnnotations.java:12:6: compiler.err.cant.resolve.location: kindname.class, Undefined, , , (compiler.misc.location: kindname.class, ErroneousAnnotations, null)
2 errors

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2018, 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
@ -21,7 +21,9 @@
* questions.
*/
@AnnotatedElementInfo(annotationName="AnnotatedElementInfo",
import annot.AnnotatedElementInfo;
@AnnotatedElementInfo(annotationName="annot.AnnotatedElementInfo",
expectedSize=1,
names="Foo")
public class Foo {}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2018, 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
@ -21,6 +21,8 @@
* questions.
*/
import annot.AnnotatedElementInfo;
/**
* Class to hold annotations for ElementsAnnotatedWithTest.
*/

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2018, 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
@ -21,6 +21,8 @@
* questions.
*/
import annot.AnnotatedElementInfo;
/**
* Class to hold annotations for TestElementsAnnotatedWith.
*/

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2018, 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
@ -21,6 +21,8 @@
* questions.
*/
import annot.AnnotatedElementInfo;
/**
* Class to hold annotations for TestElementsAnnotatedWith.
*/

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2018, 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
@ -23,13 +23,14 @@
/*
* @test
* @bug 6397298 6400986 6425592 6449798 6453386 6508401 6498938 6911854 8030049 8038080 8032230
* @summary Tests that getElementsAnnotatedWith works properly.
* @bug 6397298 6400986 6425592 6449798 6453386 6508401 6498938 6911854 8030049 8038080 8032230 8190886
* @summary Tests that getElementsAnnotatedWith[Any] methods work properly.
* @author Joseph D. Darcy
* @library /tools/javac/lib
* @modules java.compiler
* jdk.compiler
* @build JavacTestingAbstractProcessor
* @compile annot/AnnotatedElementInfo.java annot/MarkerAnnot.java
* @compile TestElementsAnnotatedWith.java
* @compile InheritedAnnotation.java
* @compile TpAnno.java
@ -41,11 +42,17 @@
* @compile -processor TestElementsAnnotatedWith -proc:only Foo.java
* @compile -processor TestElementsAnnotatedWith -proc:only TypeParameterAnnotations.java
* @compile -processor TestElementsAnnotatedWith -proc:only ParameterAnnotations.java
* @compile -processor TestElementsAnnotatedWith -proc:only pkg/package-info.java
* @compile -processor TestElementsAnnotatedWith -proc:only mod/quux/package-info.java
* @compile -processor TestElementsAnnotatedWith -proc:only mod/quux/Quux.java
* @compile mod/quux/Quux.java mod/quux/package-info.java
* @compile -processor TestElementsAnnotatedWith -proc:only -AsingleModuleMode=true mod/module-info.java
* @compile/fail/ref=ErroneousAnnotations.out -processor TestElementsAnnotatedWith -proc:only -XDrawDiagnostics ErroneousAnnotations.java
* @compile Foo.java
* @compile/process -processor TestElementsAnnotatedWith -proc:only Foo
*/
import annot.AnnotatedElementInfo;
import java.lang.annotation.Annotation;
import java.util.Collections;
import java.util.Set;
@ -148,8 +155,6 @@ public class TestElementsAnnotatedWith extends JavacTestingAbstractProcessor {
* getElementsAnnotatedWith(X) UNION getElementsAnnotatedWith(Y).
*/
void checkSetOfAnnotatedElements(RoundEnvironment re) {
TypeElement annotatedElemInfoElem = elements.getTypeElement("AnnotatedElementInfo");
// For the "Any" methods, search for both the expected
// annotation and AnnotatedElementInfo and verify the return
// set is the union of searching for AnnotatedElementInfo and
@ -162,28 +167,45 @@ public class TestElementsAnnotatedWith extends JavacTestingAbstractProcessor {
Set<? extends Element> resultsBaseAny = Collections.emptySet();
Set<? extends Element> resultsBaseAnyMulti = Collections.emptySet();
boolean singleModuleMode = processingEnv.getOptions().get("singleModuleMode") != null;
TypeElement annotatedElemInfoElem = null;
if (!re.processingOver()) {
testNonAnnotations(re);
// Verify AnnotatedElementInfo is present on the first
// specified type.
TypeElement firstType = typesIn(re.getRootElements()).iterator().next();
Element firstElement = re.getRootElements().iterator().next();
AnnotatedElementInfo annotatedElemInfo =
firstType.getAnnotation(AnnotatedElementInfo.class);
firstElement.getAnnotation(AnnotatedElementInfo.class);
ModuleElement moduleContext;
if (singleModuleMode) {
// Should also be the case that firstElement.getKind() == ElementKind.MODULE
moduleContext = (ModuleElement)firstElement;
} else {
moduleContext = elements.getModuleElement(""); // unnamed module
}
annotatedElemInfoElem =
elements.getTypeElement(moduleContext, "annot.AnnotatedElementInfo");
boolean failed = false;
Objects.requireNonNull(annotatedElemInfo,
"Missing AnnotatedElementInfo annotation on " + firstType);
"Missing AnnotatedElementInfo annotation on " + firstElement);
// Verify that the annotation information is as expected.
Set<String> expectedNames =
new HashSet<>(Arrays.asList(annotatedElemInfo.names()));
String annotationName = annotatedElemInfo.annotationName();
TypeElement annotationTypeElem = elements.getTypeElement(annotationName);
TypeElement annotationTypeElem = elements.getTypeElement(moduleContext,
annotationName);
resultsMeta = re.getElementsAnnotatedWith(annotationTypeElem);
resultsMetaAny = re.getElementsAnnotatedWithAny(annotationTypeElem);
@ -229,7 +251,7 @@ public class TestElementsAnnotatedWith extends JavacTestingAbstractProcessor {
System.err.printf("Inconsistent Base with vs withAny results");
}
if (!resultsMeta.equals(resultsBase)) {
if (!singleModuleMode && !resultsMeta.equals(resultsBase)) {
failed = true;
System.err.println("Base and Meta sets unequal;\n meta: " + resultsMeta +
"\nbase: " + resultsBase);
@ -241,7 +263,7 @@ public class TestElementsAnnotatedWith extends JavacTestingAbstractProcessor {
"\nbase: " + resultsBase);
}
if (!resultsBaseAnyMulti.equals(resultsMetaAnyMulti)) {
if (!singleModuleMode && !resultsBaseAnyMulti.equals(resultsMetaAnyMulti)) {
failed = true;
System.err.println("BaseMulti and MetaMulti sets unequal;\n meta: " + resultsMeta +
"\nbase: " + resultsBase);
@ -255,10 +277,16 @@ public class TestElementsAnnotatedWith extends JavacTestingAbstractProcessor {
// If processing is over without an error, the specified
// elements should be empty so an empty set should be
// returned.
throwOnNonEmpty(re.getElementsAnnotatedWith(annotatedElemInfoElem), "resultsMeta");
throwOnNonEmpty(re.getElementsAnnotatedWithAny(annotatedElemInfoElem), "resultsMetaAny");
throwOnNonEmpty(re.getElementsAnnotatedWith(AnnotatedElementInfo.class), "resultsBase");
throwOnNonEmpty(re.getElementsAnnotatedWithAny(Set.of(AnnotatedElementInfo.class)), "resultsBaseAny");
if (!singleModuleMode) {
// Could also use two-argument form of getTypeElement with an unnamed module argument.
annotatedElemInfoElem = elements.getTypeElement("annot.AnnotatedElementInfo");
throwOnNonEmpty(re.getElementsAnnotatedWith(annotatedElemInfoElem), "resultsMeta");
throwOnNonEmpty(re.getElementsAnnotatedWithAny(annotatedElemInfoElem), "resultsMetaAny");
}
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2018, 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
@ -21,6 +21,8 @@
* questions.
*/
import annot.AnnotatedElementInfo;
/**
* Class to hold annotations for TestElementsAnnotatedWith.
*/

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2018, 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
@ -21,7 +21,10 @@
* questions.
*/
package annot;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
/**
@ -29,6 +32,7 @@ import static java.lang.annotation.RetentionPolicy.*;
* with a given annotation.
*/
@Retention(RUNTIME)
@Target({TYPE, MODULE, PACKAGE})
public @interface AnnotatedElementInfo {
String annotationName();
int expectedSize();

@ -0,0 +1,36 @@
/*
* Copyright (c) 2018, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package annot;
import java.lang.annotation.*;
import static java.lang.annotation.RetentionPolicy.*;
import static java.lang.annotation.ElementType.*;
/**
* A marker annotation.
*/
@Retention(RUNTIME)
@Target({TYPE, MODULE, PACKAGE})
public @interface MarkerAnnot {
}

@ -0,0 +1,33 @@
/*
* Copyright (c) 2018, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* A module
*/
@annot.AnnotatedElementInfo(annotationName="annot.MarkerAnnot",
expectedSize=1,
names={"mod"})
@annot.MarkerAnnot
module mod {
exports quux;
}

@ -0,0 +1,30 @@
/*
* Copyright (c) 2018, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package quux;
@annot.AnnotatedElementInfo(annotationName="annot.MarkerAnnot", expectedSize=1, names={"Quux"})
@SuppressWarnings("")
@annot.MarkerAnnot
public class Quux {
}

@ -0,0 +1,31 @@
/*
* Copyright (c) 2018, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* A package
*/
@annot.AnnotatedElementInfo(annotationName="annot.MarkerAnnot",
expectedSize=1,
names={"quux"})
@annot.MarkerAnnot
package quux;

@ -0,0 +1,29 @@
/*
* Copyright (c) 2015, 2018, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg;
@SuppressWarnings("")
@annot.MarkerAnnot
public class Foo {
}

@ -0,0 +1,31 @@
/*
* Copyright (c) 2018, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* A package
*/
@annot.AnnotatedElementInfo(annotationName="annot.MarkerAnnot",
expectedSize=1,
names={"pkg"})
@annot.MarkerAnnot
package pkg;