8282274: Compiler implementation for Pattern Matching for switch (Third Preview)
Co-authored-by: Brian Goetz <briangoetz@openjdk.org> Co-authored-by: Jan Lahoda <jlahoda@openjdk.org> Reviewed-by: mcimadamore, vromero, abimpoudis
This commit is contained in:
parent
2d34acfec9
commit
0155e4b76b
src
java.base/share/classes/java/lang
jdk.compiler/share/classes/com/sun
source
tools/javac
test/langtools/tools/javac
classfiles/attributes/LineNumberTable
diags/examples
CantRefNonEffectivelyFinalVar.javaDuplicateUnconditionalPattern.javaFeatureUnconditionalPatternsInInstanceof.javaNotApplicableTypes.javaUnconditionalPatternAndDefault.java
patterns
CaseStructureTest.javaDisambiguatePatterns.javaDomination.javaEnumTypeChanges.javaExhaustiveness.javaGuards.javaGuardsErrors.javaGuardsErrors.outInstanceofTotalPattern-15.outInstanceofTotalPattern-16.outInstanceofTotalPattern-preview.outInstanceofTotalPattern.javaNestedPatternVariablesBytecode.javaNullSwitch.javaParenthesized.javaRawTypeBindingWarning.javaRawTypeBindingWarning.outSealedTypeChanges.javaSimpleAndGuardPattern.javaSwitchErrors.javaSwitchErrors.outSwitches.java
66
src/java.base/share/classes/java/lang/MatchException.java
Normal file
66
src/java.base/share/classes/java/lang/MatchException.java
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022, 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 java.lang;
|
||||||
|
|
||||||
|
import jdk.internal.javac.PreviewFeature;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown to indicate an unexpected failure in pattern matching.
|
||||||
|
*
|
||||||
|
* {@code MatchException} may be thrown when an exhaustive pattern matching language construct
|
||||||
|
* (such as a switch expression) encounters a value that does not match any of the provided
|
||||||
|
* patterns at runtime. This can currently arise for separate compilation anomalies,
|
||||||
|
* where a sealed interface has a different set of permitted subtypes at runtime than
|
||||||
|
* it had at compilation time, an enum has a different set of constants at runtime than
|
||||||
|
* it had at compilation time, or the type hierarchy has changed in incompatible ways between
|
||||||
|
* compile time and run time.
|
||||||
|
*
|
||||||
|
* @jls 14.11.3 Execution of a switch Statement
|
||||||
|
* @jls 14.30.2 Pattern Matching
|
||||||
|
* @jls 15.28.2 Run-Time Evaluation of switch Expressions
|
||||||
|
*
|
||||||
|
* @since 19
|
||||||
|
*/
|
||||||
|
@PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING)
|
||||||
|
public final class MatchException extends RuntimeException {
|
||||||
|
@java.io.Serial
|
||||||
|
private static final long serialVersionUID = 0L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs an {@code MatchException} with the specified detail message and
|
||||||
|
* cause.
|
||||||
|
*
|
||||||
|
* @param message the detail message (which is saved for later retrieval
|
||||||
|
* by the {@link #getMessage()} method).
|
||||||
|
* @param cause the cause (which is saved for later retrieval by the
|
||||||
|
* {@link #getCause()} method). (A {@code null} value is
|
||||||
|
* permitted, and indicates that the cause is nonexistent or
|
||||||
|
* unknown.)
|
||||||
|
*/
|
||||||
|
public MatchException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -25,10 +25,23 @@
|
|||||||
|
|
||||||
package com.sun.source.tree;
|
package com.sun.source.tree;
|
||||||
|
|
||||||
|
import jdk.internal.javac.PreviewFeature;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A tree node used as the base class for the different kinds of
|
* A tree node used as the base class for the different kinds of
|
||||||
* patterns.
|
* patterns.
|
||||||
*
|
*
|
||||||
* @since 16
|
* @since 16
|
||||||
*/
|
*/
|
||||||
public interface PatternTree extends Tree, CaseLabelTree {}
|
public interface PatternTree extends Tree, CaseLabelTree {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The guard for the case.
|
||||||
|
*
|
||||||
|
* @return the guard
|
||||||
|
* @since 19
|
||||||
|
*/
|
||||||
|
@PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
|
||||||
|
ExpressionTree getGuard();
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -228,14 +228,6 @@ public interface Tree {
|
|||||||
*/
|
*/
|
||||||
BINDING_PATTERN(BindingPatternTree.class),
|
BINDING_PATTERN(BindingPatternTree.class),
|
||||||
|
|
||||||
/**
|
|
||||||
* Used for instances of {@link GuardedPatternTree}.
|
|
||||||
*
|
|
||||||
* @since 17
|
|
||||||
*/
|
|
||||||
@PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
|
|
||||||
GUARDED_PATTERN(GuardedPatternTree.class),
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used for instances of {@link ParenthesizedPatternTree}.
|
* Used for instances of {@link ParenthesizedPatternTree}.
|
||||||
*
|
*
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -302,16 +302,6 @@ public interface TreeVisitor<R,P> {
|
|||||||
*/
|
*/
|
||||||
R visitNewArray(NewArrayTree node, P p);
|
R visitNewArray(NewArrayTree node, P p);
|
||||||
|
|
||||||
/**
|
|
||||||
* Visits a {@code GuardPatternTree} node.
|
|
||||||
* @param node the node being visited
|
|
||||||
* @param p a parameter value
|
|
||||||
* @return a result value
|
|
||||||
* @since 17
|
|
||||||
*/
|
|
||||||
@PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
|
|
||||||
R visitGuardedPattern(GuardedPatternTree node, P p);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visits a {@code ParenthesizedPatternTree} node.
|
* Visits a {@code ParenthesizedPatternTree} node.
|
||||||
* @param node the node being visited
|
* @param node the node being visited
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -703,22 +703,6 @@ public class SimpleTreeVisitor <R,P> implements TreeVisitor<R,P> {
|
|||||||
return defaultAction(node, p);
|
return defaultAction(node, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*
|
|
||||||
* @implSpec This implementation calls {@code defaultAction}.
|
|
||||||
*
|
|
||||||
* @param node {@inheritDoc}
|
|
||||||
* @param p {@inheritDoc}
|
|
||||||
* @return the result of {@code defaultAction}
|
|
||||||
* @since 17
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
|
|
||||||
public R visitGuardedPattern(GuardedPatternTree node, P p) {
|
|
||||||
return defaultAction(node, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -771,7 +771,9 @@ public class TreeScanner<R,P> implements TreeVisitor<R,P> {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public R visitBindingPattern(BindingPatternTree node, P p) {
|
public R visitBindingPattern(BindingPatternTree node, P p) {
|
||||||
return scan(node.getVariable(), p);
|
R r = scan(node.getVariable(), p);
|
||||||
|
r = scanAndReduce(node.getGuard(), p, r);
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -833,24 +835,9 @@ public class TreeScanner<R,P> implements TreeVisitor<R,P> {
|
|||||||
@Override
|
@Override
|
||||||
@PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
|
@PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
|
||||||
public R visitParenthesizedPattern(ParenthesizedPatternTree node, P p) {
|
public R visitParenthesizedPattern(ParenthesizedPatternTree node, P p) {
|
||||||
return scan(node.getPattern(), p);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*
|
|
||||||
* @implSpec This implementation scans the children in left to right order.
|
|
||||||
*
|
|
||||||
* @param node {@inheritDoc}
|
|
||||||
* @param p {@inheritDoc}
|
|
||||||
* @return the result of scanning
|
|
||||||
* @since 17
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
@PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
|
|
||||||
public R visitGuardedPattern(GuardedPatternTree node, P p) {
|
|
||||||
R r = scan(node.getPattern(), p);
|
R r = scan(node.getPattern(), p);
|
||||||
return scanAndReduce(node.getExpression(), p, r);
|
r = scanAndReduce(node.getGuard(), p, r);
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -186,6 +186,7 @@ public class Preview {
|
|||||||
return switch (feature) {
|
return switch (feature) {
|
||||||
case CASE_NULL -> true;
|
case CASE_NULL -> true;
|
||||||
case PATTERN_SWITCH -> true;
|
case PATTERN_SWITCH -> true;
|
||||||
|
case UNCONDITIONAL_PATTERN_IN_INSTANCEOF -> true;
|
||||||
|
|
||||||
//Note: this is a backdoor which allows to optionally treat all features as 'preview' (for testing).
|
//Note: this is a backdoor which allows to optionally treat all features as 'preview' (for testing).
|
||||||
//When real preview features will be added, this method can be implemented to return 'true'
|
//When real preview features will be added, this method can be implemented to return 'true'
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -239,6 +239,7 @@ public enum Source {
|
|||||||
CASE_NULL(JDK17, Fragments.FeatureCaseNull, DiagKind.NORMAL),
|
CASE_NULL(JDK17, Fragments.FeatureCaseNull, DiagKind.NORMAL),
|
||||||
PATTERN_SWITCH(JDK17, Fragments.FeaturePatternSwitch, DiagKind.PLURAL),
|
PATTERN_SWITCH(JDK17, Fragments.FeaturePatternSwitch, DiagKind.PLURAL),
|
||||||
REDUNDANT_STRICTFP(JDK17),
|
REDUNDANT_STRICTFP(JDK17),
|
||||||
|
UNCONDITIONAL_PATTERN_IN_INSTANCEOF(JDK19, Fragments.FeatureUnconditionalPatternsInInstanceof, DiagKind.PLURAL),
|
||||||
;
|
;
|
||||||
|
|
||||||
enum DiagKind {
|
enum DiagKind {
|
||||||
|
@ -189,6 +189,7 @@ public class Symtab {
|
|||||||
public final Type assertionErrorType;
|
public final Type assertionErrorType;
|
||||||
public final Type incompatibleClassChangeErrorType;
|
public final Type incompatibleClassChangeErrorType;
|
||||||
public final Type cloneNotSupportedExceptionType;
|
public final Type cloneNotSupportedExceptionType;
|
||||||
|
public final Type matchExceptionType;
|
||||||
public final Type annotationType;
|
public final Type annotationType;
|
||||||
public final TypeSymbol enumSym;
|
public final TypeSymbol enumSym;
|
||||||
public final Type listType;
|
public final Type listType;
|
||||||
@ -553,6 +554,7 @@ public class Symtab {
|
|||||||
assertionErrorType = enterClass("java.lang.AssertionError");
|
assertionErrorType = enterClass("java.lang.AssertionError");
|
||||||
incompatibleClassChangeErrorType = enterClass("java.lang.IncompatibleClassChangeError");
|
incompatibleClassChangeErrorType = enterClass("java.lang.IncompatibleClassChangeError");
|
||||||
cloneNotSupportedExceptionType = enterClass("java.lang.CloneNotSupportedException");
|
cloneNotSupportedExceptionType = enterClass("java.lang.CloneNotSupportedException");
|
||||||
|
matchExceptionType = enterClass("java.lang.MatchException");
|
||||||
annotationType = enterClass("java.lang.annotation.Annotation");
|
annotationType = enterClass("java.lang.annotation.Annotation");
|
||||||
classLoaderType = enterClass("java.lang.ClassLoader");
|
classLoaderType = enterClass("java.lang.ClassLoader");
|
||||||
enumSym = enterClass(java_base, names.java_lang_Enum);
|
enumSym = enterClass(java_base, names.java_lang_Enum);
|
||||||
|
@ -174,6 +174,8 @@ public class Attr extends JCTree.Visitor {
|
|||||||
allowRecords = Feature.RECORDS.allowedInSource(source);
|
allowRecords = Feature.RECORDS.allowedInSource(source);
|
||||||
allowPatternSwitch = (preview.isEnabled() || !preview.isPreview(Feature.PATTERN_SWITCH)) &&
|
allowPatternSwitch = (preview.isEnabled() || !preview.isPreview(Feature.PATTERN_SWITCH)) &&
|
||||||
Feature.PATTERN_SWITCH.allowedInSource(source);
|
Feature.PATTERN_SWITCH.allowedInSource(source);
|
||||||
|
allowUnconditionalPatternsInstanceOf = (preview.isEnabled() || !preview.isPreview(Feature.UNCONDITIONAL_PATTERN_IN_INSTANCEOF)) &&
|
||||||
|
Feature.UNCONDITIONAL_PATTERN_IN_INSTANCEOF.allowedInSource(source);
|
||||||
sourceName = source.name;
|
sourceName = source.name;
|
||||||
useBeforeDeclarationWarning = options.isSet("useBeforeDeclarationWarning");
|
useBeforeDeclarationWarning = options.isSet("useBeforeDeclarationWarning");
|
||||||
|
|
||||||
@ -218,6 +220,10 @@ public class Attr extends JCTree.Visitor {
|
|||||||
*/
|
*/
|
||||||
private final boolean allowPatternSwitch;
|
private final boolean allowPatternSwitch;
|
||||||
|
|
||||||
|
/** Are unconditional patterns in instanceof allowed
|
||||||
|
*/
|
||||||
|
private final boolean allowUnconditionalPatternsInstanceOf;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Switch: warn about use of variable before declaration?
|
* Switch: warn about use of variable before declaration?
|
||||||
* RFE: 6425594
|
* RFE: 6425594
|
||||||
@ -1691,7 +1697,8 @@ public class Attr extends JCTree.Visitor {
|
|||||||
List<Type> coveredTypesForPatterns = List.nil();
|
List<Type> coveredTypesForPatterns = List.nil();
|
||||||
List<Type> coveredTypesForConstants = List.nil();
|
List<Type> coveredTypesForConstants = List.nil();
|
||||||
boolean hasDefault = false; // Is there a default label?
|
boolean hasDefault = false; // Is there a default label?
|
||||||
boolean hasTotalPattern = false; // Is there a total pattern?
|
boolean hasUnconditionalPattern = false; // Is there a unconditional pattern?
|
||||||
|
boolean lastPatternErroneous = false; // Has the last pattern erroneous type?
|
||||||
boolean hasNullPattern = false; // Is there a null pattern?
|
boolean hasNullPattern = false; // Is there a null pattern?
|
||||||
CaseTree.CaseKind caseKind = null;
|
CaseTree.CaseKind caseKind = null;
|
||||||
boolean wasError = false;
|
boolean wasError = false;
|
||||||
@ -1706,7 +1713,7 @@ public class Attr extends JCTree.Visitor {
|
|||||||
wasError = true;
|
wasError = true;
|
||||||
}
|
}
|
||||||
MatchBindings currentBindings = prevBindings;
|
MatchBindings currentBindings = prevBindings;
|
||||||
boolean wasTotalPattern = hasTotalPattern;
|
boolean wasUnconditionalPattern = hasUnconditionalPattern;
|
||||||
for (JCCaseLabel pat : c.labels) {
|
for (JCCaseLabel pat : c.labels) {
|
||||||
if (pat.isExpression()) {
|
if (pat.isExpression()) {
|
||||||
JCExpression expr = (JCExpression) pat;
|
JCExpression expr = (JCExpression) pat;
|
||||||
@ -1714,7 +1721,7 @@ public class Attr extends JCTree.Visitor {
|
|||||||
preview.checkSourceLevel(expr.pos(), Feature.CASE_NULL);
|
preview.checkSourceLevel(expr.pos(), Feature.CASE_NULL);
|
||||||
if (hasNullPattern) {
|
if (hasNullPattern) {
|
||||||
log.error(pat.pos(), Errors.DuplicateCaseLabel);
|
log.error(pat.pos(), Errors.DuplicateCaseLabel);
|
||||||
} else if (wasTotalPattern) {
|
} else if (wasUnconditionalPattern) {
|
||||||
log.error(pat.pos(), Errors.PatternDominated);
|
log.error(pat.pos(), Errors.PatternDominated);
|
||||||
}
|
}
|
||||||
hasNullPattern = true;
|
hasNullPattern = true;
|
||||||
@ -1767,42 +1774,57 @@ public class Attr extends JCTree.Visitor {
|
|||||||
} else if (pat.hasTag(DEFAULTCASELABEL)) {
|
} else if (pat.hasTag(DEFAULTCASELABEL)) {
|
||||||
if (hasDefault) {
|
if (hasDefault) {
|
||||||
log.error(pat.pos(), Errors.DuplicateDefaultLabel);
|
log.error(pat.pos(), Errors.DuplicateDefaultLabel);
|
||||||
} else if (hasTotalPattern) {
|
} else if (hasUnconditionalPattern) {
|
||||||
log.error(pat.pos(), Errors.TotalPatternAndDefault);
|
log.error(pat.pos(), Errors.UnconditionalPatternAndDefault);
|
||||||
}
|
}
|
||||||
hasDefault = true;
|
hasDefault = true;
|
||||||
matchBindings = MatchBindingsComputer.EMPTY;
|
matchBindings = MatchBindingsComputer.EMPTY;
|
||||||
} else {
|
} else {
|
||||||
//binding pattern
|
//binding pattern
|
||||||
attribExpr(pat, switchEnv);
|
attribExpr(pat, switchEnv);
|
||||||
var primary = TreeInfo.primaryPatternType((JCPattern) pat);
|
Type primaryType = TreeInfo.primaryPatternType(pat);
|
||||||
Type primaryType = primary.type();
|
|
||||||
if (!primaryType.hasTag(TYPEVAR)) {
|
if (!primaryType.hasTag(TYPEVAR)) {
|
||||||
primaryType = chk.checkClassOrArrayType(pat.pos(), primaryType);
|
primaryType = chk.checkClassOrArrayType(pat.pos(), primaryType);
|
||||||
}
|
}
|
||||||
checkCastablePattern(pat.pos(), seltype, primaryType);
|
checkCastablePattern(pat.pos(), seltype, primaryType);
|
||||||
Type patternType = types.erasure(primaryType);
|
Type patternType = types.erasure(primaryType);
|
||||||
boolean isTotal = primary.unconditional() &&
|
JCExpression guard = ((JCPattern) pat).guard;
|
||||||
!patternType.isErroneous() &&
|
if (guard != null) {
|
||||||
types.isSubtype(types.erasure(seltype), patternType);
|
MatchBindings afterPattern = matchBindings;
|
||||||
if (isTotal) {
|
Env<AttrContext> bodyEnv = bindingEnv(env, matchBindings.bindingsWhenTrue);
|
||||||
if (hasTotalPattern) {
|
try {
|
||||||
log.error(pat.pos(), Errors.DuplicateTotalPattern);
|
attribExpr(guard, bodyEnv, syms.booleanType);
|
||||||
} else if (hasDefault) {
|
} finally {
|
||||||
log.error(pat.pos(), Errors.TotalPatternAndDefault);
|
bodyEnv.info.scope.leave();
|
||||||
}
|
}
|
||||||
hasTotalPattern = true;
|
matchBindings = matchBindingsComputer.caseGuard(c, afterPattern, matchBindings);
|
||||||
}
|
}
|
||||||
|
boolean unguarded = TreeInfo.unguardedCaseLabel(pat);
|
||||||
|
boolean unconditional =
|
||||||
|
unguarded &&
|
||||||
|
!patternType.isErroneous() &&
|
||||||
|
types.isSubtype(types.boxedTypeOrType(types.erasure(seltype)),
|
||||||
|
patternType);
|
||||||
|
if (unconditional) {
|
||||||
|
if (hasUnconditionalPattern) {
|
||||||
|
log.error(pat.pos(), Errors.DuplicateUnconditionalPattern);
|
||||||
|
} else if (hasDefault) {
|
||||||
|
log.error(pat.pos(), Errors.UnconditionalPatternAndDefault);
|
||||||
|
}
|
||||||
|
hasUnconditionalPattern = true;
|
||||||
|
}
|
||||||
|
lastPatternErroneous = patternType.isErroneous();
|
||||||
checkCaseLabelDominated(pat.pos(), coveredTypesForPatterns, patternType);
|
checkCaseLabelDominated(pat.pos(), coveredTypesForPatterns, patternType);
|
||||||
if (!patternType.isErroneous()) {
|
if (!patternType.isErroneous()) {
|
||||||
coveredTypesForConstants = coveredTypesForConstants.prepend(patternType);
|
coveredTypesForConstants = coveredTypesForConstants.prepend(patternType);
|
||||||
if (primary.unconditional()) {
|
if (unguarded) {
|
||||||
coveredTypesForPatterns = coveredTypesForPatterns.prepend(patternType);
|
coveredTypesForPatterns = coveredTypesForPatterns.prepend(patternType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
currentBindings = matchBindingsComputer.switchCase(pat, currentBindings, matchBindings);
|
currentBindings = matchBindingsComputer.switchCase(pat, currentBindings, matchBindings);
|
||||||
}
|
}
|
||||||
|
|
||||||
Env<AttrContext> caseEnv =
|
Env<AttrContext> caseEnv =
|
||||||
bindingEnv(switchEnv, c, currentBindings.bindingsWhenTrue);
|
bindingEnv(switchEnv, c, currentBindings.bindingsWhenTrue);
|
||||||
try {
|
try {
|
||||||
@ -1822,10 +1844,12 @@ public class Attr extends JCTree.Visitor {
|
|||||||
chk.checkSwitchCaseStructure(cases);
|
chk.checkSwitchCaseStructure(cases);
|
||||||
}
|
}
|
||||||
if (switchTree.hasTag(SWITCH)) {
|
if (switchTree.hasTag(SWITCH)) {
|
||||||
((JCSwitch) switchTree).hasTotalPattern = hasDefault || hasTotalPattern;
|
((JCSwitch) switchTree).hasUnconditionalPattern =
|
||||||
|
hasDefault || hasUnconditionalPattern || lastPatternErroneous;
|
||||||
((JCSwitch) switchTree).patternSwitch = patternSwitch;
|
((JCSwitch) switchTree).patternSwitch = patternSwitch;
|
||||||
} else if (switchTree.hasTag(SWITCH_EXPRESSION)) {
|
} else if (switchTree.hasTag(SWITCH_EXPRESSION)) {
|
||||||
((JCSwitchExpression) switchTree).hasTotalPattern = hasDefault || hasTotalPattern;
|
((JCSwitchExpression) switchTree).hasUnconditionalPattern =
|
||||||
|
hasDefault || hasUnconditionalPattern || lastPatternErroneous;
|
||||||
((JCSwitchExpression) switchTree).patternSwitch = patternSwitch;
|
((JCSwitchExpression) switchTree).patternSwitch = patternSwitch;
|
||||||
} else {
|
} else {
|
||||||
Assert.error(switchTree.getTag().name());
|
Assert.error(switchTree.getTag().name());
|
||||||
@ -4095,7 +4119,11 @@ public class Attr extends JCTree.Visitor {
|
|||||||
clazztype = tree.pattern.type;
|
clazztype = tree.pattern.type;
|
||||||
if (types.isSubtype(exprtype, clazztype) &&
|
if (types.isSubtype(exprtype, clazztype) &&
|
||||||
!exprtype.isErroneous() && !clazztype.isErroneous()) {
|
!exprtype.isErroneous() && !clazztype.isErroneous()) {
|
||||||
log.error(tree.pos(), Errors.InstanceofPatternNoSubtype(exprtype, clazztype));
|
if (!allowUnconditionalPatternsInstanceOf) {
|
||||||
|
log.error(tree.pos(), Errors.InstanceofPatternNoSubtype(exprtype, clazztype));
|
||||||
|
} else if (preview.isPreview(Feature.UNCONDITIONAL_PATTERN_IN_INSTANCEOF)) {
|
||||||
|
preview.warnPreview(tree.pattern.pos(), Feature.UNCONDITIONAL_PATTERN_IN_INSTANCEOF);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
typeTree = TreeInfo.primaryPatternTree((JCPattern) tree.pattern).var.vartype;
|
typeTree = TreeInfo.primaryPatternTree((JCPattern) tree.pattern).var.vartype;
|
||||||
} else {
|
} else {
|
||||||
@ -4131,6 +4159,10 @@ public class Attr extends JCTree.Visitor {
|
|||||||
chk.basicHandler.report(pos,
|
chk.basicHandler.report(pos,
|
||||||
diags.fragment(Fragments.InconvertibleTypes(exprType, pattType)));
|
diags.fragment(Fragments.InconvertibleTypes(exprType, pattType)));
|
||||||
return false;
|
return false;
|
||||||
|
} else if (exprType.isPrimitive() ^ pattType.isPrimitive()) {
|
||||||
|
chk.basicHandler.report(pos,
|
||||||
|
diags.fragment(Fragments.NotApplicableTypes(exprType, pattType)));
|
||||||
|
return false;
|
||||||
} else if (warner.hasLint(LintCategory.UNCHECKED)) {
|
} else if (warner.hasLint(LintCategory.UNCHECKED)) {
|
||||||
log.error(pos,
|
log.error(pos,
|
||||||
Errors.InstanceofReifiableNotSafe(exprType, pattType));
|
Errors.InstanceofReifiableNotSafe(exprType, pattType));
|
||||||
@ -4163,20 +4195,6 @@ public class Attr extends JCTree.Visitor {
|
|||||||
result = tree.type = tree.pattern.type;
|
result = tree.type = tree.pattern.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitGuardPattern(JCGuardPattern tree) {
|
|
||||||
attribExpr(tree.patt, env);
|
|
||||||
MatchBindings afterPattern = matchBindings;
|
|
||||||
Env<AttrContext> bodyEnv = bindingEnv(env, matchBindings.bindingsWhenTrue);
|
|
||||||
try {
|
|
||||||
attribExpr(tree.expr, bodyEnv, syms.booleanType);
|
|
||||||
} finally {
|
|
||||||
bodyEnv.info.scope.leave();
|
|
||||||
}
|
|
||||||
result = tree.type = tree.patt.type;
|
|
||||||
matchBindings = matchBindingsComputer.guardedPattern(tree, afterPattern, matchBindings);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void visitIndexed(JCArrayAccess tree) {
|
public void visitIndexed(JCArrayAccess tree) {
|
||||||
Type owntype = types.createErrorType(tree.type);
|
Type owntype = types.createErrorType(tree.type);
|
||||||
Type atype = attribExpr(tree.indexed, env);
|
Type atype = attribExpr(tree.indexed, env);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -39,7 +39,6 @@ import com.sun.tools.javac.code.Source.Feature;
|
|||||||
import com.sun.tools.javac.resources.CompilerProperties.Errors;
|
import com.sun.tools.javac.resources.CompilerProperties.Errors;
|
||||||
import com.sun.tools.javac.resources.CompilerProperties.Warnings;
|
import com.sun.tools.javac.resources.CompilerProperties.Warnings;
|
||||||
import com.sun.tools.javac.tree.*;
|
import com.sun.tools.javac.tree.*;
|
||||||
import com.sun.tools.javac.tree.TreeInfo.PatternPrimaryType;
|
|
||||||
import com.sun.tools.javac.util.*;
|
import com.sun.tools.javac.util.*;
|
||||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
||||||
import com.sun.tools.javac.util.JCDiagnostic.Error;
|
import com.sun.tools.javac.util.JCDiagnostic.Error;
|
||||||
@ -671,7 +670,9 @@ public class Flow {
|
|||||||
JCCase c = l.head;
|
JCCase c = l.head;
|
||||||
for (JCCaseLabel pat : c.labels) {
|
for (JCCaseLabel pat : c.labels) {
|
||||||
scan(pat);
|
scan(pat);
|
||||||
handleConstantCaseLabel(constants, pat);
|
if (TreeInfo.unguardedCaseLabel(pat)) {
|
||||||
|
handleConstantCaseLabel(constants, pat);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
scanStats(c.stats);
|
scanStats(c.stats);
|
||||||
if (alive != Liveness.DEAD && c.caseKind == JCCase.RULE) {
|
if (alive != Liveness.DEAD && c.caseKind == JCCase.RULE) {
|
||||||
@ -686,7 +687,7 @@ public class Flow {
|
|||||||
l.tail.head.pos(),
|
l.tail.head.pos(),
|
||||||
Warnings.PossibleFallThroughIntoCase);
|
Warnings.PossibleFallThroughIntoCase);
|
||||||
}
|
}
|
||||||
tree.isExhaustive = tree.hasTotalPattern ||
|
tree.isExhaustive = tree.hasUnconditionalPattern ||
|
||||||
TreeInfo.isErrorEnumSwitch(tree.selector, tree.cases);
|
TreeInfo.isErrorEnumSwitch(tree.selector, tree.cases);
|
||||||
if (exhaustiveSwitch) {
|
if (exhaustiveSwitch) {
|
||||||
tree.isExhaustive |= isExhaustive(tree.selector.pos(), tree.selector.type, constants);
|
tree.isExhaustive |= isExhaustive(tree.selector.pos(), tree.selector.type, constants);
|
||||||
@ -694,7 +695,7 @@ public class Flow {
|
|||||||
log.error(tree, Errors.NotExhaustiveStatement);
|
log.error(tree, Errors.NotExhaustiveStatement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!tree.hasTotalPattern) {
|
if (!tree.hasUnconditionalPattern) {
|
||||||
alive = Liveness.ALIVE;
|
alive = Liveness.ALIVE;
|
||||||
}
|
}
|
||||||
alive = alive.or(resolveBreaks(tree, prevPendingExits));
|
alive = alive.or(resolveBreaks(tree, prevPendingExits));
|
||||||
@ -712,7 +713,9 @@ public class Flow {
|
|||||||
JCCase c = l.head;
|
JCCase c = l.head;
|
||||||
for (JCCaseLabel pat : c.labels) {
|
for (JCCaseLabel pat : c.labels) {
|
||||||
scan(pat);
|
scan(pat);
|
||||||
handleConstantCaseLabel(constants, pat);
|
if (TreeInfo.unguardedCaseLabel(pat)) {
|
||||||
|
handleConstantCaseLabel(constants, pat);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
scanStats(c.stats);
|
scanStats(c.stats);
|
||||||
if (alive == Liveness.ALIVE) {
|
if (alive == Liveness.ALIVE) {
|
||||||
@ -725,7 +728,7 @@ public class Flow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tree.isExhaustive = tree.hasTotalPattern ||
|
tree.isExhaustive = tree.hasUnconditionalPattern ||
|
||||||
TreeInfo.isErrorEnumSwitch(tree.selector, tree.cases) ||
|
TreeInfo.isErrorEnumSwitch(tree.selector, tree.cases) ||
|
||||||
isExhaustive(tree.selector.pos(), tree.selector.type, constants);
|
isExhaustive(tree.selector.pos(), tree.selector.type, constants);
|
||||||
if (!tree.isExhaustive) {
|
if (!tree.isExhaustive) {
|
||||||
@ -742,11 +745,9 @@ public class Flow {
|
|||||||
if (expr.hasTag(IDENT) && ((JCIdent) expr).sym.isEnum())
|
if (expr.hasTag(IDENT) && ((JCIdent) expr).sym.isEnum())
|
||||||
constants.add(((JCIdent) expr).sym);
|
constants.add(((JCIdent) expr).sym);
|
||||||
} else if (pat.isPattern()) {
|
} else if (pat.isPattern()) {
|
||||||
PatternPrimaryType patternType = TreeInfo.primaryPatternType((JCPattern) pat);
|
Type primaryType = TreeInfo.primaryPatternType(pat);
|
||||||
|
|
||||||
if (patternType.unconditional()) {
|
constants.add(primaryType.tsym);
|
||||||
constants.add(patternType.type().tsym);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2014,6 +2015,14 @@ public class Flow {
|
|||||||
scanExpr(l.head);
|
scanExpr(l.head);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void scanPattern(JCTree tree) {
|
||||||
|
scan(tree);
|
||||||
|
if (inits.isReset()) {
|
||||||
|
inits.assign(initsWhenTrue);
|
||||||
|
uninits.assign(uninitsWhenTrue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Analyze a condition. Make sure to set (un)initsWhenTrue(WhenFalse)
|
/** Analyze a condition. Make sure to set (un)initsWhenTrue(WhenFalse)
|
||||||
* rather than (un)inits on exit.
|
* rather than (un)inits on exit.
|
||||||
*/
|
*/
|
||||||
@ -2454,11 +2463,7 @@ public class Flow {
|
|||||||
uninits.assign(uninits.andSet(uninitsSwitch));
|
uninits.assign(uninits.andSet(uninitsSwitch));
|
||||||
JCCase c = l.head;
|
JCCase c = l.head;
|
||||||
for (JCCaseLabel pat : c.labels) {
|
for (JCCaseLabel pat : c.labels) {
|
||||||
scan(pat);
|
scanPattern(pat);
|
||||||
if (inits.isReset()) {
|
|
||||||
inits.assign(initsWhenTrue);
|
|
||||||
uninits.assign(uninitsWhenTrue);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (l.head.stats.isEmpty() &&
|
if (l.head.stats.isEmpty() &&
|
||||||
l.tail.nonEmpty() &&
|
l.tail.nonEmpty() &&
|
||||||
@ -2847,8 +2852,9 @@ public class Flow {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitBindingPattern(JCBindingPattern tree) {
|
public void visitBindingPattern(JCBindingPattern tree) {
|
||||||
super.visitBindingPattern(tree);
|
scan(tree.var);
|
||||||
initParam(tree.var);
|
initParam(tree.var);
|
||||||
|
scan(tree.guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
void referenced(Symbol sym) {
|
void referenced(Symbol sym) {
|
||||||
@ -2940,7 +2946,7 @@ public class Flow {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GUARDPATTERN:
|
case BINDINGPATTERN, PARENTHESIZEDPATTERN:
|
||||||
case LAMBDA:
|
case LAMBDA:
|
||||||
if ((sym.flags() & (EFFECTIVELY_FINAL | FINAL)) == 0) {
|
if ((sym.flags() & (EFFECTIVELY_FINAL | FINAL)) == 0) {
|
||||||
reportEffectivelyFinalError(pos, sym);
|
reportEffectivelyFinalError(pos, sym);
|
||||||
@ -2964,7 +2970,7 @@ public class Flow {
|
|||||||
reportInnerClsNeedsFinalError(tree, sym);
|
reportInnerClsNeedsFinalError(tree, sym);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GUARDPATTERN:
|
case CASE:
|
||||||
case LAMBDA:
|
case LAMBDA:
|
||||||
reportEffectivelyFinalError(tree, sym);
|
reportEffectivelyFinalError(tree, sym);
|
||||||
}
|
}
|
||||||
@ -2975,7 +2981,7 @@ public class Flow {
|
|||||||
void reportEffectivelyFinalError(DiagnosticPosition pos, Symbol sym) {
|
void reportEffectivelyFinalError(DiagnosticPosition pos, Symbol sym) {
|
||||||
Fragment subKey = switch (currentTree.getTag()) {
|
Fragment subKey = switch (currentTree.getTag()) {
|
||||||
case LAMBDA -> Fragments.Lambda;
|
case LAMBDA -> Fragments.Lambda;
|
||||||
case GUARDPATTERN -> Fragments.Guard;
|
case BINDINGPATTERN, PARENTHESIZEDPATTERN -> Fragments.Guard;
|
||||||
case CLASSDEF -> Fragments.InnerCls;
|
case CLASSDEF -> Fragments.InnerCls;
|
||||||
default -> throw new AssertionError("Unexpected tree kind: " + currentTree.getTag());
|
default -> throw new AssertionError("Unexpected tree kind: " + currentTree.getTag());
|
||||||
};
|
};
|
||||||
@ -3015,12 +3021,24 @@ public class Flow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitGuardPattern(JCGuardPattern tree) {
|
public void visitBindingPattern(JCBindingPattern tree) {
|
||||||
scan(tree.patt);
|
scan(tree.var);
|
||||||
JCTree prevTree = currentTree;
|
JCTree prevTree = currentTree;
|
||||||
try {
|
try {
|
||||||
currentTree = tree;
|
currentTree = tree;
|
||||||
scan(tree.expr);
|
scan(tree.guard);
|
||||||
|
} finally {
|
||||||
|
currentTree = prevTree;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitParenthesizedPattern(JCParenthesizedPattern tree) {
|
||||||
|
scan(tree.pattern);
|
||||||
|
JCTree prevTree = currentTree;
|
||||||
|
try {
|
||||||
|
currentTree = tree;
|
||||||
|
scan(tree.guard);
|
||||||
} finally {
|
} finally {
|
||||||
currentTree = prevTree;
|
currentTree = prevTree;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -3615,20 +3615,26 @@ public class Lower extends TreeTranslator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void visitSwitch(JCSwitch tree) {
|
public void visitSwitch(JCSwitch tree) {
|
||||||
List<JCCase> cases = tree.patternSwitch ? addDefaultIfNeeded(tree.cases) : tree.cases;
|
boolean matchException = tree.patternSwitch && !tree.wasEnumSelector;
|
||||||
|
List<JCCase> cases = tree.patternSwitch ? addDefaultIfNeeded(matchException, tree.cases)
|
||||||
|
: tree.cases;
|
||||||
handleSwitch(tree, tree.selector, cases);
|
handleSwitch(tree, tree.selector, cases);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitSwitchExpression(JCSwitchExpression tree) {
|
public void visitSwitchExpression(JCSwitchExpression tree) {
|
||||||
List<JCCase> cases = addDefaultIfNeeded(tree.cases);
|
boolean matchException = tree.patternSwitch && !tree.wasEnumSelector;
|
||||||
|
List<JCCase> cases = addDefaultIfNeeded(matchException, tree.cases);
|
||||||
handleSwitch(tree, tree.selector, cases);
|
handleSwitch(tree, tree.selector, cases);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<JCCase> addDefaultIfNeeded(List<JCCase> cases) {
|
private List<JCCase> addDefaultIfNeeded(boolean matchException, List<JCCase> cases) {
|
||||||
if (cases.stream().flatMap(c -> c.labels.stream()).noneMatch(p -> p.hasTag(Tag.DEFAULTCASELABEL))) {
|
if (cases.stream().flatMap(c -> c.labels.stream()).noneMatch(p -> p.hasTag(Tag.DEFAULTCASELABEL))) {
|
||||||
JCThrow thr = make.Throw(makeNewClass(syms.incompatibleClassChangeErrorType,
|
Type exception = matchException ? syms.matchExceptionType
|
||||||
List.nil()));
|
: syms.incompatibleClassChangeErrorType;
|
||||||
|
List<JCExpression> params = matchException ? List.of(makeNull(), makeNull())
|
||||||
|
: List.nil();
|
||||||
|
JCThrow thr = make.Throw(makeNewClass(exception, params));
|
||||||
JCCase c = make.Case(JCCase.STATEMENT, List.of(make.DefaultCaseLabel()), List.of(thr), null);
|
JCCase c = make.Case(JCCase.STATEMENT, List.of(make.DefaultCaseLabel()), List.of(thr), null);
|
||||||
cases = cases.prepend(c);
|
cases = cases.prepend(c);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -29,7 +29,7 @@ import com.sun.tools.javac.code.Symbol;
|
|||||||
import com.sun.tools.javac.code.Symbol.BindingSymbol;
|
import com.sun.tools.javac.code.Symbol.BindingSymbol;
|
||||||
import com.sun.tools.javac.resources.CompilerProperties.Errors;
|
import com.sun.tools.javac.resources.CompilerProperties.Errors;
|
||||||
import com.sun.tools.javac.tree.JCTree;
|
import com.sun.tools.javac.tree.JCTree;
|
||||||
import com.sun.tools.javac.tree.JCTree.JCGuardPattern;
|
import com.sun.tools.javac.tree.JCTree.JCCase;
|
||||||
import com.sun.tools.javac.tree.JCTree.Tag;
|
import com.sun.tools.javac.tree.JCTree.Tag;
|
||||||
import com.sun.tools.javac.tree.TreeScanner;
|
import com.sun.tools.javac.tree.TreeScanner;
|
||||||
import com.sun.tools.javac.util.Context;
|
import com.sun.tools.javac.util.Context;
|
||||||
@ -112,7 +112,7 @@ public class MatchBindingsComputer extends TreeScanner {
|
|||||||
return EMPTY;
|
return EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MatchBindings guardedPattern(JCGuardPattern tree, MatchBindings patternBindings, MatchBindings guardBindings) {
|
public MatchBindings caseGuard(JCCase tree, MatchBindings patternBindings, MatchBindings guardBindings) {
|
||||||
return andOperation(tree.pos(), patternBindings, guardBindings);
|
return andOperation(tree.pos(), patternBindings, guardBindings);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +142,7 @@ public class MatchBindingsComputer extends TreeScanner {
|
|||||||
public MatchBindings finishBindings(JCTree tree, MatchBindings matchBindings) {
|
public MatchBindings finishBindings(JCTree tree, MatchBindings matchBindings) {
|
||||||
switch (tree.getTag()) {
|
switch (tree.getTag()) {
|
||||||
case NOT: case AND: case OR: case BINDINGPATTERN:
|
case NOT: case AND: case OR: case BINDINGPATTERN:
|
||||||
case PARENTHESIZEDPATTERN: case GUARDPATTERN:
|
case PARENTHESIZEDPATTERN:
|
||||||
case PARENS: case TYPETEST:
|
case PARENS: case TYPETEST:
|
||||||
case CONDEXPR: //error recovery:
|
case CONDEXPR: //error recovery:
|
||||||
return matchBindings;
|
return matchBindings;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -85,7 +85,6 @@ import com.sun.tools.javac.tree.JCTree.JCClassDecl;
|
|||||||
import com.sun.tools.javac.tree.JCTree.JCContinue;
|
import com.sun.tools.javac.tree.JCTree.JCContinue;
|
||||||
import com.sun.tools.javac.tree.JCTree.JCDoWhileLoop;
|
import com.sun.tools.javac.tree.JCTree.JCDoWhileLoop;
|
||||||
import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
|
import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
|
||||||
import com.sun.tools.javac.tree.JCTree.JCGuardPattern;
|
|
||||||
import com.sun.tools.javac.tree.JCTree.JCLambda;
|
import com.sun.tools.javac.tree.JCTree.JCLambda;
|
||||||
import com.sun.tools.javac.tree.JCTree.JCParenthesizedPattern;
|
import com.sun.tools.javac.tree.JCTree.JCParenthesizedPattern;
|
||||||
import com.sun.tools.javac.tree.JCTree.JCPattern;
|
import com.sun.tools.javac.tree.JCTree.JCPattern;
|
||||||
@ -255,27 +254,22 @@ public class TransPatterns extends TreeTranslator {
|
|||||||
result = translate(tree.pattern);
|
result = translate(tree.pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitGuardPattern(JCGuardPattern tree) {
|
|
||||||
JCExpression pattern = (JCExpression) this.<JCTree>translate(tree.patt);
|
|
||||||
JCExpression guard = translate(tree.expr);
|
|
||||||
result = makeBinary(Tag.AND, pattern, guard);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitSwitch(JCSwitch tree) {
|
public void visitSwitch(JCSwitch tree) {
|
||||||
handleSwitch(tree, tree.selector, tree.cases, tree.hasTotalPattern, tree.patternSwitch);
|
handleSwitch(tree, tree.selector, tree.cases,
|
||||||
|
tree.hasUnconditionalPattern, tree.patternSwitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitSwitchExpression(JCSwitchExpression tree) {
|
public void visitSwitchExpression(JCSwitchExpression tree) {
|
||||||
handleSwitch(tree, tree.selector, tree.cases, tree.hasTotalPattern, tree.patternSwitch);
|
handleSwitch(tree, tree.selector, tree.cases,
|
||||||
|
tree.hasUnconditionalPattern, tree.patternSwitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSwitch(JCTree tree,
|
private void handleSwitch(JCTree tree,
|
||||||
JCExpression selector,
|
JCExpression selector,
|
||||||
List<JCCase> cases,
|
List<JCCase> cases,
|
||||||
boolean hasTotalPattern,
|
boolean hasUnconditionalPattern,
|
||||||
boolean patternSwitch) {
|
boolean patternSwitch) {
|
||||||
if (patternSwitch) {
|
if (patternSwitch) {
|
||||||
Type seltype = selector.type.hasTag(BOT)
|
Type seltype = selector.type.hasTag(BOT)
|
||||||
@ -340,12 +334,6 @@ public class TransPatterns extends TreeTranslator {
|
|||||||
|
|
||||||
JCCase lastCase = cases.last();
|
JCCase lastCase = cases.last();
|
||||||
|
|
||||||
if (hasTotalPattern && !hasNullCase) {
|
|
||||||
if (cases.stream().flatMap(c -> c.labels.stream()).noneMatch(l -> l.hasTag(Tag.DEFAULTCASELABEL))) {
|
|
||||||
lastCase.labels = lastCase.labels.prepend(makeLit(syms.botType, null));
|
|
||||||
hasNullCase = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
selector = translate(selector);
|
selector = translate(selector);
|
||||||
boolean needsNullCheck = !hasNullCase && !seltype.isPrimitive();
|
boolean needsNullCheck = !hasNullCase && !seltype.isPrimitive();
|
||||||
statements.append(make.at(tree.pos).VarDef(temp, needsNullCheck ? attr.makeNullCheck(selector)
|
statements.append(make.at(tree.pos).VarDef(temp, needsNullCheck ? attr.makeNullCheck(selector)
|
||||||
@ -415,6 +403,9 @@ public class TransPatterns extends TreeTranslator {
|
|||||||
try {
|
try {
|
||||||
currentValue = temp;
|
currentValue = temp;
|
||||||
JCExpression test = (JCExpression) this.<JCTree>translate(p);
|
JCExpression test = (JCExpression) this.<JCTree>translate(p);
|
||||||
|
if (((JCPattern) p).guard != null) {
|
||||||
|
test = makeBinary(Tag.AND, test, translate(((JCPattern) p).guard));
|
||||||
|
}
|
||||||
c.stats = translate(c.stats);
|
c.stats = translate(c.stats);
|
||||||
JCContinue continueSwitch = make.at(clearedPatterns.head.pos()).Continue(null);
|
JCContinue continueSwitch = make.at(clearedPatterns.head.pos()).Continue(null);
|
||||||
continueSwitch.target = tree;
|
continueSwitch.target = tree;
|
||||||
@ -437,10 +428,11 @@ public class TransPatterns extends TreeTranslator {
|
|||||||
if (p.hasTag(Tag.DEFAULTCASELABEL)) {
|
if (p.hasTag(Tag.DEFAULTCASELABEL)) {
|
||||||
translatedLabels.add(p);
|
translatedLabels.add(p);
|
||||||
hasDefault = true;
|
hasDefault = true;
|
||||||
} else if (hasTotalPattern && !hasDefault &&
|
} else if (hasUnconditionalPattern && !hasDefault &&
|
||||||
c == lastCase && p.isPattern()) {
|
c == lastCase && p.isPattern()) {
|
||||||
//If the switch has total pattern, the last case will contain it.
|
//If the switch has unconditional pattern,
|
||||||
//Convert the total pattern to default:
|
//the last case will contain it.
|
||||||
|
//Convert the unconditional pattern to default:
|
||||||
translatedLabels.add(make.DefaultCaseLabel());
|
translatedLabels.add(make.DefaultCaseLabel());
|
||||||
} else {
|
} else {
|
||||||
int value;
|
int value;
|
||||||
@ -466,11 +458,13 @@ public class TransPatterns extends TreeTranslator {
|
|||||||
if (tree.hasTag(Tag.SWITCH)) {
|
if (tree.hasTag(Tag.SWITCH)) {
|
||||||
((JCSwitch) tree).selector = selector;
|
((JCSwitch) tree).selector = selector;
|
||||||
((JCSwitch) tree).cases = cases;
|
((JCSwitch) tree).cases = cases;
|
||||||
|
((JCSwitch) tree).wasEnumSelector = enumSelector;
|
||||||
statements.append((JCSwitch) tree);
|
statements.append((JCSwitch) tree);
|
||||||
result = make.Block(0, statements.toList());
|
result = make.Block(0, statements.toList());
|
||||||
} else {
|
} else {
|
||||||
((JCSwitchExpression) tree).selector = selector;
|
((JCSwitchExpression) tree).selector = selector;
|
||||||
((JCSwitchExpression) tree).cases = cases;
|
((JCSwitchExpression) tree).cases = cases;
|
||||||
|
((JCSwitchExpression) tree).wasEnumSelector = enumSelector;
|
||||||
LetExpr r = (LetExpr) make.LetExpr(statements.toList(), (JCSwitchExpression) tree)
|
LetExpr r = (LetExpr) make.LetExpr(statements.toList(), (JCSwitchExpression) tree)
|
||||||
.setType(tree.type);
|
.setType(tree.type);
|
||||||
|
|
||||||
@ -486,13 +480,13 @@ public class TransPatterns extends TreeTranslator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Type principalType(JCPattern p) {
|
private Type principalType(JCTree p) {
|
||||||
return types.boxedTypeOrType(types.erasure(TreeInfo.primaryPatternType(p).type()));
|
return types.boxedTypeOrType(types.erasure(TreeInfo.primaryPatternType(p)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private LoadableConstant toLoadableConstant(JCCaseLabel l, Type selector) {
|
private LoadableConstant toLoadableConstant(JCCaseLabel l, Type selector) {
|
||||||
if (l.isPattern()) {
|
if (l.isPattern()) {
|
||||||
Type principalType = principalType((JCPattern) l);
|
Type principalType = principalType(l);
|
||||||
if (types.isSubtype(selector, principalType)) {
|
if (types.isSubtype(selector, principalType)) {
|
||||||
return (LoadableConstant) selector;
|
return (LoadableConstant) selector;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -565,6 +565,7 @@ public class TransTypes extends TreeTranslator {
|
|||||||
|
|
||||||
public void visitBindingPattern(JCBindingPattern tree) {
|
public void visitBindingPattern(JCBindingPattern tree) {
|
||||||
tree.var = translate(tree.var, null);
|
tree.var = translate(tree.var, null);
|
||||||
|
tree.guard = translate(tree.guard, syms.booleanType);
|
||||||
result = tree;
|
result = tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -582,13 +583,7 @@ public class TransTypes extends TreeTranslator {
|
|||||||
@Override
|
@Override
|
||||||
public void visitParenthesizedPattern(JCParenthesizedPattern tree) {
|
public void visitParenthesizedPattern(JCParenthesizedPattern tree) {
|
||||||
tree.pattern = translate(tree.pattern, null);
|
tree.pattern = translate(tree.pattern, null);
|
||||||
result = tree;
|
tree.guard = translate(tree.guard, syms.booleanType);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitGuardPattern(JCGuardPattern tree) {
|
|
||||||
tree.patt = translate(tree.patt, null);
|
|
||||||
tree.expr = translate(tree.expr, syms.booleanType);
|
|
||||||
result = tree;
|
result = tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -763,12 +763,12 @@ public class JavacParser implements Parser {
|
|||||||
/** parses patterns.
|
/** parses patterns.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public JCPattern parsePattern(int pos, JCModifiers mods, JCExpression parsedType, boolean inInstanceOf) {
|
public JCPattern parsePattern(int pos, JCModifiers mods, JCExpression parsedType) {
|
||||||
JCPattern pattern;
|
JCPattern pattern;
|
||||||
if (token.kind == LPAREN && parsedType == null) {
|
if (token.kind == LPAREN && parsedType == null) {
|
||||||
int startPos = token.pos;
|
int startPos = token.pos;
|
||||||
accept(LPAREN);
|
accept(LPAREN);
|
||||||
JCPattern p = parsePattern(token.pos, null, null, false);
|
JCPattern p = parsePattern(token.pos, null, null);
|
||||||
accept(RPAREN);
|
accept(RPAREN);
|
||||||
pattern = toP(F.at(startPos).ParenthesizedPattern(p));
|
pattern = toP(F.at(startPos).ParenthesizedPattern(p));
|
||||||
} else {
|
} else {
|
||||||
@ -777,12 +777,6 @@ public class JavacParser implements Parser {
|
|||||||
JCVariableDecl var = toP(F.at(token.pos).VarDef(mods, ident(), e, null));
|
JCVariableDecl var = toP(F.at(token.pos).VarDef(mods, ident(), e, null));
|
||||||
pattern = toP(F.at(pos).BindingPattern(var));
|
pattern = toP(F.at(pos).BindingPattern(var));
|
||||||
}
|
}
|
||||||
if (!inInstanceOf && token.kind == AMPAMP) {
|
|
||||||
checkSourceLevel(Feature.PATTERN_SWITCH);
|
|
||||||
nextToken();
|
|
||||||
JCExpression guard = term(EXPR | NOLAMBDA);
|
|
||||||
pattern = F.at(pos).GuardPattern(pattern, guard);
|
|
||||||
}
|
|
||||||
return pattern;
|
return pattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -967,7 +961,7 @@ public class JavacParser implements Parser {
|
|||||||
JCTree pattern;
|
JCTree pattern;
|
||||||
if (token.kind == LPAREN) {
|
if (token.kind == LPAREN) {
|
||||||
checkSourceLevel(token.pos, Feature.PATTERN_SWITCH);
|
checkSourceLevel(token.pos, Feature.PATTERN_SWITCH);
|
||||||
pattern = parsePattern(token.pos, null, null, true);
|
pattern = parsePattern(token.pos, null, null);
|
||||||
} else {
|
} else {
|
||||||
int patternPos = token.pos;
|
int patternPos = token.pos;
|
||||||
JCModifiers mods = optFinal(0);
|
JCModifiers mods = optFinal(0);
|
||||||
@ -975,7 +969,7 @@ public class JavacParser implements Parser {
|
|||||||
JCExpression type = unannotatedType(false);
|
JCExpression type = unannotatedType(false);
|
||||||
if (token.kind == IDENTIFIER) {
|
if (token.kind == IDENTIFIER) {
|
||||||
checkSourceLevel(token.pos, Feature.PATTERN_MATCHING_IN_INSTANCEOF);
|
checkSourceLevel(token.pos, Feature.PATTERN_MATCHING_IN_INSTANCEOF);
|
||||||
pattern = parsePattern(patternPos, mods, type, true);
|
pattern = parsePattern(patternPos, mods, type);
|
||||||
} else {
|
} else {
|
||||||
checkNoMods(typePos, mods.flags & ~Flags.DEPRECATED);
|
checkNoMods(typePos, mods.flags & ~Flags.DEPRECATED);
|
||||||
if (mods.annotations.nonEmpty()) {
|
if (mods.annotations.nonEmpty()) {
|
||||||
@ -3076,7 +3070,12 @@ public class JavacParser implements Parser {
|
|||||||
analyzePattern(lookahead) == PatternResult.PATTERN;
|
analyzePattern(lookahead) == PatternResult.PATTERN;
|
||||||
if (pattern) {
|
if (pattern) {
|
||||||
checkSourceLevel(token.pos, Feature.PATTERN_SWITCH);
|
checkSourceLevel(token.pos, Feature.PATTERN_SWITCH);
|
||||||
return parsePattern(patternPos, mods, null, false);
|
JCPattern p = parsePattern(patternPos, mods, null);
|
||||||
|
if (token.kind == IDENTIFIER && token.name() == names.when) {
|
||||||
|
nextToken();
|
||||||
|
p.guard = term(EXPR | NOLAMBDA);
|
||||||
|
}
|
||||||
|
return p;
|
||||||
} else {
|
} else {
|
||||||
return term(EXPR | NOLAMBDA);
|
return term(EXPR | NOLAMBDA);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
|
# Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# This code is free software; you can redistribute it and/or modify it
|
||||||
@ -506,11 +506,11 @@ compiler.err.pattern.dominated=\
|
|||||||
compiler.err.duplicate.default.label=\
|
compiler.err.duplicate.default.label=\
|
||||||
duplicate default label
|
duplicate default label
|
||||||
|
|
||||||
compiler.err.duplicate.total.pattern=\
|
compiler.err.duplicate.unconditional.pattern=\
|
||||||
duplicate total pattern
|
duplicate unconditional pattern
|
||||||
|
|
||||||
compiler.err.total.pattern.and.default=\
|
compiler.err.unconditional.pattern.and.default=\
|
||||||
switch has both a total pattern and a default label
|
switch has both an unconditional pattern and a default label
|
||||||
|
|
||||||
# 0: type, 1: type
|
# 0: type, 1: type
|
||||||
compiler.err.constant.label.not.compatible=\
|
compiler.err.constant.label.not.compatible=\
|
||||||
@ -2518,6 +2518,10 @@ compiler.warn.prob.found.req=\
|
|||||||
compiler.misc.inconvertible.types=\
|
compiler.misc.inconvertible.types=\
|
||||||
{0} cannot be converted to {1}
|
{0} cannot be converted to {1}
|
||||||
|
|
||||||
|
# 0: type, 1: type
|
||||||
|
compiler.misc.not.applicable.types=\
|
||||||
|
pattern of type {1} is not applicable at {0}
|
||||||
|
|
||||||
# 0: type, 1: type
|
# 0: type, 1: type
|
||||||
compiler.misc.possible.loss.of.precision=\
|
compiler.misc.possible.loss.of.precision=\
|
||||||
possible lossy conversion from {0} to {1}
|
possible lossy conversion from {0} to {1}
|
||||||
@ -3082,6 +3086,9 @@ compiler.misc.feature.case.null=\
|
|||||||
compiler.misc.feature.pattern.switch=\
|
compiler.misc.feature.pattern.switch=\
|
||||||
patterns in switch statements
|
patterns in switch statements
|
||||||
|
|
||||||
|
compiler.misc.feature.unconditional.patterns.in.instanceof=\
|
||||||
|
unconditional patterns in instanceof
|
||||||
|
|
||||||
compiler.warn.underscore.as.identifier=\
|
compiler.warn.underscore.as.identifier=\
|
||||||
as of release 9, ''_'' is a keyword, and may not be used as an identifier
|
as of release 9, ''_'' is a keyword, and may not be used as an identifier
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -241,7 +241,6 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
|||||||
*/
|
*/
|
||||||
BINDINGPATTERN,
|
BINDINGPATTERN,
|
||||||
DEFAULTCASELABEL,
|
DEFAULTCASELABEL,
|
||||||
GUARDPATTERN,
|
|
||||||
PARENTHESIZEDPATTERN,
|
PARENTHESIZEDPATTERN,
|
||||||
|
|
||||||
/** Indexed array expressions, of type Indexed.
|
/** Indexed array expressions, of type Indexed.
|
||||||
@ -1284,9 +1283,10 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
|||||||
public List<JCCase> cases;
|
public List<JCCase> cases;
|
||||||
/** Position of closing brace, optional. */
|
/** Position of closing brace, optional. */
|
||||||
public int endpos = Position.NOPOS;
|
public int endpos = Position.NOPOS;
|
||||||
public boolean hasTotalPattern;
|
public boolean hasUnconditionalPattern;
|
||||||
public boolean isExhaustive;
|
public boolean isExhaustive;
|
||||||
public boolean patternSwitch;
|
public boolean patternSwitch;
|
||||||
|
public boolean wasEnumSelector;
|
||||||
protected JCSwitch(JCExpression selector, List<JCCase> cases) {
|
protected JCSwitch(JCExpression selector, List<JCCase> cases) {
|
||||||
this.selector = selector;
|
this.selector = selector;
|
||||||
this.cases = cases;
|
this.cases = cases;
|
||||||
@ -1371,9 +1371,10 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
|||||||
public List<JCCase> cases;
|
public List<JCCase> cases;
|
||||||
/** Position of closing brace, optional. */
|
/** Position of closing brace, optional. */
|
||||||
public int endpos = Position.NOPOS;
|
public int endpos = Position.NOPOS;
|
||||||
public boolean hasTotalPattern;
|
public boolean hasUnconditionalPattern;
|
||||||
public boolean isExhaustive;
|
public boolean isExhaustive;
|
||||||
public boolean patternSwitch;
|
public boolean patternSwitch;
|
||||||
|
public boolean wasEnumSelector;
|
||||||
protected JCSwitchExpression(JCExpression selector, List<JCCase> cases) {
|
protected JCSwitchExpression(JCExpression selector, List<JCCase> cases) {
|
||||||
this.selector = selector;
|
this.selector = selector;
|
||||||
this.cases = cases;
|
this.cases = cases;
|
||||||
@ -2243,6 +2244,11 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
|||||||
public abstract static class JCPattern extends JCCaseLabel
|
public abstract static class JCPattern extends JCCaseLabel
|
||||||
implements PatternTree {
|
implements PatternTree {
|
||||||
|
|
||||||
|
public JCExpression guard;
|
||||||
|
|
||||||
|
@Override @DefinedBy(Api.COMPILER_TREE)
|
||||||
|
public JCExpression getGuard() { return guard; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isExpression() {
|
public boolean isExpression() {
|
||||||
return false;
|
return false;
|
||||||
@ -2362,48 +2368,6 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class JCGuardPattern extends JCPattern
|
|
||||||
implements GuardedPatternTree {
|
|
||||||
public JCPattern patt;
|
|
||||||
public JCExpression expr;
|
|
||||||
|
|
||||||
public JCGuardPattern(JCPattern patt, JCExpression expr) {
|
|
||||||
this.patt = patt;
|
|
||||||
this.expr = expr;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override @DefinedBy(Api.COMPILER_TREE)
|
|
||||||
public PatternTree getPattern() {
|
|
||||||
return patt;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override @DefinedBy(Api.COMPILER_TREE)
|
|
||||||
public ExpressionTree getExpression() {
|
|
||||||
return expr;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void accept(Visitor v) {
|
|
||||||
v.visitGuardPattern(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@DefinedBy(Api.COMPILER_TREE)
|
|
||||||
public Kind getKind() {
|
|
||||||
return Kind.GUARDED_PATTERN;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@DefinedBy(Api.COMPILER_TREE)
|
|
||||||
public <R, D> R accept(TreeVisitor<R, D> v, D d) {
|
|
||||||
return v.visitGuardedPattern(this, d);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Tag getTag() {
|
|
||||||
return Tag.GUARDPATTERN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An array selection
|
* An array selection
|
||||||
*/
|
*/
|
||||||
@ -3446,7 +3410,6 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
|||||||
public void visitBindingPattern(JCBindingPattern that) { visitTree(that); }
|
public void visitBindingPattern(JCBindingPattern that) { visitTree(that); }
|
||||||
public void visitDefaultCaseLabel(JCDefaultCaseLabel that) { visitTree(that); }
|
public void visitDefaultCaseLabel(JCDefaultCaseLabel that) { visitTree(that); }
|
||||||
public void visitParenthesizedPattern(JCParenthesizedPattern that) { visitTree(that); }
|
public void visitParenthesizedPattern(JCParenthesizedPattern that) { visitTree(that); }
|
||||||
public void visitGuardPattern(JCGuardPattern that) { visitTree(that); }
|
|
||||||
public void visitIndexed(JCArrayAccess that) { visitTree(that); }
|
public void visitIndexed(JCArrayAccess that) { visitTree(that); }
|
||||||
public void visitSelect(JCFieldAccess that) { visitTree(that); }
|
public void visitSelect(JCFieldAccess that) { visitTree(that); }
|
||||||
public void visitReference(JCMemberReference that) { visitTree(that); }
|
public void visitReference(JCMemberReference that) { visitTree(that); }
|
||||||
|
@ -900,6 +900,10 @@ public class Pretty extends JCTree.Visitor {
|
|||||||
public void visitBindingPattern(JCBindingPattern patt) {
|
public void visitBindingPattern(JCBindingPattern patt) {
|
||||||
try {
|
try {
|
||||||
printExpr(patt.var);
|
printExpr(patt.var);
|
||||||
|
if (patt.guard != null) {
|
||||||
|
print(" when ");
|
||||||
|
printExpr(patt.guard);
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new UncheckedIOException(e);
|
throw new UncheckedIOException(e);
|
||||||
}
|
}
|
||||||
@ -911,17 +915,10 @@ public class Pretty extends JCTree.Visitor {
|
|||||||
print("(");
|
print("(");
|
||||||
printExpr(patt.pattern);
|
printExpr(patt.pattern);
|
||||||
print(")");
|
print(")");
|
||||||
} catch (IOException e) {
|
if (patt.guard != null) {
|
||||||
throw new UncheckedIOException(e);
|
print(" when ");
|
||||||
}
|
printExpr(patt.guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitGuardPattern(JCGuardPattern patt) {
|
|
||||||
try {
|
|
||||||
printExpr(patt.patt);
|
|
||||||
print(" && ");
|
|
||||||
printExpr(patt.expr);
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new UncheckedIOException(e);
|
throw new UncheckedIOException(e);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -494,22 +494,20 @@ public class TreeCopier<P> implements TreeVisitor<JCTree,P> {
|
|||||||
public JCTree visitBindingPattern(BindingPatternTree node, P p) {
|
public JCTree visitBindingPattern(BindingPatternTree node, P p) {
|
||||||
JCBindingPattern t = (JCBindingPattern) node;
|
JCBindingPattern t = (JCBindingPattern) node;
|
||||||
JCVariableDecl var = copy(t.var, p);
|
JCVariableDecl var = copy(t.var, p);
|
||||||
return M.at(t.pos).BindingPattern(var);
|
JCExpression guard = copy(t.guard, p);
|
||||||
}
|
JCPattern pat = M.at(t.pos).BindingPattern(var);
|
||||||
|
pat.guard = guard;
|
||||||
@DefinedBy(Api.COMPILER_TREE)
|
return pat;
|
||||||
public JCTree visitGuardedPattern(GuardedPatternTree node, P p) {
|
|
||||||
JCGuardPattern t = (JCGuardPattern) node;
|
|
||||||
JCPattern patt = copy(t.patt, p);
|
|
||||||
JCExpression expr = copy(t.expr, p);
|
|
||||||
return M.at(t.pos).GuardPattern(patt, expr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@DefinedBy(Api.COMPILER_TREE)
|
@DefinedBy(Api.COMPILER_TREE)
|
||||||
public JCTree visitParenthesizedPattern(ParenthesizedPatternTree node, P p) {
|
public JCTree visitParenthesizedPattern(ParenthesizedPatternTree node, P p) {
|
||||||
JCParenthesizedPattern t = (JCParenthesizedPattern) node;
|
JCParenthesizedPattern t = (JCParenthesizedPattern) node;
|
||||||
JCPattern pattern = copy(t.pattern, p);
|
JCPattern pattern = copy(t.pattern, p);
|
||||||
return M.at(t.pos).ParenthesizedPattern(pattern);
|
JCExpression guard = copy(t.guard, p);
|
||||||
|
JCPattern pat = M.at(t.pos).ParenthesizedPattern(pattern);
|
||||||
|
pat.guard = guard;
|
||||||
|
return pat;
|
||||||
}
|
}
|
||||||
|
|
||||||
@DefinedBy(Api.COMPILER_TREE)
|
@DefinedBy(Api.COMPILER_TREE)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -542,10 +542,6 @@ public class TreeInfo {
|
|||||||
JCBindingPattern node = (JCBindingPattern)tree;
|
JCBindingPattern node = (JCBindingPattern)tree;
|
||||||
return getStartPos(node.var);
|
return getStartPos(node.var);
|
||||||
}
|
}
|
||||||
case GUARDPATTERN: {
|
|
||||||
JCGuardPattern node = (JCGuardPattern) tree;
|
|
||||||
return getStartPos(node.patt);
|
|
||||||
}
|
|
||||||
case ERRONEOUS: {
|
case ERRONEOUS: {
|
||||||
JCErroneous node = (JCErroneous)tree;
|
JCErroneous node = (JCErroneous)tree;
|
||||||
if (node.errs != null && node.errs.nonEmpty()) {
|
if (node.errs != null && node.errs.nonEmpty()) {
|
||||||
@ -644,10 +640,6 @@ public class TreeInfo {
|
|||||||
JCParenthesizedPattern node = (JCParenthesizedPattern) tree;
|
JCParenthesizedPattern node = (JCParenthesizedPattern) tree;
|
||||||
return getEndPos(node.pattern, endPosTable);
|
return getEndPos(node.pattern, endPosTable);
|
||||||
}
|
}
|
||||||
case GUARDPATTERN: {
|
|
||||||
JCGuardPattern node = (JCGuardPattern) tree;
|
|
||||||
return getEndPos(node.expr, endPosTable);
|
|
||||||
}
|
|
||||||
case ERRONEOUS: {
|
case ERRONEOUS: {
|
||||||
JCErroneous node = (JCErroneous)tree;
|
JCErroneous node = (JCErroneous)tree;
|
||||||
if (node.errs != null && node.errs.nonEmpty())
|
if (node.errs != null && node.errs.nonEmpty())
|
||||||
@ -1314,42 +1306,40 @@ public class TreeInfo {
|
|||||||
.allMatch(p -> p.hasTag(IDENT));
|
.allMatch(p -> p.hasTag(IDENT));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PatternPrimaryType primaryPatternType(JCPattern pat) {
|
public static Type primaryPatternType(JCTree pat) {
|
||||||
return switch (pat.getTag()) {
|
return switch (pat.getTag()) {
|
||||||
case BINDINGPATTERN -> new PatternPrimaryType(((JCBindingPattern) pat).type, true);
|
case BINDINGPATTERN -> pat.type;
|
||||||
case GUARDPATTERN -> {
|
|
||||||
JCGuardPattern guarded = (JCGuardPattern) pat;
|
|
||||||
PatternPrimaryType nested = primaryPatternType(guarded.patt);
|
|
||||||
boolean unconditional = nested.unconditional();
|
|
||||||
if (guarded.expr.type.hasTag(BOOLEAN) && unconditional) {
|
|
||||||
unconditional = false;
|
|
||||||
var constValue = guarded.expr.type.constValue();
|
|
||||||
if (constValue != null && ((int) constValue) == 1) {
|
|
||||||
unconditional = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
yield new PatternPrimaryType(nested.type(), unconditional);
|
|
||||||
}
|
|
||||||
case PARENTHESIZEDPATTERN -> primaryPatternType(((JCParenthesizedPattern) pat).pattern);
|
case PARENTHESIZEDPATTERN -> primaryPatternType(((JCParenthesizedPattern) pat).pattern);
|
||||||
default -> throw new AssertionError();
|
default -> throw new AssertionError();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static JCBindingPattern primaryPatternTree(JCPattern pat) {
|
public static JCBindingPattern primaryPatternTree(JCTree pat) {
|
||||||
return switch (pat.getTag()) {
|
return switch (pat.getTag()) {
|
||||||
case BINDINGPATTERN -> (JCBindingPattern) pat;
|
case BINDINGPATTERN -> (JCBindingPattern) pat;
|
||||||
case GUARDPATTERN -> primaryPatternTree(((JCGuardPattern) pat).patt);
|
|
||||||
case PARENTHESIZEDPATTERN -> primaryPatternTree(((JCParenthesizedPattern) pat).pattern);
|
case PARENTHESIZEDPATTERN -> primaryPatternTree(((JCParenthesizedPattern) pat).pattern);
|
||||||
default -> throw new AssertionError();
|
default -> throw new AssertionError();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public record PatternPrimaryType(Type type, boolean unconditional) {}
|
|
||||||
|
|
||||||
public static boolean expectedExhaustive(JCSwitch tree) {
|
public static boolean expectedExhaustive(JCSwitch tree) {
|
||||||
return tree.patternSwitch ||
|
return tree.patternSwitch ||
|
||||||
tree.cases.stream()
|
tree.cases.stream()
|
||||||
.flatMap(c -> c.labels.stream())
|
.flatMap(c -> c.labels.stream())
|
||||||
.anyMatch(l -> TreeInfo.isNull(l));
|
.anyMatch(l -> TreeInfo.isNull(l));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean unguardedCaseLabel(JCCaseLabel cse) {
|
||||||
|
if (!cse.isPattern()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
JCExpression guard = ((JCPattern) cse).guard;
|
||||||
|
if (guard == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
var constValue = guard.type.constValue();
|
||||||
|
return constValue != null &&
|
||||||
|
guard.type.hasTag(BOOLEAN) &&
|
||||||
|
((int) constValue) == 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -500,12 +500,6 @@ public class TreeMaker implements JCTree.Factory {
|
|||||||
return tree;
|
return tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JCGuardPattern GuardPattern(JCPattern guardedPattern, JCExpression expr) {
|
|
||||||
JCGuardPattern tree = new JCGuardPattern(guardedPattern, expr);
|
|
||||||
tree.pos = pos;
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JCArrayAccess Indexed(JCExpression indexed, JCExpression index) {
|
public JCArrayAccess Indexed(JCExpression indexed, JCExpression index) {
|
||||||
JCArrayAccess tree = new JCArrayAccess(indexed, index);
|
JCArrayAccess tree = new JCArrayAccess(indexed, index);
|
||||||
tree.pos = pos;
|
tree.pos = pos;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -305,6 +305,7 @@ public class TreeScanner extends Visitor {
|
|||||||
|
|
||||||
public void visitBindingPattern(JCBindingPattern tree) {
|
public void visitBindingPattern(JCBindingPattern tree) {
|
||||||
scan(tree.var);
|
scan(tree.var);
|
||||||
|
scan(tree.guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -312,14 +313,9 @@ public class TreeScanner extends Visitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitParenthesizedPattern(JCParenthesizedPattern that) {
|
public void visitParenthesizedPattern(JCParenthesizedPattern tree) {
|
||||||
scan(that.pattern);
|
scan(tree.pattern);
|
||||||
}
|
scan(tree.guard);
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitGuardPattern(JCGuardPattern that) {
|
|
||||||
scan(that.patt);
|
|
||||||
scan(that.expr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visitIndexed(JCArrayAccess tree) {
|
public void visitIndexed(JCArrayAccess tree) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -360,6 +360,7 @@ public class TreeTranslator extends JCTree.Visitor {
|
|||||||
|
|
||||||
public void visitBindingPattern(JCBindingPattern tree) {
|
public void visitBindingPattern(JCBindingPattern tree) {
|
||||||
tree.var = translate(tree.var);
|
tree.var = translate(tree.var);
|
||||||
|
tree.guard = translate(tree.guard);
|
||||||
result = tree;
|
result = tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,13 +372,7 @@ public class TreeTranslator extends JCTree.Visitor {
|
|||||||
@Override
|
@Override
|
||||||
public void visitParenthesizedPattern(JCParenthesizedPattern tree) {
|
public void visitParenthesizedPattern(JCParenthesizedPattern tree) {
|
||||||
tree.pattern = translate(tree.pattern);
|
tree.pattern = translate(tree.pattern);
|
||||||
result = tree;
|
tree.guard = translate(tree.guard);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitGuardPattern(JCGuardPattern tree) {
|
|
||||||
tree.patt = translate(tree.patt);
|
|
||||||
tree.expr = translate(tree.expr);
|
|
||||||
result = tree;
|
result = tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -69,6 +69,7 @@ public class Names {
|
|||||||
public final Name transitive;
|
public final Name transitive;
|
||||||
public final Name uses;
|
public final Name uses;
|
||||||
public final Name open;
|
public final Name open;
|
||||||
|
public final Name when;
|
||||||
public final Name with;
|
public final Name with;
|
||||||
public final Name yield;
|
public final Name yield;
|
||||||
|
|
||||||
@ -248,6 +249,7 @@ public class Names {
|
|||||||
transitive = fromString("transitive");
|
transitive = fromString("transitive");
|
||||||
uses = fromString("uses");
|
uses = fromString("uses");
|
||||||
open = fromString("open");
|
open = fromString("open");
|
||||||
|
when = fromString("when");
|
||||||
with = fromString("with");
|
with = fromString("with");
|
||||||
yield = fromString("yield");
|
yield = fromString("yield");
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ public class RuleSwitchBreaks extends LineNumberTestBase {
|
|||||||
public class TestGuards { // 1
|
public class TestGuards { // 1
|
||||||
private void test(Object o) { // 2
|
private void test(Object o) { // 2
|
||||||
switch (o) { // 3
|
switch (o) { // 3
|
||||||
case String s && s.isEmpty() -> // 4
|
case String s when s.isEmpty() -> // 4
|
||||||
System.out.println("a"); // 5
|
System.out.println("a"); // 5
|
||||||
case String s -> // 6
|
case String s -> // 6
|
||||||
System.out.println("a"); // 7
|
System.out.println("a"); // 7
|
||||||
|
@ -48,7 +48,7 @@ class CantRefNonEffectivelyFinalVar {
|
|||||||
|
|
||||||
void test3(Object o, int i) {
|
void test3(Object o, int i) {
|
||||||
switch (o) {
|
switch (o) {
|
||||||
case String s && s.length() == i++: break;
|
case String s when s.length() == i++: break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -21,12 +21,12 @@
|
|||||||
* questions.
|
* questions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// key: compiler.err.duplicate.total.pattern
|
// key: compiler.err.duplicate.unconditional.pattern
|
||||||
// key: compiler.misc.feature.pattern.switch
|
// key: compiler.misc.feature.pattern.switch
|
||||||
// key: compiler.warn.preview.feature.use.plural
|
// key: compiler.warn.preview.feature.use.plural
|
||||||
// options: --enable-preview -source ${jdk.version} -Xlint:preview
|
// options: --enable-preview -source ${jdk.version} -Xlint:preview
|
||||||
|
|
||||||
class DuplicateTotalPattern {
|
class DuplicateUnconditionalPattern {
|
||||||
private void doSwitch(Object o) {
|
private void doSwitch(Object o) {
|
||||||
switch (o) {
|
switch (o) {
|
||||||
case Object obj: break;
|
case Object obj: break;
|
33
test/langtools/tools/javac/diags/examples/FeatureUnconditionalPatternsInInstanceof.java
Normal file
33
test/langtools/tools/javac/diags/examples/FeatureUnconditionalPatternsInInstanceof.java
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2010, 2022, 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.misc.feature.unconditional.patterns.in.instanceof
|
||||||
|
// key: compiler.warn.preview.feature.use.plural
|
||||||
|
// options: --enable-preview -source ${jdk.version} -Xlint:-options,preview
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
class FeatureUnconditionalTypesInstanceof {
|
||||||
|
String s;
|
||||||
|
boolean b = (s instanceof String str);
|
||||||
|
}
|
@ -1,12 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
* published by the Free Software Foundation. Oracle designates this
|
* published by the Free Software Foundation.
|
||||||
* 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
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
@ -23,28 +21,16 @@
|
|||||||
* questions.
|
* questions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.sun.source.tree;
|
// key: compiler.misc.not.applicable.types
|
||||||
|
// key: compiler.err.prob.found.req
|
||||||
import jdk.internal.javac.PreviewFeature;
|
// key: compiler.note.preview.filename
|
||||||
|
// key: compiler.note.preview.recompile
|
||||||
/**
|
// options: --enable-preview --source ${jdk.version}
|
||||||
* A guard pattern tree.
|
|
||||||
*
|
|
||||||
* @since 17
|
|
||||||
*/
|
|
||||||
@PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
|
|
||||||
public interface GuardedPatternTree extends PatternTree {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The guarded pattern expression.
|
|
||||||
* @return the guarded pattern
|
|
||||||
*/
|
|
||||||
public PatternTree getPattern();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The guard expression.
|
|
||||||
* @return the guard expression
|
|
||||||
*/
|
|
||||||
public ExpressionTree getExpression();
|
|
||||||
|
|
||||||
|
class NotApplicableTypes {
|
||||||
|
void t(int i) {
|
||||||
|
switch (i) {
|
||||||
|
case Integer j -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -21,12 +21,12 @@
|
|||||||
* questions.
|
* questions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// key: compiler.err.total.pattern.and.default
|
// key: compiler.err.unconditional.pattern.and.default
|
||||||
// key: compiler.misc.feature.pattern.switch
|
// key: compiler.misc.feature.pattern.switch
|
||||||
// key: compiler.warn.preview.feature.use.plural
|
// key: compiler.warn.preview.feature.use.plural
|
||||||
// options: --enable-preview -source ${jdk.version} -Xlint:preview
|
// options: --enable-preview -source ${jdk.version} -Xlint:preview
|
||||||
|
|
||||||
class TotalPatternAndDefault {
|
class UnconditionalPatternAndDefault {
|
||||||
private void doSwitch(Object o) {
|
private void doSwitch(Object o) {
|
||||||
switch (o) {
|
switch (o) {
|
||||||
case Object obj: break;
|
case Object obj: break;
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -94,7 +94,7 @@ public class CaseStructureTest extends ComboInstance<CaseStructureTest> {
|
|||||||
|
|
||||||
task.generate(result -> {
|
task.generate(result -> {
|
||||||
boolean shouldPass = true;
|
boolean shouldPass = true;
|
||||||
long patternCases = Arrays.stream(caseLabels).filter(l -> l == CaseLabel.TYPE_PATTERN || l == CaseLabel.GUARDED_PATTERN || l == CaseLabel.PARENTHESIZED_PATTERN).count();
|
long patternCases = Arrays.stream(caseLabels).filter(l -> l == CaseLabel.TYPE_PATTERN || l == CaseLabel.PARENTHESIZED_PATTERN).count();
|
||||||
long typePatternCases = Arrays.stream(caseLabels).filter(l -> l == CaseLabel.TYPE_PATTERN).count();
|
long typePatternCases = Arrays.stream(caseLabels).filter(l -> l == CaseLabel.TYPE_PATTERN).count();
|
||||||
long constantCases = Arrays.stream(caseLabels).filter(l -> l == CaseLabel.CONSTANT).count();
|
long constantCases = Arrays.stream(caseLabels).filter(l -> l == CaseLabel.CONSTANT).count();
|
||||||
long nullCases = Arrays.stream(caseLabels).filter(l -> l == CaseLabel.NULL).count();
|
long nullCases = Arrays.stream(caseLabels).filter(l -> l == CaseLabel.NULL).count();
|
||||||
@ -126,7 +126,7 @@ public class CaseStructureTest extends ComboInstance<CaseStructureTest> {
|
|||||||
for (CaseLabel label : caseLabels) {
|
for (CaseLabel label : caseLabels) {
|
||||||
switch (label) {
|
switch (label) {
|
||||||
case NULL: if (seenPattern) shouldPass = false; break;
|
case NULL: if (seenPattern) shouldPass = false; break;
|
||||||
case GUARDED_PATTERN, PARENTHESIZED_PATTERN, TYPE_PATTERN: seenPattern = true; break;
|
case PARENTHESIZED_PATTERN, TYPE_PATTERN: seenPattern = true; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,7 +140,6 @@ public class CaseStructureTest extends ComboInstance<CaseStructureTest> {
|
|||||||
NONE(""),
|
NONE(""),
|
||||||
TYPE_PATTERN("Integer i"),
|
TYPE_PATTERN("Integer i"),
|
||||||
PARENTHESIZED_PATTERN("(Integer i)"),
|
PARENTHESIZED_PATTERN("(Integer i)"),
|
||||||
GUARDED_PATTERN("Integer i && i > 0"),
|
|
||||||
CONSTANT("1"),
|
CONSTANT("1"),
|
||||||
NULL("null"),
|
NULL("null"),
|
||||||
DEFAULT("default");
|
DEFAULT("default");
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -53,7 +53,7 @@ public class DisambiguatePatterns {
|
|||||||
DisambiguatePatterns test = new DisambiguatePatterns();
|
DisambiguatePatterns test = new DisambiguatePatterns();
|
||||||
test.disambiguationTest("String s",
|
test.disambiguationTest("String s",
|
||||||
ExpressionType.PATTERN);
|
ExpressionType.PATTERN);
|
||||||
test.disambiguationTest("String s && s.isEmpty()",
|
test.disambiguationTest("String s when s.isEmpty()",
|
||||||
ExpressionType.PATTERN);
|
ExpressionType.PATTERN);
|
||||||
test.disambiguationTest("(String s)",
|
test.disambiguationTest("(String s)",
|
||||||
ExpressionType.PATTERN);
|
ExpressionType.PATTERN);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -40,22 +40,22 @@ public class Domination {
|
|||||||
int testDominatesError2(Object o) {
|
int testDominatesError2(Object o) {
|
||||||
switch (o) {
|
switch (o) {
|
||||||
case CharSequence cs: return 0;
|
case CharSequence cs: return 0;
|
||||||
case String s && s.isEmpty(): return 1;
|
case String s when s.isEmpty(): return 1;
|
||||||
case Object x: return -1;
|
case Object x: return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int testDominatesError3(Object o) {
|
int testDominatesError3(Object o) {
|
||||||
switch (o) {
|
switch (o) {
|
||||||
case CharSequence cs && true: return 0;
|
case CharSequence cs when true: return 0;
|
||||||
case String s && s.isEmpty(): return 1;
|
case String s when s.isEmpty(): return 1;
|
||||||
case Object x: return -1;
|
case Object x: return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int testNotDominates1(Object o) {
|
int testNotDominates1(Object o) {
|
||||||
switch (o) {
|
switch (o) {
|
||||||
case CharSequence cs && cs.length() == 0: return 0;
|
case CharSequence cs when cs.length() == 0: return 0;
|
||||||
case String s: return 1;
|
case String s: return 1;
|
||||||
case Object x: return -1;
|
case Object x: return -1;
|
||||||
}
|
}
|
||||||
@ -70,14 +70,14 @@ public class Domination {
|
|||||||
|
|
||||||
int testDominatesStringConstant2(String str) {
|
int testDominatesStringConstant2(String str) {
|
||||||
switch (str) {
|
switch (str) {
|
||||||
case (String s && s.isEmpty()): return 1;
|
case String s when s.isEmpty(): return 1;
|
||||||
case "": return -1;
|
case "": return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int testDominatesStringConstant3(String str) {
|
int testDominatesStringConstant3(String str) {
|
||||||
switch (str) {
|
switch (str) {
|
||||||
case (String s && !s.isEmpty()): return 1;
|
case String s when !s.isEmpty(): return 1;
|
||||||
case "": return -1;
|
case "": return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,14 +91,14 @@ public class Domination {
|
|||||||
|
|
||||||
int testDominatesIntegerConstant2(Integer i) {
|
int testDominatesIntegerConstant2(Integer i) {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case (Integer j && j == 0): return 1;
|
case Integer j when j == 0: return 1;
|
||||||
case 0: return -1;
|
case 0: return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int testDominatesIntegerConstant3(Integer i) {
|
int testDominatesIntegerConstant3(Integer i) {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case (Integer j && j == 1): return 1;
|
case Integer j when j == 1: return 1;
|
||||||
case 0: return -1;
|
case 0: return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -120,7 +120,7 @@ public class Domination {
|
|||||||
}
|
}
|
||||||
E e = E.A;
|
E e = E.A;
|
||||||
switch (e) {
|
switch (e) {
|
||||||
case (E d && d == E.A): return 1;
|
case E d when d == E.A: return 1;
|
||||||
case A: return -1;
|
case A: return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -131,7 +131,7 @@ public class Domination {
|
|||||||
}
|
}
|
||||||
E e = E.A;
|
E e = E.A;
|
||||||
switch (e) {
|
switch (e) {
|
||||||
case (E d && d == E.B): return 1;
|
case E d when d == E.B: return 1;
|
||||||
case A: return -1;
|
case A: return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -42,6 +42,8 @@ public class EnumTypeChanges {
|
|||||||
void run() throws Exception {
|
void run() throws Exception {
|
||||||
doRun(this::statementEnum);
|
doRun(this::statementEnum);
|
||||||
doRun(this::expressionEnum);
|
doRun(this::expressionEnum);
|
||||||
|
doRunExhaustive(this::expressionEnumExhaustive);
|
||||||
|
doRunExhaustive(this::statementEnumExhaustive);
|
||||||
}
|
}
|
||||||
|
|
||||||
void doRun(Function<EnumTypeChangesEnum, String> c) throws Exception {
|
void doRun(Function<EnumTypeChangesEnum, String> c) throws Exception {
|
||||||
@ -49,11 +51,20 @@ public class EnumTypeChanges {
|
|||||||
assertEquals("D", c.apply(EnumTypeChangesEnum.valueOf("C")));
|
assertEquals("D", c.apply(EnumTypeChangesEnum.valueOf("C")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void doRunExhaustive(Function<EnumTypeChangesEnum, String> c) throws Exception {
|
||||||
|
try {
|
||||||
|
c.apply(EnumTypeChangesEnum.valueOf("C"));
|
||||||
|
throw new AssertionError();
|
||||||
|
} catch (IncompatibleClassChangeError e) {
|
||||||
|
//expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String statementEnum(EnumTypeChangesEnum e) {
|
String statementEnum(EnumTypeChangesEnum e) {
|
||||||
switch (e) {
|
switch (e) {
|
||||||
case A -> { return "A"; }
|
case A -> { return "A"; }
|
||||||
case B -> { return "B"; }
|
case B -> { return "B"; }
|
||||||
case EnumTypeChangesEnum e1 && false -> throw new AssertionError();
|
case EnumTypeChangesEnum e1 when false -> throw new AssertionError();
|
||||||
default -> { return "D"; }
|
default -> { return "D"; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -62,11 +73,28 @@ public class EnumTypeChanges {
|
|||||||
return switch (e) {
|
return switch (e) {
|
||||||
case A -> "A";
|
case A -> "A";
|
||||||
case B -> "B";
|
case B -> "B";
|
||||||
case EnumTypeChangesEnum e1 && false -> throw new AssertionError();
|
case EnumTypeChangesEnum e1 when false -> throw new AssertionError();
|
||||||
default -> "D";
|
default -> "D";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String statementEnumExhaustive(EnumTypeChangesEnum e) {
|
||||||
|
switch (e) {
|
||||||
|
case A -> { return "A"; }
|
||||||
|
case B -> { return "B"; }
|
||||||
|
case EnumTypeChangesEnum x when e == EnumTypeChangesEnum.A -> throw new AssertionError();
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
String expressionEnumExhaustive(EnumTypeChangesEnum e) {
|
||||||
|
return switch (e) {
|
||||||
|
case A -> "A";
|
||||||
|
case B -> "B";
|
||||||
|
case EnumTypeChangesEnum x when e == EnumTypeChangesEnum.A -> throw new AssertionError();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private static void assertEquals(Object o1, Object o2) {
|
private static void assertEquals(Object o1, Object o2) {
|
||||||
if (!Objects.equals(o1, o2)) {
|
if (!Objects.equals(o1, o2)) {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -207,7 +207,7 @@ public class Exhaustiveness extends TestRunner {
|
|||||||
public class Test {
|
public class Test {
|
||||||
private int test(S obj) {
|
private int test(S obj) {
|
||||||
return switch (obj) {
|
return switch (obj) {
|
||||||
case A a && a.toString().isEmpty() -> 0;
|
case A a when a.toString().isEmpty() -> 0;
|
||||||
case B b -> 1;
|
case B b -> 1;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -241,7 +241,7 @@ public class Exhaustiveness extends TestRunner {
|
|||||||
private static final boolean TEST = true;
|
private static final boolean TEST = true;
|
||||||
private int test(S obj) {
|
private int test(S obj) {
|
||||||
return switch (obj) {
|
return switch (obj) {
|
||||||
case A a && !(!(TEST)) -> 0;
|
case A a when !(!(TEST)) -> 0;
|
||||||
case B b -> 1;
|
case B b -> 1;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -270,7 +270,7 @@ public class Exhaustiveness extends TestRunner {
|
|||||||
public class Test {
|
public class Test {
|
||||||
private int test(S obj) {
|
private int test(S obj) {
|
||||||
return switch (obj) {
|
return switch (obj) {
|
||||||
case A a && false -> 0;
|
case A a when false -> 0;
|
||||||
case B b -> 1;
|
case B b -> 1;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -531,7 +531,7 @@ public class Exhaustiveness extends TestRunner {
|
|||||||
private int test(S obj, boolean b) {
|
private int test(S obj, boolean b) {
|
||||||
return switch (obj) {
|
return switch (obj) {
|
||||||
case A a -> 0;
|
case A a -> 0;
|
||||||
case C c && b -> 0;
|
case C c when b -> 0;
|
||||||
case C c -> 0;
|
case C c -> 0;
|
||||||
case D d -> 0;
|
case D d -> 0;
|
||||||
};
|
};
|
||||||
@ -571,7 +571,7 @@ public class Exhaustiveness extends TestRunner {
|
|||||||
return switch (obj) {
|
return switch (obj) {
|
||||||
case A a -> 0;
|
case A a -> 0;
|
||||||
case C c -> 0;
|
case C c -> 0;
|
||||||
case D d && b -> 0;
|
case D d when b -> 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -620,7 +620,7 @@ public class Exhaustiveness extends TestRunner {
|
|||||||
private <T extends Base & S & Marker> int test(T obj, boolean b) {
|
private <T extends Base & S & Marker> int test(T obj, boolean b) {
|
||||||
return switch (obj) {
|
return switch (obj) {
|
||||||
case A a -> 0;
|
case A a -> 0;
|
||||||
case C c && b -> 0;
|
case C c when b -> 0;
|
||||||
case C c -> 0;
|
case C c -> 0;
|
||||||
case D d -> 0;
|
case D d -> 0;
|
||||||
};
|
};
|
||||||
@ -668,7 +668,7 @@ public class Exhaustiveness extends TestRunner {
|
|||||||
return switch (obj) {
|
return switch (obj) {
|
||||||
case A a -> 0;
|
case A a -> 0;
|
||||||
case C c -> 0;
|
case C c -> 0;
|
||||||
case D d && b -> 0;
|
case D d when b -> 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -867,6 +867,53 @@ public class Exhaustiveness extends TestRunner {
|
|||||||
"4 errors");
|
"4 errors");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNonPrimitiveBooleanGuard(Path base) throws Exception {
|
||||||
|
doTest(base,
|
||||||
|
new String[0],
|
||||||
|
"""
|
||||||
|
package test;
|
||||||
|
public class Test {
|
||||||
|
sealed interface A {}
|
||||||
|
final class B1 implements A {}
|
||||||
|
final class B2 implements A {}
|
||||||
|
|
||||||
|
void test(A arg, Boolean g) {
|
||||||
|
int i = switch (arg) {
|
||||||
|
case B1 b1 when g -> 1;
|
||||||
|
case B2 b2 -> 2;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
"Test.java:8:17: compiler.err.not.exhaustive",
|
||||||
|
"- compiler.note.preview.filename: Test.java, DEFAULT",
|
||||||
|
"- compiler.note.preview.recompile",
|
||||||
|
"1 error");
|
||||||
|
doTest(base,
|
||||||
|
new String[0],
|
||||||
|
"""
|
||||||
|
package test;
|
||||||
|
public class Test {
|
||||||
|
sealed interface A {}
|
||||||
|
final class B1 implements A {}
|
||||||
|
final class B2 implements A {}
|
||||||
|
|
||||||
|
void test(A arg) {
|
||||||
|
int i = switch (arg) {
|
||||||
|
case B1 b1 when undefined() -> 1;
|
||||||
|
case B2 b2 -> 2;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
"Test.java:9:29: compiler.err.cant.resolve.location.args: kindname.method, undefined, , , (compiler.misc.location: kindname.class, test.Test, null)",
|
||||||
|
"Test.java:8:17: compiler.err.not.exhaustive",
|
||||||
|
"- compiler.note.preview.filename: Test.java, DEFAULT",
|
||||||
|
"- compiler.note.preview.recompile",
|
||||||
|
"2 errors");
|
||||||
|
}
|
||||||
|
|
||||||
private void doTest(Path base, String[] libraryCode, String testCode, String... expectedErrors) throws IOException {
|
private void doTest(Path base, String[] libraryCode, String testCode, String... expectedErrors) throws IOException {
|
||||||
Path current = base.resolve(".");
|
Path current = base.resolve(".");
|
||||||
Path libClasses = current.resolve("libClasses");
|
Path libClasses = current.resolve("libClasses");
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -49,6 +49,7 @@ public class Guards {
|
|||||||
runIfTrue(this::typeGuardAfterParenthesizedTrueSwitchStatement);
|
runIfTrue(this::typeGuardAfterParenthesizedTrueSwitchStatement);
|
||||||
runIfTrue(this::typeGuardAfterParenthesizedTrueSwitchExpression);
|
runIfTrue(this::typeGuardAfterParenthesizedTrueSwitchExpression);
|
||||||
runIfTrue(this::typeGuardAfterParenthesizedTrueIfStatement);
|
runIfTrue(this::typeGuardAfterParenthesizedTrueIfStatement);
|
||||||
|
testGuardNPE();
|
||||||
}
|
}
|
||||||
|
|
||||||
void run(Function<Object, String> convert) {
|
void run(Function<Object, String> convert) {
|
||||||
@ -66,8 +67,8 @@ public class Guards {
|
|||||||
|
|
||||||
String typeTestPatternSwitchTest(Object o) {
|
String typeTestPatternSwitchTest(Object o) {
|
||||||
switch (o) {
|
switch (o) {
|
||||||
case Integer i && i == 0: return "zero";
|
case Integer i when i == 0: return "zero";
|
||||||
case Integer i && i == 1: return "one";
|
case Integer i when i == 1: return "one";
|
||||||
case Integer i: return "other";
|
case Integer i: return "other";
|
||||||
case Object x: return "any";
|
case Object x: return "any";
|
||||||
}
|
}
|
||||||
@ -75,8 +76,8 @@ public class Guards {
|
|||||||
|
|
||||||
String typeTestPatternSwitchExpressionTest(Object o) {
|
String typeTestPatternSwitchExpressionTest(Object o) {
|
||||||
return switch (o) {
|
return switch (o) {
|
||||||
case Integer i && i == 0 -> "zero";
|
case Integer i when i == 0 -> "zero";
|
||||||
case Integer i && i == 1 -> { yield "one"; }
|
case Integer i when i == 1 -> { yield "one"; }
|
||||||
case Integer i -> "other";
|
case Integer i -> "other";
|
||||||
case Object x -> "any";
|
case Object x -> "any";
|
||||||
};
|
};
|
||||||
@ -85,8 +86,8 @@ public class Guards {
|
|||||||
String testBooleanSwitchExpression(Object o) {
|
String testBooleanSwitchExpression(Object o) {
|
||||||
String x;
|
String x;
|
||||||
if (switch (o) {
|
if (switch (o) {
|
||||||
case Integer i && i == 0 -> (x = "zero") != null;
|
case Integer i when i == 0 -> (x = "zero") != null;
|
||||||
case Integer i && i == 1 -> { x = "one"; yield true; }
|
case Integer i when i == 1 -> { x = "one"; yield true; }
|
||||||
case Integer i -> { x = "other"; yield true; }
|
case Integer i -> { x = "other"; yield true; }
|
||||||
case Object other -> (x = "any") != null;
|
case Object other -> (x = "any") != null;
|
||||||
}) {
|
}) {
|
||||||
@ -99,8 +100,8 @@ public class Guards {
|
|||||||
String typeGuardIfTrueSwitchStatement(Object o) {
|
String typeGuardIfTrueSwitchStatement(Object o) {
|
||||||
Object o2 = "";
|
Object o2 = "";
|
||||||
switch (o) {
|
switch (o) {
|
||||||
case Integer i && i == 0 && i < 1 && o2 instanceof String s: o = s + String.valueOf(i); return "true";
|
case Integer i when i == 0 && i < 1 && o2 instanceof String s: o = s + String.valueOf(i); return "true";
|
||||||
case Integer i && i == 0 || i > 1: o = String.valueOf(i); return "second";
|
case Integer i when i == 0 || i > 1: o = String.valueOf(i); return "second";
|
||||||
case Object x: return "any";
|
case Object x: return "any";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,17 +109,17 @@ public class Guards {
|
|||||||
String typeGuardIfTrueSwitchExpression(Object o) {
|
String typeGuardIfTrueSwitchExpression(Object o) {
|
||||||
Object o2 = "";
|
Object o2 = "";
|
||||||
return switch (o) {
|
return switch (o) {
|
||||||
case Integer i && i == 0 && i < 1 && o2 instanceof String s: o = s + String.valueOf(i); yield "true";
|
case Integer i when i == 0 && i < 1 && o2 instanceof String s: o = s + String.valueOf(i); yield "true";
|
||||||
case Integer i && i == 0 || i > 1: o = String.valueOf(i); yield "second";
|
case Integer i when i == 0 || i > 1: o = String.valueOf(i); yield "second";
|
||||||
case Object x: yield "any";
|
case Object x: yield "any";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
String typeGuardIfTrueIfStatement(Object o) {
|
String typeGuardIfTrueIfStatement(Object o) {
|
||||||
Object o2 = "";
|
Object o2 = "";
|
||||||
if (o != null && o instanceof (Integer i && i == 0 && i < 1) && (o = i) != null && o2 instanceof String s) {
|
if (o != null && o instanceof Integer i && i == 0 && i < 1 && (o = i) != null && o2 instanceof String s) {
|
||||||
return s != null ? "true" : null;
|
return s != null ? "true" : null;
|
||||||
} else if (o != null && o instanceof (Integer i && i == 0 || i > 1) && (o = i) != null) {
|
} else if (o != null && o instanceof Integer i && (i == 0 || i > 1) && (o = i) != null) {
|
||||||
return "second";
|
return "second";
|
||||||
} else {
|
} else {
|
||||||
return "any";
|
return "any";
|
||||||
@ -127,24 +128,24 @@ public class Guards {
|
|||||||
|
|
||||||
String typeGuardAfterParenthesizedTrueSwitchStatement(Object o) {
|
String typeGuardAfterParenthesizedTrueSwitchStatement(Object o) {
|
||||||
switch (o) {
|
switch (o) {
|
||||||
case (Integer i) && i == 0: o = String.valueOf(i); return "true";
|
case (Integer i) when i == 0: o = String.valueOf(i); return "true";
|
||||||
case ((Integer i) && i == 2): o = String.valueOf(i); return "second";
|
case (Integer i) when i == 2: o = String.valueOf(i); return "second";
|
||||||
case Object x: return "any";
|
case Object x: return "any";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String typeGuardAfterParenthesizedTrueSwitchExpression(Object o) {
|
String typeGuardAfterParenthesizedTrueSwitchExpression(Object o) {
|
||||||
return switch (o) {
|
return switch (o) {
|
||||||
case (Integer i) && i == 0: o = String.valueOf(i); yield "true";
|
case (Integer i) when i == 0: o = String.valueOf(i); yield "true";
|
||||||
case ((Integer i) && i == 2): o = String.valueOf(i); yield "second";
|
case (Integer i) when i == 2: o = String.valueOf(i); yield "second";
|
||||||
case Object x: yield "any";
|
case Object x: yield "any";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
String typeGuardAfterParenthesizedTrueIfStatement(Object o) {
|
String typeGuardAfterParenthesizedTrueIfStatement(Object o) {
|
||||||
if (o != null && o instanceof ((Integer i) && i == 0)) {
|
if (o != null && o instanceof (Integer i) && i == 0) {
|
||||||
return "true";
|
return "true";
|
||||||
} else if (o != null && o instanceof (((Integer i) && i == 2)) && (o = i) != null) {
|
} else if (o != null && o instanceof (Integer i) && i == 2 && (o = i) != null) {
|
||||||
return "second";
|
return "second";
|
||||||
} else {
|
} else {
|
||||||
return "any";
|
return "any";
|
||||||
@ -152,12 +153,32 @@ public class Guards {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String testPatternInGuard(Object o) {
|
String testPatternInGuard(Object o) {
|
||||||
if (o instanceof (CharSequence cs && cs instanceof String s)) {
|
if (o instanceof CharSequence cs && cs instanceof String s) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void testGuardNPE() {
|
||||||
|
assertEquals("empty", guardNPE(""));
|
||||||
|
assertEquals("A", guardNPE("A"));
|
||||||
|
assertEquals("other", guardNPE(1));
|
||||||
|
try {
|
||||||
|
guardNPE(null);
|
||||||
|
throw new AssertionError("Expected exception missing.");
|
||||||
|
} catch (NullPointerException ex) {
|
||||||
|
//expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String guardNPE(Object o) {
|
||||||
|
return switch (o) {
|
||||||
|
case null, String s when s.isEmpty() -> "empty";
|
||||||
|
case String s -> s;
|
||||||
|
case Object x -> "other";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
void assertEquals(String expected, String actual) {
|
void assertEquals(String expected, String actual) {
|
||||||
if (!Objects.equals(expected, actual)) {
|
if (!Objects.equals(expected, actual)) {
|
||||||
throw new AssertionError("Expected: " + expected + ", but got: " + actual);
|
throw new AssertionError("Expected: " + expected + ", but got: " + actual);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -28,11 +28,13 @@
|
|||||||
* @compile/fail/ref=GuardsErrors.out -XDrawDiagnostics --enable-preview -source ${jdk.version} GuardsErrors.java
|
* @compile/fail/ref=GuardsErrors.out -XDrawDiagnostics --enable-preview -source ${jdk.version} GuardsErrors.java
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//TODO: tests and error recovery for misplaced guards
|
||||||
|
|
||||||
public class GuardsErrors {
|
public class GuardsErrors {
|
||||||
|
|
||||||
void typeTestPatternSwitchTest(Object o, int check) {
|
void typeTestPatternSwitchTest(Object o, int check) {
|
||||||
switch (o) {
|
switch (o) {
|
||||||
case Integer i && i == check -> System.err.println(); //error: check is not effectivelly final
|
case Integer i when i == check -> System.err.println(); //error: check is not effectivelly final
|
||||||
default -> {}
|
default -> {}
|
||||||
}
|
}
|
||||||
check = 0;
|
check = 0;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
GuardsErrors.java:35:36: compiler.err.cant.ref.non.effectively.final.var: check, (compiler.misc.guard)
|
GuardsErrors.java:37:38: compiler.err.cant.ref.non.effectively.final.var: check, (compiler.misc.guard)
|
||||||
- compiler.note.preview.filename: GuardsErrors.java, DEFAULT
|
- compiler.note.preview.filename: GuardsErrors.java, DEFAULT
|
||||||
- compiler.note.preview.recompile
|
- compiler.note.preview.recompile
|
||||||
1 error
|
1 error
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
InstanceofTotalPattern.java:18:37: compiler.err.feature.not.supported.in.source: (compiler.misc.feature.pattern.matching.instanceof), 15, 16
|
||||||
|
1 error
|
@ -0,0 +1,3 @@
|
|||||||
|
InstanceofTotalPattern.java:18:19: compiler.err.instanceof.pattern.no.subtype: java.lang.String, java.lang.String
|
||||||
|
InstanceofTotalPattern.java:22:17: compiler.err.instanceof.pattern.no.subtype: java.lang.String, java.lang.String
|
||||||
|
2 errors
|
@ -0,0 +1,3 @@
|
|||||||
|
InstanceofTotalPattern.java:18:30: compiler.warn.preview.feature.use.plural: (compiler.misc.feature.unconditional.patterns.in.instanceof)
|
||||||
|
InstanceofTotalPattern.java:22:28: compiler.warn.preview.feature.use.plural: (compiler.misc.feature.unconditional.patterns.in.instanceof)
|
||||||
|
2 warnings
|
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* @test /nodynamiccopyright/
|
||||||
|
* @summary Verify behavior of total patterns in instanceof
|
||||||
|
* @compile/fail/ref=InstanceofTotalPattern-15.out -source 15 -Xlint:-options -XDrawDiagnostics InstanceofTotalPattern.java
|
||||||
|
* @compile/fail/ref=InstanceofTotalPattern-16.out -source 16 -Xlint:-options -XDrawDiagnostics InstanceofTotalPattern.java
|
||||||
|
* @compile/ref=InstanceofTotalPattern-preview.out --enable-preview -source ${jdk.version} -Xlint:-options,preview -XDrawDiagnostics InstanceofTotalPattern.java
|
||||||
|
* @run main/othervm --enable-preview InstanceofTotalPattern
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class InstanceofTotalPattern {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
new InstanceofTotalPattern().totalTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
void totalTest() {
|
||||||
|
String str = "";
|
||||||
|
if (!(str instanceof String s1)) {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
str = null;
|
||||||
|
if (str instanceof String s2) {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -71,7 +71,7 @@ public class NestedPatternVariablesBytecode extends TestRunner {
|
|||||||
String code = """
|
String code = """
|
||||||
class NestedPatterVariablesTest {
|
class NestedPatterVariablesTest {
|
||||||
String test(Object o) {
|
String test(Object o) {
|
||||||
if (o instanceof (CharSequence cs && cs instanceof String s)) {
|
if (o instanceof CharSequence cs && cs instanceof String s) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -45,12 +45,18 @@ public class NullSwitch {
|
|||||||
assertEquals(0, matchingSwitch8(""));
|
assertEquals(0, matchingSwitch8(""));
|
||||||
assertEquals(1, matchingSwitch8(null));
|
assertEquals(1, matchingSwitch8(null));
|
||||||
assertEquals(1, matchingSwitch8(0.0));
|
assertEquals(1, matchingSwitch8(0.0));
|
||||||
assertEquals(0, matchingSwitch9(""));
|
assertEquals(0, matchingSwitch9a(""));
|
||||||
assertEquals(1, matchingSwitch9(null));
|
assertEquals(1, matchingSwitch9a(null));
|
||||||
assertEquals(1, matchingSwitch9(0.0));
|
assertEquals(1, matchingSwitch9a(0.0));
|
||||||
assertEquals(0, matchingSwitch10(""));
|
assertEquals(0, matchingSwitch10a(""));
|
||||||
assertEquals(1, matchingSwitch10(null));
|
assertEquals(1, matchingSwitch10a(null));
|
||||||
assertEquals(1, matchingSwitch10(0.0));
|
assertEquals(1, matchingSwitch10a(0.0));
|
||||||
|
assertEquals(0, matchingSwitch9b(""));
|
||||||
|
assertEquals(2, matchingSwitch9b(null));
|
||||||
|
assertEquals(1, matchingSwitch9b(0.0));
|
||||||
|
assertEquals(0, matchingSwitch10b(""));
|
||||||
|
assertEquals(2, matchingSwitch10b(null));
|
||||||
|
assertEquals(1, matchingSwitch10b(0.0));
|
||||||
assertEquals(0, matchingSwitch11(""));
|
assertEquals(0, matchingSwitch11(""));
|
||||||
assertEquals(2, matchingSwitch11(null));
|
assertEquals(2, matchingSwitch11(null));
|
||||||
assertEquals(1, matchingSwitch11(0.0));
|
assertEquals(1, matchingSwitch11(0.0));
|
||||||
@ -126,17 +132,39 @@ public class NullSwitch {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private int matchingSwitch9(Object obj) {
|
private int matchingSwitch9a(Object obj) {
|
||||||
return switch (obj) {
|
return switch (obj) {
|
||||||
case String s: yield 0;
|
case String s: yield 0;
|
||||||
case Object o: yield 1;
|
case null, Object o: yield 1;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private int matchingSwitch10(Object obj) {
|
private int matchingSwitch10a(Object obj) {
|
||||||
switch (obj) {
|
switch (obj) {
|
||||||
case String s: return 0;
|
case String s: return 0;
|
||||||
case Object o: return 1;
|
case null, Object o: return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int matchingSwitch9b(Object obj) {
|
||||||
|
try {
|
||||||
|
return switch (obj) {
|
||||||
|
case String s: yield 0;
|
||||||
|
case Object o: yield 1;
|
||||||
|
};
|
||||||
|
} catch (NullPointerException ex) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int matchingSwitch10b(Object obj) {
|
||||||
|
try {
|
||||||
|
switch (obj) {
|
||||||
|
case String s: return 0;
|
||||||
|
case Object o: return 1;
|
||||||
|
}
|
||||||
|
} catch (NullPointerException ex) {
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -36,17 +36,17 @@ public class Parenthesized {
|
|||||||
void run() {
|
void run() {
|
||||||
Object o = "";
|
Object o = "";
|
||||||
switch (o) {
|
switch (o) {
|
||||||
case (String s && s.isEmpty()) -> System.err.println("OK: " + s);
|
case (String s) when s.isEmpty() -> System.err.println("OK: " + s);
|
||||||
default -> throw new AssertionError();
|
default -> throw new AssertionError();
|
||||||
}
|
}
|
||||||
System.err.println(switch (o) {
|
System.err.println(switch (o) {
|
||||||
case (String s && s.isEmpty()) -> "OK: " + s;
|
case (String s) when s.isEmpty() -> "OK: " + s;
|
||||||
default -> throw new AssertionError();
|
default -> throw new AssertionError();
|
||||||
});
|
});
|
||||||
if (o instanceof (String s && s.isEmpty())) {
|
if (o instanceof (String s) && s.isEmpty()) {
|
||||||
System.err.println("OK: " + s);
|
System.err.println("OK: " + s);
|
||||||
}
|
}
|
||||||
boolean b1 = o instanceof (String s && s.isEmpty());
|
boolean b1 = o instanceof (String s) && s.isEmpty();
|
||||||
boolean b2 = o instanceof String s && s.isEmpty();
|
boolean b2 = o instanceof String s && s.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ public class RawTypeBindingWarning<T> {
|
|||||||
default -> {}
|
default -> {}
|
||||||
}
|
}
|
||||||
switch (o) {
|
switch (o) {
|
||||||
case (RawTypeBindingWarning w && false) -> {}
|
case RawTypeBindingWarning w when false -> {}
|
||||||
default -> {}
|
default -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
RawTypeBindingWarning.java:9:29: compiler.warn.raw.class.use: RawTypeBindingWarning, RawTypeBindingWarning<T>
|
RawTypeBindingWarning.java:9:29: compiler.warn.raw.class.use: RawTypeBindingWarning, RawTypeBindingWarning<T>
|
||||||
RawTypeBindingWarning.java:13:18: compiler.warn.raw.class.use: RawTypeBindingWarning, RawTypeBindingWarning<T>
|
RawTypeBindingWarning.java:13:18: compiler.warn.raw.class.use: RawTypeBindingWarning, RawTypeBindingWarning<T>
|
||||||
RawTypeBindingWarning.java:17:19: compiler.warn.raw.class.use: RawTypeBindingWarning, RawTypeBindingWarning<T>
|
RawTypeBindingWarning.java:17:19: compiler.warn.raw.class.use: RawTypeBindingWarning, RawTypeBindingWarning<T>
|
||||||
RawTypeBindingWarning.java:21:19: compiler.warn.raw.class.use: RawTypeBindingWarning, RawTypeBindingWarning<T>
|
RawTypeBindingWarning.java:21:18: compiler.warn.raw.class.use: RawTypeBindingWarning, RawTypeBindingWarning<T>
|
||||||
- compiler.note.preview.filename: RawTypeBindingWarning.java, DEFAULT
|
- compiler.note.preview.filename: RawTypeBindingWarning.java, DEFAULT
|
||||||
- compiler.note.preview.recompile
|
- compiler.note.preview.recompile
|
||||||
4 warnings
|
4 warnings
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -39,11 +39,11 @@ public class SealedTypeChanges {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void run() throws Exception {
|
void run() throws Exception {
|
||||||
doRun(this::expressionIntf, this::validateIncompatibleClassChangeError);
|
doRun(this::expressionIntf, this::validateMatchException);
|
||||||
doRun(this::statementIntf, this::validateIncompatibleClassChangeError);
|
doRun(this::statementIntf, this::validateMatchException);
|
||||||
doRun(this::expressionCls, this::validateIncompatibleClassChangeError);
|
doRun(this::expressionCls, this::validateMatchException);
|
||||||
doRun(this::statementCls, this::validateIncompatibleClassChangeError);
|
doRun(this::statementCls, this::validateMatchException);
|
||||||
doRun(this::statementFallThrough, this::validateIncompatibleClassChangeError);
|
doRun(this::statementFallThrough, this::validateMatchException);
|
||||||
doRun(this::expressionCoveredIntf, this::validateTestException);
|
doRun(this::expressionCoveredIntf, this::validateTestException);
|
||||||
doRun(this::statementCoveredIntf, this::validateTestException);
|
doRun(this::statementCoveredIntf, this::validateTestException);
|
||||||
doRun(this::expressionCoveredCls, this::validateTestException);
|
doRun(this::expressionCoveredCls, this::validateTestException);
|
||||||
@ -60,8 +60,8 @@ public class SealedTypeChanges {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void validateIncompatibleClassChangeError(Throwable t) {
|
void validateMatchException(Throwable t) {
|
||||||
if (!(t instanceof IncompatibleClassChangeError)) {
|
if (!(t instanceof MatchException)) {
|
||||||
throw new AssertionError("Unexpected exception", t);
|
throw new AssertionError("Unexpected exception", t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, 2022, 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
|
* @test
|
||||||
* @compile --enable-preview -source ${jdk.version} -doe SimpleAndGuardPattern.java
|
* @compile --enable-preview -source ${jdk.version} -doe SimpleAndGuardPattern.java
|
||||||
* @run main/othervm --enable-preview SimpleAndGuardPattern
|
* @run main/othervm --enable-preview SimpleAndGuardPattern
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class SimpleAndGuardPattern {
|
public class SimpleAndGuardPattern {
|
||||||
@ -23,7 +45,7 @@ public class SimpleAndGuardPattern {
|
|||||||
|
|
||||||
private static int simple(Object o) throws Throwable {
|
private static int simple(Object o) throws Throwable {
|
||||||
return switch (o) {
|
return switch (o) {
|
||||||
case String s && s.equalsIgnoreCase("test") -> s.length();
|
case String s when s.equalsIgnoreCase("test") -> s.length();
|
||||||
default -> -1;
|
default -> -1;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -175,20 +175,20 @@ public class SwitchErrors {
|
|||||||
}
|
}
|
||||||
Object guardWithMatchingStatement(Object o1, Object o2) {
|
Object guardWithMatchingStatement(Object o1, Object o2) {
|
||||||
switch (o1) {
|
switch (o1) {
|
||||||
case String s && s.isEmpty() || o2 instanceof Number n: return n;
|
case String s when s.isEmpty() || o2 instanceof Number n: return n;
|
||||||
default: return null;
|
default: return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Object guardWithMatchingExpression(Object o1, Object o2) {
|
Object guardWithMatchingExpression(Object o1, Object o2) {
|
||||||
return switch (o1) {
|
return switch (o1) {
|
||||||
case String s && s.isEmpty() || o2 instanceof Number n -> n;
|
case String s when s.isEmpty() || o2 instanceof Number n -> n;
|
||||||
default -> null;
|
default -> null;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
void test8269146a1(Integer i) {
|
void test8269146a1(Integer i) {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
//error - illegal combination of pattern and constant:
|
//error - illegal combination of pattern and constant:
|
||||||
case 1, Integer o && o != null:
|
case 1, Integer o when o != null:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -197,7 +197,7 @@ public class SwitchErrors {
|
|||||||
void test8269146a2(Integer i) {
|
void test8269146a2(Integer i) {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
//error - illegal combination of pattern and constant:
|
//error - illegal combination of pattern and constant:
|
||||||
case Integer o && o != null, 1:
|
case Integer o when o != null, 1:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -206,7 +206,7 @@ public class SwitchErrors {
|
|||||||
void test8269146b(Integer i) {
|
void test8269146b(Integer i) {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
//error - illegal combination of null and pattern other than type pattern:
|
//error - illegal combination of null and pattern other than type pattern:
|
||||||
case null, Integer o && o != null:
|
case null, Integer o when o != null:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -222,14 +222,14 @@ public class SwitchErrors {
|
|||||||
void test8269301a(Integer i) {
|
void test8269301a(Integer i) {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
//error - illegal combination of pattern, constant and default
|
//error - illegal combination of pattern, constant and default
|
||||||
case 1, Integer o && o != null, default:
|
case 1, Integer o when o != null, default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void test8269301b(Integer i) {
|
void test8269301b(Integer i) {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
//error - illegal combination of pattern, constant and default
|
//error - illegal combination of pattern, constant and default
|
||||||
case Integer o && o != null, 1, default:
|
case Integer o when o != null, 1, default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -244,4 +244,14 @@ public class SwitchErrors {
|
|||||||
case CharSequence cs: break;
|
case CharSequence cs: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void primitiveToReference(int i) {
|
||||||
|
switch (i) {
|
||||||
|
case Integer j: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void referenceToPrimitive(Integer i) {
|
||||||
|
switch (i) {
|
||||||
|
case int j: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,11 @@ SwitchErrors.java:23:18: compiler.err.prob.found.req: (compiler.misc.inconvertib
|
|||||||
SwitchErrors.java:28:18: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: compiler.misc.type.null, int)
|
SwitchErrors.java:28:18: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: compiler.misc.type.null, int)
|
||||||
SwitchErrors.java:29:18: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.String, int)
|
SwitchErrors.java:29:18: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.String, int)
|
||||||
SwitchErrors.java:30:18: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: int, java.lang.CharSequence)
|
SwitchErrors.java:30:18: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: int, java.lang.CharSequence)
|
||||||
SwitchErrors.java:36:13: compiler.err.total.pattern.and.default
|
SwitchErrors.java:36:13: compiler.err.unconditional.pattern.and.default
|
||||||
SwitchErrors.java:42:18: compiler.err.pattern.dominated
|
SwitchErrors.java:42:18: compiler.err.pattern.dominated
|
||||||
SwitchErrors.java:42:24: compiler.err.total.pattern.and.default
|
SwitchErrors.java:42:24: compiler.err.unconditional.pattern.and.default
|
||||||
SwitchErrors.java:48:18: compiler.err.total.pattern.and.default
|
SwitchErrors.java:48:18: compiler.err.unconditional.pattern.and.default
|
||||||
SwitchErrors.java:54:18: compiler.err.duplicate.total.pattern
|
SwitchErrors.java:54:18: compiler.err.duplicate.unconditional.pattern
|
||||||
SwitchErrors.java:60:13: compiler.err.duplicate.default.label
|
SwitchErrors.java:60:13: compiler.err.duplicate.default.label
|
||||||
SwitchErrors.java:66:13: compiler.err.duplicate.default.label
|
SwitchErrors.java:66:13: compiler.err.duplicate.default.label
|
||||||
SwitchErrors.java:71:27: compiler.err.duplicate.default.label
|
SwitchErrors.java:71:27: compiler.err.duplicate.default.label
|
||||||
@ -29,17 +29,18 @@ SwitchErrors.java:148:27: compiler.err.flows.through.to.pattern
|
|||||||
SwitchErrors.java:154:18: compiler.err.flows.through.to.pattern
|
SwitchErrors.java:154:18: compiler.err.flows.through.to.pattern
|
||||||
SwitchErrors.java:160:18: compiler.err.pattern.dominated
|
SwitchErrors.java:160:18: compiler.err.pattern.dominated
|
||||||
SwitchErrors.java:172:18: compiler.err.pattern.expected
|
SwitchErrors.java:172:18: compiler.err.pattern.expected
|
||||||
SwitchErrors.java:178:76: compiler.err.cant.resolve.location: kindname.variable, n, , , (compiler.misc.location: kindname.class, SwitchErrors, null)
|
SwitchErrors.java:178:78: compiler.err.cant.resolve.location: kindname.variable, n, , , (compiler.misc.location: kindname.class, SwitchErrors, null)
|
||||||
SwitchErrors.java:184:71: compiler.err.cant.resolve.location: kindname.variable, n, , , (compiler.misc.location: kindname.class, SwitchErrors, null)
|
SwitchErrors.java:184:73: compiler.err.cant.resolve.location: kindname.variable, n, , , (compiler.misc.location: kindname.class, SwitchErrors, null)
|
||||||
SwitchErrors.java:191:21: compiler.err.flows.through.to.pattern
|
SwitchErrors.java:191:21: compiler.err.flows.through.to.pattern
|
||||||
SwitchErrors.java:200:42: compiler.err.pattern.dominated
|
SwitchErrors.java:200:44: compiler.err.pattern.dominated
|
||||||
SwitchErrors.java:209:24: compiler.err.flows.through.to.pattern
|
SwitchErrors.java:218:29: compiler.err.unconditional.pattern.and.default
|
||||||
SwitchErrors.java:218:29: compiler.err.total.pattern.and.default
|
|
||||||
SwitchErrors.java:225:21: compiler.err.flows.through.to.pattern
|
SwitchErrors.java:225:21: compiler.err.flows.through.to.pattern
|
||||||
SwitchErrors.java:225:45: compiler.err.flows.through.from.pattern
|
SwitchErrors.java:225:47: compiler.err.flows.through.from.pattern
|
||||||
SwitchErrors.java:232:42: compiler.err.pattern.dominated
|
SwitchErrors.java:232:44: compiler.err.pattern.dominated
|
||||||
SwitchErrors.java:232:45: compiler.err.flows.through.from.pattern
|
SwitchErrors.java:232:47: compiler.err.flows.through.from.pattern
|
||||||
SwitchErrors.java:244:18: compiler.err.duplicate.total.pattern
|
SwitchErrors.java:244:18: compiler.err.duplicate.unconditional.pattern
|
||||||
|
SwitchErrors.java:249:18: compiler.err.prob.found.req: (compiler.misc.not.applicable.types: int, java.lang.Integer)
|
||||||
|
SwitchErrors.java:254:18: compiler.err.type.found.req: int, (compiler.misc.type.req.class.array)
|
||||||
SwitchErrors.java:9:9: compiler.err.not.exhaustive.statement
|
SwitchErrors.java:9:9: compiler.err.not.exhaustive.statement
|
||||||
SwitchErrors.java:15:9: compiler.err.not.exhaustive.statement
|
SwitchErrors.java:15:9: compiler.err.not.exhaustive.statement
|
||||||
SwitchErrors.java:21:9: compiler.err.not.exhaustive.statement
|
SwitchErrors.java:21:9: compiler.err.not.exhaustive.statement
|
||||||
@ -54,4 +55,4 @@ SwitchErrors.java:164:9: compiler.err.not.exhaustive.statement
|
|||||||
SwitchErrors.java:237:9: compiler.err.not.exhaustive.statement
|
SwitchErrors.java:237:9: compiler.err.not.exhaustive.statement
|
||||||
- compiler.note.preview.filename: SwitchErrors.java, DEFAULT
|
- compiler.note.preview.filename: SwitchErrors.java, DEFAULT
|
||||||
- compiler.note.preview.recompile
|
- compiler.note.preview.recompile
|
||||||
54 errors
|
55 errors
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -82,7 +82,7 @@ public class Switches {
|
|||||||
switchNestingTest(this::switchNestingExpressionStatement);
|
switchNestingTest(this::switchNestingExpressionStatement);
|
||||||
switchNestingTest(this::switchNestingExpressionExpression);
|
switchNestingTest(this::switchNestingExpressionExpression);
|
||||||
switchNestingTest(this::switchNestingIfSwitch);
|
switchNestingTest(this::switchNestingIfSwitch);
|
||||||
assertEquals(2, switchOverNull1());
|
npeTest(x -> switchOverNull1());
|
||||||
assertEquals(2, switchOverNull2());
|
assertEquals(2, switchOverNull2());
|
||||||
assertEquals(2, switchOverNull3());
|
assertEquals(2, switchOverNull3());
|
||||||
assertEquals(5, switchOverPrimitiveInt(0));
|
assertEquals(5, switchOverPrimitiveInt(0));
|
||||||
@ -269,7 +269,7 @@ public class Switches {
|
|||||||
case A: return "a";
|
case A: return "a";
|
||||||
case B: return "b";
|
case B: return "b";
|
||||||
case C: return String.valueOf(e);
|
case C: return String.valueOf(e);
|
||||||
case E x && "A".equals(x.name()): return "broken";
|
case E x when "A".equals(x.name()): return "broken";
|
||||||
case null, E x: return String.valueOf(x);
|
case null, E x: return String.valueOf(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -279,7 +279,7 @@ public class Switches {
|
|||||||
case A -> "a";
|
case A -> "a";
|
||||||
case B -> "b";
|
case B -> "b";
|
||||||
case C -> String.valueOf(e);
|
case C -> String.valueOf(e);
|
||||||
case E x && "A".equals(x.name()) -> "broken";
|
case E x when "A".equals(x.name()) -> "broken";
|
||||||
case null, E x -> String.valueOf(x);
|
case null, E x -> String.valueOf(x);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -288,7 +288,7 @@ public class Switches {
|
|||||||
switch (e) {
|
switch (e) {
|
||||||
case A: return "a";
|
case A: return "a";
|
||||||
case B: return "b";
|
case B: return "b";
|
||||||
case E x && "C".equals(x.name()): return "C";
|
case E x when "C".equals(x.name()): return "C";
|
||||||
case null, E x: return e == E.C ? "broken" : String.valueOf(x);
|
case null, E x: return e == E.C ? "broken" : String.valueOf(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -297,7 +297,7 @@ public class Switches {
|
|||||||
return switch (e) {
|
return switch (e) {
|
||||||
case A -> "a";
|
case A -> "a";
|
||||||
case B -> "b";
|
case B -> "b";
|
||||||
case E x && "C".equals(x.name()) -> "C";
|
case E x when "C".equals(x.name()) -> "C";
|
||||||
case null, E x -> e == E.C ? "broken" : String.valueOf(x);
|
case null, E x -> e == E.C ? "broken" : String.valueOf(x);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -306,7 +306,7 @@ public class Switches {
|
|||||||
switch (e) {
|
switch (e) {
|
||||||
case A: return "a";
|
case A: return "a";
|
||||||
case B: return "b";
|
case B: return "b";
|
||||||
case Object x && "C".equals(x.toString()): return "C";
|
case Object x when "C".equals(x.toString()): return "C";
|
||||||
case null, E x: return e == E.C ? "broken" : String.valueOf(x);
|
case null, E x: return e == E.C ? "broken" : String.valueOf(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -315,7 +315,7 @@ public class Switches {
|
|||||||
return switch (e) {
|
return switch (e) {
|
||||||
case A -> "a";
|
case A -> "a";
|
||||||
case B -> "b";
|
case B -> "b";
|
||||||
case Object x && "C".equals(x.toString()) -> "C";
|
case Object x when "C".equals(x.toString()) -> "C";
|
||||||
case null, E x -> e == E.C ? "broken" : String.valueOf(x);
|
case null, E x -> e == E.C ? "broken" : String.valueOf(x);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -324,7 +324,7 @@ public class Switches {
|
|||||||
switch (e) {
|
switch (e) {
|
||||||
case A: return "a";
|
case A: return "a";
|
||||||
case B: return "b";
|
case B: return "b";
|
||||||
case Runnable x && "C".equals(x.toString()): return "C";
|
case Runnable x when "C".equals(x.toString()): return "C";
|
||||||
case null, E x: return e == E.C ? "broken" : String.valueOf(x);
|
case null, E x: return e == E.C ? "broken" : String.valueOf(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -333,7 +333,7 @@ public class Switches {
|
|||||||
return switch (e) {
|
return switch (e) {
|
||||||
case A -> "a";
|
case A -> "a";
|
||||||
case B -> "b";
|
case B -> "b";
|
||||||
case Runnable x && "C".equals(x.toString()) -> "C";
|
case Runnable x when "C".equals(x.toString()) -> "C";
|
||||||
case null, E x -> e == E.C ? "broken" : String.valueOf(x);
|
case null, E x -> e == E.C ? "broken" : String.valueOf(x);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -342,7 +342,7 @@ public class Switches {
|
|||||||
switch (e != null ? e.name() : null) {
|
switch (e != null ? e.name() : null) {
|
||||||
case "A": return "a";
|
case "A": return "a";
|
||||||
case Switches.ConstantClassClash: return "b";
|
case Switches.ConstantClassClash: return "b";
|
||||||
case String x && "C".equals(x): return "C";
|
case String x when "C".equals(x): return "C";
|
||||||
case null, String x: return "C".equals(x) ? "broken" : String.valueOf(x);
|
case null, String x: return "C".equals(x) ? "broken" : String.valueOf(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -351,7 +351,7 @@ public class Switches {
|
|||||||
return switch (e != null ? e.name() : null) {
|
return switch (e != null ? e.name() : null) {
|
||||||
case "A" -> "a";
|
case "A" -> "a";
|
||||||
case ConstantClassClash -> "b";
|
case ConstantClassClash -> "b";
|
||||||
case String x && "C".equals(x) -> "C";
|
case String x when "C".equals(x) -> "C";
|
||||||
case null, String x -> e == E.C ? "broken" : String.valueOf(x);
|
case null, String x -> e == E.C ? "broken" : String.valueOf(x);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -360,7 +360,7 @@ public class Switches {
|
|||||||
switch (e != null ? e.ordinal() : null) {
|
switch (e != null ? e.ordinal() : null) {
|
||||||
case 0: return "a";
|
case 0: return "a";
|
||||||
case 1: return "b";
|
case 1: return "b";
|
||||||
case Integer x && x.equals(2): return "C";
|
case Integer x when x.equals(2): return "C";
|
||||||
case null, Integer x: return Objects.equals(x, 2) ? "broken" : String.valueOf(x);
|
case null, Integer x: return Objects.equals(x, 2) ? "broken" : String.valueOf(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -369,7 +369,7 @@ public class Switches {
|
|||||||
return switch (e != null ? e.ordinal() : null) {
|
return switch (e != null ? e.ordinal() : null) {
|
||||||
case 0 -> "a";
|
case 0 -> "a";
|
||||||
case 1 -> "b";
|
case 1 -> "b";
|
||||||
case Integer x && x.equals(2) -> "C";
|
case Integer x when x.equals(2) -> "C";
|
||||||
case null, Integer x -> Objects.equals(x, 2) ? "broken" : String.valueOf(x);
|
case null, Integer x -> Objects.equals(x, 2) ? "broken" : String.valueOf(x);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -378,7 +378,7 @@ public class Switches {
|
|||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case Integer o && o != null:
|
case Integer o when o != null:
|
||||||
r = 1;
|
r = 1;
|
||||||
default:
|
default:
|
||||||
r = 2;
|
r = 2;
|
||||||
@ -389,7 +389,7 @@ public class Switches {
|
|||||||
|
|
||||||
Integer testFallThroughExpression(Integer i) {
|
Integer testFallThroughExpression(Integer i) {
|
||||||
int r = switch (i) {
|
int r = switch (i) {
|
||||||
case Integer o && o != null:
|
case Integer o when o != null:
|
||||||
r = 1;
|
r = 1;
|
||||||
default:
|
default:
|
||||||
r = 2;
|
r = 2;
|
||||||
@ -403,7 +403,7 @@ public class Switches {
|
|||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case Integer o && o != null:
|
case Integer o when o != null:
|
||||||
r = 1;
|
r = 1;
|
||||||
case null, default:
|
case null, default:
|
||||||
r = 2;
|
r = 2;
|
||||||
@ -414,7 +414,7 @@ public class Switches {
|
|||||||
|
|
||||||
Integer testFallThrough2Expression(Integer i) {
|
Integer testFallThrough2Expression(Integer i) {
|
||||||
int r = switch (i) {
|
int r = switch (i) {
|
||||||
case Integer o && o != null:
|
case Integer o when o != null:
|
||||||
r = 1;
|
r = 1;
|
||||||
case null, default:
|
case null, default:
|
||||||
r = 2;
|
r = 2;
|
||||||
@ -439,8 +439,17 @@ public class Switches {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void exhaustiveStatementSane(Object o) {
|
void exhaustiveStatementSane(Object o) {
|
||||||
switch (o) {
|
try {
|
||||||
case Object obj:; //no break intentionally - should not fall through to any possible default
|
switch (o) {
|
||||||
|
case Object obj:; //no break intentionally - should not fall through to any possible default
|
||||||
|
}
|
||||||
|
if (o == null) {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
} catch (NullPointerException ex) {
|
||||||
|
if (o != null) {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
switch (o) {
|
switch (o) {
|
||||||
case null, Object obj:; //no break intentionally - should not fall through to any possible default
|
case null, Object obj:; //no break intentionally - should not fall through to any possible default
|
||||||
@ -597,7 +606,7 @@ public class Switches {
|
|||||||
private int switchOverPrimitiveInt(Integer i) {
|
private int switchOverPrimitiveInt(Integer i) {
|
||||||
return switch (i) {
|
return switch (i) {
|
||||||
case 0 -> 5 + 0;
|
case 0 -> 5 + 0;
|
||||||
case Integer j && j == 1 -> 6 + j;
|
case Integer j when j == 1 -> 6 + j;
|
||||||
case Integer j -> 7 + j;
|
case Integer j -> 7 + j;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user