3009984866
Change-Id: Id992c63a83bbb8eb2f2539f8735b72ee1c3a2e39 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/504121 Reviewed-by: Johnni Winther <johnniwinther@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
439 lines
10 KiB
Dart
439 lines
10 KiB
Dart
// 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.
|
|
|
|
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(ExtensionMethodsParserTest);
|
|
defineReflectiveTests(UpdateNodeTextExpectations);
|
|
});
|
|
}
|
|
|
|
@reflectiveTest
|
|
class ExtensionMethodsParserTest extends ParserDiagnosticsTest {
|
|
void test_complex_extends() {
|
|
var parseResult = parseTestCodeWithDiagnostics(r'''
|
|
extension E extends A with B, C implements D { }
|
|
// ^^^^^^^
|
|
// [diag.expectedInstead] Expected 'on' instead of this.
|
|
// ^^^^
|
|
// [diag.unexpectedToken] Unexpected text 'with'.
|
|
// ^
|
|
// [diag.unexpectedToken] Unexpected text ','.
|
|
// ^^^^^^^^^^
|
|
// [diag.unexpectedToken] Unexpected text 'implements'.
|
|
''');
|
|
|
|
var node = parseResult.findNode.singleExtensionDeclaration;
|
|
assertParsedNodeText(node, r'''
|
|
ExtensionDeclaration
|
|
extensionKeyword: extension
|
|
name: E
|
|
onClause: ExtensionOnClause
|
|
onKeyword: extends
|
|
extendedType: NamedType
|
|
name: A
|
|
body: BlockClassBody
|
|
leftBracket: {
|
|
rightBracket: }
|
|
''');
|
|
}
|
|
|
|
void test_complex_implements() {
|
|
var parseResult = parseTestCodeWithDiagnostics(r'''
|
|
extension E implements C, D { }
|
|
// ^^^^^^^^^^
|
|
// [diag.expectedInstead] Expected 'on' instead of this.
|
|
// ^
|
|
// [diag.unexpectedToken] Unexpected text ','.
|
|
''');
|
|
|
|
var node = parseResult.findNode.singleExtensionDeclaration;
|
|
assertParsedNodeText(node, r'''
|
|
ExtensionDeclaration
|
|
extensionKeyword: extension
|
|
name: E
|
|
onClause: ExtensionOnClause
|
|
onKeyword: implements
|
|
extendedType: NamedType
|
|
name: C
|
|
body: BlockClassBody
|
|
leftBracket: {
|
|
rightBracket: }
|
|
''');
|
|
}
|
|
|
|
void test_complex_type() {
|
|
var parseResult = parseTestCodeWithDiagnostics(r'''
|
|
extension E on C<T> {}
|
|
''');
|
|
|
|
var node = parseResult.findNode.singleExtensionDeclaration;
|
|
assertParsedNodeText(node, r'''
|
|
ExtensionDeclaration
|
|
extensionKeyword: extension
|
|
name: E
|
|
onClause: ExtensionOnClause
|
|
onKeyword: on
|
|
extendedType: NamedType
|
|
name: C
|
|
typeArguments: TypeArgumentList
|
|
leftBracket: <
|
|
arguments
|
|
NamedType
|
|
name: T
|
|
rightBracket: >
|
|
body: BlockClassBody
|
|
leftBracket: {
|
|
rightBracket: }
|
|
''');
|
|
}
|
|
|
|
void test_complex_type2() {
|
|
var parseResult = parseTestCodeWithDiagnostics(r'''
|
|
extension E<T> on C<T> {}
|
|
''');
|
|
|
|
var node = parseResult.findNode.singleExtensionDeclaration;
|
|
assertParsedNodeText(node, r'''
|
|
ExtensionDeclaration
|
|
extensionKeyword: extension
|
|
name: E
|
|
typeParameters: TypeParameterList
|
|
leftBracket: <
|
|
typeParameters
|
|
TypeParameter
|
|
name: T
|
|
rightBracket: >
|
|
onClause: ExtensionOnClause
|
|
onKeyword: on
|
|
extendedType: NamedType
|
|
name: C
|
|
typeArguments: TypeArgumentList
|
|
leftBracket: <
|
|
arguments
|
|
NamedType
|
|
name: T
|
|
rightBracket: >
|
|
body: BlockClassBody
|
|
leftBracket: {
|
|
rightBracket: }
|
|
''');
|
|
}
|
|
|
|
void test_complex_type2_no_name() {
|
|
var parseResult = parseTestCodeWithDiagnostics(r'''
|
|
extension<T> on C<T> {}
|
|
''');
|
|
|
|
var node = parseResult.findNode.singleExtensionDeclaration;
|
|
assertParsedNodeText(node, r'''
|
|
ExtensionDeclaration
|
|
extensionKeyword: extension
|
|
typeParameters: TypeParameterList
|
|
leftBracket: <
|
|
typeParameters
|
|
TypeParameter
|
|
name: T
|
|
rightBracket: >
|
|
onClause: ExtensionOnClause
|
|
onKeyword: on
|
|
extendedType: NamedType
|
|
name: C
|
|
typeArguments: TypeArgumentList
|
|
leftBracket: <
|
|
arguments
|
|
NamedType
|
|
name: T
|
|
rightBracket: >
|
|
body: BlockClassBody
|
|
leftBracket: {
|
|
rightBracket: }
|
|
''');
|
|
}
|
|
|
|
void test_constructor_named() {
|
|
var parseResult = parseTestCodeWithDiagnostics('''
|
|
extension E on C {
|
|
E.named();
|
|
//^
|
|
// [diag.extensionDeclaresConstructor] Extensions can't declare constructors.
|
|
}
|
|
class C {}
|
|
''');
|
|
|
|
var node = parseResult.findNode.singleExtensionDeclaration;
|
|
assertParsedNodeText(node, r'''
|
|
ExtensionDeclaration
|
|
extensionKeyword: extension
|
|
name: E
|
|
onClause: ExtensionOnClause
|
|
onKeyword: on
|
|
extendedType: NamedType
|
|
name: C
|
|
body: BlockClassBody
|
|
leftBracket: {
|
|
rightBracket: }
|
|
''');
|
|
}
|
|
|
|
void test_constructor_unnamed() {
|
|
var parseResult = parseTestCodeWithDiagnostics('''
|
|
extension E on C {
|
|
E();
|
|
//^
|
|
// [diag.extensionDeclaresConstructor] Extensions can't declare constructors.
|
|
}
|
|
class C {}
|
|
''');
|
|
|
|
var node = parseResult.findNode.singleExtensionDeclaration;
|
|
assertParsedNodeText(node, r'''
|
|
ExtensionDeclaration
|
|
extensionKeyword: extension
|
|
name: E
|
|
onClause: ExtensionOnClause
|
|
onKeyword: on
|
|
extendedType: NamedType
|
|
name: C
|
|
body: BlockClassBody
|
|
leftBracket: {
|
|
rightBracket: }
|
|
''');
|
|
}
|
|
|
|
void test_missing_on() {
|
|
var parseResult = parseTestCodeWithDiagnostics(r'''
|
|
extension E
|
|
// ^
|
|
// [diag.expectedToken] Expected to find 'on'.
|
|
// ^
|
|
// [diag.expectedTypeName][column 12][length 0] Expected a type name.
|
|
// [diag.expectedExtensionBody][column 12][length 0] An extension declaration must have a body, even if it is empty.
|
|
''');
|
|
|
|
var node = parseResult.findNode.singleExtensionDeclaration;
|
|
assertParsedNodeText(node, r'''
|
|
ExtensionDeclaration
|
|
extensionKeyword: extension
|
|
name: E
|
|
onClause: ExtensionOnClause
|
|
onKeyword: on <synthetic>
|
|
extendedType: NamedType
|
|
name: <empty> <synthetic>
|
|
body: BlockClassBody
|
|
leftBracket: { <synthetic>
|
|
rightBracket: } <synthetic>
|
|
''');
|
|
}
|
|
|
|
void test_missing_on_withBlock() {
|
|
var parseResult = parseTestCodeWithDiagnostics(r'''
|
|
extension E {}
|
|
// ^
|
|
// [diag.expectedToken] Expected to find 'on'.
|
|
// ^
|
|
// [diag.expectedTypeName] Expected a type name.
|
|
''');
|
|
|
|
var node = parseResult.findNode.singleExtensionDeclaration;
|
|
assertParsedNodeText(node, r'''
|
|
ExtensionDeclaration
|
|
extensionKeyword: extension
|
|
name: E
|
|
onClause: ExtensionOnClause
|
|
onKeyword: on <synthetic>
|
|
extendedType: NamedType
|
|
name: <empty> <synthetic>
|
|
body: BlockClassBody
|
|
leftBracket: {
|
|
rightBracket: }
|
|
''');
|
|
}
|
|
|
|
void test_missing_on_withClassAndBlock() {
|
|
var parseResult = parseTestCodeWithDiagnostics(r'''
|
|
extension E C {}
|
|
// ^
|
|
// [diag.expectedToken] Expected to find 'on'.
|
|
''');
|
|
|
|
var node = parseResult.findNode.singleExtensionDeclaration;
|
|
assertParsedNodeText(node, r'''
|
|
ExtensionDeclaration
|
|
extensionKeyword: extension
|
|
name: E
|
|
onClause: ExtensionOnClause
|
|
onKeyword: on <synthetic>
|
|
extendedType: NamedType
|
|
name: C
|
|
body: BlockClassBody
|
|
leftBracket: {
|
|
rightBracket: }
|
|
''');
|
|
}
|
|
|
|
void test_parse_toplevel_member_called_late_calling_self() {
|
|
var parseResult = parseTestCodeWithDiagnostics(r'''
|
|
void late() {
|
|
late();
|
|
}
|
|
''');
|
|
|
|
var node = parseResult.findNode.singleFunctionDeclaration;
|
|
assertParsedNodeText(node, r'''
|
|
FunctionDeclaration
|
|
returnType: NamedType
|
|
name: void
|
|
name: late
|
|
functionExpression: FunctionExpression
|
|
parameters: FormalParameterList
|
|
leftParenthesis: (
|
|
rightParenthesis: )
|
|
body: BlockFunctionBody
|
|
block: Block
|
|
leftBracket: {
|
|
statements
|
|
ExpressionStatement
|
|
expression: MethodInvocation
|
|
methodName: SimpleIdentifier
|
|
token: late
|
|
argumentList: ArgumentList
|
|
leftParenthesis: (
|
|
rightParenthesis: )
|
|
semicolon: ;
|
|
rightBracket: }
|
|
''');
|
|
}
|
|
|
|
void test_simple() {
|
|
var parseResult = parseTestCodeWithDiagnostics(r'''
|
|
extension E on C {}
|
|
''');
|
|
|
|
var node = parseResult.findNode.singleExtensionDeclaration;
|
|
assertParsedNodeText(node, r'''
|
|
ExtensionDeclaration
|
|
extensionKeyword: extension
|
|
name: E
|
|
onClause: ExtensionOnClause
|
|
onKeyword: on
|
|
extendedType: NamedType
|
|
name: C
|
|
body: BlockClassBody
|
|
leftBracket: {
|
|
rightBracket: }
|
|
''');
|
|
}
|
|
|
|
void test_simple_extends() {
|
|
var parseResult = parseTestCodeWithDiagnostics(r'''
|
|
extension E extends C { }
|
|
// ^^^^^^^
|
|
// [diag.expectedInstead] Expected 'on' instead of this.
|
|
''');
|
|
|
|
var node = parseResult.findNode.singleExtensionDeclaration;
|
|
assertParsedNodeText(node, r'''
|
|
ExtensionDeclaration
|
|
extensionKeyword: extension
|
|
name: E
|
|
onClause: ExtensionOnClause
|
|
onKeyword: extends
|
|
extendedType: NamedType
|
|
name: C
|
|
body: BlockClassBody
|
|
leftBracket: {
|
|
rightBracket: }
|
|
''');
|
|
}
|
|
|
|
void test_simple_implements() {
|
|
var parseResult = parseTestCodeWithDiagnostics(r'''
|
|
extension E implements C { }
|
|
// ^^^^^^^^^^
|
|
// [diag.expectedInstead] Expected 'on' instead of this.
|
|
''');
|
|
|
|
var node = parseResult.findNode.singleExtensionDeclaration;
|
|
assertParsedNodeText(node, r'''
|
|
ExtensionDeclaration
|
|
extensionKeyword: extension
|
|
name: E
|
|
onClause: ExtensionOnClause
|
|
onKeyword: implements
|
|
extendedType: NamedType
|
|
name: C
|
|
body: BlockClassBody
|
|
leftBracket: {
|
|
rightBracket: }
|
|
''');
|
|
}
|
|
|
|
void test_simple_no_name() {
|
|
var parseResult = parseTestCodeWithDiagnostics(r'''
|
|
extension on C {}
|
|
''');
|
|
|
|
var node = parseResult.findNode.singleExtensionDeclaration;
|
|
assertParsedNodeText(node, r'''
|
|
ExtensionDeclaration
|
|
extensionKeyword: extension
|
|
onClause: ExtensionOnClause
|
|
onKeyword: on
|
|
extendedType: NamedType
|
|
name: C
|
|
body: BlockClassBody
|
|
leftBracket: {
|
|
rightBracket: }
|
|
''');
|
|
}
|
|
|
|
void test_simple_with() {
|
|
var parseResult = parseTestCodeWithDiagnostics(r'''
|
|
extension E with C { }
|
|
// ^^^^
|
|
// [diag.expectedInstead] Expected 'on' instead of this.
|
|
''');
|
|
|
|
var node = parseResult.findNode.singleExtensionDeclaration;
|
|
assertParsedNodeText(node, r'''
|
|
ExtensionDeclaration
|
|
extensionKeyword: extension
|
|
name: E
|
|
onClause: ExtensionOnClause
|
|
onKeyword: with
|
|
extendedType: NamedType
|
|
name: C
|
|
body: BlockClassBody
|
|
leftBracket: {
|
|
rightBracket: }
|
|
''');
|
|
}
|
|
|
|
void test_void_type() {
|
|
var parseResult = parseTestCodeWithDiagnostics(r'''
|
|
extension E on void {}
|
|
''');
|
|
|
|
var node = parseResult.findNode.singleExtensionDeclaration;
|
|
assertParsedNodeText(node, r'''
|
|
ExtensionDeclaration
|
|
extensionKeyword: extension
|
|
name: E
|
|
onClause: ExtensionOnClause
|
|
onKeyword: on
|
|
extendedType: NamedType
|
|
name: void
|
|
body: BlockClassBody
|
|
leftBracket: {
|
|
rightBracket: }
|
|
''');
|
|
}
|
|
}
|