50bee6831f
Change-Id: I436d320b98751c7263cb08ce500e6aa5da1bfcd1 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/486440 Reviewed-by: Johnni Winther <johnniwinther@google.com>
1350 lines
34 KiB
Dart
1350 lines
34 KiB
Dart
// Copyright (c) 2021, 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/dart/analysis/features.dart';
|
|
import 'package:analyzer/src/diagnostic/diagnostic.dart' as diag;
|
|
import 'package:pub_semver/pub_semver.dart';
|
|
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
|
|
|
import '../src/dart/resolution/node_text_expectations.dart';
|
|
import '../src/diagnostics/parser_diagnostics.dart';
|
|
|
|
main() {
|
|
defineReflectiveSuite(() {
|
|
defineReflectiveTests(FunctionReferenceParserTest);
|
|
defineReflectiveTests(UpdateNodeTextExpectations);
|
|
});
|
|
}
|
|
|
|
/// Tests exercising the fasta parser's handling of generic instantiations.
|
|
@reflectiveTest
|
|
class FunctionReferenceParserTest extends ParserDiagnosticsTest {
|
|
void test_feature_disabled() {
|
|
var parseResult = parseStringWithErrors(
|
|
'void f() { f<a, b>; }',
|
|
featureSet: FeatureSet.fromEnableFlags2(
|
|
sdkLanguageVersion: Version.parse('2.13.0'),
|
|
flags: [],
|
|
),
|
|
);
|
|
parseResult.assertErrors([error(diag.experimentNotEnabled, 12, 6)]);
|
|
|
|
var node = parseResult.findNode.singleExpressionStatement.expression;
|
|
assertParsedNodeText(node, r'''
|
|
FunctionReference
|
|
function: SimpleIdentifier
|
|
token: f
|
|
typeArguments: TypeArgumentList
|
|
leftBracket: <
|
|
arguments
|
|
NamedType
|
|
name: a
|
|
NamedType
|
|
name: b
|
|
rightBracket: >
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_accepted_closeBrace() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = {f<a, b>};
|
|
''');
|
|
parseResult.assertNoErrors();
|
|
var node = parseResult.findNode.singleSetOrMapLiteral.elements[0];
|
|
assertParsedNodeText(node, r'''
|
|
FunctionReference
|
|
function: SimpleIdentifier
|
|
token: f
|
|
typeArguments: TypeArgumentList
|
|
leftBracket: <
|
|
arguments
|
|
NamedType
|
|
name: a
|
|
NamedType
|
|
name: b
|
|
rightBracket: >
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_accepted_closeBracket() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = [f<a, b>];
|
|
''');
|
|
parseResult.assertNoErrors();
|
|
var node = parseResult.findNode.singleListLiteral.elements[0];
|
|
assertParsedNodeText(node, r'''
|
|
FunctionReference
|
|
function: SimpleIdentifier
|
|
token: f
|
|
typeArguments: TypeArgumentList
|
|
leftBracket: <
|
|
arguments
|
|
NamedType
|
|
name: a
|
|
NamedType
|
|
name: b
|
|
rightBracket: >
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_accepted_closeParen() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = g(f<a, b>);
|
|
''');
|
|
parseResult.assertNoErrors();
|
|
var node =
|
|
parseResult.findNode.singleMethodInvocation.argumentList.arguments[0];
|
|
assertParsedNodeText(node, r'''
|
|
FunctionReference
|
|
function: SimpleIdentifier
|
|
token: f
|
|
typeArguments: TypeArgumentList
|
|
leftBracket: <
|
|
arguments
|
|
NamedType
|
|
name: a
|
|
NamedType
|
|
name: b
|
|
rightBracket: >
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_accepted_colon() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = {f<a, b>: null};
|
|
''');
|
|
parseResult.assertNoErrors();
|
|
var node = parseResult.findNode.mapLiteralEntry('null').key;
|
|
assertParsedNodeText(node, r'''
|
|
FunctionReference
|
|
function: SimpleIdentifier
|
|
token: f
|
|
typeArguments: TypeArgumentList
|
|
leftBracket: <
|
|
arguments
|
|
NamedType
|
|
name: a
|
|
NamedType
|
|
name: b
|
|
rightBracket: >
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_accepted_comma() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = [f<a, b>, null];
|
|
''');
|
|
parseResult.assertNoErrors();
|
|
var node = parseResult.findNode.singleListLiteral.elements[0];
|
|
assertParsedNodeText(node, r'''
|
|
FunctionReference
|
|
function: SimpleIdentifier
|
|
token: f
|
|
typeArguments: TypeArgumentList
|
|
leftBracket: <
|
|
arguments
|
|
NamedType
|
|
name: a
|
|
NamedType
|
|
name: b
|
|
rightBracket: >
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_accepted_equals() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f<a, b> == null;
|
|
''');
|
|
parseResult.assertNoErrors();
|
|
var node = parseResult.findNode.singleBinaryExpression.leftOperand;
|
|
assertParsedNodeText(node, r'''
|
|
FunctionReference
|
|
function: SimpleIdentifier
|
|
token: f
|
|
typeArguments: TypeArgumentList
|
|
leftBracket: <
|
|
arguments
|
|
NamedType
|
|
name: a
|
|
NamedType
|
|
name: b
|
|
rightBracket: >
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_accepted_not_equals() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f<a, b> != null;
|
|
''');
|
|
parseResult.assertNoErrors();
|
|
var node = parseResult.findNode.singleBinaryExpression.leftOperand;
|
|
assertParsedNodeText(node, r'''
|
|
FunctionReference
|
|
function: SimpleIdentifier
|
|
token: f
|
|
typeArguments: TypeArgumentList
|
|
leftBracket: <
|
|
arguments
|
|
NamedType
|
|
name: a
|
|
NamedType
|
|
name: b
|
|
rightBracket: >
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_accepted_openParen() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f<a, b>();
|
|
''');
|
|
parseResult.assertNoErrors();
|
|
var node = parseResult.findNode.singleMethodInvocation;
|
|
assertParsedNodeText(node, r'''
|
|
MethodInvocation
|
|
methodName: SimpleIdentifier
|
|
token: f
|
|
typeArguments: TypeArgumentList
|
|
leftBracket: <
|
|
arguments
|
|
NamedType
|
|
name: a
|
|
NamedType
|
|
name: b
|
|
rightBracket: >
|
|
argumentList: ArgumentList
|
|
leftParenthesis: (
|
|
rightParenthesis: )
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_accepted_period_methodInvocation() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f<a, b>.toString();
|
|
''');
|
|
parseResult.assertNoErrors();
|
|
var node = parseResult.findNode.singleInstanceCreationExpression;
|
|
assertParsedNodeText(node, r'''
|
|
InstanceCreationExpression
|
|
constructorName: ConstructorName
|
|
type: NamedType
|
|
name: f
|
|
typeArguments: TypeArgumentList
|
|
leftBracket: <
|
|
arguments
|
|
NamedType
|
|
name: a
|
|
NamedType
|
|
name: b
|
|
rightBracket: >
|
|
period: .
|
|
name: SimpleIdentifier
|
|
token: toString
|
|
argumentList: ArgumentList
|
|
leftParenthesis: (
|
|
rightParenthesis: )
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_accepted_period_methodInvocation_generic() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f<a, b>.foo<c>();
|
|
''');
|
|
parseResult.assertNoErrors();
|
|
var node = parseResult.findNode.singleMethodInvocation.target!;
|
|
assertParsedNodeText(node, r'''
|
|
FunctionReference
|
|
function: SimpleIdentifier
|
|
token: f
|
|
typeArguments: TypeArgumentList
|
|
leftBracket: <
|
|
arguments
|
|
NamedType
|
|
name: a
|
|
NamedType
|
|
name: b
|
|
rightBracket: >
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_accepted_period_propertyAccess() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f<a, b>.hashCode;
|
|
''');
|
|
parseResult.assertNoErrors();
|
|
var node = parseResult.findNode.singlePropertyAccess.target!;
|
|
assertParsedNodeText(node, r'''
|
|
FunctionReference
|
|
function: SimpleIdentifier
|
|
token: f
|
|
typeArguments: TypeArgumentList
|
|
leftBracket: <
|
|
arguments
|
|
NamedType
|
|
name: a
|
|
NamedType
|
|
name: b
|
|
rightBracket: >
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_accepted_semicolon() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
void f() {
|
|
f<a, b>;
|
|
}
|
|
''');
|
|
parseResult.assertNoErrors();
|
|
var node = parseResult.findNode.singleExpressionStatement.expression;
|
|
assertParsedNodeText(node, r'''
|
|
FunctionReference
|
|
function: SimpleIdentifier
|
|
token: f
|
|
typeArguments: TypeArgumentList
|
|
leftBracket: <
|
|
arguments
|
|
NamedType
|
|
name: a
|
|
NamedType
|
|
name: b
|
|
rightBracket: >
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_rejected_ampersand() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f(a<b,c>&d);
|
|
''');
|
|
parseResult.assertErrors([error(diag.missingIdentifier, 16, 1)]);
|
|
var node = parseResult.findNode.singleMethodInvocation;
|
|
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: <empty> <synthetic>
|
|
operator: &
|
|
rightOperand: SimpleIdentifier
|
|
token: d
|
|
rightParenthesis: )
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_rejected_as() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f(a < b, c > as);
|
|
''');
|
|
parseResult.assertNoErrors();
|
|
var node = parseResult.findNode.singleMethodInvocation;
|
|
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: SimpleIdentifier
|
|
token: as
|
|
rightParenthesis: )
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_rejected_asterisk() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f(a<b,c>*d);
|
|
''');
|
|
parseResult.assertErrors([error(diag.missingIdentifier, 16, 1)]);
|
|
var node = parseResult.findNode.singleMethodInvocation;
|
|
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: <empty> <synthetic>
|
|
operator: *
|
|
rightOperand: SimpleIdentifier
|
|
token: d
|
|
rightParenthesis: )
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_rejected_bang_openBracket() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f(a < b, c > ![d]);
|
|
''');
|
|
parseResult.assertNoErrors();
|
|
var node = parseResult.findNode.singleMethodInvocation;
|
|
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: PrefixExpression
|
|
operator: !
|
|
operand: ListLiteral
|
|
leftBracket: [
|
|
elements
|
|
SimpleIdentifier
|
|
token: d
|
|
rightBracket: ]
|
|
rightParenthesis: )
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_rejected_bang_paren() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f(a < b, c > !(d));
|
|
''');
|
|
parseResult.assertNoErrors();
|
|
var node = parseResult.findNode.singleMethodInvocation;
|
|
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: PrefixExpression
|
|
operator: !
|
|
operand: ParenthesizedExpression
|
|
leftParenthesis: (
|
|
expression: SimpleIdentifier
|
|
token: d
|
|
rightParenthesis: )
|
|
rightParenthesis: )
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_rejected_bar() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f(a<b,c>|d);
|
|
''');
|
|
parseResult.assertErrors([error(diag.missingIdentifier, 16, 1)]);
|
|
var node = parseResult.findNode.singleMethodInvocation;
|
|
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: <empty> <synthetic>
|
|
operator: |
|
|
rightOperand: SimpleIdentifier
|
|
token: d
|
|
rightParenthesis: )
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_rejected_caret() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f(a<b,c>^d);
|
|
''');
|
|
parseResult.assertErrors([error(diag.missingIdentifier, 16, 1)]);
|
|
var node = parseResult.findNode.singleMethodInvocation;
|
|
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: <empty> <synthetic>
|
|
operator: ^
|
|
rightOperand: SimpleIdentifier
|
|
token: d
|
|
rightParenthesis: )
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_rejected_is() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f(a<b,c> is int);
|
|
''');
|
|
parseResult.assertErrors([error(diag.missingIdentifier, 17, 2)]);
|
|
var node = parseResult.findNode.singleMethodInvocation;
|
|
assertParsedNodeText(node, r'''
|
|
MethodInvocation
|
|
methodName: SimpleIdentifier
|
|
token: f
|
|
argumentList: ArgumentList
|
|
leftParenthesis: (
|
|
arguments
|
|
BinaryExpression
|
|
leftOperand: SimpleIdentifier
|
|
token: a
|
|
operator: <
|
|
rightOperand: SimpleIdentifier
|
|
token: b
|
|
IsExpression
|
|
expression: BinaryExpression
|
|
leftOperand: SimpleIdentifier
|
|
token: c
|
|
operator: >
|
|
rightOperand: SimpleIdentifier
|
|
token: <empty> <synthetic>
|
|
isOperator: is
|
|
type: NamedType
|
|
name: int
|
|
rightParenthesis: )
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_rejected_lessThan() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f<a><b>;
|
|
''');
|
|
parseResult.assertErrors([
|
|
error(diag.equalityCannotBeEqualityOperand, 11, 1),
|
|
error(diag.expectedToken, 15, 1),
|
|
]);
|
|
var node = parseResult.findNode.singleVariableDeclaration.initializer!;
|
|
assertParsedNodeText(node, r'''
|
|
BinaryExpression
|
|
leftOperand: BinaryExpression
|
|
leftOperand: SimpleIdentifier
|
|
token: f
|
|
operator: <
|
|
rightOperand: SimpleIdentifier
|
|
token: a
|
|
operator: >
|
|
rightOperand: ListLiteral
|
|
typeArguments: TypeArgumentList
|
|
leftBracket: <
|
|
arguments
|
|
NamedType
|
|
name: b
|
|
rightBracket: >
|
|
leftBracket: [ <synthetic>
|
|
rightBracket: ] <synthetic>
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_rejected_minus() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f(a < b, c > -d);
|
|
''');
|
|
parseResult.assertNoErrors();
|
|
var node = parseResult.findNode.singleMethodInvocation;
|
|
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: PrefixExpression
|
|
operator: -
|
|
operand: SimpleIdentifier
|
|
token: d
|
|
rightParenthesis: )
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_rejected_openBracket() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f(a < b, c > [d]);
|
|
''');
|
|
parseResult.assertNoErrors();
|
|
var node = parseResult.findNode.singleMethodInvocation;
|
|
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: ListLiteral
|
|
leftBracket: [
|
|
elements
|
|
SimpleIdentifier
|
|
token: d
|
|
rightBracket: ]
|
|
rightParenthesis: )
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_rejected_openBracket_error() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f(a<b,c>[d]>e);
|
|
''');
|
|
parseResult.assertErrors([
|
|
error(diag.equalityCannotBeEqualityOperand, 19, 1),
|
|
]);
|
|
var node = parseResult.findNode.singleMethodInvocation;
|
|
assertParsedNodeText(node, r'''
|
|
MethodInvocation
|
|
methodName: SimpleIdentifier
|
|
token: f
|
|
argumentList: ArgumentList
|
|
leftParenthesis: (
|
|
arguments
|
|
BinaryExpression
|
|
leftOperand: SimpleIdentifier
|
|
token: a
|
|
operator: <
|
|
rightOperand: SimpleIdentifier
|
|
token: b
|
|
BinaryExpression
|
|
leftOperand: BinaryExpression
|
|
leftOperand: SimpleIdentifier
|
|
token: c
|
|
operator: >
|
|
rightOperand: ListLiteral
|
|
leftBracket: [
|
|
elements
|
|
SimpleIdentifier
|
|
token: d
|
|
rightBracket: ]
|
|
operator: >
|
|
rightOperand: SimpleIdentifier
|
|
token: e
|
|
rightParenthesis: )
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_rejected_openBracket_unambiguous() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f(a < b, c > [d, e]);
|
|
''');
|
|
parseResult.assertNoErrors();
|
|
var node = parseResult.findNode.singleMethodInvocation;
|
|
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: ListLiteral
|
|
leftBracket: [
|
|
elements
|
|
SimpleIdentifier
|
|
token: d
|
|
SimpleIdentifier
|
|
token: e
|
|
rightBracket: ]
|
|
rightParenthesis: )
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_rejected_percent() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f(a<b,c>%d);
|
|
''');
|
|
parseResult.assertErrors([error(diag.missingIdentifier, 16, 1)]);
|
|
var node = parseResult.findNode.singleMethodInvocation;
|
|
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: <empty> <synthetic>
|
|
operator: %
|
|
rightOperand: SimpleIdentifier
|
|
token: d
|
|
rightParenthesis: )
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_rejected_period_period() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f(a<b,c>..toString());
|
|
''');
|
|
parseResult.assertErrors([error(diag.missingIdentifier, 16, 2)]);
|
|
var node = parseResult.findNode.methodInvocation('f(');
|
|
assertParsedNodeText(node, r'''
|
|
MethodInvocation
|
|
methodName: SimpleIdentifier
|
|
token: f
|
|
argumentList: ArgumentList
|
|
leftParenthesis: (
|
|
arguments
|
|
BinaryExpression
|
|
leftOperand: SimpleIdentifier
|
|
token: a
|
|
operator: <
|
|
rightOperand: SimpleIdentifier
|
|
token: b
|
|
CascadeExpression
|
|
target: BinaryExpression
|
|
leftOperand: SimpleIdentifier
|
|
token: c
|
|
operator: >
|
|
rightOperand: SimpleIdentifier
|
|
token: <empty> <synthetic>
|
|
cascadeSections
|
|
MethodInvocation
|
|
operator: ..
|
|
methodName: SimpleIdentifier
|
|
token: toString
|
|
argumentList: ArgumentList
|
|
leftParenthesis: (
|
|
rightParenthesis: )
|
|
rightParenthesis: )
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_rejected_plus() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f(a<b,c>+d);
|
|
''');
|
|
parseResult.assertErrors([error(diag.missingIdentifier, 16, 1)]);
|
|
var node = parseResult.findNode.singleMethodInvocation;
|
|
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: <empty> <synthetic>
|
|
operator: +
|
|
rightOperand: SimpleIdentifier
|
|
token: d
|
|
rightParenthesis: )
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_rejected_question() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f(a<b,c> ? null : null);
|
|
''');
|
|
parseResult.assertErrors([error(diag.missingIdentifier, 17, 1)]);
|
|
var node = parseResult.findNode.singleMethodInvocation;
|
|
assertParsedNodeText(node, r'''
|
|
MethodInvocation
|
|
methodName: SimpleIdentifier
|
|
token: f
|
|
argumentList: ArgumentList
|
|
leftParenthesis: (
|
|
arguments
|
|
BinaryExpression
|
|
leftOperand: SimpleIdentifier
|
|
token: a
|
|
operator: <
|
|
rightOperand: SimpleIdentifier
|
|
token: b
|
|
ConditionalExpression
|
|
condition: BinaryExpression
|
|
leftOperand: SimpleIdentifier
|
|
token: c
|
|
operator: >
|
|
rightOperand: SimpleIdentifier
|
|
token: <empty> <synthetic>
|
|
question: ?
|
|
thenExpression: NullLiteral
|
|
literal: null
|
|
colon: :
|
|
elseExpression: NullLiteral
|
|
literal: null
|
|
rightParenthesis: )
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_rejected_question_period_methodInvocation() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f(a<b,c>?.toString());
|
|
''');
|
|
parseResult.assertErrors([error(diag.missingIdentifier, 16, 2)]);
|
|
var node = parseResult.findNode.methodInvocation('f(');
|
|
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: MethodInvocation
|
|
target: SimpleIdentifier
|
|
token: <empty> <synthetic>
|
|
operator: ?.
|
|
methodName: SimpleIdentifier
|
|
token: toString
|
|
argumentList: ArgumentList
|
|
leftParenthesis: (
|
|
rightParenthesis: )
|
|
rightParenthesis: )
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_rejected_question_period_methodInvocation_generic() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f(a<b,c>?.foo<c>());
|
|
''');
|
|
parseResult.assertErrors([error(diag.missingIdentifier, 16, 2)]);
|
|
var node = parseResult.findNode.methodInvocation('f(');
|
|
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: MethodInvocation
|
|
target: SimpleIdentifier
|
|
token: <empty> <synthetic>
|
|
operator: ?.
|
|
methodName: SimpleIdentifier
|
|
token: foo
|
|
typeArguments: TypeArgumentList
|
|
leftBracket: <
|
|
arguments
|
|
NamedType
|
|
name: c
|
|
rightBracket: >
|
|
argumentList: ArgumentList
|
|
leftParenthesis: (
|
|
rightParenthesis: )
|
|
rightParenthesis: )
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_rejected_question_period_period() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f(a<b,c>?..toString());
|
|
''');
|
|
parseResult.assertErrors([
|
|
error(diag.missingIdentifier, 16, 3),
|
|
error(diag.expectedToken, 19, 8),
|
|
]);
|
|
var node = parseResult.findNode.methodInvocation('f(');
|
|
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: SimpleIdentifier
|
|
token: <empty> <synthetic>
|
|
MethodInvocation
|
|
methodName: SimpleIdentifier
|
|
token: toString
|
|
argumentList: ArgumentList
|
|
leftParenthesis: (
|
|
rightParenthesis: )
|
|
rightParenthesis: )
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_rejected_question_period_propertyAccess() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f(a<b,c>?.hashCode);
|
|
''');
|
|
parseResult.assertErrors([error(diag.missingIdentifier, 16, 2)]);
|
|
var node = parseResult.findNode.singleMethodInvocation;
|
|
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: PropertyAccess
|
|
target: SimpleIdentifier
|
|
token: <empty> <synthetic>
|
|
operator: ?.
|
|
propertyName: SimpleIdentifier
|
|
token: hashCode
|
|
rightParenthesis: )
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_rejected_question_question() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f(a<b,c> ?? d);
|
|
''');
|
|
parseResult.assertErrors([error(diag.missingIdentifier, 17, 2)]);
|
|
var node = parseResult.findNode.singleMethodInvocation;
|
|
assertParsedNodeText(node, r'''
|
|
MethodInvocation
|
|
methodName: SimpleIdentifier
|
|
token: f
|
|
argumentList: ArgumentList
|
|
leftParenthesis: (
|
|
arguments
|
|
BinaryExpression
|
|
leftOperand: SimpleIdentifier
|
|
token: a
|
|
operator: <
|
|
rightOperand: SimpleIdentifier
|
|
token: b
|
|
BinaryExpression
|
|
leftOperand: BinaryExpression
|
|
leftOperand: SimpleIdentifier
|
|
token: c
|
|
operator: >
|
|
rightOperand: SimpleIdentifier
|
|
token: <empty> <synthetic>
|
|
operator: ??
|
|
rightOperand: SimpleIdentifier
|
|
token: d
|
|
rightParenthesis: )
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_rejected_slash() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f(a<b,c>/d);
|
|
''');
|
|
parseResult.assertErrors([error(diag.missingIdentifier, 16, 1)]);
|
|
var node = parseResult.findNode.singleMethodInvocation;
|
|
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: <empty> <synthetic>
|
|
operator: /
|
|
rightOperand: SimpleIdentifier
|
|
token: d
|
|
rightParenthesis: )
|
|
''');
|
|
}
|
|
|
|
void test_followingToken_rejected_tilde_slash() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f(a<b,c>~/d);
|
|
''');
|
|
parseResult.assertErrors([error(diag.missingIdentifier, 16, 2)]);
|
|
var node = parseResult.findNode.singleMethodInvocation;
|
|
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: <empty> <synthetic>
|
|
operator: ~/
|
|
rightOperand: SimpleIdentifier
|
|
token: d
|
|
rightParenthesis: )
|
|
''');
|
|
}
|
|
|
|
void test_functionReference_after_indexExpression() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = x[0]<a, b>;
|
|
''');
|
|
parseResult.assertNoErrors();
|
|
var node = parseResult.findNode.singleVariableDeclaration.initializer!;
|
|
assertParsedNodeText(node, r'''
|
|
FunctionReference
|
|
function: IndexExpression
|
|
target: SimpleIdentifier
|
|
token: x
|
|
leftBracket: [
|
|
index: IntegerLiteral
|
|
literal: 0
|
|
rightBracket: ]
|
|
typeArguments: TypeArgumentList
|
|
leftBracket: <
|
|
arguments
|
|
NamedType
|
|
name: a
|
|
NamedType
|
|
name: b
|
|
rightBracket: >
|
|
''');
|
|
}
|
|
|
|
void test_functionReference_after_indexExpression_bang() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = x[0]!<a, b>;
|
|
''');
|
|
parseResult.assertNoErrors();
|
|
var node = parseResult.findNode.singleVariableDeclaration.initializer!;
|
|
assertParsedNodeText(node, r'''
|
|
FunctionReference
|
|
function: PostfixExpression
|
|
operand: IndexExpression
|
|
target: SimpleIdentifier
|
|
token: x
|
|
leftBracket: [
|
|
index: IntegerLiteral
|
|
literal: 0
|
|
rightBracket: ]
|
|
operator: !
|
|
typeArguments: TypeArgumentList
|
|
leftBracket: <
|
|
arguments
|
|
NamedType
|
|
name: a
|
|
NamedType
|
|
name: b
|
|
rightBracket: >
|
|
''');
|
|
}
|
|
|
|
void test_functionReference_after_indexExpression_functionCall() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = x[0]()<a, b>;
|
|
''');
|
|
parseResult.assertNoErrors();
|
|
var node = parseResult.findNode.singleVariableDeclaration.initializer!;
|
|
assertParsedNodeText(node, r'''
|
|
FunctionReference
|
|
function: FunctionExpressionInvocation
|
|
function: IndexExpression
|
|
target: SimpleIdentifier
|
|
token: x
|
|
leftBracket: [
|
|
index: IntegerLiteral
|
|
literal: 0
|
|
rightBracket: ]
|
|
argumentList: ArgumentList
|
|
leftParenthesis: (
|
|
rightParenthesis: )
|
|
typeArguments: TypeArgumentList
|
|
leftBracket: <
|
|
arguments
|
|
NamedType
|
|
name: a
|
|
NamedType
|
|
name: b
|
|
rightBracket: >
|
|
''');
|
|
}
|
|
|
|
void test_functionReference_after_indexExpression_nullAware() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = x?[0]<a, b>;
|
|
''');
|
|
parseResult.assertNoErrors();
|
|
var node = parseResult.findNode.singleVariableDeclaration.initializer!;
|
|
assertParsedNodeText(node, r'''
|
|
FunctionReference
|
|
function: IndexExpression
|
|
target: SimpleIdentifier
|
|
token: x
|
|
question: ?
|
|
leftBracket: [
|
|
index: IntegerLiteral
|
|
literal: 0
|
|
rightBracket: ]
|
|
typeArguments: TypeArgumentList
|
|
leftBracket: <
|
|
arguments
|
|
NamedType
|
|
name: a
|
|
NamedType
|
|
name: b
|
|
rightBracket: >
|
|
''');
|
|
}
|
|
|
|
void test_methodTearoff() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f().m<a, b>;
|
|
''');
|
|
parseResult.assertNoErrors();
|
|
var node = parseResult.findNode.singleVariableDeclaration.initializer!;
|
|
assertParsedNodeText(node, r'''
|
|
FunctionReference
|
|
function: PropertyAccess
|
|
target: MethodInvocation
|
|
methodName: SimpleIdentifier
|
|
token: f
|
|
argumentList: ArgumentList
|
|
leftParenthesis: (
|
|
rightParenthesis: )
|
|
operator: .
|
|
propertyName: SimpleIdentifier
|
|
token: m
|
|
typeArguments: TypeArgumentList
|
|
leftBracket: <
|
|
arguments
|
|
NamedType
|
|
name: a
|
|
NamedType
|
|
name: b
|
|
rightBracket: >
|
|
''');
|
|
}
|
|
|
|
void test_methodTearoff_cascaded() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = f()..m<a, b>;
|
|
''');
|
|
parseResult.assertNoErrors();
|
|
var node = parseResult.findNode.singleCascadeExpression.cascadeSections[0];
|
|
assertParsedNodeText(node, r'''
|
|
FunctionReference
|
|
function: PropertyAccess
|
|
operator: ..
|
|
propertyName: SimpleIdentifier
|
|
token: m
|
|
typeArguments: TypeArgumentList
|
|
leftBracket: <
|
|
arguments
|
|
NamedType
|
|
name: a
|
|
NamedType
|
|
name: b
|
|
rightBracket: >
|
|
''');
|
|
}
|
|
|
|
void test_prefixedIdentifier() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = prefix.f<a, b>;
|
|
''');
|
|
parseResult.assertNoErrors();
|
|
var node = parseResult.findNode.singleVariableDeclaration.initializer!;
|
|
assertParsedNodeText(node, r'''
|
|
FunctionReference
|
|
function: PrefixedIdentifier
|
|
prefix: SimpleIdentifier
|
|
token: prefix
|
|
period: .
|
|
identifier: SimpleIdentifier
|
|
token: f
|
|
typeArguments: TypeArgumentList
|
|
leftBracket: <
|
|
arguments
|
|
NamedType
|
|
name: a
|
|
NamedType
|
|
name: b
|
|
rightBracket: >
|
|
''');
|
|
}
|
|
|
|
void test_three_identifiers() {
|
|
var parseResult = parseStringWithErrors(r'''
|
|
var x = prefix.ClassName.m<a, b>;
|
|
''');
|
|
parseResult.assertNoErrors();
|
|
var node = parseResult.findNode.singleVariableDeclaration.initializer!;
|
|
assertParsedNodeText(node, r'''
|
|
FunctionReference
|
|
function: PropertyAccess
|
|
target: PrefixedIdentifier
|
|
prefix: SimpleIdentifier
|
|
token: prefix
|
|
period: .
|
|
identifier: SimpleIdentifier
|
|
token: ClassName
|
|
operator: .
|
|
propertyName: SimpleIdentifier
|
|
token: m
|
|
typeArguments: TypeArgumentList
|
|
leftBracket: <
|
|
arguments
|
|
NamedType
|
|
name: a
|
|
NamedType
|
|
name: b
|
|
rightBracket: >
|
|
''');
|
|
}
|
|
}
|