blob: 624bc2ea2815630e099216e9d6191a94b44f9de2 [file] [log] [blame] [edit]
// Copyright (c) 2020, 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.
/// @docImport 'simple_parser_test.dart';
library;
import 'package:analyzer/src/diagnostic/diagnostic.dart' as diag;
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../src/diagnostics/parser_diagnostics.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(ComplexParserTest);
});
}
/// The class `ComplexParserTest` defines parser tests that test the parsing of
/// more complex code fragments or the interactions between multiple parsing
/// methods. For example, tests to ensure that the precedence of operations is
/// being handled correctly should be defined in this class.
///
/// Simpler tests should be defined in the class [SimpleParserTest].
@reflectiveTest
class ComplexParserTest extends ParserDiagnosticsTest {
void test_additiveExpression_normal() {
var parseResult = parseStringWithErrors(r'''
void f() {
x + y - z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: +
rightOperand: SimpleIdentifier
token: y
operator: -
rightOperand: SimpleIdentifier
token: z
''');
}
void test_additiveExpression_noSpaces() {
var parseResult = parseStringWithErrors(r'''
void f() {
i+1;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: SimpleIdentifier
token: i
operator: +
rightOperand: IntegerLiteral
literal: 1
''');
}
void test_additiveExpression_precedence_multiplicative_left() {
var parseResult = parseStringWithErrors(r'''
void f() {
x * y + z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: *
rightOperand: SimpleIdentifier
token: y
operator: +
rightOperand: SimpleIdentifier
token: z
''');
}
void test_additiveExpression_precedence_multiplicative_left_withSuper() {
var parseResult = parseStringWithErrors(r'''
class A {
void f() {
super * y - z;
}
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: BinaryExpression
leftOperand: SuperExpression
superKeyword: super
operator: *
rightOperand: SimpleIdentifier
token: y
operator: -
rightOperand: SimpleIdentifier
token: z
''');
}
void test_additiveExpression_precedence_multiplicative_right() {
var parseResult = parseStringWithErrors(r'''
void f() {
x + y * z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: +
rightOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: y
operator: *
rightOperand: SimpleIdentifier
token: z
''');
}
void test_additiveExpression_super() {
var parseResult = parseStringWithErrors(r'''
class A {
void f() {
super + y - z;
}
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: BinaryExpression
leftOperand: SuperExpression
superKeyword: super
operator: +
rightOperand: SimpleIdentifier
token: y
operator: -
rightOperand: SimpleIdentifier
token: z
''');
}
void test_assignableExpression_arguments_normal_chain() {
var parseResult = parseStringWithErrors(r'''
void f() {
a(b)(c).d(e).f;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
PropertyAccess
target: MethodInvocation
target: FunctionExpressionInvocation
function: MethodInvocation
methodName: SimpleIdentifier
token: a
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: b
rightParenthesis: )
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: c
rightParenthesis: )
operator: .
methodName: SimpleIdentifier
token: d
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: e
rightParenthesis: )
operator: .
propertyName: SimpleIdentifier
token: f
''');
}
void test_assignableExpression_arguments_normal_chain_typeArguments() {
var parseResult = parseStringWithErrors(r'''
void f() {
a<E>(b)<F>(c).d<G>(e).f;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
PropertyAccess
target: MethodInvocation
target: FunctionExpressionInvocation
function: MethodInvocation
methodName: SimpleIdentifier
token: a
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: E
rightBracket: >
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: b
rightParenthesis: )
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: F
rightBracket: >
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: c
rightParenthesis: )
operator: .
methodName: SimpleIdentifier
token: d
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: G
rightBracket: >
argumentList: ArgumentList
leftParenthesis: (
arguments
SimpleIdentifier
token: e
rightParenthesis: )
operator: .
propertyName: SimpleIdentifier
token: f
''');
}
void test_assignmentExpression_compound() {
var parseResult = parseStringWithErrors(r'''
void f() {
x = y = 0;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
AssignmentExpression
leftHandSide: SimpleIdentifier
token: x
operator: =
rightHandSide: AssignmentExpression
leftHandSide: SimpleIdentifier
token: y
operator: =
rightHandSide: IntegerLiteral
literal: 0
''');
}
void test_assignmentExpression_indexExpression() {
var parseResult = parseStringWithErrors(r'''
void f() {
x[1] = 0;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
AssignmentExpression
leftHandSide: IndexExpression
target: SimpleIdentifier
token: x
leftBracket: [
index: IntegerLiteral
literal: 1
rightBracket: ]
operator: =
rightHandSide: IntegerLiteral
literal: 0
''');
}
void test_assignmentExpression_prefixedIdentifier() {
var parseResult = parseStringWithErrors(r'''
void f() {
x.y = 0;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
AssignmentExpression
leftHandSide: PrefixedIdentifier
prefix: SimpleIdentifier
token: x
period: .
identifier: SimpleIdentifier
token: y
operator: =
rightHandSide: IntegerLiteral
literal: 0
''');
}
void test_assignmentExpression_propertyAccess() {
var parseResult = parseStringWithErrors(r'''
class A {
void f() {
super.y = 0;
}
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
AssignmentExpression
leftHandSide: PropertyAccess
target: SuperExpression
superKeyword: super
operator: .
propertyName: SimpleIdentifier
token: y
operator: =
rightHandSide: IntegerLiteral
literal: 0
''');
}
void test_binary_operator_written_out_expression() {
var parseResult = parseStringWithErrors(r'''
void f() {
x xor y;
}
''');
parseResult.assertErrors([error(diag.expectedToken, 15, 3)]);
var node = parseResult.findNode.singleBlock;
assertParsedNodeText(node, r'''
Block
leftBracket: {
statements
VariableDeclarationStatement
variables: VariableDeclarationList
type: NamedType
name: x
variables
VariableDeclaration
name: xor
semicolon: ; <synthetic>
ExpressionStatement
expression: SimpleIdentifier
token: y
semicolon: ;
rightBracket: }
''');
}
void test_binary_operator_written_out_expression_logical() {
// Report `and` and recover with a synthetic `&&` in the parsed AST.
var parseResult = parseStringWithErrors(r'''
void f() {
x > 0 and y > 1;
}
''');
parseResult.assertErrors([error(diag.binaryOperatorWrittenOut, 19, 3)]);
var node = parseResult.findNode.singleBlock;
assertParsedNodeText(node, r'''
Block
leftBracket: {
statements
ExpressionStatement
expression: BinaryExpression
leftOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: >
rightOperand: IntegerLiteral
literal: 0
operator: && <synthetic>
rightOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: y
operator: >
rightOperand: IntegerLiteral
literal: 1
semicolon: ;
rightBracket: }
''');
}
void test_bitwiseAndExpression_normal() {
var parseResult = parseStringWithErrors(r'''
void f() {
x & y & z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: &
rightOperand: SimpleIdentifier
token: y
operator: &
rightOperand: SimpleIdentifier
token: z
''');
}
void test_bitwiseAndExpression_precedence_equality_left() {
var parseResult = parseStringWithErrors(r'''
void f() {
x == y && z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: ==
rightOperand: SimpleIdentifier
token: y
operator: &&
rightOperand: SimpleIdentifier
token: z
''');
}
void test_bitwiseAndExpression_precedence_equality_right() {
var parseResult = parseStringWithErrors(r'''
void f() {
x && y == z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: &&
rightOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: y
operator: ==
rightOperand: SimpleIdentifier
token: z
''');
}
void test_bitwiseAndExpression_super() {
var parseResult = parseStringWithErrors(r'''
class A {
void f() {
super & y & z;
}
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: BinaryExpression
leftOperand: SuperExpression
superKeyword: super
operator: &
rightOperand: SimpleIdentifier
token: y
operator: &
rightOperand: SimpleIdentifier
token: z
''');
}
void test_bitwiseOrExpression_normal() {
var parseResult = parseStringWithErrors(r'''
void f() {
x | y | z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: |
rightOperand: SimpleIdentifier
token: y
operator: |
rightOperand: SimpleIdentifier
token: z
''');
}
void test_bitwiseOrExpression_precedence_xor_left() {
var parseResult = parseStringWithErrors(r'''
void f() {
x ^ y | z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: ^
rightOperand: SimpleIdentifier
token: y
operator: |
rightOperand: SimpleIdentifier
token: z
''');
}
void test_bitwiseOrExpression_precedence_xor_right() {
var parseResult = parseStringWithErrors(r'''
void f() {
x | y ^ z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: |
rightOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: y
operator: ^
rightOperand: SimpleIdentifier
token: z
''');
}
void test_bitwiseOrExpression_super() {
var parseResult = parseStringWithErrors(r'''
class A {
void f() {
super | y | z;
}
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: BinaryExpression
leftOperand: SuperExpression
superKeyword: super
operator: |
rightOperand: SimpleIdentifier
token: y
operator: |
rightOperand: SimpleIdentifier
token: z
''');
}
void test_bitwiseXorExpression_normal() {
var parseResult = parseStringWithErrors(r'''
void f() {
x ^ y ^ z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: ^
rightOperand: SimpleIdentifier
token: y
operator: ^
rightOperand: SimpleIdentifier
token: z
''');
}
void test_bitwiseXorExpression_precedence_and_left() {
var parseResult = parseStringWithErrors(r'''
void f() {
x & y ^ z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: &
rightOperand: SimpleIdentifier
token: y
operator: ^
rightOperand: SimpleIdentifier
token: z
''');
}
void test_bitwiseXorExpression_precedence_and_right() {
var parseResult = parseStringWithErrors(r'''
void f() {
x ^ y & z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: ^
rightOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: y
operator: &
rightOperand: SimpleIdentifier
token: z
''');
}
void test_bitwiseXorExpression_super() {
var parseResult = parseStringWithErrors(r'''
class A {
void f() {
super ^ y ^ z;
}
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: BinaryExpression
leftOperand: SuperExpression
superKeyword: super
operator: ^
rightOperand: SimpleIdentifier
token: y
operator: ^
rightOperand: SimpleIdentifier
token: z
''');
}
void test_cascade_withAssignment() {
var parseResult = parseStringWithErrors(r'''
void f() {
new Map()..[3] = 4 ..[0] = 11;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
CascadeExpression
target: InstanceCreationExpression
keyword: new
constructorName: ConstructorName
type: NamedType
name: Map
argumentList: ArgumentList
leftParenthesis: (
rightParenthesis: )
cascadeSections
AssignmentExpression
leftHandSide: IndexExpression
period: ..
leftBracket: [
index: IntegerLiteral
literal: 3
rightBracket: ]
operator: =
rightHandSide: IntegerLiteral
literal: 4
AssignmentExpression
leftHandSide: IndexExpression
period: ..
leftBracket: [
index: IntegerLiteral
literal: 0
rightBracket: ]
operator: =
rightHandSide: IntegerLiteral
literal: 11
''');
}
void test_conditionalExpression_precedence_ifNullExpression() {
var parseResult = parseStringWithErrors(r'''
void f() {
a ?? b ? y : z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
ConditionalExpression
condition: BinaryExpression
leftOperand: SimpleIdentifier
token: a
operator: ??
rightOperand: SimpleIdentifier
token: b
question: ?
thenExpression: SimpleIdentifier
token: y
colon: :
elseExpression: SimpleIdentifier
token: z
''');
}
void test_conditionalExpression_precedence_logicalOrExpression() {
var parseResult = parseStringWithErrors(r'''
void f() {
a | b ? y : z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
ConditionalExpression
condition: BinaryExpression
leftOperand: SimpleIdentifier
token: a
operator: |
rightOperand: SimpleIdentifier
token: b
question: ?
thenExpression: SimpleIdentifier
token: y
colon: :
elseExpression: SimpleIdentifier
token: z
''');
}
void test_conditionalExpression_precedence_nullableType_as() {
var parseResult = parseStringWithErrors(r'''
void f() {
x as bool ? (x + y) : z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
ConditionalExpression
condition: AsExpression
expression: SimpleIdentifier
token: x
asOperator: as
type: NamedType
name: bool
question: ?
thenExpression: ParenthesizedExpression
leftParenthesis: (
expression: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: +
rightOperand: SimpleIdentifier
token: y
rightParenthesis: )
colon: :
elseExpression: SimpleIdentifier
token: z
''');
}
void test_conditionalExpression_precedence_nullableType_as2() {
var parseResult = parseStringWithErrors(r'''
void f() {
x as bool? ? (x + y) : z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
ConditionalExpression
condition: AsExpression
expression: SimpleIdentifier
token: x
asOperator: as
type: NamedType
name: bool
question: ?
question: ?
thenExpression: ParenthesizedExpression
leftParenthesis: (
expression: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: +
rightOperand: SimpleIdentifier
token: y
rightParenthesis: )
colon: :
elseExpression: SimpleIdentifier
token: z
''');
}
void test_conditionalExpression_precedence_nullableType_as3() {
var parseResult = parseStringWithErrors(r'''
void f() {
(x as bool?) ? (x + y) : z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
ConditionalExpression
condition: ParenthesizedExpression
leftParenthesis: (
expression: AsExpression
expression: SimpleIdentifier
token: x
asOperator: as
type: NamedType
name: bool
question: ?
rightParenthesis: )
question: ?
thenExpression: ParenthesizedExpression
leftParenthesis: (
expression: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: +
rightOperand: SimpleIdentifier
token: y
rightParenthesis: )
colon: :
elseExpression: SimpleIdentifier
token: z
''');
}
void test_conditionalExpression_precedence_nullableType_is() {
var parseResult = parseStringWithErrors(r'''
void f() {
x is String ? (x + y) : z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
ConditionalExpression
condition: IsExpression
expression: SimpleIdentifier
token: x
isOperator: is
type: NamedType
name: String
question: ?
thenExpression: ParenthesizedExpression
leftParenthesis: (
expression: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: +
rightOperand: SimpleIdentifier
token: y
rightParenthesis: )
colon: :
elseExpression: SimpleIdentifier
token: z
''');
}
void test_conditionalExpression_precedence_nullableType_is2() {
var parseResult = parseStringWithErrors(r'''
void f() {
x is String? ? (x + y) : z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
ConditionalExpression
condition: IsExpression
expression: SimpleIdentifier
token: x
isOperator: is
type: NamedType
name: String
question: ?
question: ?
thenExpression: ParenthesizedExpression
leftParenthesis: (
expression: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: +
rightOperand: SimpleIdentifier
token: y
rightParenthesis: )
colon: :
elseExpression: SimpleIdentifier
token: z
''');
}
void test_conditionalExpression_precedence_nullableType_is3() {
var parseResult = parseStringWithErrors(r'''
void f() {
(x is String?) ? (x + y) : z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
ConditionalExpression
condition: ParenthesizedExpression
leftParenthesis: (
expression: IsExpression
expression: SimpleIdentifier
token: x
isOperator: is
type: NamedType
name: String
question: ?
rightParenthesis: )
question: ?
thenExpression: ParenthesizedExpression
leftParenthesis: (
expression: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: +
rightOperand: SimpleIdentifier
token: y
rightParenthesis: )
colon: :
elseExpression: SimpleIdentifier
token: z
''');
}
void test_conditionalExpression_precedence_nullableTypeWithTypeArg1_is() {
var parseResult = parseStringWithErrors(r'''
void f() {
x is String<S> ? (x + y) : z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
ConditionalExpression
condition: IsExpression
expression: SimpleIdentifier
token: x
isOperator: is
type: NamedType
name: String
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: S
rightBracket: >
question: ?
thenExpression: ParenthesizedExpression
leftParenthesis: (
expression: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: +
rightOperand: SimpleIdentifier
token: y
rightParenthesis: )
colon: :
elseExpression: SimpleIdentifier
token: z
''');
}
void test_conditionalExpression_precedence_nullableTypeWithTypeArg1GFT_is() {
var parseResult = parseStringWithErrors(r'''
void f() {
x is String<S> Function() ? (x + y) : z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
ConditionalExpression
condition: IsExpression
expression: SimpleIdentifier
token: x
isOperator: is
type: GenericFunctionType
returnType: NamedType
name: String
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: S
rightBracket: >
functionKeyword: Function
parameters: FormalParameterList
leftParenthesis: (
rightParenthesis: )
question: ?
thenExpression: ParenthesizedExpression
leftParenthesis: (
expression: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: +
rightOperand: SimpleIdentifier
token: y
rightParenthesis: )
colon: :
elseExpression: SimpleIdentifier
token: z
''');
}
void test_conditionalExpression_precedence_nullableTypeWithTypeArg2_is() {
var parseResult = parseStringWithErrors(r'''
void f() {
x is String<S,T> ? (x + y) : z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
ConditionalExpression
condition: IsExpression
expression: SimpleIdentifier
token: x
isOperator: is
type: NamedType
name: String
typeArguments: TypeArgumentList
leftBracket: <
arguments
NamedType
name: S
NamedType
name: T
rightBracket: >
question: ?
thenExpression: ParenthesizedExpression
leftParenthesis: (
expression: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: +
rightOperand: SimpleIdentifier
token: y
rightParenthesis: )
colon: :
elseExpression: SimpleIdentifier
token: z
''');
}
void test_conditionalExpression_precedence_prefixedNullableType_is() {
var parseResult = parseStringWithErrors(r'''
void f() {
x is p.A ? (x + y) : z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
ConditionalExpression
condition: IsExpression
expression: SimpleIdentifier
token: x
isOperator: is
type: NamedType
importPrefix: ImportPrefixReference
name: p
period: .
name: A
question: ?
thenExpression: ParenthesizedExpression
leftParenthesis: (
expression: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: +
rightOperand: SimpleIdentifier
token: y
rightParenthesis: )
colon: :
elseExpression: SimpleIdentifier
token: z
''');
}
void test_conditionalExpression_precedence_withAssignment() {
var parseResult = parseStringWithErrors(r'''
void f() {
b ? c = true : g();
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
ConditionalExpression
condition: SimpleIdentifier
token: b
question: ?
thenExpression: AssignmentExpression
leftHandSide: SimpleIdentifier
token: c
operator: =
rightHandSide: BooleanLiteral
literal: true
colon: :
elseExpression: MethodInvocation
methodName: SimpleIdentifier
token: g
argumentList: ArgumentList
leftParenthesis: (
rightParenthesis: )
''');
}
void test_conditionalExpression_precedence_withAssignment2() {
var parseResult = parseStringWithErrors(r'''
void f() {
b.x ? c = true : g();
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
ConditionalExpression
condition: PrefixedIdentifier
prefix: SimpleIdentifier
token: b
period: .
identifier: SimpleIdentifier
token: x
question: ?
thenExpression: AssignmentExpression
leftHandSide: SimpleIdentifier
token: c
operator: =
rightHandSide: BooleanLiteral
literal: true
colon: :
elseExpression: MethodInvocation
methodName: SimpleIdentifier
token: g
argumentList: ArgumentList
leftParenthesis: (
rightParenthesis: )
''');
}
void test_conditionalExpression_prefixedValue() {
var parseResult = parseStringWithErrors(r'''
void f() {
a.b ? y : z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
ConditionalExpression
condition: PrefixedIdentifier
prefix: SimpleIdentifier
token: a
period: .
identifier: SimpleIdentifier
token: b
question: ?
thenExpression: SimpleIdentifier
token: y
colon: :
elseExpression: SimpleIdentifier
token: z
''');
}
void test_conditionalExpression_prefixedValue2() {
var parseResult = parseStringWithErrors(r'''
void f() {
a.b ? x.y : z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
ConditionalExpression
condition: PrefixedIdentifier
prefix: SimpleIdentifier
token: a
period: .
identifier: SimpleIdentifier
token: b
question: ?
thenExpression: PrefixedIdentifier
prefix: SimpleIdentifier
token: x
period: .
identifier: SimpleIdentifier
token: y
colon: :
elseExpression: SimpleIdentifier
token: z
''');
}
void test_constructor_initializer_withParenthesizedExpression() {
var parseResult = parseStringWithErrors(r'''
class C {
C() : this.a = (b == null ? c : d);
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleConstructorFieldInitializer;
assertParsedNodeText(node, r'''
ConstructorFieldInitializer
thisKeyword: this
period: .
fieldName: SimpleIdentifier
token: a
equals: =
expression: ParenthesizedExpression
leftParenthesis: (
expression: ConditionalExpression
condition: BinaryExpression
leftOperand: SimpleIdentifier
token: b
operator: ==
rightOperand: NullLiteral
literal: null
question: ?
thenExpression: SimpleIdentifier
token: c
colon: :
elseExpression: SimpleIdentifier
token: d
rightParenthesis: )
''');
}
void test_equalityExpression_normal() {
var parseResult = parseStringWithErrors(r'''
void f() {
x == y != z;
}
''');
parseResult.assertErrors([
error(diag.equalityCannotBeEqualityOperand, 20, 2),
]);
var node = parseResult.findNode.singleBlock;
assertParsedNodeText(node, r'''
Block
leftBracket: {
statements
ExpressionStatement
expression: BinaryExpression
leftOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: ==
rightOperand: SimpleIdentifier
token: y
operator: !=
rightOperand: SimpleIdentifier
token: z
semicolon: ;
rightBracket: }
''');
}
void test_equalityExpression_precedence_relational_left() {
var parseResult = parseStringWithErrors(r'''
void f() {
x is y == z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: IsExpression
expression: SimpleIdentifier
token: x
isOperator: is
type: NamedType
name: y
operator: ==
rightOperand: SimpleIdentifier
token: z
''');
}
void test_equalityExpression_precedence_relational_right() {
var parseResult = parseStringWithErrors(r'''
void f() {
x == y is z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: ==
rightOperand: IsExpression
expression: SimpleIdentifier
token: y
isOperator: is
type: NamedType
name: z
''');
}
void test_equalityExpression_super() {
var parseResult = parseStringWithErrors(r'''
class A {
void f() {
super == y != z;
}
}
''');
parseResult.assertErrors([
error(diag.equalityCannotBeEqualityOperand, 38, 2),
]);
var node = parseResult.findNode.singleBlock;
assertParsedNodeText(node, r'''
Block
leftBracket: {
statements
ExpressionStatement
expression: BinaryExpression
leftOperand: BinaryExpression
leftOperand: SuperExpression
superKeyword: super
operator: ==
rightOperand: SimpleIdentifier
token: y
operator: !=
rightOperand: SimpleIdentifier
token: z
semicolon: ;
rightBracket: }
''');
}
void test_ifNullExpression() {
var parseResult = parseStringWithErrors(r'''
void f() {
x ?? y ?? z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: ??
rightOperand: SimpleIdentifier
token: y
operator: ??
rightOperand: SimpleIdentifier
token: z
''');
}
void test_ifNullExpression_precedence_logicalOr_left() {
var parseResult = parseStringWithErrors(r'''
void f() {
x || y ?? z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: ||
rightOperand: SimpleIdentifier
token: y
operator: ??
rightOperand: SimpleIdentifier
token: z
''');
}
void test_ifNullExpression_precedence_logicalOr_right() {
var parseResult = parseStringWithErrors(r'''
void f() {
x ?? y || z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: ??
rightOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: y
operator: ||
rightOperand: SimpleIdentifier
token: z
''');
}
void test_logicalAndExpression() {
var parseResult = parseStringWithErrors(r'''
void f() {
x && y && z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: &&
rightOperand: SimpleIdentifier
token: y
operator: &&
rightOperand: SimpleIdentifier
token: z
''');
}
void test_logicalAndExpression_precedence_bitwiseOr_left() {
var parseResult = parseStringWithErrors(r'''
void f() {
x | y < z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: |
rightOperand: SimpleIdentifier
token: y
operator: <
rightOperand: SimpleIdentifier
token: z
''');
}
void test_logicalAndExpression_precedence_bitwiseOr_right() {
var parseResult = parseStringWithErrors(r'''
void f() {
x < y | z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: <
rightOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: y
operator: |
rightOperand: SimpleIdentifier
token: z
''');
}
void test_logicalAndExpressionStatement() {
// Ensure `<` and `>` are parsed as operators, not type arguments.
var parseResult = parseStringWithErrors(r'''
void f() {
C<T && T>U;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: C
operator: <
rightOperand: SimpleIdentifier
token: T
operator: &&
rightOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: T
operator: >
rightOperand: SimpleIdentifier
token: U
''');
}
void test_logicalOrExpression() {
var parseResult = parseStringWithErrors(r'''
void f() {
x || y || z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: ||
rightOperand: SimpleIdentifier
token: y
operator: ||
rightOperand: SimpleIdentifier
token: z
''');
}
void test_logicalOrExpression_precedence_logicalAnd_left() {
var parseResult = parseStringWithErrors(r'''
void f() {
x && y || z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: &&
rightOperand: SimpleIdentifier
token: y
operator: ||
rightOperand: SimpleIdentifier
token: z
''');
}
void test_logicalOrExpression_precedence_logicalAnd_right() {
var parseResult = parseStringWithErrors(r'''
void f() {
x || y && z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: ||
rightOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: y
operator: &&
rightOperand: SimpleIdentifier
token: z
''');
}
void test_methodInvocation1() {
// Ensure `<` and `>` in arguments are parsed as operators, not type args.
var parseResult = parseStringWithErrors(r'''
void f() {
f(a < b, c > 3);
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
MethodInvocation
methodName: SimpleIdentifier
token: f
argumentList: ArgumentList
leftParenthesis: (
arguments
BinaryExpression
leftOperand: SimpleIdentifier
token: a
operator: <
rightOperand: SimpleIdentifier
token: b
BinaryExpression
leftOperand: SimpleIdentifier
token: c
operator: >
rightOperand: IntegerLiteral
literal: 3
rightParenthesis: )
''');
}
void test_methodInvocation2() {
// Ensure `<` and `>` in arguments are parsed as operators, not type args.
var parseResult = parseStringWithErrors(r'''
void f() {
f(a < b, c >> 3);
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
MethodInvocation
methodName: SimpleIdentifier
token: f
argumentList: ArgumentList
leftParenthesis: (
arguments
BinaryExpression
leftOperand: SimpleIdentifier
token: a
operator: <
rightOperand: SimpleIdentifier
token: b
BinaryExpression
leftOperand: SimpleIdentifier
token: c
operator: >>
rightOperand: IntegerLiteral
literal: 3
rightParenthesis: )
''');
}
void test_methodInvocation3() {
// Ensure `<` and `>` in arguments are parsed as operators, not type args.
var parseResult = parseStringWithErrors(r'''
void f() {
f(a < b, c < d >> 3);
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
MethodInvocation
methodName: SimpleIdentifier
token: f
argumentList: ArgumentList
leftParenthesis: (
arguments
BinaryExpression
leftOperand: SimpleIdentifier
token: a
operator: <
rightOperand: SimpleIdentifier
token: b
BinaryExpression
leftOperand: SimpleIdentifier
token: c
operator: <
rightOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: d
operator: >>
rightOperand: IntegerLiteral
literal: 3
rightParenthesis: )
''');
}
void test_multipleLabels_statement() {
var parseResult = parseStringWithErrors(r'''
void f() {
a: b: c: return x;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleLabeledStatement;
assertParsedNodeText(node, r'''
LabeledStatement
labels
Label
label: SimpleIdentifier
token: a
colon: :
Label
label: SimpleIdentifier
token: b
colon: :
Label
label: SimpleIdentifier
token: c
colon: :
statement: ReturnStatement
returnKeyword: return
expression: SimpleIdentifier
token: x
semicolon: ;
''');
}
void test_multiplicativeExpression_normal() {
var parseResult = parseStringWithErrors(r'''
void f() {
x * y / z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: *
rightOperand: SimpleIdentifier
token: y
operator: /
rightOperand: SimpleIdentifier
token: z
''');
}
void test_multiplicativeExpression_precedence_unary_left() {
var parseResult = parseStringWithErrors(r'''
void f() {
-x * y;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: PrefixExpression
operator: -
operand: SimpleIdentifier
token: x
operator: *
rightOperand: SimpleIdentifier
token: y
''');
}
void test_multiplicativeExpression_precedence_unary_right() {
var parseResult = parseStringWithErrors(r'''
void f() {
x * -y;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: *
rightOperand: PrefixExpression
operator: -
operand: SimpleIdentifier
token: y
''');
}
void test_multiplicativeExpression_super() {
var parseResult = parseStringWithErrors(r'''
class A {
void f() {
super * y / z;
}
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: BinaryExpression
leftOperand: SuperExpression
superKeyword: super
operator: *
rightOperand: SimpleIdentifier
token: y
operator: /
rightOperand: SimpleIdentifier
token: z
''');
}
void test_relationalExpression_precedence_shift_right() {
var parseResult = parseStringWithErrors(r'''
void f() {
x << y is z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
IsExpression
expression: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: <<
rightOperand: SimpleIdentifier
token: y
isOperator: is
type: NamedType
name: z
''');
}
void test_shiftExpression_normal() {
var parseResult = parseStringWithErrors(r'''
void f() {
x >> 4 << 3;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: >>
rightOperand: IntegerLiteral
literal: 4
operator: <<
rightOperand: IntegerLiteral
literal: 3
''');
}
void test_shiftExpression_precedence_additive_left() {
var parseResult = parseStringWithErrors(r'''
void f() {
x + y << z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: +
rightOperand: SimpleIdentifier
token: y
operator: <<
rightOperand: SimpleIdentifier
token: z
''');
}
void test_shiftExpression_precedence_additive_right() {
var parseResult = parseStringWithErrors(r'''
void f() {
x << y + z;
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: SimpleIdentifier
token: x
operator: <<
rightOperand: BinaryExpression
leftOperand: SimpleIdentifier
token: y
operator: +
rightOperand: SimpleIdentifier
token: z
''');
}
void test_shiftExpression_super() {
var parseResult = parseStringWithErrors(r'''
class A {
void f() {
super >> 4 << 3;
}
}
''');
parseResult.assertNoErrors();
var node = parseResult.findNode.singleExpressionStatement.expression;
assertParsedNodeText(node, r'''
BinaryExpression
leftOperand: BinaryExpression
leftOperand: SuperExpression
superKeyword: super
operator: >>
rightOperand: IntegerLiteral
literal: 4
operator: <<
rightOperand: IntegerLiteral
literal: 3
''');
}
void test_topLevelFunction_nestedGenericFunction() {
var parseResult = parseStringWithErrors(r'''
void f() {
void g<T>() {
}
}
''');
parseResult.assertNoErrors();
var node = parseResult
.findNode
.singleFunctionDeclarationStatement
.functionDeclaration;
assertParsedNodeText(node, r'''
FunctionDeclaration
returnType: NamedType
name: void
name: g
functionExpression: FunctionExpression
typeParameters: TypeParameterList
leftBracket: <
typeParameters
TypeParameter
name: T
rightBracket: >
parameters: FormalParameterList
leftParenthesis: (
rightParenthesis: )
body: BlockFunctionBody
block: Block
leftBracket: {
rightBracket: }
''');
}
}