| /* | |
| * Copyright (c) 2005, 2024, 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. Oracle designates this | |
| * particular file as subject to the "Classpath" exception as provided | |
| * by Oracle in the LICENSE file that accompanied this code. | |
| * | |
| * 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. | |
| */ | |
| /** | |
| * Utilities to assist in the processing of | |
| * {@linkplain javax.lang.model.element program elements} and | |
| * {@linkplain javax.lang.model.type types}. | |
| * | |
| * <p> 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. | |
| * | |
| * <p> Unless otherwise specified, methods in this package will throw | |
| * a {@code NullPointerException} if given a {@code null} argument. | |
| * | |
| * @apiNote | |
| * | |
| * <h2 id=expectedEvolution>Expected visitor evolution</h2> | |
| * | |
| * As the Java programming language evolves, the visitor interfaces of | |
| * the language model also evolve as do the concrete visitors in this | |
| * package. A <a href="https://openjdk.org/jeps/12">preview language | |
| * feature</a> in JDK <i>N</i> 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 | |
| * <em>not</em> marked as preview. | |
| * | |
| * <p>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: | |
| * <ul> | |
| * | |
| * <li>the preview language construct has a corresponding new modeling | |
| * interface and a concomitant new kind constant, such as a new {@link | |
| * javax.lang.model.element.ElementKind} constant | |
| * | |
| * <li>the preview language construct only triggers the introduction | |
| * of a new kind <em>without</em> a new modeling interface | |
| * | |
| * </ul> | |
| * | |
| * 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. | |
| * | |
| * <h3 id=topLevelLangConstruct>Adding visitor support for a | |
| * top-level language construct</h3> | |
| * | |
| * Consider a new language feature, preview feature 1, in JDK <i>N</i>. This | |
| * feature has a top-level element interface to model it: | |
| * | |
| * <pre> | |
| * 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... | |
| * } | |
| * </pre> | |
| * A new element kind would also be introduced to model such a feature: | |
| * | |
| * <pre> | |
| * // Sample diff of ElementKind.java | |
| * + /** | |
| * + * A preview feature 1. | |
| * + * @since N | |
| * + */ | |
| * + PREVIEW_FEATURE_1, | |
| * </pre> | |
| * | |
| * A {@code default} method is added to {@code ElementVisitor} to accommodate the new construct: | |
| * <pre> | |
| * // 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); | |
| * + } | |
| * </pre> | |
| * | |
| * Given the {@code 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: | |
| * | |
| * <pre> | |
| * // 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 | |
| * + * {@code 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); | |
| * + } | |
| * </pre> | |
| * | |
| * When preview feature 1 exits preview in JDK (<i>N+k</i>), a set of | |
| * visitors for language level (<i>N+k</i>) would be added. The | |
| * methods operating over the feature would be moved from the preview | |
| * visitors to the new language level (<i>N+k</i>) visitors. Each | |
| * preview visitor would then have its direct superclass changed to | |
| * the new corresponding (<i>N+k</i>) visitor. | |
| * | |
| * <h3 id=newKindLangConstruct>Adding visitor support for a language | |
| * construct that is a new kind of an existing construct</h3> | |
| * | |
| * Consider a new language feature, preview feature 2, in JDK | |
| * <i>N</i>. This feature has a new element kind <em>without</em> 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: | |
| * | |
| * <pre> | |
| * // 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; | |
| * }; | |
| * } | |
| * </pre> | |
| * | |
| * The kind visitors need support for the new variety of element: | |
| * <pre> | |
| * // 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); | |
| * + } | |
| * </pre> | |
| * | |
| * The preview element kind visitor in turn overrides {@code | |
| * visitVariableAsPreviewFeature2}: | |
| * <pre> | |
| * // 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); | |
| * + } | |
| * </pre> | |
| * | |
| * As in the case where a new interface is introduced, when preview | |
| * feature 2 exits preview in JDK (<i>N+k</i>), a set of visitors for | |
| * language level (<i>N+k</i>) 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 (<i>N+k</i>) visitors. Each | |
| * preview visitor would then have its direct superclass changed to | |
| * the new corresponding (<i>N+k</i>) visitor. | |
| * | |
| * @since 1.6 | |
| * | |
| * @see <a href="https://jcp.org/en/jsr/detail?id=269"> | |
| * JSR 269: Pluggable Annotation Processing API</a> | |
| */ | |
| package javax.lang.model.util; |