Package javax.lang.model.util


package javax.lang.model.util
Utilities to assist in the processing of program elements and types.

Unless otherwise specified in a particular implementation, the collections returned by methods in this package should be expected to be unmodifiable by the caller and unsafe for concurrent access.

Unless otherwise specified, methods in this package will throw a NullPointerException if given a null argument.

API Note:

Expected visitor evolution

As the Java programming language evolves, the visitor interfaces of the language model also evolve as do the concrete visitors in this package. A preview language feature in JDK N may have API elements added in the set of visitors for the preview language level. Such new elements are marked as reflective preview API. Any existing methods whose specification is updated to support the preview feature are not marked as preview.

The remainder of this note will show two examples of the API changes in the model and visitors that can be added to support a language feature. The examples will use additions to the elements portion of the language model, but the updates to visitors for types or annotation values would be analogous. Two distinct cases are:

  • the preview language construct has a corresponding new modeling interface and a concomitant new kind constant, such as a new ElementKind constant
  • the preview language construct only triggers the introduction of a new kind without a new modeling interface
If a preview language feature is withdrawn rather than evolving to a permanent platform feature, the API elements associated with the feature are expected to be removed. The examples below outline the API changes expected when a preview feature becomes a permanent feature.

Adding visitor support for a top-level language construct

Consider a new language feature, preview feature 1, in JDK N. This feature has a top-level element interface to model it:
 package javax.lang.model.element;
 /**
  * Represents a preview feature 1.
  *
  * @since N
  */
  public interface PreviewFeature1Element extends Element {
  // Methods to retrieve information specific to the preview feature...
  }
 
A new element kind would also be introduced to model such a feature:
  //  Sample diff of ElementKind.java
  +    /**
  +     * A preview feature 1.
  +     * @since N
  +     */
  +     PREVIEW_FEATURE_1,
 
A default method is added to ElementVisitor to accommodate the new construct:
 //  Sample diff for ElementVisitor.java
  +    /**
  +     * Visits a preview feature 1.
  +     *
  +     * @implSpec The default implementation visits a {@code
  +     * PreviewFeature1Element} by calling {@code visitUnknown(e, p)}.
  +     *
  +     * @param e  the element to visit
  +     * @param p  a visitor-specified parameter
  +     * @return a visitor-specified result
  +     * @since N
  +     */
  +    default R visitPreviewFeature1(PreviewFeature1Element e, P p) {
  +        return visitUnknown(e, p);
  +    }
 
Given the default method on the visitor interface, the preview visitor classes need to override this method and take an action appropriate for the visitor's semantics:
 //  Sample diff for AbstractElementVisitorPreview.java
 //  Re-abstract visitPreviewFeature1.
  +    /**
  +     * {@inheritDoc ElementVisitor}
  +     *
  +     * @implSpec Visits a {@code PreviewFeature1Element} in a manner
  +     * defined by a subclass.
  +     *
  +     * @param e {@inheritDoc ElementVisitor}
  +     * @param p {@inheritDoc ElementVisitor}
  +     * @return a visitor-specified result
  +     * @since N
  +     */
  +    @Override
  +    public abstract R visitPreviewFeature1(PreviewFeature1Element e, P p);

 //  Sample diff for ElementKindVisitorPreview.java
 //  Take the default action for a preview feature 1.
  +
  +    /**
  +     * {@inheritDoc ElementVisitor}
  +     *
  +     * @implSpec This implementation calls {@code defaultAction}.
  +     *
  +     * @param e {@inheritDoc ElementVisitor}
  +     * @param p {@inheritDoc ElementVisitor}
  +     * @return  the result of {@code defaultAction}
  +     * @since N
  +     */
  +    @Override
  +    public R visitPreviewFeature1(PreviewFeature1Element e, P p) {
  +        return defaultAction(e, p);
  +    }

 //  Sample diff for ElementScannerPreview.java
 //  Scan the enclosed elements of a preview feature 1.
  +
  +    /**
  +     * {@inheritDoc ElementVisitor}
  +     *
  +     * @implSpec This implementation scans the enclosed elements.
  +     *
  +     * @param e {@inheritDoc ElementVisitor}
  +     * @param p {@inheritDoc ElementVisitor}
  +     * @return  {@inheritDoc ElementScanner6}
  +     * @since N
  +     */
  +    @Override
  +    public R visitPreviewFeature1(PreviewFeature1Element e, P p) {
  +        return scan(e.getEnclosedElements(), p);
  +    }

 //  Sample diff for SimpleElementVisitorPreview.java
 //  Take the default action for a preview feature 1.
  +    /**
  +     * {@inheritDoc ElementVisitor}
  +     *
  +     * @implSpec Visits a {@code PreviewFeature1Element} by calling
  +     * defaultAction.
  +     *
  +     * @param e {@inheritDoc ElementVisitor}
  +     * @param p {@inheritDoc ElementVisitor}
  +     * @return  {@inheritDoc ElementVisitor}
  +     * @since N
  +     */
  +    @Override
  +    public R visitPreviewFeature1(PreviewFeature1Element e, P p) {
  +        return defaultAction(e, p);
  +    }
 
