| // 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:_fe_analyzer_shared/src/scanner/scanner.dart' as fasta; |
| import 'package:analyzer/dart/ast/ast.dart'; |
| import 'package:analyzer/dart/ast/token.dart'; |
| import 'package:analyzer/src/dart/scanner/scanner.dart'; |
| import 'package:analyzer/src/error/codes.dart'; |
| import 'package:test/test.dart'; |
| import 'package:test_reflective_loader/test_reflective_loader.dart'; |
| |
| import '../util/ast_type_matchers.dart'; |
| import '../util/feature_sets.dart'; |
| import 'parser_test_base.dart'; |
| |
| main() { |
| defineReflectiveSuite(() { |
| defineReflectiveTests(ErrorParserTest); |
| }); |
| } |
| |
| /// This defines parser tests that test the parsing of code to ensure that |
| /// errors are correctly reported, and in some cases, not reported. |
| @reflectiveTest |
| class ErrorParserTest extends FastaParserTestCase { |
| void test_abstractClassMember_constructor() { |
| createParser('abstract C.c();'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.abstractClassMember, 0, 8), |
| ]); |
| } |
| |
| void test_abstractClassMember_field() { |
| createParser('abstract C f;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| assertNoErrors(); |
| } |
| |
| void test_abstractClassMember_getter() { |
| createParser('abstract get m;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.abstractClassMember, 0, 8), |
| ]); |
| } |
| |
| void test_abstractClassMember_method() { |
| createParser('abstract m();'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.abstractClassMember, 0, 8), |
| ]); |
| } |
| |
| void test_abstractClassMember_setter() { |
| createParser('abstract set m(v);'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.abstractClassMember, 0, 8), |
| ]); |
| } |
| |
| void test_abstractEnum() { |
| parseCompilationUnit( |
| "abstract enum E {ONE}", |
| errors: [expectedError(ParserErrorCode.extraneousModifier, 0, 8)], |
| ); |
| } |
| |
| void test_abstractTopLevelFunction_function() { |
| parseCompilationUnit( |
| "abstract f(v) {}", |
| errors: [expectedError(ParserErrorCode.extraneousModifier, 0, 8)], |
| ); |
| } |
| |
| void test_abstractTopLevelFunction_getter() { |
| parseCompilationUnit( |
| "abstract get m {}", |
| errors: [expectedError(ParserErrorCode.extraneousModifier, 0, 8)], |
| ); |
| } |
| |
| void test_abstractTopLevelFunction_setter() { |
| parseCompilationUnit( |
| "abstract set m(v) {}", |
| errors: [expectedError(ParserErrorCode.extraneousModifier, 0, 8)], |
| ); |
| } |
| |
| void test_abstractTopLevelVariable() { |
| parseCompilationUnit( |
| "abstract C f;", |
| errors: [expectedError(ParserErrorCode.extraneousModifier, 0, 8)], |
| ); |
| } |
| |
| void test_abstractTypeDef() { |
| parseCompilationUnit( |
| "abstract typedef F();", |
| errors: [expectedError(ParserErrorCode.extraneousModifier, 0, 8)], |
| ); |
| } |
| |
| void test_await_missing_async2_issue36048() { |
| parseCompilationUnit( |
| ''' |
| main() { // missing async |
| await foo.bar(); |
| } |
| ''', |
| errors: [expectedError(CompileTimeErrorCode.awaitInWrongContext, 28, 5)], |
| ); |
| } |
| |
| void test_await_missing_async3_issue36048() { |
| parseCompilationUnit( |
| ''' |
| main() { // missing async |
| (await foo); |
| } |
| ''', |
| errors: [expectedError(CompileTimeErrorCode.awaitInWrongContext, 29, 5)], |
| ); |
| } |
| |
| void test_await_missing_async4_issue36048() { |
| parseCompilationUnit( |
| ''' |
| main() { // missing async |
| [await foo]; |
| } |
| ''', |
| errors: [expectedError(CompileTimeErrorCode.awaitInWrongContext, 29, 5)], |
| ); |
| } |
| |
| void test_await_missing_async_issue36048() { |
| parseCompilationUnit( |
| ''' |
| main() { // missing async |
| await foo(); |
| } |
| ''', |
| errors: [expectedError(CompileTimeErrorCode.awaitInWrongContext, 28, 5)], |
| ); |
| } |
| |
| void test_breakOutsideOfLoop_breakInDoStatement() { |
| var statement = parseStatement('do {break;} while (x);') as DoStatement; |
| expectNotNullIfNoErrors(statement); |
| assertNoErrors(); |
| } |
| |
| void test_breakOutsideOfLoop_breakInForStatement() { |
| var statement = parseStatement('for (; x;) {break;}'); |
| expectNotNullIfNoErrors(statement); |
| assertNoErrors(); |
| } |
| |
| void test_breakOutsideOfLoop_breakInIfStatement() { |
| var statement = parseStatement('if (x) {break;}') as IfStatement; |
| expectNotNullIfNoErrors(statement); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.breakOutsideOfLoop, 8, 5), |
| ]); |
| } |
| |
| void test_breakOutsideOfLoop_breakInSwitchStatement() { |
| var statement = |
| parseStatement('switch (x) {case 1: break;}') as SwitchStatement; |
| expectNotNullIfNoErrors(statement); |
| assertNoErrors(); |
| } |
| |
| void test_breakOutsideOfLoop_breakInWhileStatement() { |
| var statement = parseStatement('while (x) {break;}') as WhileStatement; |
| expectNotNullIfNoErrors(statement); |
| assertNoErrors(); |
| } |
| |
| void test_breakOutsideOfLoop_functionExpression_inALoop() { |
| parseStatement("for(; x;) {() {break;};}"); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.breakOutsideOfLoop, 15, 5), |
| ]); |
| } |
| |
| void test_breakOutsideOfLoop_functionExpression_withALoop() { |
| parseStatement("() {for (; x;) {break;}};"); |
| } |
| |
| void test_classInClass_abstract() { |
| parseCompilationUnit( |
| "class C { abstract class B {} }", |
| errors: [ |
| expectedError(ParserErrorCode.abstractClassMember, 10, 8), |
| expectedError(ParserErrorCode.classInClass, 19, 5), |
| ], |
| ); |
| } |
| |
| void test_classInClass_nonAbstract() { |
| parseCompilationUnit( |
| "class C { class B {} }", |
| errors: [expectedError(ParserErrorCode.classInClass, 10, 5)], |
| ); |
| } |
| |
| void test_classTypeAlias_abstractAfterEq() { |
| // This syntax has been removed from the language in favor of |
| // "abstract class A = B with C;" (issue 18098). |
| createParser('class A = abstract B with C;', expectedEndOffset: 21); |
| CompilationUnitMember member = parseFullCompilationUnitMember(); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(CompileTimeErrorCode.builtInIdentifierAsType, 10, 8), |
| expectedError(ParserErrorCode.expectedToken, 19, 1), |
| expectedError(ParserErrorCode.expectedToken, 19, 1), |
| ]); |
| } |
| |
| void test_colonInPlaceOfIn() { |
| parseStatement("for (var x : list) {}"); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.colonInPlaceOfIn, 11, 1), |
| ]); |
| } |
| |
| void test_constAndCovariant() { |
| createParser('covariant const C f = null;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.conflictingModifiers, 10, 5), |
| ]); |
| } |
| |
| void test_constAndFinal() { |
| createParser('const final int x = null;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([expectedError(ParserErrorCode.constAndFinal, 6, 5)]); |
| } |
| |
| void test_constAndVar() { |
| createParser('const var x = null;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.conflictingModifiers, 6, 3), |
| ]); |
| } |
| |
| void test_constClass() { |
| parseCompilationUnit( |
| "const class C {}", |
| errors: [expectedError(ParserErrorCode.constClass, 0, 5)], |
| ); |
| } |
| |
| void test_constConstructorWithBody() { |
| createParser('const C() {}'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.constConstructorWithBody, 10, 1), |
| ]); |
| } |
| |
| void test_constEnum() { |
| parseCompilationUnit( |
| "const enum E {ONE}", |
| errors: [ |
| // Fasta interprets the `const` as a malformed top level const |
| // and `enum` as the start of an enum declaration. |
| expectedError(ParserErrorCode.expectedToken, 0, 5), |
| expectedError(ParserErrorCode.missingIdentifier, 6, 4), |
| ], |
| ); |
| } |
| |
| void test_constFactory() { |
| createParser('const factory C() {}'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([expectedError(ParserErrorCode.constFactory, 0, 5)]); |
| } |
| |
| void test_constMethod() { |
| createParser('const int m() {}'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([expectedError(ParserErrorCode.constMethod, 0, 5)]); |
| } |
| |
| void test_constMethod_noReturnType() { |
| createParser('const m() {}'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([expectedError(ParserErrorCode.constMethod, 0, 5)]); |
| } |
| |
| void test_constMethod_noReturnType2() { |
| createParser('const m();'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([expectedError(ParserErrorCode.constMethod, 0, 5)]); |
| } |
| |
| void test_constructor_super_cascade_synthetic() { |
| // https://github.com/dart-lang/sdk/issues/37110 |
| parseCompilationUnit( |
| 'class B extends A { B(): super.. {} }', |
| errors: [ |
| expectedError(ParserErrorCode.invalidSuperInInitializer, 25, 5), |
| expectedError(ParserErrorCode.expectedToken, 30, 2), |
| expectedError(ParserErrorCode.missingIdentifier, 33, 1), |
| ], |
| ); |
| } |
| |
| void test_constructor_super_field() { |
| // https://github.com/dart-lang/sdk/issues/36262 |
| // https://github.com/dart-lang/sdk/issues/31198 |
| parseCompilationUnit( |
| 'class B extends A { B(): super().foo {} }', |
| errors: [expectedError(ParserErrorCode.invalidSuperInInitializer, 25, 5)], |
| ); |
| } |
| |
| void test_constructor_super_method() { |
| // https://github.com/dart-lang/sdk/issues/36262 |
| // https://github.com/dart-lang/sdk/issues/31198 |
| parseCompilationUnit( |
| 'class B extends A { B(): super().foo() {} }', |
| errors: [expectedError(ParserErrorCode.invalidSuperInInitializer, 25, 5)], |
| ); |
| } |
| |
| void test_constructor_super_named_method() { |
| // https://github.com/dart-lang/sdk/issues/37600 |
| parseCompilationUnit( |
| 'class B extends A { B(): super.c().create() {} }', |
| errors: [expectedError(ParserErrorCode.invalidSuperInInitializer, 25, 5)], |
| ); |
| } |
| |
| void test_constructor_super_named_method_method() { |
| // https://github.com/dart-lang/sdk/issues/37600 |
| parseCompilationUnit( |
| 'class B extends A { B(): super.c().create().x() {} }', |
| errors: [expectedError(ParserErrorCode.invalidSuperInInitializer, 25, 5)], |
| ); |
| } |
| |
| void test_constructor_this_cascade_synthetic() { |
| // https://github.com/dart-lang/sdk/issues/37110 |
| parseCompilationUnit( |
| 'class B extends A { B(): this.. {} }', |
| errors: [ |
| expectedError(ParserErrorCode.missingAssignmentInInitializer, 25, 4), |
| expectedError(ParserErrorCode.expectedToken, 29, 2), |
| expectedError(ParserErrorCode.missingIdentifier, 32, 1), |
| ], |
| ); |
| } |
| |
| void test_constructor_this_field() { |
| // https://github.com/dart-lang/sdk/issues/36262 |
| // https://github.com/dart-lang/sdk/issues/31198 |
| parseCompilationUnit( |
| 'class B extends A { B(): this().foo; }', |
| errors: [expectedError(ParserErrorCode.invalidThisInInitializer, 25, 4)], |
| ); |
| } |
| |
| void test_constructor_this_method() { |
| // https://github.com/dart-lang/sdk/issues/36262 |
| // https://github.com/dart-lang/sdk/issues/31198 |
| parseCompilationUnit( |
| 'class B extends A { B(): this().foo(); }', |
| errors: [expectedError(ParserErrorCode.invalidThisInInitializer, 25, 4)], |
| ); |
| } |
| |
| void test_constructor_this_named_method() { |
| // https://github.com/dart-lang/sdk/issues/37600 |
| parseCompilationUnit( |
| 'class B extends A { B(): super.c().create() {} }', |
| errors: [expectedError(ParserErrorCode.invalidSuperInInitializer, 25, 5)], |
| ); |
| } |
| |
| void test_constructor_this_named_method_field() { |
| // https://github.com/dart-lang/sdk/issues/37600 |
| parseCompilationUnit( |
| 'class B extends A { B(): super.c().create().x {} }', |
| errors: [expectedError(ParserErrorCode.invalidSuperInInitializer, 25, 5)], |
| ); |
| } |
| |
| void test_constructorPartial() { |
| createParser('class C { C< }'); |
| parser.parseCompilationUnit2(); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.expectedToken, 11, 1), |
| expectedError(ParserErrorCode.expectedTypeName, 13, 1), |
| expectedError(ParserErrorCode.missingIdentifier, 13, 1), |
| ]); |
| } |
| |
| void test_constructorPartial2() { |
| createParser('class C { C<@Foo }'); |
| parser.parseCompilationUnit2(); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.annotationOnTypeArgument, 12, 4), |
| expectedError(ParserErrorCode.expectedToken, 13, 3), |
| expectedError(ParserErrorCode.expectedTypeName, 17, 1), |
| expectedError(ParserErrorCode.missingIdentifier, 17, 1), |
| ]); |
| } |
| |
| void test_constructorPartial3() { |
| createParser('class C { C<@Foo @Bar() }'); |
| parser.parseCompilationUnit2(); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.annotationOnTypeArgument, 12, 4), |
| expectedError(ParserErrorCode.annotationOnTypeArgument, 17, 6), |
| expectedError(ParserErrorCode.expectedToken, 22, 1), |
| expectedError(ParserErrorCode.expectedTypeName, 24, 1), |
| expectedError(ParserErrorCode.missingIdentifier, 24, 1), |
| ]); |
| } |
| |
| void test_constructorWithReturnType() { |
| createParser('C C() {}'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.constructorWithReturnType, 0, 1), |
| ]); |
| } |
| |
| void test_constructorWithReturnType_var() { |
| createParser('var C() {}'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([expectedError(ParserErrorCode.varReturnType, 0, 3)]); |
| } |
| |
| void test_constTypedef() { |
| parseCompilationUnit( |
| "const typedef F();", |
| errors: [ |
| // Fasta interprets the `const` as a malformed top level const |
| // and `typedef` as the start of an typedef declaration. |
| expectedError(ParserErrorCode.expectedToken, 0, 5), |
| expectedError(ParserErrorCode.missingIdentifier, 6, 7), |
| ], |
| ); |
| } |
| |
| void test_continueOutsideOfLoop_continueInDoStatement() { |
| var statement = parseStatement('do {continue;} while (x);') as DoStatement; |
| expectNotNullIfNoErrors(statement); |
| assertNoErrors(); |
| } |
| |
| void test_continueOutsideOfLoop_continueInForStatement() { |
| var statement = parseStatement('for (; x;) {continue;}'); |
| expectNotNullIfNoErrors(statement); |
| assertNoErrors(); |
| } |
| |
| void test_continueOutsideOfLoop_continueInIfStatement() { |
| var statement = parseStatement('if (x) {continue;}') as IfStatement; |
| expectNotNullIfNoErrors(statement); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.continueOutsideOfLoop, 8, 8), |
| ]); |
| } |
| |
| void test_continueOutsideOfLoop_continueInSwitchStatement() { |
| var statement = |
| parseStatement('switch (x) {case 1: continue a;}') as SwitchStatement; |
| expectNotNullIfNoErrors(statement); |
| assertNoErrors(); |
| } |
| |
| void test_continueOutsideOfLoop_continueInWhileStatement() { |
| var statement = parseStatement('while (x) {continue;}') as WhileStatement; |
| expectNotNullIfNoErrors(statement); |
| assertNoErrors(); |
| } |
| |
| void test_continueOutsideOfLoop_functionExpression_inALoop() { |
| parseStatement("for(; x;) {() {continue;};}"); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.continueOutsideOfLoop, 15, 8), |
| ]); |
| } |
| |
| void test_continueOutsideOfLoop_functionExpression_withALoop() { |
| parseStatement("() {for (; x;) {continue;}};"); |
| } |
| |
| void test_continueWithoutLabelInCase_error() { |
| var statement = |
| parseStatement('switch (x) {case 1: continue;}') as SwitchStatement; |
| expectNotNullIfNoErrors(statement); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.continueWithoutLabelInCase, 20, 8), |
| ]); |
| } |
| |
| void test_continueWithoutLabelInCase_noError() { |
| var statement = |
| parseStatement('switch (x) {case 1: continue a;}') as SwitchStatement; |
| expectNotNullIfNoErrors(statement); |
| assertNoErrors(); |
| } |
| |
| void test_continueWithoutLabelInCase_noError_switchInLoop() { |
| var statement = |
| parseStatement('while (a) { switch (b) {default: continue;}}') |
| as WhileStatement; |
| expectNotNullIfNoErrors(statement); |
| assertNoErrors(); |
| } |
| |
| void test_covariantAfterVar() { |
| createParser('var covariant f;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.modifierOutOfOrder, 4, 9), |
| ]); |
| } |
| |
| void test_covariantAndFinal() { |
| createParser('covariant final f = null;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrorsWithCodes([ParserErrorCode.finalAndCovariant]); |
| } |
| |
| void test_covariantAndStatic() { |
| createParser('covariant static A f;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.covariantAndStatic, 10, 6), |
| ]); |
| } |
| |
| void test_covariantAndType_local() { |
| // This is currently reporting EXPECTED_TOKEN for a missing semicolon, but |
| // this would be a better error message. |
| parseStatement("covariant int x;"); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.extraneousModifier, 0, 9), |
| ]); |
| } |
| |
| void test_covariantConstructor() { |
| createParser('class C { covariant C(); }'); |
| var member = parseFullCompilationUnitMember() as ClassDeclaration; |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.covariantMember, 10, 9), |
| ]); |
| } |
| |
| void test_covariantMember_getter_noReturnType() { |
| createParser('static covariant get x => 0;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.covariantAndStatic, 7, 9), |
| ]); |
| } |
| |
| void test_covariantMember_getter_returnType() { |
| createParser('static covariant int get x => 0;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.covariantAndStatic, 7, 9), |
| ]); |
| } |
| |
| void test_covariantMember_method() { |
| createParser('covariant int m() => 0;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.covariantMember, 0, 9), |
| ]); |
| } |
| |
| void test_covariantTopLevelDeclaration_class() { |
| createParser('covariant class C {}'); |
| var member = parseFullCompilationUnitMember() as ClassDeclaration; |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.extraneousModifier, 0, 9), |
| ]); |
| } |
| |
| void test_covariantTopLevelDeclaration_enum() { |
| createParser('covariant enum E { v }'); |
| var member = parseFullCompilationUnitMember() as EnumDeclaration; |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.extraneousModifier, 0, 9), |
| ]); |
| } |
| |
| void test_covariantTopLevelDeclaration_typedef() { |
| parseCompilationUnit( |
| "covariant typedef F();", |
| errors: [expectedError(ParserErrorCode.extraneousModifier, 0, 9)], |
| ); |
| } |
| |
| void test_defaultValueInFunctionType_named_colon() { |
| createParser('({int x : 0})'); |
| FormalParameter parameter = parser |
| .parseFormalParameterList(inFunctionType: true) |
| .parameters[0]; |
| expectNotNullIfNoErrors(parameter); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.defaultValueInFunctionType, 8, 1), |
| ]); |
| } |
| |
| void test_defaultValueInFunctionType_named_equal() { |
| createParser('({int x = 0})'); |
| FormalParameter parameter = parser |
| .parseFormalParameterList(inFunctionType: true) |
| .parameters[0]; |
| expectNotNullIfNoErrors(parameter); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.defaultValueInFunctionType, 8, 1), |
| ]); |
| } |
| |
| void test_defaultValueInFunctionType_positional() { |
| createParser('([int x = 0])'); |
| FormalParameter parameter = parser |
| .parseFormalParameterList(inFunctionType: true) |
| .parameters[0]; |
| expectNotNullIfNoErrors(parameter); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.defaultValueInFunctionType, 8, 1), |
| ]); |
| } |
| |
| void test_directiveAfterDeclaration_classBeforeDirective() { |
| // TODO(brianwilkerson): Remove codes when highlighting is fixed. |
| CompilationUnit unit = parseCompilationUnit( |
| "class Foo{} library l;", |
| codes: [ParserErrorCode.libraryDirectiveNotFirst], |
| errors: [expectedError(ParserErrorCode.libraryDirectiveNotFirst, 12, 10)], |
| ); |
| expect(unit, isNotNull); |
| } |
| |
| void test_directiveAfterDeclaration_classBetweenDirectives() { |
| // TODO(brianwilkerson): Remove codes when highlighting is fixed. |
| CompilationUnit unit = parseCompilationUnit( |
| "library l;\nclass Foo{}\npart 'a.dart';", |
| codes: [ParserErrorCode.directiveAfterDeclaration], |
| errors: [ |
| expectedError(ParserErrorCode.directiveAfterDeclaration, 23, 14), |
| ], |
| ); |
| expect(unit, isNotNull); |
| } |
| |
| void test_duplicatedModifier_const() { |
| createParser('const const m = null;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.duplicatedModifier, 6, 5), |
| ]); |
| } |
| |
| void test_duplicatedModifier_external() { |
| createParser('external external f();'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.duplicatedModifier, 9, 8), |
| ]); |
| } |
| |
| void test_duplicatedModifier_factory() { |
| createParser('factory factory C() {}'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.duplicatedModifier, 8, 7), |
| ]); |
| } |
| |
| void test_duplicatedModifier_final() { |
| createParser('final final m = null;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.duplicatedModifier, 6, 5), |
| ]); |
| } |
| |
| void test_duplicatedModifier_static() { |
| createParser('static static var m;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.duplicatedModifier, 7, 6), |
| ]); |
| } |
| |
| void test_duplicatedModifier_var() { |
| createParser('var var m;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.duplicatedModifier, 4, 3), |
| ]); |
| } |
| |
| void test_duplicateLabelInSwitchStatement() { |
| var statement = |
| parseStatement('switch (e) {l1: case 0: break; l1: case 1: break;}') |
| as SwitchStatement; |
| expectNotNullIfNoErrors(statement); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.duplicateLabelInSwitchStatement, 31, 2), |
| ]); |
| } |
| |
| void test_emptyEnumBody() { |
| createParser('enum E {}'); |
| var declaration = parseFullCompilationUnitMember() as EnumDeclaration; |
| expectNotNullIfNoErrors(declaration); |
| // TODO(brianwilkerson): Convert codes to errors when highlighting is fixed. |
| listener.assertErrorsWithCodes([]); |
| // listener |
| // .assertErrors([expectedError(ParserErrorCode.EMPTY_ENUM_BODY, 7, 2),]); |
| } |
| |
| void test_enumInClass() { |
| parseCompilationUnit( |
| r''' |
| class Foo { |
| enum Bar { |
| Bar1, Bar2, Bar3 |
| } |
| } |
| ''', |
| errors: [expectedError(ParserErrorCode.enumInClass, 14, 4)], |
| ); |
| } |
| |
| void test_equalityCannotBeEqualityOperand_eq_eq() { |
| parseExpression( |
| "1 == 2 == 3", |
| errors: [ |
| expectedError(ParserErrorCode.equalityCannotBeEqualityOperand, 7, 2), |
| ], |
| ); |
| } |
| |
| void test_equalityCannotBeEqualityOperand_eq_neq() { |
| parseExpression( |
| "1 == 2 != 3", |
| errors: [ |
| expectedError(ParserErrorCode.equalityCannotBeEqualityOperand, 7, 2), |
| ], |
| ); |
| } |
| |
| void test_equalityCannotBeEqualityOperand_neq_eq() { |
| parseExpression( |
| "1 != 2 == 3", |
| errors: [ |
| expectedError(ParserErrorCode.equalityCannotBeEqualityOperand, 7, 2), |
| ], |
| ); |
| } |
| |
| void test_expectedBody_class() { |
| parseCompilationUnit( |
| "class A class B {}", |
| errors: [expectedError(ParserErrorCode.expectedClassBody, 6, 1)], |
| ); |
| } |
| |
| void test_expectedCaseOrDefault() { |
| var statement = parseStatement('switch (e) {break;}') as SwitchStatement; |
| expectNotNullIfNoErrors(statement); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.expectedToken, 12, 5), |
| ]); |
| } |
| |
| void test_expectedClassMember_inClass_afterType() { |
| parseCompilationUnit( |
| 'class C{ heart 2 heart }', |
| errors: [ |
| expectedError(ParserErrorCode.missingConstFinalVarOrType, 9, 5), |
| expectedError(ParserErrorCode.expectedToken, 9, 5), |
| expectedError(ParserErrorCode.expectedClassMember, 15, 1), |
| expectedError(ParserErrorCode.missingConstFinalVarOrType, 17, 5), |
| expectedError(ParserErrorCode.expectedToken, 17, 5), |
| ], |
| ); |
| } |
| |
| void test_expectedClassMember_inClass_beforeType() { |
| parseCompilationUnit( |
| 'class C { 4 score }', |
| errors: [ |
| expectedError(ParserErrorCode.expectedClassMember, 10, 1), |
| expectedError(ParserErrorCode.missingConstFinalVarOrType, 12, 5), |
| expectedError(ParserErrorCode.expectedToken, 12, 5), |
| ], |
| ); |
| } |
| |
| void test_expectedExecutable_afterAnnotation_atEOF() { |
| // TODO(brianwilkerson): Remove codes when highlighting is fixed. |
| parseCompilationUnit( |
| '@A', |
| codes: [ParserErrorCode.expectedExecutable], |
| errors: [expectedError(ParserErrorCode.expectedExecutable, 1, 1)], |
| ); |
| } |
| |
| void test_expectedExecutable_inClass_afterVoid() { |
| parseCompilationUnit( |
| 'class C { void 2 void }', |
| errors: [ |
| expectedError(ParserErrorCode.missingIdentifier, 15, 1), |
| expectedError(ParserErrorCode.expectedToken, 15, 1), |
| expectedError(ParserErrorCode.expectedToken, 17, 4), |
| expectedError(ParserErrorCode.missingIdentifier, 22, 1), |
| ], |
| ); |
| } |
| |
| void test_expectedExecutable_topLevel_afterType() { |
| CompilationUnit unit = parseCompilationUnit( |
| 'heart 2 heart', |
| errors: [ |
| expectedError(ParserErrorCode.missingConstFinalVarOrType, 0, 5), |
| expectedError(ParserErrorCode.expectedToken, 0, 5), |
| expectedError(ParserErrorCode.expectedExecutable, 6, 1), |
| expectedError(ParserErrorCode.missingConstFinalVarOrType, 8, 5), |
| expectedError(ParserErrorCode.expectedToken, 8, 5), |
| ], |
| ); |
| expect(unit, isNotNull); |
| } |
| |
| void test_expectedExecutable_topLevel_afterVoid() { |
| CompilationUnit unit = parseCompilationUnit( |
| 'void 2 void', |
| errors: [ |
| expectedError(ParserErrorCode.expectedToken, 0, 4), |
| expectedError(ParserErrorCode.missingIdentifier, 5, 1), |
| expectedError(ParserErrorCode.expectedExecutable, 5, 1), |
| expectedError(ParserErrorCode.expectedToken, 7, 4), |
| expectedError(ParserErrorCode.missingIdentifier, 11, 0), |
| ], |
| ); |
| expect(unit, isNotNull); |
| } |
| |
| void test_expectedExecutable_topLevel_beforeType() { |
| parseCompilationUnit( |
| '4 score', |
| errors: [ |
| expectedError(ParserErrorCode.expectedExecutable, 0, 1), |
| expectedError(ParserErrorCode.missingConstFinalVarOrType, 2, 5), |
| expectedError(ParserErrorCode.expectedToken, 2, 5), |
| ], |
| ); |
| } |
| |
| void test_expectedExecutable_topLevel_eof() { |
| parseCompilationUnit( |
| 'x', |
| errors: [ |
| expectedError(ParserErrorCode.missingConstFinalVarOrType, 0, 1), |
| expectedError(ParserErrorCode.expectedToken, 0, 1), |
| ], |
| ); |
| } |
| |
| void test_expectedInterpolationIdentifier() { |
| var literal = |
| parseExpression( |
| "'\$x\$'", |
| errors: [expectedError(ScannerErrorCode.missingIdentifier, 4, 1)], |
| ) |
| as StringLiteral; |
| expectNotNullIfNoErrors(literal); |
| } |
| |
| void test_expectedInterpolationIdentifier_emptyString() { |
| // The scanner inserts an empty string token between the two $'s; we need to |
| // make sure that the MISSING_IDENTIFIER error that is generated has a |
| // nonzero width so that it will show up in the editor UI. |
| var literal = |
| parseExpression( |
| "'\$\$foo'", |
| errors: [expectedError(ScannerErrorCode.missingIdentifier, 2, 1)], |
| ) |
| as StringLiteral; |
| expectNotNullIfNoErrors(literal); |
| } |
| |
| void test_expectedToken_commaMissingInArgumentList() { |
| createParser('(x, y z)'); |
| ArgumentList list = parser.parseArgumentList(); |
| expectNotNullIfNoErrors(list); |
| listener.assertErrors([expectedError(ParserErrorCode.expectedToken, 6, 1)]); |
| } |
| |
| void test_expectedToken_parseStatement_afterVoid() { |
| parseStatement("void}", expectedEndOffset: 4); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.expectedToken, 0, 4), |
| expectedError(ParserErrorCode.missingIdentifier, 4, 1), |
| ]); |
| } |
| |
| void test_expectedToken_semicolonMissingAfterExport() { |
| // TODO(brianwilkerson): Remove codes when highlighting is fixed. |
| CompilationUnit unit = parseCompilationUnit( |
| "export '' class A {}", |
| codes: [ParserErrorCode.expectedToken], |
| errors: [expectedError(ParserErrorCode.expectedToken, 7, 2)], |
| ); |
| ExportDirective directive = unit.directives[0] as ExportDirective; |
| expect(directive.uri, isNotNull); |
| expect(directive.uri.stringValue, ''); |
| expect(directive.uri.beginToken.isSynthetic, false); |
| expect(directive.uri.isSynthetic, false); |
| Token semicolon = directive.semicolon; |
| expect(semicolon, isNotNull); |
| expect(semicolon.isSynthetic, isTrue); |
| ClassDeclaration clazz = unit.declarations[0] as ClassDeclaration; |
| expect(clazz.name.lexeme, 'A'); |
| } |
| |
| void test_expectedToken_semicolonMissingAfterExpression() { |
| parseStatement("x"); |
| // TODO(brianwilkerson): Convert codes to errors when highlighting is fixed. |
| listener.assertErrorsWithCodes([ParserErrorCode.expectedToken]); |
| // listener |
| // .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 1)]); |
| } |
| |
| void test_expectedToken_semicolonMissingAfterImport() { |
| // TODO(brianwilkerson): Remove codes when highlighting is fixed. |
| CompilationUnit unit = parseCompilationUnit( |
| "import '' class A {}", |
| codes: [ParserErrorCode.expectedToken], |
| errors: [expectedError(ParserErrorCode.expectedToken, 7, 2)], |
| ); |
| ImportDirective directive = unit.directives[0] as ImportDirective; |
| Token semicolon = directive.semicolon; |
| expect(semicolon, isNotNull); |
| expect(semicolon.isSynthetic, isTrue); |
| } |
| |
| void test_expectedToken_uriAndSemicolonMissingAfterExport() { |
| CompilationUnit unit = parseCompilationUnit( |
| "export class A {}", |
| errors: [ |
| expectedError(ParserErrorCode.expectedToken, 0, 6), |
| expectedError(ParserErrorCode.expectedStringLiteral, 7, 5), |
| ], |
| ); |
| ExportDirective directive = unit.directives[0] as ExportDirective; |
| expect(directive.uri, isNotNull); |
| expect(directive.uri.stringValue, ''); |
| expect(directive.uri.beginToken.isSynthetic, true); |
| expect(directive.uri.isSynthetic, true); |
| Token semicolon = directive.semicolon; |
| expect(semicolon, isNotNull); |
| expect(semicolon.isSynthetic, isTrue); |
| ClassDeclaration clazz = unit.declarations[0] as ClassDeclaration; |
| expect(clazz.name.lexeme, 'A'); |
| } |
| |
| void test_expectedToken_whileMissingInDoStatement() { |
| parseStatement("do {} (x);"); |
| listener.assertErrors([expectedError(ParserErrorCode.expectedToken, 6, 1)]); |
| } |
| |
| void test_expectedTypeName_as() { |
| parseExpression( |
| "x as", |
| errors: [expectedError(ParserErrorCode.expectedTypeName, 4, 0)], |
| ); |
| } |
| |
| void test_expectedTypeName_as_void() { |
| parseExpression( |
| "x as void)", |
| expectedEndOffset: 9, |
| errors: [expectedError(ParserErrorCode.expectedTypeName, 5, 4)], |
| ); |
| } |
| |
| void test_expectedTypeName_is() { |
| parseExpression( |
| "x is", |
| errors: [expectedError(ParserErrorCode.expectedTypeName, 4, 0)], |
| ); |
| } |
| |
| void test_expectedTypeName_is_void() { |
| parseExpression( |
| "x is void)", |
| expectedEndOffset: 9, |
| errors: [expectedError(ParserErrorCode.expectedTypeName, 5, 4)], |
| ); |
| } |
| |
| void test_exportAsType() { |
| parseCompilationUnit( |
| 'export<dynamic> foo;', |
| errors: [ |
| expectedError(CompileTimeErrorCode.builtInIdentifierAsType, 0, 6), |
| ], |
| ); |
| } |
| |
| void test_exportAsType_inClass() { |
| parseCompilationUnit( |
| 'class C { export<dynamic> foo; }', |
| errors: [ |
| expectedError(CompileTimeErrorCode.builtInIdentifierAsType, 10, 6), |
| ], |
| ); |
| } |
| |
| void test_externalAfterConst() { |
| createParser('const external C();'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.modifierOutOfOrder, 6, 8), |
| ]); |
| } |
| |
| void test_externalAfterFactory() { |
| createParser('factory external C();'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.modifierOutOfOrder, 8, 8), |
| ]); |
| } |
| |
| void test_externalAfterStatic() { |
| createParser('static external int m();'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.modifierOutOfOrder, 7, 8), |
| ]); |
| } |
| |
| void test_externalClass() { |
| parseCompilationUnit( |
| "external class C {}", |
| errors: [expectedError(ParserErrorCode.externalClass, 0, 8)], |
| ); |
| } |
| |
| void test_externalConstructorWithBody_factory() { |
| createParser('external factory C() {}'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.externalFactoryWithBody, 21, 1), |
| ]); |
| } |
| |
| void test_externalConstructorWithBody_named() { |
| createParser('external C.c() {}'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| // TODO(brianwilkerson): Convert codes to errors when highlighting is fixed. |
| listener.assertErrorsWithCodes([ParserErrorCode.externalMethodWithBody]); |
| // listener.assertErrors( |
| // [expectedError(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, 15, 2)]); |
| } |
| |
| void test_externalEnum() { |
| parseCompilationUnit( |
| "external enum E {ONE}", |
| errors: [expectedError(ParserErrorCode.externalEnum, 0, 8)], |
| ); |
| } |
| |
| void test_externalField_const() { |
| createParser('external const A f;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(CompileTimeErrorCode.constNotInitialized, 17, 1), |
| ]); |
| } |
| |
| void test_externalField_final() { |
| createParser('external final A f;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| assertNoErrors(); |
| } |
| |
| void test_externalField_static() { |
| createParser('external static A f;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| assertNoErrors(); |
| } |
| |
| void test_externalField_typed() { |
| createParser('external A f;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| assertNoErrors(); |
| } |
| |
| void test_externalField_untyped() { |
| createParser('external var f;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| assertNoErrors(); |
| } |
| |
| void test_externalGetterWithBody() { |
| createParser('external int get x {}'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| // TODO(brianwilkerson): Convert codes to errors when highlighting is fixed. |
| listener.assertErrorsWithCodes([ParserErrorCode.externalMethodWithBody]); |
| // listener.assertErrors( |
| // [expectedError(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, 19, 2)]); |
| } |
| |
| void test_externalMethodWithBody() { |
| createParser('external m() {}'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| // TODO(brianwilkerson): Convert codes to errors when highlighting is fixed. |
| listener.assertErrorsWithCodes([ParserErrorCode.externalMethodWithBody]); |
| // listener.assertErrors( |
| // [expectedError(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, 13, 2)]); |
| } |
| |
| void test_externalOperatorWithBody() { |
| createParser('external operator +(int value) {}'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| // TODO(brianwilkerson): Convert codes to errors when highlighting is fixed. |
| listener.assertErrorsWithCodes([ParserErrorCode.externalMethodWithBody]); |
| // listener.assertErrors( |
| // [expectedError(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, 31, 2)]); |
| } |
| |
| void test_externalSetterWithBody() { |
| createParser('external set x(int value) {}'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| // TODO(brianwilkerson): Convert codes to errors when highlighting is fixed. |
| listener.assertErrorsWithCodes([ParserErrorCode.externalMethodWithBody]); |
| // listener.assertErrors( |
| // [expectedError(ParserErrorCode.EXTERNAL_METHOD_WITH_BODY, 26, 2)]); |
| } |
| |
| void test_externalTypedef() { |
| parseCompilationUnit( |
| "external typedef F();", |
| errors: [expectedError(ParserErrorCode.externalTypedef, 0, 8)], |
| ); |
| } |
| |
| void test_extraCommaInParameterList() { |
| createParser('(int a, , int b)'); |
| FormalParameterList list = parser.parseFormalParameterList(); |
| expectNotNullIfNoErrors(list); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingIdentifier, 8, 1), |
| ]); |
| } |
| |
| void test_extraCommaTrailingNamedParameterGroup() { |
| createParser('({int b},)'); |
| FormalParameterList list = parser.parseFormalParameterList(); |
| expectNotNullIfNoErrors(list); |
| listener.assertErrors([expectedError(ParserErrorCode.expectedToken, 8, 1)]); |
| } |
| |
| void test_extraCommaTrailingPositionalParameterGroup() { |
| createParser('([int b],)'); |
| FormalParameterList list = parser.parseFormalParameterList(); |
| expectNotNullIfNoErrors(list); |
| listener.assertErrors([expectedError(ParserErrorCode.expectedToken, 8, 1)]); |
| } |
| |
| void test_extraTrailingCommaInParameterList() { |
| createParser('(a,,)'); |
| FormalParameterList list = parser.parseFormalParameterList(); |
| expectNotNullIfNoErrors(list); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingIdentifier, 3, 1), |
| ]); |
| } |
| |
| void test_factory_issue_36400() { |
| parseCompilationUnit( |
| 'class T { T factory T() { return null; } }', |
| errors: [expectedError(ParserErrorCode.typeBeforeFactory, 10, 1)], |
| ); |
| } |
| |
| void test_factoryTopLevelDeclaration_class() { |
| parseCompilationUnit( |
| "factory class C {}", |
| errors: [expectedError(ParserErrorCode.factoryTopLevelDeclaration, 0, 7)], |
| ); |
| } |
| |
| void test_factoryTopLevelDeclaration_enum() { |
| parseCompilationUnit( |
| "factory enum E { v }", |
| errors: [expectedError(ParserErrorCode.factoryTopLevelDeclaration, 0, 7)], |
| ); |
| } |
| |
| void test_factoryTopLevelDeclaration_typedef() { |
| parseCompilationUnit( |
| "factory typedef F();", |
| errors: [expectedError(ParserErrorCode.factoryTopLevelDeclaration, 0, 7)], |
| ); |
| } |
| |
| void test_factoryWithInitializers() { |
| createParser('factory C() : x = 3 {}', expectedEndOffset: 12); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingFunctionBody, 12, 1), |
| ]); |
| } |
| |
| void test_factoryWithoutBody() { |
| createParser('factory C();'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingFunctionBody, 11, 1), |
| ]); |
| } |
| |
| void test_fieldInitializerOutsideConstructor() { |
| createParser('void m(this.x);'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.fieldInitializerOutsideConstructor, 7, 4), |
| ]); |
| } |
| |
| void test_finalAndCovariant() { |
| createParser('final covariant f = null;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.modifierOutOfOrder, 6, 9), |
| expectedError(ParserErrorCode.finalAndCovariant, 6, 9), |
| ]); |
| } |
| |
| void test_finalAndVar() { |
| createParser('final var x = null;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([expectedError(ParserErrorCode.finalAndVar, 6, 3)]); |
| } |
| |
| void test_finalClassMember_modifierOnly() { |
| createParser('final'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.expectedToken, 0, 5), |
| expectedError(ParserErrorCode.missingIdentifier, 5, 0), |
| ]); |
| } |
| |
| void test_finalConstructor() { |
| createParser('final C() {}'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.extraneousModifier, 0, 5), |
| ]); |
| } |
| |
| void test_finalEnum() { |
| parseCompilationUnit( |
| "final enum E {ONE}", |
| errors: [error(ParserErrorCode.finalEnum, 0, 5)], |
| ); |
| } |
| |
| void test_finalMethod() { |
| createParser('final int m() {}'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.extraneousModifier, 0, 5), |
| ]); |
| } |
| |
| void test_finalTypedef() { |
| parseCompilationUnit( |
| "final typedef F();", |
| errors: [ |
| // Fasta interprets the `final` as a malformed top level final |
| // and `typedef` as the start of an typedef declaration. |
| expectedError(ParserErrorCode.expectedToken, 0, 5), |
| expectedError(ParserErrorCode.missingIdentifier, 6, 7), |
| ], |
| ); |
| } |
| |
| void test_functionTypedField_invalidType_abstract() { |
| parseCompilationUnit( |
| "Function(abstract) x = null;", |
| errors: [ |
| expectedError(CompileTimeErrorCode.builtInIdentifierAsType, 9, 8), |
| ], |
| ); |
| } |
| |
| void test_functionTypedField_invalidType_class() { |
| parseCompilationUnit( |
| "Function(class) x = null;", |
| errors: [ |
| expectedError(ParserErrorCode.expectedTypeName, 9, 5), |
| expectedError(ParserErrorCode.expectedIdentifierButGotKeyword, 9, 5), |
| ], |
| ); |
| } |
| |
| void test_functionTypedParameter_const() { |
| parseCompilationUnit( |
| "void f(const x()) {}", |
| errors: [ |
| expectedError(ParserErrorCode.extraneousModifier, 7, 5), |
| expectedError(ParserErrorCode.functionTypedParameterVar, 7, 5), |
| ], |
| ); |
| } |
| |
| void test_functionTypedParameter_final() { |
| parseCompilationUnit( |
| "void f(final x()) {}", |
| errors: [expectedError(ParserErrorCode.functionTypedParameterVar, 7, 5)], |
| ); |
| } |
| |
| void test_functionTypedParameter_incomplete1() { |
| parseCompilationUnit( |
| "void f(int Function(", |
| errors: [ |
| expectedError(ScannerErrorCode.expectedToken, 20, 1), |
| expectedError(ScannerErrorCode.expectedToken, 20, 1), |
| expectedError(ParserErrorCode.missingFunctionBody, 20, 0), |
| ], |
| ); |
| } |
| |
| void test_functionTypedParameter_var() { |
| parseCompilationUnit( |
| "void f(var x()) {}", |
| errors: [expectedError(ParserErrorCode.functionTypedParameterVar, 7, 3)], |
| ); |
| } |
| |
| void test_genericFunctionType_asIdentifier() { |
| createParser('final int Function = 0;'); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expectNotNullIfNoErrors(unit); |
| listener.assertErrors([]); |
| } |
| |
| void test_genericFunctionType_asIdentifier2() { |
| createParser('int Function() {}'); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expectNotNullIfNoErrors(unit); |
| listener.assertErrors([]); |
| } |
| |
| void test_genericFunctionType_asIdentifier3() { |
| createParser('int Function() => 0;'); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expectNotNullIfNoErrors(unit); |
| listener.assertErrors([]); |
| } |
| |
| void test_genericFunctionType_extraLessThan() { |
| createParser(''' |
| class Wrong<T> { |
| T Function(<List<int> foo) bar; |
| }'''); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expectNotNullIfNoErrors(unit); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.expectedTypeName, 30, 1), |
| expectedError(ParserErrorCode.expectedToken, 30, 1), |
| ]); |
| } |
| |
| void test_getterInFunction_block_noReturnType() { |
| Statement result = parseStatement( |
| "get x { return _x; }", |
| expectedEndOffset: 4, |
| ); |
| // Fasta considers `get` to be an identifier in this situation. |
| // TODO(danrubel): Investigate better recovery. |
| var statement = result as ExpressionStatement; |
| listener.assertErrors([expectedError(ParserErrorCode.expectedToken, 0, 3)]); |
| expect(statement.expression.toSource(), 'get'); |
| } |
| |
| void test_getterInFunction_block_returnType() { |
| // Fasta considers `get` to be an identifier in this situation. |
| parseStatement("int get x { return _x; }", expectedEndOffset: 8); |
| listener.assertErrors([expectedError(ParserErrorCode.expectedToken, 4, 3)]); |
| } |
| |
| void test_getterInFunction_expression_noReturnType() { |
| // Fasta considers `get` to be an identifier in this situation. |
| parseStatement("get x => _x;", expectedEndOffset: 4); |
| listener.assertErrors([expectedError(ParserErrorCode.expectedToken, 0, 3)]); |
| } |
| |
| void test_getterInFunction_expression_returnType() { |
| // Fasta considers `get` to be an identifier in this situation. |
| parseStatement("int get x => _x;", expectedEndOffset: 8); |
| listener.assertErrors([expectedError(ParserErrorCode.expectedToken, 4, 3)]); |
| } |
| |
| void test_getterNativeWithBody() { |
| createParser('String get m native "str" => 0;'); |
| parser.parseClassMember('C') as MethodDeclaration; |
| if (!allowNativeClause) { |
| assertErrorsWithCodes([ |
| ParserErrorCode.nativeClauseShouldBeAnnotation, |
| ParserErrorCode.externalMethodWithBody, |
| ]); |
| } else { |
| assertErrorsWithCodes([ParserErrorCode.externalMethodWithBody]); |
| } |
| } |
| |
| void test_getterWithParameters() { |
| createParser('int get x() {}'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| // TODO(brianwilkerson): Convert codes to errors when highlighting is fixed. |
| listener.assertErrorsWithCodes([ParserErrorCode.getterWithParameters]); |
| // listener.assertErrors( |
| // [expectedError(ParserErrorCode.GETTER_WITH_PARAMETERS, 9, 2)]); |
| } |
| |
| void test_illegalAssignmentToNonAssignable_assign_int() { |
| parseStatement("0 = 1;"); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingAssignableSelector, 0, 1), |
| expectedError(ParserErrorCode.illegalAssignmentToNonAssignable, 0, 1), |
| ]); |
| } |
| |
| void test_illegalAssignmentToNonAssignable_assign_this() { |
| parseStatement("this = 1;"); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingAssignableSelector, 0, 4), |
| expectedError(ParserErrorCode.illegalAssignmentToNonAssignable, 0, 4), |
| ]); |
| } |
| |
| void test_illegalAssignmentToNonAssignable_postfix_minusMinus_literal() { |
| parseExpression( |
| "0--", |
| errors: [ |
| expectedError(ParserErrorCode.illegalAssignmentToNonAssignable, 1, 2), |
| ], |
| ); |
| } |
| |
| void test_illegalAssignmentToNonAssignable_postfix_plusPlus_literal() { |
| parseExpression( |
| "0++", |
| errors: [ |
| expectedError(ParserErrorCode.illegalAssignmentToNonAssignable, 1, 2), |
| ], |
| ); |
| } |
| |
| void test_illegalAssignmentToNonAssignable_postfix_plusPlus_parenthesized() { |
| parseExpression( |
| "(x)++", |
| errors: [ |
| expectedError(ParserErrorCode.illegalAssignmentToNonAssignable, 3, 2), |
| ], |
| ); |
| } |
| |
| void test_illegalAssignmentToNonAssignable_primarySelectorPostfix() { |
| parseExpression( |
| "x(y)(z)++", |
| errors: [ |
| expectedError(ParserErrorCode.illegalAssignmentToNonAssignable, 7, 2), |
| ], |
| ); |
| } |
| |
| void test_illegalAssignmentToNonAssignable_superAssigned() { |
| parseStatement("super = x;"); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingAssignableSelector, 0, 5), |
| expectedError(ParserErrorCode.illegalAssignmentToNonAssignable, 0, 5), |
| ]); |
| } |
| |
| void test_implementsBeforeExtends() { |
| parseCompilationUnit( |
| "class A implements B extends C {}", |
| errors: [expectedError(ParserErrorCode.implementsBeforeExtends, 21, 7)], |
| ); |
| } |
| |
| void test_implementsBeforeWith() { |
| parseCompilationUnit( |
| "class A extends B implements C with D {}", |
| errors: [expectedError(ParserErrorCode.implementsBeforeWith, 31, 4)], |
| ); |
| } |
| |
| void test_initializedVariableInForEach() { |
| var statement = parseStatement('for (int a = 0 in foo) {}'); |
| expectNotNullIfNoErrors(statement); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.initializedVariableInForEach, 11, 1), |
| ]); |
| } |
| |
| void test_initializedVariableInForEach_annotation() { |
| var statement = parseStatement('for (@Foo var a = 0 in foo) {}'); |
| expectNotNullIfNoErrors(statement); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.initializedVariableInForEach, 16, 1), |
| ]); |
| } |
| |
| void test_initializedVariableInForEach_localFunction() { |
| var statement = parseStatement('for (f()) {}'); |
| expectNotNullIfNoErrors(statement); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.expectedToken, 7, 1), |
| expectedError(ParserErrorCode.expectedToken, 7, 1), |
| expectedError(ParserErrorCode.missingIdentifier, 8, 1), |
| ]); |
| } |
| |
| void test_initializedVariableInForEach_localFunction2() { |
| var statement = parseStatement('for (T f()) {}'); |
| expectNotNullIfNoErrors(statement); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.expectedToken, 7, 1), |
| expectedError(ParserErrorCode.expectedToken, 9, 1), |
| ]); |
| } |
| |
| void test_initializedVariableInForEach_var() { |
| var statement = parseStatement('for (var a = 0 in foo) {}'); |
| expectNotNullIfNoErrors(statement); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.initializedVariableInForEach, 11, 1), |
| ]); |
| } |
| |
| void test_invalidAwaitInFor() { |
| var statement = parseStatement('await for (; ;) {}'); |
| expectNotNullIfNoErrors(statement); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.invalidAwaitInFor, 0, 5), |
| ]); |
| } |
| |
| void test_invalidCodePoint() { |
| var literal = |
| parseExpression( |
| "'begin \\u{110000}'", |
| errors: [expectedError(ParserErrorCode.invalidCodePoint, 7, 9)], |
| ) |
| as StringLiteral; |
| expectNotNullIfNoErrors(literal); |
| } |
| |
| @failingTest |
| void test_invalidCommentReference__new_nonIdentifier() { |
| // This test fails because the method parseCommentReference returns null. |
| createParser(''); |
| var reference = parseCommentReference('new 42', 0) as CommentReference; |
| expectNotNullIfNoErrors(reference); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.invalidCommentReference, 0, 6), |
| ]); |
| } |
| |
| @failingTest |
| void test_invalidCommentReference__new_tooMuch() { |
| createParser(''); |
| var reference = parseCommentReference('new a.b.c.d', 0) as CommentReference; |
| expectNotNullIfNoErrors(reference); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.invalidCommentReference, 0, 11), |
| ]); |
| } |
| |
| @failingTest |
| void test_invalidCommentReference__nonNew_nonIdentifier() { |
| // This test fails because the method parseCommentReference returns null. |
| createParser(''); |
| var reference = parseCommentReference('42', 0) as CommentReference; |
| expectNotNullIfNoErrors(reference); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.invalidCommentReference, 0, 2), |
| ]); |
| } |
| |
| @failingTest |
| void test_invalidCommentReference__nonNew_tooMuch() { |
| createParser(''); |
| var reference = parseCommentReference('a.b.c.d', 0) as CommentReference; |
| expectNotNullIfNoErrors(reference); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.invalidCommentReference, 0, 7), |
| ]); |
| } |
| |
| void test_invalidConstructorName_star() { |
| createParser("C.*();"); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingIdentifier, 2, 1), |
| ]); |
| } |
| |
| void test_invalidConstructorName_with() { |
| createParser("C.with();"); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.expectedIdentifierButGotKeyword, 2, 4), |
| ]); |
| } |
| |
| void test_invalidConstructorSuperAssignment() { |
| createParser("C() : super = 42;"); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| error(ParserErrorCode.missingAssignableSelector, 6, 5), |
| error(ParserErrorCode.invalidInitializer, 6, 10), |
| ]); |
| } |
| |
| void test_invalidConstructorSuperFieldAssignment() { |
| createParser("C() : super.a = 42;"); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError( |
| ParserErrorCode.fieldInitializedOutsideDeclaringClass, |
| 12, |
| 1, |
| ), |
| ]); |
| } |
| |
| void test_invalidHexEscape_invalidDigit() { |
| var literal = |
| parseExpression( |
| "'not \\x0 a'", |
| errors: [expectedError(ParserErrorCode.invalidHexEscape, 5, 3)], |
| ) |
| as StringLiteral; |
| expectNotNullIfNoErrors(literal); |
| } |
| |
| void test_invalidHexEscape_tooFewDigits() { |
| var literal = |
| parseExpression( |
| "'\\x0'", |
| errors: [expectedError(ParserErrorCode.invalidHexEscape, 1, 3)], |
| ) |
| as StringLiteral; |
| expectNotNullIfNoErrors(literal); |
| } |
| |
| void test_invalidInlineFunctionType() { |
| parseCompilationUnit( |
| 'typedef F = int Function(int a());', |
| errors: [ |
| expectedError(CompileTimeErrorCode.invalidInlineFunctionType, 30, 1), |
| ], |
| ); |
| } |
| |
| void test_invalidInterpolation_missingClosingBrace_issue35900() { |
| parseCompilationUnit( |
| r"main () { print('${x' '); }", |
| errors: [ |
| expectedError(ScannerErrorCode.expectedToken, 23, 1), |
| expectedError(ScannerErrorCode.unterminatedStringLiteral, 26, 1), |
| expectedError(ParserErrorCode.expectedToken, 20, 3), |
| expectedError(ParserErrorCode.expectedStringLiteral, 23, 1), |
| expectedError(ParserErrorCode.expectedExecutable, 27, 0), |
| ], |
| ); |
| } |
| |
| void test_invalidInterpolationIdentifier_startWithDigit() { |
| var literal = |
| parseExpression( |
| "'\$1'", |
| errors: [expectedError(ScannerErrorCode.missingIdentifier, 2, 1)], |
| ) |
| as StringLiteral; |
| expectNotNullIfNoErrors(literal); |
| } |
| |
| void test_invalidLiteralInConfiguration() { |
| createParser("if (a == 'x \$y z') 'a.dart'"); |
| Configuration configuration = parser.parseConfiguration(); |
| expectNotNullIfNoErrors(configuration); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.invalidLiteralInConfiguration, 12, 2), |
| ]); |
| } |
| |
| void test_invalidOperator() { |
| CompilationUnit unit = parseCompilationUnit( |
| 'class C { void operator ===(x) { } }', |
| errors: [expectedError(ScannerErrorCode.unsupportedOperator, 24, 1)], |
| ); |
| expect(unit, isNotNull); |
| } |
| |
| void test_invalidOperator_unary() { |
| createParser('class C { int operator unary- => 0; }'); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expectNotNullIfNoErrors(unit); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.unexpectedToken, 23, 5), |
| expectedError(ParserErrorCode.missingMethodParameters, 28, 1), |
| ]); |
| } |
| |
| void test_invalidOperatorAfterSuper_assignableExpression() { |
| Expression expression = parseAssignableExpression('super?.v', false); |
| expectNotNullIfNoErrors(expression); |
| listener.assertErrors([ |
| expectedError( |
| ParserErrorCode.invalidOperatorQuestionmarkPeriodForSuper, |
| 5, |
| 2, |
| ), |
| ]); |
| } |
| |
| void test_invalidOperatorAfterSuper_constructorInitializer2() { |
| parseCompilationUnit( |
| 'class C { C() : super?.namedConstructor(); }', |
| errors: [ |
| expectedError( |
| ParserErrorCode.invalidOperatorQuestionmarkPeriodForSuper, |
| 21, |
| 2, |
| ), |
| ], |
| ); |
| } |
| |
| void test_invalidOperatorAfterSuper_primaryExpression() { |
| Expression expression = parseExpression( |
| 'super?.v', |
| errors: [ |
| expectedError( |
| ParserErrorCode.invalidOperatorQuestionmarkPeriodForSuper, |
| 5, |
| 2, |
| ), |
| ], |
| ); |
| expectNotNullIfNoErrors(expression); |
| } |
| |
| void test_invalidOperatorForSuper() { |
| createParser('++super'); |
| Expression expression = parser.parseUnaryExpression(); |
| expectNotNullIfNoErrors(expression); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingAssignableSelector, 2, 5), |
| ]); |
| } |
| |
| void test_invalidPropertyAccess_this() { |
| parseExpression( |
| 'x.this', |
| errors: [expectedError(ParserErrorCode.missingIdentifier, 2, 4)], |
| ); |
| } |
| |
| void test_invalidStarAfterAsync() { |
| createParser('foo() async* => 0;'); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expectNotNullIfNoErrors(unit); |
| listener.assertErrors([ |
| expectedError(CompileTimeErrorCode.returnInGenerator, 13, 2), |
| ]); |
| } |
| |
| void test_invalidSync() { |
| createParser('foo() sync* => 0;'); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expectNotNullIfNoErrors(unit); |
| listener.assertErrors([ |
| expectedError(CompileTimeErrorCode.returnInGenerator, 12, 2), |
| ]); |
| } |
| |
| void test_invalidTopLevelSetter() { |
| parseCompilationUnit( |
| "var set foo; main(){}", |
| errors: [ |
| expectedError(ParserErrorCode.varReturnType, 0, 3), |
| expectedError(ParserErrorCode.missingFunctionParameters, 8, 3), |
| expectedError(ParserErrorCode.missingFunctionBody, 11, 1), |
| ], |
| ); |
| } |
| |
| void test_invalidTopLevelVar() { |
| parseCompilationUnit( |
| "var Function(var arg);", |
| errors: [ |
| expectedError(ParserErrorCode.varReturnType, 0, 3), |
| expectedError(ParserErrorCode.missingFunctionBody, 21, 1), |
| ], |
| ); |
| } |
| |
| void test_invalidTypedef() { |
| parseCompilationUnit( |
| "typedef var Function(var arg);", |
| errors: [ |
| expectedError(ParserErrorCode.expectedToken, 0, 7), |
| expectedError(ParserErrorCode.missingIdentifier, 8, 3), |
| expectedError(ParserErrorCode.missingTypedefParameters, 8, 3), |
| expectedError(ParserErrorCode.varReturnType, 8, 3), |
| expectedError(ParserErrorCode.missingFunctionBody, 29, 1), |
| ], |
| ); |
| } |
| |
| void test_invalidTypedef2() { |
| // https://github.com/dart-lang/sdk/issues/31171 |
| parseCompilationUnit( |
| "typedef T = typedef F = Map<String, dynamic> Function();", |
| errors: [ |
| expectedError(ParserErrorCode.expectedToken, 10, 1), |
| expectedError(ParserErrorCode.expectedTypeName, 12, 7), |
| ], |
| ); |
| } |
| |
| void test_invalidUnicodeEscape_incomplete_noDigits() { |
| Expression expression = parseStringLiteral("'\\u{'"); |
| expectNotNullIfNoErrors(expression); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.invalidUnicodeEscapeUBracket, 1, 3), |
| ]); |
| } |
| |
| void test_invalidUnicodeEscape_incomplete_noDigits_noBracket() { |
| Expression expression = parseStringLiteral("'\\u'"); |
| expectNotNullIfNoErrors(expression); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.invalidUnicodeEscapeUStarted, 1, 2), |
| ]); |
| } |
| |
| void test_invalidUnicodeEscape_incomplete_someDigits() { |
| Expression expression = parseStringLiteral("'\\u{0A'"); |
| expectNotNullIfNoErrors(expression); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.invalidUnicodeEscapeUBracket, 1, 5), |
| ]); |
| } |
| |
| void test_invalidUnicodeEscape_invalidDigit() { |
| Expression expression = parseStringLiteral("'\\u0 and some more'"); |
| expectNotNullIfNoErrors(expression); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.invalidUnicodeEscapeUNoBracket, 1, 3), |
| ]); |
| } |
| |
| void test_invalidUnicodeEscape_too_high_number_variable() { |
| Expression expression = parseStringLiteral("'\\u{110000}'"); |
| expectNotNullIfNoErrors(expression); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.invalidCodePoint, 1, 9), |
| ]); |
| } |
| |
| void test_invalidUnicodeEscape_tooFewDigits_fixed() { |
| Expression expression = parseStringLiteral("'\\u04'"); |
| expectNotNullIfNoErrors(expression); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.invalidUnicodeEscapeUNoBracket, 1, 4), |
| ]); |
| } |
| |
| void test_invalidUnicodeEscape_tooFewDigits_variable() { |
| Expression expression = parseStringLiteral("'\\u{}'"); |
| expectNotNullIfNoErrors(expression); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.invalidUnicodeEscapeUBracket, 1, 4), |
| ]); |
| } |
| |
| void test_invalidUnicodeEscape_tooManyDigits_variable() { |
| Expression expression = parseStringLiteral("'\\u{0000000001}'"); |
| expectNotNullIfNoErrors(expression); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.invalidUnicodeEscapeUBracket, 1, 9), |
| ]); |
| } |
| |
| void test_libraryDirectiveNotFirst() { |
| parseCompilationUnit( |
| "import 'x.dart'; library l;", |
| errors: [expectedError(ParserErrorCode.libraryDirectiveNotFirst, 17, 7)], |
| ); |
| } |
| |
| void test_libraryDirectiveNotFirst_afterPart() { |
| CompilationUnit unit = parseCompilationUnit( |
| "part 'a.dart';\nlibrary l;", |
| errors: [expectedError(ParserErrorCode.libraryDirectiveNotFirst, 15, 7)], |
| ); |
| expect(unit, isNotNull); |
| } |
| |
| void test_localFunction_annotation() { |
| CompilationUnit unit = parseCompilationUnit( |
| "class C { m() { @Foo f() {} } }", |
| ); |
| expect(unit.declarations, hasLength(1)); |
| var declaration = unit.declarations[0] as ClassDeclaration; |
| expect(declaration.members, hasLength(1)); |
| var member = declaration.members[0] as MethodDeclaration; |
| var body = member.body as BlockFunctionBody; |
| expect(body.block.statements, hasLength(1)); |
| var statement = body.block.statements[0] as FunctionDeclarationStatement; |
| expect(statement.functionDeclaration.metadata, hasLength(1)); |
| Annotation metadata = statement.functionDeclaration.metadata[0]; |
| expect(metadata.name.name, 'Foo'); |
| } |
| |
| void test_localFunctionDeclarationModifier_abstract() { |
| parseCompilationUnit( |
| "class C { m() { abstract f() {} } }", |
| errors: [expectedError(ParserErrorCode.extraneousModifier, 16, 8)], |
| ); |
| } |
| |
| void test_localFunctionDeclarationModifier_external() { |
| parseCompilationUnit( |
| "class C { m() { external f() {} } }", |
| errors: [expectedError(ParserErrorCode.extraneousModifier, 16, 8)], |
| ); |
| } |
| |
| void test_localFunctionDeclarationModifier_factory() { |
| parseCompilationUnit( |
| "class C { m() { factory f() {} } }", |
| errors: [expectedError(ParserErrorCode.expectedToken, 16, 7)], |
| ); |
| } |
| |
| void test_localFunctionDeclarationModifier_static() { |
| parseCompilationUnit( |
| "class C { m() { static f() {} } }", |
| errors: [expectedError(ParserErrorCode.extraneousModifier, 16, 6)], |
| ); |
| } |
| |
| void test_method_invalidTypeParameterExtends() { |
| // Regression test for https://github.com/dart-lang/sdk/issues/25739. |
| |
| // TODO(jmesserly): ideally we'd be better at parser recovery here. |
| createParser('f<E>(E extends num p);'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([expectedError(ParserErrorCode.expectedToken, 7, 7)]); |
| expect(member, isMethodDeclaration); |
| var method = member as MethodDeclaration; |
| expect( |
| method.parameters.toString(), |
| '(E)', |
| reason: 'parser recovers what it can', |
| ); |
| } |
| |
| void test_method_invalidTypeParameters() { |
| createParser('void m<E, hello!>() {}'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.expectedToken, 10, 5), |
| ]); |
| expect(member, isMethodDeclaration); |
| var method = member as MethodDeclaration; |
| expect( |
| method.typeParameters.toString(), |
| '<E, hello>', |
| reason: 'parser recovers what it can', |
| ); |
| } |
| |
| void test_missing_closing_bracket_issue37528() { |
| var code = '\${foo'; |
| createParser(code); |
| var result = fasta.scanString(code); |
| expect(result.hasErrors, isTrue); |
| var token = parserProxy.fastaParser.syntheticPreviousToken(result.tokens); |
| try { |
| parserProxy.fastaParser.parseExpression(token); |
| // TODO(danrubel): Replace this test once root cause is found |
| fail('exception expected'); |
| } catch (e) { |
| var msg = e.toString(); |
| expect(msg.contains('test_missing_closing_bracket_issue37528'), isTrue); |
| } |
| } |
| |
| void test_missingAssignableSelector_identifiersAssigned() { |
| parseExpression("x.y = y;", expectedEndOffset: 7); |
| } |
| |
| void test_missingAssignableSelector_prefix_minusMinus_literal() { |
| parseExpression( |
| "--0", |
| errors: [expectedError(ParserErrorCode.missingAssignableSelector, 2, 1)], |
| ); |
| } |
| |
| void test_missingAssignableSelector_prefix_plusPlus_literal() { |
| parseExpression( |
| "++0", |
| errors: [expectedError(ParserErrorCode.missingAssignableSelector, 2, 1)], |
| ); |
| } |
| |
| void test_missingAssignableSelector_selector() { |
| parseExpression("x(y)(z).a++"); |
| } |
| |
| void test_missingAssignableSelector_superAsExpressionFunctionBody() { |
| CompilationUnit unit = parseCompilationUnit( |
| 'main() => super;', |
| errors: [error(ParserErrorCode.missingAssignableSelector, 10, 5)], |
| ); |
| var declaration = unit.declarations.first as FunctionDeclaration; |
| var body = declaration.functionExpression.body as ExpressionFunctionBody; |
| var expression = body.expression; |
| expect(expression, isSuperExpression); |
| var superExpression = expression as SuperExpression; |
| expect(superExpression.superKeyword, isNotNull); |
| } |
| |
| void test_missingAssignableSelector_superPrimaryExpression() { |
| CompilationUnit unit = parseCompilationUnit( |
| 'main() {super;}', |
| errors: [expectedError(ParserErrorCode.missingAssignableSelector, 8, 5)], |
| ); |
| var declaration = unit.declarations.first as FunctionDeclaration; |
| var blockBody = declaration.functionExpression.body as BlockFunctionBody; |
| var statement = blockBody.block.statements.first as ExpressionStatement; |
| var expression = statement.expression; |
| expect(expression, isSuperExpression); |
| var superExpression = expression as SuperExpression; |
| expect(superExpression.superKeyword, isNotNull); |
| } |
| |
| void test_missingAssignableSelector_superPropertyAccessAssigned() { |
| parseExpression("super.x = x;", expectedEndOffset: 11); |
| } |
| |
| void test_missingCatchOrFinally() { |
| var statement = parseStatement('try {}') as TryStatement; |
| expectNotNullIfNoErrors(statement); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingCatchOrFinally, 0, 3), |
| ]); |
| expect(statement, isNotNull); |
| } |
| |
| void test_missingClosingParenthesis() { |
| createParser( |
| '(int a, int b ;', |
| expectedEndOffset: 14 /* parsing ends at synthetic ')' */, |
| ); |
| FormalParameterList list = parser.parseFormalParameterList(); |
| expectNotNullIfNoErrors(list); |
| listener.assertErrors([ |
| expectedError(ScannerErrorCode.expectedToken, 14, 1), |
| ]); |
| } |
| |
| void test_missingConstFinalVarOrType_static() { |
| parseCompilationUnit( |
| "class A { static f; }", |
| errors: [ |
| expectedError(ParserErrorCode.missingConstFinalVarOrType, 17, 1), |
| ], |
| ); |
| } |
| |
| void test_missingConstFinalVarOrType_topLevel() { |
| parseCompilationUnit( |
| 'a;', |
| errors: [expectedError(ParserErrorCode.missingConstFinalVarOrType, 0, 1)], |
| ); |
| } |
| |
| void test_missingEnumBody() { |
| createParser('enum E;', expectedEndOffset: 6); |
| var declaration = parseFullCompilationUnitMember() as EnumDeclaration; |
| expectNotNullIfNoErrors(declaration); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingEnumBody, 6, 1), |
| ]); |
| } |
| |
| void test_missingEnumComma() { |
| createParser('enum E {one two}'); |
| var declaration = parseFullCompilationUnitMember() as EnumDeclaration; |
| expectNotNullIfNoErrors(declaration); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.expectedToken, 12, 3), |
| ]); |
| } |
| |
| void test_missingExpressionInThrow() { |
| var expression = |
| (parseStatement('throw;') as ExpressionStatement).expression |
| as ThrowExpression; |
| expectNotNullIfNoErrors(expression); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingExpressionInThrow, 5, 1), |
| ]); |
| } |
| |
| void test_missingFunctionBody_emptyNotAllowed() { |
| createParser(';'); |
| FunctionBody functionBody = parser.parseFunctionBody( |
| false, |
| ParserErrorCode.missingFunctionBody, |
| false, |
| ); |
| expectNotNullIfNoErrors(functionBody); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingFunctionBody, 0, 1), |
| ]); |
| } |
| |
| void test_missingFunctionBody_invalid() { |
| createParser('return 0;'); |
| FunctionBody functionBody = parser.parseFunctionBody( |
| false, |
| ParserErrorCode.missingFunctionBody, |
| false, |
| ); |
| expectNotNullIfNoErrors(functionBody); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingFunctionBody, 0, 6), |
| ]); |
| } |
| |
| void test_missingFunctionParameters_local_nonVoid_block() { |
| // The parser does not recognize this as a function declaration, so it tries |
| // to parse it as an expression statement. It isn't clear what the best |
| // error message is in this case. |
| parseStatement("int f { return x;}", expectedEndOffset: 6); |
| listener.assertErrors([expectedError(ParserErrorCode.expectedToken, 4, 1)]); |
| } |
| |
| void test_missingFunctionParameters_local_nonVoid_expression() { |
| // The parser does not recognize this as a function declaration, so it tries |
| // to parse it as an expression statement. It isn't clear what the best |
| // error message is in this case. |
| parseStatement("int f => x;"); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingFunctionParameters, 6, 2), |
| ]); |
| } |
| |
| void test_missingFunctionParameters_local_void_block() { |
| parseStatement("void f { return x;}", expectedEndOffset: 7); |
| listener.assertErrors([expectedError(ParserErrorCode.expectedToken, 5, 1)]); |
| } |
| |
| void test_missingFunctionParameters_local_void_expression() { |
| parseStatement("void f => x;"); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingFunctionParameters, 7, 2), |
| ]); |
| } |
| |
| void test_missingFunctionParameters_topLevel_nonVoid_block() { |
| parseCompilationUnit( |
| "int f { return x;}", |
| errors: [expectedError(ParserErrorCode.missingFunctionParameters, 4, 1)], |
| ); |
| } |
| |
| void test_missingFunctionParameters_topLevel_nonVoid_expression() { |
| parseCompilationUnit( |
| "int f => x;", |
| errors: [expectedError(ParserErrorCode.missingFunctionParameters, 4, 1)], |
| ); |
| } |
| |
| void test_missingFunctionParameters_topLevel_void_block() { |
| CompilationUnit unit = parseCompilationUnit( |
| "void f { return x;}", |
| errors: [expectedError(ParserErrorCode.missingFunctionParameters, 5, 1)], |
| ); |
| var funct = unit.declarations[0] as FunctionDeclaration; |
| expect(funct.functionExpression.parameters, hasLength(0)); |
| } |
| |
| void test_missingFunctionParameters_topLevel_void_expression() { |
| CompilationUnit unit = parseCompilationUnit( |
| "void f => x;", |
| errors: [expectedError(ParserErrorCode.missingFunctionParameters, 5, 1)], |
| ); |
| var funct = unit.declarations[0] as FunctionDeclaration; |
| expect(funct.functionExpression.parameters, hasLength(0)); |
| } |
| |
| void test_missingIdentifier_afterOperator() { |
| createParser('1 *'); |
| var expression = parser.parseMultiplicativeExpression() as BinaryExpression; |
| expectNotNullIfNoErrors(expression); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingIdentifier, 3, 0), |
| ]); |
| } |
| |
| void test_missingIdentifier_beforeClosingCurly() { |
| createParser('int}', expectedEndOffset: 3); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingConstFinalVarOrType, 0, 3), |
| expectedError(ParserErrorCode.expectedToken, 0, 3), |
| ]); |
| } |
| |
| void test_missingIdentifier_inEnum() { |
| createParser('enum E {, TWO}'); |
| var declaration = parseFullCompilationUnitMember() as EnumDeclaration; |
| expectNotNullIfNoErrors(declaration); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingIdentifier, 8, 1), |
| ]); |
| } |
| |
| void test_missingIdentifier_inParameterGroupNamed() { |
| createParser('(a, {})'); |
| FormalParameterList list = parser.parseFormalParameterList(); |
| expectNotNullIfNoErrors(list); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingIdentifier, 5, 1), |
| ]); |
| } |
| |
| void test_missingIdentifier_inParameterGroupOptional() { |
| createParser('(a, [])'); |
| FormalParameterList list = parser.parseFormalParameterList(); |
| expectNotNullIfNoErrors(list); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingIdentifier, 5, 1), |
| ]); |
| } |
| |
| void test_missingIdentifier_inSymbol_afterPeriod() { |
| SymbolLiteral literal = parseSymbolLiteral('#a.'); |
| expectNotNullIfNoErrors(literal); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingIdentifier, 3, 1), |
| ]); |
| } |
| |
| void test_missingIdentifier_inSymbol_first() { |
| SymbolLiteral literal = parseSymbolLiteral('#'); |
| expectNotNullIfNoErrors(literal); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingIdentifier, 1, 1), |
| ]); |
| } |
| |
| void test_missingIdentifierForParameterGroup() { |
| createParser('(,)'); |
| FormalParameterList list = parser.parseFormalParameterList(); |
| expectNotNullIfNoErrors(list); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingIdentifier, 1, 1), |
| ]); |
| } |
| |
| void test_missingKeywordOperator() { |
| createParser('+(x) {}'); |
| var method = parser.parseClassMember('C') as MethodDeclaration; |
| expectNotNullIfNoErrors(method); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingKeywordOperator, 0, 1), |
| ]); |
| } |
| |
| void test_missingKeywordOperator_parseClassMember() { |
| createParser('+() {}'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingKeywordOperator, 0, 1), |
| ]); |
| } |
| |
| void test_missingKeywordOperator_parseClassMember_afterTypeName() { |
| createParser('int +() {}'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingKeywordOperator, 4, 1), |
| ]); |
| } |
| |
| void test_missingKeywordOperator_parseClassMember_afterVoid() { |
| createParser('void +() {}'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingKeywordOperator, 5, 1), |
| ]); |
| } |
| |
| void test_missingMethodParameters_void_block() { |
| createParser('void m {} }', expectedEndOffset: 10); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingMethodParameters, 5, 1), |
| ]); |
| expect(member, isMethodDeclaration); |
| var method = member as MethodDeclaration; |
| expect(method.parameters, hasLength(0)); |
| } |
| |
| void test_missingMethodParameters_void_expression() { |
| createParser('void m => null; }', expectedEndOffset: 16); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingMethodParameters, 5, 1), |
| ]); |
| } |
| |
| void test_missingNameForNamedParameter_colon() { |
| createParser('({int : 0})'); |
| FormalParameter parameter = parser |
| .parseFormalParameterList(inFunctionType: true) |
| .parameters[0]; |
| expectNotNullIfNoErrors(parameter); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingIdentifier, 6, 1), |
| expectedError(ParserErrorCode.defaultValueInFunctionType, 6, 1), |
| ]); |
| expect(parameter.name, isNotNull); |
| } |
| |
| void test_missingNameForNamedParameter_equals() { |
| createParser('({int = 0})'); |
| FormalParameter parameter = parser |
| .parseFormalParameterList(inFunctionType: true) |
| .parameters[0]; |
| expectNotNullIfNoErrors(parameter); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingIdentifier, 6, 1), |
| expectedError(ParserErrorCode.defaultValueInFunctionType, 6, 1), |
| ]); |
| expect(parameter.name, isNotNull); |
| } |
| |
| void test_missingNameForNamedParameter_noDefault() { |
| createParser('({int})'); |
| FormalParameter parameter = parser |
| .parseFormalParameterList(inFunctionType: true) |
| .parameters[0]; |
| expectNotNullIfNoErrors(parameter); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingIdentifier, 5, 1), |
| ]); |
| expect(parameter.name, isNotNull); |
| } |
| |
| void test_missingNameInPartOfDirective() { |
| CompilationUnit unit = parseCompilationUnit( |
| "part of;", |
| errors: [expectedError(ParserErrorCode.expectedStringLiteral, 7, 1)], |
| ); |
| expect(unit, isNotNull); |
| } |
| |
| void test_missingPrefixInDeferredImport() { |
| parseCompilationUnit( |
| "import 'foo.dart' deferred;", |
| errors: [ |
| expectedError(ParserErrorCode.missingPrefixInDeferredImport, 18, 8), |
| ], |
| ); |
| } |
| |
| void test_missingStartAfterSync() { |
| createParser('sync {}'); |
| FunctionBody functionBody = parser.parseFunctionBody( |
| false, |
| ParserErrorCode.missingFunctionBody, |
| false, |
| ); |
| expectNotNullIfNoErrors(functionBody); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingStarAfterSync, 0, 4), |
| ]); |
| } |
| |
| void test_missingStatement() { |
| parseStatement("is"); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.expectedToken, 0, 2), |
| expectedError(ParserErrorCode.missingIdentifier, 0, 2), |
| expectedError(ParserErrorCode.expectedTypeName, 2, 0), |
| ]); |
| } |
| |
| void test_missingStatement_afterVoid() { |
| parseStatement("void;"); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingIdentifier, 4, 1), |
| ]); |
| } |
| |
| void test_missingTerminatorForParameterGroup_named() { |
| createParser('(a, {b: 0)'); |
| FormalParameterList list = parser.parseFormalParameterList(); |
| expectNotNullIfNoErrors(list); |
| listener.assertErrors([ |
| expectedError(ScannerErrorCode.expectedToken, 9, 1), |
| ]); |
| } |
| |
| void test_missingTerminatorForParameterGroup_optional() { |
| createParser('(a, [b = 0)'); |
| FormalParameterList list = parser.parseFormalParameterList(); |
| expectNotNullIfNoErrors(list); |
| listener.assertErrors([ |
| expectedError(ScannerErrorCode.expectedToken, 10, 1), |
| ]); |
| } |
| |
| void test_missingTypedefParameters_nonVoid() { |
| parseCompilationUnit( |
| "typedef int F;", |
| errors: [expectedError(ParserErrorCode.missingTypedefParameters, 13, 1)], |
| ); |
| } |
| |
| void test_missingTypedefParameters_typeParameters() { |
| parseCompilationUnit( |
| "typedef F<E>;", |
| errors: [expectedError(ParserErrorCode.missingTypedefParameters, 12, 1)], |
| ); |
| } |
| |
| void test_missingTypedefParameters_void() { |
| parseCompilationUnit( |
| "typedef void F;", |
| errors: [expectedError(ParserErrorCode.missingTypedefParameters, 14, 1)], |
| ); |
| } |
| |
| void test_missingVariableInForEach() { |
| var statement = parseStatement('for (a < b in foo) {}'); |
| expectNotNullIfNoErrors(statement); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.unexpectedToken, 7, 1), |
| ]); |
| } |
| |
| void test_mixedParameterGroups_namedPositional() { |
| createParser('(a, {b}, [c])'); |
| FormalParameterList list = parser.parseFormalParameterList(); |
| expectNotNullIfNoErrors(list); |
| listener.assertErrors([expectedError(ParserErrorCode.expectedToken, 7, 1)]); |
| } |
| |
| void test_mixedParameterGroups_positionalNamed() { |
| createParser('(a, [b], {c})'); |
| FormalParameterList list = parser.parseFormalParameterList(); |
| expectNotNullIfNoErrors(list); |
| listener.assertErrors([expectedError(ParserErrorCode.expectedToken, 7, 1)]); |
| } |
| |
| void test_mixin_application_lacks_with_clause() { |
| parseCompilationUnit( |
| "class Foo = Bar;", |
| errors: [expectedError(ParserErrorCode.expectedToken, 15, 1)], |
| ); |
| } |
| |
| void test_multipleExtendsClauses() { |
| parseCompilationUnit( |
| "class A extends B extends C {}", |
| errors: [expectedError(ParserErrorCode.multipleExtendsClauses, 18, 7)], |
| ); |
| } |
| |
| void test_multipleImplementsClauses() { |
| parseCompilationUnit( |
| "class A implements B implements C {}", |
| errors: [ |
| expectedError(ParserErrorCode.multipleImplementsClauses, 21, 10), |
| ], |
| ); |
| } |
| |
| void test_multipleLibraryDirectives() { |
| parseCompilationUnit( |
| "library l; library m;", |
| errors: [expectedError(ParserErrorCode.multipleLibraryDirectives, 11, 7)], |
| ); |
| } |
| |
| void test_multipleNamedParameterGroups() { |
| createParser('(a, {b}, {c})'); |
| FormalParameterList list = parser.parseFormalParameterList(); |
| expectNotNullIfNoErrors(list); |
| listener.assertErrors([expectedError(ParserErrorCode.expectedToken, 7, 1)]); |
| } |
| |
| void test_multiplePartOfDirectives() { |
| parseCompilationUnit( |
| "part of l; part of m;", |
| errors: [expectedError(ParserErrorCode.multiplePartOfDirectives, 11, 4)], |
| ); |
| } |
| |
| void test_multiplePositionalParameterGroups() { |
| createParser('(a, [b], [c])'); |
| FormalParameterList list = parser.parseFormalParameterList(); |
| expectNotNullIfNoErrors(list); |
| listener.assertErrors([expectedError(ParserErrorCode.expectedToken, 7, 1)]); |
| } |
| |
| void test_multipleVariablesInForEach() { |
| var statement = parseStatement('for (int a, b in foo) {}'); |
| expectNotNullIfNoErrors(statement); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.unexpectedToken, 10, 1), |
| ]); |
| } |
| |
| void test_multipleWithClauses() { |
| parseCompilationUnit( |
| "class A extends B with C with D {}", |
| errors: [expectedError(ParserErrorCode.multipleWithClauses, 25, 4)], |
| ); |
| } |
| |
| void test_namedFunctionExpression() { |
| Expression expression; |
| createParser('f() {}'); |
| expression = parser.parsePrimaryExpression(); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.namedFunctionExpression, 0, 1), |
| ]); |
| expect(expression, isFunctionExpression); |
| } |
| |
| void test_namedParameterOutsideGroup() { |
| createParser('(a, b : 0)'); |
| FormalParameterList list = parser.parseFormalParameterList(); |
| expectNotNullIfNoErrors(list); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.namedParameterOutsideGroup, 6, 1), |
| ]); |
| expect(list.parameters[0].isRequired, isTrue); |
| expect(list.parameters[1].isNamed, isTrue); |
| } |
| |
| void test_nonConstructorFactory_field() { |
| createParser('factory int x;', expectedEndOffset: 12); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingFunctionParameters, 12, 1), |
| expectedError(ParserErrorCode.missingFunctionBody, 12, 1), |
| ]); |
| } |
| |
| void test_nonConstructorFactory_method() { |
| createParser('factory int m() {}', expectedEndOffset: 12); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingFunctionParameters, 12, 1), |
| expectedError(ParserErrorCode.missingFunctionBody, 12, 1), |
| ]); |
| } |
| |
| void test_nonIdentifierLibraryName_library() { |
| CompilationUnit unit = parseCompilationUnit( |
| "library 'lib';", |
| errors: [expectedError(ParserErrorCode.missingIdentifier, 8, 5)], |
| ); |
| expect(unit, isNotNull); |
| } |
| |
| void test_nonIdentifierLibraryName_partOf() { |
| CompilationUnit unit = parseCompilationUnit( |
| "part of 3;", |
| errors: [ |
| expectedError(ParserErrorCode.expectedToken, 5, 2), |
| expectedError(ParserErrorCode.expectedStringLiteral, 8, 1), |
| expectedError(ParserErrorCode.expectedExecutable, 8, 1), |
| expectedError(ParserErrorCode.unexpectedToken, 9, 1), |
| ], |
| ); |
| expect(unit, isNotNull); |
| } |
| |
| void test_nonUserDefinableOperator() { |
| createParser('operator +=(int x) => x + 1;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.invalidOperator, 9, 2), |
| ]); |
| } |
| |
| void test_optionalAfterNormalParameters_named() { |
| parseCompilationUnit( |
| "f({a}, b) {}", |
| errors: [expectedError(ParserErrorCode.expectedToken, 5, 1)], |
| ); |
| } |
| |
| void test_optionalAfterNormalParameters_positional() { |
| parseCompilationUnit( |
| "f([a], b) {}", |
| errors: [expectedError(ParserErrorCode.expectedToken, 5, 1)], |
| ); |
| } |
| |
| void test_parseCascadeSection_missingIdentifier() { |
| var methodInvocation = parseCascadeSection('..()') as MethodInvocation; |
| expectNotNullIfNoErrors(methodInvocation); |
| listener.assertErrors([ |
| // Cascade section is preceded by `null` in this test |
| // and error is reported on '('. |
| expectedError(ParserErrorCode.missingIdentifier, 6, 1), |
| ]); |
| expect(methodInvocation.target, isNull); |
| expect(methodInvocation.methodName.name, ""); |
| expect(methodInvocation.typeArguments, isNull); |
| expect(methodInvocation.argumentList.arguments, hasLength(0)); |
| } |
| |
| void test_parseCascadeSection_missingIdentifier_typeArguments() { |
| var methodInvocation = parseCascadeSection('..<E>()') as MethodInvocation; |
| expectNotNullIfNoErrors(methodInvocation); |
| listener.assertErrors([ |
| // Cascade section is preceded by `null` in this test |
| // and error is reported on '<'. |
| expectedError(ParserErrorCode.missingIdentifier, 6, 1), |
| ]); |
| expect(methodInvocation.target, isNull); |
| expect(methodInvocation.methodName.name, ""); |
| expect(methodInvocation.typeArguments, isNotNull); |
| expect(methodInvocation.argumentList.arguments, hasLength(0)); |
| } |
| |
| void test_partialNamedConstructor() { |
| parseCompilationUnit( |
| 'class C { C. }', |
| errors: [ |
| expectedError(ParserErrorCode.missingIdentifier, 13, 1), |
| expectedError(ParserErrorCode.missingMethodParameters, 10, 1), |
| expectedError(ParserErrorCode.missingFunctionBody, 13, 1), |
| ], |
| ); |
| } |
| |
| void test_positionalAfterNamedArgument() { |
| createParser('(x: 1, 2)', featureSet: FeatureSets.language_2_16); |
| ArgumentList list = parser.parseArgumentList(); |
| expectNotNullIfNoErrors(list); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.positionalAfterNamedArgument, 7, 1), |
| ]); |
| } |
| |
| void test_positionalParameterOutsideGroup() { |
| createParser('(a, b = 0)'); |
| FormalParameterList list = parser.parseFormalParameterList(); |
| expectNotNullIfNoErrors(list); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.namedParameterOutsideGroup, 6, 1), |
| ]); |
| expect(list.parameters[0].isRequired, isTrue); |
| expect(list.parameters[1].isNamed, isTrue); |
| } |
| |
| void test_redirectingConstructorWithBody_named() { |
| createParser('C.x() : this() {}'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.redirectingConstructorWithBody, 15, 1), |
| ]); |
| } |
| |
| void test_redirectingConstructorWithBody_unnamed() { |
| createParser('C() : this.x() {}'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.redirectingConstructorWithBody, 15, 1), |
| ]); |
| } |
| |
| void test_redirectionInNonFactoryConstructor() { |
| createParser('C() = D;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.redirectionInNonFactoryConstructor, 4, 1), |
| ]); |
| } |
| |
| void test_setterInFunction_block() { |
| parseStatement("set x(v) {_x = v;}"); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.unexpectedToken, 0, 3), |
| ]); |
| } |
| |
| void test_setterInFunction_expression() { |
| parseStatement("set x(v) => _x = v;"); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.unexpectedToken, 0, 3), |
| ]); |
| } |
| |
| void test_staticAfterConst() { |
| createParser('final static int f;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.modifierOutOfOrder, 6, 6), |
| ]); |
| } |
| |
| void test_staticAfterFinal() { |
| createParser('const static int f;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.modifierOutOfOrder, 6, 6), |
| expectedError(CompileTimeErrorCode.constNotInitialized, 17, 1), |
| ]); |
| } |
| |
| void test_staticAfterVar() { |
| createParser('var static f;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.modifierOutOfOrder, 4, 6), |
| ]); |
| } |
| |
| void test_staticConstructor() { |
| createParser('static C.m() {}'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.staticConstructor, 0, 6), |
| ]); |
| } |
| |
| void test_staticGetterWithoutBody() { |
| createParser('static get m;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingFunctionBody, 12, 1), |
| ]); |
| } |
| |
| void test_staticOperator_noReturnType() { |
| createParser('static operator +(int x) => x + 1;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.staticOperator, 0, 6), |
| ]); |
| } |
| |
| void test_staticOperator_returnType() { |
| createParser('static int operator +(int x) => x + 1;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.staticOperator, 0, 6), |
| ]); |
| } |
| |
| void test_staticOperatorNamedMethod() { |
| // operator can be used as a method name |
| parseCompilationUnit('class C { static operator(x) => x; }'); |
| } |
| |
| void test_staticSetterWithoutBody() { |
| createParser('static set m(x);'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingFunctionBody, 15, 1), |
| ]); |
| } |
| |
| void test_staticTopLevelDeclaration_class() { |
| parseCompilationUnit( |
| "static class C {}", |
| errors: [expectedError(ParserErrorCode.extraneousModifier, 0, 6)], |
| ); |
| } |
| |
| void test_staticTopLevelDeclaration_enum() { |
| parseCompilationUnit( |
| "static enum E { v }", |
| errors: [expectedError(ParserErrorCode.extraneousModifier, 0, 6)], |
| ); |
| } |
| |
| void test_staticTopLevelDeclaration_function() { |
| parseCompilationUnit( |
| "static f() {}", |
| errors: [expectedError(ParserErrorCode.extraneousModifier, 0, 6)], |
| ); |
| } |
| |
| void test_staticTopLevelDeclaration_typedef() { |
| parseCompilationUnit( |
| "static typedef F();", |
| errors: [expectedError(ParserErrorCode.extraneousModifier, 0, 6)], |
| ); |
| } |
| |
| void test_staticTopLevelDeclaration_variable() { |
| parseCompilationUnit( |
| "static var x;", |
| errors: [expectedError(ParserErrorCode.extraneousModifier, 0, 6)], |
| ); |
| } |
| |
| void test_string_unterminated_interpolation_block() { |
| parseCompilationUnit( |
| r''' |
| m() { |
| { |
| '${${ |
| ''', |
| codes: [ |
| ScannerErrorCode.unterminatedStringLiteral, |
| ScannerErrorCode.expectedToken, |
| ScannerErrorCode.expectedToken, |
| ScannerErrorCode.expectedToken, |
| ScannerErrorCode.expectedToken, |
| ParserErrorCode.expectedToken, |
| ParserErrorCode.expectedToken, |
| ], |
| ); |
| } |
| |
| void test_switchCase_missingColon() { |
| var statement = |
| parseStatement('switch (a) {case 1 return 0;}') as SwitchStatement; |
| expect(statement, isNotNull); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.expectedToken, 19, 6), |
| ]); |
| } |
| |
| void test_switchDefault_missingColon() { |
| var statement = |
| parseStatement('switch (a) {default return 0;}') as SwitchStatement; |
| expect(statement, isNotNull); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.expectedToken, 20, 6), |
| ]); |
| } |
| |
| void test_switchHasCaseAfterDefaultCase() { |
| var statement = |
| parseStatement('switch (a) {default: return 0; case 1: return 1;}') |
| as SwitchStatement; |
| expectNotNullIfNoErrors(statement); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.switchHasCaseAfterDefaultCase, 31, 4), |
| ]); |
| } |
| |
| void test_switchHasCaseAfterDefaultCase_repeated() { |
| var statement = |
| parseStatement( |
| 'switch (a) {default: return 0; case 1: return 1; case 2: return 2;}', |
| ) |
| as SwitchStatement; |
| expectNotNullIfNoErrors(statement); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.switchHasCaseAfterDefaultCase, 31, 4), |
| expectedError(ParserErrorCode.switchHasCaseAfterDefaultCase, 49, 4), |
| ]); |
| } |
| |
| void test_switchHasMultipleDefaultCases() { |
| var statement = |
| parseStatement('switch (a) {default: return 0; default: return 1;}') |
| as SwitchStatement; |
| expectNotNullIfNoErrors(statement); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.switchHasMultipleDefaultCases, 31, 7), |
| ]); |
| } |
| |
| void test_switchHasMultipleDefaultCases_repeated() { |
| var statement = |
| parseStatement( |
| 'switch (a) {default: return 0; default: return 1; default: return 2;}', |
| ) |
| as SwitchStatement; |
| expectNotNullIfNoErrors(statement); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.switchHasMultipleDefaultCases, 31, 7), |
| expectedError(ParserErrorCode.switchHasMultipleDefaultCases, 50, 7), |
| ]); |
| } |
| |
| void test_switchMissingBlock() { |
| var statement = |
| parseStatement('switch (a) return;', expectedEndOffset: 11) |
| as SwitchStatement; |
| expect(statement, isNotNull); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.expectedSwitchStatementBody, 9, 1), |
| ]); |
| } |
| |
| void test_topLevel_getter() { |
| createParser('get x => 7;'); |
| CompilationUnitMember member = parseFullCompilationUnitMember(); |
| expectNotNullIfNoErrors(member); |
| assertNoErrors(); |
| expect(member, isFunctionDeclaration); |
| var function = member as FunctionDeclaration; |
| expect(function.functionExpression.parameters, isNull); |
| } |
| |
| void test_topLevelFactory_withFunction() { |
| parseCompilationUnit( |
| 'factory Function() x = null;', |
| errors: [expectedError(ParserErrorCode.factoryTopLevelDeclaration, 0, 7)], |
| ); |
| } |
| |
| void test_topLevelOperator_withFunction() { |
| parseCompilationUnit( |
| 'operator Function() x = null;', |
| errors: [expectedError(ParserErrorCode.topLevelOperator, 0, 8)], |
| ); |
| } |
| |
| void test_topLevelOperator_withoutOperator() { |
| createParser('+(bool x, bool y) => x | y;'); |
| CompilationUnitMember member = parseFullCompilationUnitMember(); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.topLevelOperator, 0, 1), |
| ]); |
| } |
| |
| void test_topLevelOperator_withoutType() { |
| parseCompilationUnit( |
| 'operator +(bool x, bool y) => x | y;', |
| errors: [expectedError(ParserErrorCode.topLevelOperator, 0, 8)], |
| ); |
| } |
| |
| void test_topLevelOperator_withType() { |
| parseCompilationUnit( |
| 'bool operator +(bool x, bool y) => x | y;', |
| errors: [expectedError(ParserErrorCode.topLevelOperator, 5, 8)], |
| ); |
| } |
| |
| void test_topLevelOperator_withVoid() { |
| parseCompilationUnit( |
| 'void operator +(bool x, bool y) => x | y;', |
| errors: [expectedError(ParserErrorCode.topLevelOperator, 5, 8)], |
| ); |
| } |
| |
| void test_topLevelVariable_withMetadata() { |
| parseCompilationUnit( |
| "String @A string;", |
| codes: [ |
| ParserErrorCode.missingConstFinalVarOrType, |
| ParserErrorCode.expectedToken, |
| ParserErrorCode.missingConstFinalVarOrType, |
| ], |
| ); |
| } |
| |
| void test_typedef_incomplete() { |
| // TODO(brianwilkerson): Improve recovery for this case. |
| parseCompilationUnit( |
| ''' |
| class A {} |
| class B extends A {} |
| |
| typedef T |
| |
| main() { |
| Function< |
| } |
| ''', |
| errors: [ |
| expectedError(ParserErrorCode.expectedToken, 49, 1), |
| expectedError(ParserErrorCode.expectedExecutable, 51, 1), |
| ], |
| ); |
| } |
| |
| void test_typedef_namedFunction() { |
| parseCompilationUnit( |
| 'typedef void Function();', |
| codes: [ParserErrorCode.expectedIdentifierButGotKeyword], |
| ); |
| } |
| |
| void test_typedefInClass_withoutReturnType() { |
| parseCompilationUnit( |
| "class C { typedef F(x); }", |
| errors: [expectedError(ParserErrorCode.typedefInClass, 10, 7)], |
| ); |
| } |
| |
| void test_typedefInClass_withReturnType() { |
| parseCompilationUnit( |
| "class C { typedef int F(int x); }", |
| errors: [expectedError(ParserErrorCode.typedefInClass, 10, 7)], |
| ); |
| } |
| |
| void test_unexpectedCommaThenInterpolation() { |
| // https://github.com/Dart-Code/Dart-Code/issues/1548 |
| parseCompilationUnit( |
| r"main() { String s = 'a' 'b', 'c$foo'; return s; }", |
| errors: [ |
| expectedError(ParserErrorCode.expectedToken, 27, 1), |
| expectedError(ParserErrorCode.missingIdentifier, 29, 2), |
| ], |
| ); |
| } |
| |
| void test_unexpectedTerminatorForParameterGroup_named() { |
| createParser('(a, b})'); |
| FormalParameterList list = parser.parseFormalParameterList(); |
| expectNotNullIfNoErrors(list); |
| listener.assertErrors([expectedError(ParserErrorCode.expectedToken, 5, 1)]); |
| } |
| |
| void test_unexpectedTerminatorForParameterGroup_optional() { |
| createParser('(a, b])'); |
| FormalParameterList list = parser.parseFormalParameterList(); |
| expectNotNullIfNoErrors(list); |
| listener.assertErrors([expectedError(ParserErrorCode.expectedToken, 5, 1)]); |
| } |
| |
| void test_unexpectedToken_endOfFieldDeclarationStatement() { |
| parseStatement("String s = (null));", expectedEndOffset: 17); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.expectedToken, 16, 1), |
| ]); |
| } |
| |
| void test_unexpectedToken_invalidPostfixExpression() { |
| parseExpression( |
| "f()++", |
| errors: [ |
| expectedError(ParserErrorCode.illegalAssignmentToNonAssignable, 3, 2), |
| ], |
| ); |
| } |
| |
| void test_unexpectedToken_invalidPrefixExpression() { |
| parseExpression( |
| "++f()", |
| errors: [expectedError(ParserErrorCode.missingAssignableSelector, 4, 1)], |
| ); |
| } |
| |
| void test_unexpectedToken_returnInExpressionFunctionBody() { |
| parseCompilationUnit( |
| "f() => return null;", |
| errors: [expectedError(ParserErrorCode.unexpectedToken, 7, 6)], |
| ); |
| } |
| |
| void test_unexpectedToken_semicolonBetweenClassMembers() { |
| createParser('class C { int x; ; int y;}'); |
| var declaration = parseFullCompilationUnitMember() as ClassDeclaration; |
| expectNotNullIfNoErrors(declaration); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.expectedClassMember, 17, 1), |
| ]); |
| } |
| |
| void test_unexpectedToken_semicolonBetweenCompilationUnitMembers() { |
| parseCompilationUnit( |
| "int x; ; int y;", |
| errors: [expectedError(ParserErrorCode.unexpectedToken, 7, 1)], |
| ); |
| } |
| |
| void test_unnamedLibraryDirective() { |
| CompilationUnit unit = parseCompilationUnit( |
| "library;", |
| featureSet: FeatureSets.language_2_18, |
| errors: [expectedError(ParserErrorCode.experimentNotEnabled, 0, 7)], |
| ); |
| expect(unit, isNotNull); |
| } |
| |
| void test_unnamedLibraryDirective_enabled() { |
| CompilationUnit unit = parseCompilationUnit("library;"); |
| expect(unit, isNotNull); |
| } |
| |
| void test_unterminatedString_at_eof() { |
| // Although the "unterminated string" error message is produced by the |
| // scanner, we need to verify that the parser can handle the tokens |
| // produced by the scanner when an unterminated string is encountered. |
| parseCompilationUnit( |
| r''' |
| void main() { |
| var x = "''', |
| errors: [ |
| expectedError(ScannerErrorCode.unterminatedStringLiteral, 24, 1), |
| expectedError(ScannerErrorCode.expectedToken, 25, 1), |
| expectedError(ParserErrorCode.expectedToken, 24, 1), |
| ], |
| ); |
| } |
| |
| void test_unterminatedString_at_eol() { |
| // Although the "unterminated string" error message is produced by the |
| // scanner, we need to verify that the parser can handle the tokens |
| // produced by the scanner when an unterminated string is encountered. |
| parseCompilationUnit( |
| r''' |
| void main() { |
| var x = " |
| ; |
| } |
| ''', |
| errors: [ |
| expectedError(ScannerErrorCode.unterminatedStringLiteral, 24, 1), |
| ], |
| ); |
| } |
| |
| void test_unterminatedString_multiline_at_eof_3_quotes() { |
| // Although the "unterminated string" error message is produced by the |
| // scanner, we need to verify that the parser can handle the tokens |
| // produced by the scanner when an unterminated string is encountered. |
| // TODO(brianwilkerson): Remove codes when highlighting is fixed. |
| parseCompilationUnit( |
| r''' |
| void main() { |
| var x = """''', |
| codes: [ |
| ScannerErrorCode.unterminatedStringLiteral, |
| ScannerErrorCode.expectedToken, |
| ParserErrorCode.expectedToken, |
| ], |
| errors: [ |
| expectedError(ScannerErrorCode.unterminatedStringLiteral, 24, 1), |
| expectedError(ScannerErrorCode.expectedToken, 30, 0), |
| expectedError(ParserErrorCode.expectedToken, 30, 0), |
| ], |
| ); |
| } |
| |
| void test_unterminatedString_multiline_at_eof_4_quotes() { |
| // Although the "unterminated string" error message is produced by the |
| // scanner, we need to verify that the parser can handle the tokens |
| // produced by the scanner when an unterminated string is encountered. |
| // TODO(brianwilkerson): Remove codes when highlighting is fixed. |
| parseCompilationUnit( |
| r''' |
| void main() { |
| var x = """"''', |
| codes: [ |
| ScannerErrorCode.unterminatedStringLiteral, |
| ScannerErrorCode.expectedToken, |
| ParserErrorCode.expectedToken, |
| ], |
| errors: [ |
| expectedError(ScannerErrorCode.unterminatedStringLiteral, 24, 1), |
| expectedError(ScannerErrorCode.expectedToken, 31, 0), |
| expectedError(ParserErrorCode.expectedToken, 31, 0), |
| ], |
| ); |
| } |
| |
| void test_unterminatedString_multiline_at_eof_5_quotes() { |
| // Although the "unterminated string" error message is produced by the |
| // scanner, we need to verify that the parser can handle the tokens |
| // produced by the scanner when an unterminated string is encountered. |
| // TODO(brianwilkerson): Remove codes when highlighting is fixed. |
| parseCompilationUnit( |
| r''' |
| void main() { |
| var x = """""''', |
| codes: [ |
| ScannerErrorCode.unterminatedStringLiteral, |
| ScannerErrorCode.expectedToken, |
| ParserErrorCode.expectedToken, |
| ], |
| errors: [ |
| expectedError(ScannerErrorCode.unterminatedStringLiteral, 28, 1), |
| expectedError(ScannerErrorCode.expectedToken, 32, 0), |
| expectedError(ParserErrorCode.expectedToken, 32, 0), |
| ], |
| ); |
| } |
| |
| void test_useOfUnaryPlusOperator() { |
| createParser('+x'); |
| Expression expression = parser.parseUnaryExpression(); |
| expectNotNullIfNoErrors(expression); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.missingIdentifier, 0, 1), |
| ]); |
| var binaryExpression = expression as BinaryExpression; |
| expect(binaryExpression.leftOperand.isSynthetic, isTrue); |
| expect(binaryExpression.rightOperand.isSynthetic, isFalse); |
| var identifier = binaryExpression.rightOperand as SimpleIdentifier; |
| expect(identifier.name, 'x'); |
| } |
| |
| void test_varAndType_field() { |
| parseCompilationUnit( |
| "class C { var int x; }", |
| errors: [expectedError(ParserErrorCode.varAndType, 10, 3)], |
| ); |
| } |
| |
| void test_varAndType_local() { |
| // This is currently reporting EXPECTED_TOKEN for a missing semicolon, but |
| // this would be a better error message. |
| parseStatement("var int x;"); |
| listener.assertErrors([expectedError(ParserErrorCode.varAndType, 0, 3)]); |
| } |
| |
| void test_varAndType_parameter() { |
| // This is currently reporting EXPECTED_TOKEN for a missing semicolon, but |
| // this would be a better error message. |
| createParser('(var int x)'); |
| FormalParameterList list = parser.parseFormalParameterList(); |
| expectNotNullIfNoErrors(list); |
| listener.assertErrors([expectedError(ParserErrorCode.varAndType, 1, 3)]); |
| } |
| |
| void test_varAndType_topLevelVariable() { |
| parseCompilationUnit( |
| "var int x;", |
| errors: [expectedError(ParserErrorCode.varAndType, 0, 3)], |
| ); |
| } |
| |
| void test_varAsTypeName_as() { |
| parseExpression( |
| "x as var", |
| expectedEndOffset: 5, |
| errors: [expectedError(ParserErrorCode.expectedTypeName, 5, 3)], |
| ); |
| } |
| |
| void test_varClass() { |
| parseCompilationUnit( |
| "var class C {}", |
| errors: [ |
| // Fasta interprets the `var` as a malformed top level var |
| // and `class` as the start of a class declaration. |
| expectedError(ParserErrorCode.expectedToken, 0, 3), |
| expectedError(ParserErrorCode.missingIdentifier, 4, 5), |
| ], |
| ); |
| } |
| |
| void test_varEnum() { |
| parseCompilationUnit( |
| "var enum E {ONE}", |
| errors: [ |
| // Fasta interprets the `var` as a malformed top level var |
| // and `enum` as the start of an enum declaration. |
| expectedError(ParserErrorCode.expectedToken, 0, 3), |
| expectedError(ParserErrorCode.missingIdentifier, 4, 4), |
| ], |
| ); |
| } |
| |
| void test_varReturnType() { |
| createParser('var m() {}'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| listener.assertErrors([expectedError(ParserErrorCode.varReturnType, 0, 3)]); |
| } |
| |
| void test_varTypedef() { |
| parseCompilationUnit( |
| "var typedef F();", |
| errors: [ |
| // Fasta interprets the `var` as a malformed top level var |
| // and `typedef` as the start of an typedef declaration. |
| expectedError(ParserErrorCode.expectedToken, 0, 3), |
| expectedError(ParserErrorCode.missingIdentifier, 4, 7), |
| ], |
| ); |
| } |
| |
| void test_voidParameter() { |
| var parameter = |
| parseFormalParameterList('(void a)').parameters[0] |
| as NormalFormalParameter; |
| expectNotNullIfNoErrors(parameter); |
| assertNoErrors(); |
| } |
| |
| void test_voidVariable_parseClassMember_initializer() { |
| createParser('void x = 0;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| assertNoErrors(); |
| } |
| |
| void test_voidVariable_parseClassMember_noInitializer() { |
| createParser('void x;'); |
| ClassMember member = parser.parseClassMember('C'); |
| expectNotNullIfNoErrors(member); |
| assertNoErrors(); |
| } |
| |
| void test_voidVariable_parseCompilationUnit_initializer() { |
| parseCompilationUnit("void x = 0;"); |
| } |
| |
| void test_voidVariable_parseCompilationUnit_noInitializer() { |
| parseCompilationUnit("void x;"); |
| } |
| |
| void test_voidVariable_parseCompilationUnitMember_initializer() { |
| createParser('void a = 0;'); |
| CompilationUnitMember member = parseFullCompilationUnitMember(); |
| expectNotNullIfNoErrors(member); |
| assertNoErrors(); |
| } |
| |
| void test_voidVariable_parseCompilationUnitMember_noInitializer() { |
| createParser('void a;'); |
| CompilationUnitMember member = parseFullCompilationUnitMember(); |
| expectNotNullIfNoErrors(member); |
| assertNoErrors(); |
| } |
| |
| void test_voidVariable_statement_initializer() { |
| parseStatement("void x = 0;"); |
| assertNoErrors(); |
| } |
| |
| void test_voidVariable_statement_noInitializer() { |
| parseStatement("void x;"); |
| assertNoErrors(); |
| } |
| |
| void test_withBeforeExtends() { |
| parseCompilationUnit( |
| "class A with B extends C {}", |
| errors: [expectedError(ParserErrorCode.withBeforeExtends, 15, 7)], |
| ); |
| } |
| |
| void test_withWithoutExtends() { |
| createParser('class A with B, C {}'); |
| var declaration = parseFullCompilationUnitMember() as ClassDeclaration; |
| expectNotNullIfNoErrors(declaration); |
| listener.assertNoErrors(); |
| } |
| |
| void test_wrongSeparatorForPositionalParameter() { |
| createParser('(a, [b : 0])'); |
| FormalParameterList list = parser.parseFormalParameterList(); |
| expectNotNullIfNoErrors(list); |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.wrongSeparatorForPositionalParameter, 7, 1), |
| ]); |
| } |
| |
| void test_wrongTerminatorForParameterGroup_named() { |
| createParser('(a, {b, c])'); |
| FormalParameterList list = parser.parseFormalParameterList(); |
| expectNotNullIfNoErrors(list); |
| // fasta scanner generates '(a, {b, c]})' where '}' is synthetic |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.expectedToken, 9, 1), |
| expectedError(ScannerErrorCode.expectedToken, 10, 1), |
| ]); |
| } |
| |
| void test_wrongTerminatorForParameterGroup_optional() { |
| createParser('(a, [b, c})'); |
| FormalParameterList list = parser.parseFormalParameterList(); |
| expectNotNullIfNoErrors(list); |
| // fasta scanner generates '(a, [b, c}])' where ']' is synthetic |
| listener.assertErrors([ |
| expectedError(ParserErrorCode.expectedToken, 9, 1), |
| expectedError(ScannerErrorCode.expectedToken, 10, 1), |
| ]); |
| } |
| |
| void test_yieldAsLabel() { |
| // yield can be used as a label |
| parseCompilationUnit('main() { yield: break yield; }'); |
| } |
| } |