changeset 57406:4356d1581548

8235541: Extend javax.lang.model to cover binding variables Reviewed-by: darcy
author jlahoda
date Mon, 09 Dec 2019 09:40:09 +0100
parents 8c7facf81d01
children 9468dada3479
files src/java.compiler/share/classes/javax/lang/model/element/ElementKind.java src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor14.java src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor6.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Kinds.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java test/langtools/tools/javac/api/TestGetElementReferenceData.java test/langtools/tools/javac/processing/model/element/TestBindingVariable.java test/langtools/tools/javac/processing/model/element/TestBindingVariableData.java
diffstat 9 files changed, 222 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.compiler/share/classes/javax/lang/model/element/ElementKind.java	Thu Dec 12 09:52:15 2019 +0100
+++ b/src/java.compiler/share/classes/javax/lang/model/element/ElementKind.java	Mon Dec 09 09:40:09 2019 +0100
@@ -137,7 +137,24 @@
      */
     @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS,
                                  essentialAPI=false)
-    RECORD_COMPONENT;
+    RECORD_COMPONENT,
+
+    /**
+     * {@preview Associated with pattern matching for {@code
+     * instanceof}, a preview feature of the Java language.
+     *
+     *           This enum constant is associated with <i>pattern
+     *           matching for {@code instanceof}</i>, a preview
+     *           feature of the Java language. Preview features
+     *           may be removed in a future release, or upgraded to permanent
+     *           features of the Java language.}
+     *
+     * A binding variable in a pattern .
+     * @since 14
+     */
+    @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.PATTERN_MATCHING_IN_INSTANCEOF,
+                                 essentialAPI=false)
+    BINDING_VARIABLE;
 
     /**
      * Returns {@code true} if this is a kind of class:
--- a/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor14.java	Thu Dec 12 09:52:15 2019 +0100
+++ b/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor14.java	Mon Dec 09 09:40:09 2019 +0100
@@ -136,4 +136,20 @@
     public R visitTypeAsRecord(TypeElement e, P p) {
         return defaultAction(e, p);
     }
+
+    /**
+     * Visits a {@code BINDING_VARIABLE} variable element.
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
+     *
+     * @param e {@inheritDoc}
+     * @param p {@inheritDoc}
+     * @return  the result of {@code defaultAction}
+     *
+     * @since 14
+     */
+    @Override
+    public R visitVariableAsBindingVariable(VariableElement e, P p) {
+        return defaultAction(e, p);
+    }
 }
--- a/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor6.java	Thu Dec 12 09:52:15 2019 +0100
+++ b/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor6.java	Mon Dec 09 09:40:09 2019 +0100
@@ -274,6 +274,9 @@
         case RESOURCE_VARIABLE:
             return visitVariableAsResourceVariable(e, p);
 
+        case BINDING_VARIABLE:
+            return visitVariableAsBindingVariable(e, p);
+
         default:
             throw new AssertionError("Bad kind " + k + " for VariableElement" + e);
         }
@@ -360,6 +363,21 @@
     }
 
     /**
+     * Visits a {@code BINDING_VARIABLE} 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 14
+     */
+    public R visitVariableAsBindingVariable(VariableElement e, P p) {
+        return visitUnknown(e, p);
+    }
+
+    /**
      * {@inheritDoc}
      *
      * @implSpec This implementation dispatches to the visit method
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Kinds.java	Thu Dec 12 09:52:15 2019 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Kinds.java	Mon Dec 09 09:40:09 2019 +0100
@@ -290,6 +290,7 @@
         case TYPE_PARAMETER:
             return KindName.TYPEVAR;
 
+        case BINDING_VARIABLE:
         case ENUM_CONSTANT:
         case PARAMETER:
         case LOCAL_VARIABLE:
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Thu Dec 12 09:52:15 2019 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Mon Dec 09 09:40:09 2019 +0100
@@ -1659,6 +1659,10 @@
                 return ElementKind.FIELD;
             } else if (isResourceVariable()) {
                 return ElementKind.RESOURCE_VARIABLE;
+            } else if ((flags & MATCH_BINDING) != 0) {
+                @SuppressWarnings("preview")
+                ElementKind kind = ElementKind.BINDING_VARIABLE;
+                return kind;
             } else {
                 return ElementKind.LOCAL_VARIABLE;
             }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java	Thu Dec 12 09:52:15 2019 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java	Mon Dec 09 09:40:09 2019 +0100
@@ -955,6 +955,7 @@
                         appendTypeAnnotationsToOwner(v, v.getRawTypeAttributes());
                     }
                     switch (v.getKind()) {
+                        case BINDING_VARIABLE:
                         case LOCAL_VARIABLE:
                             return TypeAnnotationPosition
                                 .localVariable(location.toList(), currentLambda,
--- a/test/langtools/tools/javac/api/TestGetElementReferenceData.java	Thu Dec 12 09:52:15 2019 +0100
+++ b/test/langtools/tools/javac/api/TestGetElementReferenceData.java	Mon Dec 09 09:40:09 2019 +0100
@@ -36,7 +36,7 @@
         utility/*getElement:METHOD:test.TestGetElementReferenceData.Base.utility()*/();
         target(TestGetElementReferenceData :: test/*getElement:METHOD:test.TestGetElementReferenceData.test()*/);
         Object/*getElement:CLASS:java.lang.Object*/ o = null;
