8223305: Compiler support for Switch Expressions
Reviewed-by: mcimadamore, vromero
This commit is contained in:
parent
c569ad302a
commit
b34b2d993c
src
java.compiler/share/classes/javax/lang/model
jdk.compiler/share/classes/com/sun
source
tools/javac
code
comp
ArgumentAttr.javaAttr.javaAttrContext.javaDeferredAttr.javaFlow.javaLower.javaMemberEnter.javaResolve.javaTransTypes.javaTreeDiffer.java
jvm
parser
resources
tree
util
test/langtools/tools/javac
diags/examples
BracketsNotAllowedImplicitLambda.javaBreakExprNotImmediate.javaFutureVarNotAllowed.javaIllegalRefToRestrictedType.javaIllegalRefToVarType.javaInvalidYield.javaInvalidYieldWarning.javaNoSwitchExpression.javaNoSwitchExpressionQualify.javaRestrictedTypeNotAllowedPreview.javaSwitchExpressions.javaVarNotAllowed.javaVarNotAllowedArray.javaVarNotAllowedCompound.javaVarNotAllowedHere.java
expswitch
lambda/deduplication
lib
lvti
parser
switchexpr
BreakTest.javaDefiniteAssignment1.javaDefiniteAssignment2.javaExpressionSwitch.javaExpressionSwitchBreaks1.javaExpressionSwitchBreaks2.javaExpressionSwitchBreaks2.outExpressionSwitchBugs.javaExpressionSwitchDA.javaExpressionSwitchEmbedding.javaExpressionSwitchFallThrough.javaExpressionSwitchFallThrough1.javaExpressionSwitchFlow.javaExpressionSwitchInExpressionSwitch.javaExpressionSwitchInfer.javaExpressionSwitchNotExhaustive.javaExpressionSwitchToString.javaExpressionSwitchUnreachable.javaParseIncomplete.javaSwitchExpressionIsNotAConstant.javaSwitchExpressionScopesIsolated.javaSwitchExpressionSimpleVisitorTest.javaTryCatch.javaWarnWrongYieldTest.javaWarnWrongYieldTest.outWrongBreakTest.javaWrongBreakTest.outWrongYieldTest.javaWrongYieldTest.out
switchextra
DefiniteAssignment1.javaDefiniteAssignment2.javaDefiniteAssignment2.outMultipleLabelsExpression.java
var_implicit_lambda
@ -257,8 +257,8 @@ public enum SourceVersion {
|
||||
* followed only by characters for which {@link
|
||||
* Character#isJavaIdentifierPart(int)} returns {@code true}.
|
||||
* This pattern matches regular identifiers, keywords, restricted
|
||||
* keywords, and the literals {@code "true"}, {@code "false"},
|
||||
* {@code "null"}, and {@code "var"}.
|
||||
* keywords, restricted identifiers and the literals {@code "true"},
|
||||
* {@code "false"}, {@code "null"}.
|
||||
*
|
||||
* The method returns {@code false} for all other strings.
|
||||
*
|
||||
@ -295,7 +295,7 @@ public enum SourceVersion {
|
||||
* for keywords, boolean literals, and the null literal.
|
||||
*
|
||||
* This method returns {@code true} for <i>restricted
|
||||
* keywords</i> and {@code "var"}.
|
||||
* keywords</i> and <i>restricted identifiers</i>
|
||||
*
|
||||
* @param name the string to check
|
||||
* @return {@code true} if this string is a
|
||||
@ -314,7 +314,7 @@ public enum SourceVersion {
|
||||
* for keywords, boolean literals, and the null literal.
|
||||
*
|
||||
* This method returns {@code true} for <i>restricted
|
||||
* keywords</i> and {@code "var"}.
|
||||
* keywords</i> and <i>restricted identifiers</i>
|
||||
*
|
||||
* @param name the string to check
|
||||
* @param version the version to use
|
||||
@ -338,7 +338,7 @@ public enum SourceVersion {
|
||||
* Returns whether or not {@code s} is a keyword, boolean literal,
|
||||
* or null literal in the latest source version.
|
||||
* This method returns {@code false} for <i>restricted
|
||||
* keywords</i> and {@code "var"}.
|
||||
* keywords</i> and <i>restricted identifiers</i>.
|
||||
*
|
||||
* @param s the string to check
|
||||
* @return {@code true} if {@code s} is a keyword, or boolean
|
||||
@ -355,7 +355,7 @@ public enum SourceVersion {
|
||||
* Returns whether or not {@code s} is a keyword, boolean literal,
|
||||
* or null literal in the given source version.
|
||||
* This method returns {@code false} for <i>restricted
|
||||
* keywords</i> and {@code "var"}.
|
||||
* keywords</i> and <i>restricted identifiers</i>.
|
||||
*
|
||||
* @param s the string to check
|
||||
* @param version the version to use
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -35,8 +35,6 @@ import javax.lang.model.element.Name;
|
||||
* break;
|
||||
*
|
||||
* break <em>label</em> ;
|
||||
*
|
||||
* break <em>expression</em> ;
|
||||
* </pre>
|
||||
*
|
||||
* @jls 14.15 The break Statement
|
||||
@ -52,17 +50,4 @@ public interface BreakTree extends StatementTree {
|
||||
*/
|
||||
Name getLabel();
|
||||
|
||||
/**
|
||||
* Returns the expression for this {@code break} statement.
|
||||
*
|
||||
* @return the expression
|
||||
* @since 12
|
||||
*
|
||||
* @deprecated This method is modeling value breaks, which are part of
|
||||
* a preview feature and may be removed if the preview feature
|
||||
* is removed.
|
||||
*
|
||||
*/
|
||||
@Deprecated(forRemoval=true, since="12")
|
||||
ExpressionTree getValue();
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -656,7 +656,21 @@ public interface Tree {
|
||||
* An implementation-reserved node. This is the not the node
|
||||
* you are looking for.
|
||||
*/
|
||||
OTHER(null);
|
||||
OTHER(null),
|
||||
|
||||
/**
|
||||
* Used for instances of {@link YieldTree}.
|
||||
*
|
||||
* @since 13
|
||||
*
|
||||
* @deprecated
|
||||
* This enum constant is modeling yield statement,
|
||||
* which are part of a preview feature and may be removed
|
||||
* if the preview feature is removed.
|
||||
*/
|
||||
@Deprecated(forRemoval=true, since="13")
|
||||
@SuppressWarnings("removal")
|
||||
YIELD(YieldTree.class);
|
||||
|
||||
|
||||
Kind(Class<? extends Tree> intf) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -555,4 +555,20 @@ public interface TreeVisitor<R,P> {
|
||||
* @return a result value
|
||||
*/
|
||||
R visitOther(Tree node, P p);
|
||||
|
||||
/**
|
||||
* Visits a YieldTree node.
|
||||
* @param node the node being visited
|
||||
* @param p a parameter value
|
||||
* @return a result value
|
||||
* @since 13
|
||||
*
|
||||
* @deprecated
|
||||
* This method is modeling yield statement,
|
||||
* which are part of a preview feature and may be removed
|
||||
* if the preview feature is removed.
|
||||
*/
|
||||
@Deprecated(forRemoval=true, since="13")
|
||||
@SuppressWarnings("removal")
|
||||
R visitYield(YieldTree node, P p);
|
||||
}
|
||||
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. 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 a {@code yield} statement.
|
||||
*
|
||||
* For example:
|
||||
* <pre>
|
||||
* yield <em>expression</em> ;
|
||||
* </pre>
|
||||
*
|
||||
* @jls section TODO
|
||||
*
|
||||
* @since 13
|
||||
*
|
||||
* @deprecated This class is modeling yield from switch expressions,
|
||||
* which are part of a preview feature and may be removed if
|
||||
* the preview feature is removed.
|
||||
*/
|
||||
@Deprecated(forRemoval=true, since="13")
|
||||
public interface YieldTree extends StatementTree {
|
||||
|
||||
/**
|
||||
* Returns the expression for this {@code yield} statement.
|
||||
*
|
||||
* @return the expression
|
||||
*/
|
||||
ExpressionTree getValue();
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -782,4 +782,18 @@ public class SimpleTreeVisitor <R,P> implements TreeVisitor<R,P> {
|
||||
public R visitOther(Tree 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
|
||||
@Deprecated(forRemoval=true, since="13")
|
||||
@SuppressWarnings("removal")
|
||||
public R visitYield(YieldTree node, P p) {
|
||||
return defaultAction(node, p);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -467,9 +467,8 @@ public class TreeScanner<R,P> implements TreeVisitor<R,P> {
|
||||
* @return the result of scanning
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("removal")
|
||||
public R visitBreak(BreakTree node, P p) {
|
||||
return scan(node.getValue(), p);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -935,4 +934,23 @@ public class TreeScanner<R,P> implements TreeVisitor<R,P> {
|
||||
public R visitErroneous(ErroneousTree node, P p) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc} This implementation returns {@code null}.
|
||||
*
|
||||
* @param node {@inheritDoc}
|
||||
* @param p {@inheritDoc}
|
||||
* @return the result of scanning
|
||||
*
|
||||
* @deprecated
|
||||
* This method is modeling switch expressions,
|
||||
* which are part of a preview feature and may be removed
|
||||
* if the preview feature is removed.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated(forRemoval=true, since="13")
|
||||
@SuppressWarnings("removal")
|
||||
public R visitYield(YieldTree node, P p) {
|
||||
return scan(node.getValue(), p);
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ public class Kinds {
|
||||
HIDDEN(Category.RESOLUTION_TARGET), // not overloaded non-target
|
||||
STATICERR(Category.RESOLUTION_TARGET), // overloaded? target
|
||||
MISSING_ENCL(Category.RESOLUTION), // not overloaded non-target
|
||||
BAD_VAR(Category.RESOLUTION), // not overloaded non-target
|
||||
BAD_RESTRICTED_TYPE(Category.RESOLUTION), // not overloaded non-target
|
||||
ABSENT_VAR(Category.RESOLUTION_TARGET, KindName.VAR), // not overloaded non-target
|
||||
WRONG_MTHS(Category.RESOLUTION_TARGET, KindName.METHOD), // overloaded target
|
||||
WRONG_MTH(Category.RESOLUTION_TARGET, KindName.METHOD), // not overloaded target
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -43,7 +43,6 @@ import com.sun.tools.javac.comp.Infer.PartiallyInferredMethodType;
|
||||
import com.sun.tools.javac.comp.Resolve.MethodResolutionPhase;
|
||||
import com.sun.tools.javac.resources.CompilerProperties.Fragments;
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
import com.sun.tools.javac.tree.JCTree.JCBreak;
|
||||
import com.sun.tools.javac.tree.JCTree.JCConditional;
|
||||
import com.sun.tools.javac.tree.JCTree.JCExpression;
|
||||
import com.sun.tools.javac.tree.JCTree.JCLambda;
|
||||
@ -77,6 +76,7 @@ import static com.sun.tools.javac.code.TypeTag.DEFERRED;
|
||||
import static com.sun.tools.javac.code.TypeTag.FORALL;
|
||||
import static com.sun.tools.javac.code.TypeTag.METHOD;
|
||||
import static com.sun.tools.javac.code.TypeTag.VOID;
|
||||
import com.sun.tools.javac.tree.JCTree.JCYield;
|
||||
|
||||
/**
|
||||
* This class performs attribution of method/constructor arguments when target-typing is enabled
|
||||
@ -468,7 +468,7 @@ public class ArgumentAttr extends JCTree.Visitor {
|
||||
*/
|
||||
class SwitchExpressionType extends ArgumentType<JCSwitchExpression> {
|
||||
/** List of break expressions (lazily populated). */
|
||||
Optional<List<JCBreak>> breakExpressions = Optional.empty();
|
||||
Optional<List<JCYield>> yieldExpressions = Optional.empty();
|
||||
|
||||
SwitchExpressionType(JCExpression tree, Env<AttrContext> env, JCSwitchExpression speculativeCond) {
|
||||
this(tree, env, speculativeCond, new HashMap<>());
|
||||
@ -487,7 +487,7 @@ public class ArgumentAttr extends JCTree.Visitor {
|
||||
return attr.types.createErrorType(resultInfo.pt);
|
||||
} else {
|
||||
//poly
|
||||
for (JCBreak brk : breakExpressions()) {
|
||||
for (JCYield brk : yieldExpressions()) {
|
||||
checkSpeculative(brk.value, brk.value.type, resultInfo);
|
||||
}
|
||||
return localInfo.pt;
|
||||
@ -495,19 +495,20 @@ public class ArgumentAttr extends JCTree.Visitor {
|
||||
}
|
||||
|
||||
/** Compute return expressions (if needed). */
|
||||
List<JCBreak> breakExpressions() {
|
||||
return breakExpressions.orElseGet(() -> {
|
||||
final List<JCBreak> res;
|
||||
ListBuffer<JCBreak> buf = new ListBuffer<>();
|
||||
List<JCYield> yieldExpressions() {
|
||||
return yieldExpressions.orElseGet(() -> {
|
||||
final List<JCYield> res;
|
||||
ListBuffer<JCYield> buf = new ListBuffer<>();
|
||||
new SwitchExpressionScanner() {
|
||||
@Override
|
||||
public void visitBreak(JCBreak tree) {
|
||||
public void visitYield(JCYield tree) {
|
||||
if (tree.target == speculativeTree)
|
||||
buf.add(tree);
|
||||
super.visitYield(tree);
|
||||
}
|
||||
}.scan(speculativeTree.cases);
|
||||
res = buf.toList();
|
||||
breakExpressions = Optional.of(res);
|
||||
yieldExpressions = Optional.of(res);
|
||||
return res;
|
||||
});
|
||||
}
|
||||
|
@ -77,6 +77,8 @@ import static com.sun.tools.javac.code.TypeTag.WILDCARD;
|
||||
import com.sun.tools.javac.comp.Analyzer.AnalyzerMode;
|
||||
import static com.sun.tools.javac.tree.JCTree.Tag.*;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
|
||||
import com.sun.tools.javac.util.Log.DeferredDiagnosticHandler;
|
||||
import com.sun.tools.javac.util.Log.DiscardDiagnosticHandler;
|
||||
|
||||
/** This is the main context-dependent analysis phase in GJC. It
|
||||
* encompasses name resolution, type checking and constant folding as
|
||||
@ -358,7 +360,7 @@ public class Attr extends JCTree.Visitor {
|
||||
Name name = (Name)node.getIdentifier();
|
||||
if (site.kind == PCK) {
|
||||
env.toplevel.packge = (PackageSymbol)site;
|
||||
return rs.findIdentInPackage(env, (TypeSymbol)site, name,
|
||||
return rs.findIdentInPackage(null, env, (TypeSymbol)site, name,
|
||||
KindSelector.TYP_PCK);
|
||||
} else {
|
||||
env.enclClass.sym = (ClassSymbol)site;
|
||||
@ -368,7 +370,7 @@ public class Attr extends JCTree.Visitor {
|
||||
|
||||
@Override @DefinedBy(Api.COMPILER_TREE)
|
||||
public Symbol visitIdentifier(IdentifierTree node, Env<AttrContext> env) {
|
||||
return rs.findIdent(env, (Name)node.getName(), KindSelector.TYP_PCK);
|
||||
return rs.findIdent(null, env, (Name)node.getName(), KindSelector.TYP_PCK);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1425,16 +1427,16 @@ public class Attr extends JCTree.Visitor {
|
||||
ListBuffer<Type> caseTypes = new ListBuffer<>();
|
||||
|
||||
handleSwitch(tree, tree.selector, tree.cases, (c, caseEnv) -> {
|
||||
caseEnv.info.breakResult = condInfo;
|
||||
caseEnv.info.yieldResult = condInfo;
|
||||
attribStats(c.stats, caseEnv);
|
||||
new TreeScanner() {
|
||||
@Override
|
||||
public void visitBreak(JCBreak brk) {
|
||||
public void visitYield(JCYield brk) {
|
||||
if (brk.target == tree) {
|
||||
caseTypePositions.append(brk.value != null ? brk.value.pos() : brk.pos());
|
||||
caseTypes.append(brk.value != null ? brk.value.type : syms.errType);
|
||||
}
|
||||
super.visitBreak(brk);
|
||||
super.visitYield(brk);
|
||||
}
|
||||
|
||||
@Override public void visitClassDef(JCClassDecl tree) {}
|
||||
@ -1864,67 +1866,19 @@ public class Attr extends JCTree.Visitor {
|
||||
}
|
||||
|
||||
public void visitBreak(JCBreak tree) {
|
||||
if (env.info.breakResult != null) {
|
||||
if (tree.value == null) {
|
||||
tree.target = findJumpTarget(tree.pos(), tree.getTag(), null, env);
|
||||
if (tree.target.hasTag(SWITCH_EXPRESSION)) {
|
||||
log.error(tree.pos(), Errors.BreakMissingValue);
|
||||
}
|
||||
} else {
|
||||
if (env.info.breakResult.pt.hasTag(VOID)) {
|
||||
//can happen?
|
||||
env.info.breakResult.checkContext.report(tree.value.pos(),
|
||||
diags.fragment(Fragments.UnexpectedRetVal));
|
||||
}
|
||||
boolean attribute = true;
|
||||
if (tree.value.hasTag(IDENT)) {
|
||||
//disambiguate break <LABEL> and break <ident-as-an-expression>:
|
||||
Name label = ((JCIdent) tree.value).name;
|
||||
Pair<JCTree, Error> jumpTarget = findJumpTargetNoError(tree.getTag(), label, env);
|
||||
tree.target = findJumpTarget(tree.pos(), tree.getTag(), tree.label, env);
|
||||
result = null;
|
||||
}
|
||||
|
||||
if (jumpTarget.fst != null) {
|
||||
JCTree speculative = deferredAttr.attribSpeculative(tree.value, env, unknownExprInfo);
|
||||
if (!speculative.type.hasTag(ERROR)) {
|
||||
log.error(tree.pos(), Errors.BreakAmbiguousTarget(label));
|
||||
if (jumpTarget.snd == null) {
|
||||
tree.target = jumpTarget.fst;
|
||||
attribute = false;
|
||||
} else {
|
||||
//nothing
|
||||
}
|
||||
} else {
|
||||
if (jumpTarget.snd != null) {
|
||||
log.error(tree.pos(), jumpTarget.snd);
|
||||
}
|
||||
tree.target = jumpTarget.fst;
|
||||
attribute = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (attribute) {
|
||||
attribTree(tree.value, env, env.info.breakResult);
|
||||
JCTree immediateTarget = findJumpTarget(tree.pos(), tree.getTag(), null, env);
|
||||
if (immediateTarget.getTag() != SWITCH_EXPRESSION) {
|
||||
log.error(tree.pos(), Errors.BreakExprNotImmediate(immediateTarget.getTag()));
|
||||
Env<AttrContext> env1 = env;
|
||||
while (env1 != null && env1.tree.getTag() != SWITCH_EXPRESSION) {
|
||||
env1 = env1.next;
|
||||
}
|
||||
Assert.checkNonNull(env1);
|
||||
tree.target = env1.tree;
|
||||
} else {
|
||||
tree.target = immediateTarget;
|
||||
}
|
||||
}
|
||||
}
|
||||
public void visitYield(JCYield tree) {
|
||||
if (env.info.yieldResult != null) {
|
||||
attribTree(tree.value, env, env.info.yieldResult);
|
||||
tree.target = findJumpTarget(tree.pos(), tree.getTag(), names.empty, env);
|
||||
} else {
|
||||
if (tree.value == null || tree.value.hasTag(IDENT)) {
|
||||
Name label = tree.value != null ? ((JCIdent) tree.value).name : null;
|
||||
tree.target = findJumpTarget(tree.pos(), tree.getTag(), label, env);
|
||||
} else {
|
||||
log.error(tree.pos(), Errors.BreakComplexValueNoSwitchExpression);
|
||||
attribTree(tree.value, env, unknownExprInfo);
|
||||
}
|
||||
log.error(tree.pos(), tree.value.hasTag(PARENS)
|
||||
? Errors.NoSwitchExpressionQualify
|
||||
: Errors.NoSwitchExpression);
|
||||
attribTree(tree.value, env, unknownExprInfo);
|
||||
}
|
||||
result = null;
|
||||
}
|
||||
@ -1934,8 +1888,8 @@ public class Attr extends JCTree.Visitor {
|
||||
result = null;
|
||||
}
|
||||
//where
|
||||
/** Return the target of a break or continue statement, if it exists,
|
||||
* report an error if not.
|
||||
/** Return the target of a break, continue or yield statement,
|
||||
* if it exists, report an error if not.
|
||||
* Note: The target of a labelled break or continue is the
|
||||
* (non-labelled) statement tree referred to by the label,
|
||||
* not the tree representing the labelled statement itself.
|
||||
@ -2009,12 +1963,10 @@ public class Attr extends JCTree.Visitor {
|
||||
if (label == null && tag == BREAK) return Pair.of(env1.tree, null);
|
||||
break;
|
||||
case SWITCH_EXPRESSION:
|
||||
if (tag == BREAK) {
|
||||
if (label == null) {
|
||||
return Pair.of(env1.tree, null);
|
||||
} else {
|
||||
pendingError = Errors.BreakOutsideSwitchExpression;
|
||||
}
|
||||
if (tag == YIELD) {
|
||||
return Pair.of(env1.tree, null);
|
||||
} else if (tag == BREAK) {
|
||||
pendingError = Errors.BreakOutsideSwitchExpression;
|
||||
} else {
|
||||
pendingError = Errors.ContinueOutsideSwitchExpression;
|
||||
}
|
||||
@ -2029,6 +1981,8 @@ public class Attr extends JCTree.Visitor {
|
||||
}
|
||||
if (label != null)
|
||||
return Pair.of(null, Errors.UndefLabel(label));
|
||||
else if (pendingError != null)
|
||||
return Pair.of(null, pendingError);
|
||||
else if (tag == CONTINUE)
|
||||
return Pair.of(null, Errors.ContOutsideLoop);
|
||||
else
|
||||
@ -2040,7 +1994,7 @@ public class Attr extends JCTree.Visitor {
|
||||
// nested within than the enclosing class.
|
||||
if (env.info.returnResult == null) {
|
||||
log.error(tree.pos(), Errors.RetOutsideMeth);
|
||||
} else if (env.info.breakResult != null) {
|
||||
} else if (env.info.yieldResult != null) {
|
||||
log.error(tree.pos(), Errors.ReturnOutsideSwitchExpression);
|
||||
} else {
|
||||
// Attribute return expression, if it exists, and check that
|
||||
@ -3136,7 +3090,7 @@ public class Attr extends JCTree.Visitor {
|
||||
} else {
|
||||
lambdaEnv = env.dup(that, env.info.dup(env.info.scope.dup()));
|
||||
}
|
||||
lambdaEnv.info.breakResult = null;
|
||||
lambdaEnv.info.yieldResult = null;
|
||||
return lambdaEnv;
|
||||
}
|
||||
|
||||
@ -3916,7 +3870,7 @@ public class Attr extends JCTree.Visitor {
|
||||
switch (site.getTag()) {
|
||||
case PACKAGE:
|
||||
return rs.accessBase(
|
||||
rs.findIdentInPackage(env, site.tsym, name, resultInfo.pkind),
|
||||
rs.findIdentInPackage(pos, env, site.tsym, name, resultInfo.pkind),
|
||||
pos, location, site, name, true);
|
||||
case ARRAY:
|
||||
case CLASS:
|
||||
@ -3931,7 +3885,7 @@ public class Attr extends JCTree.Visitor {
|
||||
return syms.getClassField(site, types);
|
||||
} else {
|
||||
// We are seeing a plain identifier as selector.
|
||||
Symbol sym = rs.findIdentInType(env, site, name, resultInfo.pkind);
|
||||
Symbol sym = rs.findIdentInType(pos, env, site, name, resultInfo.pkind);
|
||||
sym = rs.accessBase(sym, pos, location, site, name, true);
|
||||
return sym;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -101,10 +101,10 @@ public class AttrContext {
|
||||
*/
|
||||
Attr.ResultInfo returnResult = null;
|
||||
|
||||
/** ResultInfo to be used for attributing 'break' statement expressions
|
||||
/** ResultInfo to be used for attributing 'yield' statement expressions
|
||||
* (set by Attr.visitSwitchExpression)
|
||||
*/
|
||||
Attr.ResultInfo breakResult = null;
|
||||
Attr.ResultInfo yieldResult = null;
|
||||
|
||||
/** Symbol corresponding to the site of a qualified default super call
|
||||
*/
|
||||
@ -129,7 +129,7 @@ public class AttrContext {
|
||||
info.lint = lint;
|
||||
info.enclVar = enclVar;
|
||||
info.returnResult = returnResult;
|
||||
info.breakResult = breakResult;
|
||||
info.yieldResult = yieldResult;
|
||||
info.defaultSuperCallSite = defaultSuperCallSite;
|
||||
info.isSerializable = isSerializable;
|
||||
info.isLambda = isLambda;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -1161,7 +1161,7 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
|
||||
SwitchExpressionScanner() {
|
||||
super(EnumSet.of(BLOCK, CASE, CATCH, DOLOOP, FOREACHLOOP,
|
||||
FORLOOP, IF, BREAK, SYNCHRONIZED, SWITCH, TRY, WHILELOOP));
|
||||
FORLOOP, IF, SYNCHRONIZED, SWITCH, TRY, WHILELOOP, YIELD));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -314,6 +314,12 @@ public class Flow {
|
||||
JCTree getTarget(JCTree tree) {
|
||||
return ((JCContinue)tree).target;
|
||||
}
|
||||
},
|
||||
YIELD(JCTree.Tag.YIELD) {
|
||||
@Override
|
||||
JCTree getTarget(JCTree tree) {
|
||||
return ((JCYield)tree).target;
|
||||
}
|
||||
};
|
||||
|
||||
final JCTree.Tag treeTag;
|
||||
@ -386,6 +392,11 @@ public class Flow {
|
||||
return resolveJump(tree, oldPendingExits, JumpKind.BREAK);
|
||||
}
|
||||
|
||||
/** Resolve all yields of this statement. */
|
||||
Liveness resolveYields(JCTree tree, ListBuffer<PendingExit> oldPendingExits) {
|
||||
return resolveJump(tree, oldPendingExits, JumpKind.YIELD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scan(JCTree tree) {
|
||||
if (tree != null && (
|
||||
@ -400,9 +411,15 @@ public class Flow {
|
||||
}
|
||||
|
||||
protected void scanSyntheticBreak(TreeMaker make, JCTree swtch) {
|
||||
JCBreak brk = make.at(Position.NOPOS).Break(null);
|
||||
brk.target = swtch;
|
||||
scan(brk);
|
||||
if (swtch.hasTag(SWITCH_EXPRESSION)) {
|
||||
JCYield brk = make.at(Position.NOPOS).Yield(null);
|
||||
brk.target = swtch;
|
||||
scan(brk);
|
||||
} else {
|
||||
JCBreak brk = make.at(Position.NOPOS).Break(null);
|
||||
brk.target = swtch;
|
||||
scan(brk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -517,7 +534,8 @@ public class Flow {
|
||||
while (exits.nonEmpty()) {
|
||||
PendingExit exit = exits.head;
|
||||
exits = exits.tail;
|
||||
Assert.check(exit.tree.hasTag(RETURN));
|
||||
Assert.check(exit.tree.hasTag(RETURN) ||
|
||||
log.hasErrorOn(exit.tree.pos()));
|
||||
}
|
||||
} finally {
|
||||
lint = lintPrev;
|
||||
@ -677,7 +695,7 @@ public class Flow {
|
||||
log.error(tree, Errors.NotExhaustive);
|
||||
}
|
||||
alive = prevAlive;
|
||||
alive = alive.or(resolveBreaks(tree, prevPendingExits));
|
||||
alive = alive.or(resolveYields(tree, prevPendingExits));
|
||||
}
|
||||
|
||||
public void visitTry(JCTry tree) {
|
||||
@ -745,8 +763,12 @@ public class Flow {
|
||||
}
|
||||
|
||||
public void visitBreak(JCBreak tree) {
|
||||
if (tree.isValueBreak())
|
||||
scan(tree.value);
|
||||
recordExit(new PendingExit(tree));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitYield(JCYield tree) {
|
||||
scan(tree.value);
|
||||
recordExit(new PendingExit(tree));
|
||||
}
|
||||
|
||||
@ -1032,7 +1054,8 @@ public class Flow {
|
||||
PendingExit exit = exits.head;
|
||||
exits = exits.tail;
|
||||
if (!(exit instanceof ThrownPendingExit)) {
|
||||
Assert.check(exit.tree.hasTag(RETURN));
|
||||
Assert.check(exit.tree.hasTag(RETURN) ||
|
||||
log.hasErrorOn(exit.tree.pos()));
|
||||
} else {
|
||||
// uncaught throws will be reported later
|
||||
pendingExits.append(exit);
|
||||
@ -1126,7 +1149,11 @@ public class Flow {
|
||||
scan(c.pats);
|
||||
scan(c.stats);
|
||||
}
|
||||
resolveBreaks(tree, prevPendingExits);
|
||||
if (tree.hasTag(SWITCH_EXPRESSION)) {
|
||||
resolveYields(tree, prevPendingExits);
|
||||
} else {
|
||||
resolveBreaks(tree, prevPendingExits);
|
||||
}
|
||||
}
|
||||
|
||||
public void visitTry(JCTry tree) {
|
||||
@ -1267,8 +1294,11 @@ public class Flow {
|
||||
}
|
||||
|
||||
public void visitBreak(JCBreak tree) {
|
||||
if (tree.isValueBreak())
|
||||
scan(tree.value);
|
||||
recordExit(new PendingExit(tree));
|
||||
}
|
||||
|
||||
public void visitYield(JCYield tree) {
|
||||
scan(tree.value);
|
||||
recordExit(new PendingExit(tree));
|
||||
}
|
||||
|
||||
@ -1357,7 +1387,8 @@ public class Flow {
|
||||
PendingExit exit = exits.head;
|
||||
exits = exits.tail;
|
||||
if (!(exit instanceof ThrownPendingExit)) {
|
||||
Assert.check(exit.tree.hasTag(RETURN));
|
||||
Assert.check(exit.tree.hasTag(RETURN) ||
|
||||
log.hasErrorOn(exit.tree.pos()));
|
||||
} else {
|
||||
// uncaught throws will be reported later
|
||||
pendingExits.append(exit);
|
||||
@ -1977,7 +2008,9 @@ public class Flow {
|
||||
while (exits.nonEmpty()) {
|
||||
PendingExit exit = exits.head;
|
||||
exits = exits.tail;
|
||||
Assert.check(exit.tree.hasTag(RETURN), exit.tree);
|
||||
Assert.check(exit.tree.hasTag(RETURN) ||
|
||||
log.hasErrorOn(exit.tree.pos()),
|
||||
exit.tree);
|
||||
if (isInitialConstructor) {
|
||||
Assert.check(exit instanceof AssignPendingExit);
|
||||
inits.assign(((AssignPendingExit) exit).exit_inits);
|
||||
@ -2232,7 +2265,11 @@ public class Flow {
|
||||
inits.andSet(initsSwitch);
|
||||
}
|
||||
}
|
||||
resolveBreaks(tree, prevPendingExits);
|
||||
if (tree.hasTag(SWITCH_EXPRESSION)) {
|
||||
resolveYields(tree, prevPendingExits);
|
||||
} else {
|
||||
resolveBreaks(tree, prevPendingExits);
|
||||
}
|
||||
nextadr = nextadrPrev;
|
||||
}
|
||||
// where
|
||||
@ -2397,37 +2434,39 @@ public class Flow {
|
||||
|
||||
@Override
|
||||
public void visitBreak(JCBreak tree) {
|
||||
if (tree.isValueBreak()) {
|
||||
if (tree.target.hasTag(SWITCH_EXPRESSION)) {
|
||||
JCSwitchExpression expr = (JCSwitchExpression) tree.target;
|
||||
if (expr.type.hasTag(BOOLEAN)) {
|
||||
scanCond(tree.value);
|
||||
Bits initsAfterBreakWhenTrue = new Bits(initsWhenTrue);
|
||||
Bits initsAfterBreakWhenFalse = new Bits(initsWhenFalse);
|
||||
Bits uninitsAfterBreakWhenTrue = new Bits(uninitsWhenTrue);
|
||||
Bits uninitsAfterBreakWhenFalse = new Bits(uninitsWhenFalse);
|
||||
PendingExit exit = new PendingExit(tree) {
|
||||
@Override
|
||||
void resolveJump() {
|
||||
if (!inits.isReset()) {
|
||||
split(true);
|
||||
}
|
||||
initsWhenTrue.andSet(initsAfterBreakWhenTrue);
|
||||
initsWhenFalse.andSet(initsAfterBreakWhenFalse);
|
||||
uninitsWhenTrue.andSet(uninitsAfterBreakWhenTrue);
|
||||
uninitsWhenFalse.andSet(uninitsAfterBreakWhenFalse);
|
||||
}
|
||||
};
|
||||
merge();
|
||||
recordExit(exit);
|
||||
return ;
|
||||
}
|
||||
}
|
||||
scan(tree.value);
|
||||
}
|
||||
recordExit(new AssignPendingExit(tree, inits, uninits));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitYield(JCYield tree) {
|
||||
JCSwitchExpression expr = (JCSwitchExpression) tree.target;
|
||||
if (expr != null && expr.type.hasTag(BOOLEAN)) {
|
||||
scanCond(tree.value);
|
||||
Bits initsAfterBreakWhenTrue = new Bits(initsWhenTrue);
|
||||
Bits initsAfterBreakWhenFalse = new Bits(initsWhenFalse);
|
||||
Bits uninitsAfterBreakWhenTrue = new Bits(uninitsWhenTrue);
|
||||
Bits uninitsAfterBreakWhenFalse = new Bits(uninitsWhenFalse);
|
||||
PendingExit exit = new PendingExit(tree) {
|
||||
@Override
|
||||
void resolveJump() {
|
||||
if (!inits.isReset()) {
|
||||
split(true);
|
||||
}
|
||||
initsWhenTrue.andSet(initsAfterBreakWhenTrue);
|
||||
initsWhenFalse.andSet(initsAfterBreakWhenFalse);
|
||||
uninitsWhenTrue.andSet(uninitsAfterBreakWhenTrue);
|
||||
uninitsWhenFalse.andSet(uninitsAfterBreakWhenFalse);
|
||||
}
|
||||
};
|
||||
merge();
|
||||
recordExit(exit);
|
||||
return ;
|
||||
} else {
|
||||
scan(tree.value);
|
||||
recordExit(new AssignPendingExit(tree, inits, uninits));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitContinue(JCContinue tree) {
|
||||
recordExit(new AssignPendingExit(tree, inits, uninits));
|
||||
@ -2788,9 +2827,8 @@ public class Flow {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBreak(JCBreak tree) {
|
||||
if (tree.isValueBreak())
|
||||
scan(tree.value);
|
||||
public void visitYield(JCYield tree) {
|
||||
scan(tree.value);
|
||||
}
|
||||
|
||||
public void visitModuleDef(JCModuleDecl tree) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -272,9 +272,8 @@ public class Lower extends TreeTranslator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBreak(JCBreak tree) {
|
||||
if (tree.isValueBreak())
|
||||
scan(tree.value);
|
||||
public void visitYield(JCYield tree) {
|
||||
scan(tree.value);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1887,7 +1886,7 @@ public class Lower extends TreeTranslator {
|
||||
ClassSymbol c = types.boxedClass(type);
|
||||
Symbol typeSym =
|
||||
rs.accessBase(
|
||||
rs.findIdentInType(attrEnv, c.type, names.TYPE, KindSelector.VAR),
|
||||
rs.findIdentInType(pos, attrEnv, c.type, names.TYPE, KindSelector.VAR),
|
||||
pos, c.type, names.TYPE, true);
|
||||
if (typeSym.kind == VAR)
|
||||
((VarSymbol)typeSym).getConstValue(); // ensure initializer is evaluated
|
||||
@ -3224,6 +3223,11 @@ public class Lower extends TreeTranslator {
|
||||
if (tree.target == src)
|
||||
tree.target = dest;
|
||||
}
|
||||
public void visitYield(JCYield tree) {
|
||||
if (tree.target == src)
|
||||
tree.target = dest;
|
||||
scan(tree.value);
|
||||
}
|
||||
public void visitContinue(JCContinue tree) {
|
||||
if (tree.target == src)
|
||||
tree.target = dest;
|
||||
@ -3676,9 +3680,12 @@ public class Lower extends TreeTranslator {
|
||||
|
||||
@Override
|
||||
public void visitBreak(JCBreak tree) {
|
||||
if (tree.isValueBreak()) {
|
||||
tree.value = translate(tree.value, tree.target.type);
|
||||
}
|
||||
result = tree;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitYield(JCYield tree) {
|
||||
tree.value = translate(tree.value, tree.target.type);
|
||||
result = tree;
|
||||
}
|
||||
|
||||
|
@ -245,7 +245,7 @@ public class MemberEnter extends JCTree.Visitor {
|
||||
tree.sym.type.getReturnType());
|
||||
}
|
||||
if ((tree.mods.flags & STATIC) != 0) localEnv.info.staticLevel++;
|
||||
localEnv.info.breakResult = null;
|
||||
localEnv.info.yieldResult = null;
|
||||
return localEnv;
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,7 @@ import com.sun.tools.javac.jvm.*;
|
||||
import com.sun.tools.javac.main.Option;
|
||||
import com.sun.tools.javac.resources.CompilerProperties.Errors;
|
||||
import com.sun.tools.javac.resources.CompilerProperties.Fragments;
|
||||
import com.sun.tools.javac.resources.CompilerProperties.Warnings;
|
||||
import com.sun.tools.javac.tree.*;
|
||||
import com.sun.tools.javac.tree.JCTree.*;
|
||||
import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind;
|
||||
@ -52,6 +53,7 @@ import com.sun.tools.javac.util.DefinedBy.Api;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.Warning;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@ -63,6 +65,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
@ -105,6 +108,7 @@ public class Resolve {
|
||||
public final boolean checkVarargsAccessAfterResolution;
|
||||
private final boolean compactMethodDiags;
|
||||
private final boolean allowLocalVariableTypeInference;
|
||||
private final boolean allowYieldStatement;
|
||||
final EnumSet<VerboseResolutionMode> verboseResolutionMode;
|
||||
|
||||
WriteableScope polymorphicSignatureScope;
|
||||
@ -128,6 +132,7 @@ public class Resolve {
|
||||
moduleFinder = ModuleFinder.instance(context);
|
||||
types = Types.instance(context);
|
||||
diags = JCDiagnostic.Factory.instance(context);
|
||||
Preview preview = Preview.instance(context);
|
||||
Source source = Source.instance(context);
|
||||
Options options = Options.instance(context);
|
||||
compactMethodDiags = options.isSet(Option.XDIAGS, "compact") ||
|
||||
@ -136,6 +141,8 @@ public class Resolve {
|
||||
Target target = Target.instance(context);
|
||||
allowFunctionalInterfaceMostSpecific = Feature.FUNCTIONAL_INTERFACE_MOST_SPECIFIC.allowedInSource(source);
|
||||
allowLocalVariableTypeInference = Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source);
|
||||
allowYieldStatement = (!preview.isPreview(Feature.SWITCH_EXPRESSION) || preview.isEnabled()) &&
|
||||
Feature.SWITCH_EXPRESSION.allowedInSource(source);
|
||||
checkVarargsAccessAfterResolution =
|
||||
Feature.POST_APPLICABILITY_VARARGS_ACCESS_CHECK.allowedInSource(source);
|
||||
polymorphicSignatureScope = WriteableScope.create(syms.noSymbol);
|
||||
@ -2330,13 +2337,15 @@ public class Resolve {
|
||||
}
|
||||
|
||||
/** Find an unqualified identifier which matches a specified kind set.
|
||||
* @param pos position on which report warnings, if any;
|
||||
* null warnings should not be reported
|
||||
* @param env The current environment.
|
||||
* @param name The identifier's name.
|
||||
* @param kind Indicates the possible symbol kinds
|
||||
* (a subset of VAL, TYP, PCK).
|
||||
*/
|
||||
Symbol findIdent(Env<AttrContext> env, Name name, KindSelector kind) {
|
||||
return checkVarType(findIdentInternal(env, name, kind), name);
|
||||
Symbol findIdent(DiagnosticPosition pos, Env<AttrContext> env, Name name, KindSelector kind) {
|
||||
return checkRestrictedType(pos, findIdentInternal(env, name, kind), name);
|
||||
}
|
||||
|
||||
Symbol findIdentInternal(Env<AttrContext> env, Name name, KindSelector kind) {
|
||||
@ -2362,14 +2371,17 @@ public class Resolve {
|
||||
}
|
||||
|
||||
/** Find an identifier in a package which matches a specified kind set.
|
||||
* @param pos position on which report warnings, if any;
|
||||
* null warnings should not be reported
|
||||
* @param env The current environment.
|
||||
* @param name The identifier's name.
|
||||
* @param kind Indicates the possible symbol kinds
|
||||
* (a nonempty subset of TYP, PCK).
|
||||
*/
|
||||
Symbol findIdentInPackage(Env<AttrContext> env, TypeSymbol pck,
|
||||
Symbol findIdentInPackage(DiagnosticPosition pos,
|
||||
Env<AttrContext> env, TypeSymbol pck,
|
||||
Name name, KindSelector kind) {
|
||||
return checkVarType(findIdentInPackageInternal(env, pck, name, kind), name);
|
||||
return checkRestrictedType(pos, findIdentInPackageInternal(env, pck, name, kind), name);
|
||||
}
|
||||
|
||||
Symbol findIdentInPackageInternal(Env<AttrContext> env, TypeSymbol pck,
|
||||
@ -2395,15 +2407,18 @@ public class Resolve {
|
||||
}
|
||||
|
||||
/** Find an identifier among the members of a given type `site'.
|
||||
* @param pos position on which report warnings, if any;
|
||||
* null warnings should not be reported
|
||||
* @param env The current environment.
|
||||
* @param site The type containing the symbol to be found.
|
||||
* @param name The identifier's name.
|
||||
* @param kind Indicates the possible symbol kinds
|
||||
* (a subset of VAL, TYP).
|
||||
*/
|
||||
Symbol findIdentInType(Env<AttrContext> env, Type site,
|
||||
Symbol findIdentInType(DiagnosticPosition pos,
|
||||
Env<AttrContext> env, Type site,
|
||||
Name name, KindSelector kind) {
|
||||
return checkVarType(findIdentInTypeInternal(env, site, name, kind), name);
|
||||
return checkRestrictedType(pos, findIdentInTypeInternal(env, site, name, kind), name);
|
||||
}
|
||||
|
||||
Symbol findIdentInTypeInternal(Env<AttrContext> env, Type site,
|
||||
@ -2424,10 +2439,17 @@ public class Resolve {
|
||||
return bestSoFar;
|
||||
}
|
||||
|
||||
private Symbol checkVarType(Symbol bestSoFar, Name name) {
|
||||
if (allowLocalVariableTypeInference && name.equals(names.var) &&
|
||||
(bestSoFar.kind == TYP || bestSoFar.kind == ABSENT_TYP)) {
|
||||
bestSoFar = new BadVarTypeError();
|
||||
private Symbol checkRestrictedType(DiagnosticPosition pos, Symbol bestSoFar, Name name) {
|
||||
if (bestSoFar.kind == TYP || bestSoFar.kind == ABSENT_TYP) {
|
||||
if (allowLocalVariableTypeInference && name.equals(names.var)) {
|
||||
bestSoFar = new BadRestrictedTypeError(names.var);
|
||||
} else if (name.equals(names.yield)) {
|
||||
if (allowYieldStatement) {
|
||||
bestSoFar = new BadRestrictedTypeError(names.yield);
|
||||
} else if (pos != null) {
|
||||
log.warning(pos, Warnings.IllegalRefToRestrictedType(names.yield));
|
||||
}
|
||||
}
|
||||
}
|
||||
return bestSoFar;
|
||||
}
|
||||
@ -2597,7 +2619,7 @@ public class Resolve {
|
||||
Symbol resolveIdent(DiagnosticPosition pos, Env<AttrContext> env,
|
||||
Name name, KindSelector kind) {
|
||||
return accessBase(
|
||||
findIdent(env, name, kind),
|
||||
findIdent(pos, env, name, kind),
|
||||
pos, env.enclClass.sym.type, name, false);
|
||||
}
|
||||
|
||||
@ -3833,14 +3855,16 @@ public class Resolve {
|
||||
}
|
||||
}
|
||||
|
||||
class BadVarTypeError extends ResolveError {
|
||||
BadVarTypeError() {
|
||||
super(Kind.BAD_VAR, "bad var use");
|
||||
class BadRestrictedTypeError extends ResolveError {
|
||||
private final Name typeName;
|
||||
BadRestrictedTypeError(Name typeName) {
|
||||
super(Kind.BAD_RESTRICTED_TYPE, "bad var use");
|
||||
this.typeName = typeName;
|
||||
}
|
||||
|
||||
@Override
|
||||
JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
|
||||
return diags.create(dkind, log.currentSource(), pos, "illegal.ref.to.var.type");
|
||||
return diags.create(dkind, log.currentSource(), pos, "illegal.ref.to.restricted.type", typeName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -620,11 +620,14 @@ public class TransTypes extends TreeTranslator {
|
||||
|
||||
@Override
|
||||
public void visitBreak(JCBreak tree) {
|
||||
if (tree.isValueBreak()) {
|
||||
tree.value = translate(tree.value, erasure(tree.value.type));
|
||||
tree.value.type = erasure(tree.value.type);
|
||||
tree.value = retype(tree.value, tree.value.type, pt);
|
||||
}
|
||||
result = tree;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitYield(JCYield tree) {
|
||||
tree.value = translate(tree.value, erasure(tree.value.type));
|
||||
tree.value.type = erasure(tree.value.type);
|
||||
tree.value = retype(tree.value, tree.value.type, pt);
|
||||
result = tree;
|
||||
}
|
||||
|
||||
|
@ -71,6 +71,7 @@ import com.sun.tools.javac.tree.JCTree.JCProvides;
|
||||
import com.sun.tools.javac.tree.JCTree.JCRequires;
|
||||
import com.sun.tools.javac.tree.JCTree.JCReturn;
|
||||
import com.sun.tools.javac.tree.JCTree.JCSwitch;
|
||||
import com.sun.tools.javac.tree.JCTree.JCSwitchExpression;
|
||||
import com.sun.tools.javac.tree.JCTree.JCSynchronized;
|
||||
import com.sun.tools.javac.tree.JCTree.JCThrow;
|
||||
import com.sun.tools.javac.tree.JCTree.JCTry;
|
||||
@ -84,6 +85,7 @@ import com.sun.tools.javac.tree.JCTree.JCUses;
|
||||
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
|
||||
import com.sun.tools.javac.tree.JCTree.JCWhileLoop;
|
||||
import com.sun.tools.javac.tree.JCTree.JCWildcard;
|
||||
import com.sun.tools.javac.tree.JCTree.JCYield;
|
||||
import com.sun.tools.javac.tree.JCTree.LetExpr;
|
||||
import com.sun.tools.javac.tree.JCTree.TypeBoundKind;
|
||||
import com.sun.tools.javac.tree.TreeInfo;
|
||||
@ -259,6 +261,12 @@ public class TreeDiffer extends TreeScanner {
|
||||
@Override
|
||||
public void visitBreak(JCBreak tree) {
|
||||
JCBreak that = (JCBreak) parameter;
|
||||
result = tree.label == that.label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitYield(JCYield tree) {
|
||||
JCYield that = (JCYield) parameter;
|
||||
result = scan(tree.value, that.value);
|
||||
}
|
||||
|
||||
@ -498,6 +506,12 @@ public class TreeDiffer extends TreeScanner {
|
||||
result = scan(tree.selector, that.selector) && scan(tree.cases, that.cases);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSwitchExpression(JCSwitchExpression tree) {
|
||||
JCSwitchExpression that = (JCSwitchExpression) parameter;
|
||||
result = scan(tree.selector, that.selector) && scan(tree.cases, that.cases);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSynchronized(JCSynchronized tree) {
|
||||
JCSynchronized that = (JCSynchronized) parameter;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -377,6 +377,11 @@ implements CRTFlags {
|
||||
result = sr;
|
||||
}
|
||||
|
||||
public void visitYield(JCYield tree) {
|
||||
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
|
||||
result = sr;
|
||||
}
|
||||
|
||||
public void visitContinue(JCContinue tree) {
|
||||
SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
|
||||
result = sr;
|
||||
|
@ -1716,47 +1716,49 @@ public class Gen extends JCTree.Visitor {
|
||||
}
|
||||
|
||||
public void visitBreak(JCBreak tree) {
|
||||
Assert.check(code.isStatementStart());
|
||||
final Env<GenContext> targetEnv = unwindBreak(tree.target);
|
||||
targetEnv.info.addExit(code.branch(goto_));
|
||||
endFinalizerGaps(env, targetEnv);
|
||||
}
|
||||
|
||||
public void visitYield(JCYield tree) {
|
||||
Assert.check(code.isStatementStart());
|
||||
final Env<GenContext> targetEnv;
|
||||
if (tree.isValueBreak()) {
|
||||
//restore stack as it was before the switch expression:
|
||||
for (LocalItem li : stackBeforeSwitchExpression) {
|
||||
li.load();
|
||||
}
|
||||
if (inCondSwitchExpression) {
|
||||
CondItem value = genCond(tree.value, CRT_FLOW_TARGET);
|
||||
Chain falseJumps = value.jumpFalse();
|
||||
targetEnv = unwindBreak(tree);
|
||||
code.resolve(value.trueJumps);
|
||||
Chain trueJumps = code.branch(goto_);
|
||||
if (switchExpressionTrueChain == null) {
|
||||
switchExpressionTrueChain = trueJumps;
|
||||
} else {
|
||||
switchExpressionTrueChain =
|
||||
Code.mergeChains(switchExpressionTrueChain, trueJumps);
|
||||
}
|
||||
if (switchExpressionFalseChain == null) {
|
||||
switchExpressionFalseChain = falseJumps;
|
||||
} else {
|
||||
switchExpressionFalseChain =
|
||||
Code.mergeChains(switchExpressionFalseChain, falseJumps);
|
||||
}
|
||||
//restore stack as it was before the switch expression:
|
||||
for (LocalItem li : stackBeforeSwitchExpression) {
|
||||
li.load();
|
||||
}
|
||||
if (inCondSwitchExpression) {
|
||||
CondItem value = genCond(tree.value, CRT_FLOW_TARGET);
|
||||
Chain falseJumps = value.jumpFalse();
|
||||
targetEnv = unwindBreak(tree.target);
|
||||
code.resolve(value.trueJumps);
|
||||
Chain trueJumps = code.branch(goto_);
|
||||
if (switchExpressionTrueChain == null) {
|
||||
switchExpressionTrueChain = trueJumps;
|
||||
} else {
|
||||
genExpr(tree.value, pt).load();
|
||||
code.state.forceStackTop(tree.target.type);
|
||||
targetEnv = unwindBreak(tree);
|
||||
targetEnv.info.addExit(code.branch(goto_));
|
||||
switchExpressionTrueChain =
|
||||
Code.mergeChains(switchExpressionTrueChain, trueJumps);
|
||||
}
|
||||
if (switchExpressionFalseChain == null) {
|
||||
switchExpressionFalseChain = falseJumps;
|
||||
} else {
|
||||
switchExpressionFalseChain =
|
||||
Code.mergeChains(switchExpressionFalseChain, falseJumps);
|
||||
}
|
||||
} else {
|
||||
targetEnv = unwindBreak(tree);
|
||||
genExpr(tree.value, pt).load();
|
||||
code.state.forceStackTop(tree.target.type);
|
||||
targetEnv = unwindBreak(tree.target);
|
||||
targetEnv.info.addExit(code.branch(goto_));
|
||||
}
|
||||
endFinalizerGaps(env, targetEnv);
|
||||
}
|
||||
//where:
|
||||
private Env<GenContext> unwindBreak(JCBreak tree) {
|
||||
private Env<GenContext> unwindBreak(JCTree target) {
|
||||
int tmpPos = code.pendingStatPos;
|
||||
Env<GenContext> targetEnv = unwind(tree.target, env);
|
||||
Env<GenContext> targetEnv = unwind(target, env);
|
||||
code.pendingStatPos = tmpPos;
|
||||
return targetEnv;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -182,6 +182,8 @@ public class JavacParser implements Parser {
|
||||
this.keepLineMap = keepLineMap;
|
||||
this.errorTree = F.Erroneous();
|
||||
endPosTable = newEndPosTable(keepEndPositions);
|
||||
this.allowYieldStatement = (!preview.isPreview(Feature.SWITCH_EXPRESSION) || preview.isEnabled()) &&
|
||||
Feature.SWITCH_EXPRESSION.allowedInSource(source);
|
||||
}
|
||||
|
||||
protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
|
||||
@ -211,6 +213,10 @@ public class JavacParser implements Parser {
|
||||
*/
|
||||
boolean allowThisIdent;
|
||||
|
||||
/** Switch: is yield statement allowed in this source level?
|
||||
*/
|
||||
boolean allowYieldStatement;
|
||||
|
||||
/** The type of the method receiver, as specified by a first "this" parameter.
|
||||
*/
|
||||
JCVariableDecl receiverParam;
|
||||
@ -769,9 +775,10 @@ public class JavacParser implements Parser {
|
||||
|
||||
public JCExpression unannotatedType(boolean allowVar) {
|
||||
JCExpression result = term(TYPE);
|
||||
Name restrictedTypeName;
|
||||
|
||||
if (!allowVar && isRestrictedLocalVarTypeName(result, true)) {
|
||||
syntaxError(result.pos, Errors.VarNotAllowedHere);
|
||||
if (!allowVar && (restrictedTypeName = restrictedTypeName(result, true)) != null) {
|
||||
syntaxError(result.pos, Errors.RestrictedTypeNotAllowedHere(restrictedTypeName));
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -1377,6 +1384,7 @@ public class JavacParser implements Parser {
|
||||
break;
|
||||
case SWITCH:
|
||||
checkSourceLevel(Feature.SWITCH_EXPRESSION);
|
||||
allowYieldStatement = true;
|
||||
int switchPos = token.pos;
|
||||
nextToken();
|
||||
JCExpression selector = parExpression();
|
||||
@ -1436,7 +1444,7 @@ public class JavacParser implements Parser {
|
||||
kind = JCCase.RULE;
|
||||
} else {
|
||||
JCExpression value = parseExpression();
|
||||
stats = List.of(to(F.at(value).Break(value)));
|
||||
stats = List.of(to(F.at(value).Yield(value)));
|
||||
body = value;
|
||||
kind = JCCase.RULE;
|
||||
accept(SEMI);
|
||||
@ -1607,7 +1615,7 @@ public class JavacParser implements Parser {
|
||||
int depth = 0;
|
||||
boolean type = false;
|
||||
ParensResult defaultResult = ParensResult.PARENS;
|
||||
outer: for (int lookahead = 0 ; ; lookahead++) {
|
||||
outer: for (int lookahead = 0; ; lookahead++) {
|
||||
TokenKind tk = S.token(lookahead).kind;
|
||||
switch (tk) {
|
||||
case COMMA:
|
||||
@ -1782,12 +1790,13 @@ public class JavacParser implements Parser {
|
||||
if (explicitParams) {
|
||||
LambdaClassifier lambdaClassifier = new LambdaClassifier();
|
||||
for (JCVariableDecl param: params) {
|
||||
Name restrictedTypeName;
|
||||
if (param.vartype != null &&
|
||||
isRestrictedLocalVarTypeName(param.vartype, false) &&
|
||||
(restrictedTypeName = restrictedTypeName(param.vartype, false)) != null &&
|
||||
param.vartype.hasTag(TYPEARRAY)) {
|
||||
log.error(DiagnosticFlag.SYNTAX, param.pos,
|
||||
Feature.VAR_SYNTAX_IMPLICIT_LAMBDAS.allowedInSource(source)
|
||||
? Errors.VarNotAllowedArray : Errors.VarNotAllowedHere);
|
||||
? Errors.RestrictedTypeNotAllowedArray(restrictedTypeName) : Errors.RestrictedTypeNotAllowedHere(restrictedTypeName));
|
||||
}
|
||||
lambdaClassifier.addParameter(param);
|
||||
if (lambdaClassifier.result() == LambdaParameterKind.ERROR) {
|
||||
@ -1799,7 +1808,7 @@ public class JavacParser implements Parser {
|
||||
}
|
||||
for (JCVariableDecl param: params) {
|
||||
if (param.vartype != null
|
||||
&& isRestrictedLocalVarTypeName(param.vartype, true)) {
|
||||
&& restrictedTypeName(param.vartype, true) != null) {
|
||||
checkSourceLevel(param.pos, Feature.VAR_SYNTAX_IMPLICIT_LAMBDAS);
|
||||
param.startPos = TreeInfo.getStartPos(param.vartype);
|
||||
param.vartype = null;
|
||||
@ -1837,7 +1846,7 @@ public class JavacParser implements Parser {
|
||||
|
||||
void addParameter(JCVariableDecl param) {
|
||||
if (param.vartype != null && param.name != names.empty) {
|
||||
if (isRestrictedLocalVarTypeName(param.vartype, false)) {
|
||||
if (restrictedTypeName(param.vartype, false) != null) {
|
||||
reduce(LambdaParameterKind.VAR);
|
||||
} else {
|
||||
reduce(LambdaParameterKind.EXPLICIT);
|
||||
@ -1944,10 +1953,27 @@ public class JavacParser implements Parser {
|
||||
return args.toList();
|
||||
}
|
||||
|
||||
JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
|
||||
JCExpression arguments(List<JCExpression> typeArgs, JCExpression t) {
|
||||
int pos = token.pos;
|
||||
List<JCExpression> args = arguments();
|
||||
return toP(F.at(pos).Apply(typeArgs, t, args));
|
||||
JCExpression mi = F.at(pos).Apply(typeArgs, t, args);
|
||||
if (t.hasTag(IDENT) && isInvalidUnqualifiedMethodIdentifier(((JCIdent) t).pos,
|
||||
((JCIdent) t).name)) {
|
||||
log.error(DiagnosticFlag.SYNTAX, t, Errors.InvalidYield);
|
||||
mi = F.Erroneous(List.of(mi));
|
||||
}
|
||||
return toP(mi);
|
||||
}
|
||||
|
||||
boolean isInvalidUnqualifiedMethodIdentifier(int pos, Name name) {
|
||||
if (name == names.yield) {
|
||||
if (allowYieldStatement) {
|
||||
return true;
|
||||
} else {
|
||||
log.warning(pos, Warnings.InvalidYield);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** TypeArgumentsOpt = [ TypeArguments ]
|
||||
@ -2506,6 +2532,7 @@ public class JavacParser implements Parser {
|
||||
|
||||
/**This method parses a statement appearing inside a block.
|
||||
*/
|
||||
@SuppressWarnings("fallthrough")
|
||||
List<JCStatement> blockStatement() {
|
||||
//todo: skip to anchor on error(?)
|
||||
int pos = token.pos;
|
||||
@ -2543,6 +2570,52 @@ public class JavacParser implements Parser {
|
||||
log.error(DiagnosticFlag.SYNTAX, token.pos, Errors.LocalEnum);
|
||||
dc = token.comment(CommentStyle.JAVADOC);
|
||||
return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
|
||||
case IDENTIFIER:
|
||||
if (token.name() == names.yield && allowYieldStatement) {
|
||||
Token next = S.token(1);
|
||||
boolean isYieldStatement;
|
||||
switch (next.kind) {
|
||||
case PLUS: case SUB: case STRINGLITERAL: case CHARLITERAL:
|
||||
case INTLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
|
||||
case NULL: case IDENTIFIER: case TRUE: case FALSE:
|
||||
case NEW: case SWITCH: case THIS: case SUPER:
|
||||
isYieldStatement = true;
|
||||
break;
|
||||
case PLUSPLUS: case SUBSUB:
|
||||
isYieldStatement = S.token(2).kind != SEMI;
|
||||
break;
|
||||
case LPAREN:
|
||||
int lookahead = 2;
|
||||
int balance = 1;
|
||||
boolean hasComma = false;
|
||||
Token l;
|
||||
while ((l = S.token(lookahead)).kind != EOF && balance != 0) {
|
||||
switch (l.kind) {
|
||||
case LPAREN: balance++; break;
|
||||
case RPAREN: balance--; break;
|
||||
case COMMA: if (balance == 1) hasComma = true; break;
|
||||
}
|
||||
lookahead++;
|
||||
}
|
||||
isYieldStatement = (!hasComma && lookahead != 3) || l.kind == ARROW;
|
||||
break;
|
||||
case SEMI: //error recovery - this is not a valid statement:
|
||||
isYieldStatement = true;
|
||||
break;
|
||||
default:
|
||||
isYieldStatement = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (isYieldStatement) {
|
||||
nextToken();
|
||||
JCExpression t = term(EXPR);
|
||||
accept(SEMI);
|
||||
return List.of(toP(F.at(pos).Yield(t)));
|
||||
}
|
||||
|
||||
//else intentional fall-through
|
||||
}
|
||||
default:
|
||||
Token prevToken = token;
|
||||
JCExpression t = term(EXPR | TYPE);
|
||||
@ -2702,9 +2775,9 @@ public class JavacParser implements Parser {
|
||||
}
|
||||
case BREAK: {
|
||||
nextToken();
|
||||
JCExpression value = token.kind == SEMI ? null : parseExpression();
|
||||
Name label = LAX_IDENTIFIER.accepts(token.kind) ? ident() : null;
|
||||
accept(SEMI);
|
||||
JCBreak t = toP(F.at(pos).Break(value));
|
||||
JCBreak t = toP(F.at(pos).Break(label));
|
||||
return t;
|
||||
}
|
||||
case CONTINUE: {
|
||||
@ -3181,14 +3254,14 @@ public class JavacParser implements Parser {
|
||||
int startPos = Position.NOPOS;
|
||||
if (elemType.hasTag(IDENT)) {
|
||||
Name typeName = ((JCIdent)elemType).name;
|
||||
if (isRestrictedLocalVarTypeName(typeName, pos, !compound && localDecl)) {
|
||||
if (isRestrictedTypeName(typeName, pos, !compound && localDecl)) {
|
||||
if (type.hasTag(TYPEARRAY) && !compound) {
|
||||
//error - 'var' and arrays
|
||||
reportSyntaxError(pos, Errors.VarNotAllowedArray);
|
||||
reportSyntaxError(pos, Errors.RestrictedTypeNotAllowedArray(typeName));
|
||||
} else {
|
||||
if(compound)
|
||||
//error - 'var' in compound local var decl
|
||||
reportSyntaxError(pos, Errors.VarNotAllowedCompound);
|
||||
reportSyntaxError(pos, Errors.RestrictedTypeNotAllowedCompound(typeName));
|
||||
startPos = TreeInfo.getStartPos(mods);
|
||||
if (startPos == Position.NOPOS)
|
||||
startPos = TreeInfo.getStartPos(type);
|
||||
@ -3204,23 +3277,30 @@ public class JavacParser implements Parser {
|
||||
return result;
|
||||
}
|
||||
|
||||
boolean isRestrictedLocalVarTypeName(JCExpression e, boolean shouldWarn) {
|
||||
Name restrictedTypeName(JCExpression e, boolean shouldWarn) {
|
||||
switch (e.getTag()) {
|
||||
case IDENT:
|
||||
return isRestrictedLocalVarTypeName(((JCIdent)e).name, e.pos, shouldWarn);
|
||||
return isRestrictedTypeName(((JCIdent)e).name, e.pos, shouldWarn) ? ((JCIdent)e).name : null;
|
||||
case TYPEARRAY:
|
||||
return isRestrictedLocalVarTypeName(((JCArrayTypeTree)e).elemtype, shouldWarn);
|
||||
return restrictedTypeName(((JCArrayTypeTree)e).elemtype, shouldWarn);
|
||||
default:
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
boolean isRestrictedLocalVarTypeName(Name name, int pos, boolean shouldWarn) {
|
||||
boolean isRestrictedTypeName(Name name, int pos, boolean shouldWarn) {
|
||||
if (name == names.var) {
|
||||
if (Feature.LOCAL_VARIABLE_TYPE_INFERENCE.allowedInSource(source)) {
|
||||
return true;
|
||||
} else if (shouldWarn) {
|
||||
log.warning(pos, Warnings.VarNotAllowed);
|
||||
log.warning(pos, Warnings.RestrictedTypeNotAllowed(name, Source.JDK10));
|
||||
}
|
||||
}
|
||||
if (name == names.yield) {
|
||||
if (allowYieldStatement) {
|
||||
return true;
|
||||
} else if (shouldWarn) {
|
||||
log.warning(pos, Warnings.RestrictedTypeNotAllowedPreview(name, Source.JDK13));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -3614,8 +3694,8 @@ public class JavacParser implements Parser {
|
||||
Name typeName() {
|
||||
int pos = token.pos;
|
||||
Name name = ident();
|
||||
if (isRestrictedLocalVarTypeName(name, pos, true)) {
|
||||
reportSyntaxError(pos, Errors.VarNotAllowed);
|
||||
if (isRestrictedTypeName(name, pos, true)) {
|
||||
reportSyntaxError(pos, Errors.RestrictedTypeNotAllowed(name, name == names.var ? Source.JDK10 : Source.JDK13));
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
@ -188,17 +188,14 @@ compiler.err.bad.initializer=\
|
||||
compiler.err.break.outside.switch.loop=\
|
||||
break outside switch or loop
|
||||
|
||||
compiler.err.break.missing.value=\
|
||||
missing break value
|
||||
|
||||
compiler.err.break.outside.switch.expression=\
|
||||
break outside of enclosing switch expression
|
||||
attempt to break out of a switch expression
|
||||
|
||||
compiler.err.continue.outside.switch.expression=\
|
||||
continue outside of enclosing switch expression
|
||||
attempt to continue out of a switch expression
|
||||
|
||||
compiler.err.return.outside.switch.expression=\
|
||||
return outside of enclosing switch expression
|
||||
attempt to return out of a switch expression
|
||||
|
||||
compiler.err.rule.completes.normally=\
|
||||
switch rule completes without providing a value\n\
|
||||
@ -208,17 +205,20 @@ compiler.err.switch.expression.completes.normally=\
|
||||
switch expression completes without providing a value\n\
|
||||
(switch expressions must either provide a value or throw for all possible input values)
|
||||
|
||||
# 0: name
|
||||
compiler.err.break.ambiguous.target=\
|
||||
ambiguous reference to ''{0}''\n\
|
||||
(''{0}'' is both a label and an expression)
|
||||
compiler.err.no.switch.expression =\
|
||||
yield outside of switch expression
|
||||
|
||||
# 0: tree tag
|
||||
compiler.err.break.expr.not.immediate=\
|
||||
value break not supported in ''{0}''
|
||||
compiler.err.no.switch.expression.qualify=\
|
||||
yield outside of switch expression\n\
|
||||
(to invoke a method called yield, qualify the yield with a receiver or type name)
|
||||
|
||||
compiler.err.break.complex.value.no.switch.expression=\
|
||||
unexpected value break
|
||||
compiler.err.invalid.yield=\
|
||||
invalid use of a restricted identifier ''yield''\n\
|
||||
(to invoke a method called yield, qualify the yield with a receiver or type name)
|
||||
|
||||
compiler.warn.invalid.yield=\
|
||||
''yield'' may become a restricted identifier in a future release\n\
|
||||
(to invoke a method called yield, qualify the yield with a receiver or type name)
|
||||
|
||||
compiler.err.switch.expression.empty=\
|
||||
switch expression does not have any case clauses
|
||||
@ -1267,29 +1267,43 @@ compiler.err.io.exception=\
|
||||
compiler.err.undef.label=\
|
||||
undefined label: {0}
|
||||
|
||||
compiler.err.illegal.ref.to.var.type=\
|
||||
illegal reference to restricted type ''var''
|
||||
# 0: name
|
||||
compiler.err.illegal.ref.to.restricted.type=\
|
||||
illegal reference to restricted type ''{0}''
|
||||
|
||||
compiler.err.var.not.allowed=\
|
||||
''var'' not allowed here\n\
|
||||
as of release 10, ''var'' is a restricted local variable type and cannot be used for type declarations
|
||||
# 0: name
|
||||
compiler.warn.illegal.ref.to.restricted.type=\
|
||||
illegal reference to restricted type ''{0}''
|
||||
|
||||
compiler.warn.var.not.allowed=\
|
||||
as of release 10, ''var'' is a restricted local variable type and cannot be used for type declarations or as the element type of an array
|
||||
# 0: name, 1: source
|
||||
compiler.err.restricted.type.not.allowed=\
|
||||
''{0}'' not allowed here\n\
|
||||
as of release {1}, ''{0}'' is a restricted type name and cannot be used for type declarations
|
||||
|
||||
# 0: name, 1: source
|
||||
compiler.warn.restricted.type.not.allowed=\
|
||||
as of release {1}, ''{0}'' is a restricted type name and cannot be used for type declarations or as the element type of an array
|
||||
|
||||
# 0: name, 1: source
|
||||
compiler.warn.restricted.type.not.allowed.preview=\
|
||||
''{0}'' may become a restricted type name in a future release and may be unusable for type declarations or as the element type of an array
|
||||
|
||||
# 0: name (variable), 1: message segment
|
||||
compiler.err.cant.infer.local.var.type=\
|
||||
cannot infer type for local variable {0}\n\
|
||||
({1})
|
||||
|
||||
compiler.err.var.not.allowed.here=\
|
||||
''var'' is not allowed here
|
||||
# 0: name
|
||||
compiler.err.restricted.type.not.allowed.here=\
|
||||
''{0}'' is not allowed here
|
||||
|
||||
compiler.err.var.not.allowed.array=\
|
||||
''var'' is not allowed as an element type of an array
|
||||
# 0: name
|
||||
compiler.err.restricted.type.not.allowed.array=\
|
||||
''{0}'' is not allowed as an element type of an array
|
||||
|
||||
compiler.err.var.not.allowed.compound=\
|
||||
''var'' is not allowed in a compound declaration
|
||||
# 0: name
|
||||
compiler.err.restricted.type.not.allowed.compound=\
|
||||
''{0}'' is not allowed in a compound declaration
|
||||
|
||||
# 0: fragment
|
||||
compiler.err.invalid.lambda.parameter.declaration=\
|
||||
@ -2666,22 +2680,6 @@ compiler.misc.kindname.static.init=\
|
||||
compiler.misc.kindname.instance.init=\
|
||||
instance initializer
|
||||
|
||||
# the following are names of tree kinds:
|
||||
compiler.misc.tree.tag.forloop=\
|
||||
for
|
||||
|
||||
compiler.misc.tree.tag.foreachloop=\
|
||||
for
|
||||
|
||||
compiler.misc.tree.tag.whileloop=\
|
||||
while
|
||||
|
||||
compiler.misc.tree.tag.doloop=\
|
||||
do
|
||||
|
||||
compiler.misc.tree.tag.switch=\
|
||||
switch
|
||||
|
||||
#####
|
||||
|
||||
compiler.misc.no.args=\
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -187,6 +187,10 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
||||
*/
|
||||
BREAK,
|
||||
|
||||
/** Yield statements, of type Yield.
|
||||
*/
|
||||
YIELD,
|
||||
|
||||
/** Continue statements, of type Continue.
|
||||
*/
|
||||
CONTINUE,
|
||||
@ -1551,10 +1555,10 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
||||
* A break from a loop or switch.
|
||||
*/
|
||||
public static class JCBreak extends JCStatement implements BreakTree {
|
||||
public JCExpression value;
|
||||
public Name label;
|
||||
public JCTree target;
|
||||
protected JCBreak(JCExpression value, JCTree target) {
|
||||
this.value = value;
|
||||
protected JCBreak(Name label, JCTree target) {
|
||||
this.label = label;
|
||||
this.target = target;
|
||||
}
|
||||
@Override
|
||||
@ -1567,11 +1571,8 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
||||
public Kind getKind() { return Kind.BREAK; }
|
||||
@DefinedBy(Api.COMPILER_TREE)
|
||||
public Name getLabel() {
|
||||
return value != null && value.getKind() == Kind.IDENTIFIER ? ((JCIdent) value).getName() : null;
|
||||
return label;
|
||||
}
|
||||
@DefinedBy(Api.COMPILER_TREE)
|
||||
@SuppressWarnings("removal")
|
||||
public JCExpression getValue() { return value; }
|
||||
@Override @DefinedBy(Api.COMPILER_TREE)
|
||||
public <R,D> R accept(TreeVisitor<R,D> v, D d) {
|
||||
return v.visitBreak(this, d);
|
||||
@ -1582,6 +1583,33 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A break-with from a switch expression.
|
||||
*/
|
||||
@SuppressWarnings("removal")
|
||||
public static class JCYield extends JCStatement implements YieldTree {
|
||||
public JCExpression value;
|
||||
public JCTree target;
|
||||
protected JCYield(JCExpression value, JCTree target) {
|
||||
this.value = value;
|
||||
this.target = target;
|
||||
}
|
||||
@Override
|
||||
public void accept(Visitor v) { v.visitYield(this); }
|
||||
@DefinedBy(Api.COMPILER_TREE)
|
||||
public Kind getKind() { return Kind.YIELD; }
|
||||
@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.visitYield(this, d);
|
||||
}
|
||||
@Override
|
||||
public Tag getTag() {
|
||||
return YIELD;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A continue of a loop.
|
||||
*/
|
||||
@ -3091,7 +3119,8 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
||||
JCExpression elsepart);
|
||||
JCIf If(JCExpression cond, JCStatement thenpart, JCStatement elsepart);
|
||||
JCExpressionStatement Exec(JCExpression expr);
|
||||
JCBreak Break(JCExpression value);
|
||||
JCBreak Break(Name label);
|
||||
JCYield Yield(JCExpression value);
|
||||
JCContinue Continue(Name label);
|
||||
JCReturn Return(JCExpression expr);
|
||||
JCThrow Throw(JCExpression expr);
|
||||
@ -3162,6 +3191,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
||||
public void visitIf(JCIf that) { visitTree(that); }
|
||||
public void visitExec(JCExpressionStatement that) { visitTree(that); }
|
||||
public void visitBreak(JCBreak that) { visitTree(that); }
|
||||
public void visitYield(JCYield that) { visitTree(that); }
|
||||
public void visitContinue(JCContinue that) { visitTree(that); }
|
||||
public void visitReturn(JCReturn that) { visitTree(that); }
|
||||
public void visitThrow(JCThrow that) { visitTree(that); }
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -982,7 +982,18 @@ public class Pretty extends JCTree.Visitor {
|
||||
public void visitBreak(JCBreak tree) {
|
||||
try {
|
||||
print("break");
|
||||
if (tree.value != null) print(" " + tree.value);
|
||||
if (tree.label != null) print(" " + tree.label);
|
||||
print(";");
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void visitYield(JCYield tree) {
|
||||
try {
|
||||
print("yield");
|
||||
print(" ");
|
||||
printExpr(tree.value);
|
||||
print(";");
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -140,8 +140,15 @@ public class TreeCopier<P> implements TreeVisitor<JCTree,P> {
|
||||
@DefinedBy(Api.COMPILER_TREE)
|
||||
public JCTree visitBreak(BreakTree node, P p) {
|
||||
JCBreak t = (JCBreak) node;
|
||||
return M.at(t.pos).Break(t.label);
|
||||
}
|
||||
|
||||
@DefinedBy(Api.COMPILER_TREE)
|
||||
@SuppressWarnings("removal")
|
||||
public JCTree visitYield(YieldTree node, P p) {
|
||||
JCYield t = (JCYield) node;
|
||||
JCExpression value = copy(t.value, p);
|
||||
return M.at(t.pos).Break(value);
|
||||
return M.at(t.pos).Yield(value);
|
||||
}
|
||||
|
||||
@DefinedBy(Api.COMPILER_TREE)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -333,12 +333,18 @@ public class TreeMaker implements JCTree.Factory {
|
||||
return tree;
|
||||
}
|
||||
|
||||
public JCBreak Break(JCExpression label) {
|
||||
public JCBreak Break(Name label) {
|
||||
JCBreak tree = new JCBreak(label, null);
|
||||
tree.pos = pos;
|
||||
return tree;
|
||||
}
|
||||
|
||||
public JCYield Yield(JCExpression value) {
|
||||
JCYield tree = new JCYield(value, null);
|
||||
tree.pos = pos;
|
||||
return tree;
|
||||
}
|
||||
|
||||
public JCContinue Continue(Name label) {
|
||||
JCContinue tree = new JCContinue(label, null);
|
||||
tree.pos = pos;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -219,6 +219,9 @@ public class TreeScanner extends Visitor {
|
||||
}
|
||||
|
||||
public void visitBreak(JCBreak tree) {
|
||||
}
|
||||
|
||||
public void visitYield(JCYield tree) {
|
||||
scan(tree.value);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -258,8 +258,11 @@ public class TreeTranslator extends JCTree.Visitor {
|
||||
}
|
||||
|
||||
public void visitBreak(JCBreak tree) {
|
||||
if (tree.isValueBreak())
|
||||
tree.value = translate(tree.value);
|
||||
result = tree;
|
||||
}
|
||||
|
||||
public void visitYield(JCYield tree) {
|
||||
tree.value = translate(tree.value);
|
||||
result = tree;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -554,6 +554,13 @@ public class Log extends AbstractLog {
|
||||
}
|
||||
}
|
||||
|
||||
/**Is an error reported at the given pos (inside the current source)?*/
|
||||
public boolean hasErrorOn(DiagnosticPosition pos) {
|
||||
JavaFileObject file = source != null ? source.fileObject : null;
|
||||
|
||||
return file != null && recorded.contains(new Pair<>(file, pos.getPreferredPosition()));
|
||||
}
|
||||
|
||||
/** Prompt user after an error.
|
||||
*/
|
||||
public void prompt() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -70,6 +70,7 @@ public class Names {
|
||||
public final Name uses;
|
||||
public final Name open;
|
||||
public final Name with;
|
||||
public final Name yield;
|
||||
|
||||
// field and method names
|
||||
public final Name _name;
|
||||
@ -219,6 +220,7 @@ public class Names {
|
||||
uses = fromString("uses");
|
||||
open = fromString("open");
|
||||
with = fromString("with");
|
||||
yield = fromString("yield");
|
||||
|
||||
// field and method names
|
||||
_name = fromString("name");
|
||||
|
@ -21,7 +21,7 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// key: compiler.err.var.not.allowed.array
|
||||
// key: compiler.err.restricted.type.not.allowed.array
|
||||
|
||||
import java.util.function.*;
|
||||
|
||||
|
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// key: compiler.err.break.expr.not.immediate
|
||||
// key: compiler.misc.tree.tag.doloop
|
||||
// key: compiler.misc.tree.tag.foreachloop
|
||||
// key: compiler.misc.tree.tag.forloop
|
||||
// key: compiler.misc.tree.tag.switch
|
||||
// key: compiler.misc.tree.tag.whileloop
|
||||
// key: compiler.note.note
|
||||
// key: compiler.err.error
|
||||
// key: compiler.misc.count.error.plural
|
||||
// key: compiler.note.preview.filename
|
||||
// key: compiler.note.preview.recompile
|
||||
// key: compiler.note.note
|
||||
// options: --enable-preview -source ${jdk.version}
|
||||
// run: backdoor
|
||||
|
||||
class BreakExprNotImmediate {
|
||||
int t(int i) {
|
||||
return switch (i) {
|
||||
case 0:
|
||||
for (; ;) {
|
||||
break 1 + 1;
|
||||
}
|
||||
case 1:
|
||||
for (String s : new String[0]) {
|
||||
break 1 + 1;
|
||||
}
|
||||
case 2:
|
||||
while (true) {
|
||||
break 1 + 1;
|
||||
}
|
||||
case 3:
|
||||
do {
|
||||
break 1 + 1;
|
||||
} while (true);
|
||||
case 4:
|
||||
switch (i) {
|
||||
default: break 1 + 1;
|
||||
}
|
||||
break 0;
|
||||
};
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// key: compiler.warn.var.not.allowed
|
||||
// key: compiler.warn.restricted.type.not.allowed
|
||||
// options: --release 9
|
||||
|
||||
class var { }
|
||||
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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.
|
||||
*/
|
||||
|
||||
// key: compiler.warn.illegal.ref.to.restricted.type
|
||||
// key: compiler.warn.restricted.type.not.allowed.preview
|
||||
|
||||
class IllegalRefToVarType {
|
||||
yield list() { return null; }
|
||||
public class yield {}
|
||||
}
|
@ -21,7 +21,7 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// key: compiler.err.illegal.ref.to.var.type
|
||||
// key: compiler.err.illegal.ref.to.restricted.type
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -21,16 +21,14 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// key: compiler.err.break.ambiguous.target
|
||||
// key: compiler.note.preview.filename
|
||||
// key: compiler.note.preview.recompile
|
||||
// options: --enable-preview -source ${jdk.version}
|
||||
// key: compiler.err.invalid.yield
|
||||
// options: --enable-preview --source 13
|
||||
|
||||
class BreakAmbiguousTarget {
|
||||
void m(int i, int j) {
|
||||
j: print(switch (i) {
|
||||
default: break j;
|
||||
});
|
||||
class BreakComplexValueNoSwitchExpressions {
|
||||
void t() {
|
||||
while (true) {
|
||||
yield(1, 2);
|
||||
}
|
||||
}
|
||||
void print(int i) { }
|
||||
private void yield(int i, int j) {}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -21,12 +21,14 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// key: compiler.err.break.complex.value.no.switch.expression
|
||||
// key: compiler.warn.invalid.yield
|
||||
// options: --source 13
|
||||
|
||||
class BreakComplexValueNoSwitchExpressions {
|
||||
void t() {
|
||||
while (true) {
|
||||
break 1 + 1;
|
||||
yield(1, 2);
|
||||
}
|
||||
}
|
||||
private void yield(int i, int j) {}
|
||||
}
|
@ -21,15 +21,13 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// key: compiler.err.break.missing.value
|
||||
// key: compiler.note.preview.filename
|
||||
// key: compiler.note.preview.recompile
|
||||
// options: --enable-preview -source ${jdk.version}
|
||||
// key: compiler.err.no.switch.expression
|
||||
// options: --enable-preview --source 13
|
||||
|
||||
class BreakMissingValue {
|
||||
int t(int i) {
|
||||
return switch (i) {
|
||||
default: break;
|
||||
};
|
||||
class BreakComplexValueNoSwitchExpressions {
|
||||
void t() {
|
||||
while (true) {
|
||||
yield 1 + 1;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// key: compiler.err.no.switch.expression.qualify
|
||||
// options: --enable-preview --source 13
|
||||
|
||||
class BreakComplexValueNoSwitchExpressions {
|
||||
void t() {
|
||||
while (true) {
|
||||
yield(1 + 1);
|
||||
}
|
||||
}
|
||||
private void yield(int i) {}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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.
|
||||
*/
|
||||
|
||||
// key: compiler.warn.restricted.type.not.allowed.preview
|
||||
|
||||
class yield { }
|
@ -28,7 +28,7 @@
|
||||
class SwitchExpressions {
|
||||
int m(int i) {
|
||||
return switch (i) {
|
||||
default: break -1;
|
||||
default: yield -1;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,6 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// key: compiler.err.var.not.allowed
|
||||
// key: compiler.err.restricted.type.not.allowed
|
||||
|
||||
class var { }
|
||||
|
@ -21,7 +21,7 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// key: compiler.err.var.not.allowed.array
|
||||
// key: compiler.err.restricted.type.not.allowed.array
|
||||
|
||||
class VarNotAllowedArray {
|
||||
void test(String[] s) {
|
||||
|
@ -21,7 +21,7 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// key: compiler.err.var.not.allowed.compound
|
||||
// key: compiler.err.restricted.type.not.allowed.compound
|
||||
|
||||
class VarNotAllowedCompound {
|
||||
void test() {
|
||||
|
@ -21,7 +21,7 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// key: compiler.err.var.not.allowed.here
|
||||
// key: compiler.err.restricted.type.not.allowed.here
|
||||
|
||||
class VarNotAllowedField {
|
||||
var s = "";
|
||||
|
@ -48,11 +48,12 @@ public class ExpSwitchNestingTest extends JavacTemplateTestBase {
|
||||
private static final String INT_ESWITCH_DEFAULT = "int res = switch (x) { default -> { # } };";
|
||||
private static final String IF = "if (cond) { # } else throw new RuntimeException();";
|
||||
private static final String BLOCK = "{ # }";
|
||||
private static final String BREAK_Z = "break 0;";
|
||||
private static final String BREAK_S = "break \"hello world\";";
|
||||
private static final String BREAK_INT_FN = "break () -> 0 ;";
|
||||
private static final String YIELD_Z = "yield 0;";
|
||||
private static final String YIELD_S = "yield \"hello world\";";
|
||||
private static final String YIELD_INT_FN = "yield () -> 0 ;";
|
||||
private static final String BREAK_N = "break;";
|
||||
private static final String BREAK_L = "break label;";
|
||||
private static final String YIELD_L = "yield label;";
|
||||
private static final String RETURN_Z = "return 0;";
|
||||
private static final String RETURN_N = "return;";
|
||||
private static final String RETURN_S = "return \"Hello\";";
|
||||
@ -136,11 +137,11 @@ public class ExpSwitchNestingTest extends JavacTemplateTestBase {
|
||||
assertOK(RUNNABLE, NOTHING);
|
||||
assertOK(INT_FN, RETURN_Z);
|
||||
assertFail("compiler.err.break.outside.switch.loop", RUNNABLE, BREAK_N);
|
||||
assertFail("compiler.err.break.complex.value.no.switch.expression", RUNNABLE, BREAK_Z);
|
||||
assertFail("compiler.err.break.complex.value.no.switch.expression", RUNNABLE, BREAK_S);
|
||||
assertFail("compiler.err.no.switch.expression", RUNNABLE, YIELD_Z);
|
||||
assertFail("compiler.err.no.switch.expression", RUNNABLE, YIELD_S);
|
||||
assertFail("compiler.err.break.outside.switch.loop", INT_FN, BREAK_N);
|
||||
assertFail("compiler.err.break.complex.value.no.switch.expression", INT_FN, BREAK_Z);
|
||||
assertFail("compiler.err.break.complex.value.no.switch.expression", INT_FN, BREAK_S);
|
||||
assertFail("compiler.err.no.switch.expression", INT_FN, YIELD_Z);
|
||||
assertFail("compiler.err.no.switch.expression", INT_FN, YIELD_S);
|
||||
assertFail("compiler.err.cont.outside.loop", RUNNABLE, CONTINUE_N);
|
||||
assertFail("compiler.err.undef.label", RUNNABLE, BREAK_L);
|
||||
assertFail("compiler.err.undef.label", RUNNABLE, CONTINUE_L);
|
||||
@ -155,92 +156,94 @@ public class ExpSwitchNestingTest extends JavacTemplateTestBase {
|
||||
|
||||
public void testEswitch() {
|
||||
//Int-valued switch expressions
|
||||
assertOK(ESWITCH_Z, BREAK_Z);
|
||||
assertOK(LABEL, BLOCK, ESWITCH_Z, BREAK_Z);
|
||||
assertFail("compiler.err.break.missing.value", ESWITCH_Z, BREAK_N);
|
||||
assertFail("compiler.err.prob.found.req", ESWITCH_Z, BREAK_S);
|
||||
assertFail("compiler.err.cant.resolve.location", ESWITCH_Z, BREAK_L);
|
||||
assertOK(ESWITCH_Z, YIELD_Z);
|
||||
assertOK(LABEL, BLOCK, ESWITCH_Z, YIELD_Z);
|
||||
assertFail("compiler.err.break.outside.switch.expression", ESWITCH_Z, BREAK_N);
|
||||
assertFail("compiler.err.prob.found.req", ESWITCH_Z, YIELD_S);
|
||||
assertFail("compiler.err.undef.label", ESWITCH_Z, BREAK_L);
|
||||
assertFail("compiler.err.break.outside.switch.expression", LABEL, BLOCK, ESWITCH_Z, BREAK_L);
|
||||
assertFail("compiler.err.undef.label", ESWITCH_Z, CONTINUE_L);
|
||||
assertFail("compiler.err.cont.outside.loop", ESWITCH_Z, CONTINUE_N);
|
||||
assertFail("compiler.err.continue.outside.switch.expression", ESWITCH_Z, CONTINUE_N);
|
||||
assertFail("compiler.err.return.outside.switch.expression", ESWITCH_Z, RETURN_N);
|
||||
assertFail("compiler.err.return.outside.switch.expression", ESWITCH_Z, RETURN_Z);
|
||||
|
||||
assertOK(INT_ESWITCH_DEFAULT, BREAK_Z);
|
||||
assertFail("compiler.err.break.missing.value", INT_ESWITCH_DEFAULT, BREAK_N);
|
||||
assertFail("compiler.err.prob.found.req", INT_ESWITCH_DEFAULT, BREAK_S);
|
||||
assertFail("compiler.err.cant.resolve.location", INT_ESWITCH_DEFAULT, BREAK_L);
|
||||
assertOK(INT_ESWITCH_DEFAULT, YIELD_Z);
|
||||
assertFail("compiler.err.break.outside.switch.expression", INT_ESWITCH_DEFAULT, BREAK_N);
|
||||
assertFail("compiler.err.prob.found.req", INT_ESWITCH_DEFAULT, YIELD_S);
|
||||
assertFail("compiler.err.undef.label", INT_ESWITCH_DEFAULT, BREAK_L);
|
||||
|
||||
|
||||
// String-valued switch expressions
|
||||
assertOK(ESWITCH_S, BREAK_S);
|
||||
assertOK(LABEL, BLOCK, ESWITCH_S, BREAK_S);
|
||||
assertFail("compiler.err.break.missing.value", ESWITCH_S, BREAK_N);
|
||||
assertFail("compiler.err.prob.found.req", ESWITCH_S, BREAK_Z);
|
||||
assertFail("compiler.err.cant.resolve.location", ESWITCH_S, BREAK_L);
|
||||
assertOK(ESWITCH_S, YIELD_S);
|
||||
assertOK(LABEL, BLOCK, ESWITCH_S, YIELD_S);
|
||||
assertFail("compiler.err.break.outside.switch.expression", ESWITCH_S, BREAK_N);
|
||||
assertFail("compiler.err.prob.found.req", ESWITCH_S, YIELD_Z);
|
||||
assertFail("compiler.err.undef.label", ESWITCH_S, BREAK_L);
|
||||
assertFail("compiler.err.break.outside.switch.expression", LABEL, BLOCK, ESWITCH_S, BREAK_L);
|
||||
assertFail("compiler.err.undef.label", ESWITCH_S, CONTINUE_L);
|
||||
assertFail("compiler.err.cont.outside.loop", ESWITCH_S, CONTINUE_N);
|
||||
assertFail("compiler.err.continue.outside.switch.expression", ESWITCH_S, CONTINUE_N);
|
||||
assertFail("compiler.err.return.outside.switch.expression", ESWITCH_S, RETURN_N);
|
||||
assertFail("compiler.err.return.outside.switch.expression", ESWITCH_S, RETURN_S);
|
||||
// Function-valued switch expression
|
||||
assertOK(INT_FN_ESWITCH, BREAK_INT_FN);
|
||||
assertFail("compiler.err.break.missing.value", INT_FN_ESWITCH, BREAK_N);
|
||||
assertFail("compiler.err.prob.found.req", INT_FN_ESWITCH, BREAK_Z);
|
||||
assertFail("compiler.err.prob.found.req", INT_FN_ESWITCH, BREAK_S);
|
||||
assertOK(INT_FN_ESWITCH, YIELD_INT_FN);
|
||||
assertFail("compiler.err.break.outside.switch.expression", INT_FN_ESWITCH, BREAK_N);
|
||||
assertFail("compiler.err.prob.found.req", INT_FN_ESWITCH, YIELD_Z);
|
||||
assertFail("compiler.err.prob.found.req", INT_FN_ESWITCH, YIELD_S);
|
||||
|
||||
assertFail("compiler.err.cant.resolve.location", INT_FN_ESWITCH, BREAK_L);
|
||||
assertFail("compiler.err.undef.label", INT_FN_ESWITCH, BREAK_L);
|
||||
assertFail("compiler.err.break.outside.switch.expression", LABEL, BLOCK, INT_FN_ESWITCH, BREAK_L);
|
||||
assertFail("compiler.err.undef.label", INT_FN_ESWITCH, CONTINUE_L);
|
||||
assertFail("compiler.err.cont.outside.loop", INT_FN_ESWITCH, CONTINUE_N);
|
||||
assertFail("compiler.err.continue.outside.switch.expression", INT_FN_ESWITCH, CONTINUE_N);
|
||||
assertFail("compiler.err.return.outside.switch.expression", INT_FN_ESWITCH, RETURN_N);
|
||||
assertFail("compiler.err.return.outside.switch.expression", INT_FN_ESWITCH, RETURN_S);
|
||||
|
||||
}
|
||||
|
||||
public void testNestedInExpSwitch() {
|
||||
assertOK(ESWITCH_Z, IF, BREAK_Z);
|
||||
assertOK(ESWITCH_Z, BLOCK, BREAK_Z);
|
||||
assertOK(ESWITCH_Z, IF, YIELD_Z);
|
||||
assertOK(ESWITCH_Z, BLOCK, YIELD_Z);
|
||||
//
|
||||
assertOK(ESWITCH_Z, IF, IF, BREAK_Z);
|
||||
assertOK(ESWITCH_Z, IF, BLOCK, BREAK_Z);
|
||||
assertOK(ESWITCH_Z, BLOCK, IF, BREAK_Z);
|
||||
assertOK(ESWITCH_Z, BLOCK, BLOCK, BREAK_Z);
|
||||
assertOK(ESWITCH_Z, IF, IF, YIELD_Z);
|
||||
assertOK(ESWITCH_Z, IF, BLOCK, YIELD_Z);
|
||||
assertOK(ESWITCH_Z, BLOCK, IF, YIELD_Z);
|
||||
assertOK(ESWITCH_Z, BLOCK, BLOCK, YIELD_Z);
|
||||
//
|
||||
assertOK(ESWITCH_Z, IF, IF, IF, BREAK_Z);
|
||||
assertOK(ESWITCH_Z, IF, IF, BLOCK, BREAK_Z);
|
||||
assertOK(ESWITCH_Z, IF, BLOCK, IF, BREAK_Z);
|
||||
assertOK(ESWITCH_Z, IF, BLOCK, BLOCK, BREAK_Z);
|
||||
assertOK(ESWITCH_Z, BLOCK, IF, IF, BREAK_Z);
|
||||
assertOK(ESWITCH_Z, BLOCK, IF, BLOCK, BREAK_Z);
|
||||
assertOK(ESWITCH_Z, BLOCK, BLOCK, IF, BREAK_Z);
|
||||
assertOK(ESWITCH_Z, BLOCK, BLOCK, BLOCK, BREAK_Z);
|
||||
assertOK(ESWITCH_Z, IF, IF, IF, YIELD_Z);
|
||||
assertOK(ESWITCH_Z, IF, IF, BLOCK, YIELD_Z);
|
||||
assertOK(ESWITCH_Z, IF, BLOCK, IF, YIELD_Z);
|
||||
assertOK(ESWITCH_Z, IF, BLOCK, BLOCK, YIELD_Z);
|
||||
assertOK(ESWITCH_Z, BLOCK, IF, IF, YIELD_Z);
|
||||
assertOK(ESWITCH_Z, BLOCK, IF, BLOCK, YIELD_Z);
|
||||
assertOK(ESWITCH_Z, BLOCK, BLOCK, IF, YIELD_Z);
|
||||
assertOK(ESWITCH_Z, BLOCK, BLOCK, BLOCK, YIELD_Z);
|
||||
//
|
||||
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, SSWITCH, BREAK_Z);
|
||||
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, FOR, BREAK_Z);
|
||||
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, WHILE, BREAK_Z);
|
||||
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, DO, BREAK_Z);
|
||||
assertFail("compiler.err.break.complex.value.no.switch.expression", ESWITCH_Z, INT_FN, BREAK_Z);
|
||||
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, SSWITCH, IF, BREAK_Z);
|
||||
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, FOR, IF, BREAK_Z);
|
||||
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, WHILE, IF, BREAK_Z);
|
||||
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, DO, IF, BREAK_Z);
|
||||
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, BLOCK, SSWITCH, IF, BREAK_Z);
|
||||
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, BLOCK, FOR, IF, BREAK_Z);
|
||||
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, BLOCK, WHILE, IF, BREAK_Z);
|
||||
assertFail("compiler.err.break.expr.not.immediate", ESWITCH_Z, BLOCK, DO, IF, BREAK_Z);
|
||||
assertOK(ESWITCH_Z, YIELD_Z, SSWITCH, YIELD_Z);
|
||||
assertOK(ESWITCH_Z, YIELD_Z, FOR, YIELD_Z);
|
||||
assertOK(ESWITCH_Z, YIELD_Z, WHILE, YIELD_Z);
|
||||
assertOK(ESWITCH_Z, YIELD_Z, DO, YIELD_Z);
|
||||
assertFail("compiler.err.no.switch.expression", ESWITCH_Z, INT_FN, YIELD_Z);
|
||||
assertOK(ESWITCH_Z, YIELD_Z, SSWITCH, IF, YIELD_Z);
|
||||
assertOK(ESWITCH_Z, YIELD_Z, FOR, IF, YIELD_Z);
|
||||
assertOK(ESWITCH_Z, YIELD_Z, WHILE, IF, YIELD_Z);
|
||||
assertOK(ESWITCH_Z, YIELD_Z, DO, IF, YIELD_Z);
|
||||
assertOK(ESWITCH_Z, YIELD_Z, BLOCK, SSWITCH, IF, YIELD_Z);
|
||||
assertOK(ESWITCH_Z, YIELD_Z, BLOCK, FOR, IF, YIELD_Z);
|
||||
assertOK(ESWITCH_Z, YIELD_Z, BLOCK, WHILE, IF, YIELD_Z);
|
||||
assertOK(ESWITCH_Z, YIELD_Z, BLOCK, DO, IF, YIELD_Z);
|
||||
}
|
||||
|
||||
public void testBreakExpressionLabelDisambiguation() {
|
||||
assertOK(DEF_LABEL_VAR, ESWITCH_Z, BREAK_L);
|
||||
assertFail("compiler.err.break.ambiguous.target", LABEL, FOR, BLOCK, DEF_LABEL_VAR, ESWITCH_Z, BREAK_L);
|
||||
assertFail("compiler.err.break.ambiguous.target", DEF_LABEL_VAR, ESWITCH_Z, LABEL, FOR, BREAK_L); //label break
|
||||
assertFail("compiler.err.break.ambiguous.target", DEF_LABEL_VAR, LABEL, BLOCK, ESWITCH_Z, BREAK_L); //expression break
|
||||
assertOK(DEF_LABEL_VAR, ESWITCH_Z, YIELD_L);
|
||||
assertFail("compiler.err.undef.label", DEF_LABEL_VAR, ESWITCH_Z, BREAK_L);
|
||||
assertFail("compiler.err.break.outside.switch.expression", LABEL, FOR, BLOCK, DEF_LABEL_VAR, ESWITCH_Z, BREAK_L);
|
||||
assertOK(DEF_LABEL_VAR, ESWITCH_Z, YIELD_Z, LABEL, FOR, BREAK_L); //label break
|
||||
assertFail("compiler.err.break.outside.switch.expression", DEF_LABEL_VAR, LABEL, BLOCK, ESWITCH_Z, BREAK_L);
|
||||
assertOK(DEF_LABEL_VAR, LABEL, BLOCK, ESWITCH_Z, YIELD_L); //expression break
|
||||
//
|
||||
}
|
||||
|
||||
public void testFunReturningSwitchExp() {
|
||||
assertOK(INT_FN_ESWITCH, BREAK_INT_FN);
|
||||
assertOK(INT_FN_ESWITCH, YIELD_INT_FN);
|
||||
}
|
||||
|
||||
public void testContinueLoops() {
|
||||
|
@ -160,6 +160,9 @@ public class Deduplication {
|
||||
group((Consumer<Integer>) x -> Deduplication.this.f());
|
||||
}
|
||||
}
|
||||
|
||||
group((Function<Integer, Integer>) x -> switch (x) { default: yield x; },
|
||||
(Function<Integer, Integer>) x -> switch (x) { default: yield x; });
|
||||
}
|
||||
|
||||
void f() {}
|
||||
|
@ -84,6 +84,7 @@ public class DeduplicationTest {
|
||||
Listener diagnosticListener = new Listener();
|
||||
Path testSrc = Paths.get(System.getProperty("test.src"));
|
||||
Path file = testSrc.resolve("Deduplication.java");
|
||||
String sourceVersion = Integer.toString(Runtime.version().feature());
|
||||
JavacTask task =
|
||||
javacTool.getTask(
|
||||
null,
|
||||
@ -93,7 +94,8 @@ public class DeduplicationTest {
|
||||
"-d",
|
||||
".",
|
||||
"-XDdebug.dumpLambdaToMethodDeduplication",
|
||||
"-XDdebug.dumpLambdaToMethodStats"),
|
||||
"-XDdebug.dumpLambdaToMethodStats",
|
||||
"--enable-preview", "-source", sourceVersion),
|
||||
null,
|
||||
fileManager.getJavaFileObjects(file));
|
||||
Map<JCLambda, JCLambda> dedupedLambdas = new LinkedHashMap<>();
|
||||
@ -192,6 +194,9 @@ public class DeduplicationTest {
|
||||
(JCLambda) d.getDiagnosticPosition().getTree(),
|
||||
(MethodSymbol) d.getArgs()[0]);
|
||||
break;
|
||||
case "compiler.note.preview.filename":
|
||||
case "compiler.note.preview.recompile":
|
||||
break; //ignore
|
||||
default:
|
||||
unexpected.add(diagnostic);
|
||||
}
|
||||
|
@ -782,6 +782,11 @@ public class DPrinter {
|
||||
|
||||
@Override
|
||||
public void visitBreak(JCBreak tree) {
|
||||
printName("label", tree.label);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitYield(JCYield tree) {
|
||||
printTree("value", tree.value);
|
||||
}
|
||||
|
||||
|
@ -1,24 +1,24 @@
|
||||
ParserTest.java:14:18: compiler.err.var.not.allowed
|
||||
ParserTest.java:16:22: compiler.err.var.not.allowed
|
||||
ParserTest.java:20:19: compiler.err.var.not.allowed
|
||||
ParserTest.java:24:14: compiler.err.var.not.allowed
|
||||
ParserTest.java:28:20: compiler.err.var.not.allowed
|
||||
ParserTest.java:36:27: compiler.err.var.not.allowed
|
||||
ParserTest.java:38:5: compiler.err.var.not.allowed.here
|
||||
ParserTest.java:41:15: compiler.err.var.not.allowed.array
|
||||
ParserTest.java:42:13: compiler.err.var.not.allowed.array
|
||||
ParserTest.java:43:17: compiler.err.var.not.allowed.array
|
||||
ParserTest.java:44:13: compiler.err.var.not.allowed.array
|
||||
ParserTest.java:45:15: compiler.err.var.not.allowed.array
|
||||
ParserTest.java:46:13: compiler.err.var.not.allowed.array
|
||||
ParserTest.java:49:24: compiler.err.var.not.allowed.compound
|
||||
ParserTest.java:54:5: compiler.err.var.not.allowed.here
|
||||
ParserTest.java:58:16: compiler.err.var.not.allowed.here
|
||||
ParserTest.java:59:14: compiler.err.var.not.allowed.here
|
||||
ParserTest.java:60:24: compiler.err.var.not.allowed.here
|
||||
ParserTest.java:61:22: compiler.err.var.not.allowed.here
|
||||
ParserTest.java:63:22: compiler.err.var.not.allowed.here
|
||||
ParserTest.java:64:18: compiler.err.var.not.allowed.here
|
||||
ParserTest.java:68:35: compiler.err.var.not.allowed.here
|
||||
ParserTest.java:69:22: compiler.err.var.not.allowed.here
|
||||
ParserTest.java:14:18: compiler.err.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:16:22: compiler.err.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:20:19: compiler.err.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:24:14: compiler.err.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:28:20: compiler.err.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:36:27: compiler.err.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:38:5: compiler.err.restricted.type.not.allowed.here: var
|
||||
ParserTest.java:41:15: compiler.err.restricted.type.not.allowed.array: var
|
||||
ParserTest.java:42:13: compiler.err.restricted.type.not.allowed.array: var
|
||||
ParserTest.java:43:17: compiler.err.restricted.type.not.allowed.array: var
|
||||
ParserTest.java:44:13: compiler.err.restricted.type.not.allowed.array: var
|
||||
ParserTest.java:45:15: compiler.err.restricted.type.not.allowed.array: var
|
||||
ParserTest.java:46:13: compiler.err.restricted.type.not.allowed.array: var
|
||||
ParserTest.java:49:24: compiler.err.restricted.type.not.allowed.compound: var
|
||||
ParserTest.java:54:5: compiler.err.restricted.type.not.allowed.here: var
|
||||
ParserTest.java:58:16: compiler.err.restricted.type.not.allowed.here: var
|
||||
ParserTest.java:59:14: compiler.err.restricted.type.not.allowed.here: var
|
||||
ParserTest.java:60:24: compiler.err.restricted.type.not.allowed.here: var
|
||||
ParserTest.java:61:22: compiler.err.restricted.type.not.allowed.here: var
|
||||
ParserTest.java:63:22: compiler.err.restricted.type.not.allowed.here: var
|
||||
ParserTest.java:64:18: compiler.err.restricted.type.not.allowed.here: var
|
||||
ParserTest.java:68:35: compiler.err.restricted.type.not.allowed.here: var
|
||||
ParserTest.java:69:22: compiler.err.restricted.type.not.allowed.here: var
|
||||
23 errors
|
||||
|
@ -1,31 +1,31 @@
|
||||
ParserTest.java:14:18: compiler.warn.var.not.allowed
|
||||
ParserTest.java:16:22: compiler.warn.var.not.allowed
|
||||
ParserTest.java:20:19: compiler.warn.var.not.allowed
|
||||
ParserTest.java:24:14: compiler.warn.var.not.allowed
|
||||
ParserTest.java:28:20: compiler.warn.var.not.allowed
|
||||
ParserTest.java:36:27: compiler.warn.var.not.allowed
|
||||
ParserTest.java:38:5: compiler.warn.var.not.allowed
|
||||
ParserTest.java:41:15: compiler.warn.var.not.allowed
|
||||
ParserTest.java:42:13: compiler.warn.var.not.allowed
|
||||
ParserTest.java:43:17: compiler.warn.var.not.allowed
|
||||
ParserTest.java:44:13: compiler.warn.var.not.allowed
|
||||
ParserTest.java:45:15: compiler.warn.var.not.allowed
|
||||
ParserTest.java:46:13: compiler.warn.var.not.allowed
|
||||
ParserTest.java:47:23: compiler.warn.var.not.allowed
|
||||
ParserTest.java:48:13: compiler.warn.var.not.allowed
|
||||
ParserTest.java:49:13: compiler.warn.var.not.allowed
|
||||
ParserTest.java:50:23: compiler.warn.var.not.allowed
|
||||
ParserTest.java:51:23: compiler.warn.var.not.allowed
|
||||
ParserTest.java:54:5: compiler.warn.var.not.allowed
|
||||
ParserTest.java:58:16: compiler.warn.var.not.allowed
|
||||
ParserTest.java:59:14: compiler.warn.var.not.allowed
|
||||
ParserTest.java:60:24: compiler.warn.var.not.allowed
|
||||
ParserTest.java:61:22: compiler.warn.var.not.allowed
|
||||
ParserTest.java:63:22: compiler.warn.var.not.allowed
|
||||
ParserTest.java:63:40: compiler.warn.var.not.allowed
|
||||
ParserTest.java:64:18: compiler.warn.var.not.allowed
|
||||
ParserTest.java:68:35: compiler.warn.var.not.allowed
|
||||
ParserTest.java:69:22: compiler.warn.var.not.allowed
|
||||
ParserTest.java:73:24: compiler.warn.var.not.allowed
|
||||
ParserTest.java:74:18: compiler.warn.var.not.allowed
|
||||
30 warnings
|
||||
ParserTest.java:14:18: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:16:22: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:20:19: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:24:14: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:28:20: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:36:27: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:38:5: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:41:15: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:42:13: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:43:17: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:44:13: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:45:15: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:46:13: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:47:23: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:48:13: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:49:13: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:50:23: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:51:23: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:54:5: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:58:16: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:59:14: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:60:24: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:61:22: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:63:22: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:63:40: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:64:18: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:68:35: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:69:22: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:73:24: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
ParserTest.java:74:18: compiler.warn.restricted.type.not.allowed: var, 10
|
||||
30 warnings
|
@ -1,3 +1,3 @@
|
||||
BadTypeReference.java:14:9: compiler.err.illegal.ref.to.var.type
|
||||
BadTypeReference.java:15:21: compiler.err.illegal.ref.to.var.type
|
||||
BadTypeReference.java:14:9: compiler.err.illegal.ref.to.restricted.type: var
|
||||
BadTypeReference.java:15:21: compiler.err.illegal.ref.to.restricted.type: var
|
||||
2 errors
|
||||
|
@ -1083,12 +1083,12 @@ public class JavacParserTest extends TestCase {
|
||||
" }" +
|
||||
" int j = switch (i) {" +
|
||||
" case 0 -> i + 1;" +
|
||||
" case 1 -> { break i + 1; }" +
|
||||
" case 1 -> { yield i + 1; }" +
|
||||
" default -> throw new RuntimeException();" +
|
||||
" };" +
|
||||
" int k = switch (i) {" +
|
||||
" case 0: break i + 1;" +
|
||||
" case 1: { break i + 1; }" +
|
||||
" case 0: yield i + 1;" +
|
||||
" case 1: { yield i + 1; }" +
|
||||
" default: throw new RuntimeException();" +
|
||||
" };" +
|
||||
" }" +
|
||||
@ -1120,7 +1120,7 @@ public class JavacParserTest extends TestCase {
|
||||
List<String> expectedSpans = List.of(
|
||||
"i++;", "{ i++; }", "throw new RuntimeException();", "if (true) ;", "i++;",
|
||||
"<null>", "<null>", "<null>", "<null>", "<null>",
|
||||
"i + 1"/*TODO semicolon?*/, "{ break i + 1; }", "throw new RuntimeException();",
|
||||
"i + 1"/*TODO semicolon?*/, "{ yield i + 1; }", "throw new RuntimeException();",
|
||||
"<null>", "<null>", "<null>");
|
||||
assertEquals("the error spans are not correct; actual:" + spans, expectedSpans, spans);
|
||||
String toString = normalize(cut.toString());
|
||||
@ -1162,19 +1162,19 @@ public class JavacParserTest extends TestCase {
|
||||
" \n" +
|
||||
" }\n" +
|
||||
" int j = switch (i) {\n" +
|
||||
" case 0 -> break i + 1;\n" +
|
||||
" case 0 -> yield i + 1;\n" +
|
||||
" case 1 -> {\n" +
|
||||
" break i + 1;\n" +
|
||||
" yield i + 1;\n" +
|
||||
" }\n" +
|
||||
" default -> throw new RuntimeException();\n" +
|
||||
" };\n" +
|
||||
" int k = switch (i) {\n" +
|
||||
" case 0:\n" +
|
||||
" break i + 1;\n" +
|
||||
" yield i + 1;\n" +
|
||||
" \n" +
|
||||
" case 1:\n" +
|
||||
" {\n" +
|
||||
" break i + 1;\n" +
|
||||
" yield i + 1;\n" +
|
||||
" }\n" +
|
||||
" \n" +
|
||||
" default:\n" +
|
||||
|
@ -54,7 +54,7 @@ public class BreakTest {
|
||||
" int t2(Integer i) {" +
|
||||
" return switch (i) {" +
|
||||
" case null: break LABEL;" +
|
||||
" default: break 2;" +
|
||||
" default: yield 2;" +
|
||||
" }" +
|
||||
" }" +
|
||||
"}";
|
||||
@ -79,7 +79,7 @@ public class BreakTest {
|
||||
}
|
||||
}.scan(ct.parse(), null);
|
||||
|
||||
List<String> expected = Arrays.asList("LABEL", null, "LABEL", null);
|
||||
List<String> expected = Arrays.asList("LABEL", null, "LABEL");
|
||||
|
||||
if (!expected.equals(labels)) {
|
||||
throw new AssertionError("Unexpected labels found: " + labels);
|
||||
|
@ -37,8 +37,8 @@ public class DefiniteAssignment1 {
|
||||
int x;
|
||||
|
||||
boolean t1 = (b && switch(a) {
|
||||
case 0: break (x = 1) == 1 || true;
|
||||
default: break false;
|
||||
case 0: yield (x = 1) == 1 || true;
|
||||
default: yield false;
|
||||
}) && x == 1; //x is definitelly assigned here
|
||||
|
||||
if (!t1) {
|
||||
@ -50,8 +50,8 @@ public class DefiniteAssignment1 {
|
||||
int x;
|
||||
|
||||
boolean t1 = (b && switch(a) {
|
||||
case 0: break (x = 1) == 1 || isTrue();
|
||||
default: break false;
|
||||
case 0: yield (x = 1) == 1 || isTrue();
|
||||
default: yield false;
|
||||
}) && x == 1; //x is definitelly assigned here
|
||||
|
||||
if (!t1) {
|
||||
@ -63,8 +63,8 @@ public class DefiniteAssignment1 {
|
||||
int x;
|
||||
|
||||
boolean t1a = (b && switch(a) {
|
||||
case 0: break (x = 1) == 1;
|
||||
default: break false;
|
||||
case 0: yield (x = 1) == 1;
|
||||
default: yield false;
|
||||
}) && x == 1; //x is definitelly assigned here
|
||||
|
||||
if (!t1a) {
|
||||
@ -76,8 +76,8 @@ public class DefiniteAssignment1 {
|
||||
int x;
|
||||
|
||||
boolean t1b = (switch(a) {
|
||||
case 0: break (x = 1) == 1;
|
||||
default: break false;
|
||||
case 0: yield (x = 1) == 1;
|
||||
default: yield false;
|
||||
}) && x == 1; //x is definitelly assigned here
|
||||
|
||||
if (!t1b) {
|
||||
@ -89,8 +89,8 @@ public class DefiniteAssignment1 {
|
||||
int x;
|
||||
|
||||
boolean t2 = !(b && switch(a) {
|
||||
case 0: break (x = 1) == 1 || true;
|
||||
default: break false;
|
||||
case 0: yield (x = 1) == 1 || true;
|
||||
default: yield false;
|
||||
}) || x == 1;
|
||||
|
||||
if (!t2) {
|
||||
@ -102,8 +102,8 @@ public class DefiniteAssignment1 {
|
||||
int x;
|
||||
|
||||
boolean t2 = !(b && switch(a) {
|
||||
case 0: break (x = 1) == 1 || isTrue();
|
||||
default: break false;
|
||||
case 0: yield (x = 1) == 1 || isTrue();
|
||||
default: yield false;
|
||||
}) || x == 1;
|
||||
|
||||
if (!t2) {
|
||||
@ -115,8 +115,8 @@ public class DefiniteAssignment1 {
|
||||
int x;
|
||||
|
||||
boolean t3 = !(switch(a) {
|
||||
case 0: break (x = 1) == 1 || true;
|
||||
default: break false;
|
||||
case 0: yield (x = 1) == 1 || true;
|
||||
default: yield false;
|
||||
}) || x == 2;
|
||||
|
||||
if (t3) {
|
||||
@ -128,8 +128,8 @@ public class DefiniteAssignment1 {
|
||||
int x;
|
||||
|
||||
boolean t3 = !(switch(a) {
|
||||
case 0: break (x = 1) == 1 || isTrue();
|
||||
default: break false;
|
||||
case 0: yield (x = 1) == 1 || isTrue();
|
||||
default: yield false;
|
||||
}) || x == 2;
|
||||
|
||||
if (t3) {
|
||||
@ -141,7 +141,7 @@ public class DefiniteAssignment1 {
|
||||
int x;
|
||||
|
||||
boolean t4 = (b && switch(a) {
|
||||
case 0: break (x = 1) == 1 || true;
|
||||
case 0: yield (x = 1) == 1 || true;
|
||||
default: throw new IllegalStateException();
|
||||
}) && x == 1; //x is definitelly assigned here
|
||||
|
||||
@ -155,7 +155,7 @@ public class DefiniteAssignment1 {
|
||||
int x;
|
||||
|
||||
boolean t4 = (b && switch(a) {
|
||||
case 0: break (x = 1) == 1 || isTrue();
|
||||
case 0: yield (x = 1) == 1 || isTrue();
|
||||
default: throw new IllegalStateException();
|
||||
}) && x == 1; //x is definitelly assigned here
|
||||
|
||||
@ -170,8 +170,8 @@ public class DefiniteAssignment1 {
|
||||
String s = "a";
|
||||
|
||||
boolean t5 = (switch(s) {
|
||||
case "a": break (x = 1) == 1 || true;
|
||||
default: break false;
|
||||
case "a": yield (x = 1) == 1 || true;
|
||||
default: yield false;
|
||||
}) && x == 1; //x is definitelly assigned here
|
||||
|
||||
if (!t5) {
|
||||
@ -185,8 +185,8 @@ public class DefiniteAssignment1 {
|
||||
String s = "a";
|
||||
|
||||
boolean t5 = (switch(s) {
|
||||
case "a": break (x = 1) == 1 || isTrue();
|
||||
default: break false;
|
||||
case "a": yield (x = 1) == 1 || isTrue();
|
||||
default: yield false;
|
||||
}) && x == 1; //x is definitelly assigned here
|
||||
|
||||
if (!t5) {
|
||||
@ -199,8 +199,8 @@ public class DefiniteAssignment1 {
|
||||
E e = E.B;
|
||||
|
||||
boolean t6 = (switch(e) {
|
||||
case B: break (x = 1) == 1 || true;
|
||||
default: break false;
|
||||
case B: yield (x = 1) == 1 || true;
|
||||
default: yield false;
|
||||
}) && x == 1; //x is definitelly assigned here
|
||||
|
||||
if (!t6) {
|
||||
@ -213,8 +213,8 @@ public class DefiniteAssignment1 {
|
||||
E e = E.B;
|
||||
|
||||
boolean t6 = (switch(e) {
|
||||
case B: break (x = 1) == 1 || isTrue();
|
||||
default: break false;
|
||||
case B: yield (x = 1) == 1 || isTrue();
|
||||
default: yield false;
|
||||
}) && x == 1; //x is definitelly assigned here
|
||||
|
||||
if (!t6) {
|
||||
@ -251,9 +251,9 @@ public class DefiniteAssignment1 {
|
||||
E e = E.B;
|
||||
|
||||
boolean t8 = (switch(e) {
|
||||
case A: x = 1; break true;
|
||||
case B: break (x = 1) == 1 || true;
|
||||
default: break false;
|
||||
case A: x = 1; yield true;
|
||||
case B: yield (x = 1) == 1 || true;
|
||||
default: yield false;
|
||||
}) && x == 1; //x is definitelly assigned here
|
||||
|
||||
if (!t8) {
|
||||
@ -266,9 +266,9 @@ public class DefiniteAssignment1 {
|
||||
E e = E.B;
|
||||
|
||||
boolean t8 = (switch(e) {
|
||||
case A: x = 1; break isTrue();
|
||||
case B: break (x = 1) == 1 || isTrue();
|
||||
default: break false;
|
||||
case A: x = 1; yield isTrue();
|
||||
case B: yield (x = 1) == 1 || isTrue();
|
||||
default: yield false;
|
||||
}) && x == 1; //x is definitelly assigned here
|
||||
|
||||
if (!t8) {
|
||||
@ -281,9 +281,9 @@ public class DefiniteAssignment1 {
|
||||
E e = E.A;
|
||||
|
||||
boolean t9 = (switch(e) {
|
||||
case A: x = 1; break true;
|
||||
case B: break (x = 1) == 1 || true;
|
||||
default: break false;
|
||||
case A: x = 1; yield true;
|
||||
case B: yield (x = 1) == 1 || true;
|
||||
default: yield false;
|
||||
}) && x == 1; //x is definitelly assigned here
|
||||
|
||||
if (!t9) {
|
||||
@ -296,9 +296,9 @@ public class DefiniteAssignment1 {
|
||||
E e = E.A;
|
||||
|
||||
boolean t9 = (switch(e) {
|
||||
case A: x = 1; break isTrue();
|
||||
case B: break (x = 1) == 1 || isTrue();
|
||||
default: break false;
|
||||
case A: x = 1; yield isTrue();
|
||||
case B: yield (x = 1) == 1 || isTrue();
|
||||
default: yield false;
|
||||
}) && x == 1; //x is definitelly assigned here
|
||||
|
||||
if (!t9) {
|
||||
@ -311,9 +311,9 @@ public class DefiniteAssignment1 {
|
||||
E e = E.C;
|
||||
|
||||
boolean tA = (switch(e) {
|
||||
case A: x = 1; break true;
|
||||
case B: break (x = 1) == 1 || true;
|
||||
default: break false;
|
||||
case A: x = 1; yield true;
|
||||
case B: yield (x = 1) == 1 || true;
|
||||
default: yield false;
|
||||
}) && x == 1; //x is definitelly assigned here
|
||||
|
||||
if (tA) {
|
||||
@ -326,9 +326,9 @@ public class DefiniteAssignment1 {
|
||||
E e = E.C;
|
||||
|
||||
boolean tA = (switch(e) {
|
||||
case A: x = 1; break isTrue();
|
||||
case B: break (x = 1) == 1 || isTrue();
|
||||
default: break false;
|
||||
case A: x = 1; yield isTrue();
|
||||
case B: yield (x = 1) == 1 || isTrue();
|
||||
default: yield false;
|
||||
}) && x == 1; //x is definitelly assigned here
|
||||
|
||||
if (tA) {
|
||||
@ -341,9 +341,9 @@ public class DefiniteAssignment1 {
|
||||
E e = E.C;
|
||||
|
||||
boolean tA = (switch(e) {
|
||||
case A: x = 1; break true;
|
||||
case B: break (x = 2) == 2 || true;
|
||||
default: break false;
|
||||
case A: x = 1; yield true;
|
||||
case B: yield (x = 2) == 2 || true;
|
||||
default: yield false;
|
||||
}) || (x = 3) == 3; //x is definitelly unassigned here
|
||||
|
||||
if (x != 3) {
|
||||
@ -356,9 +356,9 @@ public class DefiniteAssignment1 {
|
||||
E e = E.A;
|
||||
|
||||
boolean tA = (switch(e) {
|
||||
case A: break isTrue() && (x = 1) == 1;
|
||||
case B: break (x = 1) == 1 || isTrue();
|
||||
default: break false;
|
||||
case A: yield isTrue() && (x = 1) == 1;
|
||||
case B: yield (x = 1) == 1 || isTrue();
|
||||
default: yield false;
|
||||
}) && x == 1; //x is definitelly assigned here
|
||||
|
||||
if (!tA) {
|
||||
@ -371,9 +371,9 @@ public class DefiniteAssignment1 {
|
||||
E e = E.A;
|
||||
|
||||
boolean tA = (switch(e) {
|
||||
case A: break isTrue() && e != E.C ? (x = 1) == 1 && e != E.B : false;
|
||||
case B: break (x = 1) == 1 || true;
|
||||
default: break false;
|
||||
case A: yield isTrue() && e != E.C ? (x = 1) == 1 && e != E.B : false;
|
||||
case B: yield (x = 1) == 1 || true;
|
||||
default: yield false;
|
||||
}) && x == 1; //x is definitelly assigned here
|
||||
|
||||
if (!tA) {
|
||||
@ -386,9 +386,9 @@ public class DefiniteAssignment1 {
|
||||
E e = E.A;
|
||||
|
||||
boolean tA = (switch(e) {
|
||||
case A: break isTrue() && e != E.C ? (x = 1) == 1 && e != E.B : false;
|
||||
case B: break (x = 1) == 1 || isTrue();
|
||||
default: break false;
|
||||
case A: yield isTrue() && e != E.C ? (x = 1) == 1 && e != E.B : false;
|
||||
case B: yield (x = 1) == 1 || isTrue();
|
||||
default: yield false;
|
||||
}) && x == 1; //x is definitelly assigned here
|
||||
|
||||
if (!tA) {
|
||||
@ -416,9 +416,9 @@ public class DefiniteAssignment1 {
|
||||
E e = E.A;
|
||||
|
||||
boolean tA = (switch(e) {
|
||||
case A -> { x = 1; break true; }
|
||||
case B -> { x = 1; break true; }
|
||||
case C -> { x = 1; break true; }
|
||||
case A -> { x = 1; yield true; }
|
||||
case B -> { x = 1; yield true; }
|
||||
case C -> { x = 1; yield true; }
|
||||
}) && x == 1; //x is definitelly assigned here
|
||||
|
||||
if (!tA) {
|
||||
|
@ -15,8 +15,8 @@ public class DefiniteAssignment2 {
|
||||
int x;
|
||||
|
||||
t = (b && switch(a) {
|
||||
case 0: break (x = 1) == 1 || true;
|
||||
default: break false;
|
||||
case 0: yield (x = 1) == 1 || true;
|
||||
default: yield false;
|
||||
}) || x == 1;
|
||||
}
|
||||
|
||||
@ -24,8 +24,8 @@ public class DefiniteAssignment2 {
|
||||
int x;
|
||||
|
||||
t = (switch(a) {
|
||||
case 0: break (x = 1) == 1;
|
||||
default: break false;
|
||||
case 0: yield (x = 1) == 1;
|
||||
default: yield false;
|
||||
}) || x == 1;
|
||||
}
|
||||
|
||||
@ -33,9 +33,9 @@ public class DefiniteAssignment2 {
|
||||
int x;
|
||||
|
||||
t = (switch(a) {
|
||||
case 0: x = 1; break true;
|
||||
case 1: break (x = 1) == 1;
|
||||
default: break false;
|
||||
case 0: x = 1; yield true;
|
||||
case 1: yield (x = 1) == 1;
|
||||
default: yield false;
|
||||
}) || x == 1;
|
||||
}
|
||||
|
||||
@ -43,9 +43,9 @@ public class DefiniteAssignment2 {
|
||||
int x;
|
||||
|
||||
t = (switch(a) {
|
||||
case 0: break true;
|
||||
case 1: break (x = 1) == 1;
|
||||
default: break false;
|
||||
case 0: yield true;
|
||||
case 1: yield (x = 1) == 1;
|
||||
default: yield false;
|
||||
}) && x == 1;
|
||||
}
|
||||
|
||||
@ -53,9 +53,9 @@ public class DefiniteAssignment2 {
|
||||
int x;
|
||||
|
||||
t = (switch(a) {
|
||||
case 0: break false;
|
||||
case 1: break isTrue() || (x = 1) == 1;
|
||||
default: break false;
|
||||
case 0: yield false;
|
||||
case 1: yield isTrue() || (x = 1) == 1;
|
||||
default: yield false;
|
||||
}) && x == 1;
|
||||
}
|
||||
|
||||
@ -63,9 +63,9 @@ public class DefiniteAssignment2 {
|
||||
int x;
|
||||
|
||||
t = (switch(a) {
|
||||
case 0: break false;
|
||||
case 1: break isTrue() ? true : (x = 1) == 1;
|
||||
default: break false;
|
||||
case 0: yield false;
|
||||
case 1: yield isTrue() ? true : (x = 1) == 1;
|
||||
default: yield false;
|
||||
}) && x == 1;
|
||||
}
|
||||
|
||||
@ -73,9 +73,9 @@ public class DefiniteAssignment2 {
|
||||
final int x;
|
||||
|
||||
t = (switch(a) {
|
||||
case 0: break false;
|
||||
case 1: break isTrue() ? true : (x = 1) == 1;
|
||||
default: break false;
|
||||
case 0: yield false;
|
||||
case 1: yield isTrue() ? true : (x = 1) == 1;
|
||||
default: yield false;
|
||||
}) && (x = 1) == 1;
|
||||
}
|
||||
}
|
||||
|
@ -39,15 +39,15 @@ public class ExpressionSwitch {
|
||||
private String print(T t) {
|
||||
return switch (t) {
|
||||
case A -> "A";
|
||||
case B -> { break "B"; }
|
||||
default -> { break "other"; }
|
||||
case B -> { yield "B"; }
|
||||
default -> { yield "other"; }
|
||||
};
|
||||
}
|
||||
|
||||
private String exhaustive1(T t) {
|
||||
return switch (t) {
|
||||
case A -> "A";
|
||||
case B -> { break "B"; }
|
||||
case B -> { yield "B"; }
|
||||
case C -> "C";
|
||||
case D -> "D";
|
||||
};
|
||||
@ -64,25 +64,25 @@ public class ExpressionSwitch {
|
||||
|
||||
private String scopesIsolated(T t) {
|
||||
return switch (t) {
|
||||
case A -> { String res = "A"; break res;}
|
||||
case B -> { String res = "B"; break res;}
|
||||
default -> { String res = "default"; break res;}
|
||||
case A -> { String res = "A"; yield res;}
|
||||
case B -> { String res = "B"; yield res;}
|
||||
default -> { String res = "default"; yield res;}
|
||||
};
|
||||
}
|
||||
|
||||
private Supplier<String> lambdas1(T t) {
|
||||
return switch (t) {
|
||||
case A -> () -> "A";
|
||||
case B -> { break () -> "B"; }
|
||||
case B -> { yield () -> "B"; }
|
||||
default -> () -> "default";
|
||||
};
|
||||
}
|
||||
|
||||
private Supplier<String> lambdas2(T t) {
|
||||
return switch (t) {
|
||||
case A: break () -> "A";
|
||||
case B: { break () -> "B"; }
|
||||
default: break () -> "default";
|
||||
case A: yield () -> "A";
|
||||
case B: { yield () -> "B"; }
|
||||
default: yield () -> "default";
|
||||
};
|
||||
}
|
||||
|
||||
@ -91,16 +91,16 @@ public class ExpressionSwitch {
|
||||
? -2
|
||||
: switch (s) {
|
||||
case "A", "B" -> 0;
|
||||
case "C" -> { break 1; }
|
||||
case "C" -> { yield 1; }
|
||||
default -> -1;
|
||||
};
|
||||
}
|
||||
|
||||
private int convert2(String s) {
|
||||
return switch (s) {
|
||||
case "A", "B": break 0;
|
||||
case "C": break 1;
|
||||
default: break -1;
|
||||
case "A", "B": yield 0;
|
||||
case "C": yield 1;
|
||||
default: yield -1;
|
||||
};
|
||||
}
|
||||
|
||||
@ -112,7 +112,7 @@ public class ExpressionSwitch {
|
||||
default: break STOP;
|
||||
}
|
||||
return switch (t) {
|
||||
default: break good;
|
||||
default: yield good;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -58,11 +58,11 @@ public class ExpressionSwitchBreaks1 {
|
||||
case 0:
|
||||
return switch (j) {
|
||||
case 0:
|
||||
if (true) break "0-0";
|
||||
if (true) yield "0-0";
|
||||
case 1:
|
||||
break "0-1";
|
||||
yield "0-1";
|
||||
default:
|
||||
break "0-X";
|
||||
yield "0-X";
|
||||
};
|
||||
default: return "X";
|
||||
}
|
||||
@ -90,9 +90,9 @@ public class ExpressionSwitchBreaks1 {
|
||||
r = "0-X";
|
||||
break;
|
||||
}
|
||||
break r;
|
||||
yield r;
|
||||
case 1:
|
||||
break "1";
|
||||
yield "1";
|
||||
case 2:
|
||||
LOP: while (j-- > 0) {
|
||||
if (k == 5) {
|
||||
@ -102,9 +102,9 @@ public class ExpressionSwitchBreaks1 {
|
||||
break LOP;
|
||||
}
|
||||
Supplier<String> getter = () -> { return "2-X-5"; };
|
||||
break getter.get();
|
||||
yield getter.get();
|
||||
default:
|
||||
break "X";
|
||||
yield "X";
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ public class ExpressionSwitchBreaks2 {
|
||||
case 0:
|
||||
return switch (j) {
|
||||
case 0:
|
||||
break "0-0";
|
||||
yield "0-0";
|
||||
case 1:
|
||||
break ; //error: missing value
|
||||
case 2:
|
||||
@ -20,9 +20,9 @@ public class ExpressionSwitchBreaks2 {
|
||||
case 3: {
|
||||
int x = -1;
|
||||
x: switch (i + j) {
|
||||
case 0: break x; //error: cannot disambiguate, wrong type as well
|
||||
case 0: break x;
|
||||
}
|
||||
break "X";
|
||||
yield "X";
|
||||
}
|
||||
case 4: return "X"; //error: no returns from inside of the switch expression
|
||||
case 5: continue; //error: no continue out of the switch expression
|
||||
@ -31,17 +31,17 @@ public class ExpressionSwitchBreaks2 {
|
||||
default: {
|
||||
String x = "X";
|
||||
x: switch (i + j) {
|
||||
case 0: break ""; //error: cannot break from switch expression that is not immediatelly enclosing
|
||||
case 0: yield ""; //error: cannot yield from switch expression that is not immediatelly enclosing
|
||||
}
|
||||
break "X";
|
||||
yield "X";
|
||||
}
|
||||
};
|
||||
case 1:
|
||||
break "1" + undef; //error: complex value and no switch expression
|
||||
yield "1" + undef; //error: complex value and no switch expression
|
||||
}
|
||||
}
|
||||
j: print(switch (i) {
|
||||
default: break j; //error: "j" is ambiguous (expression/label)
|
||||
default: break j;
|
||||
}, 0);
|
||||
j2: print(switch (i) {
|
||||
default: break j2;
|
||||
|
@ -1,15 +1,12 @@
|
||||
ExpressionSwitchBreaks2.java:17:25: compiler.err.break.missing.value
|
||||
ExpressionSwitchBreaks2.java:19:25: compiler.err.break.outside.switch.expression
|
||||
ExpressionSwitchBreaks2.java:23:37: compiler.err.break.ambiguous.target: x
|
||||
ExpressionSwitchBreaks2.java:27:29: compiler.err.return.outside.switch.expression
|
||||
ExpressionSwitchBreaks2.java:28:29: compiler.err.continue.outside.switch.expression
|
||||
ExpressionSwitchBreaks2.java:29:29: compiler.err.continue.outside.switch.expression
|
||||
ExpressionSwitchBreaks2.java:30:29: compiler.err.undef.label: UNKNOWN
|
||||
ExpressionSwitchBreaks2.java:34:37: compiler.err.break.expr.not.immediate: compiler.misc.tree.tag.switch
|
||||
ExpressionSwitchBreaks2.java:40:17: compiler.err.break.complex.value.no.switch.expression
|
||||
ExpressionSwitchBreaks2.java:40:17: compiler.err.no.switch.expression
|
||||
ExpressionSwitchBreaks2.java:40:29: compiler.err.cant.resolve.location: kindname.variable, undef, , , (compiler.misc.location: kindname.class, ExpressionSwitchBreaks2, null)
|
||||
ExpressionSwitchBreaks2.java:44:22: compiler.err.break.ambiguous.target: j
|
||||
ExpressionSwitchBreaks2.java:44:22: compiler.err.break.outside.switch.expression
|
||||
ExpressionSwitchBreaks2.java:47:22: compiler.err.break.outside.switch.expression
|
||||
- compiler.note.preview.filename: ExpressionSwitchBreaks2.java
|
||||
- compiler.note.preview.recompile
|
||||
12 errors
|
||||
9 errors
|
||||
|
@ -34,47 +34,49 @@ public class ExpressionSwitchBugs {
|
||||
new ExpressionSwitchBugs().testNested();
|
||||
new ExpressionSwitchBugs().testAnonymousClasses();
|
||||
new ExpressionSwitchBugs().testFields();
|
||||
check(3, new C(-1, 3).test(false));
|
||||
check(3, new C(3, -1).test(true));
|
||||
}
|
||||
|
||||
private void testNested() {
|
||||
int i = 0;
|
||||
check(42, id(switch (42) {
|
||||
default: i++; break 42;
|
||||
default: i++; yield 42;
|
||||
}));
|
||||
i = 0;
|
||||
check(43, id(switch (42) {
|
||||
case 42: while (i == 0) {
|
||||
i++;
|
||||
}
|
||||
break 42 + i;
|
||||
default: i++; break 42;
|
||||
yield 42 + i;
|
||||
default: i++; yield 42;
|
||||
}));
|
||||
i = 0;
|
||||
check(42, id(switch (42) {
|
||||
case 42: if (i == 0) {
|
||||
break 42;
|
||||
yield 42;
|
||||
}
|
||||
default: i++; break 43;
|
||||
default: i++; yield 43;
|
||||
}));
|
||||
i = 0;
|
||||
check(42, id(switch (42) {
|
||||
case 42: if (i == 0) {
|
||||
break 41 + switch (0) {
|
||||
yield 41 + switch (0) {
|
||||
case 0 -> 1;
|
||||
default -> -1;
|
||||
};
|
||||
}
|
||||
default: i++; break 43;
|
||||
default: i++; yield 43;
|
||||
}));
|
||||
}
|
||||
|
||||
private void testAnonymousClasses() {
|
||||
for (int i : new int[] {1, 2}) {
|
||||
check(3, id((switch (i) {
|
||||
case 1: break new I() {
|
||||
case 1: yield new I() {
|
||||
public int g() { return 3; }
|
||||
};
|
||||
default: break (I) () -> { return 3; };
|
||||
default: yield (I) () -> { return 3; };
|
||||
}).g()));
|
||||
check(3, id((switch (i) {
|
||||
case 1 -> new I() {
|
||||
@ -96,7 +98,7 @@ public class ExpressionSwitchBugs {
|
||||
case 2 -> {
|
||||
int temp = 0;
|
||||
temp += 3;
|
||||
break temp;
|
||||
yield temp;
|
||||
}
|
||||
default -> throw new IllegalStateException();
|
||||
});
|
||||
@ -107,7 +109,7 @@ public class ExpressionSwitchBugs {
|
||||
case 2 -> {
|
||||
int temp = 0;
|
||||
temp += 3;
|
||||
break temp;
|
||||
yield temp;
|
||||
}
|
||||
default -> throw new IllegalStateException();
|
||||
});
|
||||
@ -120,7 +122,7 @@ public class ExpressionSwitchBugs {
|
||||
return -1;
|
||||
}
|
||||
|
||||
private void check(int actual, int expected) {
|
||||
private static void check(int actual, int expected) {
|
||||
if (actual != expected) {
|
||||
throw new AssertionError("Unexpected result: " + actual);
|
||||
}
|
||||
@ -129,4 +131,32 @@ public class ExpressionSwitchBugs {
|
||||
public interface I {
|
||||
public int g();
|
||||
}
|
||||
|
||||
static class Super {
|
||||
public final int i;
|
||||
|
||||
public Super(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
}
|
||||
static class C extends Super {
|
||||
public final int i;
|
||||
|
||||
public C(int superI, int i) {
|
||||
super(superI);
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
public int test(boolean fromSuper) {
|
||||
return switch (fromSuper ? 0 : 1) {
|
||||
case 0 -> {
|
||||
yield super.i;
|
||||
}
|
||||
default -> {
|
||||
yield this.i;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ public class ExpressionSwitchDA {
|
||||
int i;
|
||||
int j = 0;
|
||||
int k = switch (j) {
|
||||
case 0 -> { i=42; break 42; }
|
||||
case 0 -> { i=42; yield 42; }
|
||||
default -> i=42;
|
||||
};
|
||||
System.out.println(i);
|
||||
@ -80,7 +80,7 @@ public class ExpressionSwitchDA {
|
||||
int j = 0;
|
||||
int k = switch (j) {
|
||||
case 0 -> i=42;
|
||||
default -> { i=42; break 42; }
|
||||
default -> { i=42; yield 42; }
|
||||
};
|
||||
System.out.println(i);
|
||||
}
|
||||
@ -88,8 +88,8 @@ public class ExpressionSwitchDA {
|
||||
int i;
|
||||
int j = 0;
|
||||
int k = switch (j) {
|
||||
case 0 -> { i=42; break 42; }
|
||||
default -> { i=42; break 42; }
|
||||
case 0 -> { i=42; yield 42; }
|
||||
default -> { i=42; yield 42; }
|
||||
};
|
||||
System.out.println(i);
|
||||
}
|
||||
|
@ -39,19 +39,19 @@ public class ExpressionSwitchEmbedding {
|
||||
int i = 6;
|
||||
int o = 0;
|
||||
while (switch (i) {
|
||||
case 1: i = 0; break true;
|
||||
case 2: i = 1; break true;
|
||||
case 1: i = 0; yield true;
|
||||
case 2: i = 1; yield true;
|
||||
case 3, 4: i--;
|
||||
if (i == 2 || i == 4) {
|
||||
break switch (i) {
|
||||
yield switch (i) {
|
||||
case 2 -> true;
|
||||
case 4 -> false;
|
||||
default -> throw new IllegalStateException();
|
||||
};
|
||||
} else {
|
||||
break true;
|
||||
yield true;
|
||||
}
|
||||
default: i--; break switch (i) {
|
||||
default: i--; yield switch (i) {
|
||||
case -1 -> false;
|
||||
case 3 -> true;
|
||||
default -> true;
|
||||
@ -67,8 +67,8 @@ public class ExpressionSwitchEmbedding {
|
||||
int i = 6;
|
||||
int o = 0;
|
||||
while (switch (i) {
|
||||
case 1: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 0; break true; }
|
||||
case 2: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 1; break true; }
|
||||
case 1: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 0; yield true; }
|
||||
case 2: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 1; yield true; }
|
||||
case 3, 4:
|
||||
try {
|
||||
new ExpressionSwitchEmbedding().throwException();
|
||||
@ -76,16 +76,16 @@ public class ExpressionSwitchEmbedding {
|
||||
i--;
|
||||
if (i == 2 || i == 4) {
|
||||
try {
|
||||
break switch (i) {
|
||||
yield switch (i) {
|
||||
case 2 -> throw new ResultException(true);
|
||||
case 4 -> false;
|
||||
default -> throw new IllegalStateException();
|
||||
};
|
||||
} catch (ResultException ex) {
|
||||
break ex.result;
|
||||
yield ex.result;
|
||||
}
|
||||
} else {
|
||||
break true;
|
||||
yield true;
|
||||
}
|
||||
}
|
||||
default:
|
||||
@ -93,7 +93,7 @@ public class ExpressionSwitchEmbedding {
|
||||
new ExpressionSwitchEmbedding().throwException();
|
||||
} catch (Throwable t) {
|
||||
i--;
|
||||
break switch (i) {
|
||||
yield switch (i) {
|
||||
case -1 -> false;
|
||||
case 3 -> true;
|
||||
default -> true;
|
||||
@ -111,19 +111,19 @@ public class ExpressionSwitchEmbedding {
|
||||
int i = 6;
|
||||
int o = 0;
|
||||
if (switch (i) {
|
||||
case 1: i = 0; break true;
|
||||
case 2: i = 1; break true;
|
||||
case 1: i = 0; yield true;
|
||||
case 2: i = 1; yield true;
|
||||
case 3, 4: i--;
|
||||
if (i == 2 || i == 4) {
|
||||
break (switch (i) {
|
||||
yield (switch (i) {
|
||||
case 2 -> 3;
|
||||
case 4 -> 5;
|
||||
default -> throw new IllegalStateException();
|
||||
}) == i + 1;
|
||||
} else {
|
||||
break true;
|
||||
yield true;
|
||||
}
|
||||
default: i--; break switch (i) {
|
||||
default: i--; yield switch (i) {
|
||||
case -1 -> false;
|
||||
case 3 -> true;
|
||||
default -> true;
|
||||
@ -139,8 +139,8 @@ public class ExpressionSwitchEmbedding {
|
||||
int i = 6;
|
||||
int o = 0;
|
||||
if (switch (i) {
|
||||
case 1: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 0; break true; }
|
||||
case 2: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 1; break true; }
|
||||
case 1: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 0; yield true; }
|
||||
case 2: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 1; yield true; }
|
||||
case 3, 4:
|
||||
try {
|
||||
new ExpressionSwitchEmbedding().throwException();
|
||||
@ -148,16 +148,16 @@ public class ExpressionSwitchEmbedding {
|
||||
i--;
|
||||
if (i == 2 || i == 4) {
|
||||
try {
|
||||
break switch (i) {
|
||||
yield switch (i) {
|
||||
case 2 -> throw new ResultException(true);
|
||||
case 4 -> false;
|
||||
default -> throw new IllegalStateException();
|
||||
};
|
||||
} catch (ResultException ex) {
|
||||
break ex.result;
|
||||
yield ex.result;
|
||||
}
|
||||
} else {
|
||||
break true;
|
||||
yield true;
|
||||
}
|
||||
}
|
||||
default:
|
||||
@ -165,7 +165,7 @@ public class ExpressionSwitchEmbedding {
|
||||
new ExpressionSwitchEmbedding().throwException();
|
||||
} catch (Throwable t) {
|
||||
i--;
|
||||
break switch (i) {
|
||||
yield switch (i) {
|
||||
case -1 -> false;
|
||||
case 3 -> true;
|
||||
default -> true;
|
||||
@ -182,19 +182,19 @@ public class ExpressionSwitchEmbedding {
|
||||
{
|
||||
int o = 0;
|
||||
for (int i = 6; (switch (i) {
|
||||
case 1: i = 0; break true;
|
||||
case 2: i = 1; break true;
|
||||
case 1: i = 0; yield true;
|
||||
case 2: i = 1; yield true;
|
||||
case 3, 4: i--;
|
||||
if (i == 2 || i == 4) {
|
||||
break switch (i) {
|
||||
yield switch (i) {
|
||||
case 2 -> true;
|
||||
case 4 -> false;
|
||||
default -> throw new IllegalStateException();
|
||||
};
|
||||
} else {
|
||||
break true;
|
||||
yield true;
|
||||
}
|
||||
default: i--; break switch (i) {
|
||||
default: i--; yield switch (i) {
|
||||
case -1 -> false;
|
||||
case 3 -> true;
|
||||
default -> true;
|
||||
@ -209,8 +209,8 @@ public class ExpressionSwitchEmbedding {
|
||||
{
|
||||
int o = 0;
|
||||
for (int i = 6; (switch (i) {
|
||||
case 1: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 0; break true; }
|
||||
case 2: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 1; break true; }
|
||||
case 1: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 0; yield true; }
|
||||
case 2: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 1; yield true; }
|
||||
case 3, 4:
|
||||
try {
|
||||
new ExpressionSwitchEmbedding().throwException();
|
||||
@ -218,16 +218,16 @@ public class ExpressionSwitchEmbedding {
|
||||
i--;
|
||||
if (i == 2 || i == 4) {
|
||||
try {
|
||||
break switch (i) {
|
||||
yield switch (i) {
|
||||
case 2 -> throw new ResultException(true);
|
||||
case 4 -> false;
|
||||
default -> throw new IllegalStateException();
|
||||
};
|
||||
} catch (ResultException ex) {
|
||||
break ex.result;
|
||||
yield ex.result;
|
||||
}
|
||||
} else {
|
||||
break true;
|
||||
yield true;
|
||||
}
|
||||
}
|
||||
default:
|
||||
@ -235,7 +235,7 @@ public class ExpressionSwitchEmbedding {
|
||||
new ExpressionSwitchEmbedding().throwException();
|
||||
} catch (Throwable t) {
|
||||
i--;
|
||||
break switch (i) {
|
||||
yield switch (i) {
|
||||
case -1 -> false;
|
||||
case 3 -> true;
|
||||
default -> true;
|
||||
@ -255,19 +255,19 @@ public class ExpressionSwitchEmbedding {
|
||||
do {
|
||||
o++;
|
||||
} while (switch (i) {
|
||||
case 1: i = 0; break true;
|
||||
case 2: i = 1; break true;
|
||||
case 1: i = 0; yield true;
|
||||
case 2: i = 1; yield true;
|
||||
case 3, 4: i--;
|
||||
if (i == 2 || i == 4) {
|
||||
break switch (i) {
|
||||
yield switch (i) {
|
||||
case 2 -> true;
|
||||
case 4 -> false;
|
||||
default -> throw new IllegalStateException();
|
||||
};
|
||||
} else {
|
||||
break true;
|
||||
yield true;
|
||||
}
|
||||
default: i--; break switch (i) {
|
||||
default: i--; yield switch (i) {
|
||||
case -1 -> false;
|
||||
case 3 -> true;
|
||||
default -> true;
|
||||
@ -283,8 +283,8 @@ public class ExpressionSwitchEmbedding {
|
||||
do {
|
||||
o++;
|
||||
} while (switch (i) {
|
||||
case 1: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 0; break true; }
|
||||
case 2: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 1; break true; }
|
||||
case 1: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 0; yield true; }
|
||||
case 2: try { new ExpressionSwitchEmbedding().throwException(); } catch (Throwable t) { i = 1; yield true; }
|
||||
case 3, 4:
|
||||
try {
|
||||
new ExpressionSwitchEmbedding().throwException();
|
||||
@ -292,16 +292,16 @@ public class ExpressionSwitchEmbedding {
|
||||
i--;
|
||||
if (i == 2 || i == 4) {
|
||||
try {
|
||||
break switch (i) {
|
||||
yield switch (i) {
|
||||
case 2 -> throw new ResultException(true);
|
||||
case 4 -> false;
|
||||
default -> throw new IllegalStateException();
|
||||
};
|
||||
} catch (ResultException ex) {
|
||||
break ex.result;
|
||||
yield ex.result;
|
||||
}
|
||||
} else {
|
||||
break true;
|
||||
yield true;
|
||||
}
|
||||
}
|
||||
default:
|
||||
@ -309,7 +309,7 @@ public class ExpressionSwitchEmbedding {
|
||||
new ExpressionSwitchEmbedding().throwException();
|
||||
} catch (Throwable t) {
|
||||
i--;
|
||||
break switch (i) {
|
||||
yield switch (i) {
|
||||
case -1 -> false;
|
||||
case 3 -> true;
|
||||
default -> true;
|
||||
|
@ -53,7 +53,7 @@ public class ExpressionSwitchFallThrough {
|
||||
return switch (t) {
|
||||
case A: help = "a";
|
||||
case B: help += "b";
|
||||
default: break help;
|
||||
default: yield help;
|
||||
};
|
||||
}
|
||||
|
||||
@ -62,7 +62,7 @@ public class ExpressionSwitchFallThrough {
|
||||
return switch (t) {
|
||||
case A: help = "a";
|
||||
case B: help += "b";
|
||||
default: break help;
|
||||
default: yield help;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -50,8 +50,8 @@ public class ExpressionSwitchFallThrough1 {
|
||||
return switch (p) {
|
||||
case 0: result += "0";
|
||||
case 1: result += "1";
|
||||
break result;
|
||||
default: break "other";
|
||||
yield result;
|
||||
default: yield "other";
|
||||
};
|
||||
}
|
||||
|
||||
@ -60,7 +60,7 @@ public class ExpressionSwitchFallThrough1 {
|
||||
switch (p) {
|
||||
case 0: result += "0";
|
||||
case 1: result += "1";
|
||||
break ;
|
||||
break;
|
||||
default: result = "other";
|
||||
break;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ public class ExpressionSwitchFlow {
|
||||
private String test1(int i) {
|
||||
return switch (i) {
|
||||
case 0 -> {}
|
||||
default -> { break "other"; }
|
||||
default -> { yield "other"; }
|
||||
};
|
||||
}
|
||||
private String test2(int i) {
|
||||
@ -27,7 +27,7 @@ public class ExpressionSwitchFlow {
|
||||
}
|
||||
private String test4(int i) {
|
||||
return switch (i) {
|
||||
case 0 -> { break "other"; }
|
||||
case 0 -> { yield "other"; }
|
||||
default -> {}
|
||||
};
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -43,11 +43,11 @@ public class ExpressionSwitchInExpressionSwitch {
|
||||
default -> {
|
||||
int k = switch (j) {
|
||||
default -> {
|
||||
break 42;
|
||||
yield 42;
|
||||
}
|
||||
};
|
||||
System.out.println("didn't break to the top level");
|
||||
break 43;
|
||||
System.out.println("didn't yield to the top level");
|
||||
yield 43;
|
||||
}
|
||||
};
|
||||
if (i!=43) {
|
||||
|
@ -27,7 +27,7 @@ public class ExpressionSwitchInfer {
|
||||
|
||||
String str = switch (param) {
|
||||
case "" -> {
|
||||
break 0;
|
||||
yield 0;
|
||||
} default ->"default";
|
||||
};
|
||||
|
||||
|
@ -26,9 +26,9 @@ public class ExpressionSwitchNotExhaustive {
|
||||
s = "42";
|
||||
break;
|
||||
}
|
||||
break s;
|
||||
yield s;
|
||||
default:
|
||||
break "43";
|
||||
yield "43";
|
||||
};
|
||||
}
|
||||
enum E {
|
||||
|
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8223305
|
||||
* @summary Verify Tree.toString() related to switch expressions
|
||||
* @modules jdk.compiler
|
||||
*/
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.tools.*;
|
||||
|
||||
import com.sun.source.util.JavacTask;
|
||||
|
||||
public class ExpressionSwitchToString {
|
||||
|
||||
private static final String CODE =
|
||||
"public class C {" +
|
||||
" void t1(Integer i) {" +
|
||||
" switch (i) {" +
|
||||
" case null: i++; break;" +
|
||||
" case 0, 1: i++; break;" +
|
||||
" default: i++; break;" +
|
||||
" }" +
|
||||
" }" +
|
||||
" int t2(Integer i) {" +
|
||||
" return switch (i) {" +
|
||||
" case null: yield 0;" +
|
||||
" case 0, 1: yield 1;" +
|
||||
" default: yield 2;" +
|
||||
" }" +
|
||||
" }" +
|
||||
"}";
|
||||
|
||||
private static final String EXPECTED =
|
||||
"\n" +
|
||||
"public class C {\n" +
|
||||
" \n" +
|
||||
" void t1(Integer i) {\n" +
|
||||
" switch (i) {\n" +
|
||||
" case null:\n" +
|
||||
" i++;\n" +
|
||||
" break;\n" +
|
||||
" \n" +
|
||||
" case 0, 1:\n" +
|
||||
" i++;\n" +
|
||||
" break;\n" +
|
||||
" \n" +
|
||||
" default:\n" +
|
||||
" i++;\n" +
|
||||
" break;\n" +
|
||||
" \n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" \n" +
|
||||
" int t2(Integer i) {\n" +
|
||||
" return switch (i) {\n" +
|
||||
" case null:\n" +
|
||||
" yield 0;\n" +
|
||||
" \n" +
|
||||
" case 0, 1:\n" +
|
||||
" yield 1;\n" +
|
||||
" \n" +
|
||||
" default:\n" +
|
||||
" yield 2;\n" +
|
||||
" \n" +
|
||||
" };\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
|
||||
assert tool != null;
|
||||
DiagnosticListener<JavaFileObject> noErrors = d -> {};
|
||||
String sourceVersion = Integer.toString(Runtime.version().feature());
|
||||
|
||||
JavacTask ct = (JavacTask) tool.getTask(null, null, noErrors,
|
||||
List.of("-XDdev", "--enable-preview", "-source", sourceVersion), null,
|
||||
Arrays.asList(new MyFileObject(CODE)));
|
||||
String actualCode = ct.parse().iterator().next().toString();
|
||||
actualCode = actualCode.replace(System.getProperty("line.separator"), "\n");
|
||||
if (!EXPECTED.equals(actualCode)) {
|
||||
throw new AssertionError("Unexpected toString outcome: " +
|
||||
actualCode);
|
||||
}
|
||||
}
|
||||
|
||||
static class MyFileObject extends SimpleJavaFileObject {
|
||||
private String text;
|
||||
|
||||
public MyFileObject(String text) {
|
||||
super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
}
|
@ -11,44 +11,44 @@ public class ExpressionSwitchUnreachable {
|
||||
int z = 42;
|
||||
int i = switch (z) {
|
||||
case 0 -> {
|
||||
break 42;
|
||||
yield 42;
|
||||
System.out.println("Unreachable"); //Unreachable
|
||||
}
|
||||
default -> 0;
|
||||
};
|
||||
i = switch (z) {
|
||||
case 0 -> {
|
||||
break 42;
|
||||
break 42; //Unreachable
|
||||
yield 42;
|
||||
yield 42; //Unreachable
|
||||
}
|
||||
default -> 0;
|
||||
};
|
||||
i = switch (z) {
|
||||
case 0:
|
||||
System.out.println("0");
|
||||
break 42;
|
||||
yield 42;
|
||||
System.out.println("1"); //Unreachable
|
||||
default : break 42;
|
||||
default : yield 42;
|
||||
};
|
||||
i = switch (z) {
|
||||
case 0 -> 42;
|
||||
default -> {
|
||||
break 42;
|
||||
yield 42;
|
||||
System.out.println("Unreachable"); //Unreachable
|
||||
}
|
||||
};
|
||||
i = switch (z) {
|
||||
case 0: break 42;
|
||||
case 0: yield 42;
|
||||
default:
|
||||
System.out.println("0");
|
||||
break 42;
|
||||
yield 42;
|
||||
System.out.println("1"); //Unreachable
|
||||
};
|
||||
i = switch (z) {
|
||||
case 0:
|
||||
default:
|
||||
System.out.println("0");
|
||||
break 42;
|
||||
yield 42;
|
||||
System.out.println("1"); //Unreachable
|
||||
};
|
||||
}
|
||||
|
@ -50,9 +50,9 @@ public class ParseIncomplete {
|
||||
" }" +
|
||||
" int t2(Integer i) {" +
|
||||
" return switch (i) {" +
|
||||
" case null: break 0;" +
|
||||
" case 0, 1: break 1;" +
|
||||
" default: break 2;" +
|
||||
" case null: yield 0;" +
|
||||
" case 0, 1: yield 1;" +
|
||||
" default: yield 2;" +
|
||||
" }" +
|
||||
" }" +
|
||||
"}";
|
||||
|
@ -38,7 +38,7 @@ public class SwitchExpressionIsNotAConstant {
|
||||
int dummy = 1 + switch (i) {
|
||||
default -> {
|
||||
i++;
|
||||
break 1;
|
||||
yield 1;
|
||||
}
|
||||
};
|
||||
if (i != 1) {
|
||||
@ -51,7 +51,7 @@ public class SwitchExpressionIsNotAConstant {
|
||||
case -1 -> 1;
|
||||
default -> {
|
||||
i++;
|
||||
break 1;
|
||||
yield 1;
|
||||
}
|
||||
};
|
||||
if (i != 1) {
|
||||
@ -63,7 +63,7 @@ public class SwitchExpressionIsNotAConstant {
|
||||
int dummy = 1 + switch (i) {
|
||||
default :
|
||||
i++;
|
||||
break 1;
|
||||
yield 1;
|
||||
};
|
||||
if (i != 1) {
|
||||
throw new IllegalStateException("Side effects missing.");
|
||||
@ -72,10 +72,10 @@ public class SwitchExpressionIsNotAConstant {
|
||||
{
|
||||
i = 0;
|
||||
int dummy = 1 + switch (i) {
|
||||
case -1: break 1;
|
||||
case -1: yield 1;
|
||||
default:
|
||||
i++;
|
||||
break 1;
|
||||
yield 1;
|
||||
};
|
||||
if (i != 1) {
|
||||
throw new IllegalStateException("Side effects missing.");
|
||||
|
@ -9,9 +9,9 @@ public class SwitchExpressionScopesIsolated {
|
||||
|
||||
private String scopesIsolated(int i) {
|
||||
return switch (i) {
|
||||
case 0 -> { String res = ""; break res; }
|
||||
case 1 -> { res = ""; break res; }
|
||||
default -> { res = ""; break res; }
|
||||
case 0 -> { String res = ""; yield res; }
|
||||
case 1 -> { res = ""; yield res; }
|
||||
default -> { res = ""; yield res; }
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,7 @@ import javax.tools.*;
|
||||
|
||||
import com.sun.source.tree.CompilationUnitTree;
|
||||
import com.sun.source.tree.SwitchExpressionTree;
|
||||
import com.sun.source.tree.YieldTree;
|
||||
import com.sun.source.tree.Tree;
|
||||
import com.sun.source.util.JavacTask;
|
||||
import com.sun.source.util.SimpleTreeVisitor;
|
||||
@ -53,12 +54,13 @@ public class SwitchExpressionSimpleVisitorTest {
|
||||
String code = "class Test {\n" +
|
||||
" int t(int i) {\n" +
|
||||
" return switch(i) {\n" +
|
||||
" default: break -1;\n" +
|
||||
" default: yield -1;\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
"}\n";
|
||||
int[] callCount = new int[1];
|
||||
int[] switchExprNodeCount = new int[1];
|
||||
int[] yieldNodeCount = new int[1];
|
||||
new TreePathScanner<Void, Void>() {
|
||||
@Override
|
||||
public Void visitSwitchExpression(SwitchExpressionTree node, Void p) {
|
||||
@ -74,11 +76,27 @@ public class SwitchExpressionSimpleVisitorTest {
|
||||
}, null);
|
||||
return super.visitSwitchExpression(node, p);
|
||||
}
|
||||
@Override
|
||||
public Void visitYield(YieldTree node, Void p) {
|
||||
node.accept(new SimpleTreeVisitor<Void, Void>() {
|
||||
@Override
|
||||
protected Void defaultAction(Tree defaultActionNode, Void p) {
|
||||
callCount[0]++;
|
||||
if (node == defaultActionNode) {
|
||||
yieldNodeCount[0]++;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}, null);
|
||||
return super.visitYield(node, p);
|
||||
}
|
||||
}.scan(parse(code), null);
|
||||
|
||||
if (callCount[0] != 1 || switchExprNodeCount[0] != 1) {
|
||||
if (callCount[0] != 2 || switchExprNodeCount[0] != 1 ||
|
||||
yieldNodeCount[0] != 1) {
|
||||
throw new AssertionError("Unexpected counts; callCount=" + callCount[0] +
|
||||
", switchExprNodeCount=" + switchExprNodeCount[0]);
|
||||
", switchExprNodeCount=" + switchExprNodeCount[0] +
|
||||
", yieldNodeCount=" + yieldNodeCount[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,34 +38,34 @@ public class TryCatch {
|
||||
case 1:
|
||||
try {
|
||||
new TryCatch().throwException();
|
||||
break -1;
|
||||
yield -1;
|
||||
} catch(Throwable ex) {
|
||||
break val;
|
||||
yield val;
|
||||
}
|
||||
default: break -1;
|
||||
default: yield -1;
|
||||
};
|
||||
case 1 -> {
|
||||
try {
|
||||
break new TryCatch().id(switch (p + 1) {
|
||||
yield new TryCatch().id(switch (p + 1) {
|
||||
case 2:
|
||||
try {
|
||||
new TryCatch().throwException();
|
||||
break -1;
|
||||
yield -1;
|
||||
} catch(Throwable ex) {
|
||||
throw ex;
|
||||
}
|
||||
default: break -1;
|
||||
default: yield -1;
|
||||
});
|
||||
} catch(Throwable ex) {
|
||||
break val;
|
||||
yield val;
|
||||
}
|
||||
}
|
||||
default -> {
|
||||
try {
|
||||
new TryCatch().throwException();
|
||||
break -1;
|
||||
yield -1;
|
||||
} catch(Throwable ex) {
|
||||
break val;
|
||||
yield val;
|
||||
}
|
||||
}
|
||||
} - 1);
|
||||
@ -83,34 +83,34 @@ public class TryCatch {
|
||||
case 1:
|
||||
try {
|
||||
new TryCatch().throwException();
|
||||
break false;
|
||||
yield false;
|
||||
} catch(Throwable ex) {
|
||||
break true;
|
||||
yield true;
|
||||
}
|
||||
default: break false;
|
||||
default: yield false;
|
||||
};
|
||||
case 1 -> {
|
||||
try {
|
||||
break new TryCatch().id(switch (p + 1) {
|
||||
yield new TryCatch().id(switch (p + 1) {
|
||||
case 2:
|
||||
try {
|
||||
new TryCatch().throwException();
|
||||
break false;
|
||||
yield false;
|
||||
} catch(Throwable ex) {
|
||||
throw ex;
|
||||
}
|
||||
default: break false;
|
||||
default: yield false;
|
||||
});
|
||||
} catch(Throwable ex) {
|
||||
break true;
|
||||
yield true;
|
||||
}
|
||||
}
|
||||
default -> {
|
||||
try {
|
||||
new TryCatch().throwException();
|
||||
break false;
|
||||
yield false;
|
||||
} catch(Throwable ex) {
|
||||
break true;
|
||||
yield true;
|
||||
}
|
||||
}
|
||||
} && (x = 1) == 1 && x == 1 ? val : -1);
|
||||
@ -127,34 +127,34 @@ public class TryCatch {
|
||||
case B:
|
||||
try {
|
||||
new TryCatch().throwException();
|
||||
break -1;
|
||||
yield -1;
|
||||
} catch(Throwable ex) {
|
||||
break val;
|
||||
yield val;
|
||||
}
|
||||
default: break -1;
|
||||
default: yield -1;
|
||||
};
|
||||
case B -> {
|
||||
try {
|
||||
break new TryCatch().id(switch (e.next()) {
|
||||
yield new TryCatch().id(switch (e.next()) {
|
||||
case C:
|
||||
try {
|
||||
new TryCatch().throwException();
|
||||
break -1;
|
||||
yield -1;
|
||||
} catch(Throwable ex) {
|
||||
throw ex;
|
||||
}
|
||||
default: break -1;
|
||||
default: yield -1;
|
||||
});
|
||||
} catch(Throwable ex) {
|
||||
break val;
|
||||
yield val;
|
||||
}
|
||||
}
|
||||
default -> {
|
||||
try {
|
||||
new TryCatch().throwException();
|
||||
break -1;
|
||||
yield -1;
|
||||
} catch(Throwable ex) {
|
||||
break val;
|
||||
yield val;
|
||||
}
|
||||
}
|
||||
} - 1);
|
||||
@ -172,34 +172,34 @@ public class TryCatch {
|
||||
case B:
|
||||
try {
|
||||
new TryCatch().throwException();
|
||||
break false;
|
||||
yield false;
|
||||
} catch(Throwable ex) {
|
||||
break true;
|
||||
yield true;
|
||||
}
|
||||
default: break false;
|
||||
default: yield false;
|
||||
};
|
||||
case B -> {
|
||||
try {
|
||||
break new TryCatch().id(switch (e.next()) {
|
||||
yield new TryCatch().id(switch (e.next()) {
|
||||
case C:
|
||||
try {
|
||||
new TryCatch().throwException();
|
||||
break false;
|
||||
yield false;
|
||||
} catch(Throwable ex) {
|
||||
throw ex;
|
||||
}
|
||||
default: break false;
|
||||
default: yield false;
|
||||
});
|
||||
} catch(Throwable ex) {
|
||||
break true;
|
||||
yield true;
|
||||
}
|
||||
}
|
||||
default -> {
|
||||
try {
|
||||
new TryCatch().throwException();
|
||||
break false;
|
||||
yield false;
|
||||
} catch(Throwable ex) {
|
||||
break true;
|
||||
yield true;
|
||||
}
|
||||
}
|
||||
} && (x = 1) == 1 && x == 1 ? val : -1);
|
||||
@ -216,34 +216,34 @@ public class TryCatch {
|
||||
case "c":
|
||||
try {
|
||||
new TryCatch().throwException();
|
||||
break -1;
|
||||
yield -1;
|
||||
} catch(Throwable ex) {
|
||||
break val;
|
||||
yield val;
|
||||
}
|
||||
default: break -1;
|
||||
default: yield -1;
|
||||
};
|
||||
case "a" -> {
|
||||
try {
|
||||
break new TryCatch().id(switch (s + "c") {
|
||||
yield new TryCatch().id(switch (s + "c") {
|
||||
case "ac":
|
||||
try {
|
||||
new TryCatch().throwException();
|
||||
break -1;
|
||||
yield -1;
|
||||
} catch(Throwable ex) {
|
||||
throw ex;
|
||||
}
|
||||
default: break -1;
|
||||
default: yield -1;
|
||||
});
|
||||
} catch(Throwable ex) {
|
||||
break val;
|
||||
yield val;
|
||||
}
|
||||
}
|
||||
default -> {
|
||||
try {
|
||||
new TryCatch().throwException();
|
||||
break -1;
|
||||
yield -1;
|
||||
} catch(Throwable ex) {
|
||||
break val;
|
||||
yield val;
|
||||
}
|
||||
}
|
||||
} - 1);
|
||||
@ -261,34 +261,34 @@ public class TryCatch {
|
||||
case "c":
|
||||
try {
|
||||
new TryCatch().throwException();
|
||||
break false;
|
||||
yield false;
|
||||
} catch(Throwable ex) {
|
||||
break true;
|
||||
yield true;
|
||||
}
|
||||
default: break false;
|
||||
default: yield false;
|
||||
};
|
||||
case "a" -> {
|
||||
try {
|
||||
break new TryCatch().id(switch (s + "c") {
|
||||
yield new TryCatch().id(switch (s + "c") {
|
||||
case "ac":
|
||||
try {
|
||||
new TryCatch().throwException();
|
||||
break false;
|
||||
yield false;
|
||||
} catch(Throwable ex) {
|
||||
throw ex;
|
||||
}
|
||||
default: break false;
|
||||
default: yield false;
|
||||
});
|
||||
} catch(Throwable ex) {
|
||||
break true;
|
||||
yield true;
|
||||
}
|
||||
}
|
||||
default -> {
|
||||
try {
|
||||
new TryCatch().throwException();
|
||||
break false;
|
||||
yield false;
|
||||
} catch(Throwable ex) {
|
||||
break true;
|
||||
yield true;
|
||||
}
|
||||
}
|
||||
} && (x = 1) == 1 && x == 1 ? val : -1);
|
||||
@ -330,75 +330,75 @@ public class TryCatch {
|
||||
|
||||
static class FieldHolder {
|
||||
private final int intTest = switch (0) {
|
||||
case -1: break -1;
|
||||
case -1: yield -1;
|
||||
default:
|
||||
try {
|
||||
break new TryCatch().id(switch (2) {
|
||||
yield new TryCatch().id(switch (2) {
|
||||
case 2:
|
||||
try {
|
||||
new TryCatch().throwException();
|
||||
break -1;
|
||||
yield -1;
|
||||
} catch(Throwable ex) {
|
||||
throw ex;
|
||||
}
|
||||
default: break -1;
|
||||
default: yield -1;
|
||||
});
|
||||
} catch(Throwable ex) {
|
||||
break 3;
|
||||
yield 3;
|
||||
}
|
||||
};
|
||||
private static final int intStaticTest = switch (0) {
|
||||
case -1: break -1;
|
||||
case -1: yield -1;
|
||||
default:
|
||||
try {
|
||||
break new TryCatch().id(switch (2) {
|
||||
yield new TryCatch().id(switch (2) {
|
||||
case 2:
|
||||
try {
|
||||
new TryCatch().throwException();
|
||||
break -1;
|
||||
yield -1;
|
||||
} catch(Throwable ex) {
|
||||
throw ex;
|
||||
}
|
||||
default: break -1;
|
||||
default: yield -1;
|
||||
});
|
||||
} catch(Throwable ex) {
|
||||
break 3;
|
||||
yield 3;
|
||||
}
|
||||
};
|
||||
private final boolean booleanTest = switch (0) {
|
||||
case -1: break false;
|
||||
case -1: yield false;
|
||||
default:
|
||||
try {
|
||||
break new TryCatch().id(switch (2) {
|
||||
yield new TryCatch().id(switch (2) {
|
||||
case 2:
|
||||
try {
|
||||
new TryCatch().throwException();
|
||||
break false;
|
||||
yield false;
|
||||
} catch(Throwable ex) {
|
||||
throw ex;
|
||||
}
|
||||
default: break false;
|
||||
default: yield false;
|
||||
});
|
||||
} catch(Throwable ex) {
|
||||
break true;
|
||||
yield true;
|
||||
}
|
||||
};
|
||||
private static final boolean booleanStaticTest = switch (0) {
|
||||
case -1: break false;
|
||||
case -1: yield false;
|
||||
default:
|
||||
try {
|
||||
break new TryCatch().id(switch (2) {
|
||||
yield new TryCatch().id(switch (2) {
|
||||
case 2:
|
||||
try {
|
||||
new TryCatch().throwException();
|
||||
break false;
|
||||
yield false;
|
||||
} catch(Throwable ex) {
|
||||
throw ex;
|
||||
}
|
||||
default: break false;
|
||||
default: yield false;
|
||||
});
|
||||
} catch(Throwable ex) {
|
||||
break true;
|
||||
yield true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
162
test/langtools/tools/javac/switchexpr/WarnWrongYieldTest.java
Normal file
162
test/langtools/tools/javac/switchexpr/WarnWrongYieldTest.java
Normal file
@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8223305
|
||||
* @summary Verify correct warnings w.r.t. yield
|
||||
* @compile/ref=WarnWrongYieldTest.out -source 13 -XDrawDiagnostics -XDshould-stop.at=ATTR WarnWrongYieldTest.java
|
||||
*/
|
||||
|
||||
package t;
|
||||
|
||||
//ERROR - type called yield:
|
||||
import t.WarnWrongYieldTest.yield;
|
||||
|
||||
public class WarnWrongYieldTest {
|
||||
|
||||
// ERROR - class called yield
|
||||
class yield { }
|
||||
|
||||
// OK to have fields called yield
|
||||
String[] yield = null;
|
||||
|
||||
// ERROR - field of type yield
|
||||
yield y;
|
||||
|
||||
// OK to have methods called yield
|
||||
// Nullary yield method
|
||||
String[] yield() {
|
||||
return null;
|
||||
}
|
||||
// Unary yield method
|
||||
String[] yield(int i) {
|
||||
return null;
|
||||
}
|
||||
// Binary yield method
|
||||
String[] yield(int i, int j) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// OK to declare a local called yield
|
||||
void LocalDeclaration1() {
|
||||
int yield;
|
||||
}
|
||||
// OK to declare and initialise a local called yield
|
||||
void LocalDeclaration2() {
|
||||
int yield = 42;
|
||||
}
|
||||
|
||||
void YieldTypedLocals(int i) {
|
||||
// ERROR - Parsed as yield statement, and y1 is unknown
|
||||
yield y1 = null;
|
||||
|
||||
// ERROR - Parsed as yield statement, and y2 is unknown
|
||||
yield y2 = new yield();
|
||||
|
||||
// ERROR - can not create an yield-valued local of type Object
|
||||
Object y3 = new yield();
|
||||
|
||||
// ERROR - can not create a final yield-valued local of type yield
|
||||
final yield y4 = new yield();
|
||||
|
||||
// ERROR - can create a non-final local of type yield using qualified typename
|
||||
WarnWrongYieldTest.yield y5 = new yield();
|
||||
}
|
||||
|
||||
void MethodInvocation(int i) {
|
||||
|
||||
// OK - can access a field called yield
|
||||
String[] x = this.yield;
|
||||
|
||||
// ERROR - calling nullary yield method using simple name parsed as yield statement
|
||||
yield();
|
||||
// OK - can call nullary yield method using qualified name
|
||||
this.yield();
|
||||
|
||||
// ERROR - Calling unary yield method using simple name is parsed as yield statement
|
||||
yield(2);
|
||||
// OK - calling unary yield method using qualified name
|
||||
this.yield(2);
|
||||
|
||||
// ERROR - Calling binary yield method using simple name is parsed as yield statement
|
||||
yield(2, 2); //error
|
||||
// OK - calling binary yield method using qualified name
|
||||
this.yield(2, 2);
|
||||
|
||||
// ERROR - nullary yield method as receiver is parsed as yield statement
|
||||
yield().toString();
|
||||
// OK - nullary yield method as receiver using qualified name
|
||||
this.yield().toString();
|
||||
|
||||
// ERROR - unary yield method as receiver is parsed as yield statement
|
||||
yield(2).toString();
|
||||
// OK - unary yield method as receiver using qualified name
|
||||
this.yield(2).toString();
|
||||
|
||||
// ERROR - binary yield method as receiver is parsed as yield statement
|
||||
yield(2, 2).toString();
|
||||
// OK - binary yield method as receiver using qualified name
|
||||
this.yield(2, 2).toString();
|
||||
|
||||
// OK - yield method call is in an expression position
|
||||
String str = yield(2).toString();
|
||||
|
||||
//OK - yield is a variable
|
||||
yield.toString();
|
||||
|
||||
// OK - parsed as method call (with qualified local yield as receiver)
|
||||
this.yield.toString();
|
||||
|
||||
yield[0].toString(); //error
|
||||
}
|
||||
|
||||
private void yieldLocalVar1(int i) {
|
||||
int yield = 0;
|
||||
|
||||
//OK - yield is a variable:
|
||||
yield++;
|
||||
yield--;
|
||||
|
||||
//OK - yield is a variable:
|
||||
yield = 3;
|
||||
|
||||
//OK - yield is a variable:
|
||||
for (int j = 0; j < 3; j++)
|
||||
yield += 1;
|
||||
|
||||
//OK - yield is a variable and not at the beginning of the statement:
|
||||
yieldLocalVar1(yield);
|
||||
|
||||
//ERROR - unqualified yield method invocation:
|
||||
yieldLocalVar1(yield().length);
|
||||
yieldLocalVar1(yield.class.getModifiers());
|
||||
}
|
||||
|
||||
private void yieldLocalVar2(int i) {
|
||||
int[] yield = new int[1];
|
||||
|
||||
//OK - yield is a variable:
|
||||
yield[0] = 5;
|
||||
}
|
||||
}
|
25
test/langtools/tools/javac/switchexpr/WarnWrongYieldTest.out
Normal file
25
test/langtools/tools/javac/switchexpr/WarnWrongYieldTest.out
Normal file
@ -0,0 +1,25 @@
|
||||
WarnWrongYieldTest.java:39:11: compiler.warn.restricted.type.not.allowed.preview: yield, 13
|
||||
WarnWrongYieldTest.java:45:5: compiler.warn.restricted.type.not.allowed.preview: yield, 13
|
||||
WarnWrongYieldTest.java:72:15: compiler.warn.restricted.type.not.allowed.preview: yield, 13
|
||||
WarnWrongYieldTest.java:75:15: compiler.warn.restricted.type.not.allowed.preview: yield, 13
|
||||
WarnWrongYieldTest.java:81:21: compiler.warn.restricted.type.not.allowed.preview: yield, 13
|
||||
WarnWrongYieldTest.java:93:9: compiler.warn.invalid.yield
|
||||
WarnWrongYieldTest.java:98:9: compiler.warn.invalid.yield
|
||||
WarnWrongYieldTest.java:103:9: compiler.warn.invalid.yield
|
||||
WarnWrongYieldTest.java:108:9: compiler.warn.invalid.yield
|
||||
WarnWrongYieldTest.java:113:9: compiler.warn.invalid.yield
|
||||
WarnWrongYieldTest.java:118:9: compiler.warn.invalid.yield
|
||||
WarnWrongYieldTest.java:123:22: compiler.warn.invalid.yield
|
||||
WarnWrongYieldTest.java:152:24: compiler.warn.invalid.yield
|
||||
WarnWrongYieldTest.java:34:28: compiler.warn.illegal.ref.to.restricted.type: yield
|
||||
WarnWrongYieldTest.java:45:5: compiler.warn.illegal.ref.to.restricted.type: yield
|
||||
WarnWrongYieldTest.java:72:9: compiler.warn.illegal.ref.to.restricted.type: yield
|
||||
WarnWrongYieldTest.java:75:9: compiler.warn.illegal.ref.to.restricted.type: yield
|
||||
WarnWrongYieldTest.java:75:24: compiler.warn.illegal.ref.to.restricted.type: yield
|
||||
WarnWrongYieldTest.java:78:25: compiler.warn.illegal.ref.to.restricted.type: yield
|
||||
WarnWrongYieldTest.java:81:15: compiler.warn.illegal.ref.to.restricted.type: yield
|
||||
WarnWrongYieldTest.java:81:30: compiler.warn.illegal.ref.to.restricted.type: yield
|
||||
WarnWrongYieldTest.java:84:27: compiler.warn.illegal.ref.to.restricted.type: yield
|
||||
WarnWrongYieldTest.java:84:43: compiler.warn.illegal.ref.to.restricted.type: yield
|
||||
WarnWrongYieldTest.java:153:24: compiler.warn.illegal.ref.to.restricted.type: yield
|
||||
24 warnings
|
46
test/langtools/tools/javac/switchexpr/WrongBreakTest.java
Normal file
46
test/langtools/tools/javac/switchexpr/WrongBreakTest.java
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8223305
|
||||
* @summary Ensure javac is not crashing for wrong breaks.
|
||||
* @compile/fail/ref=WrongBreakTest.out --enable-preview -source ${jdk.version} -XDrawDiagnostics -XDshould-stop.at=FLOW WrongBreakTest.java
|
||||
*/
|
||||
|
||||
public class WrongBreakTest {
|
||||
|
||||
void test(int i) {
|
||||
int s = 0;
|
||||
int j = switch (s) { default: break; };
|
||||
test(switch (s) { default: yield; });
|
||||
Runnable r = () -> {
|
||||
yield 15;
|
||||
};
|
||||
while (true) {
|
||||
yield 15;
|
||||
}
|
||||
}
|
||||
|
||||
void test(Object o) {}
|
||||
}
|
8
test/langtools/tools/javac/switchexpr/WrongBreakTest.out
Normal file
8
test/langtools/tools/javac/switchexpr/WrongBreakTest.out
Normal file
@ -0,0 +1,8 @@
|
||||
WrongBreakTest.java:36:41: compiler.err.illegal.start.of.expr
|
||||
WrongBreakTest.java:35:39: compiler.err.break.outside.switch.expression
|
||||
WrongBreakTest.java:36:9: compiler.err.ref.ambiguous: test, kindname.method, test(int), WrongBreakTest, kindname.method, test(java.lang.Object), WrongBreakTest
|
||||
WrongBreakTest.java:38:13: compiler.err.no.switch.expression
|
||||
WrongBreakTest.java:41:13: compiler.err.no.switch.expression
|
||||
- compiler.note.preview.filename: WrongBreakTest.java
|
||||
- compiler.note.preview.recompile
|
||||
5 errors
|
225
test/langtools/tools/javac/switchexpr/WrongYieldTest.java
Normal file
225
test/langtools/tools/javac/switchexpr/WrongYieldTest.java
Normal file
@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8223305
|
||||
* @summary Ensure proper errors are returned for yields.
|
||||
* @compile/fail/ref=WrongYieldTest.out --enable-preview -source ${jdk.version} -XDrawDiagnostics -XDshould-stop.at=ATTR WrongYieldTest.java
|
||||
*/
|
||||
|
||||
package t;
|
||||
|
||||
//ERROR - type called yield:
|
||||
import t.WrongYieldTest.yield;
|
||||
|
||||
public class WrongYieldTest {
|
||||
|
||||
// ERROR - class called yield
|
||||
class yield { }
|
||||
|
||||
// OK to have fields called yield
|
||||
String[] yield = null;
|
||||
|
||||
// ERROR - field of type yield
|
||||
yield y;
|
||||
|
||||
// OK to have methods called yield
|
||||
// Nullary yield method
|
||||
String[] yield() {
|
||||
return null;
|
||||
}
|
||||
// Unary yield method
|
||||
String[] yield(int i) {
|
||||
return null;
|
||||
}
|
||||
// Binary yield method
|
||||
String[] yield(int i, int j) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// OK to declare a local called yield
|
||||
void LocalDeclaration1() {
|
||||
int yield;
|
||||
}
|
||||
// OK to declare and initialise a local called yield
|
||||
void LocalDeclaration2() {
|
||||
int yield = 42;
|
||||
}
|
||||
// ERROR can't refer to a local called yield in the initialiser
|
||||
void LocalDeclaration3() {
|
||||
int yield = yield + 1;
|
||||
}
|
||||
|
||||
// OK yield gets interpreted as an identifier in a local declaration
|
||||
void LocalDeclaration4(int i) {
|
||||
int local = switch (i) {
|
||||
default -> {
|
||||
int yield = yield + 1;
|
||||
yield 42;
|
||||
}
|
||||
};
|
||||
}
|
||||
// OK - yield a local called yield
|
||||
void LocalDeclaration5(int i) {
|
||||
int yield = 42;
|
||||
int temp = switch (i) {
|
||||
default -> {
|
||||
yield yield;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void YieldTypedLocals(int i) {
|
||||
// ERROR - Parsed as yield statement, and y1 is unknown
|
||||
yield y1 = null;
|
||||
// ..whereas..
|
||||
// ERROR - parsed as yield statement, which has no switch target
|
||||
Object y1;
|
||||
yield y1 = null;
|
||||
|
||||
// ERROR - Parsed as yield statement, and y2 is unknown
|
||||
yield y2 = new yield();
|
||||
|
||||
// OK - Parsed as yield statement that assigns local y
|
||||
Object y;
|
||||
Object o = switch (i) {
|
||||
default :
|
||||
yield y = null;
|
||||
};
|
||||
|
||||
// ERROR - Parsed as yield statement that assigns local y,
|
||||
//but the initializer refers to restricted identifier:
|
||||
Object y2;
|
||||
Object o2 = switch (i) {
|
||||
default :
|
||||
yield y2 = new yield();
|
||||
};
|
||||
|
||||
// ERROR - can not create an yield-valued local of type Object
|
||||
Object y3 = new yield();
|
||||
|
||||
// ERROR - can not create a final yield-valued local of type yield
|
||||
final yield y4 = new yield();
|
||||
|
||||
// ERROR - can create a non-final local of type yield using qualified typename
|
||||
WrongYieldTest.yield y5 = new yield();
|
||||
|
||||
}
|
||||
|
||||
void MethodInvocation(int i) {
|
||||
|
||||
// OK - can access a field called yield
|
||||
String[] x = this.yield;
|
||||
|
||||
// ERROR - calling nullary yield method using simple name parsed as yield statement
|
||||
yield();
|
||||
// OK - can call nullary yield method using qualified name
|
||||
this.yield();
|
||||
|
||||
// ERROR - Calling unary yield method using simple name is parsed as yield statement
|
||||
yield(2);
|
||||
// OK - calling unary yield method using qualified name
|
||||
this.yield(2);
|
||||
|
||||
// ERROR - Calling binary yield method using simple name is parsed as yield statement
|
||||
yield(2, 2); //error
|
||||
// OK - calling binary yield method using qualified name
|
||||
this.yield(2, 2);
|
||||
|
||||
// ERROR - nullary yield method as receiver is parsed as yield statement
|
||||
yield().toString();
|
||||
// OK - nullary yield method as receiver using qualified name
|
||||
this.yield().toString();
|
||||
|
||||
// ERROR - unary yield method as receiver is parsed as yield statement
|
||||
yield(2).toString();
|
||||
// OK - unary yield method as receiver using qualified name
|
||||
this.yield(2).toString();
|
||||
|
||||
// ERROR - binary yield method as receiver is parsed as yield statement
|
||||
yield(2, 2).toString();
|
||||
// OK - binary yield method as receiver using qualified name
|
||||
this.yield(2, 2).toString();
|
||||
|
||||
// OK - yield method call is in an expression position
|
||||
String str = yield(2).toString();
|
||||
|
||||
|
||||
|
||||
//OK - yield is a variable
|
||||
yield.toString();
|
||||
|
||||
// OK - parsed as method call (with qualified local yield as receiver)
|
||||
this.yield.toString();
|
||||
|
||||
yield[0].toString(); //error
|
||||
|
||||
// OK - parsed as yield statement in switch expression
|
||||
int j = switch (i) {
|
||||
default:
|
||||
yield(2);
|
||||
};
|
||||
|
||||
// ERROR - second yield is an unreachable statement.
|
||||
x = switch (i) {
|
||||
default: {
|
||||
yield x = null;
|
||||
yield null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void yieldLocalVar1(int i) {
|
||||
int yield = 0;
|
||||
|
||||
//OK - yield is a variable:
|
||||
yield++;
|
||||
yield--;
|
||||
|
||||
//ERROR - yield is a statement, but no enclosing switch expr:
|
||||
yield ++i;
|
||||
yield --i;
|
||||
|
||||
//OK - yield is a variable:
|
||||
yield = 3;
|
||||
|
||||
//OK - yield is a variable:
|
||||
for (int j = 0; j < 3; j++)
|
||||
yield += 1;
|
||||
|
||||
//OK - yield is a variable and not at the beginning of the statement:
|
||||
yieldLocalVar1(yield);
|
||||
|
||||
//ERROR - unqualified yield method invocation:
|
||||
yieldLocalVar1(yield().length);
|
||||
yieldLocalVar1(yield.class.getModifiers());
|
||||
}
|
||||
|
||||
private void yieldLocalVar2(int i) {
|
||||
int[] yield = new int[1];
|
||||
|
||||
//OK - yield is a variable:
|
||||
yield[0] = 5;
|
||||
}
|
||||
}
|
29
test/langtools/tools/javac/switchexpr/WrongYieldTest.out
Normal file
29
test/langtools/tools/javac/switchexpr/WrongYieldTest.out
Normal file
@ -0,0 +1,29 @@
|
||||
WrongYieldTest.java:39:11: compiler.err.restricted.type.not.allowed: yield, 13
|
||||
WrongYieldTest.java:45:5: compiler.err.restricted.type.not.allowed.here: yield
|
||||
WrongYieldTest.java:136:9: compiler.err.invalid.yield
|
||||
WrongYieldTest.java:146:9: compiler.err.invalid.yield
|
||||
WrongYieldTest.java:151:9: compiler.err.invalid.yield
|
||||
WrongYieldTest.java:161:9: compiler.err.invalid.yield
|
||||
WrongYieldTest.java:166:22: compiler.err.invalid.yield
|
||||
WrongYieldTest.java:215:24: compiler.err.invalid.yield
|
||||
WrongYieldTest.java:34:24: compiler.err.illegal.ref.to.restricted.type: yield
|
||||
WrongYieldTest.java:95:9: compiler.err.no.switch.expression
|
||||
WrongYieldTest.java:95:15: compiler.err.cant.resolve.location: kindname.variable, y1, , , (compiler.misc.location: kindname.class, t.WrongYieldTest, null)
|
||||
WrongYieldTest.java:99:9: compiler.err.no.switch.expression
|
||||
WrongYieldTest.java:102:9: compiler.err.no.switch.expression
|
||||
WrongYieldTest.java:102:15: compiler.err.cant.resolve.location: kindname.variable, y2, , , (compiler.misc.location: kindname.class, t.WrongYieldTest, null)
|
||||
WrongYieldTest.java:102:24: compiler.err.illegal.ref.to.restricted.type: yield
|
||||
WrongYieldTest.java:116:32: compiler.err.illegal.ref.to.restricted.type: yield
|
||||
WrongYieldTest.java:120:25: compiler.err.illegal.ref.to.restricted.type: yield
|
||||
WrongYieldTest.java:123:30: compiler.err.illegal.ref.to.restricted.type: yield
|
||||
WrongYieldTest.java:126:23: compiler.err.illegal.ref.to.restricted.type: yield
|
||||
WrongYieldTest.java:126:39: compiler.err.illegal.ref.to.restricted.type: yield
|
||||
WrongYieldTest.java:141:9: compiler.err.no.switch.expression.qualify
|
||||
WrongYieldTest.java:156:9: compiler.err.no.switch.expression
|
||||
WrongYieldTest.java:156:17: compiler.err.cant.deref: int
|
||||
WrongYieldTest.java:201:9: compiler.err.no.switch.expression
|
||||
WrongYieldTest.java:202:9: compiler.err.no.switch.expression
|
||||
WrongYieldTest.java:216:24: compiler.err.illegal.ref.to.restricted.type: yield
|
||||
- compiler.note.preview.filename: WrongYieldTest.java
|
||||
- compiler.note.preview.recompile
|
||||
26 errors
|
116
test/langtools/tools/javac/switchextra/DefiniteAssignment1.java
Normal file
116
test/langtools/tools/javac/switchextra/DefiniteAssignment1.java
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Verify that definite assignment works (legal code)
|
||||
* @compile --enable-preview -source ${jdk.version} DefiniteAssignment1.java
|
||||
* @run main/othervm --enable-preview DefiniteAssignment1
|
||||
*/
|
||||
public class DefiniteAssignment1 {
|
||||
public static void main(String[] args) {
|
||||
int a = 0;
|
||||
|
||||
{
|
||||
int x;
|
||||
|
||||
switch(a) {
|
||||
case 0: x = 0; break;
|
||||
default: x = 1; break;
|
||||
}
|
||||
|
||||
if (x != 0)
|
||||
throw new IllegalStateException("Unexpected value.");
|
||||
}
|
||||
|
||||
{
|
||||
int x;
|
||||
|
||||
switch(a) {
|
||||
case 1: x = 1; break;
|
||||
case 0:
|
||||
default: x = 0; break;
|
||||
}
|
||||
|
||||
if (x != 0)
|
||||
throw new IllegalStateException("Unexpected value.");
|
||||
}
|
||||
|
||||
{
|
||||
int x;
|
||||
|
||||
switch(a) {
|
||||
case 1: x = 1; break;
|
||||
case 0:
|
||||
default: x = 0;
|
||||
}
|
||||
|
||||
if (x != 0)
|
||||
throw new IllegalStateException("Unexpected value.");
|
||||
}
|
||||
|
||||
{
|
||||
int x;
|
||||
|
||||
switch(a) {
|
||||
case 0 -> x = 0;
|
||||
default -> x = 1;
|
||||
}
|
||||
|
||||
if (x != 0)
|
||||
throw new IllegalStateException("Unexpected value.");
|
||||
}
|
||||
|
||||
{
|
||||
int x;
|
||||
|
||||
try {
|
||||
switch(a) {
|
||||
case 1: x = 1; break;
|
||||
case 0:
|
||||
default: throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Unexpected value: " + x);
|
||||
} catch (UnsupportedOperationException ex) {
|
||||
//OK
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int x;
|
||||
|
||||
switch(a) {
|
||||
case 0 -> x = 0;
|
||||
default -> throw new IllegalStateException();
|
||||
}
|
||||
|
||||
if (x != 0)
|
||||
throw new IllegalStateException("Unexpected value.");
|
||||
}
|
||||
}
|
||||
|
||||
enum E {
|
||||
A, B, C;
|
||||
}
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
/**
|
||||
* @test /nodynamiccopyright/
|
||||
* @summary Verify that definite assignment works (illegal code)
|
||||
* @compile/fail/ref=DefiniteAssignment2.out -XDrawDiagnostics --enable-preview -source ${jdk.version} DefiniteAssignment2.java
|
||||
*/
|
||||
public class DefiniteAssignment2 {
|
||||
|
||||
public static void main(String[] args) {
|
||||
int a = 0;
|
||||
E e = E.A;
|
||||
|
||||
{
|
||||
int x;
|
||||
|
||||
switch(a) {
|
||||
case 0: break;
|
||||
default: x = 1; break;
|
||||
}
|
||||
|
||||
System.err.println(x);
|
||||
}
|
||||
|
||||
{
|
||||
int x;
|
||||
|
||||
switch(a) {
|
||||
case 0 -> {}
|
||||
default -> x = 1;
|
||||
}
|
||||
|
||||
System.err.println(x);
|
||||
}
|
||||
|
||||
{
|
||||
int x;
|
||||
|
||||
switch(a) {
|
||||
case 0: x = 0; break;
|
||||
default:
|
||||
}
|
||||
|
||||
System.err.println(x);
|
||||
}
|
||||
|
||||
{
|
||||
int x;
|
||||
|
||||
switch(e) {
|
||||
case A, B, C -> x = 0;
|
||||
}
|
||||
|
||||
System.err.println(x);
|
||||
}
|
||||
|
||||
{
|
||||
int x;
|
||||
|
||||
switch(e) {
|
||||
case A, B, C -> { x = 0; }
|
||||
}
|
||||
|
||||
System.err.println(x);
|
||||
}
|
||||
|
||||
{
|
||||
int x;
|
||||
|
||||
switch(e) {
|
||||
case A, B -> { x = 0; }
|
||||
case C -> throw new IllegalStateException();
|
||||
}
|
||||
|
||||
System.err.println(x);
|
||||
}
|
||||
}
|
||||
|
||||
enum E {
|
||||
A, B, C;
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
DefiniteAssignment2.java:20:28: compiler.err.var.might.not.have.been.initialized: x
|
||||
DefiniteAssignment2.java:31:28: compiler.err.var.might.not.have.been.initialized: x
|
||||
DefiniteAssignment2.java:42:28: compiler.err.var.might.not.have.been.initialized: x
|
||||
DefiniteAssignment2.java:52:28: compiler.err.var.might.not.have.been.initialized: x
|
||||
DefiniteAssignment2.java:62:28: compiler.err.var.might.not.have.been.initialized: x
|
||||
DefiniteAssignment2.java:73:28: compiler.err.var.might.not.have.been.initialized: x
|
||||
- compiler.note.preview.filename: DefiniteAssignment2.java
|
||||
- compiler.note.preview.recompile
|
||||
6 errors
|
@ -30,7 +30,7 @@ public class MultipleLabelsExpression {
|
||||
private String expression1(T t) {
|
||||
return switch (t) {
|
||||
case A -> "A";
|
||||
case B, C -> { break "B-C"; }
|
||||
case B, C -> { yield "B-C"; }
|
||||
case D -> "D";
|
||||
default -> "other";
|
||||
};
|
||||
|
@ -2,5 +2,5 @@ VarInImplicitLambdaNegTest01.java:12:28: compiler.err.invalid.lambda.parameter.d
|
||||
VarInImplicitLambdaNegTest01.java:13:28: compiler.err.invalid.lambda.parameter.declaration: (compiler.misc.var.and.implicit.not.allowed)
|
||||
VarInImplicitLambdaNegTest01.java:14:28: compiler.err.invalid.lambda.parameter.declaration: (compiler.misc.var.and.explicit.not.allowed)
|
||||
VarInImplicitLambdaNegTest01.java:15:28: compiler.err.invalid.lambda.parameter.declaration: (compiler.misc.implicit.and.explicit.not.allowed)
|
||||
VarInImplicitLambdaNegTest01.java:17:52: compiler.err.var.not.allowed.array
|
||||
VarInImplicitLambdaNegTest01.java:17:52: compiler.err.restricted.type.not.allowed.array: var
|
||||
5 errors
|
||||
|
@ -1,6 +1,6 @@
|
||||
- compiler.warn.source.no.bootclasspath: 10
|
||||
VarInImplicitLambdaNegTest01.java:12:36: compiler.err.feature.not.supported.in.source.plural: (compiler.misc.feature.var.syntax.in.implicit.lambda), 10, 11
|
||||
VarInImplicitLambdaNegTest01.java:15:28: compiler.err.invalid.lambda.parameter.declaration: (compiler.misc.implicit.and.explicit.not.allowed)
|
||||
VarInImplicitLambdaNegTest01.java:17:52: compiler.err.var.not.allowed.here
|
||||
VarInImplicitLambdaNegTest01.java:17:52: compiler.err.restricted.type.not.allowed.here: var
|
||||
3 errors
|
||||
1 warning
|
||||
|
Loading…
x
Reference in New Issue
Block a user