changeset 49145:e9bd0bef9745 switch

Removing CaseExpressionTree from both API and implementations; removing SwitchExpressionTree from API; unifying codepaths to reuse code.
author jlahoda
date Thu, 15 Feb 2018 17:44:00 +0100
parents 54fd9c57223e
children dd79a2d208a6
files src/jdk.compiler/share/classes/com/sun/source/tree/CaseExpressionTree.java src/jdk.compiler/share/classes/com/sun/source/tree/CaseTree.java src/jdk.compiler/share/classes/com/sun/source/tree/SwitchExpressionTree.java src/jdk.compiler/share/classes/com/sun/source/tree/SwitchTree.java src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ArgumentAttr.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeTranslator.java test/langtools/tools/javac/tree/SourceTreeScannerTest.java
diffstat 22 files changed, 162 insertions(+), 466 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/CaseExpressionTree.java	Mon Feb 12 16:49:27 2018 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2017, 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.
- */
-
-package com.sun.source.tree;
-
-import java.util.List;
-
-/**
- * TODO
- */
-public interface CaseExpressionTree extends Tree {
-    /**
-     * Returns the expression for the case, or
-     * {@code null} if this is the default case.
-     * @return the expression for the case, or null
-     */
-    //TODO: Tree?
-    ExpressionTree getExpression();
-
-    /**
-     * TODO
-     * @return TODO.
-     */
-    public List<? extends StatementTree> getStatements();
-
-    /**
-     * TODO
-     * @return TODO.
-     */
-    public ExpressionTree getValue();
-
-}
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/CaseTree.java	Mon Feb 12 16:49:27 2018 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/CaseTree.java	Thu Feb 15 17:44:00 2018 +0100
@@ -55,7 +55,20 @@
 
     /**
      * Returns the statements labeled by the case.
-     * @return the statements labeled by the case
+     * If this is a case in switch expression in for
+     * {@code case expression -> value}, returns null.
+     * @return the statements labeled by the case or null
      */
     List<? extends StatementTree> getStatements();
+
+    /**
+     * If this is a case in switch expression in for
+     * {@code case expression -> value}, the value of
+     * the case, null otherwise.
+     * 
+     * @return case value or null
+     */
+    public default ExpressionTree getValue() {
+        return null;
+    }
 }
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/SwitchExpressionTree.java	Mon Feb 12 16:49:27 2018 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2017, 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.
- */
-
-package com.sun.source.tree;
-
-import java.util.List;
-
-/**
- * TODO
- */
-public interface SwitchExpressionTree extends StatementTree {
-    /**
-     * Returns the expression for the {@code switch} statement.
-     * @return the expression
-     */
-    ExpressionTree getExpression();
-
-    /**
-     * Returns the cases for the expression {@code switch} statement.
-     * @return the cases
-     */
-    List<? extends CaseExpressionTree> getCases();
-}
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/SwitchTree.java	Mon Feb 12 16:49:27 2018 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/SwitchTree.java	Thu Feb 15 17:44:00 2018 +0100
@@ -43,7 +43,7 @@
  * @author Jonathan Gibbons
  * @since 1.6
  */
