1
0
mirror of https://github.com/dart-lang/sdk synced 2024-07-05 09:20:04 +00:00

Allow static error tests to detect unreachable case hints from analyzer.

Eventually, these hints should probably be moved over to warnings. But
for now, this makes it possible to write static error language tests
that validate that analyzer produces unreachable case warnings/hints
where expected.

Also updated the patterns/ and switch/ tests now that those errors must
be expected by the test.

Change-Id: If1fb92602c4bde2819b9eec73598033009054947
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/291967
Auto-Submit: Bob Nystrom <rnystrom@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Bob Nystrom <rnystrom@google.com>
This commit is contained in:
Robert Nystrom 2023-03-31 20:50:52 +00:00 committed by Commit Queue
parent a48b408a5a
commit 0196a5b296
15 changed files with 548 additions and 40 deletions

View File

@ -480,6 +480,13 @@ class AnalyzerError implements Comparable<AnalyzerError> {
'unnecessary_null_check_pattern',
};
/// The set of hints which must be expected in a test. Any hint not specified
/// here which is reported by the analyzer does not need to be expected, and
/// never causes a test to fail.
static const Set<String> _specifiedHints = {
'unreachable_switch_case',
};
/// Parses all errors from analyzer [stdout] output.
static List<AnalyzerError> parseStdout(String stdout) {
var result = <AnalyzerError>[];
@ -494,8 +501,10 @@ class AnalyzerError implements Comparable<AnalyzerError> {
for (var diagnostic in jsonData['diagnostics'] as List<dynamic>) {
var diagnosticMap = diagnostic as Map<String, dynamic>;
var code = diagnosticMap['code'] as String;
var type = diagnosticMap['type'] as String?;
if (type == 'HINT') {
if (type == 'HINT' && !_specifiedHints.contains(code)) {
// The analyzer can report hints which do not need to be expected in
// the test source. These can be ignored.
// TODO(srawlins): Hints will start to change to be warnings. There are
@ -505,10 +514,12 @@ class AnalyzerError implements Comparable<AnalyzerError> {
continue;
}
var code = diagnosticMap['code'] as String;
if (type == 'STATIC_WARNING' && !_specifiedWarnings.contains(code)) {
continue;
}
if (type == 'LINT') continue;
var errorCode = '$type.${code.toUpperCase()}';
var error = _parse(
@ -610,7 +621,8 @@ class AnalysisCommandOutput extends CommandOutput with _StaticErrorOutput {
for (var diagnostic in AnalyzerError.parseStdout(stdout)) {
if (diagnostic.severity == 'ERROR') {
errors.add(convert(diagnostic));
} else if (diagnostic.severity == 'WARNING' && warnings != null) {
} else if (warnings != null &&
(diagnostic.severity == 'WARNING' || diagnostic.severity == 'INFO')) {
warnings.add(convert(diagnostic));
}
}

View File

@ -66,6 +66,7 @@ class StaticError implements Comparable<StaticError> {
// of error codes in sdk/pkg/analyzer/lib/error/error.dart. Is there a more
// systematic way to handle this?
static const _analyzerWarningCodes = {
"HINT.UNREACHABLE_SWITCH_CASE",
"STATIC_WARNING.ANALYSIS_OPTION_DEPRECATED",
"STATIC_WARNING.INCLUDE_FILE_NOT_FOUND",
"STATIC_WARNING.INCLUDED_FILE_WARNING",

View File

@ -131,7 +131,8 @@ void unreachableCase1(bool b) {
print('false');
break;
case true: // Unreachable
// ^
// ^^^^
// [analyzer] HINT.UNREACHABLE_SWITCH_CASE
// [cfe] This case is covered by the previous cases.
print('true2');
break;
@ -165,7 +166,8 @@ void unreachableCase3(bool? b) {
print('null1');
break;
case null: // Unreachable
// ^
// ^^^^
// [analyzer] HINT.UNREACHABLE_SWITCH_CASE
// [cfe] This case is covered by the previous cases.
print('null2');
break;

View File

@ -186,7 +186,8 @@ void unreachableCase1(Enum e) {
print('b');
break;
case Enum.a: // Unreachable
// ^
// ^^^^
// [analyzer] HINT.UNREACHABLE_SWITCH_CASE
// [cfe] This case is covered by the previous cases.
print('a2');
break;
@ -209,7 +210,8 @@ void unreachableCase2(Enum e) {
print('b');
break;
case Enum.a: // Unreachable
// ^
// ^^^^
// [analyzer] HINT.UNREACHABLE_SWITCH_CASE
// [cfe] This case is covered by the previous cases.
print('a2');
break;
@ -249,7 +251,8 @@ void unreachableCase4(Enum? e) {
print('null1');
break;
case null: // Unreachable
// ^
// ^^^^
// [analyzer] HINT.UNREACHABLE_SWITCH_CASE
// [cfe] This case is covered by the previous cases.
print('null2');
break;
@ -263,7 +266,8 @@ void unreachableCase5(Enum e) {
break;
case Enum.b:
case Enum.a: // Unreachable
// ^
// ^^^^
// [analyzer] HINT.UNREACHABLE_SWITCH_CASE
// [cfe] This case is covered by the previous cases.
case Enum.c:
print('c');

View File

@ -158,7 +158,8 @@ void unreachableCase1(A r) {
print('A(b, true)');
break;
case A(a: Enum.a, b: false): // Unreachable
// ^
// ^^^^
// [analyzer] HINT.UNREACHABLE_SWITCH_CASE
// [cfe] This case is covered by the previous cases.
print('(a, false) #2');
break;
@ -204,7 +205,8 @@ void unreachableCase3(A? r) {
print('null #1');
break;
case null: // Unreachable
// ^
// ^^^^
// [analyzer] HINT.UNREACHABLE_SWITCH_CASE
// [cfe] This case is covered by the previous cases.
print('null #2');
break;

View File

@ -147,7 +147,8 @@ void unreachableCase1(({Enum a, bool b}) r) {
print('(b, true)');
break;
case (a: Enum.a, b: false): // Unreachable
// ^
// ^^^^
// [analyzer] HINT.UNREACHABLE_SWITCH_CASE
// [cfe] This case is covered by the previous cases.
print('(a, false) #2');
break;
@ -193,7 +194,8 @@ void unreachableCase3(({Enum a, bool b})? r) {
print('null #1');
break;
case null: // Unreachable
// ^
// ^^^^
// [analyzer] HINT.UNREACHABLE_SWITCH_CASE
// [cfe] This case is covered by the previous cases.
print('null #2');
break;

View File

@ -147,7 +147,8 @@ void unreachableCase1((Enum, bool) r) {
print('(b, true)');
break;
case (Enum.a, false): // Unreachable
// ^
// ^^^^
// [analyzer] HINT.UNREACHABLE_SWITCH_CASE
// [cfe] This case is covered by the previous cases.
print('(a, false) #2');
break;
@ -193,7 +194,8 @@ void unreachableCase3((Enum, bool)? r) {
print('null1');
break;
case null: // Unreachable
// ^
// ^^^^
// [analyzer] HINT.UNREACHABLE_SWITCH_CASE
// [cfe] This case is covered by the previous cases.
print('null2');
break;

View File

@ -151,7 +151,8 @@ void unreachableCase1((Enum, bool) r) {
print('(b, true)');
break;
case r0: // Unreachable
// ^
// ^^^^
// [analyzer] HINT.UNREACHABLE_SWITCH_CASE
// [cfe] This case is covered by the previous cases.
print('(a, false) #2');
break;
@ -197,7 +198,8 @@ void unreachableCase3((Enum, bool)? r) {
print('null1');
break;
case null: // Unreachable
// ^
// ^^^^
// [analyzer] HINT.UNREACHABLE_SWITCH_CASE
// [cfe] This case is covered by the previous cases.
print('null2');
break;

View File

@ -151,7 +151,8 @@ void unreachableCase1(A a) {
print('D');
break;
case A a: // Unreachable
// ^
// ^^^^
// [analyzer] HINT.UNREACHABLE_SWITCH_CASE
// [cfe] This case is covered by the previous cases.
print('A');
break;
@ -179,7 +180,8 @@ void unreachableCase3(A? a) {
print('null #1');
break;
case null: // Unreachable
// ^
// ^^^^
// [analyzer] HINT.UNREACHABLE_SWITCH_CASE
// [cfe] This case is covered by the previous cases.
print('null #2');
break;

View File

@ -143,7 +143,8 @@ void unreachableCase1((Enum, bool) r) {
print('(b, true)');
break;
case (Enum a, bool b): // Unreachable
// ^
// ^^^^
// [analyzer] HINT.UNREACHABLE_SWITCH_CASE
// [cfe] This case is covered by the previous cases.
print('(*, *)');
break;
@ -171,7 +172,8 @@ void unreachableCase3((Enum, bool)? r) {
print('null1');
break;
case null: // Unreachable
// ^
// ^^^^
// [analyzer] HINT.UNREACHABLE_SWITCH_CASE
// [cfe] This case is covered by the previous cases.
print('null2');
break;

View File

@ -15,191 +15,389 @@ class Class {
method<T>(o) {
switch (o) {
case 1 || 2: // Ok
}
switch (o) {
case 1 && 2: // Ok
}
switch (o) {
case 1 as T: // Ok
}
switch (o) {
case const Object(): // Ok
}
switch (o) {
case 1 + 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_BINARY
// [cfe] The binary operator + is not supported as a constant pattern.
}
switch (o) {
case 1 - 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_BINARY
// [cfe] The binary operator - is not supported as a constant pattern.
}
switch (o) {
case 1 * 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_BINARY
// [cfe] The binary operator * is not supported as a constant pattern.
}
switch (o) {
case 1 / 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_BINARY
// [cfe] The binary operator / is not supported as a constant pattern.
}
switch (o) {
case 1 ~/ 2: // Error
// ^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_BINARY
// [cfe] The binary operator ~/ is not supported as a constant pattern.
}
switch (o) {
case 1 % 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_BINARY
// [cfe] The binary operator % is not supported as a constant pattern.
}
switch (o) {
case 1 == 2: // Error
// ^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_BINARY
// [cfe] The binary operator == is not supported as a constant pattern.
}
switch (o) {
case 1 != 2: // Error
// ^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_BINARY
// [cfe] The binary operator != is not supported as a constant pattern.
}
switch (o) {
case 1 ^ 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_BINARY
// [cfe] The binary operator ^ is not supported as a constant pattern.
}
switch (o) {
case 1 & 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_BINARY
// [cfe] The binary operator & is not supported as a constant pattern.
}
switch (o) {
case 1 | 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_BINARY
// [cfe] The binary operator | is not supported as a constant pattern.
}
switch (o) {
case 1 < 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_BINARY
// [cfe] The binary operator < is not supported as a constant pattern.
}
switch (o) {
case 1 <= 2: // Error
// ^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_BINARY
// [cfe] The binary operator <= is not supported as a constant pattern.
}
switch (o) {
case 1 > 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_BINARY
// [cfe] The binary operator > is not supported as a constant pattern.
}
switch (o) {
case 1 >= 2: // Error
// ^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_BINARY
// [cfe] The binary operator >= is not supported as a constant pattern.
}
switch (o) {
case 1 << 2: // Error
// ^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_BINARY
// [cfe] The binary operator << is not supported as a constant pattern.
}
switch (o) {
case 1 >> 2: // Error
// ^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_BINARY
// [cfe] The binary operator >> is not supported as a constant pattern.
}
switch (o) {
case 1 >>> 2: // Error
// ^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_BINARY
// [cfe] The binary operator >>> is not supported as a constant pattern.
}
switch (o) {
case 1 + 2 + 3: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_BINARY
// [cfe] The binary operator + is not supported as a constant pattern.
}
switch (o) {
case prefix.value as T: // Ok
}
switch (o) {
case prefix.Class.value as T: // Ok
}
switch (o) {
case const 1 as int: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const 1 + 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const 1 - 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const 1 * 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const 1 / 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const 1 ~/ 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const 1 % 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const 1 == 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const 1 != 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const 1 ^ 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const 1 & 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const 1 | 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const 1 < 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const 1 <= 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const 1 > 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const 1 >= 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const 1 << 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const 1 >> 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const 1 >>> 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const 1 + 2 + 3: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const Object() == 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const <int>[] as List<T>: // Ok
}
switch (o) {
case const (1 + 2): // Ok
}
switch (o) {
case const (1 - 2): // Ok
}
switch (o) {
case const (1 * 2): // Ok
}
switch (o) {
case const (1 / 2): // Ok
}
switch (o) {
case const (1 ~/ 2): // Ok
}
switch (o) {
case const (1 % 2): // Ok
}
switch (o) {
case const (1 == 2): // Ok
}
switch (o) {
case const (1 != 2): // Ok
}
switch (o) {
case const (1 ^ 2): // Ok
}
switch (o) {
case const (1 & 2): // Ok
}
switch (o) {
case const (1 | 2): // Ok
}
switch (o) {
case const (1 < 2): // Ok
}
switch (o) {
case const (1 <= 2): // Ok
}
switch (o) {
case const (1 > 2): // Ok
}
switch (o) {
case const (1 >= 2): // Ok
}
switch (o) {
case const (1 << 2): // Ok
}
switch (o) {
case const (1 >> 2): // Ok
}
switch (o) {
case const (1 >>> 2): // Ok
}
switch (o) {
case const (1 + 2 + 3): // Ok
}
switch (o) {
case 1 ?? 2: // Error
// ^^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
@ -214,24 +412,32 @@ method<T>(o) {
// [analyzer] SYNTACTIC_ERROR.UNEXPECTED_TOKEN
// [cfe] Expected an identifier, but got ':'.
// [cfe] Unexpected token ':'.
}
switch (o) {
case o++: // Error
// ^
// [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
// ^^^
// [analyzer] COMPILE_TIME_ERROR.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION
// [cfe] Not a constant expression.
}
switch (o) {
case o--: // Error
// ^^^
// [analyzer] COMPILE_TIME_ERROR.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION
// [cfe] Not a constant expression.
// ^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_OPERATOR
}
switch (o) {
case ++o: // Error
// ^^^
// [analyzer] COMPILE_TIME_ERROR.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION
// ^
// [analyzer] COMPILE_TIME_ERROR.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION
// [cfe] Not a constant expression.
}
switch (o) {
case --o: // Error
// ^^^
// [analyzer] COMPILE_TIME_ERROR.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION

View File

@ -22,42 +22,102 @@ class Class {
dynamic variable = 0;
switch (o) {
case true: // Ok
}
switch (o) {
case null: // Ok
}
switch (o) {
case this: // Error
// ^^^^
// [analyzer] COMPILE_TIME_ERROR.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION
// [cfe] Not a constant expression.
}
switch (o) {
case this(): // Error
// ^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION
// [cfe] Not a constant expression.
}
switch (o) {
case super(): // Error
// ^^^^^
// [analyzer] COMPILE_TIME_ERROR.INVOCATION_OF_NON_FUNCTION_EXPRESSION
// ^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION
// [cfe] Method invocation is not a constant expression.
}
switch (o) {
case 42: // Ok
}
switch (o) {
case -42: // Ok
}
switch (o) {
case 42.5: // Ok
}
switch (o) {
case -42.5: // Ok
}
switch (o) {
case 'foo': // Ok
}
switch (o) {
case 'foo' 'bar': // Ok
}
switch (o) {
case value: // Ok
}
switch (o) {
case value!: // Ok
}
switch (o) {
case value?: // Ok
}
switch (o) {
case value as int: // Ok
}
switch (o) {
case -value: // Error
// ^^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_NEGATION
// [cfe] Only negation of a numeric literal is supported as a constant pattern.
}
switch (o) {
case local: // Ok
}
switch (o) {
case -local: // Error
// ^^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_NEGATION
// [cfe] Only negation of a numeric literal is supported as a constant pattern.
}
switch (o) {
case func: // Ok
}
switch (o) {
case prefix.value: // Ok
}
switch (o) {
case -prefix.value: // Error
// ^^^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_NEGATION
@ -65,15 +125,27 @@ class Class {
// ^^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_NEGATION
// [cfe] Only negation of a numeric literal is supported as a constant pattern.
}
switch (o) {
case prefix.Class.named: // Ok
}
switch (o) {
case 1 + 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_BINARY
// [cfe] The binary operator + is not supported as a constant pattern.
}
switch (o) {
case 1 * 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_BINARY
// [cfe] The binary operator * is not supported as a constant pattern.
}
switch (o) {
case void fun() {}: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
@ -86,92 +158,155 @@ class Class {
// [analyzer] SYNTACTIC_ERROR.UNEXPECTED_TOKEN
// [cfe] Expected an identifier, but got ':'.
// [cfe] Unexpected token ':'.
}
switch (o) {
case assert(false): // Error
// ^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
// ^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION
// [cfe] `assert` can't be used as an expression.
}
switch (o) {
case switch (o) { _ => true }: // Error
// ^^^^^^^^^^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION
// [cfe] Not a constant expression.
// ^
// [cfe] Not a constant expression.
}
switch (o) {
case await 0: // Error
// ^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION
// [cfe] Not a constant expression.
}
switch (o) {
case !false: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_UNARY
// [cfe] The unary operator ! is not supported as a constant pattern.
}
switch (o) {
case ~0: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_UNARY
// [cfe] The unary operator ~ is not supported as a constant pattern.
}
switch (o) {
case ++variable: // Error
// ^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION
// ^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION
// [cfe] Not a constant expression.
}
switch (o) {
case const 0: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const 0x0: // Error
// ^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const 0.5: // Error
// ^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const true: // Error
// ^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const null: // Error
// ^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const -0: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const 'foo': // Error
// ^^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const #a: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const value: // Error
// ^^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const local: // Error
// ^^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const prefix.value: // Error
// ^^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const -prefix.value: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const prefix.Class.named: // Error
// ^^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const 1 + 2: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_CONST_PREFIX
// [cfe] The expression can't be prefixed by 'const' to form a constant pattern.
}
switch (o) {
case const void fun() {}: // Error
// ^
// [cfe] Not a constant expression.
@ -180,140 +315,281 @@ class Class {
// [cfe] A function expression can't have a name.
// ^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION
}
switch (o) {
case const assert(false): // Error
// ^^^^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
// ^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION
// [cfe] `assert` can't be used as an expression.
}
switch (o) {
case const switch (o) { _ => true }: // Error
// ^^^^^^^^^^^^^^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION
// [cfe] Not a constant expression.
// ^
// [cfe] Not a constant expression.
}
switch (o) {
case const await 0: // Error
// ^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION
// [cfe] Not a constant expression.
}
switch (o) {
case const !false: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_UNARY
// [cfe] The unary operator ! is not supported as a constant pattern.
}
switch (o) {
case const ~0: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_UNARY
// [cfe] The unary operator ~ is not supported as a constant pattern.
}
switch (o) {
case const ++variable: // Error
// ^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION
// ^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION
// [cfe] Not a constant expression.
}
switch (o) {
case const Class(): // Ok
}
switch (o) {
case const Class(0): // Ok
}
switch (o) {
case const GenericClass(): // Ok
}
switch (o) {
case const GenericClass(a: 0): // Ok
}
switch (o) {
case const GenericClass<int>(): // Ok
}
switch (o) {
case const GenericClass<int>(a: 0): // Ok
}
switch (o) {
case const GenericClass<int>.new(): // Ok
}
switch (o) {
case const GenericClass<int>.new(a: 1): // Ok
}
switch (o) {
case const []: // Ok
}
switch (o) {
case const <int>[]: // Ok
}
switch (o) {
case const {}: // Ok
}
switch (o) {
case const <int, String>{}: // Ok
}
switch (o) {
case const const Class(): // Error
// ^^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_DUPLICATE_CONST
// [cfe] Duplicate 'const' keyword in constant expression.
}
switch (o) {
case const const Class(0): // Error
// ^^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_DUPLICATE_CONST
// [cfe] Duplicate 'const' keyword in constant expression.
}
switch (o) {
case const const GenericClass(): // Error
// ^^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_DUPLICATE_CONST
// [cfe] Duplicate 'const' keyword in constant expression.
}
switch (o) {
case const const GenericClass(a: 0): // Error
// ^^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_DUPLICATE_CONST
// [cfe] Duplicate 'const' keyword in constant expression.
}
switch (o) {
case const const GenericClass<int>(): // Error
// ^^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_DUPLICATE_CONST
// [cfe] Duplicate 'const' keyword in constant expression.
}
switch (o) {
case const const GenericClass<int>(a: 0): // Error
// ^^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_DUPLICATE_CONST
// [cfe] Duplicate 'const' keyword in constant expression.
}
switch (o) {
case const const []: // Error
// ^^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_DUPLICATE_CONST
// [cfe] Duplicate 'const' keyword in constant expression.
}
switch (o) {
case const const <int>[]: // Error
// ^^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_DUPLICATE_CONST
// [cfe] Duplicate 'const' keyword in constant expression.
}
switch (o) {
case const const {}: // Error
// ^^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_DUPLICATE_CONST
// [cfe] Duplicate 'const' keyword in constant expression.
}
switch (o) {
case const const <int, String>{}: // Error
// ^^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_DUPLICATE_CONST
// [cfe] Duplicate 'const' keyword in constant expression.
}
switch (o) {
case const new Class(): // Error
// ^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION
// [cfe] New expression is not a constant expression.
// ^
// [cfe] New expression is not a constant expression.
}
switch (o) {
case new Class(): // Error
// ^^^^^^^^^^^
// [analyzer] COMPILE_TIME_ERROR.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION
// [cfe] New expression is not a constant expression.
// ^
// [cfe] New expression is not a constant expression.
}
switch (o) {
case const (): // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_EMPTY_RECORD_LITERAL
// [cfe] The empty record literal is not supported as a constant pattern.
}
switch (o) {
case const const (): // Error
// ^^^^^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_DUPLICATE_CONST
// [cfe] Duplicate 'const' keyword in constant expression.
}
switch (o) {
case const (1): // Ok
}
switch (o) {
case const (-1): // Ok
}
switch (o) {
case const (value): // Ok
}
switch (o) {
case const (-value): // Ok
}
switch (o) {
case const (1 + 2): // Ok
}
switch (o) {
case GenericClass<int>: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_GENERIC
// [cfe] This expression is not supported as a constant pattern.
}
switch (o) {
case prefix.GenericClass<int>: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_GENERIC
// [cfe] This expression is not supported as a constant pattern.
}
switch (o) {
case GenericClass<int>.new: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_GENERIC
// [cfe] This expression is not supported as a constant pattern.
}
switch (o) {
case prefix.GenericClass<int>.new: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_GENERIC
// [cfe] This expression is not supported as a constant pattern.
}
switch (o) {
case const GenericClass<int>: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_GENERIC
// [cfe] This expression is not supported as a constant pattern.
}
switch (o) {
case const prefix.GenericClass<int>: // Error
// ^
// [analyzer] SYNTACTIC_ERROR.INVALID_CONSTANT_PATTERN_GENERIC
// [cfe] This expression is not supported as a constant pattern.
}
switch (o) {
case const (GenericClass<int>): // Ok
}
switch (o) {
case const (prefix.GenericClass<int>): // Ok
}
switch (o) {
case const (GenericClass<int>.new): // Ok
}
switch (o) {
case const (prefix.GenericClass<int>.new): // Ok
print(0);
}

View File

@ -10,7 +10,7 @@ main() {
// If cases sharing a body don't agree on a variable's finality, it is still
// considered in scope and an error to use.
switch ('value') {
case final int local:
case final int local when false: // Guard to make the next case reachable.
case int local:
print(local);
// ^^^^^

View File

@ -26,9 +26,9 @@ main() {
// It's an error to have an empty map pattern.
switch (map) {
case {}:
// ^^
// [analyzer] unspecified
// [cfe] unspecified
// ^^^^
// [analyzer] HINT.UNREACHABLE_SWITCH_CASE
// [cfe] unspecified
}
// Later cases may be unreachable because map patterns ignore extra keys.

View File

@ -1,6 +1,3 @@
// TODO(multitest): This was automatically migrated from a multitest and may
// contain strange or dead code.
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
@ -16,8 +13,6 @@ class A {
class B implements A {
const B();
}
class C implements D {
@ -32,27 +27,27 @@ class D implements A {
}
main() {
switch (new B()) {
}
switch (new C()) {
case const C():
Expect.fail("bad switch");
break;
}
switch (new C()) {
case const A.C() as C:
Expect.fail("bad switch");
break;
}
switch (new C()) {
case const A.C2() as C:
Expect.fail("bad switch");
break;
}
switch (new A()) {
case const A():
Expect.fail("bad switch");
break;
}
}