mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 09:58:32 +00:00
Report CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION
Change-Id: Idb6d0963515457e1748362dbda1441d5820a040a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/273521 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
parent
4275d595b6
commit
48d0d95edb
|
@ -336,6 +336,8 @@ CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR:
|
|||
status: needsEvaluation
|
||||
CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT:
|
||||
status: needsEvaluation
|
||||
CompileTimeErrorCode.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION:
|
||||
status: needsEvaluation
|
||||
CompileTimeErrorCode.CONTINUE_LABEL_ON_SWITCH:
|
||||
status: needsEvaluation
|
||||
CompileTimeErrorCode.COULD_NOT_INFER:
|
||||
|
|
|
@ -4302,6 +4302,8 @@ abstract class ExpressionImpl extends AstNodeImpl
|
|||
var parent = child.parent;
|
||||
if (parent is ConstantContextForExpressionImpl) {
|
||||
return true;
|
||||
} else if (parent is ConstantPatternImpl) {
|
||||
return true;
|
||||
} else if (parent is EnumConstantArguments) {
|
||||
return true;
|
||||
} else if (parent is TypedLiteralImpl && parent.constKeyword != null) {
|
||||
|
|
|
@ -99,6 +99,16 @@ class ConstantVerifier extends RecursiveAstVisitor<void> {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitConstantPattern(ConstantPattern node) {
|
||||
_validate(
|
||||
node.expression,
|
||||
CompileTimeErrorCode.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION,
|
||||
);
|
||||
|
||||
super.visitConstantPattern(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitConstructorDeclaration(ConstructorDeclaration node) {
|
||||
var constKeyword = node.constKeyword;
|
||||
|
|
|
@ -22,6 +22,11 @@ class ConstantExpressionsDependenciesFinder extends RecursiveAstVisitor {
|
|||
HashSet<ConstantEvaluationTarget> dependencies =
|
||||
HashSet<ConstantEvaluationTarget>();
|
||||
|
||||
@override
|
||||
visitConstantPattern(ConstantPattern node) {
|
||||
_find(node.expression);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitInstanceCreationExpression(InstanceCreationExpression node) {
|
||||
if (node.isConst) {
|
||||
|
|
|
@ -620,6 +620,14 @@ class CompileTimeErrorCode extends AnalyzerErrorCode {
|
|||
uniqueName: 'CONFLICTING_TYPE_VARIABLE_AND_MIXIN',
|
||||
);
|
||||
|
||||
/// No parameters.
|
||||
static const CompileTimeErrorCode
|
||||
CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION = CompileTimeErrorCode(
|
||||
'CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION',
|
||||
"The expression of a constant pattern must be a valid constant.",
|
||||
correctionMessage: "Try making the expression a valid constant.",
|
||||
);
|
||||
|
||||
/// 16.12.2 Const: It is a compile-time error if evaluation of a constant
|
||||
/// object results in an uncaught exception being thrown.
|
||||
///
|
||||
|
|
|
@ -88,6 +88,7 @@ const List<ErrorCode> errorCodeValues = [
|
|||
CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_EXTENSION,
|
||||
CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER_MIXIN,
|
||||
CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MIXIN,
|
||||
CompileTimeErrorCode.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION,
|
||||
CompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
|
||||
CompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
|
||||
CompileTimeErrorCode.CONST_CONSTRUCTOR_THROWS_EXCEPTION,
|
||||
|
|
|
@ -2878,6 +2878,10 @@ CompileTimeErrorCode:
|
|||
|
||||
Parameters:
|
||||
0: the name of the type
|
||||
CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION:
|
||||
problemMessage: The expression of a constant pattern must be a valid constant.
|
||||
correctionMessage: Try making the expression a valid constant.
|
||||
comment: No parameters.
|
||||
CONTINUE_LABEL_ON_SWITCH:
|
||||
problemMessage: A `continue` label resolves to a `switch` statement, but the label must be on a loop or a switch member.
|
||||
hasPublishedDocs: true
|
||||
|
|
|
@ -298,7 +298,6 @@ class C {
|
|||
assertInContext("C()}", true);
|
||||
}
|
||||
|
||||
@FailingTest(reason: 'not yet implemented')
|
||||
test_inConstantContext_instanceCreation_switch_true() {
|
||||
parse('''
|
||||
f(v) {
|
||||
|
@ -479,7 +478,6 @@ final x = const (0, [1]);
|
|||
assertInContext('[1]', true);
|
||||
}
|
||||
|
||||
@FailingTest(reason: 'not yet implemented')
|
||||
test_inConstantContext_listLiteral_switch_true() {
|
||||
parse('''
|
||||
f(v) {
|
||||
|
@ -607,7 +605,6 @@ f() {
|
|||
assertInContext("{'d", true);
|
||||
}
|
||||
|
||||
@FailingTest(reason: 'not yet implemented')
|
||||
test_inConstantContext_mapLiteral_switch_true() {
|
||||
parse('''
|
||||
f(v) {
|
||||
|
|
|
@ -40,9 +40,10 @@ CastPattern
|
|||
|
||||
test_switchCase() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(x, y) {
|
||||
void f(x) {
|
||||
const a = 0;
|
||||
switch (x) {
|
||||
case y as int:
|
||||
case a as int:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -52,9 +53,9 @@ void f(x, y) {
|
|||
CastPattern
|
||||
pattern: ConstantPattern
|
||||
expression: SimpleIdentifier
|
||||
token: y
|
||||
staticElement: self::@function::f::@parameter::y
|
||||
staticType: dynamic
|
||||
token: a
|
||||
staticElement: a@20
|
||||
staticType: int
|
||||
asToken: as
|
||||
type: NamedType
|
||||
name: SimpleIdentifier
|
||||
|
|
|
@ -199,8 +199,12 @@ IfElement
|
|||
|
||||
test_rewrite_caseClause_pattern() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(Object x, int Function() a) {
|
||||
[if (x case const a()) 0];
|
||||
void f(Object x) {
|
||||
[if (x case const A()) 0];
|
||||
}
|
||||
|
||||
class A {
|
||||
const A();
|
||||
}
|
||||
''');
|
||||
|
||||
|
@ -218,17 +222,19 @@ IfElement
|
|||
guardedPattern: GuardedPattern
|
||||
pattern: ConstantPattern
|
||||
const: const
|
||||
expression: FunctionExpressionInvocation
|
||||
function: SimpleIdentifier
|
||||
token: a
|
||||
staticElement: self::@function::f::@parameter::a
|
||||
staticType: int Function()
|
||||
expression: InstanceCreationExpression
|
||||
constructorName: ConstructorName
|
||||
type: NamedType
|
||||
name: SimpleIdentifier
|
||||
token: A
|
||||
staticElement: self::@class::A
|
||||
staticType: null
|
||||
type: A
|
||||
staticElement: self::@class::A::@constructor::new
|
||||
argumentList: ArgumentList
|
||||
leftParenthesis: (
|
||||
rightParenthesis: )
|
||||
staticElement: <null>
|
||||
staticInvokeType: int Function()
|
||||
staticType: int
|
||||
staticType: A
|
||||
rightParenthesis: )
|
||||
thenElement: IntegerLiteral
|
||||
literal: 0
|
||||
|
|
|
@ -927,8 +927,12 @@ IfStatement
|
|||
|
||||
test_rewrite_caseClause_pattern() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(x, int Function() a) {
|
||||
if (x case const a()) {}
|
||||
void f(x) {
|
||||
if (x case const A()) {}
|
||||
}
|
||||
|
||||
class A {
|
||||
const A();
|
||||
}
|
||||
''');
|
||||
|
||||
|
@ -946,17 +950,19 @@ IfStatement
|
|||
guardedPattern: GuardedPattern
|
||||
pattern: ConstantPattern
|
||||
const: const
|
||||
expression: FunctionExpressionInvocation
|
||||
function: SimpleIdentifier
|
||||
token: a
|
||||
staticElement: self::@function::f::@parameter::a
|
||||
staticType: int Function()
|
||||
expression: InstanceCreationExpression
|
||||
constructorName: ConstructorName
|
||||
type: NamedType
|
||||
name: SimpleIdentifier
|
||||
token: A
|
||||
staticElement: self::@class::A
|
||||
staticType: null
|
||||
type: A
|
||||
staticElement: self::@class::A::@constructor::new
|
||||
argumentList: ArgumentList
|
||||
leftParenthesis: (
|
||||
rightParenthesis: )
|
||||
staticElement: <null>
|
||||
staticInvokeType: int Function()
|
||||
staticType: int
|
||||
staticType: A
|
||||
rightParenthesis: )
|
||||
thenStatement: Block
|
||||
leftBracket: {
|
||||
|
|
|
@ -94,12 +94,16 @@ SwitchExpressionCase
|
|||
|
||||
test_rewrite_case_pattern() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(Object? x, int Function() a) {
|
||||
void f(Object? x) {
|
||||
(switch (x) {
|
||||
const a() => 0,
|
||||
const A() => 0,
|
||||
_ => 1,
|
||||
});
|
||||
}
|
||||
|
||||
class A {
|
||||
const A();
|
||||
}
|
||||
''');
|
||||
|
||||
final node = findNode.switchExpressionCase('=> 0');
|
||||
|
@ -108,17 +112,19 @@ SwitchExpressionCase
|
|||
guardedPattern: GuardedPattern
|
||||
pattern: ConstantPattern
|
||||
const: const
|
||||
expression: FunctionExpressionInvocation
|
||||
function: SimpleIdentifier
|
||||
token: a
|
||||
staticElement: self::@function::f::@parameter::a
|
||||
staticType: int Function()
|
||||
expression: InstanceCreationExpression
|
||||
constructorName: ConstructorName
|
||||
type: NamedType
|
||||
name: SimpleIdentifier
|
||||
token: A
|
||||
staticElement: self::@class::A
|
||||
staticType: null
|
||||
type: A
|
||||
staticElement: self::@class::A::@constructor::new
|
||||
argumentList: ArgumentList
|
||||
leftParenthesis: (
|
||||
rightParenthesis: )
|
||||
staticElement: <null>
|
||||
staticInvokeType: int Function()
|
||||
staticType: int
|
||||
staticType: A
|
||||
arrow: =>
|
||||
expression: IntegerLiteral
|
||||
literal: 0
|
||||
|
|
|
@ -134,12 +134,16 @@ SwitchStatement
|
|||
|
||||
test_rewrite_pattern() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(Object? x, int Function() a) {
|
||||
void f(Object? x) {
|
||||
switch (x) {
|
||||
case const a():
|
||||
case const A():
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
class A {
|
||||
const A();
|
||||
}
|
||||
''');
|
||||
|
||||
final node = findNode.switchStatement('switch');
|
||||
|
@ -159,17 +163,19 @@ SwitchStatement
|
|||
guardedPattern: GuardedPattern
|
||||
pattern: ConstantPattern
|
||||
const: const
|
||||
expression: FunctionExpressionInvocation
|
||||
function: SimpleIdentifier
|
||||
token: a
|
||||
staticElement: self::@function::f::@parameter::a
|
||||
staticType: int Function()
|
||||
expression: InstanceCreationExpression
|
||||
constructorName: ConstructorName
|
||||
type: NamedType
|
||||
name: SimpleIdentifier
|
||||
token: A
|
||||
staticElement: self::@class::A
|
||||
staticType: null
|
||||
type: A
|
||||
staticElement: self::@class::A::@constructor::new
|
||||
argumentList: ArgumentList
|
||||
leftParenthesis: (
|
||||
rightParenthesis: )
|
||||
staticElement: <null>
|
||||
staticInvokeType: int Function()
|
||||
staticType: int
|
||||
staticType: A
|
||||
colon: :
|
||||
statements
|
||||
BreakStatement
|
||||
|
|
|
@ -0,0 +1,530 @@
|
|||
// Copyright (c) 2022, 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.
|
||||
|
||||
import 'package:analyzer/src/error/codes.dart';
|
||||
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||
|
||||
import '../dart/resolution/context_collection_resolution.dart';
|
||||
|
||||
main() {
|
||||
defineReflectiveSuite(() {
|
||||
defineReflectiveTests(ConstantPatternWithNonConstantExpressionTest);
|
||||
});
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class ConstantPatternWithNonConstantExpressionTest
|
||||
extends PubPackageResolutionTest {
|
||||
test_boolLiteral() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(x) {
|
||||
if (x case true) {}
|
||||
}
|
||||
''');
|
||||
|
||||
var node = findNode.singleGuardedPattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
GuardedPattern
|
||||
pattern: ConstantPattern
|
||||
expression: BooleanLiteral
|
||||
literal: true
|
||||
staticType: bool
|
||||
''');
|
||||
}
|
||||
|
||||
test_class_field_const() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
class A {
|
||||
static const a = 0;
|
||||
}
|
||||
|
||||
void f(x) {
|
||||
if (x case A.a) {}
|
||||
}
|
||||
''');
|
||||
|
||||
var node = findNode.singleGuardedPattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
GuardedPattern
|
||||
pattern: ConstantPattern
|
||||
expression: PrefixedIdentifier
|
||||
prefix: SimpleIdentifier
|
||||
token: A
|
||||
staticElement: self::@class::A
|
||||
staticType: null
|
||||
period: .
|
||||
identifier: SimpleIdentifier
|
||||
token: a
|
||||
staticElement: self::@class::A::@getter::a
|
||||
staticType: int
|
||||
staticElement: self::@class::A::@getter::a
|
||||
staticType: int
|
||||
''');
|
||||
}
|
||||
|
||||
test_class_field_notConst() async {
|
||||
await assertErrorsInCode(r'''
|
||||
class A {
|
||||
static final a = 0;
|
||||
}
|
||||
|
||||
void f(x) {
|
||||
if (x case A.a) {}
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION,
|
||||
60, 3),
|
||||
]);
|
||||
}
|
||||
|
||||
test_doubleLiteral() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(x) {
|
||||
if (x case 1.2) {}
|
||||
}
|
||||
''');
|
||||
|
||||
var node = findNode.singleGuardedPattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
GuardedPattern
|
||||
pattern: ConstantPattern
|
||||
expression: DoubleLiteral
|
||||
literal: 1.2
|
||||
staticType: double
|
||||
''');
|
||||
}
|
||||
|
||||
test_importPredix_class_field_const() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
class A {
|
||||
static const a = 0;
|
||||
}
|
||||
''');
|
||||
|
||||
await assertNoErrorsInCode(r'''
|
||||
import 'a.dart' as prefix;
|
||||
|
||||
void f(x) {
|
||||
if (x case prefix.A.a) {}
|
||||
}
|
||||
''');
|
||||
|
||||
var node = findNode.singleGuardedPattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
GuardedPattern
|
||||
pattern: ConstantPattern
|
||||
expression: PropertyAccess
|
||||
target: PrefixedIdentifier
|
||||
prefix: SimpleIdentifier
|
||||
token: prefix
|
||||
staticElement: self::@prefix::prefix
|
||||
staticType: null
|
||||
period: .
|
||||
identifier: SimpleIdentifier
|
||||
token: A
|
||||
staticElement: package:test/a.dart::@class::A
|
||||
staticType: null
|
||||
staticElement: package:test/a.dart::@class::A
|
||||
staticType: null
|
||||
operator: .
|
||||
propertyName: SimpleIdentifier
|
||||
token: a
|
||||
staticElement: package:test/a.dart::@class::A::@getter::a
|
||||
staticType: int
|
||||
staticType: int
|
||||
''');
|
||||
}
|
||||
|
||||
test_importPredix_class_field_notConst() async {
|
||||
newFile('$testPackageLibPath/a.dart', r'''
|
||||
class A {
|
||||
static const a = 0;
|
||||
}
|
||||
''');
|
||||
|
||||
await assertNoErrorsInCode(r'''
|
||||
import 'a.dart' as prefix;
|
||||
|
||||
void f(x) {
|
||||
if (x case prefix.A.a) {}
|
||||
}
|
||||
''');
|
||||
|
||||
var node = findNode.singleGuardedPattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
GuardedPattern
|
||||
pattern: ConstantPattern
|
||||
expression: PropertyAccess
|
||||
target: PrefixedIdentifier
|
||||
prefix: SimpleIdentifier
|
||||
token: prefix
|
||||
staticElement: self::@prefix::prefix
|
||||
staticType: null
|
||||
period: .
|
||||
identifier: SimpleIdentifier
|
||||
token: A
|
||||
staticElement: package:test/a.dart::@class::A
|
||||
staticType: null
|
||||
staticElement: package:test/a.dart::@class::A
|
||||
staticType: null
|
||||
operator: .
|
||||
propertyName: SimpleIdentifier
|
||||
token: a
|
||||
staticElement: package:test/a.dart::@class::A::@getter::a
|
||||
staticType: int
|
||||
staticType: int
|
||||
''');
|
||||
}
|
||||
|
||||
test_instanceCreation_const() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
class A {
|
||||
const A();
|
||||
}
|
||||
|
||||
void f(x) {
|
||||
if (x case const A()) {}
|
||||
}
|
||||
''');
|
||||
|
||||
var node = findNode.singleGuardedPattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
GuardedPattern
|
||||
pattern: ConstantPattern
|
||||
const: const
|
||||
expression: InstanceCreationExpression
|
||||
constructorName: ConstructorName
|
||||
type: NamedType
|
||||
name: SimpleIdentifier
|
||||
token: A
|
||||
staticElement: self::@class::A
|
||||
staticType: null
|
||||
type: A
|
||||
staticElement: self::@class::A::@constructor::new
|
||||
argumentList: ArgumentList
|
||||
leftParenthesis: (
|
||||
rightParenthesis: )
|
||||
staticType: A
|
||||
''');
|
||||
}
|
||||
|
||||
test_intLiteral() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(x) {
|
||||
if (x case 0) {}
|
||||
}
|
||||
''');
|
||||
|
||||
var node = findNode.singleGuardedPattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
GuardedPattern
|
||||
pattern: ConstantPattern
|
||||
expression: IntegerLiteral
|
||||
literal: 0
|
||||
staticType: int
|
||||
''');
|
||||
}
|
||||
|
||||
test_listLiteral_element_intLiteral() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(x) {
|
||||
if (x case const [0]) {}
|
||||
}
|
||||
''');
|
||||
|
||||
var node = findNode.singleGuardedPattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
GuardedPattern
|
||||
pattern: ConstantPattern
|
||||
const: const
|
||||
expression: ListLiteral
|
||||
leftBracket: [
|
||||
elements
|
||||
IntegerLiteral
|
||||
literal: 0
|
||||
staticType: int
|
||||
rightBracket: ]
|
||||
staticType: List<int>
|
||||
''');
|
||||
}
|
||||
|
||||
test_listLiteral_element_localVariable_const() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(x) {
|
||||
const a = 0;
|
||||
if (x case const [a]) {}
|
||||
}
|
||||
''');
|
||||
|
||||
var node = findNode.singleGuardedPattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
GuardedPattern
|
||||
pattern: ConstantPattern
|
||||
const: const
|
||||
expression: ListLiteral
|
||||
leftBracket: [
|
||||
elements
|
||||
SimpleIdentifier
|
||||
token: a
|
||||
staticElement: a@20
|
||||
staticType: int
|
||||
rightBracket: ]
|
||||
staticType: List<int>
|
||||
''');
|
||||
}
|
||||
|
||||
test_listLiteral_element_localVariable_notConst() async {
|
||||
await assertErrorsInCode(r'''
|
||||
void f(x) {
|
||||
final a = 0;
|
||||
if (x case const [a]) {}
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION,
|
||||
47, 1),
|
||||
error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 47, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_localVariable_const() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(x) {
|
||||
const a = 0;
|
||||
if (x case a) {}
|
||||
}
|
||||
''');
|
||||
|
||||
var node = findNode.singleGuardedPattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
GuardedPattern
|
||||
pattern: ConstantPattern
|
||||
expression: SimpleIdentifier
|
||||
token: a
|
||||
staticElement: a@20
|
||||
staticType: int
|
||||
''');
|
||||
}
|
||||
|
||||
test_localVariable_notConst() async {
|
||||
await assertErrorsInCode(r'''
|
||||
void f(x) {
|
||||
var a = 0;
|
||||
if (x case a) {}
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION,
|
||||
38, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mapLiteral_entries_intLiteral_intLiteral() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(x) {
|
||||
if (x case const {0: 1}) {}
|
||||
}
|
||||
''');
|
||||
|
||||
var node = findNode.singleGuardedPattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
GuardedPattern
|
||||
pattern: ConstantPattern
|
||||
const: const
|
||||
expression: SetOrMapLiteral
|
||||
leftBracket: {
|
||||
elements
|
||||
SetOrMapLiteral
|
||||
key: IntegerLiteral
|
||||
literal: 0
|
||||
staticType: int
|
||||
separator: :
|
||||
value: IntegerLiteral
|
||||
literal: 1
|
||||
staticType: int
|
||||
rightBracket: }
|
||||
isMap: true
|
||||
staticType: Map<int, int>
|
||||
''');
|
||||
}
|
||||
|
||||
test_mapLiteral_entries_key_localVariable_const() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(x) {
|
||||
const a = 0;
|
||||
if (x case const {a: 1}) {}
|
||||
}
|
||||
''');
|
||||
|
||||
var node = findNode.singleGuardedPattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
GuardedPattern
|
||||
pattern: ConstantPattern
|
||||
const: const
|
||||
expression: SetOrMapLiteral
|
||||
leftBracket: {
|
||||
elements
|
||||
SetOrMapLiteral
|
||||
key: SimpleIdentifier
|
||||
token: a
|
||||
staticElement: a@20
|
||||
staticType: int
|
||||
separator: :
|
||||
value: IntegerLiteral
|
||||
literal: 1
|
||||
staticType: int
|
||||
rightBracket: }
|
||||
isMap: true
|
||||
staticType: Map<int, int>
|
||||
''');
|
||||
}
|
||||
|
||||
test_mapLiteral_entries_key_localVariable_notConst() async {
|
||||
await assertErrorsInCode(r'''
|
||||
void f(x) {
|
||||
final a = 0;
|
||||
if (x case const {a: 1}) {}
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION,
|
||||
47, 1),
|
||||
error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 47, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_mapLiteral_entries_value_localVariable_const() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(x) {
|
||||
const a = 0;
|
||||
if (x case const {0: a}) {}
|
||||
}
|
||||
''');
|
||||
|
||||
var node = findNode.singleGuardedPattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
GuardedPattern
|
||||
pattern: ConstantPattern
|
||||
const: const
|
||||
expression: SetOrMapLiteral
|
||||
leftBracket: {
|
||||
elements
|
||||
SetOrMapLiteral
|
||||
key: IntegerLiteral
|
||||
literal: 0
|
||||
staticType: int
|
||||
separator: :
|
||||
value: SimpleIdentifier
|
||||
token: a
|
||||
staticElement: a@20
|
||||
staticType: int
|
||||
rightBracket: }
|
||||
isMap: true
|
||||
staticType: Map<int, int>
|
||||
''');
|
||||
}
|
||||
|
||||
test_mapLiteral_entries_value_localVariable_notConst() async {
|
||||
await assertErrorsInCode(r'''
|
||||
void f(x) {
|
||||
final a = 0;
|
||||
if (x case const {0: a}) {}
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION,
|
||||
50, 1),
|
||||
error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 50, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_setLiteral_element_intLiteral() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(x) {
|
||||
if (x case const {0}) {}
|
||||
}
|
||||
''');
|
||||
|
||||
var node = findNode.singleGuardedPattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
GuardedPattern
|
||||
pattern: ConstantPattern
|
||||
const: const
|
||||
expression: SetOrMapLiteral
|
||||
leftBracket: {
|
||||
elements
|
||||
IntegerLiteral
|
||||
literal: 0
|
||||
staticType: int
|
||||
rightBracket: }
|
||||
isMap: false
|
||||
staticType: Set<int>
|
||||
''');
|
||||
}
|
||||
|
||||
test_setLiteral_element_localVariable_const() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void f(x) {
|
||||
const a = 0;
|
||||
if (x case const {a}) {}
|
||||
}
|
||||
''');
|
||||
|
||||
var node = findNode.singleGuardedPattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
GuardedPattern
|
||||
pattern: ConstantPattern
|
||||
const: const
|
||||
expression: SetOrMapLiteral
|
||||
leftBracket: {
|
||||
elements
|
||||
SimpleIdentifier
|
||||
token: a
|
||||
staticElement: a@20
|
||||
staticType: int
|
||||
rightBracket: }
|
||||
isMap: false
|
||||
staticType: Set<int>
|
||||
''');
|
||||
}
|
||||
|
||||
test_topLevelVariable_const() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
const a = 0;
|
||||
|
||||
void f(x) {
|
||||
if (x case a) {}
|
||||
}
|
||||
''');
|
||||
|
||||
var node = findNode.singleGuardedPattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
GuardedPattern
|
||||
pattern: ConstantPattern
|
||||
expression: SimpleIdentifier
|
||||
token: a
|
||||
staticElement: self::@getter::a
|
||||
staticType: int
|
||||
''');
|
||||
}
|
||||
|
||||
test_topLevelVariable_notConst() async {
|
||||
await assertErrorsInCode(r'''
|
||||
final a = 0;
|
||||
|
||||
void f(x) {
|
||||
if (x case a) {}
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION,
|
||||
39, 1),
|
||||
]);
|
||||
|
||||
var node = findNode.singleGuardedPattern;
|
||||
assertResolvedNodeText(node, r'''
|
||||
GuardedPattern
|
||||
pattern: ConstantPattern
|
||||
expression: SimpleIdentifier
|
||||
token: a
|
||||
staticElement: self::@getter::a
|
||||
staticType: int
|
||||
''');
|
||||
}
|
||||
}
|
|
@ -126,6 +126,8 @@ import 'const_with_non_type_test.dart' as const_with_non_type;
|
|||
import 'const_with_type_parameters_test.dart' as const_with_type_parameters;
|
||||
import 'const_with_undefined_constructor_test.dart'
|
||||
as const_with_undefined_constructor;
|
||||
import 'constant_pattern_with_non_constant_expression_test.dart'
|
||||
as constant_pattern_with_non_constant_expression;
|
||||
import 'could_not_infer_test.dart' as could_not_infer;
|
||||
import 'creation_of_struct_or_union_test.dart' as creation_of_struct_or_union;
|
||||
import 'dead_code_test.dart' as dead_code;
|
||||
|
@ -901,6 +903,7 @@ main() {
|
|||
const_with_non_type.main();
|
||||
const_with_type_parameters.main();
|
||||
const_with_undefined_constructor.main();
|
||||
constant_pattern_with_non_constant_expression.main();
|
||||
could_not_infer.main();
|
||||
creation_of_struct_or_union.main();
|
||||
dead_code.main();
|
||||
|
|
Loading…
Reference in a new issue