// 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 parseIdentifierList(String identifiers) { createParser('show $identifiers'); List 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(()); }', 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()); var literal = result as IntegerLiteral; expect(literal.value, 3); } test_parseArgument_named() { Expression result = parseArgument('foo: "a"'); expect(result, const TypeMatcher()); 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 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 arguments = argumentList.arguments; expect(arguments, hasLength(4)); } void test_parseArgumentList_noNamed() { createParser('(x, y, z)'); ArgumentList argumentList = parser.parseArgumentList(); expectNotNullIfNoErrors(argumentList); assertNoErrors(); NodeList arguments = argumentList.arguments; expect(arguments, hasLength(3)); } void test_parseArgumentList_onlyNamed() { createParser('(x: x, y: y)'); ArgumentList argumentList = parser.parseArgumentList(); expectNotNullIfNoErrors(argumentList); assertNoErrors(); NodeList arguments = argumentList.arguments; expect(arguments, hasLength(2)); } void test_parseArgumentList_trailing_comma() { createParser('(x, y, z,)'); ArgumentList argumentList = parser.parseArgumentList(); expectNotNullIfNoErrors(argumentList); assertNoErrors(); NodeList arguments = argumentList.arguments; expect(arguments, hasLength(3)); } void test_parseArgumentList_typeArguments() { createParser('(a(d))'); ArgumentList argumentList = parser.parseArgumentList(); expectNotNullIfNoErrors(argumentList); assertNoErrors(); NodeList arguments = argumentList.arguments; expect(arguments, hasLength(1)); } void test_parseArgumentList_typeArguments_none() { createParser('(a(d))'); ArgumentList argumentList = parser.parseArgumentList(); expectNotNullIfNoErrors(argumentList); assertNoErrors(); NodeList arguments = argumentList.arguments; expect(arguments, hasLength(2)); } void test_parseArgumentList_typeArguments_prefixed() { createParser('(a(d))'); ArgumentList argumentList = parser.parseArgumentList(); expectNotNullIfNoErrors(argumentList); assertNoErrors(); NodeList arguments = argumentList.arguments; expect(arguments, hasLength(1)); } void test_parseCombinators_h() { createParser('hide a'); List 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 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 combinators = parser.parseCombinators(); expectNotNullIfNoErrors(combinators); assertNoErrors(); expect(combinators, hasLength(4)); } void test_parseCombinators_s() { createParser('show a'); List 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 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 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 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 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 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 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 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 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 tokens = [token]; createParser(''); List 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 references = parser.parseCommentReferences([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 references = parser.parseCommentReferences([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 tokens = [ DocumentationCommentToken( TokenType.SINGLE_LINE_COMMENT, "/// xxx [a] yyy [b] zzz", 3), DocumentationCommentToken(TokenType.SINGLE_LINE_COMMENT, "/// x [c]", 28) ]; createParser(''); List 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 tokens = [ DocumentationCommentToken(TokenType.MULTI_LINE_COMMENT, "/**\n * a[i]\n * non-code line\n */", 3) ]; createParser(''); List references = parser.parseCommentReferences(tokens); expectNotNullIfNoErrors(references); assertNoErrors(); expect(references, isEmpty); } void test_parseCommentReferences_skipCodeBlock_4spaces_lines() { List tokens = [ DocumentationCommentToken( TokenType.SINGLE_LINE_COMMENT, "/// Code block:", 0), DocumentationCommentToken( TokenType.SINGLE_LINE_COMMENT, "/// a[i] == b[i]", 0) ]; createParser(''); List references = parser.parseCommentReferences(tokens); expectNotNullIfNoErrors(references); assertNoErrors(); expect(references, isEmpty); } void test_parseCommentReferences_skipCodeBlock_bracketed() { List tokens = [ DocumentationCommentToken( TokenType.MULTI_LINE_COMMENT, "/** [:xxx [a] yyy:] [b] zzz */", 3) ]; createParser(''); List 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 tokens = [ DocumentationCommentToken( TokenType.MULTI_LINE_COMMENT, "/** `a[i]` and [b] */", 0) ]; createParser(''); List 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 tokens = [ DocumentationCommentToken( TokenType.MULTI_LINE_COMMENT, r''' /** * First. * ```dart * Some [int] reference. * ``` * Last. */ ''', 3) ]; createParser(''); List 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 tokens = commentText .split('\n') .map((line) => DocumentationCommentToken(TokenType.SINGLE_LINE_COMMENT, line, 0)) .toList(); createParser(''); List references = parser.parseCommentReferences(tokens); expectNotNullIfNoErrors(references); assertNoErrors(); expect(references, isEmpty); } void test_parseCommentReferences_skipCodeBlock_gitHub_notTerminated() { List tokens = [ DocumentationCommentToken( TokenType.MULTI_LINE_COMMENT, "/** `a[i] and [b] */", 0) ]; createParser(''); List references = parser.parseCommentReferences(tokens); expectNotNullIfNoErrors(references); assertNoErrors(); expect(references, hasLength(2)); } void test_parseCommentReferences_skipCodeBlock_spaces() { List tokens = [ DocumentationCommentToken(TokenType.MULTI_LINE_COMMENT, "/**\n * a[i]\n * xxx [i] zzz\n */", 3) ]; createParser(''); List 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 tokens = [ DocumentationCommentToken( TokenType.MULTI_LINE_COMMENT, ''' /** * [a link split across multiple * lines](http://www.google.com) [b] zzz */ ''', 3) ]; createParser(''); List 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 tokens = [ DocumentationCommentToken(TokenType.MULTI_LINE_COMMENT, "/** [a](http://www.google.com) [b] zzz */", 3) ]; createParser(''); List 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 tokens = [ DocumentationCommentToken( TokenType.MULTI_LINE_COMMENT, ''' /** * [a link split across multiple * lines][c] [b] zzz */ ''', 3) ]; createParser(''); List 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 tokens = [ DocumentationCommentToken( TokenType.MULTI_LINE_COMMENT, "/** [a][c] [b] zzz */", 3) ]; createParser(''); List 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 tokens = [ DocumentationCommentToken(TokenType.MULTI_LINE_COMMENT, "/** [a]: http://www.google.com (Google) [b] zzz */", 3) ]; createParser(''); List 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 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 list = parseIdentifierList('a, b, c'); expectNotNullIfNoErrors(list); assertNoErrors(); expect(list, hasLength(3)); } void test_parseIdentifierList_single() { List 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.sync(() => 3).then((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 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.sync(() => 3).then((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 typeArg = init.typeArguments!.arguments; expect(typeArg, hasLength(1)); expect(typeArg[0].beginToken.lexeme, 'int'); } void test_parseInstanceCreation_noKeyword_noPrefix() { enableOptionalNewAndConst = true; createParser('f() => C.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'); 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.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'); 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.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'); expect(constructorName.period, isNotNull); expect(constructorName.name, isNotNull); expect(creation.argumentList, isNotNull); } void test_parseInstanceCreation_noKeyword_varInit() { enableOptionalNewAndConst = true; createParser(''' class C {} void main() {final c = C();} '''); 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(), ''); } 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 ;', 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(core.List 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 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()'); 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(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 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 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 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 Function()'); 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 Function(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 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'); 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(''); 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('>'); 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('>'); 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('>>'); 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(''); 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'); 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'); 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(''); 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('>=', 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('>=', 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('<', 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('=', 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(());', 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); } }