RFR: JDK-8213103: RoundEnvironment.getElementsAnnotatedWith(Class) crashes with -source 8
joe darcy
joe.darcy at oracle.com
Wed Oct 31 17:27:05 UTC 2018
Hi Jan,
On 10/31/2018 3:50 AM, Jan Lahoda wrote:
> Hi,
>
> When RoundEnvironment.getElementsAnnotatedWith(Class) converts the
> Class to TypeElement, it uses:
> eltUtils.getTypeElement(eltUtils.getModuleElement(<class-module-name>),
> <class-name>)
>
> But this fails with -source 8, as there are no module (so
> getModuleElement returns null, and getTypeElement checks the module
> parameter is non-null). The proposed fix is to avoid this code.
>
> Bug: https://bugs.openjdk.java.net/browse/JDK-8213103
> Webrev: http://cr.openjdk.java.net/~jlahoda/8213103/webrev.00/index.html
>
> Any feedback is welcome,
>
Thanks for looking at this issue.
Stepping back a bit, the API functionality being supported is
RoundEnvironment.getElementsAnnotatedWith(Class<? extends
Annotation> a)
and related methods which take in annotation types indicated using Class
objects (a runtime core reflection representation) and convert them
internally to TypeElement's (a compile-time representation) by
extracting the name of the annotation type and then doing various look-ups.
If the compile-time and runtime environments and configured to be
consistent with each other, then a runtime annotation type should be
able to get back a corresponding compile-time representation. However,
it is possible for the environments to not be consistent, leading to
this bug and the earlier change 8190886: "package-info handling in
RoundEnvironment.getElementsAnnotatedWith" which this proposed fix amends.
The proposed "return null" arm in
@@ -285,13 +285,15 @@
// differ from the single module being compiled.
String name = annotation.getCanonicalName();
TypeElement annotationElement = eltUtils.getTypeElement(name);
if (annotationElement != null)
return annotationElement;
- else {
+ else if (!eltUtils.getAllModuleElements().isEmpty()) {
String moduleName =
Objects.requireNonNullElse(annotation.getModule().getName(), "");
return
eltUtils.getTypeElement(eltUtils.getModuleElement(moduleName), name);
+ } else {
+ return null;
}
}
private Element mirrorAsElement(AnnotationMirror annotationMirror) {
return annotationMirror.getAnnotationType().asElement();
is basically the handling for an inconsistent environment pre-modules.
The preceding lines are an, in retrospect, incomplete handling of an
inconsistent state with modules.
I recommend the check for "if modules are supported" be implemented
using a Source-based predicate so that any future dead code will get
removed once modules are in all supported source levels. In that route
is not chosen, is getAllModuleElements() a good-performing predicate for
this purpose? Would something like "if (getModuleElement("java.base")
!= null )" be better?
If the annotation type indicated by the Class object *cannot* be turned
into an compile-time annotation type, arguably that is an erroneous
situation that should cause an exception. The IllegalArgumentException
clauses of
RoundEnvironment.getElementsAnnotatedWith(Class<? extends Annotation> a)
RoundEnvironment.getElementsAnnotatedWithAny(Set<Class<? extends
Annotation>> annotations)
could be expanded to cover this situation and, in the implementation,
return null replaced by throwing an informative exception.
What do you think?
Cheers,
-Joe
More information about the compiler-dev
mailing list