| // 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:analyzer/dart/ast/ast.dart'; |
| import 'package:analyzer/dart/ast/token.dart'; |
| import 'package:analyzer/src/dart/ast/ast.dart'; |
| import 'package:analyzer/src/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 'parser_test_base.dart'; |
| |
| main() { |
| defineReflectiveSuite(() { |
| defineReflectiveTests(SimpleParserTest); |
| }); |
| } |
| |
| /// Parser tests that test individual parsing methods. The code fragments should |
| /// be as minimal as possible in order to test the method, but should not test |
| /// the interactions between the method under test and other methods. |
| /// |
| /// More complex tests should be defined in the class [ComplexParserTest]. |
| @reflectiveTest |
| class SimpleParserTest extends FastaParserTestCase { |
| ConstructorName parseConstructorName(String name) { |
| createParser('new $name();'); |
| Statement statement = parser.parseStatement2(); |
| expect(statement, isExpressionStatement); |
| Expression expression = (statement as ExpressionStatement).expression; |
| expect(expression, isInstanceCreationExpression); |
| return (expression as InstanceCreationExpression).constructorName; |
| } |
| |
| ExtendsClause parseExtendsClause(String clause) { |
| createParser('class TestClass $clause {}'); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expect(unit, isNotNull); |
| expect(unit.declarations, hasLength(1)); |
| var classDecl = unit.declarations[0] as ClassDeclaration; |
| expect(classDecl, isNotNull); |
| return classDecl.extendsClause!; |
| } |
| |
| List<SimpleIdentifier> parseIdentifierList(String identifiers) { |
| createParser('show $identifiers'); |
| List<Combinator> combinators = parser.parseCombinators(); |
| expect(combinators, hasLength(1)); |
| return (combinators[0] as ShowCombinator).shownNames; |
| } |
| |
| ImplementsClause parseImplementsClause(String clause) { |
| createParser('class TestClass $clause {}'); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expect(unit, isNotNull); |
| expect(unit.declarations, hasLength(1)); |
| var classDecl = unit.declarations[0] as ClassDeclaration; |
| expect(classDecl, isNotNull); |
| return classDecl.implementsClause!; |
| } |
| |
| LibraryIdentifier parseLibraryIdentifier(String name) { |
| createParser('library $name;'); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expect(unit, isNotNull); |
| expect(unit.directives, hasLength(1)); |
| var directive = unit.directives[0] as LibraryDirective; |
| return directive.name; |
| } |
| |
| /// Parse the given [content] as a sequence of statements by enclosing it in a |
| /// block. The [expectedCount] is the number of statements that are expected |
| /// to be parsed. If [errorCodes] are provided, verify that the error codes of |
| /// the errors that are expected are found. |
| void parseStatementList(String content, int expectedCount) { |
| Statement statement = parseStatement('{$content}'); |
| expect(statement, isBlock); |
| var block = statement as Block; |
| expect(block.statements, hasLength(expectedCount)); |
| } |
| |
| VariableDeclaration parseVariableDeclaration(String declaration) { |
| createParser(declaration); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expect(unit, isNotNull); |
| expect(unit.declarations, hasLength(1)); |
| var decl = unit.declarations[0] as TopLevelVariableDeclaration; |
| expect(decl, isNotNull); |
| return decl.variables.variables[0]; |
| } |
| |
| WithClause parseWithClause(String clause) { |
| createParser('class TestClass extends Object $clause {}'); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expect(unit, isNotNull); |
| expect(unit.declarations, hasLength(1)); |
| var classDecl = unit.declarations[0] as ClassDeclaration; |
| expect(classDecl, isNotNull); |
| return classDecl.withClause!; |
| } |
| |
| void test_classDeclaration_complexTypeParam() { |
| CompilationUnit unit = parseCompilationUnit(''' |
| class C<@Foo.bar(const [], const [1], const{"":r""}, 0xFF + 2, .3, 4.5) T> {} |
| '''); |
| var clazz = unit.declarations[0] as ClassDeclaration; |
| expect(clazz.name.name, 'C'); |
| expect(clazz.typeParameters!.typeParameters, hasLength(1)); |
| TypeParameter typeParameter = clazz.typeParameters!.typeParameters[0]; |
| expect(typeParameter.name.name, 'T'); |
| expect(typeParameter.metadata, hasLength(1)); |
| Annotation metadata = typeParameter.metadata[0]; |
| expect(metadata.name.name, 'Foo.bar'); |
| } |
| |
| void test_classDeclaration_invalid_super() { |
| parseCompilationUnit(''' |
| class C { |
| C() : super.const(); |
| } |
| ''', errors: [ |
| expectedError(ParserErrorCode.INVALID_SUPER_IN_INITIALIZER, 18, 5), |
| expectedError(ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 24, 5), |
| expectedError(ParserErrorCode.MISSING_IDENTIFIER, 24, 5), |
| expectedError(ParserErrorCode.MISSING_IDENTIFIER, 29, 1), |
| ]); |
| } |
| |
| void test_classDeclaration_invalid_this() { |
| parseCompilationUnit(''' |
| class C { |
| C() : this.const(); |
| } |
| ''', errors: [ |
| expectedError(ParserErrorCode.MISSING_ASSIGNMENT_IN_INITIALIZER, 18, 4), |
| expectedError(ParserErrorCode.MISSING_IDENTIFIER, 23, 5), |
| expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 23, 5), |
| expectedError(ParserErrorCode.CONST_METHOD, 23, 5), |
| expectedError(ParserErrorCode.MISSING_IDENTIFIER, 28, 1), |
| ]); |
| } |
| |
| void test_method_name_notNull_37733() { |
| // https://github.com/dart-lang/sdk/issues/37733 |
| var unit = parseCompilationUnit(r'class C { f(<T>()); }', errors: [ |
| expectedError(ParserErrorCode.MISSING_IDENTIFIER, 12, 1), |
| ]); |
| var classDeclaration = unit.declarations[0] as ClassDeclaration; |
| var method = classDeclaration.members[0] as MethodDeclaration; |
| expect(method.parameters!.parameters, hasLength(1)); |
| var parameter = |
| method.parameters!.parameters[0] as FunctionTypedFormalParameter; |
| expect(parameter.identifier, isNotNull); |
| } |
| |
| void test_parseAnnotation_n1() { |
| createParser('@A'); |
| Annotation annotation = parser.parseAnnotation(); |
| expectNotNullIfNoErrors(annotation); |
| assertNoErrors(); |
| expect(annotation.atSign, isNotNull); |
| expect(annotation.name, isNotNull); |
| expect(annotation.period, isNull); |
| expect(annotation.constructorName, isNull); |
| expect(annotation.arguments, isNull); |
| } |
| |
| void test_parseAnnotation_n1_a() { |
| createParser('@A(x,y)'); |
| Annotation annotation = parser.parseAnnotation(); |
| expectNotNullIfNoErrors(annotation); |
| assertNoErrors(); |
| expect(annotation.atSign, isNotNull); |
| expect(annotation.name, isNotNull); |
| expect(annotation.period, isNull); |
| expect(annotation.constructorName, isNull); |
| expect(annotation.arguments, isNotNull); |
| } |
| |
| void test_parseAnnotation_n2() { |
| createParser('@A.B'); |
| Annotation annotation = parser.parseAnnotation(); |
| expectNotNullIfNoErrors(annotation); |
| assertNoErrors(); |
| expect(annotation.atSign, isNotNull); |
| expect(annotation.name, isNotNull); |
| expect(annotation.period, isNull); |
| expect(annotation.constructorName, isNull); |
| expect(annotation.arguments, isNull); |
| } |
| |
| void test_parseAnnotation_n2_a() { |
| createParser('@A.B(x,y)'); |
| Annotation annotation = parser.parseAnnotation(); |
| expectNotNullIfNoErrors(annotation); |
| assertNoErrors(); |
| expect(annotation.atSign, isNotNull); |
| expect(annotation.name, isNotNull); |
| expect(annotation.period, isNull); |
| expect(annotation.constructorName, isNull); |
| expect(annotation.arguments, isNotNull); |
| } |
| |
| void test_parseAnnotation_n3() { |
| createParser('@A.B.C'); |
| Annotation annotation = parser.parseAnnotation(); |
| expectNotNullIfNoErrors(annotation); |
| assertNoErrors(); |
| expect(annotation.atSign, isNotNull); |
| expect(annotation.name, isNotNull); |
| expect(annotation.period, isNotNull); |
| expect(annotation.constructorName, isNotNull); |
| expect(annotation.arguments, isNull); |
| } |
| |
| void test_parseAnnotation_n3_a() { |
| createParser('@A.B.C(x,y)'); |
| Annotation annotation = parser.parseAnnotation(); |
| expectNotNullIfNoErrors(annotation); |
| assertNoErrors(); |
| expect(annotation.atSign, isNotNull); |
| expect(annotation.name, isNotNull); |
| expect(annotation.period, isNotNull); |
| expect(annotation.constructorName, isNotNull); |
| expect(annotation.arguments, isNotNull); |
| } |
| |
| test_parseArgument() { |
| Expression result = parseArgument('3'); |
| expect(result, const TypeMatcher<IntegerLiteral>()); |
| var literal = result as IntegerLiteral; |
| expect(literal.value, 3); |
| } |
| |
| test_parseArgument_named() { |
| Expression result = parseArgument('foo: "a"'); |
| expect(result, const TypeMatcher<NamedExpression>()); |
| var expression = result as NamedExpression; |
| var literal = expression.expression as StringLiteral; |
| expect(literal.stringValue, 'a'); |
| } |
| |
| void test_parseArgumentList_empty() { |
| createParser('()'); |
| ArgumentList argumentList = parser.parseArgumentList(); |
| expectNotNullIfNoErrors(argumentList); |
| assertNoErrors(); |
| NodeList<Expression> arguments = argumentList.arguments; |
| expect(arguments, hasLength(0)); |
| } |
| |
| void test_parseArgumentList_mixed() { |
| createParser('(w, x, y: y, z: z)'); |
| ArgumentList argumentList = parser.parseArgumentList(); |
| expectNotNullIfNoErrors(argumentList); |
| assertNoErrors(); |
| NodeList<Expression> arguments = argumentList.arguments; |
| expect(arguments, hasLength(4)); |
| } |
| |
| void test_parseArgumentList_noNamed() { |
| createParser('(x, y, z)'); |
| ArgumentList argumentList = parser.parseArgumentList(); |
| expectNotNullIfNoErrors(argumentList); |
| assertNoErrors(); |
| NodeList<Expression> arguments = argumentList.arguments; |
| expect(arguments, hasLength(3)); |
| } |
| |
| void test_parseArgumentList_onlyNamed() { |
| createParser('(x: x, y: y)'); |
| ArgumentList argumentList = parser.parseArgumentList(); |
| expectNotNullIfNoErrors(argumentList); |
| assertNoErrors(); |
| NodeList<Expression> arguments = argumentList.arguments; |
| expect(arguments, hasLength(2)); |
| } |
| |
| void test_parseArgumentList_trailing_comma() { |
| createParser('(x, y, z,)'); |
| ArgumentList argumentList = parser.parseArgumentList(); |
| expectNotNullIfNoErrors(argumentList); |
| assertNoErrors(); |
| NodeList<Expression> arguments = argumentList.arguments; |
| expect(arguments, hasLength(3)); |
| } |
| |
| void test_parseArgumentList_typeArguments() { |
| createParser('(a<b,c>(d))'); |
| ArgumentList argumentList = parser.parseArgumentList(); |
| expectNotNullIfNoErrors(argumentList); |
| assertNoErrors(); |
| NodeList<Expression> arguments = argumentList.arguments; |
| expect(arguments, hasLength(1)); |
| } |
| |
| void test_parseArgumentList_typeArguments_none() { |
| createParser('(a<b,p.q.c>(d))'); |
| ArgumentList argumentList = parser.parseArgumentList(); |
| expectNotNullIfNoErrors(argumentList); |
| assertNoErrors(); |
| NodeList<Expression> arguments = argumentList.arguments; |
| expect(arguments, hasLength(2)); |
| } |
| |
| void test_parseArgumentList_typeArguments_prefixed() { |
| createParser('(a<b,p.c>(d))'); |
| ArgumentList argumentList = parser.parseArgumentList(); |
| expectNotNullIfNoErrors(argumentList); |
| assertNoErrors(); |
| NodeList<Expression> arguments = argumentList.arguments; |
| expect(arguments, hasLength(1)); |
| } |
| |
| void test_parseCombinators_h() { |
| createParser('hide a'); |
| List<Combinator> combinators = parser.parseCombinators(); |
| expectNotNullIfNoErrors(combinators); |
| assertNoErrors(); |
| expect(combinators, hasLength(1)); |
| HideCombinator combinator = combinators[0] as HideCombinator; |
| expect(combinator, isNotNull); |
| expect(combinator.keyword, isNotNull); |
| expect(combinator.hiddenNames, hasLength(1)); |
| } |
| |
| void test_parseCombinators_hs() { |
| createParser('hide a show b'); |
| List<Combinator> combinators = parser.parseCombinators(); |
| expectNotNullIfNoErrors(combinators); |
| assertNoErrors(); |
| expect(combinators, hasLength(2)); |
| HideCombinator hideCombinator = combinators[0] as HideCombinator; |
| expect(hideCombinator, isNotNull); |
| expect(hideCombinator.keyword, isNotNull); |
| expect(hideCombinator.hiddenNames, hasLength(1)); |
| ShowCombinator showCombinator = combinators[1] as ShowCombinator; |
| expect(showCombinator, isNotNull); |
| expect(showCombinator.keyword, isNotNull); |
| expect(showCombinator.shownNames, hasLength(1)); |
| } |
| |
| void test_parseCombinators_hshs() { |
| createParser('hide a show b hide c show d'); |
| List<Combinator> combinators = parser.parseCombinators(); |
| expectNotNullIfNoErrors(combinators); |
| assertNoErrors(); |
| expect(combinators, hasLength(4)); |
| } |
| |
| void test_parseCombinators_s() { |
| createParser('show a'); |
| List<Combinator> combinators = parser.parseCombinators(); |
| expectNotNullIfNoErrors(combinators); |
| assertNoErrors(); |
| expect(combinators, hasLength(1)); |
| ShowCombinator combinator = combinators[0] as ShowCombinator; |
| expect(combinator, isNotNull); |
| expect(combinator.keyword, isNotNull); |
| expect(combinator.shownNames, hasLength(1)); |
| } |
| |
| void test_parseCommentAndMetadata_c() { |
| createParser('/** 1 */ class C {}'); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expectNotNullIfNoErrors(unit); |
| assertNoErrors(); |
| var declaration = unit.declarations[0] as ClassDeclaration; |
| expect(declaration.documentationComment, isNotNull); |
| expect(declaration.metadata, isEmpty); |
| } |
| |
| void test_parseCommentAndMetadata_cmc() { |
| createParser('/** 1 */ @A /** 2 */ class C {}'); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expectNotNullIfNoErrors(unit); |
| assertNoErrors(); |
| var declaration = unit.declarations[0] as ClassDeclaration; |
| Comment comment = declaration.documentationComment!; |
| expect(comment.isDocumentation, isTrue); |
| expect(comment.tokens, hasLength(1)); |
| expect(comment.tokens[0].lexeme, '/** 2 */'); |
| expect(declaration.metadata, hasLength(1)); |
| } |
| |
| void test_parseCommentAndMetadata_cmcm() { |
| createParser('/** 1 */ @A /** 2 */ @B class C {}'); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expectNotNullIfNoErrors(unit); |
| assertNoErrors(); |
| var declaration = unit.declarations[0] as ClassDeclaration; |
| expect(declaration.documentationComment, isNotNull); |
| expect(declaration.metadata, hasLength(2)); |
| } |
| |
| void test_parseCommentAndMetadata_cmm() { |
| createParser('/** 1 */ @A @B class C {}'); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expectNotNullIfNoErrors(unit); |
| assertNoErrors(); |
| var declaration = unit.declarations[0] as ClassDeclaration; |
| expect(declaration.documentationComment, isNotNull); |
| expect(declaration.metadata, hasLength(2)); |
| } |
| |
| void test_parseCommentAndMetadata_m() { |
| createParser('@A class C {}'); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expectNotNullIfNoErrors(unit); |
| assertNoErrors(); |
| var declaration = unit.declarations[0] as ClassDeclaration; |
| expect(declaration.documentationComment, isNull); |
| expect(declaration.metadata, hasLength(1)); |
| } |
| |
| void test_parseCommentAndMetadata_mcm() { |
| createParser('@A /** 1 */ @B class C {}'); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expectNotNullIfNoErrors(unit); |
| assertNoErrors(); |
| var declaration = unit.declarations[0] as ClassDeclaration; |
| expect(declaration.documentationComment, isNotNull); |
| expect(declaration.metadata, hasLength(2)); |
| } |
| |
| void test_parseCommentAndMetadata_mcmc() { |
| createParser('@A /** 1 */ @B /** 2 */ class C {}'); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expectNotNullIfNoErrors(unit); |
| assertNoErrors(); |
| var declaration = unit.declarations[0] as ClassDeclaration; |
| expect(declaration.documentationComment, isNotNull); |
| expect(declaration.documentationComment!.tokens[0].lexeme, contains('2')); |
| expect(declaration.metadata, hasLength(2)); |
| } |
| |
| void test_parseCommentAndMetadata_mix1() { |
| createParser(r''' |
| /** |
| * aaa |
| */ |
| /** |
| * bbb |
| */ |
| class A {} |
| '''); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expectNotNullIfNoErrors(unit); |
| assertNoErrors(); |
| var declaration = unit.declarations[0] as ClassDeclaration; |
| expect(declaration.metadata, hasLength(0)); |
| List<Token> tokens = declaration.documentationComment!.tokens; |
| expect(tokens, hasLength(1)); |
| expect(tokens[0].lexeme, contains('bbb')); |
| } |
| |
| void test_parseCommentAndMetadata_mix2() { |
| createParser(r''' |
| /** |
| * aaa |
| */ |
| /// bbb |
| /// ccc |
| class B {} |
| '''); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expectNotNullIfNoErrors(unit); |
| assertNoErrors(); |
| var declaration = unit.declarations[0] as ClassDeclaration; |
| expect(declaration.metadata, hasLength(0)); |
| List<Token> tokens = declaration.documentationComment!.tokens; |
| expect(tokens, hasLength(2)); |
| expect(tokens[0].lexeme, contains('bbb')); |
| expect(tokens[1].lexeme, contains('ccc')); |
| } |
| |
| void test_parseCommentAndMetadata_mix3() { |
| createParser(r''' |
| /// aaa |
| /// bbb |
| /** |
| * ccc |
| */ |
| class C {} |
| '''); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expectNotNullIfNoErrors(unit); |
| assertNoErrors(); |
| var declaration = unit.declarations[0] as ClassDeclaration; |
| expect(declaration.metadata, hasLength(0)); |
| List<Token> tokens = declaration.documentationComment!.tokens; |
| expect(tokens, hasLength(1)); |
| expect(tokens[0].lexeme, contains('ccc')); |
| } |
| |
| test_parseCommentAndMetadata_mix4() { |
| createParser(r''' |
| /// aaa |
| /// bbb |
| /** |
| * ccc |
| */ |
| /// ddd |
| class D {} |
| '''); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expectNotNullIfNoErrors(unit); |
| assertNoErrors(); |
| var declaration = unit.declarations[0] as ClassDeclaration; |
| expect(declaration.metadata, hasLength(0)); |
| List<Token> tokens = declaration.documentationComment!.tokens; |
| expect(tokens, hasLength(1)); |
| expect(tokens[0].lexeme, contains('ddd')); |
| } |
| |
| test_parseCommentAndMetadata_mix5() { |
| createParser(r''' |
| /** |
| * aaa |
| */ |
| // bbb |
| class E {} |
| '''); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expectNotNullIfNoErrors(unit); |
| assertNoErrors(); |
| var declaration = unit.declarations[0] as ClassDeclaration; |
| expect(declaration.metadata, hasLength(0)); |
| List<Token> tokens = declaration.documentationComment!.tokens; |
| expect(tokens, hasLength(1)); |
| expect(tokens[0].lexeme, contains('aaa')); |
| } |
| |
| void test_parseCommentAndMetadata_mm() { |
| createParser('@A @B(x) class C {}'); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expectNotNullIfNoErrors(unit); |
| assertNoErrors(); |
| var declaration = unit.declarations[0] as ClassDeclaration; |
| expect(declaration.documentationComment, isNull); |
| expect(declaration.metadata, hasLength(2)); |
| } |
| |
| void test_parseCommentAndMetadata_none() { |
| createParser('class C {}'); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expectNotNullIfNoErrors(unit); |
| assertNoErrors(); |
| var declaration = unit.declarations[0] as ClassDeclaration; |
| expect(declaration.documentationComment, isNull); |
| expect(declaration.metadata, isEmpty); |
| } |
| |
| void test_parseCommentAndMetadata_singleLine() { |
| createParser(r''' |
| /// 1 |
| /// 2 |
| class C {} |
| '''); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expectNotNullIfNoErrors(unit); |
| assertNoErrors(); |
| var declaration = unit.declarations[0] as ClassDeclaration; |
| expect(declaration.documentationComment, isNotNull); |
| expect(declaration.metadata, isEmpty); |
| } |
| |
| void test_parseCommentReference_new_prefixed() { |
| createParser(''); |
| var reference = parseCommentReference('new a.b', 7)!; |
| expectNotNullIfNoErrors(reference); |
| assertNoErrors(); |
| expect(reference.expression, isPrefixedIdentifier); |
| var prefixedIdentifier = reference.expression as PrefixedIdentifier; |
| SimpleIdentifier prefix = prefixedIdentifier.prefix; |
| expect(prefix.token, isNotNull); |
| expect(prefix.name, "a"); |
| expect(prefix.offset, 11); |
| expect(prefixedIdentifier.period, isNotNull); |
| SimpleIdentifier identifier = prefixedIdentifier.identifier; |
| expect(identifier.token, isNotNull); |
| expect(identifier.name, "b"); |
| expect(identifier.offset, 13); |
| } |
| |
| void test_parseCommentReference_new_simple() { |
| createParser(''); |
| var reference = parseCommentReference('new a', 5)!; |
| expectNotNullIfNoErrors(reference); |
| assertNoErrors(); |
| expect(reference.expression, isSimpleIdentifier); |
| var identifier = reference.expression as SimpleIdentifier; |
| expect(identifier.token, isNotNull); |
| expect(identifier.name, "a"); |
| expect(identifier.offset, 9); |
| } |
| |
| void test_parseCommentReference_operator_withKeyword_notPrefixed() { |
| createParser(''); |
| var reference = parseCommentReference('operator ==', 5)!; |
| expectNotNullIfNoErrors(reference); |
| assertNoErrors(); |
| expect(reference.expression, isSimpleIdentifier); |
| var identifier = reference.expression as SimpleIdentifier; |
| expect(identifier.token, isNotNull); |
| expect(identifier.name, "=="); |
| expect(identifier.offset, 14); |
| } |
| |
| void test_parseCommentReference_operator_withKeyword_prefixed() { |
| createParser(''); |
| var reference = parseCommentReference('Object.operator==', 7)!; |
| expectNotNullIfNoErrors(reference); |
| assertNoErrors(); |
| expect(reference.expression, isPrefixedIdentifier); |
| var prefixedIdentifier = reference.expression as PrefixedIdentifier; |
| SimpleIdentifier prefix = prefixedIdentifier.prefix; |
| expect(prefix.token, isNotNull); |
| expect(prefix.name, "Object"); |
| expect(prefix.offset, 7); |
| expect(prefixedIdentifier.period, isNotNull); |
| SimpleIdentifier identifier = prefixedIdentifier.identifier; |
| expect(identifier.token, isNotNull); |
| expect(identifier.name, "=="); |
| expect(identifier.offset, 22); |
| } |
| |
| void test_parseCommentReference_operator_withoutKeyword_notPrefixed() { |
| createParser(''); |
| var reference = parseCommentReference('==', 5)!; |
| expectNotNullIfNoErrors(reference); |
| assertNoErrors(); |
| expect(reference.expression, isSimpleIdentifier); |
| var identifier = reference.expression as SimpleIdentifier; |
| expect(identifier.token, isNotNull); |
| expect(identifier.name, "=="); |
| expect(identifier.offset, 5); |
| } |
| |
| void test_parseCommentReference_operator_withoutKeyword_prefixed() { |
| createParser(''); |
| var reference = parseCommentReference('Object.==', 7)!; |
| expectNotNullIfNoErrors(reference); |
| assertNoErrors(); |
| expect(reference.expression, isPrefixedIdentifier); |
| var prefixedIdentifier = reference.expression as PrefixedIdentifier; |
| SimpleIdentifier prefix = prefixedIdentifier.prefix; |
| expect(prefix.token, isNotNull); |
| expect(prefix.name, "Object"); |
| expect(prefix.offset, 7); |
| expect(prefixedIdentifier.period, isNotNull); |
| SimpleIdentifier identifier = prefixedIdentifier.identifier; |
| expect(identifier.token, isNotNull); |
| expect(identifier.name, "=="); |
| expect(identifier.offset, 14); |
| } |
| |
| void test_parseCommentReference_prefixed() { |
| createParser(''); |
| var reference = parseCommentReference('a.b', 7)!; |
| expectNotNullIfNoErrors(reference); |
| assertNoErrors(); |
| expect(reference.expression, isPrefixedIdentifier); |
| var prefixedIdentifier = reference.expression as PrefixedIdentifier; |
| SimpleIdentifier prefix = prefixedIdentifier.prefix; |
| expect(prefix.token, isNotNull); |
| expect(prefix.name, "a"); |
| expect(prefix.offset, 7); |
| expect(prefixedIdentifier.period, isNotNull); |
| SimpleIdentifier identifier = prefixedIdentifier.identifier; |
| expect(identifier.token, isNotNull); |
| expect(identifier.name, "b"); |
| expect(identifier.offset, 9); |
| } |
| |
| void test_parseCommentReference_simple() { |
| createParser(''); |
| var reference = parseCommentReference('a', 5)!; |
| expectNotNullIfNoErrors(reference); |
| assertNoErrors(); |
| expect(reference.expression, isSimpleIdentifier); |
| var identifier = reference.expression as SimpleIdentifier; |
| expect(identifier.token, isNotNull); |
| expect(identifier.name, "a"); |
| expect(identifier.offset, 5); |
| } |
| |
| void test_parseCommentReference_synthetic() { |
| createParser(''); |
| var reference = parseCommentReference('', 5)!; |
| expectNotNullIfNoErrors(reference); |
| assertNoErrors(); |
| expect(reference.expression, isSimpleIdentifier); |
| var identifier = reference.expression as SimpleIdentifier; |
| expect(identifier, isNotNull); |
| expect(identifier.isSynthetic, isTrue); |
| expect(identifier.token, isNotNull); |
| expect(identifier.name, ""); |
| expect(identifier.offset, 5); |
| // Should end with EOF token. |
| Token nextToken = identifier.token.next!; |
| expect(nextToken, isNotNull); |
| expect(nextToken.type, TokenType.EOF); |
| } |
| |
| @failingTest |
| void test_parseCommentReference_this() { |
| // This fails because we are returning null from the method and asserting |
| // that the return value is not null. |
| createParser(''); |
| var reference = parseCommentReference('this', 5)!; |
| expectNotNullIfNoErrors(reference); |
| assertNoErrors(); |
| var identifier = reference.expression as SimpleIdentifier; |
| expect(identifier.token, isNotNull); |
| expect(identifier.name, "a"); |
| expect(identifier.offset, 5); |
| } |
| |
| void test_parseCommentReferences_33738() { |
| CompilationUnit unit = |
| parseCompilationUnit('/** [String] */ abstract class Foo {}'); |
| var clazz = unit.declarations[0] as ClassDeclaration; |
| Comment comment = clazz.documentationComment!; |
| expect(clazz.isAbstract, isTrue); |
| List<CommentReference> references = comment.references; |
| expect(references, hasLength(1)); |
| CommentReference reference = references[0]; |
| expect(reference, isNotNull); |
| expect(reference.expression, isNotNull); |
| expect(reference.offset, 5); |
| } |
| |
| void test_parseCommentReferences_beforeAnnotation() { |
| CompilationUnit unit = parseCompilationUnit(''' |
| /// See [int] and [String] |
| /// and [Object]. |
| @Annotation |
| abstract class Foo {} |
| '''); |
| var clazz = unit.declarations[0] as ClassDeclaration; |
| Comment comment = clazz.documentationComment!; |
| expect(clazz.isAbstract, isTrue); |
| List<CommentReference> references = comment.references; |
| expect(references, hasLength(3)); |
| |
| expectReference(int index, String expectedText, int expectedOffset) { |
| CommentReference reference = references[index]; |
| var identifier = reference.expression as Identifier; |
| expect(identifier.name, expectedText); |
| expect(reference.offset, expectedOffset); |
| } |
| |
| expectReference(0, 'int', 9); |
| expectReference(1, 'String', 19); |
| expectReference(2, 'Object', 36); |
| } |
| |
| void test_parseCommentReferences_complex() { |
| CompilationUnit unit = parseCompilationUnit(''' |
| /// This dartdoc comment [should] be ignored |
| @Annotation |
| /// This dartdoc comment is [included]. |
| // a non dartdoc comment [inbetween] |
| /// See [int] and [String] but `not [a]` |
| /// ``` |
| /// This [code] block should be ignored |
| /// ``` |
| /// and [Object]. |
| abstract class Foo {} |
| '''); |
| var clazz = unit.declarations[0] as ClassDeclaration; |
| Comment comment = clazz.documentationComment!; |
| expect(clazz.isAbstract, isTrue); |
| List<CommentReference> references = comment.references; |
| expect(references, hasLength(4)); |
| |
| expectReference(int index, String expectedText, int expectedOffset) { |
| CommentReference reference = references[index]; |
| var identifier = reference.expression as Identifier; |
| expect(identifier.name, expectedText); |
| expect(reference.offset, expectedOffset); |
| } |
| |
| expectReference(0, 'included', 86); |
| expectReference(1, 'int', 143); |
| expectReference(2, 'String', 153); |
| expectReference(3, 'Object', 240); |
| } |
| |
| void test_parseCommentReferences_multiLine() { |
| DocumentationCommentToken token = DocumentationCommentToken( |
| TokenType.MULTI_LINE_COMMENT, "/** xxx [a] yyy [bb] zzz */", 3); |
| List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[token]; |
| createParser(''); |
| List<CommentReference> references = parser.parseCommentReferences(tokens); |
| expectNotNullIfNoErrors(references); |
| assertNoErrors(); |
| expect(references, hasLength(2)); |
| { |
| CommentReference reference = references[0]; |
| expect(reference, isNotNull); |
| expect(reference.expression, isNotNull); |
| expect(reference.offset, 12); |
| Token referenceToken = reference.expression.beginToken; |
| expect(referenceToken.offset, 12); |
| expect(referenceToken.lexeme, 'a'); |
| } |
| { |
| CommentReference reference = references[1]; |
| expect(reference, isNotNull); |
| expect(reference.expression, isNotNull); |
| expect(reference.offset, 20); |
| Token referenceToken = reference.expression.beginToken; |
| expect(referenceToken.offset, 20); |
| expect(referenceToken.lexeme, 'bb'); |
| } |
| } |
| |
| void test_parseCommentReferences_notClosed_noIdentifier() { |
| DocumentationCommentToken docToken = DocumentationCommentToken( |
| TokenType.MULTI_LINE_COMMENT, "/** [ some text", 5); |
| createParser(''); |
| List<CommentReference> references = |
| parser.parseCommentReferences(<DocumentationCommentToken>[docToken]); |
| expectNotNullIfNoErrors(references); |
| assertNoErrors(); |
| expect(references, hasLength(1)); |
| CommentReference reference = references[0]; |
| Token referenceToken = reference.expression.beginToken; |
| expect(reference, isNotNull); |
| expect(reference.expression, isNotNull); |
| var identifier = reference.expression as Identifier; |
| expect(identifier.isSynthetic, isTrue); |
| expect(identifier.name, ""); |
| // Should end with EOF token. |
| Token nextToken = referenceToken.next!; |
| expect(nextToken, isNotNull); |
| expect(nextToken.type, TokenType.EOF); |
| } |
| |
| void test_parseCommentReferences_notClosed_withIdentifier() { |
| DocumentationCommentToken docToken = DocumentationCommentToken( |
| TokenType.MULTI_LINE_COMMENT, "/** [namePrefix some text", 5); |
| createParser(''); |
| List<CommentReference> references = |
| parser.parseCommentReferences(<DocumentationCommentToken>[docToken]); |
| expectNotNullIfNoErrors(references); |
| assertNoErrors(); |
| expect(references, hasLength(1)); |
| CommentReference reference = references[0]; |
| Token referenceToken = reference.expression.beginToken; |
| expect(reference, isNotNull); |
| expect(referenceToken, same(reference.beginToken)); |
| expect(reference.expression, isNotNull); |
| var identifier = reference.expression as Identifier; |
| expect(identifier.isSynthetic, isFalse); |
| expect(identifier.name, "namePrefix"); |
| // Should end with EOF token. |
| Token nextToken = referenceToken.next!; |
| expect(nextToken, isNotNull); |
| expect(nextToken.type, TokenType.EOF); |
| } |
| |
| void test_parseCommentReferences_singleLine() { |
| List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[ |
| DocumentationCommentToken( |
| TokenType.SINGLE_LINE_COMMENT, "/// xxx [a] yyy [b] zzz", 3), |
| DocumentationCommentToken(TokenType.SINGLE_LINE_COMMENT, "/// x [c]", 28) |
| ]; |
| createParser(''); |
| List<CommentReference> references = parser.parseCommentReferences(tokens); |
| expectNotNullIfNoErrors(references); |
| assertNoErrors(); |
| expect(references, hasLength(3)); |
| CommentReference reference = references[0]; |
| expect(reference, isNotNull); |
| expect(reference.expression, isNotNull); |
| expect(reference.offset, 12); |
| reference = references[1]; |
| expect(reference, isNotNull); |
| expect(reference.expression, isNotNull); |
| expect(reference.offset, 20); |
| reference = references[2]; |
| expect(reference, isNotNull); |
| expect(reference.expression, isNotNull); |
| expect(reference.offset, 35); |
| } |
| |
| void test_parseCommentReferences_skipCodeBlock_4spaces_block() { |
| List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[ |
| DocumentationCommentToken(TokenType.MULTI_LINE_COMMENT, |
| "/**\n * a[i]\n * non-code line\n */", 3) |
| ]; |
| createParser(''); |
| List<CommentReference> references = parser.parseCommentReferences(tokens); |
| expectNotNullIfNoErrors(references); |
| assertNoErrors(); |
| expect(references, isEmpty); |
| } |
| |
| void test_parseCommentReferences_skipCodeBlock_4spaces_lines() { |
| List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[ |
| DocumentationCommentToken( |
| TokenType.SINGLE_LINE_COMMENT, "/// Code block:", 0), |
| DocumentationCommentToken( |
| TokenType.SINGLE_LINE_COMMENT, "/// a[i] == b[i]", 0) |
| ]; |
| createParser(''); |
| List<CommentReference> references = parser.parseCommentReferences(tokens); |
| expectNotNullIfNoErrors(references); |
| assertNoErrors(); |
| expect(references, isEmpty); |
| } |
| |
| void test_parseCommentReferences_skipCodeBlock_bracketed() { |
| List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[ |
| DocumentationCommentToken( |
| TokenType.MULTI_LINE_COMMENT, "/** [:xxx [a] yyy:] [b] zzz */", 3) |
| ]; |
| createParser(''); |
| List<CommentReference> references = parser.parseCommentReferences(tokens); |
| expectNotNullIfNoErrors(references); |
| assertNoErrors(); |
| expect(references, hasLength(1)); |
| CommentReference reference = references[0]; |
| expect(reference, isNotNull); |
| expect(reference.expression, isNotNull); |
| expect(reference.offset, 24); |
| } |
| |
| void test_parseCommentReferences_skipCodeBlock_gitHub() { |
| List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[ |
| DocumentationCommentToken( |
| TokenType.MULTI_LINE_COMMENT, "/** `a[i]` and [b] */", 0) |
| ]; |
| createParser(''); |
| List<CommentReference> references = parser.parseCommentReferences(tokens); |
| expectNotNullIfNoErrors(references); |
| assertNoErrors(); |
| expect(references, hasLength(1)); |
| CommentReference reference = references[0]; |
| expect(reference, isNotNull); |
| expect(reference.expression, isNotNull); |
| expect(reference.offset, 16); |
| } |
| |
| void test_parseCommentReferences_skipCodeBlock_gitHub_multiLine() { |
| List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[ |
| DocumentationCommentToken( |
| TokenType.MULTI_LINE_COMMENT, |
| r''' |
| /** |
| * First. |
| * ```dart |
| * Some [int] reference. |
| * ``` |
| * Last. |
| */ |
| ''', |
| 3) |
| ]; |
| createParser(''); |
| List<CommentReference> references = parser.parseCommentReferences(tokens); |
| expectNotNullIfNoErrors(references); |
| assertNoErrors(); |
| expect(references, isEmpty); |
| } |
| |
| void test_parseCommentReferences_skipCodeBlock_gitHub_multiLine_lines() { |
| String commentText = r''' |
| /// First. |
| /// ```dart |
| /// Some [int] reference. |
| /// ``` |
| /// Last. |
| '''; |
| List<DocumentationCommentToken> tokens = commentText |
| .split('\n') |
| .map((line) => |
| DocumentationCommentToken(TokenType.SINGLE_LINE_COMMENT, line, 0)) |
| .toList(); |
| createParser(''); |
| List<CommentReference> references = parser.parseCommentReferences(tokens); |
| expectNotNullIfNoErrors(references); |
| assertNoErrors(); |
| expect(references, isEmpty); |
| } |
| |
| void test_parseCommentReferences_skipCodeBlock_gitHub_notTerminated() { |
| List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[ |
| DocumentationCommentToken( |
| TokenType.MULTI_LINE_COMMENT, "/** `a[i] and [b] */", 0) |
| ]; |
| createParser(''); |
| List<CommentReference> references = parser.parseCommentReferences(tokens); |
| expectNotNullIfNoErrors(references); |
| assertNoErrors(); |
| expect(references, hasLength(2)); |
| } |
| |
| void test_parseCommentReferences_skipCodeBlock_spaces() { |
| List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[ |
| DocumentationCommentToken(TokenType.MULTI_LINE_COMMENT, |
| "/**\n * a[i]\n * xxx [i] zzz\n */", 3) |
| ]; |
| createParser(''); |
| List<CommentReference> references = parser.parseCommentReferences(tokens); |
| expectNotNullIfNoErrors(references); |
| assertNoErrors(); |
| expect(references, hasLength(1)); |
| CommentReference reference = references[0]; |
| expect(reference, isNotNull); |
| expect(reference.expression, isNotNull); |
| expect(reference.offset, 27); |
| } |
| |
| @failingTest |
| void test_parseCommentReferences_skipLink_direct_multiLine() { |
| List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[ |
| DocumentationCommentToken( |
| TokenType.MULTI_LINE_COMMENT, |
| ''' |
| /** |
| * [a link split across multiple |
| * lines](http://www.google.com) [b] zzz |
| */ |
| ''', |
| 3) |
| ]; |
| createParser(''); |
| List<CommentReference> references = parser.parseCommentReferences(tokens); |
| expectNotNullIfNoErrors(references); |
| assertNoErrors(); |
| expect(references, hasLength(1)); |
| CommentReference reference = references[0]; |
| expect(reference, isNotNull); |
| expect(reference.expression, isNotNull); |
| expect(reference.offset, 74); |
| } |
| |
| void test_parseCommentReferences_skipLink_direct_singleLine() { |
| List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[ |
| DocumentationCommentToken(TokenType.MULTI_LINE_COMMENT, |
| "/** [a](http://www.google.com) [b] zzz */", 3) |
| ]; |
| createParser(''); |
| List<CommentReference> references = parser.parseCommentReferences(tokens); |
| expectNotNullIfNoErrors(references); |
| assertNoErrors(); |
| expect(references, hasLength(1)); |
| CommentReference reference = references[0]; |
| expect(reference, isNotNull); |
| expect(reference.expression, isNotNull); |
| expect(reference.offset, 35); |
| } |
| |
| @failingTest |
| void test_parseCommentReferences_skipLink_reference_multiLine() { |
| List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[ |
| DocumentationCommentToken( |
| TokenType.MULTI_LINE_COMMENT, |
| ''' |
| /** |
| * [a link split across multiple |
| * lines][c] [b] zzz |
| */ |
| ''', |
| 3) |
| ]; |
| createParser(''); |
| List<CommentReference> references = parser.parseCommentReferences(tokens); |
| expectNotNullIfNoErrors(references); |
| assertNoErrors(); |
| expect(references, hasLength(1)); |
| CommentReference reference = references[0]; |
| expect(reference, isNotNull); |
| expect(reference.expression, isNotNull); |
| expect(reference.offset, 54); |
| } |
| |
| void test_parseCommentReferences_skipLink_reference_singleLine() { |
| List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[ |
| DocumentationCommentToken( |
| TokenType.MULTI_LINE_COMMENT, "/** [a][c] [b] zzz */", 3) |
| ]; |
| createParser(''); |
| List<CommentReference> references = parser.parseCommentReferences(tokens); |
| expectNotNullIfNoErrors(references); |
| assertNoErrors(); |
| expect(references, hasLength(1)); |
| CommentReference reference = references[0]; |
| expect(reference, isNotNull); |
| expect(reference.expression, isNotNull); |
| expect(reference.offset, 15); |
| } |
| |
| void test_parseCommentReferences_skipLinkDefinition() { |
| List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[ |
| DocumentationCommentToken(TokenType.MULTI_LINE_COMMENT, |
| "/** [a]: http://www.google.com (Google) [b] zzz */", 3) |
| ]; |
| createParser(''); |
| List<CommentReference> references = parser.parseCommentReferences(tokens); |
| expectNotNullIfNoErrors(references); |
| assertNoErrors(); |
| expect(references, hasLength(1)); |
| CommentReference reference = references[0]; |
| expect(reference, isNotNull); |
| expect(reference.expression, isNotNull); |
| expect(reference.offset, 44); |
| } |
| |
| void test_parseConfiguration_noOperator_dottedIdentifier() { |
| createParser("if (a.b) 'c.dart'"); |
| Configuration configuration = parser.parseConfiguration(); |
| expectNotNullIfNoErrors(configuration); |
| assertNoErrors(); |
| expect(configuration.ifKeyword, isNotNull); |
| expect(configuration.leftParenthesis, isNotNull); |
| expectDottedName(configuration.name, ["a", "b"]); |
| expect(configuration.equalToken, isNull); |
| expect(configuration.value, isNull); |
| expect(configuration.rightParenthesis, isNotNull); |
| expect(configuration.uri, isNotNull); |
| } |
| |
| void test_parseConfiguration_noOperator_simpleIdentifier() { |
| createParser("if (a) 'b.dart'"); |
| Configuration configuration = parser.parseConfiguration(); |
| expectNotNullIfNoErrors(configuration); |
| assertNoErrors(); |
| expect(configuration.ifKeyword, isNotNull); |
| expect(configuration.leftParenthesis, isNotNull); |
| expectDottedName(configuration.name, ["a"]); |
| expect(configuration.equalToken, isNull); |
| expect(configuration.value, isNull); |
| expect(configuration.rightParenthesis, isNotNull); |
| expect(configuration.uri, isNotNull); |
| } |
| |
| void test_parseConfiguration_operator_dottedIdentifier() { |
| createParser("if (a.b == 'c') 'd.dart'"); |
| Configuration configuration = parser.parseConfiguration(); |
| expectNotNullIfNoErrors(configuration); |
| assertNoErrors(); |
| expect(configuration.ifKeyword, isNotNull); |
| expect(configuration.leftParenthesis, isNotNull); |
| expectDottedName(configuration.name, ["a", "b"]); |
| expect(configuration.equalToken, isNotNull); |
| expect(configuration.value, isNotNull); |
| expect(configuration.rightParenthesis, isNotNull); |
| expect(configuration.uri, isNotNull); |
| } |
| |
| void test_parseConfiguration_operator_simpleIdentifier() { |
| createParser("if (a == 'b') 'c.dart'"); |
| Configuration configuration = parser.parseConfiguration(); |
| expectNotNullIfNoErrors(configuration); |
| assertNoErrors(); |
| expect(configuration.ifKeyword, isNotNull); |
| expect(configuration.leftParenthesis, isNotNull); |
| expectDottedName(configuration.name, ["a"]); |
| expect(configuration.equalToken, isNotNull); |
| expect(configuration.value, isNotNull); |
| expect(configuration.rightParenthesis, isNotNull); |
| expect(configuration.uri, isNotNull); |
| } |
| |
| void test_parseConstructorName_named_noPrefix() { |
| ConstructorName name = parseConstructorName('A.n'); |
| expectNotNullIfNoErrors(name); |
| assertNoErrors(); |
| expect(name.type, isNotNull); |
| expect(name.period, isNull); |
| expect(name.name, isNull); |
| } |
| |
| void test_parseConstructorName_named_prefixed() { |
| ConstructorName name = parseConstructorName('p.A.n'); |
| expectNotNullIfNoErrors(name); |
| assertNoErrors(); |
| expect(name.type, isNotNull); |
| expect(name.period, isNotNull); |
| expect(name.name, isNotNull); |
| } |
| |
| void test_parseConstructorName_unnamed_noPrefix() { |
| ConstructorName name = parseConstructorName('A'); |
| expectNotNullIfNoErrors(name); |
| assertNoErrors(); |
| expect(name.type, isNotNull); |
| expect(name.period, isNull); |
| expect(name.name, isNull); |
| } |
| |
| void test_parseConstructorName_unnamed_prefixed() { |
| ConstructorName name = parseConstructorName('p.A'); |
| expectNotNullIfNoErrors(name); |
| assertNoErrors(); |
| expect(name.type, isNotNull); |
| expect(name.period, isNull); |
| expect(name.name, isNull); |
| } |
| |
| void test_parseDocumentationComment_block() { |
| createParser('/** */ class C {}'); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| Comment comment = unit.declarations[0].documentationComment!; |
| expectNotNullIfNoErrors(comment); |
| assertNoErrors(); |
| expect(comment.isBlock, isFalse); |
| expect(comment.isDocumentation, isTrue); |
| expect(comment.isEndOfLine, isFalse); |
| } |
| |
| void test_parseDocumentationComment_block_withReference() { |
| createParser('/** [a] */ class C {}'); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| Comment comment = unit.declarations[0].documentationComment!; |
| expectNotNullIfNoErrors(comment); |
| assertNoErrors(); |
| expect(comment.isBlock, isFalse); |
| expect(comment.isDocumentation, isTrue); |
| expect(comment.isEndOfLine, isFalse); |
| NodeList<CommentReference> references = comment.references; |
| expect(references, hasLength(1)); |
| CommentReference reference = references[0]; |
| expect(reference, isNotNull); |
| expect(reference.offset, 5); |
| } |
| |
| void test_parseDocumentationComment_endOfLine() { |
| createParser('/// \n/// \n class C {}'); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| Comment comment = unit.declarations[0].documentationComment!; |
| expectNotNullIfNoErrors(comment); |
| assertNoErrors(); |
| expect(comment.isBlock, isFalse); |
| expect(comment.isDocumentation, isTrue); |
| expect(comment.isEndOfLine, isFalse); |
| } |
| |
| void test_parseExtendsClause() { |
| ExtendsClause clause = parseExtendsClause('extends B'); |
| expectNotNullIfNoErrors(clause); |
| assertNoErrors(); |
| expect(clause.extendsKeyword, isNotNull); |
| expect(clause.superclass, isNotNull); |
| expect(clause.superclass, isNamedType); |
| } |
| |
| void test_parseFunctionBody_block() { |
| createParser('{}'); |
| FunctionBody functionBody = parser.parseFunctionBody( |
| false, ParserErrorCode.MISSING_FUNCTION_BODY, false); |
| expectNotNullIfNoErrors(functionBody); |
| assertNoErrors(); |
| expect(functionBody, isBlockFunctionBody); |
| var body = functionBody as BlockFunctionBody; |
| expect(body.keyword, isNull); |
| expect(body.star, isNull); |
| expect(body.block, isNotNull); |
| expect(body.isAsynchronous, isFalse); |
| expect(body.isGenerator, isFalse); |
| expect(body.isSynchronous, isTrue); |
| } |
| |
| void test_parseFunctionBody_block_async() { |
| createParser('async {}'); |
| FunctionBody functionBody = parser.parseFunctionBody( |
| false, ParserErrorCode.MISSING_FUNCTION_BODY, false); |
| expectNotNullIfNoErrors(functionBody); |
| assertNoErrors(); |
| expect(functionBody, isBlockFunctionBody); |
| var body = functionBody as BlockFunctionBody; |
| expect(body.keyword, isNotNull); |
| expect(body.keyword!.lexeme, Keyword.ASYNC.lexeme); |
| expect(body.star, isNull); |
| expect(body.block, isNotNull); |
| expect(body.isAsynchronous, isTrue); |
| expect(body.isGenerator, isFalse); |
| expect(body.isSynchronous, isFalse); |
| } |
| |
| void test_parseFunctionBody_block_asyncGenerator() { |
| createParser('async* {}'); |
| FunctionBody functionBody = parser.parseFunctionBody( |
| false, ParserErrorCode.MISSING_FUNCTION_BODY, false); |
| expectNotNullIfNoErrors(functionBody); |
| assertNoErrors(); |
| expect(functionBody, isBlockFunctionBody); |
| var body = functionBody as BlockFunctionBody; |
| expect(body.keyword, isNotNull); |
| expect(body.keyword!.lexeme, Keyword.ASYNC.lexeme); |
| expect(body.star, isNotNull); |
| expect(body.block, isNotNull); |
| expect(body.isAsynchronous, isTrue); |
| expect(body.isGenerator, isTrue); |
| expect(body.isSynchronous, isFalse); |
| } |
| |
| void test_parseFunctionBody_block_syncGenerator() { |
| createParser('sync* {}'); |
| FunctionBody functionBody = parser.parseFunctionBody( |
| false, ParserErrorCode.MISSING_FUNCTION_BODY, false); |
| expectNotNullIfNoErrors(functionBody); |
| assertNoErrors(); |
| expect(functionBody, isBlockFunctionBody); |
| var body = functionBody as BlockFunctionBody; |
| expect(body.keyword, isNotNull); |
| expect(body.keyword!.lexeme, Keyword.SYNC.lexeme); |
| expect(body.star, isNotNull); |
| expect(body.block, isNotNull); |
| expect(body.isAsynchronous, isFalse); |
| expect(body.isGenerator, isTrue); |
| expect(body.isSynchronous, isTrue); |
| } |
| |
| void test_parseFunctionBody_empty() { |
| createParser(';'); |
| FunctionBody functionBody = parser.parseFunctionBody( |
| true, ParserErrorCode.MISSING_FUNCTION_BODY, false); |
| expectNotNullIfNoErrors(functionBody); |
| assertNoErrors(); |
| expect(functionBody, isEmptyFunctionBody); |
| var body = functionBody as EmptyFunctionBody; |
| expect(body.semicolon, isNotNull); |
| } |
| |
| void test_parseFunctionBody_expression() { |
| createParser('=> y;'); |
| FunctionBody functionBody = parser.parseFunctionBody( |
| false, ParserErrorCode.MISSING_FUNCTION_BODY, false); |
| expectNotNullIfNoErrors(functionBody); |
| assertNoErrors(); |
| expect(functionBody, isExpressionFunctionBody); |
| var body = functionBody as ExpressionFunctionBody; |
| expect(body.keyword, isNull); |
| expect(body.functionDefinition, isNotNull); |
| expect(body.expression, isNotNull); |
| expect(body.semicolon, isNotNull); |
| expect(body.isAsynchronous, isFalse); |
| expect(body.isGenerator, isFalse); |
| expect(body.isSynchronous, isTrue); |
| } |
| |
| void test_parseFunctionBody_expression_async() { |
| createParser('async => y;'); |
| FunctionBody functionBody = parser.parseFunctionBody( |
| false, ParserErrorCode.MISSING_FUNCTION_BODY, false); |
| expectNotNullIfNoErrors(functionBody); |
| assertNoErrors(); |
| expect(functionBody, isExpressionFunctionBody); |
| var body = functionBody as ExpressionFunctionBody; |
| expect(body.keyword, isNotNull); |
| expect(body.keyword!.lexeme, Keyword.ASYNC.lexeme); |
| expect(body.functionDefinition, isNotNull); |
| expect(body.expression, isNotNull); |
| expect(body.semicolon, isNotNull); |
| expect(body.isAsynchronous, isTrue); |
| expect(body.isGenerator, isFalse); |
| expect(body.isSynchronous, isFalse); |
| } |
| |
| void test_parseIdentifierList_multiple() { |
| List<SimpleIdentifier> list = parseIdentifierList('a, b, c'); |
| expectNotNullIfNoErrors(list); |
| assertNoErrors(); |
| expect(list, hasLength(3)); |
| } |
| |
| void test_parseIdentifierList_single() { |
| List<SimpleIdentifier> list = parseIdentifierList('a'); |
| expectNotNullIfNoErrors(list); |
| assertNoErrors(); |
| expect(list, hasLength(1)); |
| } |
| |
| void test_parseImplementsClause_multiple() { |
| ImplementsClause clause = parseImplementsClause('implements A, B, C'); |
| expectNotNullIfNoErrors(clause); |
| assertNoErrors(); |
| expect(clause.interfaces, hasLength(3)); |
| expect(clause.implementsKeyword, isNotNull); |
| } |
| |
| void test_parseImplementsClause_single() { |
| ImplementsClause clause = parseImplementsClause('implements A'); |
| expectNotNullIfNoErrors(clause); |
| assertNoErrors(); |
| expect(clause.interfaces, hasLength(1)); |
| expect(clause.implementsKeyword, isNotNull); |
| } |
| |
| void test_parseInstanceCreation_keyword_33647() { |
| enableOptionalNewAndConst = true; |
| CompilationUnit unit = parseCompilationUnit(''' |
| var c = new Future<int>.sync(() => 3).then<int>((e) => e); |
| '''); |
| expect(unit, isNotNull); |
| var v = unit.declarations[0] as TopLevelVariableDeclaration; |
| var init = v.variables.variables[0].initializer as MethodInvocation; |
| expect(init.methodName.name, 'then'); |
| NodeList<TypeAnnotation> typeArg = init.typeArguments!.arguments; |
| expect(typeArg, hasLength(1)); |
| expect(typeArg[0].beginToken.lexeme, 'int'); |
| } |
| |
| void test_parseInstanceCreation_noKeyword_33647() { |
| enableOptionalNewAndConst = true; |
| CompilationUnit unit = parseCompilationUnit(''' |
| var c = Future<int>.sync(() => 3).then<int>((e) => e); |
| '''); |
| expect(unit, isNotNull); |
| var v = unit.declarations[0] as TopLevelVariableDeclaration; |
| var init = v.variables.variables[0].initializer as MethodInvocation; |
| expect(init.methodName.name, 'then'); |
| NodeList<TypeAnnotation> typeArg = init.typeArguments!.arguments; |
| expect(typeArg, hasLength(1)); |
| expect(typeArg[0].beginToken.lexeme, 'int'); |
| } |
| |
| void test_parseInstanceCreation_noKeyword_noPrefix() { |
| enableOptionalNewAndConst = true; |
| createParser('f() => C<E>.n();'); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expect(unit, isNotNull); |
| var f = unit.declarations[0] as FunctionDeclaration; |
| var body = f.functionExpression.body as ExpressionFunctionBody; |
| expect(body.expression, isInstanceCreationExpression); |
| var creation = body.expression as InstanceCreationExpressionImpl; |
| expect(creation.keyword, isNull); |
| ConstructorName constructorName = creation.constructorName; |
| expect(constructorName.type.toSource(), 'C<E>'); |
| expect(constructorName.period, isNotNull); |
| expect(constructorName.name, isNotNull); |
| expect(creation.argumentList, isNotNull); |
| expect(creation.typeArguments, isNull); |
| } |
| |
| void test_parseInstanceCreation_noKeyword_noPrefix_34403() { |
| enableOptionalNewAndConst = true; |
| createParser('f() => C<E>.n<B>();'); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expect(unit, isNotNull); |
| var f = unit.declarations[0] as FunctionDeclaration; |
| var body = f.functionExpression.body as ExpressionFunctionBody; |
| expect(body.expression, isMethodInvocation); |
| var methodInvocation = body.expression as MethodInvocationImpl; |
| var target = methodInvocation.target!; |
| expect(target, isFunctionReference); |
| expect(target.toSource(), 'C<E>'); |
| expect(methodInvocation.methodName.name, 'n'); |
| expect(methodInvocation.argumentList, isNotNull); |
| expect(methodInvocation.typeArguments!.arguments, hasLength(1)); |
| } |
| |
| void test_parseInstanceCreation_noKeyword_prefix() { |
| enableOptionalNewAndConst = true; |
| createParser('f() => p.C<E>.n();'); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expect(unit, isNotNull); |
| var f = unit.declarations[0] as FunctionDeclaration; |
| var body = f.functionExpression.body as ExpressionFunctionBody; |
| expect(body.expression, isInstanceCreationExpression); |
| var creation = body.expression as InstanceCreationExpression; |
| expect(creation.keyword, isNull); |
| ConstructorName constructorName = creation.constructorName; |
| expect(constructorName.type.toSource(), 'p.C<E>'); |
| expect(constructorName.period, isNotNull); |
| expect(constructorName.name, isNotNull); |
| expect(creation.argumentList, isNotNull); |
| } |
| |
| void test_parseInstanceCreation_noKeyword_varInit() { |
| enableOptionalNewAndConst = true; |
| createParser(''' |
| class C<T, S> {} |
| void main() {final c = C<int, int Function(String)>();} |
| '''); |
| CompilationUnit unit = parser.parseCompilationUnit2(); |
| expect(unit, isNotNull); |
| var f = unit.declarations[1] as FunctionDeclaration; |
| var body = f.functionExpression.body as BlockFunctionBody; |
| var statement = body.block.statements[0] as VariableDeclarationStatement; |
| VariableDeclaration variable = statement.variables.variables[0]; |
| var creation = variable.initializer as MethodInvocation; |
| expect(creation.methodName.name, 'C'); |
| expect(creation.typeArguments!.toSource(), '<int, int Function(String)>'); |
| } |
| |
| void test_parseLibraryIdentifier_builtin() { |
| String name = "deferred"; |
| LibraryIdentifier identifier = parseLibraryIdentifier(name); |
| expectNotNullIfNoErrors(identifier); |
| assertNoErrors(); |
| expect(identifier.name, name); |
| expect(identifier.beginToken.type.isBuiltIn, isTrue); |
| } |
| |
| void test_parseLibraryIdentifier_invalid() { |
| parseCompilationUnit('library <myLibId>;', errors: [ |
| expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 0, 7), |
| expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 17, 1), |
| ]); |
| } |
| |
| void test_parseLibraryIdentifier_multiple() { |
| String name = "a.b.c"; |
| LibraryIdentifier identifier = parseLibraryIdentifier(name); |
| expectNotNullIfNoErrors(identifier); |
| assertNoErrors(); |
| expect(identifier.name, name); |
| } |
| |
| void test_parseLibraryIdentifier_pseudo() { |
| String name = "await"; |
| LibraryIdentifier identifier = parseLibraryIdentifier(name); |
| expectNotNullIfNoErrors(identifier); |
| assertNoErrors(); |
| expect(identifier.name, name); |
| expect(identifier.beginToken.type.isPseudo, isTrue); |
| } |
| |
| void test_parseLibraryIdentifier_single() { |
| String name = "a"; |
| LibraryIdentifier identifier = parseLibraryIdentifier(name); |
| expectNotNullIfNoErrors(identifier); |
| assertNoErrors(); |
| expect(identifier.name, name); |
| } |
| |
| void test_parseOptionalReturnType() { |
| // TODO(brianwilkerson) Implement tests for this method. |
| } |
| |
| void test_parseReturnStatement_noValue() { |
| var statement = parseStatement('return;') as ReturnStatement; |
| expectNotNullIfNoErrors(statement); |
| assertNoErrors(); |
| expect(statement.returnKeyword, isNotNull); |
| expect(statement.expression, isNull); |
| expect(statement.semicolon, isNotNull); |
| } |
| |
| void test_parseReturnStatement_value() { |
| var statement = parseStatement('return x;') as ReturnStatement; |
| expectNotNullIfNoErrors(statement); |
| assertNoErrors(); |
| expect(statement.returnKeyword, isNotNull); |
| expect(statement.expression, isNotNull); |
| expect(statement.semicolon, isNotNull); |
| } |
| |
| void test_parseStatement_function_noReturnType() { |
| createParser(''' |
| Function<A>(core.List<core.int> x) m() => null; |
| '''); |
| Statement statement = parser.parseStatement2(); |
| expect(statement, isFunctionDeclarationStatement); |
| expect( |
| (statement as FunctionDeclarationStatement) |
| .functionDeclaration |
| .functionExpression |
| .body, |
| isExpressionFunctionBody); |
| } |
| |
| void test_parseStatements_multiple() { |
| parseStatementList("return; return;", 2); |
| } |
| |
| void test_parseStatements_single() { |
| parseStatementList("return;", 1); |
| } |
| |
| void test_parseTypeAnnotation_function_noReturnType_noParameters() { |
| createParser('Function()'); |
| var functionType = parser.parseTypeAnnotation(false) as GenericFunctionType; |
| expectNotNullIfNoErrors(functionType); |
| assertNoErrors(); |
| expect(functionType.returnType, isNull); |
| expect(functionType.functionKeyword, isNotNull); |
| expect(functionType.typeParameters, isNull); |
| FormalParameterList parameterList = functionType.parameters; |
| expect(parameterList, isNotNull); |
| expect(parameterList.parameters, hasLength(0)); |
| } |
| |
| void test_parseTypeAnnotation_function_noReturnType_parameters() { |
| createParser('Function(int, int)'); |
| var functionType = parser.parseTypeAnnotation(false) as GenericFunctionType; |
| expectNotNullIfNoErrors(functionType); |
| assertNoErrors(); |
| expect(functionType.returnType, isNull); |
| expect(functionType.functionKeyword, isNotNull); |
| expect(functionType.typeParameters, isNull); |
| FormalParameterList parameterList = functionType.parameters; |
| expect(parameterList, isNotNull); |
| NodeList<FormalParameter> parameters = parameterList.parameters; |
| expect(parameters, hasLength(2)); |
| |
| expect(parameters[0], isSimpleFormalParameter); |
| var parameter = parameters[0] as SimpleFormalParameter; |
| expect(parameter.identifier, isNull); |
| expect(parameter.type, isNamedType); |
| expect((parameter.type as NamedType).name.name, 'int'); |
| |
| expect(parameters[1], isSimpleFormalParameter); |
| parameter = parameters[1] as SimpleFormalParameter; |
| expect(parameter.identifier, isNull); |
| expect(parameter.type, isNamedType); |
| expect((parameter.type as NamedType).name.name, 'int'); |
| } |
| |
| void test_parseTypeAnnotation_function_noReturnType_typeParameters() { |
| createParser('Function<S, T>()'); |
| var functionType = parser.parseTypeAnnotation(false) as GenericFunctionType; |
| expectNotNullIfNoErrors(functionType); |
| assertNoErrors(); |
| expect(functionType.returnType, isNull); |
| expect(functionType.functionKeyword, isNotNull); |
| var typeParameters = functionType.typeParameters!; |
| expect(typeParameters, isNotNull); |
| expect(typeParameters.typeParameters, hasLength(2)); |
| FormalParameterList parameterList = functionType.parameters; |
| expect(parameterList, isNotNull); |
| expect(parameterList.parameters, hasLength(0)); |
| } |
| |
| void |
| test_parseTypeAnnotation_function_noReturnType_typeParameters_parameters() { |
| createParser('Function<T>(String, {T t})'); |
| var functionType = parser.parseTypeAnnotation(false) as GenericFunctionType; |
| expectNotNullIfNoErrors(functionType); |
| assertNoErrors(); |
| expect(functionType.returnType, isNull); |
| expect(functionType.functionKeyword, isNotNull); |
| var typeParameters = functionType.typeParameters!; |
| expect(typeParameters, isNotNull); |
| expect(typeParameters.typeParameters, hasLength(1)); |
| FormalParameterList parameterList = functionType.parameters; |
| expect(parameterList, isNotNull); |
| expect(parameterList.parameters, hasLength(2)); |
| } |
| |
| void test_parseTypeAnnotation_function_returnType_classFunction() { |
| createParser('Function'); |
| var functionType = parser.parseTypeAnnotation(false) as NamedType; |
| expectNotNullIfNoErrors(functionType); |
| assertNoErrors(); |
| } |
| |
| void test_parseTypeAnnotation_function_returnType_function() { |
| createParser('A Function(B, C) Function(D)'); |
| // TODO(scheglov) improve the test to verify also the node properties |
| var functionType = parser.parseTypeAnnotation(false) as GenericFunctionType; |
| expectNotNullIfNoErrors(functionType); |
| assertNoErrors(); |
| } |
| |
| void test_parseTypeAnnotation_function_returnType_noParameters() { |
| createParser('List<int> Function()'); |
| var functionType = parser.parseTypeAnnotation(false) as GenericFunctionType; |
| expectNotNullIfNoErrors(functionType); |
| assertNoErrors(); |
| expect(functionType.returnType, isNotNull); |
| expect(functionType.functionKeyword, isNotNull); |
| expect(functionType.typeParameters, isNull); |
| FormalParameterList parameterList = functionType.parameters; |
| expect(parameterList, isNotNull); |
| expect(parameterList.parameters, hasLength(0)); |
| } |
| |
| void test_parseTypeAnnotation_function_returnType_parameters() { |
| createParser('List<int> Function(String s, int i)'); |
| var functionType = parser.parseTypeAnnotation(false) as GenericFunctionType; |
| expectNotNullIfNoErrors(functionType); |
| assertNoErrors(); |
| expect(functionType.returnType, isNotNull); |
| expect(functionType.functionKeyword, isNotNull); |
| expect(functionType.typeParameters, isNull); |
| FormalParameterList parameterList = functionType.parameters; |
| expect(parameterList, isNotNull); |
| NodeList<FormalParameter> parameters = parameterList.parameters; |
| expect(parameters, hasLength(2)); |
| |
| expect(parameters[0], isSimpleFormalParameter); |
| var parameter = parameters[0] as SimpleFormalParameter; |
| expect(parameter.identifier, isNotNull); |
| expect(parameter.identifier!.name, 's'); |
| expect(parameter.type, isNamedType); |
| expect((parameter.type as NamedType).name.name, 'String'); |
| |
| expect(parameters[1], isSimpleFormalParameter); |
| parameter = parameters[1] as SimpleFormalParameter; |
| expect(parameter.identifier, isNotNull); |
| expect(parameter.identifier!.name, 'i'); |
| expect(parameter.type, isNamedType); |
| expect((parameter.type as NamedType).name.name, 'int'); |
| } |
| |
| void test_parseTypeAnnotation_function_returnType_simple() { |
| createParser('A Function(B, C)'); |
| // TODO(scheglov) improve the test to verify also the node properties |
| var functionType = parser.parseTypeAnnotation(false) as GenericFunctionType; |
| expectNotNullIfNoErrors(functionType); |
| assertNoErrors(); |
| } |
| |
| void test_parseTypeAnnotation_function_returnType_typeParameters() { |
| createParser('List<T> Function<T>()'); |
| var functionType = parser.parseTypeAnnotation(false) as GenericFunctionType; |
| expectNotNullIfNoErrors(functionType); |
| assertNoErrors(); |
| expect(functionType.returnType, isNotNull); |
| expect(functionType.functionKeyword, isNotNull); |
| var typeParameters = functionType.typeParameters!; |
| expect(typeParameters, isNotNull); |
| expect(typeParameters.typeParameters, hasLength(1)); |
| FormalParameterList parameterList = functionType.parameters; |
| expect(parameterList, isNotNull); |
| expect(parameterList.parameters, hasLength(0)); |
| } |
| |
| void |
| test_parseTypeAnnotation_function_returnType_typeParameters_parameters() { |
| createParser('List<T> Function<T>(String s, [T])'); |
| var functionType = parser.parseTypeAnnotation(false) as GenericFunctionType; |
| expectNotNullIfNoErrors(functionType); |
| assertNoErrors(); |
| expect(functionType.returnType, isNotNull); |
| expect(functionType.functionKeyword, isNotNull); |
| var typeParameters = functionType.typeParameters!; |
| expect(typeParameters, isNotNull); |
| expect(typeParameters.typeParameters, hasLength(1)); |
| FormalParameterList parameterList = functionType.parameters; |
| expect(parameterList, isNotNull); |
| expect(parameterList.parameters, hasLength(2)); |
| } |
| |
| void test_parseTypeAnnotation_function_returnType_withArguments() { |
| createParser('A<B> Function(C)'); |
| // TODO(scheglov) improve this test to verify also the node properties |
| var functionType = parser.parseTypeAnnotation(false) as GenericFunctionType; |
| expectNotNullIfNoErrors(functionType); |
| assertNoErrors(); |
| } |
| |
| void test_parseTypeAnnotation_named() { |
| createParser('A<B>'); |
| var namedType = parser.parseTypeAnnotation(false) as NamedType; |
| expectNotNullIfNoErrors(namedType); |
| assertNoErrors(); |
| } |
| |
| void test_parseTypeArgumentList_empty() { |
| createParser('<>'); |
| TypeArgumentList argumentList = parser.parseTypeArgumentList(); |
| expectNotNullIfNoErrors(argumentList); |
| listener.assertErrorsWithCodes([ParserErrorCode.EXPECTED_TYPE_NAME]); |
| expect(argumentList.leftBracket, isNotNull); |
| expect(argumentList.arguments, hasLength(1)); |
| expect(argumentList.rightBracket, isNotNull); |
| } |
| |
| void test_parseTypeArgumentList_multiple() { |
| createParser('<int, int, int>'); |
| TypeArgumentList argumentList = parser.parseTypeArgumentList(); |
| expectNotNullIfNoErrors(argumentList); |
| assertNoErrors(); |
| expect(argumentList.leftBracket, isNotNull); |
| expect(argumentList.arguments, hasLength(3)); |
| expect(argumentList.rightBracket, isNotNull); |
| } |
| |
| void test_parseTypeArgumentList_nested() { |
| createParser('<A<B>>'); |
| TypeArgumentList argumentList = parser.parseTypeArgumentList(); |
| expectNotNullIfNoErrors(argumentList); |
| assertNoErrors(); |
| expect(argumentList.leftBracket, isNotNull); |
| expect(argumentList.arguments, hasLength(1)); |
| var argument = argumentList.arguments[0] as NamedType; |
| expect(argument, isNotNull); |
| var innerList = argument.typeArguments!; |
| expect(innerList, isNotNull); |
| expect(innerList.arguments, hasLength(1)); |
| expect(argumentList.rightBracket, isNotNull); |
| } |
| |
| void test_parseTypeArgumentList_nested_withComment_double() { |
| createParser('<A<B /* 0 */ >>'); |
| TypeArgumentList argumentList = parser.parseTypeArgumentList(); |
| expectNotNullIfNoErrors(argumentList); |
| assertNoErrors(); |
| expect(argumentList.leftBracket, isNotNull); |
| expect(argumentList.rightBracket, isNotNull); |
| expect(argumentList.arguments, hasLength(1)); |
| |
| var argument = argumentList.arguments[0] as NamedType; |
| expect(argument, isNotNull); |
| |
| var innerList = argument.typeArguments!; |
| expect(innerList, isNotNull); |
| expect(innerList.leftBracket, isNotNull); |
| expect(innerList.arguments, hasLength(1)); |
| expect(innerList.rightBracket, isNotNull); |
| expect(innerList.rightBracket.precedingComments, isNotNull); |
| } |
| |
| void test_parseTypeArgumentList_nested_withComment_tripple() { |
| createParser('<A<B<C /* 0 */ >>>'); |
| TypeArgumentList argumentList = parser.parseTypeArgumentList(); |
| expectNotNullIfNoErrors(argumentList); |
| assertNoErrors(); |
| expect(argumentList.leftBracket, isNotNull); |
| expect(argumentList.rightBracket, isNotNull); |
| expect(argumentList.arguments, hasLength(1)); |
| |
| var argument = argumentList.arguments[0] as NamedType; |
| expect(argument, isNotNull); |
| |
| var innerList = argument.typeArguments!; |
| expect(innerList, isNotNull); |
| expect(innerList.leftBracket, isNotNull); |
| expect(innerList.arguments, hasLength(1)); |
| expect(innerList.rightBracket, isNotNull); |
| |
| var innerArgument = innerList.arguments[0] as NamedType; |
| expect(innerArgument, isNotNull); |
| |
| var innerInnerList = innerArgument.typeArguments!; |
| expect(innerInnerList, isNotNull); |
| expect(innerInnerList.leftBracket, isNotNull); |
| expect(innerInnerList.arguments, hasLength(1)); |
| expect(innerInnerList.rightBracket, isNotNull); |
| expect(innerInnerList.rightBracket.precedingComments, isNotNull); |
| } |
| |
| void test_parseTypeArgumentList_single() { |
| createParser('<int>'); |
| TypeArgumentList argumentList = parser.parseTypeArgumentList(); |
| expectNotNullIfNoErrors(argumentList); |
| assertNoErrors(); |
| expect(argumentList.leftBracket, isNotNull); |
| expect(argumentList.arguments, hasLength(1)); |
| expect(argumentList.rightBracket, isNotNull); |
| } |
| |
| void test_parseTypeName_parameterized() { |
| createParser('List<int>'); |
| NamedType namedType = parser.parseTypeName(false); |
| expectNotNullIfNoErrors(namedType); |
| assertNoErrors(); |
| expect(namedType.name, isNotNull); |
| expect(namedType.typeArguments, isNotNull); |
| } |
| |
| void test_parseTypeName_simple() { |
| createParser('int'); |
| NamedType namedType = parser.parseTypeName(false); |
| expectNotNullIfNoErrors(namedType); |
| assertNoErrors(); |
| expect(namedType.name, isNotNull); |
| expect(namedType.typeArguments, isNull); |
| } |
| |
| void test_parseTypeParameter_bounded_functionType_noReturn() { |
| createParser('A extends Function(int)'); |
| TypeParameter parameter = parser.parseTypeParameter(); |
| expectNotNullIfNoErrors(parameter); |
| assertNoErrors(); |
| expect(parameter.bound, isGenericFunctionType); |
| expect(parameter.extendsKeyword, isNotNull); |
| expect(parameter.name, isNotNull); |
| } |
| |
| void test_parseTypeParameter_bounded_functionType_return() { |
| createParser('A extends String Function(int)'); |
| TypeParameter parameter = parser.parseTypeParameter(); |
| expectNotNullIfNoErrors(parameter); |
| assertNoErrors(); |
| expect(parameter.bound, isGenericFunctionType); |
| expect(parameter.extendsKeyword, isNotNull); |
| expect(parameter.name, isNotNull); |
| } |
| |
| void test_parseTypeParameter_bounded_generic() { |
| createParser('A extends B<C>'); |
| TypeParameter parameter = parser.parseTypeParameter(); |
| expectNotNullIfNoErrors(parameter); |
| assertNoErrors(); |
| expect(parameter.bound, isNamedType); |
| expect(parameter.extendsKeyword, isNotNull); |
| expect(parameter.name, isNotNull); |
| } |
| |
| void test_parseTypeParameter_bounded_simple() { |
| createParser('A extends B'); |
| TypeParameter parameter = parser.parseTypeParameter(); |
| expectNotNullIfNoErrors(parameter); |
| assertNoErrors(); |
| expect(parameter.bound, isNamedType); |
| expect(parameter.extendsKeyword, isNotNull); |
| expect(parameter.name, isNotNull); |
| } |
| |
| void test_parseTypeParameter_simple() { |
| createParser('A'); |
| TypeParameter parameter = parser.parseTypeParameter(); |
| expectNotNullIfNoErrors(parameter); |
| assertNoErrors(); |
| expect(parameter.bound, isNull); |
| expect(parameter.extendsKeyword, isNull); |
| expect(parameter.name, isNotNull); |
| } |
| |
| void test_parseTypeParameterList_multiple() { |
| createParser('<A, B extends C, D>'); |
| TypeParameterList parameterList = parser.parseTypeParameterList()!; |
| expectNotNullIfNoErrors(parameterList); |
| assertNoErrors(); |
| expect(parameterList.leftBracket, isNotNull); |
| expect(parameterList.rightBracket, isNotNull); |
| expect(parameterList.typeParameters, hasLength(3)); |
| } |
| |
| void test_parseTypeParameterList_parameterizedWithTrailingEquals() { |
| createParser('<A extends B<E>>=', expectedEndOffset: 16); |
| TypeParameterList parameterList = parser.parseTypeParameterList()!; |
| expectNotNullIfNoErrors(parameterList); |
| assertNoErrors(); |
| expect(parameterList.leftBracket, isNotNull); |
| expect(parameterList.rightBracket, isNotNull); |
| expect(parameterList.typeParameters, hasLength(1)); |
| } |
| |
| void test_parseTypeParameterList_parameterizedWithTrailingEquals2() { |
| createParser('<A extends B<E /* foo */ >>=', expectedEndOffset: 27); |
| TypeParameterList parameterList = parser.parseTypeParameterList()!; |
| expectNotNullIfNoErrors(parameterList); |
| assertNoErrors(); |
| expect(parameterList.leftBracket, isNotNull); |
| expect(parameterList.rightBracket, isNotNull); |
| expect(parameterList.typeParameters, hasLength(1)); |
| TypeParameter typeParameter = parameterList.typeParameters[0]; |
| expect(typeParameter.name.name, 'A'); |
| var bound = typeParameter.bound as NamedType; |
| expect(bound.name.name, 'B'); |
| var typeArguments = bound.typeArguments!; |
| expect(typeArguments.arguments, hasLength(1)); |
| expect(typeArguments.rightBracket, isNotNull); |
| expect(typeArguments.rightBracket.precedingComments!.lexeme, '/* foo */'); |
| var argument = typeArguments.arguments[0] as NamedType; |
| expect(argument.name.name, 'E'); |
| } |
| |
| void test_parseTypeParameterList_single() { |
| createParser('<<A>', expectedEndOffset: 0); |
| var parameterList = parser.parseTypeParameterList(); |
| // TODO(danrubel): Consider splitting `<<` and marking the first `<` |
| // as an unexpected token. |
| expect(parameterList, isNull); |
| assertNoErrors(); |
| } |
| |
| void test_parseTypeParameterList_withTrailingEquals() { |
| createParser('<A>=', expectedEndOffset: 3); |
| TypeParameterList parameterList = parser.parseTypeParameterList()!; |
| expectNotNullIfNoErrors(parameterList); |
| assertNoErrors(); |
| expect(parameterList.leftBracket, isNotNull); |
| expect(parameterList.rightBracket, isNotNull); |
| expect(parameterList.typeParameters, hasLength(1)); |
| } |
| |
| void test_parseVariableDeclaration_equals() { |
| VariableDeclaration declaration = parseVariableDeclaration('var a = b;'); |
| expectNotNullIfNoErrors(declaration); |
| assertNoErrors(); |
| expect(declaration.name, isNotNull); |
| expect(declaration.equals, isNotNull); |
| expect(declaration.initializer, isNotNull); |
| } |
| |
| void test_parseVariableDeclaration_final_late() { |
| var statement = |
| parseStatement('final late a;') as VariableDeclarationStatement; |
| var declarationList = statement.variables; |
| assertErrors( |
| errors: [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 6, 4)]); |
| expect(declarationList.keyword!.lexeme, 'final'); |
| expect(declarationList.type, isNull); |
| expect(declarationList.variables, hasLength(1)); |
| } |
| |
| void test_parseVariableDeclaration_late() { |
| var statement = parseStatement('late a;') as VariableDeclarationStatement; |
| var declarationList = statement.variables; |
| assertErrors(errors: [ |
| expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 5, 1) |
| ]); |
| expect(declarationList.keyword, isNull); |
| expect(declarationList.type, isNull); |
| expect(declarationList.variables, hasLength(1)); |
| } |
| |
| void test_parseVariableDeclaration_late_final() { |
| var statement = |
| parseStatement('late final a;') as VariableDeclarationStatement; |
| var declarationList = statement.variables; |
| assertNoErrors(); |
| expect(declarationList.keyword!.lexeme, 'final'); |
| expect(declarationList.type, isNull); |
| expect(declarationList.variables, hasLength(1)); |
| } |
| |
| void test_parseVariableDeclaration_late_init() { |
| var statement = |
| parseStatement('late a = 0;') as VariableDeclarationStatement; |
| var declarationList = statement.variables; |
| assertErrors(errors: [ |
| expectedError(ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 5, 1) |
| ]); |
| expect(declarationList.keyword, isNull); |
| expect(declarationList.type, isNull); |
| expect(declarationList.variables, hasLength(1)); |
| } |
| |
| void test_parseVariableDeclaration_late_type() { |
| var statement = parseStatement('late A a;') as VariableDeclarationStatement; |
| var declarationList = statement.variables; |
| assertNoErrors(); |
| expect(declarationList.lateKeyword, isNotNull); |
| expect(declarationList.keyword, isNull); |
| expect(declarationList.type, isNotNull); |
| expect(declarationList.variables, hasLength(1)); |
| } |
| |
| void test_parseVariableDeclaration_late_var() { |
| var statement = |
| parseStatement('late var a;') as VariableDeclarationStatement; |
| var declarationList = statement.variables; |
| assertNoErrors(); |
| expect(declarationList.lateKeyword, isNotNull); |
| expect(declarationList.keyword?.lexeme, 'var'); |
| expect(declarationList.type, isNull); |
| expect(declarationList.variables, hasLength(1)); |
| } |
| |
| void test_parseVariableDeclaration_late_var_init() { |
| var statement = |
| parseStatement('late var a = 0;') as VariableDeclarationStatement; |
| var declarationList = statement.variables; |
| assertNoErrors(); |
| expect(declarationList.lateKeyword, isNotNull); |
| expect(declarationList.keyword?.lexeme, 'var'); |
| expect(declarationList.type, isNull); |
| expect(declarationList.variables, hasLength(1)); |
| } |
| |
| void test_parseVariableDeclaration_noEquals() { |
| VariableDeclaration declaration = parseVariableDeclaration('var a;'); |
| expectNotNullIfNoErrors(declaration); |
| assertNoErrors(); |
| expect(declaration.name, isNotNull); |
| expect(declaration.equals, isNull); |
| expect(declaration.initializer, isNull); |
| } |
| |
| void test_parseWithClause_multiple() { |
| WithClause clause = parseWithClause('with A, B, C'); |
| expectNotNullIfNoErrors(clause); |
| assertNoErrors(); |
| expect(clause.withKeyword, isNotNull); |
| expect(clause.mixinTypes, hasLength(3)); |
| } |
| |
| void test_parseWithClause_single() { |
| WithClause clause = parseWithClause('with M'); |
| expectNotNullIfNoErrors(clause); |
| assertNoErrors(); |
| expect(clause.withKeyword, isNotNull); |
| expect(clause.mixinTypes, hasLength(1)); |
| } |
| |
| void test_typeAlias_37733() { |
| // https://github.com/dart-lang/sdk/issues/37733 |
| var unit = parseCompilationUnit(r'typedef K=Function(<>($', errors: [ |
| expectedError(CompileTimeErrorCode.INVALID_INLINE_FUNCTION_TYPE, 19, 1), |
| expectedError(ParserErrorCode.MISSING_IDENTIFIER, 19, 1), |
| expectedError(ParserErrorCode.MISSING_IDENTIFIER, 20, 1), |
| expectedError(ParserErrorCode.EXPECTED_TOKEN, 22, 1), |
| expectedError(ScannerErrorCode.EXPECTED_TOKEN, 23, 1), |
| expectedError(ScannerErrorCode.EXPECTED_TOKEN, 23, 1), |
| ]); |
| var typeAlias = unit.declarations[0] as GenericTypeAlias; |
| expect(typeAlias.name.toSource(), 'K'); |
| var functionType = typeAlias.functionType!; |
| expect(functionType.parameters.parameters, hasLength(1)); |
| var parameter = functionType.parameters.parameters[0]; |
| expect(parameter.identifier, isNotNull); |
| } |
| |
| void test_typeAlias_parameter_missingIdentifier_37733() { |
| // https://github.com/dart-lang/sdk/issues/37733 |
| var unit = parseCompilationUnit(r'typedef T=Function(<S>());', errors: [ |
| expectedError(CompileTimeErrorCode.INVALID_INLINE_FUNCTION_TYPE, 19, 1), |
| expectedError(ParserErrorCode.MISSING_IDENTIFIER, 19, 1), |
| ]); |
| var typeAlias = unit.declarations[0] as GenericTypeAlias; |
| expect(typeAlias.name.toSource(), 'T'); |
| var functionType = typeAlias.functionType!; |
| expect(functionType.parameters.parameters, hasLength(1)); |
| var parameter = functionType.parameters.parameters[0]; |
| expect(parameter.identifier, isNotNull); |
| } |
| } |