-public interface SwitchTree extends StatementTree {
+public interface SwitchTree extends StatementTree, ExpressionTree {
     /**
      * Returns the expression for the {@code switch} statement.
      * @return the expression
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java	Mon Feb 12 16:49:27 2018 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java	Thu Feb 15 17:44:00 2018 +0100
@@ -99,11 +99,6 @@
         CASE(CaseTree.class),
 
         /**
-         * Used for instances of {@link CaseExpressionTree}.
-         */
-        CASE_EXPRESSION(CaseExpressionTree.class),
-
-        /**
          * Used for instances of {@link CatchTree}.
          */
         CATCH(CatchTree.class),
@@ -245,11 +240,6 @@
         SWITCH(SwitchTree.class),
 
         /**
-         * Used for instances of {@link SwitchExpressionTree}.
-         */
-        SWITCH_EXPRESSION(SwitchExpressionTree.class),
-
-        /**
          * Used for instances of {@link SynchronizedTree}.
          */
         SYNCHRONIZED(SynchronizedTree.class),
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java	Mon Feb 12 16:49:27 2018 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java	Thu Feb 15 17:44:00 2018 +0100
@@ -138,14 +138,6 @@
     R visitCase(CaseTree node, P p);
 
     /**
-     * Visits a CaseExpressionTree node.
-     * @param node the node being visited
-     * @param p a parameter value
-     * @return a result value
-     */
-    R visitCaseExpression(CaseExpressionTree node, P p);
-
-    /**
      * Visits a CatchTree node.
      * @param node the node being visited
      * @param p a parameter value
@@ -362,14 +354,6 @@
     R visitSwitch(SwitchTree node, P p);
 
     /**
-     * Visits a SwitchExpressionTree node.
-     * @param node the node being visited
-     * @param p a parameter value
-     * @return a result value
-     */
-    R visitSwitchExpression(SwitchExpressionTree node, P p);
-
-    /**
      * Visits a SynchronizedTree node.
      * @param node the node being visited
      * @param p a parameter value
--- a/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java	Mon Feb 12 16:49:27 2018 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java	Thu Feb 15 17:44:00 2018 +0100
@@ -271,18 +271,6 @@
      * @return  the result of {@code defaultAction}
      */
     @Override
-    public R visitSwitchExpression(SwitchExpressionTree node, P p) {
-        return defaultAction(node, p);
-    }
-
-    /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
-     *
-     * @param node {@inheritDoc}
-     * @param p {@inheritDoc}
-     * @return  the result of {@code defaultAction}
-     */
-    @Override
     public R visitCase(CaseTree node, P p) {
         return defaultAction(node, p);
     }
@@ -295,18 +283,6 @@
      * @return  the result of {@code defaultAction}
      */
     @Override
-    public R visitCaseExpression(CaseExpressionTree node, P p) {
-        return defaultAction(node, p);
-    }
-
-    /**
-     * {@inheritDoc} This implementation calls {@code defaultAction}.
-     *
-     * @param node {@inheritDoc}
-     * @param p {@inheritDoc}
-     * @return  the result of {@code defaultAction}
-     */
-    @Override
     public R visitSynchronized(SynchronizedTree node, P p) {
         return defaultAction(node, p);
     }
--- a/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java	Mon Feb 12 16:49:27 2018 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java	Thu Feb 15 17:44:00 2018 +0100
@@ -341,37 +341,9 @@
      * @return the result of scanning
      */
     @Override
-    public R visitSwitchExpression(SwitchExpressionTree node, P p) {
-        R r = scan(node.getExpression(), p);
-        r = scanAndReduce(node.getCases(), p, r);
-        return r;
-    }
-
-    /**
-     * {@inheritDoc} This implementation scans the children in left to right order.
-     *
-     * @param node  {@inheritDoc}
-     * @param p  {@inheritDoc}
-     * @return the result of scanning
-     */
-    @Override
     public R visitCase(CaseTree node, P p) {
         R r = scan(node.getExpression(), p);
         r = scanAndReduce(node.getStatements(), p, r);
-        return r;
-    }
-
-    /**
-     * {@inheritDoc} This implementation scans the children in left to right order.
-     *
-     * @param node  {@inheritDoc}
-     * @param p  {@inheritDoc}
-     * @return the result of scanning
-     */
-    @Override
-    public R visitCaseExpression(CaseExpressionTree node, P p) {
-        R r = scan(node.getExpression(), p);
-        r = scanAndReduce(node.getStatements(), p, r);
         r = scanAndReduce(node.getValue(), p, r);
         return r;
     }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ArgumentAttr.java	Mon Feb 12 16:49:27 2018 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ArgumentAttr.java	Thu Feb 15 17:44:00 2018 +0100
@@ -77,7 +77,7 @@
 import static com.sun.tools.javac.code.TypeTag.VOID;
 import com.sun.tools.javac.comp.DeferredAttr.SwitchExpressionScanner;
 import com.sun.tools.javac.tree.JCTree.JCBreak;
-import com.sun.tools.javac.tree.JCTree.JCCaseExpression;
+import com.sun.tools.javac.tree.JCTree.JCCase;
 import com.sun.tools.javac.tree.JCTree.JCSwitchExpression;
 
 /**
@@ -491,14 +491,8 @@
                 return attr.types.createErrorType(resultInfo.pt);
             } else {
                 //poly
-                for (JCCaseExpression c : speculativeTree.cases) {
-                    if (c.stats != null) {
-                        for (JCBreak brk : breakExpressions()) {
-                            checkSpeculative(brk.value, brk.value.type, resultInfo);
-                        }
-                    } else {
-                        checkSpeculative(c.value, localInfo);
-                    }
+                for (JCBreak brk : breakExpressions()) {
+                    checkSpeculative(brk.value, brk.value.type, resultInfo);
                 }
                 return localInfo.pt;
             }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Feb 12 16:49:27 2018 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Feb 15 17:44:00 2018 +0100
@@ -26,6 +26,7 @@
 package com.sun.tools.javac.comp;
 
 import java.util.*;
+import java.util.function.BiConsumer;
 import java.util.function.BiFunction;
 import java.util.function.Function;
 
@@ -1394,9 +1395,8 @@
     }
 
     public void visitSwitch(JCSwitch tree) {
-        handleSwitch(tree, tree.selector, tree.cases, c -> c.pat, (c, caseEnv) -> {
+        handleSwitch(tree, tree.selector, tree.cases, (c, caseEnv) -> {
             attribStats(c.stats, caseEnv);
-            return c.stats;
         });
         result = null;
     }
@@ -1421,27 +1421,21 @@
 
         ListBuffer<Type> caseTypes = new ListBuffer<>();
 
-        handleSwitch(tree, tree.selector, tree.cases, c -> c.pat, (c, caseEnv) -> {
-            if (c.stats != null) {
-                caseEnv.info.breakResult = condInfo;
-                attribStats(c.stats, caseEnv);
-                new TreeScanner() {
-                    @Override
-                    public void visitBreak(JCBreak brk) {
-                        if (brk.target == tree)
-                            caseTypes.append(brk.value != null ? brk.value.type : syms.errType);
-                        super.visitBreak(brk);
-                    }
-
-                    @Override public void visitClassDef(JCClassDecl tree) {}
-                    @Override public void visitLambda(JCLambda tree) {}
-                    @Override public void visitMethodDef(JCMethodDecl tree) {}
-                }.scan(c.stats);
-                return c.stats;
-            } else {
-                caseTypes.append(attribExpr(c.value, caseEnv, condInfo));
-                return List.nil();
-            }
+        handleSwitch(tree, tree.selector, tree.cases, (c, caseEnv) -> {
+            caseEnv.info.breakResult = condInfo;
+            attribStats(c.stats, caseEnv);
+            new TreeScanner() {
+                @Override
+                public void visitBreak(JCBreak brk) {
+                    if (brk.target == tree)
+                        caseTypes.append(brk.value != null ? brk.value.type : syms.errType);
+                    super.visitBreak(brk);
+                }
+
+                @Override public void visitClassDef(JCClassDecl tree) {}
+                @Override public void visitLambda(JCLambda tree) {}
+                @Override public void visitMethodDef(JCMethodDecl tree) {}
+            }.scan(c.stats);
         });
 
         Type owntype = (tree.polyKind == PolyKind.STANDALONE) ? condType(tree, caseTypes.toList()) : pt();
@@ -1449,11 +1443,10 @@
         result = tree.type = check(tree, owntype, KindSelector.VAL, resultInfo);
     }
 
-    private <Z extends JCTree> void handleSwitch(JCTree switchTree,
-                                                 JCExpression selector,
-                                                 List<Z> cases,
-                                                 Function<Z, JCExpression> patternGetter,
-                                                 BiFunction<Z, Env<AttrContext>, List<JCStatement>> attribCase) {
+    private void handleSwitch(JCTree switchTree,
+                              JCExpression selector,
+                              List<JCCase> cases,
+                              BiConsumer<JCCase, Env<AttrContext>> attribCase) {
         Type seltype = attribExpr(selector, env);
 
         Env<AttrContext> switchEnv =
@@ -1476,9 +1469,9 @@
             // check that there are no duplicate case labels or default clauses.
             Set<Object> labels = new HashSet<>(); // The set of case labels.
             boolean hasDefault = false;      // Is there a default label?
-            for (List<Z> l = cases; l.nonEmpty(); l = l.tail) {
-                Z c = l.head;
-                JCExpression pat = patternGetter.apply(c);
+            for (List<JCCase> l = cases; l.nonEmpty(); l = l.tail) {
+                JCCase c = l.head;
+                JCExpression pat = c.pat;
                 if (pat != null) {
                     if (TreeInfo.isNull(pat)) {
                         //case null:
@@ -1514,12 +1507,11 @@
                 }
                 Env<AttrContext> caseEnv =
                     switchEnv.dup(c, env.info.dup(switchEnv.info.scope.dup()));
-                List<JCStatement> stats = List.nil();
                 try {
-                    stats = attribCase.apply(c, caseEnv);
+                    attribCase.accept(c, caseEnv);
                 } finally {
                     caseEnv.info.scope.leave();
-                    addVars(stats, switchEnv.info.scope);
+                    addVars(c.stats, switchEnv.info.scope);
                 }
             }
         } finally {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java	Mon Feb 12 16:49:27 2018 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java	Thu Feb 15 17:44:00 2018 +0100
@@ -637,9 +637,9 @@
             }
             boolean hasDefault = false;
             boolean prevAlive = alive;
-            for (List<JCCaseExpression> l = tree.cases; l.nonEmpty(); l = l.tail) {
+            for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
                 alive = true;
-                JCCaseExpression c = l.head;
+                JCCase c = l.head;
                 if (c.pat == null)
                     hasDefault = true;
                 else {
@@ -648,10 +648,7 @@
                         constants.remove(((JCIdent) c.pat).name);
                     }
                 }
-                if (c.stats != null)
-                    scanStats(c.stats);
-                if (c.value != null)
-                    scanStat(c.value);
+                scanStats(c.stats);
             }
             if ((constants == null || !constants.isEmpty()) && !hasDefault) {
                 log.error(tree, Errors.NotExhaustive);
@@ -1087,26 +1084,20 @@
         }
 
         public void visitSwitch(JCSwitch tree) {
-            ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
-            pendingExits = new ListBuffer<>();
-            scan(tree.selector);
-            for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
-                JCCase c = l.head;
-                if (c.pat != null) {
-                    scan(c.pat);
-                }
-                scan(c.stats);
-            }
-            resolveBreaks(tree, prevPendingExits);
+            handleSwitch(tree, tree.selector, tree.cases);
         }
 
         @Override
         public void visitSwitchExpression(JCSwitchExpression tree) {
+            handleSwitch(tree, tree.selector, tree.cases);
+        }
+
+        private void handleSwitch(JCTree tree, JCExpression selector, List<JCCase> cases) {
             ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
             pendingExits = new ListBuffer<>();
-            scan(tree.selector);
-            for (List<JCCaseExpression> l = tree.cases; l.nonEmpty(); l = l.tail) {
-                JCCaseExpression c = l.head;
+            scan(selector);
+            for (List<JCCase> l = cases; l.nonEmpty(); l = l.tail) {
+                JCCase c = l.head;
                 if (c.pat != null) {
                     scan(c.pat);
                 }
@@ -2172,14 +2163,22 @@
         }
 
         public void visitSwitch(JCSwitch tree) {
+            handleSwitch(tree, tree.selector, tree.cases);
+        }
+
+        public void visitSwitchExpression(JCSwitchExpression tree) {
+            handleSwitch(tree, tree.selector, tree.cases);
+        }
+
+        private void handleSwitch(JCTree tree, JCExpression selector, List<JCCase> cases) {
             ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
             pendingExits = new ListBuffer<>();
             int nextadrPrev = nextadr;
-            scanExpr(tree.selector);
+            scanExpr(selector);
             final Bits initsSwitch = new Bits(inits);
             final Bits uninitsSwitch = new Bits(uninits);
             boolean hasDefault = false;
-            for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
+            for (List<JCCase> l = cases; l.nonEmpty(); l = l.tail) {
                 inits.assign(initsSwitch);
                 uninits.assign(uninits.andSet(uninitsSwitch));
                 JCCase c = l.head;
@@ -2206,46 +2205,6 @@
             resolveBreaks(tree, prevPendingExits);
             nextadr = nextadrPrev;
         }
-
-        public void visitSwitchExpression(JCSwitchExpression tree) {
-            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
-            pendingExits = new ListBuffer<>();
-            int nextadrPrev = nextadr;
-            scanExpr(tree.selector);
-            final Bits initsSwitch = new Bits(inits);
-            final Bits uninitsSwitch = new Bits(uninits);
-            boolean hasDefault = false;
-            for (List<JCCaseExpression> l = tree.cases; l.nonEmpty(); l = l.tail) {
-                inits.assign(initsSwitch);
-                uninits.assign(uninits.andSet(uninitsSwitch));
-                JCCaseExpression c = l.head;
-                if (c.pat == null) {
-                    hasDefault = true;
-                } else {
-                    scanExpr(c.pat);
-                }
-                if (hasDefault) {
-                    inits.assign(initsSwitch);
-                    uninits.assign(uninits.andSet(uninitsSwitch));
-                }
-                if (c.stats != null) {
-                    scan(c.stats);
-                    addVars(c.stats, initsSwitch, uninitsSwitch);
-                } else {
-                    scan(c.value);
-                }
-                if (!hasDefault) {
-                    inits.assign(initsSwitch);
-                    uninits.assign(uninits.andSet(uninitsSwitch));
-                }
-                // Warn about fall-through if lint switch fallthrough enabled.
-            }
-            if (!hasDefault) {
-                inits.andSet(initsSwitch);
-            }
-            resolveBreaks(tree, prevPendingExits);
-            nextadr = nextadrPrev;
-        }
         // where
             /** Add any variables defined in stats to inits and uninits. */
             private void addVars(List<JCStatement> stats, final Bits inits,
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Mon Feb 12 16:49:27 2018 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java	Thu Feb 15 17:44:00 2018 +0100
@@ -71,6 +71,7 @@
 import javax.lang.model.type.TypeKind;
 
 import com.sun.tools.javac.main.Option;
+import com.sun.tools.javac.tree.JCTree.JCCase.CaseKind;
 
 /**
  * This pass desugars lambda expressions into static methods
@@ -655,7 +656,7 @@
             JCBreak br = make.Break(null);
             breaks.add(br);
             List<JCStatement> stmts = entry.getValue().append(br).toList();
-            cases.add(make.Case(make.Literal(entry.getKey()), stmts));
+            cases.add(make.Case(make.Literal(entry.getKey()), stmts, CaseKind.STATEMENTS));
         }
         JCSwitch sw = make.Switch(deserGetter("getImplMethodName", syms.stringType), cases.toList());
         for (JCBreak br : breaks) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Mon Feb 12 16:49:27 2018 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Thu Feb 15 17:44:00 2018 +0100
@@ -56,6 +56,7 @@
 import static com.sun.tools.javac.code.Kinds.Kind.*;
 import static com.sun.tools.javac.code.Symbol.OperatorSymbol.AccessCode.DEREF;
 import static com.sun.tools.javac.jvm.ByteCodes.*;
+import com.sun.tools.javac.tree.JCTree.JCCase.CaseKind;
 import static com.sun.tools.javac.tree.JCTree.JCOperatorExpression.OperandPos.LEFT;
 import static com.sun.tools.javac.tree.JCTree.Tag.*;
 
@@ -3471,7 +3472,7 @@
             
             if (!hasNullCase(tree)) {
                 JCThrow npe = make.Throw(makeNewClass(syms.nullPointerExceptionType, List.nil()));
-                tree.cases = tree.cases.prepend(make.Case(makeNull(), List.of(npe)));
+                tree.cases = tree.cases.prepend(make.Case(makeNull(), List.of(npe), CaseKind.STATEMENTS));
             }
 
             tree.cases.head.pat = make.Literal(-1);
@@ -3594,7 +3595,7 @@
             if (c.pat != null) {
                 VarSymbol label = (VarSymbol)TreeInfo.symbol(c.pat);
                 JCLiteral pat = TreeInfo.isNull(c.pat) ? make.Literal(-1) : map.forConstant(label);
-                cases.append(make.Case(pat, c.stats));
+                cases.append(make.Case(pat, c.stats, CaseKind.STATEMENTS));
             } else {
                 cases.append(c);
             }
@@ -3756,7 +3757,7 @@
                 breakStmt.target = switch1;
                 lb.append(elsepart).append(breakStmt);
 
-                caseBuffer.append(make.Case(make.Literal(hashCode), lb.toList()));
+                caseBuffer.append(make.Case(make.Literal(hashCode), lb.toList(), CaseKind.STATEMENTS));
             }
 
             switch1.cases = caseBuffer.toList();
@@ -3802,7 +3803,8 @@
                 }
 
                 lb.append(make.Case(caseExpr,
-                                    oneCase.getStatements()));
+                                    oneCase.getStatements(),
+                                    CaseKind.STATEMENTS));
 
                 casePosition2++;
             }
@@ -3884,7 +3886,8 @@
                 caseBuffer.append(make.Case(entry.getKey(), List.of(
                                             make.Exec(make.Assign(make.Ident(dollar_tmp),
                                                                   make.Literal(entry.getValue()))
-                                                          . setType(dollar_tmp.type)))));
+                                                          . setType(dollar_tmp.type))),
+                                            CaseKind.STATEMENTS));
             }
 
             switch1.cases = caseBuffer.toList();
@@ -3923,7 +3926,8 @@
                 }
 
                 lb.append(make.Case(caseExpr,
-                                    oneCase.getStatements()));
+                                    oneCase.getStatements(),
+                                    CaseKind.STATEMENTS));
 
                 casePosition2++;
             }
@@ -4013,49 +4017,42 @@
         switchStatement.cases = tree.cases.stream().map(c -> convertCase(dollar_switchexpr, switchStatement, tree, c)).collect(List.collector());
         if (tree.cases.stream().noneMatch(c -> c.pat == null)) {
             JCThrow thr = make.Throw(makeNewClass(syms.incompatibleClassChangeErrorType, List.nil()));
-            switchStatement.cases = switchStatement.cases.append(make.Case(null, List.of(thr)));
+            switchStatement.cases = switchStatement.cases.append(make.Case(null, List.of(thr), CaseKind.STATEMENTS));
         }
         stmtList.append(translate(switchStatement));
 
         result = make.LetExpr(stmtList.toList(), make.Ident(dollar_switchexpr)).setType(dollar_switchexpr.type);
     }
         //where:
-        private JCCase convertCase(VarSymbol dollar_switchexpr, JCSwitch switchStatement, JCSwitchExpression switchExpr, JCCaseExpression c) {
+        private JCCase convertCase(VarSymbol dollar_switchexpr, JCSwitch switchStatement, JCSwitchExpression switchExpr, JCCase c) {
             make.at(c.pos());
             ListBuffer<JCStatement> statements = new ListBuffer<>();
-            if (c.stats != null) {
-                statements.addAll(new TreeTranslator() {
-                    @Override
-                    public void visitLambda(JCLambda tree) {}
-                    @Override
-                    public void visitClassDef(JCClassDecl tree) {}
-                    @Override
-                    public void visitMethodDef(JCMethodDecl tree) {}
-                    @SuppressWarnings("unchecked")
-                    public <T extends JCTree> List<T> translate(List<T> trees) {
-                        if (trees == null) return null;
-                        ListBuffer<T> result = new ListBuffer<>();
-                        for (List<T> l = trees; l.nonEmpty(); l = l.tail) {
-                            if (l.head.hasTag(BREAK) && ((JCBreak) l.head).target == switchExpr) {
-                                JCBreak tree = (JCBreak) l.head;
-                                tree.target = switchStatement;
-                                result.append((T) make.Exec(make.Assign(make.Ident(dollar_switchexpr), translate(tree.value)).setType(dollar_switchexpr.type)));
-                                result.append((T) tree);
-                                tree.value = null;
-                            } else {
-                                result.append(translate(l.head));
-                            }
+            statements.addAll(new TreeTranslator() {
+                @Override
+                public void visitLambda(JCLambda tree) {}
+                @Override
+                public void visitClassDef(JCClassDecl tree) {}
+                @Override
+                public void visitMethodDef(JCMethodDecl tree) {}
+                @SuppressWarnings("unchecked")
+                public <T extends JCTree> List<T> translate(List<T> trees) {
+                    if (trees == null) return null;
+                    ListBuffer<T> result = new ListBuffer<>();
+                    for (List<T> l = trees; l.nonEmpty(); l = l.tail) {
+                        if (l.head.hasTag(BREAK) && ((JCBreak) l.head).target == switchExpr) {
+                            JCBreak tree = (JCBreak) l.head;
+                            tree.target = switchStatement;
+                            result.append((T) make.Exec(make.Assign(make.Ident(dollar_switchexpr), translate(tree.value)).setType(dollar_switchexpr.type)));
+                            result.append((T) tree);
+                            tree.value = null;
+                        } else {
+                            result.append(translate(l.head));
                         }
-                        return result.toList();
                     }
-                }.translate(c.stats));
-            } else {
-                statements.add(make.Exec(make.Assign(make.Ident(dollar_switchexpr), c.value).setType(dollar_switchexpr.type)));
-                JCBreak brk = make.Break(null);
-                brk.target = switchStatement;
-                statements.add(brk);
-            }
-            return make.Case(c.pat, statements.toList());
+                    return result.toList();
+                }
+            }.translate(c.stats));
+            return make.Case(c.pat, statements.toList(), CaseKind.STATEMENTS);
         }
 
     public void visitNewArray(JCNewArray tree) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java	Mon Feb 12 16:49:27 2018 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java	Thu Feb 15 17:44:00 2018 +0100
@@ -627,13 +627,6 @@
         result = tree;
     }
 
-    public void visitCaseExpression(JCCaseExpression tree) {
-        tree.pat = translate(tree.pat, null);
-        tree.stats = translate(tree.stats);
-        tree.value = translate(tree.value);
-        result = tree;
-    }
-
     public void visitSynchronized(JCSynchronized tree) {
         tree.lock = translate(tree.lock, erasure(tree.lock.type));
         tree.body = translate(tree.body);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Mon Feb 12 16:49:27 2018 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Thu Feb 15 17:44:00 2018 +0100
@@ -57,6 +57,7 @@
 import static com.sun.tools.javac.parser.Tokens.TokenKind.GT;
 import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT;
 import static com.sun.tools.javac.parser.Tokens.TokenKind.LT;
+import com.sun.tools.javac.tree.JCTree.JCCase.CaseKind;
 import static com.sun.tools.javac.tree.JCTree.Tag.*;
 
 /** The parser maps a token sequence into an abstract syntax
@@ -1358,17 +1359,17 @@
             nextToken();
             JCExpression selector = parExpression();
             accept(LBRACE);
-            ListBuffer<JCCaseExpression> caseExprs = new ListBuffer<>();
+            ListBuffer<JCCase> cases = new ListBuffer<>();
             while (true) {
                 pos = token.pos;
                 switch (token.kind) {
                 case CASE:
                 case DEFAULT:
-                    caseExprs.appendList(switchExpressionStatementGroup());
+                    cases.appendList(switchExpressionStatementGroup());
                     break;
                 case RBRACE: case EOF:
                     JCSwitchExpression e = to(F.at(switchPos).SwitchExpression(selector,
-                                                                               caseExprs.toList()));
+                                                                               cases.toList()));
                     accept(RBRACE);
                     return e;
                 default:
@@ -1382,8 +1383,8 @@
         return term3Rest(t, typeArgs);
     }
 
-    private List<JCCaseExpression> switchExpressionStatementGroup() {
-        ListBuffer<JCCaseExpression> caseExprs = new ListBuffer<>();
+    private List<JCCase> switchExpressionStatementGroup() {
+        ListBuffer<JCCase> caseExprs = new ListBuffer<>();
         int casePos = token.pos;
         JCExpression pat;
 
@@ -1396,28 +1397,32 @@
                 pat = term(EXPR | NOLAMBDA);
                 if (token.kind != COMMA) break;
                 nextToken();
-                caseExprs.append(toP(F.at(casePos).CaseExpression(pat, List.nil(), null)));
+                caseExprs.append(toP(F.at(casePos).Case(pat, List.nil(), CaseKind.STATEMENTS)));
             };
         }
-        JCExpression value = null;
         List<JCStatement> stats = null;
+        CaseKind kind;
         switch (token.kind) {
             case ARROW:
                 nextToken();
                 if (token.kind == TokenKind.THROW) {
                     //TODO: record the arrow used?
                     stats = List.of(parseStatement());
+                    kind = CaseKind.STATEMENTS;
                 } else {
-                    value = parseExpression();
+                    JCExpression value = parseExpression();
+                    stats = List.of(to(F.at(value).Break(value)));
+                    kind = CaseKind.VALUE;
                     accept(SEMI);
                 }
                 break;
             default:
                 accept(COLON);
                 stats = blockStatements();
+                kind = CaseKind.STATEMENTS;
                 break;
         }
-        caseExprs.append(toP(F.at(casePos).CaseExpression(pat, stats, value)));
+        caseExprs.append(toP(F.at(casePos).Case(pat, stats, kind)));
         return caseExprs.toList();
     }
 
@@ -2722,13 +2727,13 @@
                 pat = parseExpression();
                 if (token.kind != COMMA) break;
                 nextToken();
-                c = F.at(pos).Case(pat, List.nil());
+                c = F.at(pos).Case(pat, List.nil(), CaseKind.STATEMENTS);
                 storeEnd(c, S.prevToken().endPos);
                 cases.append(c);
             };
             accept(COLON);
             stats = blockStatements();
-            c = F.at(pos).Case(pat, stats);
+            c = F.at(pos).Case(pat, stats, CaseKind.STATEMENTS);
             if (stats.isEmpty())
                 storeEnd(c, S.prevToken().endPos);
             return cases.append(c).toList();
@@ -2736,7 +2741,7 @@
             nextToken();
             accept(COLON);
             stats = blockStatements();
-            c = F.at(pos).Case(null, stats);
+            c = F.at(pos).Case(null, stats, CaseKind.STATEMENTS);
             if (stats.isEmpty())
                 storeEnd(c, S.prevToken().endPos);
             return cases.append(c).toList();
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java	Mon Feb 12 16:49:27 2018 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java	Thu Feb 15 17:44:00 2018 +0100
@@ -51,6 +51,7 @@
 import com.sun.tools.javac.code.Directive.ExportsDirective;
 import com.sun.tools.javac.code.Directive.OpensDirective;
 import com.sun.tools.javac.code.Type.ModuleType;
+import com.sun.tools.javac.tree.JCTree.JCCase.CaseKind;
 import com.sun.tools.javac.tree.JCTree.JCPolyExpression.PolyKind;
 
 /**
@@ -1253,9 +1254,11 @@
     public static class JCCase extends JCStatement implements CaseTree {
         public JCExpression pat;
         public List<JCStatement> stats;
-        protected JCCase(JCExpression pat, List<JCStatement> stats) {
+        public final CaseKind kind;
+        protected JCCase(JCExpression pat, List<JCStatement> stats, CaseKind kind) {
             this.pat = pat;
             this.stats = stats;
+            this.kind = kind;
         }
         @Override
         public void accept(Visitor v) { v.visitCase(this); }
@@ -1265,7 +1268,9 @@
         @DefinedBy(Api.COMPILER_TREE)
         public JCExpression getExpression() { return pat; }
         @DefinedBy(Api.COMPILER_TREE)
-        public List<JCStatement> getStatements() { return stats; }
+        public List<JCStatement> getStatements() { return kind == CaseKind.STATEMENTS ? stats : null; }
+        @DefinedBy(Api.COMPILER_TREE)
+        public JCExpression getValue() { return kind == CaseKind.VALUE ? ((JCBreak) stats.head).value : null; }
         @Override @DefinedBy(Api.COMPILER_TREE)
         public <R,D> R accept(TreeVisitor<R,D> v, D d) {
             return v.visitCase(this, d);
@@ -1274,15 +1279,19 @@
         public Tag getTag() {
             return CASE;
         }
+        public enum CaseKind {
+            STATEMENTS,
+            VALUE;
+        }
     }
 
     /**
      * A "switch ( ) { }" construction.
      */
-    public static class JCSwitchExpression extends JCPolyExpression implements SwitchExpressionTree {
+    public static class JCSwitchExpression extends JCPolyExpression implements SwitchTree {
         public JCExpression selector;
-        public List<JCCaseExpression> cases;
-        protected JCSwitchExpression(JCExpression selector, List<JCCaseExpression> cases) {
+        public List<JCCase> cases;
+        protected JCSwitchExpression(JCExpression selector, List<JCCase> cases) {
             this.selector = selector;
             this.cases = cases;
         }
@@ -1290,14 +1299,14 @@
         public void accept(Visitor v) { v.visitSwitchExpression(this); }
 
         @DefinedBy(Api.COMPILER_TREE)
-        public Kind getKind() { return Kind.SWITCH_EXPRESSION; }
+        public Kind getKind() { return Kind.SWITCH; }
         @DefinedBy(Api.COMPILER_TREE)
         public JCExpression getExpression() { return selector; }
         @DefinedBy(Api.COMPILER_TREE)
-        public List<JCCaseExpression> getCases() { return cases; }
+        public List<JCCase> getCases() { return cases; }
         @Override @DefinedBy(Api.COMPILER_TREE)
         public <R,D> R accept(TreeVisitor<R,D> v, D d) {
-            return v.visitSwitchExpression(this, d);
+            return v.visitSwitch(this, d);
         }
         @Override
         public Tag getTag() {
@@ -1306,41 +1315,6 @@
     }
 
     /**
-     * A "case  :" of a switch.
-     */
-    public static class JCCaseExpression extends JCExpression implements CaseExpressionTree {
-        public JCExpression pat;
-        public List<JCStatement> stats;
-        public JCExpression value;
-        protected JCCaseExpression(JCExpression pat, List<JCStatement> stats, JCExpression value) {
-            this.pat = pat;
-            this.stats = stats;
-            this.value = value;
-        }
-        @Override
-        public void accept(Visitor v) { v.visitCaseExpression(this); }
-
-        @DefinedBy(Api.COMPILER_TREE)
-        public Kind getKind() { return Kind.CASE_EXPRESSION; }
-        @DefinedBy(Api.COMPILER_TREE)
-        public JCExpression getExpression() { return pat; }
-        @DefinedBy(Api.COMPILER_TREE)
-        public List<JCStatement> getStatements() { return stats; }
-        @DefinedBy(Api.COMPILER_TREE)
-        public JCExpression getValue() { return value; }
-        @Override @DefinedBy(Api.COMPILER_TREE)
-        public <R,D> R accept(TreeVisitor<R,D> v, D d) {
-            return v.visitCaseExpression(this, d);
-        }
-        @Override
-        public Tag getTag() {
-            return CASE_EXPRESSIOM;
-        }
-    }
-
-
-
-    /**
      * A synchronized block.
      */
     public static class JCSynchronized extends JCStatement implements SynchronizedTree {
@@ -3079,7 +3053,7 @@
         JCEnhancedForLoop ForeachLoop(JCVariableDecl var, JCExpression expr, JCStatement body);
         JCLabeledStatement Labelled(Name label, JCStatement body);
         JCSwitch Switch(JCExpression selector, List<JCCase> cases);
-        JCCase Case(JCExpression pat, List<JCStatement> stats);
+        JCCase Case(JCExpression pat, List<JCStatement> stats, CaseKind kind);
         JCSynchronized Synchronized(JCExpression lock, JCBlock body);
         JCTry Try(JCBlock body, List<JCCatch> catchers, JCBlock finalizer);
         JCTry Try(List<JCTree> resources,
@@ -3156,7 +3130,6 @@
         public void visitSwitch(JCSwitch that)               { visitTree(that); }
         public void visitCase(JCCase that)                   { visitTree(that); }
         public void visitSwitchExpression(JCSwitchExpression that)               { visitTree(that); }
-        public void visitCaseExpression(JCCaseExpression that)                   { visitTree(that); }
         public void visitSynchronized(JCSynchronized that)   { visitTree(that); }
         public void visitTry(JCTry that)                     { visitTree(that); }
         public void visitCatch(JCCatch that)                 { visitTree(that); }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java	Mon Feb 12 16:49:27 2018 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java	Thu Feb 15 17:44:00 2018 +0100
@@ -841,7 +841,7 @@
                 print("case ");
                 printExpr(tree.pat);
             }
-            print(": ");
+            print(": "); //XXX
             println();
             indent();
             printStats(tree.stats);
@@ -872,30 +872,6 @@
         }
     }
 
-    public void visitCaseExpression(JCCaseExpression tree) {
-        try {
-            if (tree.pat == null) {
-                print("default");
-            } else {
-                print("case ");
-                printExpr(tree.pat);
-            }
-            if (tree.stats != null) {
-                print(":");
-                println();
-                indent();
-                printStats(tree.stats);
-                undent();
-            } else {
-                print(" -> ");
-                printExpr(tree.value);
-            }
-            align();
-        } catch (IOException e) {
-            throw new UncheckedIOException(e);
-        }
-    }
-
     public void visitSynchronized(JCSynchronized tree) {
         try {
             print("synchronized ");
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java	Mon Feb 12 16:49:27 2018 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java	Thu Feb 15 17:44:00 2018 +0100
@@ -149,16 +149,7 @@
         JCCase t = (JCCase) node;
         JCExpression pat = copy(t.pat, p);
         List<JCStatement> stats = copy(t.stats, p);
-        return M.at(t.pos).Case(pat, stats);
-    }
-
-    @DefinedBy(Api.COMPILER_TREE)
-    public JCTree visitCaseExpression(CaseExpressionTree node, P p) {
-        JCCaseExpression t = (JCCaseExpression) node;
-        JCExpression pat = copy(t.pat, p);
-        List<JCStatement> stats = copy(t.stats, p);
-        JCExpression value = copy(t.value, p);
-        return M.at(t.pos).CaseExpression(pat, stats, value);
+        return M.at(t.pos).Case(pat, stats, t.kind);
     }
 
     @DefinedBy(Api.COMPILER_TREE)
@@ -374,18 +365,17 @@
 
     @DefinedBy(Api.COMPILER_TREE)
     public JCTree visitSwitch(SwitchTree node, P p) {
-        JCSwitch t = (JCSwitch) node;
-        JCExpression selector = copy(t.selector, p);
-        List<JCCase> cases = copy(t.cases, p);
-        return M.at(t.pos).Switch(selector, cases);
-    }
-
-    @DefinedBy(Api.COMPILER_TREE)
-    public JCTree visitSwitchExpression(SwitchExpressionTree node, P p) {
-        JCSwitchExpression t = (JCSwitchExpression) node;
-        JCExpression selector = copy(t.selector, p);
-        List<JCCaseExpression> cases = copy(t.cases, p);
-        return M.at(t.pos).SwitchExpression(selector, cases);
+        if (node instanceof JCSwitch) {
+            JCSwitch t = (JCSwitch) node;
+            JCExpression selector = copy(t.selector, p);
+            List<JCCase> cases = copy(t.cases, p);
+            return M.at(t.pos).Switch(selector, cases);
+        } else {
+            JCSwitchExpression t = (JCSwitchExpression) node;
+            JCExpression selector = copy(t.selector, p);
+            List<JCCase> cases = copy(t.cases, p);
+            return M.at(t.pos).SwitchExpression(selector, cases);
+        }
     }
 
     @DefinedBy(Api.COMPILER_TREE)
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java	Mon Feb 12 16:49:27 2018 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java	Thu Feb 15 17:44:00 2018 +0100
@@ -40,6 +40,7 @@
 import static com.sun.tools.javac.code.Flags.*;
 import static com.sun.tools.javac.code.Kinds.Kind.*;
 import static com.sun.tools.javac.code.TypeTag.*;
+import com.sun.tools.javac.tree.JCTree.JCCase.CaseKind;
 
 /** Factory class for trees.
  *
@@ -272,24 +273,18 @@
         return tree;
     }
 
-    public JCCase Case(JCExpression pat, List<JCStatement> stats) {
-        JCCase tree = new JCCase(pat, stats);
+    public JCCase Case(JCExpression pat, List<JCStatement> stats, CaseKind kind) {
+        JCCase tree = new JCCase(pat, stats, kind);
         tree.pos = pos;
         return tree;
     }
 
-    public JCSwitchExpression SwitchExpression(JCExpression selector, List<JCCaseExpression> cases) {
+    public JCSwitchExpression SwitchExpression(JCExpression selector, List<JCCase> cases) {
         JCSwitchExpression tree = new JCSwitchExpression(selector, cases);
         tree.pos = pos;
         return tree;
     }
 
-    public JCCaseExpression CaseExpression(JCExpression pat, List<JCStatement> stats, JCExpression value) {
-        JCCaseExpression tree = new JCCaseExpression(pat, stats, value);
-        tree.pos = pos;
-        return tree;
-    }
-
     public JCSynchronized Synchronized(JCExpression lock, JCBlock body) {
         JCSynchronized tree = new JCSynchronized(lock, body);
         tree.pos = pos;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java	Mon Feb 12 16:49:27 2018 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java	Thu Feb 15 17:44:00 2018 +0100
@@ -185,12 +185,6 @@
         scan(tree.cases);
     }
 
-    public void visitCaseExpression(JCCaseExpression tree) {
-        scan(tree.pat);
-        scan(tree.stats);
-        scan(tree.value);
-    }
-
     public void visitSynchronized(JCSynchronized tree) {
         scan(tree.lock);
         scan(tree.body);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeTranslator.java	Mon Feb 12 16:49:27 2018 +0100
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeTranslator.java	Thu Feb 15 17:44:00 2018 +0100
@@ -95,14 +95,6 @@
         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) {
@@ -222,14 +214,7 @@
 
     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);
+        tree.cases = translateCases(tree.cases);
         result = tree;
     }
 
--- a/test/langtools/tools/javac/tree/SourceTreeScannerTest.java	Mon Feb 12 16:49:27 2018 +0100
+++ b/test/langtools/tools/javac/tree/SourceTreeScannerTest.java	Thu Feb 15 17:44:00 2018 +0100
@@ -47,11 +47,14 @@
 import java.io.*;
 import java.lang.reflect.*;
 import java.util.*;
+
 import javax.tools.*;
 
 import com.sun.source.tree.Tree;
 import com.sun.source.util.TreeScanner;
 import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCCase;
+import com.sun.tools.javac.tree.JCTree.JCCase.CaseKind;
 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
 import com.sun.tools.javac.tree.JCTree.JCModuleDecl;
 import com.sun.tools.javac.tree.JCTree.TypeBoundKind;
@@ -150,6 +153,9 @@
                             // The modifiers will not found by TreeScanner,
                             // but the embedded annotations will be.
                             reflectiveScan(((JCModuleDecl) tree).mods.annotations);
+                        } else if (tree instanceof JCCase && f.getName().equals("stats") &&
+                                   ((JCCase) tree).kind == CaseKind.VALUE) {
+                            reflectiveScan(((JCCase) tree).getValue());
                         } else {
                             reflectiveScan(f.get(tree));
                         }