8163315: Implement an API to identify an implicitly declared annotation (or declaration)
Summary: Adding javax.lang.model.util.Elements.getOrigin
Reviewed-by: jjg
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/element/package-info.java Fri Dec 16 12:02:30 2016 +0100
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/element/package-info.java Fri Dec 16 12:04:32 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2013, 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
@@ -53,7 +53,9 @@
* Names of parameters may not be recoverable from class files.
*
* The {@linkplain javax.lang.model.element.Modifier modifiers} on an
- * element may differ in some cases including:
+ * element created from a class file may differ in some cases from an
+ * element for the same declaration created from a source file
+ * including:
*
* <ul>
* <li> {@code strictfp} on a class or interface
@@ -61,10 +63,19 @@
* <li> {@code protected}, {@code private}, and {@code static} on classes and interfaces
* </ul>
*
- * Additionally, synthetic constructs in a class file, such as
- * accessor methods used in implementing nested classes and bridge
- * methods used in implementing covariant returns, are translation
- * artifacts outside of this model.
+ * Some elements which are {@linkplain
+ * javax.lang.model.util.Elements.Origin#MANDATED mandated} may not be
+ * marked as such when created from class files.
+ *
+ * Additionally, {@linkplain
+ * javax.lang.model.util.Elements.Origin#SYNTHETIC synthetic}
+ * constructs in a class file, such as accessor methods used in
+ * implementing nested classes and {@linkplain
+ * javax.lang.model.util.Elements.Origin#isBridge(ExecutableElement)
+ * bridge methods} used in implementing covariant returns, are
+ * translation artifacts strictly outside of this model. However, when
+ * operating on class files, it is helpful be able to operate on such
+ * elements, screening them out when appropriate.
*
* <p>During annotation processing, operating on incomplete or
* erroneous programs is necessary; however, there are fewer
--- a/langtools/src/java.compiler/share/classes/javax/lang/model/util/Elements.java Fri Dec 16 12:02:30 2016 +0100
+++ b/langtools/src/java.compiler/share/classes/javax/lang/model/util/Elements.java Fri Dec 16 12:04:32 2016 +0100
@@ -29,6 +29,7 @@
import java.util.List;
import java.util.Map;
+import javax.lang.model.AnnotatedConstruct;
import javax.lang.model.element.*;
@@ -143,6 +144,167 @@
boolean isDeprecated(Element e);
/**
+ * Returns the <em>origin</em> of the given element.
+ *
+ * <p>Note that if this method returns {@link Origin#EXPLICIT
+ * EXPLICIT} and the element was created from a class file, then
+ * the element may not, in fact, correspond to an explicitly
+ * declared construct in source code. This is due to limitations
+ * of the fidelity of the class file format in preserving
+ * information from source code. For example, at least some
+ * versions of the class file format do not preserve whether a
+ * constructor was explicitly declared by the programmer or was
+ * implicitly declared as the <em>default constructor</em>.
+ *
+ * @implSpec The default implementation of this method returns
+ * {@link Origin#EXPLICIT EXPLICIT}.
+ *
+ * @param e the element being examined
+ * @return the origin of the given element
+ * @since 9
+ */
+ default Origin getOrigin(Element e) {
+ return Origin.EXPLICIT;
+ }
+
+ /**
+ * Returns the <em>origin</em> of the given annotation mirror.
+ *
+ * An annotation mirror is {@linkplain Origin#MANDATED mandated}
+ * if it is an implicitly declared <em>container annotation</em>
+ * used to hold repeated annotations of a repeatable annotation
+ * type.
+ *
+ * <p>Note that if this method returns {@link Origin#EXPLICIT
+ * EXPLICIT} and the annotation mirror was created from a class
+ * file, then the element may not, in fact, correspond to an
+ * explicitly declared construct in source code. This is due to
+ * limitations of the fidelity of the class file format in
+ * preserving information from source code. For example, at least
+ * some versions of the class file format do not preserve whether
+ * an annotation was explicitly declared by the programmer or was
+ * implicitly declared as a <em>container annotation</em>.
+ *
+ * @implSpec The default implementation of this method returns
+ * {@link Origin#EXPLICIT EXPLICIT}.
+ *
+ * @param c the construct the annotation mirror modifies
+ * @param a the annotation mirror being examined
+ * @return the origin of the given annotation mirror
+ * @jls 9.6.3 Repeatable Annotation Types
+ * @jls 9.7.5 Multiple Annotations of the Same Type
+ * @since 9
+ */
+ default Origin getOrigin(AnnotatedConstruct c,
+ AnnotationMirror a) {
+ return Origin.EXPLICIT;
+ }
+
+ /**
+ * Returns the <em>origin</em> of the given module directive.
+ *
+ * <p>Note that if this method returns {@link Origin#EXPLICIT
+ * EXPLICIT} and the module directive was created from a class
+ * file, then the module directive may not, in fact, correspond to
+ * an explicitly declared construct in source code. This is due to
+ * limitations of the fidelity of the class file format in
+ * preserving information from source code. For example, at least
+ * some versions of the class file format do not preserve whether
+ * a {@code uses} directive was explicitly declared by the
+ * programmer or was added as a synthetic construct.
+ *
+ * <p>Note that an implementation may not be able to reliably
+ * determine the origin status of the directive if the directive
+ * is created from a class file due to limitations of the fidelity
+ * of the class file format in preserving information from source
+ * code.
+ *
+ * @implSpec The default implementation of this method returns
+ * {@link Origin#EXPLICIT EXPLICIT}.
+ *
+ * @param m the module of the directive
+ * @param directive the module directive being examined
+ * @return the origin of the given directive
+ * @since 9
+ */
+ default Origin getOrigin(ModuleElement m,
+ ModuleElement.Directive directive) {
+ return Origin.EXPLICIT;
+ }
+
+ /**
+ * The <em>origin</em> of an element or other language model
+ * item. The origin of an element or item models how a construct
+ * in a program is declared in the source code, explicitly,
+ * implicitly, etc.
+ *
+ * <p>Note that it is possible additional kinds of origin values
+ * will be added in future versions of the platform.
+ *
+ * @jls 13.1 The Form of a Binary
+ * @since 9
+ */
+ public enum Origin {
+ /**
+ * Describes a construct explicitly declared in source code.
+ */
+ EXPLICIT,
+
+ /**
+ * A mandated construct is one that is not explicitly declared
+ * in the source code, but whose presence is mandated by the
+ * specification. Such a construct is said to be implicitly
+ * declared.
+ *
+ * One example of a mandated element is a <em>default
+ * constructor</em> in a class that contains no explicit
+ * constructor declarations.
+ *
+ * Another example of a mandated construct is an implicitly
+ * declared <em>container annotation</em> used to hold
+ * multiple annotations of a repeatable annotation type.
+ *
+ * @jls 8.8.9 Default Constructor
+ * @jls 9.6.3 Repeatable Annotation Types
+ * @jls 9.7.5 Multiple Annotations of the Same Type
+ */
+ MANDATED,
+
+ /**
+ * A synthetic construct is one that is neither implicitly nor
+ * explicitly declared in the source code. Such a construct is
+ * typically a translation artifact created by a compiler.
+ */
+ SYNTHETIC;
+
+ /**
+ * Returns {@code true} for values corresponding to constructs
+ * that are implicitly or explicitly declared, {@code false}
+ * otherwise.
+ * @return {@code true} for {@link EXPLICIT} and {@link
+ * MANDATED}, {@code false} otherwise.
+ */
+ public boolean isDeclared() {
+ return this != SYNTHETIC;
+ }
+ }
+
+ /**
+ * Returns {@code true} if the executable element is a bridge
+ * method, {@code false} otherwise.
+ *
+ * @implSpec The default implementation of this method returns {@code false}.
+ *
+ * @param e the executable being examined
+ * @return {@code true} if the executable element is a bridge
+ * method, {@code false} otherwise
+ * @since 9
+ */
+ default boolean isBridge(ExecutableElement e) {
+ return false;
+ }
+
+ /**
* Returns the <i>binary name</i> of a type element.
*
* @param type the type element being examined