OpenJDK / amber / amber
changeset 52915:2cb2cae03443 patterns
Merging patterns-stage-1 branch into the patterns branch.
line wrap: on
line diff
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/BindingPatternTree.java Wed Oct 17 13:56:45 2018 +0200 +++ b/src/jdk.compiler/share/classes/com/sun/source/tree/BindingPatternTree.java Wed Oct 24 17:25:26 2018 +0200 @@ -25,6 +25,8 @@ package com.sun.source.tree; +import javax.lang.model.element.Name; + /** * A binding pattern tree */ @@ -36,5 +38,11 @@ */ Tree getType(); + /** + * A binding variable name. + * @return something + */ + Name getBinding(); + }
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/InstanceOfTree.java Wed Oct 17 13:56:45 2018 +0200 +++ b/src/jdk.compiler/share/classes/com/sun/source/tree/InstanceOfTree.java Wed Oct 24 17:25:26 2018 +0200 @@ -51,4 +51,10 @@ * @return the type */ Tree getType(); + + /** + * Returns the tested pattern. + * @return the tested pattern + */ + PatternTree getPattern(); }
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/MatchesTree.java Wed Oct 17 13:56:45 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +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; - -/** - * A tree node for an {@code matches} expression. - * - * For example: - * <pre> - * <em>expression</em> matches <em>pattern</em> - * </pre> - * - */ -public interface MatchesTree extends ExpressionTree { - /** - * Returns the expression to be matched. - * @return the expression - */ - ExpressionTree getExpression(); - - /** - * Returns the pattern to match against. - * @return the pattern - */ - Tree getPattern(); -}
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/PatternTree.java Wed Oct 17 13:56:45 2018 +0200 +++ b/src/jdk.compiler/share/classes/com/sun/source/tree/PatternTree.java Wed Oct 24 17:25:26 2018 +0200 @@ -32,9 +32,4 @@ */ public interface PatternTree extends Tree { - /** - * A doc to make build happy - * @return something - */ - Name getBinding(); }
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java Wed Oct 17 13:56:45 2018 +0200 +++ b/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java Wed Oct 24 17:25:26 2018 +0200 @@ -179,11 +179,6 @@ LABELED_STATEMENT(LabeledStatementTree.class), /** - * Used for instances of {@link MatchesTree}. - */ - MATCHES(MatchesTree.class), - - /** * Used for instances of {@link MethodTree}. */ METHOD(MethodTree.class),
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java Wed Oct 17 13:56:45 2018 +0200 +++ b/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java Wed Oct 24 17:25:26 2018 +0200 @@ -258,14 +258,6 @@ R visitLiteral(LiteralTree node, P p); /** - * Visits a MatchesTree node. - * @param node the node being visited - * @param p a parameter value - * @return a result value - */ - R visitMatches(MatchesTree node, P p); - - /** * Visits an BindingPattern node. * @param node the node being visited * @param p a parameter value
--- a/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java Wed Oct 17 13:56:45 2018 +0200 +++ b/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java Wed Oct 24 17:25:26 2018 +0200 @@ -566,18 +566,6 @@ * @return the result of {@code defaultAction} */ @Override - public R visitMatches(MatchesTree 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 visitBindingPattern(BindingPatternTree node, P p) { return defaultAction(node, p); }
--- a/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java Wed Oct 17 13:56:45 2018 +0200 +++ b/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java Wed Oct 24 17:25:26 2018 +0200 @@ -677,7 +677,11 @@ @Override public R visitInstanceOf(InstanceOfTree node, P p) { R r = scan(node.getExpression(), p); - r = scanAndReduce(node.getType(), p, r); + if (node.getPattern() != null) { + r = scanAndReduce(node.getPattern(), p, r); + } else { + r = scanAndReduce(node.getType(), p, r); + } return r; } @@ -689,20 +693,6 @@ * @return the result of scanning */ @Override - public R visitMatches(MatchesTree node, P p) { - R r = scan(node.getExpression(), p); - r = scanAndReduce(node.getPattern(), p, r); - return r; - } - - /** - * {@inheritDoc} This implementation scans the children in left to right order. - * - * @param node the node being visited - * @param p a parameter value - * @return a result value - */ - @Override public R visitBindingPattern(BindingPatternTree node, P p) { return scan(node.getType(), p); }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java Wed Oct 17 13:56:45 2018 +0200 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java Wed Oct 24 17:25:26 2018 +0200 @@ -324,6 +324,11 @@ */ public static final long MATCH_BINDING = 1L<<58; + /** + * A flag to indicate a match binding variable whose scope extends after the current statement. + */ + public static final long MATCH_BINDING_TO_OUTER = 1L<<59; + /** Modifier masks. */ public static final int
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Wed Oct 17 13:56:45 2018 +0200 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Wed Oct 24 17:25:26 2018 +0200 @@ -1320,6 +1320,12 @@ public void visitDoLoop(JCDoWhileLoop tree) { attribStat(tree.body, env.dup(tree)); attribExpr(tree.cond, env, syms.booleanType); + if (!breaksOutOf(tree, tree.body)) { + List<BindingSymbol> bindings = getMatchBindings(types, log, tree.cond, false); + + bindings.forEach(env.info.scope::enter); + bindings.forEach(BindingSymbol::preserveBinding); + } result = null; } @@ -1332,9 +1338,29 @@ } finally { whileEnv.info.scope.leave(); } + if (!breaksOutOf(tree, tree.body)) { + List<BindingSymbol> bindings = getMatchBindings(types, log, tree.cond, false); + + bindings.forEach(env.info.scope::enter); + bindings.forEach(BindingSymbol::preserveBinding); + } result = null; } + private boolean breaksOutOf(JCTree loop, JCTree body) { + //TODO: should correctly reflect liveness: + boolean[] breaksOut = new boolean[1]; + new TreeScanner() { + @Override + public void visitBreak(JCBreak tree) { + breaksOut[0] |= tree.target == loop; + super.visitBreak(tree); + } + }.scan(body); + + return breaksOut[0]; + } + public void visitForLoop(JCForLoop tree) { Env<AttrContext> loopEnv = env.dup(env.tree, env.info.dup(env.info.scope.dup())); @@ -1354,6 +1380,12 @@ } finally { bodyEnv.info.scope.leave(); } + if (!breaksOutOf(tree, tree.body)) { + List<BindingSymbol> bindings = getMatchBindings(types, log, tree.cond, false); + + bindings.forEach(env.info.scope::enter); + bindings.forEach(BindingSymbol::preserveBinding); + } result = null; } finally { @@ -1596,7 +1628,7 @@ addVars(c.stats, switchEnv.info.scope); } - flow.aliveAfterCase(caseEnv, c, make); + c.completesNormally = flow.aliveAfter(caseEnv, c, make); prevBindings = c.completesNormally ? matchBindings : null; } } finally { @@ -1944,25 +1976,66 @@ // if (x) { y } [ else z ] include x.T in y; include x.F in z - Env<AttrContext> thenEnv = bindingEnv(env, getMatchBindings(types, log, tree.cond, true)); + List<BindingSymbol> thenBindings = getMatchBindings(types, log, tree.cond, true); + Env<AttrContext> thenEnv = bindingEnv(env, thenBindings); + try { attribStat(tree.thenpart, thenEnv); } finally { thenEnv.info.scope.leave(); } + preFlow(tree.thenpart); + boolean aliveAfterThen = flow.aliveAfter(env, tree.thenpart, make); + boolean aliveAfterElse; + List<BindingSymbol> elseBindings = List.nil(); + if (tree.elsepart != null) { - Env<AttrContext> elseEnv = bindingEnv(env, getMatchBindings(types, log, tree.cond, false)); + elseBindings = getMatchBindings(types, log, tree.cond, false); + + Env<AttrContext> elseEnv = bindingEnv(env, elseBindings); try { attribStat(tree.elsepart, elseEnv); } finally { elseEnv.info.scope.leave(); } - } + preFlow(tree.elsepart); + aliveAfterElse = flow.aliveAfter(env, tree.elsepart, make); + } else { + aliveAfterElse = true; + } + chk.checkEmptyIf(tree); + + List<BindingSymbol> afterIfBindings = List.nil(); + + if (aliveAfterThen && !aliveAfterElse) { + afterIfBindings = thenBindings; + } else if (aliveAfterElse && !aliveAfterThen) { + afterIfBindings = elseBindings; + } + + afterIfBindings.forEach(env.info.scope::enter); + afterIfBindings.forEach(BindingSymbol::preserveBinding); + result = null; } + void preFlow(JCTree tree) { + new PostAttrAnalyzer() { + @Override + public void scan(JCTree tree) { + if (tree == null || + (tree.type != null && + tree.type == Type.stuckType)) { + //don't touch stuck expressions! + return; + } + super.scan(tree); + } + }.scan(tree); + } + public void visitExec(JCExpressionStatement tree) { //a fresh environment is required for 292 inference to work properly --- //see Infer.instantiatePolymorphicSignatureInstance() @@ -3763,29 +3836,29 @@ public void visitTypeTest(JCInstanceOf tree) { Type exprtype = chk.checkNullOrRefType( tree.expr.pos(), attribExpr(tree.expr, env)); - Type clazztype = attribType(tree.clazz, env); - if (!clazztype.hasTag(TYPEVAR)) { - clazztype = chk.checkClassOrArrayType(tree.clazz.pos(), clazztype); - } - if (!clazztype.isErroneous() && !types.isReifiable(clazztype)) { - log.error(tree.clazz.pos(), Errors.IllegalGenericTypeForInstof); - clazztype = types.createErrorType(clazztype); - } - chk.validate(tree.clazz, env, false); - chk.checkCastable(tree.expr.pos(), exprtype, clazztype); - result = check(tree, syms.booleanType, KindSelector.VAL, resultInfo); - } - - public void visitPatternTest(JCMatches tree) { - Type exprtype = attribExpr(tree.expr, env); //no target type - ResultInfo castInfo = unknownExprInfo; + Type clazztype; if (tree.pattern.getTag() == BINDINGPATTERN) { JCBindingPattern bindingPattern = (JCBindingPattern) tree.pattern; + ResultInfo castInfo = unknownExprInfo; if (bindingPattern.vartype == null) castInfo = castInfo(exprtype); - } - attribTree(tree.pattern, env, castInfo); - chk.checkCastable(tree.expr.pos(), exprtype, tree.pattern.type); + attribTree(tree.pattern, env, castInfo); + clazztype = tree.pattern.type; + if (!clazztype.hasTag(TYPEVAR)) { + clazztype = chk.checkClassOrArrayType(tree.pattern.pos(), clazztype); + } + } else { + clazztype = attribType(tree.pattern, env); + if (!clazztype.hasTag(TYPEVAR)) { + clazztype = chk.checkClassOrArrayType(tree.pattern.pos(), clazztype); + } + if (!clazztype.isErroneous() && !types.isReifiable(clazztype)) { + log.error(tree.pattern.pos(), Errors.IllegalGenericTypeForInstof); + clazztype = types.createErrorType(clazztype); + } + chk.validate(tree.pattern, env, false); + } + chk.checkCastable(tree.expr.pos(), exprtype, clazztype); result = check(tree, syms.booleanType, KindSelector.VAL, resultInfo); } @@ -5235,8 +5308,8 @@ super.visitTypeCast(tree); } public void visitTypeTest(JCInstanceOf tree) { - if (tree.clazz != null && tree.clazz.type != null) - validateAnnotatedType(tree.clazz, tree.clazz.type); + if (tree.pattern != null && !(tree.pattern instanceof JCPattern) && tree.pattern.type != null) + validateAnnotatedType(tree.pattern, tree.pattern.type); super.visitTypeTest(tree); } public void visitNewClass(JCNewClass tree) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java Wed Oct 17 13:56:45 2018 +0200 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java Wed Oct 24 17:25:26 2018 +0200 @@ -256,7 +256,7 @@ } } - public void aliveAfterCase(Env<AttrContext> env, JCCase that, TreeMaker make) { + public boolean aliveAfter(Env<AttrContext> env, JCTree that, TreeMaker make) { //we need to disable diagnostics temporarily; the problem is that if //a lambda expression contains e.g. an unreachable statement, an error //message will be reported and will cause compilation to skip the flow analyis @@ -264,10 +264,10 @@ //related errors, which will allow for more errors to be detected Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log); try { - CaseAliveAnalyzer analyzer = new CaseAliveAnalyzer(); + SnippetAliveAnalyzer analyzer = new SnippetAliveAnalyzer(); - analyzer.analyzeTree(env, that.stats, make); - that.completesNormally = analyzer.isAlive(); + analyzer.analyzeTree(env, that, make); + return analyzer.isAlive(); } finally { log.popDiagnosticHandler(diagHandler); } @@ -1544,9 +1544,9 @@ } /** - * TODO + * Determine if alive after the given tree. */ - class CaseAliveAnalyzer extends AliveAnalyzer { + class SnippetAliveAnalyzer extends AliveAnalyzer { @Override public void visitClassDef(JCClassDecl tree) { //skip
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java Wed Oct 17 13:56:45 2018 +0200 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java Wed Oct 24 17:25:26 2018 +0200 @@ -66,7 +66,6 @@ import com.sun.tools.javac.tree.JCTree.JCSwitchExpression; import static com.sun.tools.javac.tree.JCTree.Tag.*; - /** This pass translates away some syntactic sugar: inner classes, * class literals, assertions, foreach loops, etc. *
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MatchBindingsComputer.java Wed Oct 17 13:56:45 2018 +0200 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MatchBindingsComputer.java Wed Oct 24 17:25:26 2018 +0200 @@ -193,9 +193,9 @@ } return bindings; } - + public static class BindingSymbol extends VarSymbol { - + public BindingSymbol(Name name, Type type, Symbol owner) { super(Flags.FINAL | Flags.HASINIT | Flags.MATCH_BINDING, name, type, owner); } @@ -207,6 +207,14 @@ List<BindingSymbol> aliases() { return List.of(this); } + + public void preserveBinding() { + flags_field |= Flags.MATCH_BINDING_TO_OUTER; + } + + public boolean isPreserved() { + return (flags_field & Flags.MATCH_BINDING_TO_OUTER) != 0; + } } public static class IntersectionBindingSymbol extends BindingSymbol { @@ -224,5 +232,14 @@ List<BindingSymbol> aliases() { return aliases; } + + @Override + public void preserveBinding() { + aliases.stream().forEach(BindingSymbol::preserveBinding); + } + + public boolean isPreserved() { + return aliases.stream().allMatch(BindingSymbol::isPreserved); + } } }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java Wed Oct 17 13:56:45 2018 +0200 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java Wed Oct 24 17:25:26 2018 +0200 @@ -39,15 +39,14 @@ import com.sun.tools.javac.tree.JCTree.JCBreak; import com.sun.tools.javac.tree.JCTree.JCCase; import com.sun.tools.javac.tree.JCTree.JCConditional; -import com.sun.tools.javac.tree.JCTree.JCLiteralPattern; import com.sun.tools.javac.tree.JCTree.JCExpression; import com.sun.tools.javac.tree.JCTree.JCForLoop; import com.sun.tools.javac.tree.JCTree.JCIdent; import com.sun.tools.javac.tree.JCTree.JCIf; import com.sun.tools.javac.tree.JCTree.JCInstanceOf; import com.sun.tools.javac.tree.JCTree.JCLabeledStatement; +import com.sun.tools.javac.tree.JCTree.JCLiteralPattern; import com.sun.tools.javac.tree.JCTree.JCLiteralPattern.LiteralPatternKind; -import com.sun.tools.javac.tree.JCTree.JCMatches; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCStatement; import com.sun.tools.javac.tree.JCTree.JCSwitch; @@ -66,6 +65,7 @@ import com.sun.tools.javac.util.Options; import java.util.Map; +import java.util.Map.Entry; import java.util.stream.Collectors; import com.sun.tools.javac.code.Symbol.MethodSymbol; @@ -74,7 +74,7 @@ import static com.sun.tools.javac.tree.JCTree.Tag.SWITCH; /** - * This pass translates pattern-matching constructs, such as __match and __matches. + * This pass translates pattern-matching constructs, such as instanceof <pattern> and switch. */ public class TransPatterns extends TreeTranslator { @@ -116,6 +116,11 @@ //do nothing return this; } + + @Override + boolean tryPrepend(BindingSymbol binding, JCVariableDecl var) { + return false; + } }; JCLabeledStatement pendingMatchLabel = null; @@ -136,60 +141,55 @@ debugTransPatterns = Options.instance(context).isSet("debug.patterns"); } - public void visitPatternTest(JCMatches tree) { - JCTree pattern = tree.pattern; - switch (pattern.getTag()) { - case BINDINGPATTERN:{ - JCBindingPattern patt = (JCBindingPattern)pattern; - VarSymbol pattSym = patt.symbol; - Type tempType = tree.expr.type.hasTag(BOT) ? - syms.objectType - : tree.expr.type; - VarSymbol temp = new VarSymbol(pattSym.flags(), - pattSym.name.append(names.fromString("$temp")), - tempType, - patt.symbol.owner); - JCExpression translatedExpr = translate(tree.expr); - Type castTargetType = types.boxedTypeOrType(pattSym.erasure(types)); - if (patt.vartype == null || tree.expr.type.isPrimitive()) { - result = make.Literal(BOOLEAN,1).setType(syms.booleanType); + @Override + public void visitTypeTest(JCInstanceOf tree) { + if (tree.pattern.hasTag(Tag.BINDINGPATTERN)) { + JCBindingPattern patt = (JCBindingPattern)tree.pattern; + VarSymbol pattSym = patt.symbol; + Type tempType = tree.expr.type.hasTag(BOT) ? + syms.objectType + : tree.expr.type; + VarSymbol temp = new VarSymbol(pattSym.flags(), + pattSym.name.append(names.fromString("$temp")), + tempType, + patt.symbol.owner); + JCExpression translatedExpr = translate(tree.expr); + Type castTargetType = types.boxedTypeOrType(pattSym.erasure(types)); + if (patt.vartype == null || tree.expr.type.isPrimitive()) { + result = make.Literal(BOOLEAN,1).setType(syms.booleanType); + } else { + result = makeTypeTest(make.Ident(temp), make.Type(castTargetType)); + } + + VarSymbol bindingVar = bindingContext.getBindingFor(patt.symbol); + if (bindingVar != null) { + JCAssign fakeInit = (JCAssign)make.at(tree.pos).Assign( + make.Ident(bindingVar), convert(make.Ident(temp), castTargetType)).setType(bindingVar.erasure(types)); + result = makeBinary(Tag.AND, (JCExpression)result, + makeBinary(Tag.EQ, fakeInit, convert(make.Ident(temp), castTargetType))); + } + result = make.at(tree.pos).LetExpr(make.VarDef(temp, translatedExpr), (JCExpression)result).setType(syms.booleanType); + } else if (tree.pattern.hasTag(Tag.LITERALPATTERN)) { + //XXX: should this be here, or do we change switch desugaring? + JCLiteralPattern patt = (JCLiteralPattern)tree.pattern; + if (patt.patternKind == LiteralPatternKind.TYPE) { + result = makeTypeTest(tree.expr, patt.value); + } else { + JCExpression ce = patt.value; + JCExpression lhs = ce.type.hasTag(BOT) ? + tree.expr + : make.TypeCast(make.Type(ce.type), tree.expr).setType(ce.type.baseType()); + if (!ce.type.hasTag(BOT) && tree.expr.type.isReference()) { + result = translate(makeBinary( + Tag.AND, + makeTypeTest(tree.expr, make.Type(types.boxedTypeOrType(ce.type))), + makeBinary(JCTree.Tag.EQ, lhs, ce))); } else { - result = makeTypeTest(make.Ident(temp), make.Type(castTargetType)); + result = translate(makeBinary(JCTree.Tag.EQ, lhs, ce)); } - - VarSymbol bindingVar = bindingContext.getBindingFor(patt.symbol); - if (bindingVar != null) { - JCAssign fakeInit = (JCAssign)make.at(tree.pos).Assign( - make.Ident(bindingVar), convert(make.Ident(temp), castTargetType)).setType(bindingVar.erasure(types)); - result = makeBinary(Tag.AND, (JCExpression)result, - makeBinary(Tag.EQ, fakeInit, convert(make.Ident(temp), castTargetType))); - } - result = make.at(tree.pos).LetExpr(make.VarDef(temp, translatedExpr), (JCExpression)result).setType(syms.booleanType); - break; } - case LITERALPATTERN: { - JCLiteralPattern patt = (JCLiteralPattern)pattern; - if (patt.patternKind == LiteralPatternKind.TYPE) { - result = makeTypeTest(tree.expr, patt.value); - } else { - JCExpression ce = ((JCLiteralPattern) pattern).value; - JCExpression lhs = ce.type.hasTag(BOT) ? - tree.expr - : make.TypeCast(make.Type(ce.type), tree.expr).setType(ce.type.baseType()); - if (!ce.type.hasTag(BOT) && tree.expr.type.isReference()) { - result = translate(makeBinary( - Tag.AND, - makeTypeTest(tree.expr, make.Type(types.boxedTypeOrType(ce.type))), - makeBinary(JCTree.Tag.EQ, lhs, ce))); - } else { - result = translate(makeBinary(JCTree.Tag.EQ, lhs, ce)); - } - } - break; - } - default: { - Assert.error("Cannot get here"); - } + } else { + super.visitTypeTest(tree); } } @@ -290,7 +290,7 @@ for (JCCase clause : tree.cases) { Assert.check(clause.pats.size() <= 1); - final JCExpression jcMatches = clause.pats.nonEmpty() ? make.PatternTest(tree.selector, clause.pats.head) : make.Literal(BOOLEAN, 1); + final JCExpression jcMatches = clause.pats.nonEmpty() ? make.TypeTest(tree.selector, clause.pats.head) : make.Literal(BOOLEAN, 1); jcMatches.setType(syms.booleanType); JCStatement body; List<JCStatement> stats = clause.stats; @@ -342,6 +342,28 @@ } } + @Override + public void visitBlock(JCBlock tree) { + ListBuffer<JCStatement> statements = new ListBuffer<>(); + bindingContext = new BasicBindingContext(List.nil()) { + boolean tryPrepend(BindingSymbol binding, JCVariableDecl var) { + hoistedVarMap.put(binding, var.sym); + statements.append(var); + return true; + } + }; + try { + for (List<JCStatement> l = tree.stats; l.nonEmpty(); l = l.tail) { + statements.append(translate(l.head)); + } + + tree.stats = statements.toList(); + result = tree; + } finally { + bindingContext.pop(); + } + } + public JCTree translateTopLevelClass(Env<AttrContext> env, JCTree cdef, TreeMaker make) { try { this.make = make; @@ -430,6 +452,7 @@ abstract JCStatement decorateStatement(JCStatement stat); abstract JCExpression decorateExpression(JCExpression expr); abstract BindingContext pop(); + abstract boolean tryPrepend(BindingSymbol binding, JCVariableDecl var); } class BasicBindingContext extends BindingContext { @@ -461,11 +484,18 @@ JCStatement decorateStatement(JCStatement stat) { if (hoistedVarMap.isEmpty()) return stat; ListBuffer<JCStatement> stats = new ListBuffer<>(); - for (VarSymbol vsym : hoistedVarMap.values()) { - stats.add(makeHoistedVarDecl(stat.pos, vsym)); + for (Entry<BindingSymbol, VarSymbol> e : hoistedVarMap.entrySet()) { + JCVariableDecl decl = makeHoistedVarDecl(stat.pos, e.getValue()); + if (!e.getKey().isPreserved() || + !parent.tryPrepend(e.getKey(), decl)) { + stats.add(decl); + } } - stats.add(stat); - return make.at(stat.pos).Block(0, stats.toList()); + if (stats.nonEmpty()) { + stats.add(stat); + stat = make.at(stat.pos).Block(0, stats.toList()); + } + return stat; } @Override @@ -481,6 +511,11 @@ return bindingContext = parent; } + @Override + boolean tryPrepend(BindingSymbol binding, JCVariableDecl var) { + return false; + } + private JCVariableDecl makeHoistedVarDecl(int pos, VarSymbol varSymbol) { return make.at(pos).VarDef(varSymbol, makeDefaultValue(pos, varSymbol.erasure(types))); }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java Wed Oct 17 13:56:45 2018 +0200 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java Wed Oct 24 17:25:26 2018 +0200 @@ -567,19 +567,13 @@ result = tree; } - public void visitPatternTest(JCMatches tree) { - tree.expr = translate(tree.expr, null); - tree.pattern = translate(tree.pattern, null); - result = tree; - } - public void visitBindingPattern(JCBindingPattern tree) { if (tree.vartype != null) { tree.vartype = translate(tree.vartype, null); } result = tree; } - + public void visitSwitchExpression(JCSwitchExpression tree) { Type selsuper = types.supertype(tree.selector.type); boolean enumSwitch = selsuper != null && @@ -790,7 +784,7 @@ public void visitTypeTest(JCInstanceOf tree) { tree.expr = translate(tree.expr, null); - tree.clazz = translate(tree.clazz, null); + tree.pattern = translate(tree.pattern, null); result = tree; }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TreeDiffer.java Wed Oct 17 13:56:45 2018 +0200 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TreeDiffer.java Wed Oct 24 17:25:26 2018 +0200 @@ -577,7 +577,7 @@ @Override public void visitTypeTest(JCInstanceOf tree) { JCInstanceOf that = (JCInstanceOf) parameter; - result = scan(tree.expr, that.expr) && scan(tree.clazz, that.clazz); + result = scan(tree.expr, that.expr) && scan(tree.pattern, that.pattern); } @Override
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/CRTable.java Wed Oct 17 13:56:45 2018 +0200 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/CRTable.java Wed Oct 24 17:25:26 2018 +0200 @@ -459,7 +459,7 @@ public void visitTypeTest(JCInstanceOf tree) { SourceRange sr = new SourceRange(startPos(tree), endPos(tree)); sr.mergeWith(csp(tree.expr)); - sr.mergeWith(csp(tree.clazz)); + sr.mergeWith(csp(tree.pattern)); result = sr; }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java Wed Oct 17 13:56:45 2018 +0200 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java Wed Oct 24 17:25:26 2018 +0200 @@ -1558,6 +1558,9 @@ CondItem c = genCond(TreeInfo.skipParens(tree.cond), CRT_FLOW_CONTROLLER); Chain elseChain = c.jumpFalse(); + if (!code.isStatementStart()) { + System.err.println("G"); + } Assert.check(code.isStatementStart()); if (!c.isFalse()) { code.resolve(c.trueJumps); @@ -2024,7 +2027,7 @@ public void visitTypeTest(JCInstanceOf tree) { genExpr(tree.expr, tree.expr.type).load(); setTypeAnnotationPositions(tree.pos); - code.emitop2(instanceof_, makeRef(tree.pos(), tree.clazz.type)); + code.emitop2(instanceof_, makeRef(tree.pos(), tree.pattern.type)); result = items.makeStackItem(syms.booleanType); }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java Wed Oct 17 13:56:45 2018 +0200 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java Wed Oct 24 17:25:26 2018 +0200 @@ -361,7 +361,6 @@ case DO: case TRY: case SWITCH: - case MATCH: case RETURN: case THROW: case BREAK: @@ -584,11 +583,6 @@ Name name = token.name(); nextToken(); return name; - } else if (token.kind == MATCHES || token.kind == TokenKind.MATCH || token.kind == VAR) { - //'matches', 'match', 'var' are just identifiers when inside other expressions - Name name = token.name(); - nextToken(); - return name; } else { accept(IDENTIFIER); if (advanceOnErrors) { @@ -748,7 +742,7 @@ public JCPattern parsePattern() { int pos = token.pos; - if (token.kind == VAR) { + if (token.kind == IDENTIFIER && token.name() == names.var) { nextToken(); return toP(F.at(pos).BindingPattern(ident(), null)); } else { @@ -911,7 +905,7 @@ /* Expression2Rest = {infixop Expression3} * | Expression3 instanceof Type - * | Expression3 matches Pattern + * | Expression3 instanceof Pattern * infixop = "||" * | "&&" * | "|" @@ -924,7 +918,6 @@ * | "*" | "/" | "%" */ JCExpression term2Rest(JCExpression t, int minprec) { - JCExpression[] odStack = newOdStack(); Token[] opStack = newOpStack(); @@ -939,13 +932,16 @@ if (token.kind == INSTANCEOF) { int pos = token.pos; nextToken(); - JCExpression typ = parseType(); - odStack[top] = F.at(pos).TypeTest(odStack[top], typ); - } else if (token.kind == MATCHES) { - int pos = token.pos; - nextToken(); - JCPattern pat = parsePattern(); - odStack[top] = F.at(pos).PatternTest(odStack[top], pat); + int patternPos = token.pos; + JCTree pattern = parseType(true); + if (token.kind == IDENTIFIER) { + if (pattern.hasTag(IDENT) && isRestrictedLocalVarTypeName((JCIdent) pattern, keepLineMap)) { + reportSyntaxError(pos, Errors.VarNotAllowed); + pattern = null; + } + pattern = toP(F.at(patternPos).BindingPattern(ident(), pattern)); + } + odStack[top] = F.at(pos).TypeTest(odStack[top], pattern); } else { topOp = token; nextToken(); @@ -970,18 +966,6 @@ return t; } //where - Filter<TokenKind> matchFilter = tk -> { - switch (tk) { - case LPAREN: - case DOT: - case EQ: - return false; - case MATCHES: - return true; - default: return optag(tk) == Tag.NO_TAG; - } - }; - /** If tree is a concatenation of string literals, replace it * by a single literal representing the concatenated string. */ @@ -1248,7 +1232,7 @@ t = insertAnnotationsToMostInner(expr, typeAnnos, false); } break; - case UNDERSCORE: case IDENTIFIER: case ASSERT: case ENUM: case MATCH: case MATCHES: case VAR: + case UNDERSCORE: case IDENTIFIER: case ASSERT: case ENUM: if (typeArgs != null) return illegal(); if ((mode & EXPR) != 0 && (mode & NOLAMBDA) == 0 && peekToken(ARROW)) { t = lambdaExpressionOrStatement(false, false, pos); @@ -1692,7 +1676,6 @@ case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL: case TRUE: case FALSE: case NULL: case NEW: case IDENTIFIER: case ASSERT: case ENUM: case UNDERSCORE: - case VAR: case MATCH: case MATCHES: case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID: return ParensResult.CAST; @@ -1703,21 +1686,6 @@ case ASSERT: case ENUM: case IDENTIFIER: - case VAR: - case MATCH: // ?? - case MATCHES: // ?? - if (tk == IDENTIFIER && S.token(lookahead + 1).kind == MATCHES) { - // Identifier, "matches" -> ! explicit lambda - return ParensResult.PARENS; - } - if (peekToken(lookahead, MATCHES)) { - Token next = S.token(lookahead + 1); - if (next.kind == COMMA || next.kind == RPAREN) { - // Identifier matches ','|')' -> explicit lambda - return ParensResult.EXPLICIT_LAMBDA; - } - return ParensResult.PARENS; - } if (peekToken(lookahead, LAX_IDENTIFIER)) { // Identifier, Identifier/'_'/'assert'/'enum' -> explicit lambda return ParensResult.EXPLICIT_LAMBDA; @@ -1818,8 +1786,7 @@ } /** Accepts all identifier-like tokens */ - protected Filter<TokenKind> LAX_IDENTIFIER = t -> t == IDENTIFIER || t == UNDERSCORE || t == ASSERT || t == ENUM || - t == MATCHES || t == TokenKind.MATCH || t == VAR; + protected Filter<TokenKind> LAX_IDENTIFIER = t -> t == IDENTIFIER || t == UNDERSCORE || t == ASSERT || t == ENUM; enum ParensResult { CAST, @@ -2575,7 +2542,6 @@ */ List<JCStatement> blockStatement() { //todo: skip to anchor on error(?) - Comment dc; int pos = token.pos; switch (token.kind) { case RBRACE: case CASE: case DEFAULT: case EOF: @@ -2585,16 +2551,9 @@ case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH: case ASSERT: return List.of(parseSimpleStatement()); - case MATCH: - //is it a match statement? - if (isMatchStatement()) { - return List.of(parseSimpleStatement()); - } else { - break; - } case MONKEYS_AT: case FINAL: { - dc = token.comment(CommentStyle.JAVADOC); + Comment dc = token.comment(CommentStyle.JAVADOC); JCModifiers mods = modifiersOpt(); if (token.kind == INTERFACE || token.kind == CLASS || @@ -2606,13 +2565,13 @@ } } case ABSTRACT: case STRICTFP: { - dc = token.comment(CommentStyle.JAVADOC); + Comment dc = token.comment(CommentStyle.JAVADOC); JCModifiers mods = modifiersOpt(); return List.of(classOrInterfaceOrEnumDeclaration(mods, dc)); } case INTERFACE: case CLASS: - dc = token.comment(CommentStyle.JAVADOC); + Comment dc = token.comment(CommentStyle.JAVADOC); return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc)); case ENUM: log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.LocalEnum); @@ -2639,33 +2598,7 @@ return List.of(expr); } } - //where - boolean isMatchStatement() { - //we need a LPAREN - if (!peekToken(LPAREN)) { - return false; - } - //then we scan through the contents of the '(...)', looking for a matching closing parens, - //followed by an '{'. - int depth = 1; - for (int lookahead = 2 ; ; lookahead++) { - TokenKind tk = S.token(lookahead).kind; - switch (tk) { - case LPAREN: - depth++; - break; - case RPAREN: - depth--; - if (depth == 0) { - return S.token(lookahead + 1).kind == LBRACE; - } - break; - case EOF: - return false; - } - } - } private List<JCStatement> localVariableDeclarations(JCModifiers mods, JCExpression type) { ListBuffer<JCStatement> stats = variableDeclarators(mods, type, new ListBuffer<>(), true); @@ -2772,7 +2705,6 @@ } return F.at(pos).Try(resources, body, catchers.toList(), finalizer); } - case MATCH: case SWITCH: { nextToken(); JCExpression selector = parExpression(); @@ -4318,7 +4250,7 @@ /** Return precedence of operator represented by token, * -1 if token is not a binary operator. @see TreeInfo.opPrec */ - int prec(TokenKind token) { + static int prec(TokenKind token) { JCTree.Tag oc = optag(token); return (oc != NO_TAG) ? TreeInfo.opPrec(oc) : -1; } @@ -4338,7 +4270,7 @@ /** Return operation tag of binary operator represented by token, * No_TAG if token is not a binary operator. */ - JCTree.Tag optag(TokenKind token) { + static JCTree.Tag optag(TokenKind token) { switch (token) { case BARBAR: return OR; @@ -4402,8 +4334,6 @@ return MOD_ASG; case INSTANCEOF: return TYPETEST; - case MATCHES: - return peekToken(matchFilter) ? PATTERNTEST : NO_TAG; default: return NO_TAG; }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/Tokens.java Wed Oct 17 13:56:45 2018 +0200 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/Tokens.java Wed Oct 24 17:25:26 2018 +0200 @@ -145,8 +145,6 @@ INT("int", Tag.NAMED), INTERFACE("interface"), LONG("long", Tag.NAMED), - MATCH("__match", Tag.NAMED), - MATCHES("__matches", Tag.NAMED), NATIVE("native"), NEW("new"), PACKAGE("package"), @@ -165,7 +163,6 @@ THROWS("throws"), TRANSIENT("transient"), TRY("try"), - VAR("var", Tag.NAMED), VOID("void", Tag.NAMED), VOLATILE("volatile"), WHILE("while"),
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java Wed Oct 17 13:56:45 2018 +0200 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java Wed Oct 24 17:25:26 2018 +0200 @@ -153,18 +153,14 @@ */ SWITCH, + /** Case parts in switch statements/expressions, of type Case. + */ + CASE, + /** Switch expression statements, of type Switch. */ SWITCH_EXPRESSION, - /** Case parts in switch statements/expressions, of type Case. - */ - CASE, - - /** Case parts in match statements, of type Clause. - */ - CLAUSE, - /** Synchronized statements, of type Synchonized. */ SYNCHRONIZED, @@ -241,10 +237,6 @@ */ TYPETEST, - /** Pattern test expression, of type PatternTest. - */ - PATTERNTEST, - /** Patterns. */ BINDINGPATTERN, @@ -1330,8 +1322,6 @@ } } - - /** * A "switch ( ) { }" construction. */ @@ -2146,10 +2136,10 @@ */ public static class JCInstanceOf extends JCExpression implements InstanceOfTree { public JCExpression expr; - public JCTree clazz; - protected JCInstanceOf(JCExpression expr, JCTree clazz) { + public JCTree pattern; + protected JCInstanceOf(JCExpression expr, JCTree pattern) { this.expr = expr; - this.clazz = clazz; + this.pattern = pattern; } @Override public void accept(Visitor v) { v.visitTypeTest(this); } @@ -2157,7 +2147,13 @@ @DefinedBy(Api.COMPILER_TREE) public Kind getKind() { return Kind.INSTANCE_OF; } @DefinedBy(Api.COMPILER_TREE) - public JCTree getType() { return clazz; } + public JCTree getType() { return pattern instanceof JCPattern ? pattern.hasTag(BINDINGPATTERN) ? ((JCBindingPattern) pattern).vartype : null : pattern; } + + @Override @DefinedBy(Api.COMPILER_TREE) + public JCPattern getPattern() { + return pattern instanceof JCPattern ? (JCPattern) pattern : null; + } + @DefinedBy(Api.COMPILER_TREE) public JCExpression getExpression() { return expr; } @Override @DefinedBy(Api.COMPILER_TREE) @@ -2171,52 +2167,22 @@ } /** - * A pattern match test. - */ - public static class JCMatches extends JCExpression - implements MatchesTree { - public JCExpression expr; - public JCPattern pattern; - protected JCMatches(JCExpression expr, JCPattern pattern) { - this.expr = expr; - this.pattern = pattern; - } - @Override - public void accept(Visitor v) { v.visitPatternTest(this); } - - @DefinedBy(Api.COMPILER_TREE) - public Kind getKind() { return Kind.MATCHES; } - @DefinedBy(Api.COMPILER_TREE) - public JCPattern getPattern() { return pattern; } - @DefinedBy(Api.COMPILER_TREE) - public JCExpression getExpression() { return expr; } - @Override @DefinedBy(Api.COMPILER_TREE) - public <R,D> R accept(TreeVisitor<R,D> v, D d) { - return v.visitMatches(this, d); - } - @Override - public Tag getTag() { - return PATTERNTEST; - } - } - - /** * Pattern matching forms. */ public static abstract class JCPattern extends JCTree implements PatternTree { public JCExpression constExpression() { return null; - } + } } public static class JCBindingPattern extends JCPattern implements BindingPatternTree { public Name name; public BindingSymbol symbol; - public JCExpression vartype; /** Null if var pattern */ - - protected JCBindingPattern(Name name, BindingSymbol symbol, JCExpression vartype) { + public JCTree vartype; + + protected JCBindingPattern(Name name, BindingSymbol symbol, JCTree vartype) { this.name = name; this.symbol = symbol; this.vartype = vartype; @@ -2265,12 +2231,6 @@ this.value = value; } - @DefinedBy(Api.COMPILER_TREE) - @Override - public Name getBinding() { - return null; - } - @Override public void accept(Visitor v) { v.visitLiteralPattern(this); @@ -3279,8 +3239,7 @@ JCBinary Binary(Tag opcode, JCExpression lhs, JCExpression rhs); JCTypeCast TypeCast(JCTree expr, JCExpression type); JCInstanceOf TypeTest(JCExpression expr, JCTree clazz); - JCMatches PatternTest(JCExpression expr, JCPattern clazz); - JCBindingPattern BindingPattern(Name name, JCExpression vartype); + JCBindingPattern BindingPattern(Name name, JCTree vartype); JCLiteralPattern LiteralPattern(JCExpression cexp); JCArrayAccess Indexed(JCExpression indexed, JCExpression index); JCFieldAccess Select(JCExpression selected, Name selector); @@ -3345,7 +3304,6 @@ public void visitBinary(JCBinary that) { visitTree(that); } public void visitTypeCast(JCTypeCast that) { visitTree(that); } public void visitTypeTest(JCInstanceOf that) { visitTree(that); } - public void visitPatternTest(JCMatches that) { visitTree(that); } public void visitBindingPattern(JCBindingPattern that) { visitTree(that); } public void visitLiteralPattern(JCLiteralPattern that) { visitTree(that); } public void visitIndexed(JCArrayAccess that) { visitTree(that); }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java Wed Oct 17 13:56:45 2018 +0200 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java Wed Oct 24 17:25:26 2018 +0200 @@ -1313,19 +1313,11 @@ open(prec, TreeInfo.ordPrec); printExpr(tree.expr, TreeInfo.ordPrec); print(" instanceof "); - printExpr(tree.clazz, TreeInfo.ordPrec + 1); - close(prec, TreeInfo.ordPrec); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - - public void visitPatternTest(JCMatches tree) { - try { - open(prec, TreeInfo.ordPrec); - printExpr(tree.expr, TreeInfo.ordPrec); - print(" matches "); - printPattern(tree.pattern); + if (tree.pattern instanceof JCPattern) { + printPattern(tree.pattern); + } else { + printExpr(tree.getType(), TreeInfo.ordPrec + 1); + } close(prec, TreeInfo.ordPrec); } catch (IOException e) { throw new UncheckedIOException(e);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java Wed Oct 17 13:56:45 2018 +0200 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java Wed Oct 24 17:25:26 2018 +0200 @@ -475,23 +475,14 @@ public JCTree visitInstanceOf(InstanceOfTree node, P p) { JCInstanceOf t = (JCInstanceOf) node; JCExpression expr = copy(t.expr, p); - JCTree clazz = copy(t.clazz, p); - return M.at(t.pos).TypeTest(expr, clazz); + JCTree pattern = copy(t.pattern, p); + return M.at(t.pos).TypeTest(expr, pattern); } @DefinedBy(Api.COMPILER_TREE) - public JCTree visitMatches(MatchesTree node, P p) { - JCMatches t = (JCMatches) node; - JCExpression expr = copy(t.expr, p); - JCPattern pattern = copy(t.pattern, p); - return M.at(t.pos).PatternTest(expr, pattern); - } - - - @DefinedBy(Api.COMPILER_TREE) public JCTree visitBindingPattern(BindingPatternTree node, P p) { JCBindingPattern t = (JCBindingPattern) node; - JCExpression vartype = copy(t.vartype, p); + JCTree vartype = copy(t.vartype, p); return M.at(t.pos).BindingPattern(t.name, vartype); }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java Wed Oct 17 13:56:45 2018 +0200 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java Wed Oct 24 17:25:26 2018 +0200 @@ -454,8 +454,6 @@ return getStartPos(((JCArrayTypeTree) tree).elemtype); case TYPETEST: return getStartPos(((JCInstanceOf) tree).expr); - case PATTERNTEST: - return getStartPos(((JCMatches) tree).expr); case ANNOTATED_TYPE: { JCAnnotatedType node = (JCAnnotatedType) tree; if (node.annotations.nonEmpty()) { @@ -573,9 +571,7 @@ case TYPECAST: return getEndPos(((JCTypeCast) tree).expr, endPosTable); case TYPETEST: - return getEndPos(((JCInstanceOf) tree).clazz, endPosTable); - case PATTERNTEST: - return getEndPos(((JCMatches) tree).pattern, endPosTable); + return getEndPos(((JCInstanceOf) tree).pattern, endPosTable); case WHILELOOP: return getEndPos(((JCWhileLoop) tree).body, endPosTable); case ANNOTATED_TYPE: @@ -1012,8 +1008,7 @@ case MUL: case DIV: case MOD: return mulPrec; - case TYPETEST: - case PATTERNTEST: return ordPrec; + case TYPETEST: return ordPrec; default: throw new AssertionError(); } }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java Wed Oct 17 13:56:45 2018 +0200 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java Wed Oct 24 17:25:26 2018 +0200 @@ -441,13 +441,7 @@ return tree; } - public JCMatches PatternTest(JCExpression expr, JCPattern patt) { - JCMatches tree = new JCMatches(expr, patt); - tree.pos = pos; - return tree; - } - - public JCBindingPattern BindingPattern(Name name, JCExpression vartype) { + public JCBindingPattern BindingPattern(Name name, JCTree vartype) { JCBindingPattern tree = new JCBindingPattern(name, null, vartype); tree.pos = pos; return tree;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java Wed Oct 17 13:56:45 2018 +0200 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeScanner.java Wed Oct 24 17:25:26 2018 +0200 @@ -296,11 +296,6 @@ public void visitTypeTest(JCInstanceOf tree) { scan(tree.expr); - scan(tree.clazz); - } - - public void visitPatternTest(JCMatches tree) { - scan(tree.expr); scan(tree.pattern); }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeTranslator.java Wed Oct 17 13:56:45 2018 +0200 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeTranslator.java Wed Oct 24 17:25:26 2018 +0200 @@ -351,12 +351,6 @@ public void visitTypeTest(JCInstanceOf tree) { tree.expr = translate(tree.expr); - tree.clazz = translate(tree.clazz); - result = tree; - } - - public void visitPatternTest(JCMatches tree) { - tree.expr = translate(tree.expr); tree.pattern = translate(tree.pattern); result = tree; }
--- a/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java Wed Oct 17 13:56:45 2018 +0200 +++ b/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java Wed Oct 24 17:25:26 2018 +0200 @@ -212,7 +212,6 @@ LONG(TokenKind.LONG, XEXPR1|XDECL1), // long SHORT(TokenKind.SHORT, XEXPR1|XDECL1), // short VOID(TokenKind.VOID, XEXPR1|XDECL1), // void - VAR(TokenKind.VAR, XEXPR1|XDECL1|XTERM), // var // Modifiers keywords ABSTRACT(TokenKind.ABSTRACT, XDECL1), // abstract @@ -255,7 +254,6 @@ THROW(TokenKind.THROW, XSTMT1|XSTART), // throw TRY(TokenKind.TRY, XSTMT1|XSTART), // try WHILE(TokenKind.WHILE, XSTMT1|XSTART), // while - MATCH(TokenKind.MATCH, XSTMT1|XSTART), // match // Statement keywords that we shouldn't see -- inside braces CASE(TokenKind.CASE, XSTMT|XSTART), // case @@ -317,7 +315,6 @@ LTLTEQ(TokenKind.LTLTEQ, XEXPR), // <<= GTGTEQ(TokenKind.GTGTEQ, XEXPR), // >>= GTGTGTEQ(TokenKind.GTGTGTEQ, XEXPR), // >>>= - MATCHES(TokenKind.MATCHES, XEXPR), // combined/processed kinds UNMATCHED(XERRO), @@ -668,7 +665,6 @@ case BRACES: case SEMI: return Completeness.COMPLETE; - case VAR: case IDENTIFIER: return isBracesNeeded ? Completeness.DEFINITELY_INCOMPLETE
--- a/test/langtools/tools/javac/patterns/BindingsTest1.java Wed Oct 17 13:56:45 2018 +0200 +++ b/test/langtools/tools/javac/patterns/BindingsTest1.java Wed Oct 24 17:25:26 2018 +0200 @@ -1,6 +1,6 @@ /* * @test - * @summary Basic tests for bindings from __matches + * @summary Basic tests for bindings from instanceof * @compile BindingsTest1.java * @run main BindingsTest1 */ @@ -15,34 +15,34 @@ // Test for (e matches P).T = { binding variables in P } - if (o1 __matches String s) { + if (o1 instanceof String s) { s.length(); } // Test for e1 && e2.T = union(e1.T, e2.T) - if (o1 __matches String s && o2 __matches Integer in) { + if (o1 instanceof String s && o2 instanceof Integer in) { s.length(); in.intValue(); } // Test for e1 && e2.F = intersect(e1.F, e2.F) - if (!(o1 __matches String s) && !(o1 __matches String s)) { + if (!(o1 instanceof String s) && !(o1 instanceof String s)) { } else { s.length(); } // test for e1&&e2 - include e1.T in e2 - if (o1 __matches String s && s.length()>0) { + if (o1 instanceof String s && s.length()>0) { System.out.print("done"); } // Test for (e1 || e2).T = intersect(e1.T, e2.T) - if (o1 __matches String s || o3 __matches String s){ + if (o1 instanceof String s || o3 instanceof String s){ System.out.println(s); // ? } // Test for (e1 || e2).F = union(e1.F, e2.F) - if (!(o1 __matches String s) || !(o3 __matches Integer in)){ + if (!(o1 instanceof String s) || !(o3 instanceof Integer in)){ } else { s.length(); i.intValue(); @@ -50,68 +50,93 @@ // Test for e1||e2 - include e1.F in e2 - if (!(o1 __matches String s) || s.length()>0) { + if (!(o1 instanceof String s) || s.length()>0) { System.out.println("done"); } // Test for (e1 ? e2 : e3).T contains intersect(e2.T, e3.T) - if (Ktrue() ? o2 __matches Integer x : o2 __matches Integer x) { + if (Ktrue() ? o2 instanceof Integer x : o2 instanceof Integer x) { x.intValue(); } // Test for (e1 ? e2 : e3).T contains intersect(e1.T, e3.T) - if (o1 __matches String s ? true : o1 __matches String s) { + if (o1 instanceof String s ? true : o1 instanceof String s) { s.length(); } // Test for (e1 ? e2 : e3).T contains intersect(e1.F, e2.T) - if (!(o1 __matches String s) ? (o1 __matches String s) : true) { + if (!(o1 instanceof String s) ? (o1 instanceof String s) : true) { s.length(); } // Test for (e1 ? e2 : e3).F contains intersect(e2.F, e3.F) - if (Ktrue() ? !(o2 __matches Integer x) : !(o2 __matches Integer x)){ + if (Ktrue() ? !(o2 instanceof Integer x) : !(o2 instanceof Integer x)){ } else { x.intValue(); } // Test for (e1 ? e2 : e3).F contains intersect(e1.T, e3.F) - if (o1 __matches String s ? true : !(o1 __matches String s)){ + if (o1 instanceof String s ? true : !(o1 instanceof String s)){ } else { s.length(); } // Test for (e1 ? e2 : e3).F contains intersect(e1.F, e2.F) - if (!(o1 __matches String s) ? !(o1 __matches String s) : true){ + if (!(o1 instanceof String s) ? !(o1 instanceof String s) : true){ } else { s.length(); } // Test for e1 ? e2: e3 - include e1.T in e2 - if (o1 __matches String s ? s.length()>0 : false) { + if (o1 instanceof String s ? s.length()>0 : false) { System.out.println("done"); } // Test for e1 ? e2 : e3 - include e1.F in e3 - if (!(o1 __matches String s) ? false : s.length()>0){ + if (!(o1 instanceof String s) ? false : s.length()>0){ System.out.println("done"); } // Test for (!e).T = e.F - if (!(!(o1 __matches String s) || !(o3 __matches Integer in))){ + if (!(!(o1 instanceof String s) || !(o3 instanceof Integer in))){ s.length(); i.intValue(); } // Test for (!e).F = e.T - if (!(o1 __matches String s)) { + if (!(o1 instanceof String s)) { } else { s.length(); } + L1: { + if (o1 instanceof String s) { + s.length(); + } else { + break L1; + } + s.length(); + } + L2: { + if (!(o1 instanceof String s)) { + break L2; + } else { + s.length(); + } + s.length(); + } + + L3: { + if ((o1 instanceof String s) || (o3 instanceof String s)) { + s.length(); + } else { + break L3; + } + s.length(); + } System.out.println("BindingsTest1 complete"); }
--- a/test/langtools/tools/javac/patterns/BindingsTest2.java Wed Oct 17 13:56:45 2018 +0200 +++ b/test/langtools/tools/javac/patterns/BindingsTest2.java Wed Oct 24 17:25:26 2018 +0200 @@ -12,103 +12,103 @@ Object o3 = "there"; - if (Ktrue() ? o2 __matches Integer x : o2 __matches String x) { + if (Ktrue() ? o2 instanceof Integer x : o2 instanceof String x) { x.intValue(); } - if (Ktrue() ? o2 __matches Integer x : true) { + if (Ktrue() ? o2 instanceof Integer x : true) { x.intValue(); } - if (o1 __matches String s ? true : true) { + if (o1 instanceof String s ? true : true) { s.length(); } - if (o1 __matches String s ? true : o2 __matches Integer s) { + if (o1 instanceof String s ? true : o2 instanceof Integer s) { s.length(); } - if (o1 __matches String s ? true : o2 __matches Integer i) { + if (o1 instanceof String s ? true : o2 instanceof Integer i) { s.length(); } // Test for (e1 ? e2 : e3).T contains intersect(e1.F, e2.T) - if (!(o1 __matches String s) ? true : true) { + if (!(o1 instanceof String s) ? true : true) { s.length(); } - if (!(o1 __matches String s) ? (o2 __matches Integer s) : true) { + if (!(o1 instanceof String s) ? (o2 instanceof Integer s) : true) { s.length(); } - if (!(o1 __matches String s) ? (o2 __matches Integer i) : true) { + if (!(o1 instanceof String s) ? (o2 instanceof Integer i) : true) { s.length(); i.intValue(); } - if (!(o1 __matches String s) ? (o1 __matches String s2) : true) { + if (!(o1 instanceof String s) ? (o1 instanceof String s2) : true) { s.length(); s2.length(); } // Test for (e1 ? e2 : e3).F contains intersect(e2.F, e3.F) - if (Ktrue() ? !(o2 __matches Integer x) : !(o1 __matches String x)){ + if (Ktrue() ? !(o2 instanceof Integer x) : !(o1 instanceof String x)){ } else { x.intValue(); } - if (Ktrue() ? !(o2 __matches Integer x) : !(o1 __matches String s)){ + if (Ktrue() ? !(o2 instanceof Integer x) : !(o1 instanceof String s)){ } else { x.intValue(); } - if (Ktrue() ? !(o2 __matches Integer x) : !(o2 __matches Integer x1)){ + if (Ktrue() ? !(o2 instanceof Integer x) : !(o2 instanceof Integer x1)){ } else { x.intValue(); x1.intValue(); } - if (Ktrue() ? !(o2 __matches Integer x) : false){ + if (Ktrue() ? !(o2 instanceof Integer x) : false){ } else { x.intValue(); } // Test for (e1 ? e2 : e3).F contains intersect(e1.T, e3.F) - if (o1 __matches String s ? true : !(o2 __matches Integer s)){ + if (o1 instanceof String s ? true : !(o2 instanceof Integer s)){ } else { s.length(); } - if (o1 __matches String s ? true : !(o2 __matches Integer i)){ + if (o1 instanceof String s ? true : !(o2 instanceof Integer i)){ } else { s.length(); i.intValue(); } - if (o1 __matches String s ? true : !(o2 __matches String s1)){ + if (o1 instanceof String s ? true : !(o2 instanceof String s1)){ } else { s.length(); s1.length(); } // Test for (e1 ? e2 : e3).F contains intersect(e1.F, e2.F) - if (!(o1 __matches String s) ? !(o1 __matches String s1) : true){ + if (!(o1 instanceof String s) ? !(o1 instanceof String s1) : true){ } else { s.length(); s1.length(); } - if (!(o1 __matches String s) ? !(o2 __matches Integer s) : true){ + if (!(o1 instanceof String s) ? !(o2 instanceof Integer s) : true){ } else { s.length(); } - if (!(o1 __matches String s) ? !(o2 __matches Integer i) : true){ + if (!(o1 instanceof String s) ? !(o2 instanceof Integer i) : true){ } else { s.length(); i.intValue(); } // Test for e1 ? e2: e3 - include e1.T in e2 - if (o1 __matches String s ? false : s.length()>0) { + if (o1 instanceof String s ? false : s.length()>0) { System.out.println("done"); } - if (o1 __matches String s ? false : s.intValue!=0) { + if (o1 instanceof String s ? false : s.intValue!=0) { System.out.println("done"); } // Test for e1 ? e2 : e3 - include e1.F in e3 - if (!(o1 __matches String s) ? s.length()>0 : false){ + if (!(o1 instanceof String s) ? s.length()>0 : false){ System.out.println("done"); } - if (!(o1 __matches String s) ? s.intValue>0 : false){ + if (!(o1 instanceof String s) ? s.intValue>0 : false){ System.out.println("done"); }
--- a/test/langtools/tools/javac/patterns/BindingsTest2.out Wed Oct 17 13:56:45 2018 +0200 +++ b/test/langtools/tools/javac/patterns/BindingsTest2.out Wed Oct 24 17:25:26 2018 +0200 @@ -2,11 +2,11 @@ BindingsTest2.java:16:13: compiler.err.cant.resolve.location: kindname.variable, x, , , (compiler.misc.location: kindname.class, BindingsTest2, null) BindingsTest2.java:19:13: compiler.err.cant.resolve.location: kindname.variable, x, , , (compiler.misc.location: kindname.class, BindingsTest2, null) BindingsTest2.java:23:13: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null) -BindingsTest2.java:25:35: compiler.err.match.binding.exists.with.different.type +BindingsTest2.java:25:36: compiler.err.match.binding.exists.with.different.type BindingsTest2.java:26:13: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null) BindingsTest2.java:29:13: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null) BindingsTest2.java:34:13: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null) -BindingsTest2.java:36:38: compiler.err.match.binding.exists.with.different.type +BindingsTest2.java:36:39: compiler.err.match.binding.exists.with.different.type BindingsTest2.java:37:13: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null) BindingsTest2.java:40:13: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null) BindingsTest2.java:41:13: compiler.err.cant.resolve.location: kindname.variable, i, , , (compiler.misc.location: kindname.class, BindingsTest2, null) @@ -18,7 +18,7 @@ BindingsTest2.java:60:13: compiler.err.cant.resolve.location: kindname.variable, x, , , (compiler.misc.location: kindname.class, BindingsTest2, null) BindingsTest2.java:61:13: compiler.err.cant.resolve.location: kindname.variable, x1, , , (compiler.misc.location: kindname.class, BindingsTest2, null) BindingsTest2.java:65:13: compiler.err.cant.resolve.location: kindname.variable, x, , , (compiler.misc.location: kindname.class, BindingsTest2, null) -BindingsTest2.java:69:35: compiler.err.match.binding.exists.with.different.type +BindingsTest2.java:69:36: compiler.err.match.binding.exists.with.different.type BindingsTest2.java:71:13: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null) BindingsTest2.java:75:13: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null) BindingsTest2.java:76:13: compiler.err.cant.resolve.location: kindname.variable, i, , , (compiler.misc.location: kindname.class, BindingsTest2, null) @@ -26,12 +26,12 @@ BindingsTest2.java:81:13: compiler.err.cant.resolve.location: kindname.variable, s1, , , (compiler.misc.location: kindname.class, BindingsTest2, null) BindingsTest2.java:86:13: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null) BindingsTest2.java:87:13: compiler.err.cant.resolve.location: kindname.variable, s1, , , (compiler.misc.location: kindname.class, BindingsTest2, null) -BindingsTest2.java:89:38: compiler.err.match.binding.exists.with.different.type +BindingsTest2.java:89:39: compiler.err.match.binding.exists.with.different.type BindingsTest2.java:91:13: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null) BindingsTest2.java:95:13: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null) BindingsTest2.java:96:13: compiler.err.cant.resolve.location: kindname.variable, i, , , (compiler.misc.location: kindname.class, BindingsTest2, null) -BindingsTest2.java:100:45: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null) -BindingsTest2.java:103:45: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null) -BindingsTest2.java:108:40: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null) -BindingsTest2.java:111:40: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null) +BindingsTest2.java:100:46: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null) +BindingsTest2.java:103:46: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null) +BindingsTest2.java:108:41: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null) +BindingsTest2.java:111:41: compiler.err.cant.resolve.location: kindname.variable, s, , , (compiler.misc.location: kindname.class, BindingsTest2, null) 36 errors
--- a/test/langtools/tools/javac/patterns/CastConversionMatch.java Wed Oct 17 13:56:45 2018 +0200 +++ b/test/langtools/tools/javac/patterns/CastConversionMatch.java Wed Oct 24 17:25:26 2018 +0200 @@ -31,11 +31,6 @@ public class CastConversionMatch { public static void main(String [] args) { Object o = 42; - if (o __matches int s) { - System.out.println("Okay"); - } else { - throw new AssertionError("broken"); - } switch (o) { case int i: { System.out.println("Okay;");
--- a/test/langtools/tools/javac/patterns/ConstantPatternTest1.java Wed Oct 17 13:56:45 2018 +0200 +++ b/test/langtools/tools/javac/patterns/ConstantPatternTest1.java Wed Oct 24 17:25:26 2018 +0200 @@ -34,28 +34,6 @@ i++; final int constantInt = 42; - - // Simple literal constant pattern - if (i __matches 42) { - message(); - } else { - throw new AssertionError("Broken"); - } - - // Simple constant expression pattern - if (i __matches 41+1) { - message(); - } else { - throw new AssertionError("Broken"); - } - - // Constant expression pattern using a final local - if (i __matches constantInt) { - message(); - } else { - throw new AssertionError("Broken"); - } - //--- Tests for match statement // Simple literal constant pattern @@ -150,27 +128,6 @@ //--- Tests for matches expression - // Simple literal constant pattern - if (d __matches 42.0) { - message(); - } else { - throw new AssertionError("Broken"); - } - - // Simple constant expression pattern - if (d __matches 41.0+1.0) { - message(); - } else { - throw new AssertionError("Broken"); - } - - // Constant expression pattern using a final local - if (d __matches constant) { - message(); - } else { - throw new AssertionError("Broken"); - } - //--- Tests for match statement // Simple literal constant pattern @@ -260,27 +217,6 @@ String s = "Hello"; final String hello = "Hello"; - // Simple literal constant pattern - if (s __matches "Hello") { - message(); - } else { - throw new AssertionError("Broken"); - } - - // Simple constant expression pattern - if (s __matches "Hell"+"o") { - message(); - } else { - throw new AssertionError("Broken"); - } - - // Constant expression pattern using a final local - if (s __matches hello) { - message(); - } else { - throw new AssertionError("Broken"); - } - //--- Tests for match statement // Simple literal constant pattern @@ -385,47 +321,6 @@ throw new AssertionError("Broken"); } } -// ----- Constant expression patterns and reference typed expressions - - Object obj = "Hello"; - - if (obj __matches "Hello") { - message(); - } else { - throw new AssertionError("Broken"); - } - if (obj __matches null) { - throw new AssertionError("Broken"); - } - obj = 42; - if (obj __matches 42) { - message(); - } else { - throw new AssertionError("Broken"); - } - - if (obj __matches var x) { - if (obj __matches 42) { - message(); - } else { - throw new AssertionError("Broken"); - } - } else { - throw new AssertionError("Broken"); - } - - if (obj __matches 42) { - if (obj __matches var x) { - message(); - } - } - if (obj __matches null) { - throw new AssertionError("Broken"); - } - if (null __matches "Hello") { - throw new AssertionError("Broken"); - } - fortyTwoTester(42); fortyTwoTester(42.0);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/tools/javac/patterns/ConstantPatternTest2.java Wed Oct 24 17:25:26 2018 +0200 @@ -0,0 +1,106 @@ +/* + * @test + * @summary Basic tests for constant patterns + * @compile/fail/ref=ConstantPatternTest2.out -XDrawDiagnostics ConstantPatternTest2.java + */ + +public class ConstantPatternTest2 { + + public static double valueOfD(){ + return 41.0; + } + + public static void main(String[] args) { + + int i = 41; + i++; + final int constantInt = 42; + + + // Simple literal constant pattern + if (i instanceof 42) { + throw new AssertionError("Broken"); + } + + // Simple constant expression pattern + if (i instanceof 41+1) { + throw new AssertionError("Broken"); + } + + // Constant expression pattern using a final local + if (i instanceof constantInt) { + throw new AssertionError("Broken"); + } + +//--- DOUBLE TYPED CONSTANT EXPRESSIONS + + double d = valueOfD(); + d++; + final double constant = 42.0; + + // Simple literal constant pattern + if (d instanceof 42.0) { + throw new AssertionError("Broken"); + } + + // Simple constant expression pattern + if (d instanceof 41.0+1.0) { + throw new AssertionError("Broken"); + } + + // Constant expression pattern using a final local + if (d instanceof constant) { + throw new AssertionError("Broken"); + } + +//--- STRING TYPED CONSTANT EXPRESSIONS ---- + + String s = "Hello"; + final String hello = "Hello"; + + // Simple literal constant pattern + if (s instanceof "Hello") { + throw new AssertionError("Broken"); + } + + // Simple constant expression pattern + if (s instanceof "Hell"+"o") { + throw new AssertionError("Broken"); + } + + // Constant expression pattern using a final local + if (s instanceof hello) { + throw new AssertionError("Broken"); + } + +// ----- Constant expression patterns and reference typed expressions + + Object obj = "Hello"; + + if (obj instanceof "Hello") { + throw new AssertionError("Broken"); + } + if (obj instanceof null) { + throw new AssertionError("Broken"); + } + obj = 42; + if (obj instanceof 42) { + throw new AssertionError("Broken"); + } + + if (obj instanceof var x) { + throw new AssertionError("Broken"); + } + + if (obj instanceof 42) { + } + if (obj instanceof null) { + throw new AssertionError("Broken"); + } + if (null instanceof "Hello") { + throw new AssertionError("Broken"); + } + + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/tools/javac/patterns/ConstantPatternTest2.out Wed Oct 24 17:25:26 2018 +0200 @@ -0,0 +1,28 @@ +ConstantPatternTest2.java:21:26: compiler.err.illegal.start.of.type +ConstantPatternTest2.java:21:28: compiler.err.expected: ';' +ConstantPatternTest2.java:26:26: compiler.err.illegal.start.of.type +ConstantPatternTest2.java:26:28: compiler.err.not.stmt +ConstantPatternTest2.java:26:30: compiler.err.expected: ';' +ConstantPatternTest2.java:42:26: compiler.err.illegal.start.of.type +ConstantPatternTest2.java:42:30: compiler.err.expected: ';' +ConstantPatternTest2.java:47:26: compiler.err.illegal.start.of.type +ConstantPatternTest2.java:47:30: compiler.err.not.stmt +ConstantPatternTest2.java:47:34: compiler.err.expected: ';' +ConstantPatternTest2.java:62:26: compiler.err.illegal.start.of.type +ConstantPatternTest2.java:62:33: compiler.err.expected: ';' +ConstantPatternTest2.java:67:26: compiler.err.illegal.start.of.type +ConstantPatternTest2.java:67:36: compiler.err.expected: ';' +ConstantPatternTest2.java:80:28: compiler.err.illegal.start.of.type +ConstantPatternTest2.java:80:35: compiler.err.expected: ';' +ConstantPatternTest2.java:83:28: compiler.err.illegal.start.of.type +ConstantPatternTest2.java:83:32: compiler.err.expected: ';' +ConstantPatternTest2.java:87:28: compiler.err.illegal.start.of.type +ConstantPatternTest2.java:87:30: compiler.err.expected: ';' +ConstantPatternTest2.java:91:17: compiler.err.var.not.allowed +ConstantPatternTest2.java:95:28: compiler.err.illegal.start.of.type +ConstantPatternTest2.java:95:30: compiler.err.expected: ';' +ConstantPatternTest2.java:97:28: compiler.err.illegal.start.of.type +ConstantPatternTest2.java:97:32: compiler.err.expected: ';' +ConstantPatternTest2.java:100:29: compiler.err.illegal.start.of.type +ConstantPatternTest2.java:100:36: compiler.err.expected: ';' +27 errors
--- a/test/langtools/tools/javac/patterns/DuplicateBindingTest.java Wed Oct 17 13:56:45 2018 +0200 +++ b/test/langtools/tools/javac/patterns/DuplicateBindingTest.java Wed Oct 24 17:25:26 2018 +0200 @@ -12,7 +12,7 @@ if (args != null) { int s; - if (args[0] __matches String s) { // NOT OK. Redef same scope. + if (args[0] instanceof String s) { // NOT OK. Redef same scope. } int k; switch(args[0]) {
--- a/test/langtools/tools/javac/patterns/DuplicateBindingTest.out Wed Oct 17 13:56:45 2018 +0200 +++ b/test/langtools/tools/javac/patterns/DuplicateBindingTest.out Wed Oct 24 17:25:26 2018 +0200 @@ -1,4 +1,4 @@ -DuplicateBindingTest.java:15:35: compiler.err.already.defined: kindname.variable, s, kindname.method, main(java.lang.String[]) +DuplicateBindingTest.java:15:36: compiler.err.already.defined: kindname.variable, s, kindname.method, main(java.lang.String[]) DuplicateBindingTest.java:19:22: compiler.err.already.defined: kindname.variable, k, kindname.method, main(java.lang.String[]) DuplicateBindingTest.java:21:22: compiler.err.already.defined: kindname.variable, args, kindname.method, main(java.lang.String[]) DuplicateBindingTest.java:18:19: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Integer)
--- a/test/langtools/tools/javac/patterns/EnsureTypesOrderTest.java Wed Oct 17 13:56:45 2018 +0200 +++ b/test/langtools/tools/javac/patterns/EnsureTypesOrderTest.java Wed Oct 24 17:25:26 2018 +0200 @@ -6,7 +6,7 @@ */ public class EnsureTypesOrderTest { public static void main(String [] args) { - if (args __matches String s) { + if (args instanceof String s) { System.out.println("Broken"); } }
--- a/test/langtools/tools/javac/patterns/ExamplesFromProposal.java Wed Oct 17 13:56:45 2018 +0200 +++ b/test/langtools/tools/javac/patterns/ExamplesFromProposal.java Wed Oct 24 17:25:26 2018 +0200 @@ -103,7 +103,7 @@ public static void main(String[] args) { Object x = new Integer(42); - if (x __matches Integer i) { + if (x instanceof Integer i) { // can use i here System.out.println(i.intValue()); } @@ -111,19 +111,19 @@ Object obj = getSomething(); String formatted = "unknown"; - if (obj __matches Integer i) { + if (obj instanceof Integer i) { formatted = String.format("int %d", i); } - else if (obj __matches Byte b) { + else if (obj instanceof Byte b) { formatted = String.format("byte %d", b); } - else if (obj __matches Long l) { + else if (obj instanceof Long l) { formatted = String.format("long %d", l); } - else if (obj __matches Double d) { + else if (obj instanceof Double d) { formatted = String.format("double %f", d); } - else if (obj __matches String s) { + else if (obj instanceof String s) { formatted = String.format("String %s", s); } System.out.println(formatted); @@ -189,19 +189,19 @@ x = "Hello"; - if (x __matches String s1) { + if (x instanceof String s1) { System.out.println(s1); } - if (x __matches String s1 && s1.length() > 0) { + if (x instanceof String s1 && s1.length() > 0) { System.out.println(s1); } - if (x __matches String s1) { + if (x instanceof String s1) { System.out.println(s1 + " is a string"); } else { System.out.println("not a string"); } - if (!(x __matches String s1)) { + if (!(x instanceof String s1)) { System.out.println("not a string"); } else { System.out.println(s1 + " is a string");
--- a/test/langtools/tools/javac/patterns/ImpossibleTypeTest.java Wed Oct 17 13:56:45 2018 +0200 +++ b/test/langtools/tools/javac/patterns/ImpossibleTypeTest.java Wed Oct 24 17:25:26 2018 +0200 @@ -10,10 +10,10 @@ int in = 42; Integer i = 42; - if (i __matches String s ) { + if (i instanceof String s ) { System.out.println("Broken"); } - if (i __matches Undefined u ) { + if (i instanceof Undefined u ) { System.out.println("Broken"); } }
--- a/test/langtools/tools/javac/patterns/ImpossibleTypeTest.out Wed Oct 17 13:56:45 2018 +0200 +++ b/test/langtools/tools/javac/patterns/ImpossibleTypeTest.out Wed Oct 24 17:25:26 2018 +0200 @@ -1,3 +1,3 @@ ImpossibleTypeTest.java:13:13: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Integer, java.lang.String) -ImpossibleTypeTest.java:16:25: compiler.err.cant.resolve.location: kindname.class, Undefined, , , (compiler.misc.location: kindname.class, ImpossibleTypeTest, null) +ImpossibleTypeTest.java:16:26: compiler.err.cant.resolve.location: kindname.class, Undefined, , , (compiler.misc.location: kindname.class, ImpossibleTypeTest, null) 2 errors
--- a/test/langtools/tools/javac/patterns/MatchBindingScopeTest.java Wed Oct 17 13:56:45 2018 +0200 +++ b/test/langtools/tools/javac/patterns/MatchBindingScopeTest.java Wed Oct 24 17:25:26 2018 +0200 @@ -11,18 +11,18 @@ static Object o2 = i; public static void main(String[] args) { - - if (o1 __matches String j && j.length() == 5) { // OK + + if (o1 instanceof String j && j.length() == 5) { // OK System.out.println(j); // OK } else { System.out.println(j); // NOT OK } // NOT OK, name reused. - if (o1 __matches String j && o2 __matches Integer j) { + if (o1 instanceof String j && o2 instanceof Integer j) { } - if (o1 __matches String j && j.length() == 5 && o2 __matches Integer k && k == 42) { // OK + if (o1 instanceof String j && j.length() == 5 && o2 instanceof Integer k && k == 42) { // OK System.out.println(j); // OK System.out.println(k); // OK } else { @@ -30,29 +30,29 @@ System.out.println(k); // NOT OK } - if (o1 __matches String j || j.length() == 5) { // NOT OK + if (o1 instanceof String j || j.length() == 5) { // NOT OK System.out.println(j); // NOT OK } - if (o1 __matches String j || o2 __matches Integer j) { // NOT OK, types differ + if (o1 instanceof String j || o2 instanceof Integer j) { // NOT OK, types differ System.out.println(j); // NOT OK } else { System.out.println(j); // NOT OK. } - while (o1 __matches String j && j.length() == 5) { // OK + while (o1 instanceof String j && j.length() == 5) { // OK System.out.println(j); // OK } - while (o1 __matches String j || true) { + while (o1 instanceof String j || true) { System.out.println(j); // Not OK } - for (; o1 __matches String j; j.length()) { // OK + for (; o1 instanceof String j; j.length()) { // OK System.out.println(j); // OK } - for (; o1 __matches String j || true; j.length()) { // NOT OK + for (; o1 instanceof String j || true; j.length()) { // NOT OK System.out.println(j); // Not OK } @@ -65,11 +65,11 @@ break; } - int x = o1 __matches String j ? + int x = o1 instanceof String j ? j.length() : // OK. j.length(); // NOT OK. - x = !(o1 __matches String j) ? + x = !(o1 instanceof String j) ? j.length() : // NOT OK. j.length(); // OK. }
--- a/test/langtools/tools/javac/patterns/MatchBindingScopeTest.out Wed Oct 17 13:56:45 2018 +0200 +++ b/test/langtools/tools/javac/patterns/MatchBindingScopeTest.out Wed Oct 24 17:25:26 2018 +0200 @@ -1,15 +1,15 @@ MatchBindingScopeTest.java:18:32: compiler.err.cant.resolve.location: kindname.variable, j, , , (compiler.misc.location: kindname.class, MatchBindingScopeTest, null) -MatchBindingScopeTest.java:22:51: compiler.err.already.defined: kindname.variable, j, kindname.method, main(java.lang.String[]) -MatchBindingScopeTest.java:22:35: compiler.err.match.binding.exists +MatchBindingScopeTest.java:22:53: compiler.err.already.defined: kindname.variable, j, kindname.method, main(java.lang.String[]) +MatchBindingScopeTest.java:22:36: compiler.err.match.binding.exists MatchBindingScopeTest.java:29:32: compiler.err.cant.resolve.location: kindname.variable, j, , , (compiler.misc.location: kindname.class, MatchBindingScopeTest, null) MatchBindingScopeTest.java:30:32: compiler.err.cant.resolve.location: kindname.variable, k, , , (compiler.misc.location: kindname.class, MatchBindingScopeTest, null) -MatchBindingScopeTest.java:33:38: compiler.err.cant.resolve.location: kindname.variable, j, , , (compiler.misc.location: kindname.class, MatchBindingScopeTest, null) +MatchBindingScopeTest.java:33:39: compiler.err.cant.resolve.location: kindname.variable, j, , , (compiler.misc.location: kindname.class, MatchBindingScopeTest, null) MatchBindingScopeTest.java:34:32: compiler.err.cant.resolve.location: kindname.variable, j, , , (compiler.misc.location: kindname.class, MatchBindingScopeTest, null) -MatchBindingScopeTest.java:37:35: compiler.err.match.binding.exists.with.different.type +MatchBindingScopeTest.java:37:36: compiler.err.match.binding.exists.with.different.type MatchBindingScopeTest.java:38:32: compiler.err.cant.resolve.location: kindname.variable, j, , , (compiler.misc.location: kindname.class, MatchBindingScopeTest, null) MatchBindingScopeTest.java:40:32: compiler.err.cant.resolve.location: kindname.variable, j, , , (compiler.misc.location: kindname.class, MatchBindingScopeTest, null) MatchBindingScopeTest.java:48:32: compiler.err.cant.resolve.location: kindname.variable, j, , , (compiler.misc.location: kindname.class, MatchBindingScopeTest, null) -MatchBindingScopeTest.java:55:47: compiler.err.cant.resolve.location: kindname.variable, j, , , (compiler.misc.location: kindname.class, MatchBindingScopeTest, null) +MatchBindingScopeTest.java:55:48: compiler.err.cant.resolve.location: kindname.variable, j, , , (compiler.misc.location: kindname.class, MatchBindingScopeTest, null) MatchBindingScopeTest.java:56:32: compiler.err.cant.resolve.location: kindname.variable, j, , , (compiler.misc.location: kindname.class, MatchBindingScopeTest, null) MatchBindingScopeTest.java:64:21: compiler.err.cant.resolve.location: kindname.variable, x, , , (compiler.misc.location: kindname.class, MatchBindingScopeTest, null) MatchBindingScopeTest.java:70:23: compiler.err.cant.resolve.location: kindname.variable, j, , , (compiler.misc.location: kindname.class, MatchBindingScopeTest, null)
--- a/test/langtools/tools/javac/patterns/MatchesToken.java Wed Oct 17 13:56:45 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -/** - * @test - * @compile MatchesToken.java - */ -public class MatchesToken { - public void test(Object o) { - final int __matches = 1; - boolean b1 = __matches __matches __matches; - boolean b2 = o __matches __matches; - boolean b3 = __matches __matches Integer i; - boolean b4 = (__matches __matches __matches) __matches true; - } - - private void test() { - I1 i1 = (int __matches) -> {}; - I2 i2 = (int __matches, int other) -> {}; - } - - interface I1 { - public void m(int i); - } - - interface I2 { - public void m(int i1, int i2); - } -} -
--- a/test/langtools/tools/javac/patterns/NestingMatchAndMatches.java Wed Oct 17 13:56:45 2018 +0200 +++ b/test/langtools/tools/javac/patterns/NestingMatchAndMatches.java Wed Oct 24 17:25:26 2018 +0200 @@ -10,42 +10,16 @@ Object o = "Hello"; - //Nested matches - if ((o __matches String s) __matches boolean b) { - System.out.println("String!"); - } else { - throw new AssertionError("broken"); - } - if ((o __matches String s) __matches false) { - throw new AssertionError("broken"); - } else { - System.out.println("String "); - } - - if ((o __matches String s) __matches true) { - System.out.println("String!"); - } else { - throw new AssertionError("broken"); - } - - boolean b = (o __matches String s) ? (s __matches "Hello") : false; - - if (b) { - System.out.println("yes!"); - } else { - throw new AssertionError("broken"); - } - //matches inside a match switch (o) { case String s: - if (s __matches String t) { + if (s instanceof String t) { System.out.println(s+"-"+t); } } switch (o) { case String s: - if (o __matches Integer t) { + if (o instanceof Integer t) { System.out.println(s+"-"+t); throw new AssertionError("broken"); } else { @@ -107,7 +81,7 @@ case String s: switch (o2) { case String t: - if (t __matches String u) { + if (t instanceof String u) { System.out.println(s+"-"+t+"--"+u); } else { throw new AssertionError("broken");
--- a/test/langtools/tools/javac/patterns/NullsInPatterns.java Wed Oct 17 13:56:45 2018 +0200 +++ b/test/langtools/tools/javac/patterns/NullsInPatterns.java Wed Oct 24 17:25:26 2018 +0200 @@ -24,37 +24,28 @@ /* * @test * @summary Testing pattern matching against the null constant + * @compile NullsInPatterns.java * @run main NullsInPatterns */ import java.util.List; public class NullsInPatterns { - + public static void main(String[] args) { - if (null __matches List t) { + if (null instanceof List t) { throw new AssertionError("broken"); } else { System.out.println("null does not match List type pattern"); } - if (null __matches List<Integer> l) { + if (null instanceof List<Integer> l) { throw new AssertionError("broken"); } else { System.out.println("null does not match List<Integer> type pattern"); } - if (null __matches List<?> l) { + if (null instanceof List<?> l) { throw new AssertionError("broken"); } else { System.out.println("null does not match List<?> type pattern"); } - if (null __matches var x) { - System.out.println("null matches var type pattern"); - } else { - throw new AssertionError("broken"); - } - if (null __matches null) { - System.out.println("null matches null constant pattern"); - } else { - throw new AssertionError("broken"); - } } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/tools/javac/patterns/NullsInPatterns2.java Wed Oct 24 17:25:26 2018 +0200 @@ -0,0 +1,38 @@ +/* + * 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. + * + * 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 + * @summary Testing pattern matching against the null constant + * @compile/fail/ref=NullsInPatterns2.out -XDrawDiagnostics NullsInPatterns2.java + */ + +public class NullsInPatterns2 { + + public static void main(String[] args) { + if (null instanceof var x) { + } + if (null instanceof null) { + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/tools/javac/patterns/NullsInPatterns2.out Wed Oct 24 17:25:26 2018 +0200 @@ -0,0 +1,4 @@ +NullsInPatterns2.java:33:18: compiler.err.var.not.allowed +NullsInPatterns2.java:35:29: compiler.err.illegal.start.of.type +NullsInPatterns2.java:35:33: compiler.err.expected: ';' +3 errors
--- a/test/langtools/tools/javac/patterns/PatternMatchPosTest.java Wed Oct 17 13:56:45 2018 +0200 +++ b/test/langtools/tools/javac/patterns/PatternMatchPosTest.java Wed Oct 24 17:25:26 2018 +0200 @@ -61,7 +61,7 @@ SourcePositions sp = trees.getSourcePositions(); TreePath dataPath = trees.getPath(data); String text = dataPath.getCompilationUnit().getSourceFile().getCharContent(true).toString(); - + new TreeScanner<Void, Void>() { boolean print; @Override @@ -117,9 +117,11 @@ class PatternMatchPosTestData { void data(Object o) { - if (o __matches 1) { } - if (o __matches var s) { } - if (o __matches String s) { } + //no constants in instanceof +// if (o instanceof 1) { } + //no var in instanceof: +// if (o instanceof var s) { } + if (o instanceof String s) { } switch (o) { case 1: break; case String s: break;
--- a/test/langtools/tools/javac/patterns/PatternMatchPosTest.out Wed Oct 17 13:56:45 2018 +0200 +++ b/test/langtools/tools/javac/patterns/PatternMatchPosTest.out Wed Oct 24 17:25:26 2018 +0200 @@ -1,14 +1,5 @@ -(o __matches 1) -o __matches 1 -o -1 -1 -(o __matches var s) -o __matches var s -o -var s -(o __matches String s) -o __matches String s +(o instanceof String s) +o instanceof String s o String s String
--- a/test/langtools/tools/javac/patterns/PatternTypeTest1.java Wed Oct 17 13:56:45 2018 +0200 +++ b/test/langtools/tools/javac/patterns/PatternTypeTest1.java Wed Oct 24 17:25:26 2018 +0200 @@ -34,7 +34,7 @@ String s = "Hello"; Object o = i; - if (o __matches var j) { + if (o instanceof var j) { System.out.println("Match all"); } else { throw new AssertionError("Broken");
--- a/test/langtools/tools/javac/patterns/PatternTypeTest2.java Wed Oct 17 13:56:45 2018 +0200 +++ b/test/langtools/tools/javac/patterns/PatternTypeTest2.java Wed Oct 24 17:25:26 2018 +0200 @@ -34,7 +34,7 @@ String s = "Hello"; Object o = i; - if (o __matches Integer j) { + if (o instanceof Integer j) { System.out.println("It's an Integer"); } else { throw new AssertionError("Broken");
--- a/test/langtools/tools/javac/patterns/PatternVariablesAreFinal.java Wed Oct 17 13:56:45 2018 +0200 +++ b/test/langtools/tools/javac/patterns/PatternVariablesAreFinal.java Wed Oct 24 17:25:26 2018 +0200 @@ -6,7 +6,7 @@ public class PatternVariablesAreFinal { public static void main(String[] args) { Object o = 32; - if (o __matches String s) { + if (o instanceof String s) { s = "hello again"; System.out.println(s); }
--- a/test/langtools/tools/javac/patterns/PatternVariablesAreFinal2.java Wed Oct 17 13:56:45 2018 +0200 +++ b/test/langtools/tools/javac/patterns/PatternVariablesAreFinal2.java Wed Oct 24 17:25:26 2018 +0200 @@ -6,7 +6,7 @@ public class PatternVariablesAreFinal2 { public static void main(String[] args) { Object o = "42"; - if (o __matches String s) { + if (o instanceof String s) { new Object() { void run() { System.err.println(s); } }.run();
--- a/test/langtools/tools/javac/patterns/UncheckedWarningOnMatchesTest.java Wed Oct 17 13:56:45 2018 +0200 +++ b/test/langtools/tools/javac/patterns/UncheckedWarningOnMatchesTest.java Wed Oct 24 17:25:26 2018 +0200 @@ -11,7 +11,7 @@ public static void main(String [] args) { Object o = new ArrayList<UncheckedWarningOnMatchesTest>(); - if (o __matches ArrayList<Integer> ai) { // unchecked conversion + if (o instanceof ArrayList<Integer> ai) { // unchecked conversion System.out.println("Blah"); } switch (o) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/tools/javac/patterns/scope/ScopeTest.java Wed Oct 24 17:25:26 2018 +0200 @@ -0,0 +1,147 @@ +/* + * 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. + */ + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import org.testng.ITestResult; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.Test; +import tools.javac.combo.JavacTemplateTestBase; + +import static java.util.stream.Collectors.toList; + +@Test +public class ScopeTest extends JavacTemplateTestBase { + + private static String st_block(String... statements) { + return Arrays.stream(statements).collect(Collectors.joining("", "{", "}")); + } + + private static String st_if(String condition, String then, String els) { + return "if (" + condition + ") " + then + " else " + els; + } + + private static String st_while(String condition, String body) { + return "while (" + condition + ") " + body; + } + + private static String st_do_while(String body, String condition) { + return "do " + body + " while (" + condition + ");"; + } + + private static String st_for(String init, String condition, String update, String body) { + return "for (" + init + "; " + condition + "; " + update + ") " + body; + } + + private static String st_s_use() { + return "s.length();"; + } + + private static String st_break() { + return "break;"; + } + + private static String st_return() { + return "return;"; + } + + private static String st_noop() { + return ";"; + } + + private static String expr_empty() { + return ""; + } + + private static String expr_o_match_str() { + return "o instanceof String s"; + } + + private static String expr_not(String expr) { + return "!(" + expr + ")"; + } + + @AfterMethod + public void dumpTemplateIfError(ITestResult result) { + // Make sure offending template ends up in log file on failure + if (!result.isSuccess()) { + System.err.printf("Diagnostics: %s%nTemplate: %s%n", diags.errorKeys(), sourceFiles.stream().map(p -> p.snd).collect(toList())); + } + } + + private void program(String block) { + String s = "class C { void m(Object o) " + block + "}"; + addSourceFile("C.java", new StringTemplate(s)); + } + + private void assertOK(String block) { + reset(); + program(block); + try { + compile(); + } + catch (IOException e) { + throw new RuntimeException(e); + } + assertCompileSucceeded(); + } + + private void assertFail(String expectedDiag, String block) { + reset(); + addCompileOptions("--enable-preview", "-source", "12"); + program(block); + try { + compile(); + } + catch (IOException e) { + throw new RuntimeException(e); + } + assertCompileFailed(expectedDiag); + } + + public void testIf() { + assertOK(st_block(st_if(expr_o_match_str(), st_s_use(), st_return()), st_s_use())); + assertOK(st_block(st_if(expr_not(expr_o_match_str()), st_return(), st_s_use()), st_s_use())); + assertFail("compiler.err.cant.resolve.location", st_block(st_if(expr_o_match_str(), st_s_use(), st_noop()), st_s_use())); + assertFail("compiler.err.cant.resolve.location", st_block(st_if(expr_not(expr_o_match_str()), st_noop(), st_s_use()), st_s_use())); + } + + public void testWhile() { + assertOK(st_block(st_while(expr_not(expr_o_match_str()), st_noop()), st_s_use())); + assertFail("compiler.err.cant.resolve.location", st_block(st_while(expr_not(expr_o_match_str()), st_break()), st_s_use())); + } + + public void testDoWhile() { + assertOK(st_block(st_do_while(st_noop(), expr_not(expr_o_match_str())), st_s_use())); + assertFail("compiler.err.cant.resolve.location", st_block(st_do_while(st_break(), expr_not(expr_o_match_str())), st_s_use())); + } + + public void testFor() { + assertOK(st_block(st_for(expr_empty(), expr_not(expr_o_match_str()), expr_empty(), st_noop()), st_s_use())); + assertFail("compiler.err.cant.resolve.location", st_block(st_for(expr_empty(), expr_not(expr_o_match_str()), expr_empty(), st_break()), st_s_use())); + } + +}