changeset 48741:9278248c6c71 switch

Adding repeated case labels to expression switches, fixing TreeTranslator to understand switch expressions.
author jlahoda
date Mon, 15 Jan 2018 11:12:51 +0100
parents 0fe63dbc5e54
children c969fffbfc9b
files src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeTranslator.java test/langtools/tools/javac/switchexpr/ExpressionSwitchFallThrough.java test/langtools/tools/javac/switchexpr/MultipleLabels.java test/langtools/tools/javac/switchnull/SwitchNullNegative.java test/langtools/tools/javac/switchnull/SwitchNullNegative.out
diffstat 6 files changed, 192 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Fri Jan 12 20:05:51 2018 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Mon Jan 15 11:12:51 2018 +0100
@@ -1374,6 +1374,7 @@
             accept(LBRACE);
             ListBuffer<JCCaseExpression> caseExprs = new ListBuffer<>();
             while (token.kind != RBRACE) {
+                int casePos = token.pos;
                 JCExpression pat;
 
                 if (token.kind == DEFAULT) {
@@ -1381,7 +1382,12 @@
                     pat = null;
                 } else {
                     accept(CASE);
-                    pat = term(EXPR | NOLAMBDA);
+                    while (true) {
+                        pat = term(EXPR | NOLAMBDA);
+                        if (token.kind == COLON || token.kind == ARROW) break;
+                        accept(COMMA);
+                        caseExprs.append(toP(F.at(pos).CaseExpression(pat, List.nil(), null)));
+                    };
                 }
                 JCExpression value = null;
                 List<JCStatement> stats = null;
@@ -1401,7 +1407,7 @@
                         stats = blockStatements();
                         break;
                 }
-                caseExprs.append(F.at(token.pos/*XXX*/).CaseExpression(pat, stats, value));
+                caseExprs.append(F.at(casePos).CaseExpression(pat, stats, value));
             }
 
             nextToken();
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeTranslator.java	Fri Jan 12 20:05:51 2018 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeTranslator.java	Mon Jan 15 11:12:51 2018 +0100
@@ -95,6 +95,14 @@
         return trees;
     }
 
+    /**  Visitor method: translate a list of case parts of switch statements.
+     */
+    public List<JCCaseExpression> translateCaseExpressions(List<JCCaseExpression> trees) {
+        for (List<JCCaseExpression> l = trees; l.nonEmpty(); l = l.tail)
+            l.head = translate(l.head);
+        return trees;
+    }
+
     /**  Visitor method: translate a list of catch clauses in try statements.
      */
     public List<JCCatch> translateCatchers(List<JCCatch> trees) {
@@ -212,6 +220,19 @@
         result = tree;
     }
 
+    public void visitSwitchExpression(JCSwitchExpression tree) {
+        tree.selector = translate(tree.selector);
+        tree.cases = translateCaseExpressions(tree.cases);
+        result = tree;
+    }
+
+    public void visitCaseExpression(JCCaseExpression tree) {
+        tree.pat = translate(tree.pat);
+        tree.stats = translate(tree.stats);
+        tree.value = translate(tree.value);
+        result = tree;
+    }
+
     public void visitSynchronized(JCSynchronized tree) {
         tree.lock = translate(tree.lock);
         tree.body = translate(tree.body);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/switchexpr/ExpressionSwitchFallThrough.java	Mon Jan 15 11:12:51 2018 +0100
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2018, 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
+ * @compile ExpressionSwitchFallThrough.java
+ * @run main ExpressionSwitchFallThrough
+ */
+
+import java.util.Objects;
+import java.util.function.Function;
+
+public class ExpressionSwitchFallThrough {
+    public static void main(String... args) {
+        new ExpressionSwitchFallThrough().run();
+    }
+
+    private void run() {
+        runTest(this::expression1);
+        runTest(this::expression2);
+    }
+
+    private void runTest(Function<T, String> print) {
+        check(T.A,  print, "ab");
+        check(T.B,  print, "b");
+        check(T.C,  print, "");
+    }
+
+    private String expression1(T t) {
+        String help = "";
+        return switch (t) {
+            case A: help = "a";
+            case B: help += "b";
+            default: break help;
+        };
+    }
+
+    private String expression2(T t) {
+        String help = "";
+        return switch (t) {
+            case A: help = "a";
+            case B: help += "b";
+            default -> help;
+        };
+    }
+
+    private void check(T t, Function<T, String> print, String expected) {
+        String result = print.apply(t);
+        if (!Objects.equals(result, expected)) {
+            throw new AssertionError("Unexpected result: " + result);
+        }
+    }
+
+    enum T {
+        A, B, C;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/switchexpr/MultipleLabels.java	Mon Jan 15 11:12:51 2018 +0100
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2018, 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
+ * @compile MultipleLabels.java
+ * @run main MultipleLabels
+ */
+
+import java.util.Objects;
+import java.util.function.Function;
+
+public class MultipleLabels {
+    public static void main(String... args) {
+        new MultipleLabels().run();
+    }
+
+    private void run() {
+        runTest(this::statement1);
+    }
+
+    private void runTest(Function<T, String> print) {
+        check(null, print, "NULL-A");
+        check(T.A,  print, "NULL-A");
+        check(T.B,  print, "B-C");
+        check(T.C,  print, "B-C");
+        check(T.D,  print, "D");
+        check(T.E,  print, "other");
+    }
+
+    private String statement1(T t) {
+        String res;
+
+        switch (t) {
+            case null, A: res = "NULL-A"; break;
+            case B, C: res = "B-C"; break;
+            case D: res = "D"; break;
+            default: res = "other"; break;
+        }
+
+        return res;
+    }
+
+    private String expression1(T t) {
+        return switch (t) {
+            case null, A -> "NULL-A";
+            case B, C: break "B-C";
+            case D -> "D";
+            default -> "other";
+        };
+    }
+
+    private void check(T t, Function<T, String> print, String expected) {
+        String result = print.apply(t);
+        if (!Objects.equals(result, expected)) {
+            throw new AssertionError("Unexpected result: " + result);
+        }
+    }
+
+    enum T {
+        A, B, C, D, E;
+    }
+}
--- a/test/langtools/tools/javac/switchnull/SwitchNullNegative.java	Fri Jan 12 20:05:51 2018 +0100
+++ b/test/langtools/tools/javac/switchnull/SwitchNullNegative.java	Mon Jan 15 11:12:51 2018 +0100
@@ -1,5 +1,5 @@
 /**
- * @test
+ * @test /nodynamiccopyright/
  * @compile/fail/ref=SwitchNullNegative.out -XDrawDiagnostics SwitchNullNegative.java
  */
 
--- a/test/langtools/tools/javac/switchnull/SwitchNullNegative.out	Fri Jan 12 20:05:51 2018 +0100
+++ b/test/langtools/tools/javac/switchnull/SwitchNullNegative.out	Mon Jan 15 11:12:51 2018 +0100
@@ -1,5 +1,5 @@
 SwitchNullNegative.java:10:13: compiler.err.switch.null.must.be.first
 SwitchNullNegative.java:17:13: compiler.err.switch.null.must.be.reference
-SwitchNullNegative.java:26:13: compiler.err.switch.null.must.be.first
-SwitchNullNegative.java:33:13: compiler.err.switch.null.must.be.reference
+SwitchNullNegative.java:25:13: compiler.err.switch.null.must.be.first
+SwitchNullNegative.java:32:13: compiler.err.switch.null.must.be.reference
 4 errors