| // 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_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.identifier, isPrefixedIdentifier); | |
| var prefixedIdentifier = reference.identifier 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.identifier, isSimpleIdentifier); | |
| var identifier = reference.identifier 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.identifier, isSimpleIdentifier); | |
| var identifier = reference.identifier 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.identifier, isPrefixedIdentifier); | |
| var prefixedIdentifier = reference.identifier 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.identifier, isSimpleIdentifier); | |
| var identifier = reference.identifier 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.identifier, isPrefixedIdentifier); | |
| var prefixedIdentifier = reference.identifier 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.identifier, isPrefixedIdentifier); | |
| var prefixedIdentifier = reference.identifier 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.identifier, isSimpleIdentifier); | |
| var identifier = reference.identifier 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.identifier, isSimpleIdentifier); | |
| var identifier = reference.identifier 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.identifier 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.identifier, 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]; | |
| expect(reference.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]; | |
| expect(reference.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.identifier, isNotNull); | |
| expect(reference.offset, 12); | |
| Token referenceToken = reference.identifier.beginToken; | |
| expect(referenceToken.offset, 12); | |
| expect(referenceToken.lexeme, 'a'); | |
| } | |
| { | |
| CommentReference reference = references[1]; | |
| expect(reference, isNotNull); | |
| expect(reference.identifier, isNotNull); | |
| expect(reference.offset, 20); | |
| Token referenceToken = reference.identifier.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.identifier.beginToken; | |
| expect(reference, isNotNull); | |
| expect(reference.identifier, isNotNull); | |
| expect(reference.identifier.isSynthetic, isTrue); | |
| expect(reference.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.identifier.beginToken; | |
| expect(reference, isNotNull); | |
| expect(referenceToken, same(reference.beginToken)); | |
| expect(reference.identifier, isNotNull); | |
| expect(reference.identifier.isSynthetic, isFalse); | |
| expect(reference.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.identifier, isNotNull); | |
| expect(reference.offset, 12); | |
| reference = references[1]; | |
| expect(reference, isNotNull); | |
| expect(reference.identifier, isNotNull); | |
| expect(reference.offset, 20); | |
| reference = references[2]; | |
| expect(reference, isNotNull); | |
| expect(reference.identifier, 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.identifier, 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.identifier, 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.identifier, 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.identifier, 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.identifier, 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.identifier, 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.identifier, 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.identifier, 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, isTypeName); | |
| } | |
| 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, 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!.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, isTypeName); | |
| expect((parameter.type as TypeName).name.name, 'int'); | |
| expect(parameters[1], isSimpleFormalParameter); | |
| parameter = parameters[1] as SimpleFormalParameter; | |
| expect(parameter.identifier, isNull); | |
| expect(parameter.type, isTypeName); | |
| expect((parameter.type as TypeName).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 TypeName; | |
| 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, isTypeName); | |
| expect((parameter.type as TypeName).name.name, 'String'); | |
| expect(parameters[1], isSimpleFormalParameter); | |
| parameter = parameters[1] as SimpleFormalParameter; | |
| expect(parameter.identifier, isNotNull); | |
| expect(parameter.identifier!.name, 'i'); | |
| expect(parameter.type, isTypeName); | |
| expect((parameter.type as TypeName).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 typeName = parser.parseTypeAnnotation(false) as TypeName; | |
| expectNotNullIfNoErrors(typeName); | |
| 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 TypeName; | |
| 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 TypeName; | |
| 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 TypeName; | |
| 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 TypeName; | |
| 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>'); | |
| TypeName typeName = parser.parseTypeName(false); | |
| expectNotNullIfNoErrors(typeName); | |
| assertNoErrors(); | |
| expect(typeName.name, isNotNull); | |
| expect(typeName.typeArguments, isNotNull); | |
| } | |
| void test_parseTypeName_simple() { | |
| createParser('int'); | |
| TypeName typeName = parser.parseTypeName(false); | |
| expectNotNullIfNoErrors(typeName); | |
| assertNoErrors(); | |
| expect(typeName.name, isNotNull); | |
| expect(typeName.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, isTypeName); | |
| 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, isTypeName); | |
| 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 TypeName; | |
| 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 TypeName; | |
| 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;', featureSet: nonNullable) | |
| 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;', featureSet: nonNullable) | |
| 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;', featureSet: nonNullable) | |
| 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;', featureSet: nonNullable) | |
| 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;', featureSet: nonNullable) | |
| 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;', featureSet: nonNullable) | |
| 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;', featureSet: nonNullable) | |
| 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); | |
| } | |
| } |