-        if (o/*getElement:LOCAL_VARIABLE:o*/ instanceof String/*getElement:CLASS:java.lang.String*/ str/*getElement:LOCAL_VARIABLE:str*/) ;
+        if (o/*getElement:LOCAL_VARIABLE:o*/ instanceof String/*getElement:CLASS:java.lang.String*/ str/*getElement:BINDING_VARIABLE:str*/) ;
     }
     private static void target(Runnable r) { r.run(); }
     public static class Base {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/processing/model/element/TestBindingVariable.java	Mon Dec 09 09:40:09 2019 +0100
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2010, 2019, 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.
+ */
+
+/*
+ * @test
+ * @bug  8235541
+ * @summary Test that the binding variable kind is appropriately set
+ * @library /tools/javac/lib
+ * @modules jdk.compiler
+ * @build   JavacTestingAbstractProcessor
+ * @compile TestBindingVariable.java
+ * @compile --enable-preview -source ${jdk.version} -processor TestBindingVariable -proc:only TestBindingVariableData.java
+ */
+
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.lang.model.util.*;
+import java.util.*;
+import com.sun.source.tree.*;
+import com.sun.source.util.*;
+
+/**
+ * Using the tree API, retrieve element representations of the
+ * binding variables of the type test pattern, and verify their kind
+ * tags are set appropriately.
+ */
+public class TestBindingVariable extends JavacTestingAbstractProcessor implements AutoCloseable {
+    int bindingVariableCount = 0;
+
+    public boolean process(Set<? extends TypeElement> annotations,
+                          RoundEnvironment roundEnv) {
+       if (!roundEnv.processingOver()) {
+           Trees trees = Trees.instance(processingEnv);
+
+           for(Element rootElement : roundEnv.getRootElements()) {
+               TreePath treePath = trees.getPath(rootElement);
+
+               (new BindingVariableScanner(trees)).
+                   scan(treePath.getCompilationUnit(), null);
+           }
+           if (bindingVariableCount != 2)
+               throw new RuntimeException("Bad binding variable count " +
+                                          bindingVariableCount);
+       }
+       return true;
+    }
+
+    @Override
+    public void close() {}
+
+    /**
+     * Verify that a binding variable modeled as an element behaves
+     * as expected under 6 and latest specific visitors.
+     */
+    private static void testBindingVariable(Element element) {
+        ElementVisitor visitor6 = new ElementKindVisitor6<Void, Void>() {};
+
+        try {
+            visitor6.visit(element);
+            throw new RuntimeException("Expected UnknownElementException not thrown.");
+        } catch (UnknownElementException uee) {
+            ; // Expected.
+        }
+
+        ElementKindVisitor visitorLatest =
+            new ElementKindVisitor<Object, Void>() {
+            @Override
+            public Object visitVariableAsBindingVariable(VariableElement e,
+                                                         Void p) {
+                return e; // a non-null value
+            }
+        };
+
+        if (visitorLatest.visit(element) == null) {
+            throw new RuntimeException("Null result of resource variable visitation.");
+        }
+    }
+
+    class BindingVariableScanner extends TreePathScanner<Void, Void> {
+        private Trees trees;
+
+        public BindingVariableScanner(Trees trees) {
+            super();
+            this.trees = trees;
+        }
+        @Override
+        public Void visitBindingPattern(BindingPatternTree node, Void p) {
+            handleCurrentTreeAsBindingVar();
+            return super.visitBindingPattern(node, p);
+        }
+
+        @Override
+        public Void visitIdentifier(IdentifierTree node, Void p) {
+            if (node.getName().contentEquals("bindingVar")) {
+                handleCurrentTreeAsBindingVar();
+            }
+            return super.visitIdentifier(node, p);
+        }
+
+        private void handleCurrentTreeAsBindingVar() {
+           Element element = trees.getElement(getCurrentPath());
+
+           System.out.println("Name: " + element.getSimpleName() +
+                              "\tKind: " + element.getKind());
+           if (element.getKind() != ElementKind.BINDING_VARIABLE) {
+               throw new RuntimeException("Expected a binding variable, but got: " +
+                                          element.getKind());
+           }
+           testBindingVariable(element);
+           bindingVariableCount++;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/processing/model/element/TestBindingVariableData.java	Mon Dec 09 09:40:09 2019 +0100
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+public class TestBindingVariableData {
+
+    private boolean test(Object o) {
+        return o instanceof String bindingVar && !bindingVar.isEmpty();
+    }
+
+}