When preview feature 1 exits preview in JDK (N+k), a set of visitors for language level (N+k) would be added. The methods operating over the feature would be moved from the preview visitors to the new language level (N+k) visitors. Each preview visitor would then have its direct superclass changed to the new corresponding (N+k) visitor.

Adding visitor support for a language construct that is a new kind of an existing construct

Consider a new language feature, preview feature 2, in JDK N. This feature has a new element kind without a new top-level element interface needed to model it. Concretely, assume a preview feature 2 is a new kind of variable; the changes would be analogous if the feature were a new kind of executable instead or new kind of another existing top-level construct. In that case, the API changes are more limited:
  //  Sample diff for ElementKind.java
  +    /**
  +     * A preview feature 2.
  +     * @since N
  +     */
  +     PREVIEW_FEATURE_2,
  ...
  // Update existing methods as needed
       public boolean isVariable() {
           return switch(this) {
           case ENUM_CONSTANT, FIELD, PARAMETER,
                LOCAL_VARIABLE, EXCEPTION_PARAMETER, RESOURCE_VARIABLE,
  -             BINDING_VARIABLE -> true;
  +             BINDING_VARIABLE, PREVIEW_FEATURE_2 -> true;
           default -> false;
           };
       }
 
The kind visitors need support for the new variety of element:
 // Update visitVariable in ElementKindVisitor6:
        ...
        * @implSpec This implementation dispatches to the visit method for
        * the specific {@linkplain ElementKind kind} of variable, {@code
        * ENUM_CONSTANT}, {@code EXCEPTION_PARAMETER}, {@code FIELD},
  -     * {@code LOCAL_VARIABLE}, {@code PARAMETER}, or {@code RESOURCE_VARIABLE}.
  +     * {@code LOCAL_VARIABLE}, {@code PARAMETER}, {@code RESOURCE_VARIABLE},
  +     * or {@code PREVIEW_FEATURE_2}.
        *
        * @param e {@inheritDoc ElementVisitor}
        * @param p {@inheritDoc ElementVisitor}
        * @return  the result of the kind-specific visit method
        */
        @Override
        public R visitVariable(VariableElement e, P p) {
        ...
           case BINDING_VARIABLE:
               return visitVariableAsBindingVariable(e, p);

  +        case PREVIEW_FEATURE_2:
  +            return visitVariableAsPreviewFeature2(e, p);
  +
           default:
               throw new AssertionError("Bad kind " + k + " for VariableElement" + e);
        ...
  +    /**
  +     * Visits a {@code PREVIEW_FEATURE_2} variable element.
  +     *
  +     * @implSpec This implementation calls {@code visitUnknown}.
  +     *
  +     * @param e the element to visit
  +     * @param p a visitor-specified parameter
  +     * @return  the result of {@code visitUnknown}
  +     *
  +     * @since N
  +     */
  +    public R visitVariableAsPreviewFeature2(VariableElement e, P p) {
  +        return visitUnknown(e, p);
  +    }
 
The preview element kind visitor in turn overrides visitVariableAsPreviewFeature2:
 // Sample diff for ElementKindVisitorPreview:
  +    /**
  +     * {@inheritDoc ElementKindVisitor6}
  +     *
  +     * @implSpec This implementation calls {@code defaultAction}.
  +     *
  +     * @param e {@inheritDoc ElementKindVisitor6}
  +     * @param p {@inheritDoc ElementKindVisitor6}
  +     * @return  the result of {@code defaultAction}
  +     *
  +     * @since N
  +     */
  +    @Override
  +    public R visitVariableAsPreviewFeature2(VariableElement e, P p) {
  +        return defaultAction(e, p);
  +    }
 
As in the case where a new interface is introduced, when preview feature 2 exits preview in JDK (N+k), a set of visitors for language level (N+k) would be added. The methods operating over the new feature in the kind visitors would be moved from the preview visitors to new language level (N+k) visitors. Each preview visitor would then have its direct superclass changed to the new corresponding (N+k) visitor.
Since:
1.6
See Also: