blob: 02929347ead95ed96115b300d082e814cbf97ff1 [file]
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../../diagnostics/parser_diagnostics.dart';
import '../resolution/node_text_expectations.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(DocCommentParserTest);
defineReflectiveTests(UpdateNodeTextExpectations);
});
}
@reflectiveTest
class DocCommentParserTest extends ParserDiagnosticsTest {
test_animationDirective_namedArgument_blankValue() {
var parseResult = parseTestCodeWithDiagnostics(r'''
int x = 0;
/// Text.
/// {@animation 600 400 http://google.com arg=}
class A {}
''');
var node = parseResult.findNode.comment('animation');
assertParsedNodeText(node, r'''
Comment
tokens
/// Text.
/// {@animation 600 400 http://google.com arg=}
docDirectives
SimpleDocDirective
tag
offset: [26, 69]
type: [DocDirectiveType.animation]
positionalArguments
600
400
http://google.com
namedArguments
arg=
''');
}
test_animationDirective_namedArgument_missingClosingBrace() {
var parseResult = parseTestCodeWithDiagnostics(r'''
int x = 0;
/// Text.
/// {@animation 600 400 http://google.com arg=value
// ^
// [diag.docDirectiveMissingClosingBrace] Doc directive is missing a closing curly brace ('}').
class A {}
''');
var node = parseResult.findNode.comment('animation');
assertParsedNodeText(node, r'''
Comment
tokens
/// Text.
/// {@animation 600 400 http://google.com arg=value
docDirectives
SimpleDocDirective
tag
offset: [26, 73]
type: [DocDirectiveType.animation]
positionalArguments
600
400
http://google.com
namedArguments
arg=value
''');
}
test_animationDirective_namedArgument_missingValueAndClosingBrace() async {
var parseResult = parseTestCodeWithDiagnostics(r'''
int x = 0;
/// Text.
/// {@animation 600 400 http://google.com arg=
// ^
// [diag.docDirectiveMissingClosingBrace] Doc directive is missing a closing curly brace ('}').
class A {}
''');
var node = parseResult.findNode.comment('animation');
assertParsedNodeText(node, r'''
Comment
tokens
/// Text.
/// {@animation 600 400 http://google.com arg=
docDirectives
SimpleDocDirective
tag
offset: [26, 68]
type: [DocDirectiveType.animation]
positionalArguments
600
400
http://google.com
namedArguments
arg=
''');
}
test_codeSpan() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// `a[i]` and [b].
class A {}
''');
var node = parseResult.findNode.comment('a[i]');
// TODO(srawlins): Parse code into its own node.
assertParsedNodeText(node, r'''
Comment
references
CommentReference
components
CommentReferenceComponent
name: b
expression: SimpleIdentifier
token: b
tokens
/// `a[i]` and [b].
''');
}
test_codeSpan_legacy_blockComment() {
// TODO(srawlins): I believe we should drop support for `[:` `:]`.
var parseResult = parseTestCodeWithDiagnostics(r'''
/** [:xxx [a] yyy:] [b] zzz */
class A {}
''');
var node = parseResult.findNode.comment('[a]');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
components
CommentReferenceComponent
name: b
expression: SimpleIdentifier
token: b
tokens
/** [:xxx [a] yyy:] [b] zzz */
''');
}
test_codeSpan_unterminated_blockComment() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/** `a[i] and [b] */
class A {}
''');
var node = parseResult.findNode.comment('a[');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
components
CommentReferenceComponent
name: i
expression: SimpleIdentifier
token: i
CommentReference
components
CommentReferenceComponent
name: b
expression: SimpleIdentifier
token: b
tokens
/** `a[i] and [b] */
''');
}
test_codeSpan_unterminated_blockComment_fenced() {
// https://github.com/Dart-Code/Dart-Code/issues/6154
var parseResult = parseTestCodeWithDiagnostics(r'''
/**
* Test
* ```dart
* void foo() {}
*
* `
*/
class C;
''');
var node = parseResult.findNode.comment('Test');
assertParsedNodeText(node, r'''
Comment
tokens
/**
* Test
* ```dart
* void foo() {}
*
* `
*/
codeBlocks
MdCodeBlock
infoString: dart
type: CodeBlockType.fenced
lines
MdCodeBlockLine
offset: 17
length: 7
MdCodeBlockLine
offset: 29
length: 13
MdCodeBlockLine
offset: 46
length: 0
MdCodeBlockLine
offset: 51
length: 1
''');
}
/// Check we only exclude the end-of-comment marker and not anything else on
/// the same line.
test_codeSpan_unterminated_blockComment_fenced_endOfCommentMarkerOnPreviousLine() {
// https://github.com/Dart-Code/Dart-Code/issues/6154
var parseResult = parseTestCodeWithDiagnostics(r'''
/**
* Test
* ```dart
* code*/
class C;
''');
var node = parseResult.findNode.comment('Test');
assertParsedNodeText(node, r'''
Comment
tokens
/**
* Test
* ```dart
* code*/
codeBlocks
MdCodeBlock
infoString: dart
type: CodeBlockType.fenced
lines
MdCodeBlockLine
offset: 17
length: 7
MdCodeBlockLine
offset: 29
length: 4
''');
}
void test_commentReference_beforeAbstractClass() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/** [String] */ abstract class A {}
''');
var node = parseResult.findNode.classDeclaration('class A');
assertParsedNodeText(node, r'''
ClassDeclaration
documentationComment: Comment
references
CommentReference
components
CommentReferenceComponent
name: String @5
expression: SimpleIdentifier
token: String @5
tokens
/** [String] */ @0
abstractKeyword: abstract @16
classKeyword: class @25
namePart: NameWithTypeParameters
typeName: A @31
body: BlockClassBody
leftBracket: { @33
rightBracket: } @34
''', withOffsets: true);
}
void test_commentReference_beforeAnnotatedClass() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// See [int] and [String]
/// and [Object].
@Annotation
abstract class A {}
''');
var node = parseResult.findNode.classDeclaration('class A');
assertParsedNodeText(node, r'''
ClassDeclaration
documentationComment: Comment
references
CommentReference
components
CommentReferenceComponent
name: int @9
expression: SimpleIdentifier
token: int @9
CommentReference
components
CommentReferenceComponent
name: String @19
expression: SimpleIdentifier
token: String @19
CommentReference
components
CommentReferenceComponent
name: Object @36
expression: SimpleIdentifier
token: Object @36
tokens
/// See [int] and [String] @0
/// and [Object]. @27
metadata
Annotation
atSign: @ @45
expression: ParsedUnqualifiedName
name: Annotation @46
name: SimpleIdentifier
token: Annotation @46
abstractKeyword: abstract @57
classKeyword: class @66
namePart: NameWithTypeParameters
typeName: A @72
body: BlockClassBody
leftBracket: { @74
rightBracket: } @75
''', withOffsets: true);
}
test_commentReference_blockComment() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/** [a]. */
class A {}
''');
var node = parseResult.findNode.comment('[a]');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
components
CommentReferenceComponent
name: a
expression: SimpleIdentifier
token: a
tokens
/** [a]. */
''');
}
void test_commentReference_complexBeforeClass() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// 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 A {}
''');
var node = parseResult.findNode.classDeclaration('class A');
assertParsedNodeText(node, r'''
ClassDeclaration
documentationComment: Comment
references
CommentReference
components
CommentReferenceComponent
name: included @86
expression: SimpleIdentifier
token: included @86
CommentReference
components
CommentReferenceComponent
name: int @143
expression: SimpleIdentifier
token: int @143
CommentReference
components
CommentReferenceComponent
name: String @153
expression: SimpleIdentifier
token: String @153
CommentReference
components
CommentReferenceComponent
name: Object @240
expression: SimpleIdentifier
token: Object @240
tokens
/// This dartdoc comment is [included]. @57
/// See [int] and [String] but `not [a]` @134
/// ``` @175
/// This [code] block should be ignored @183
/// ``` @223
/// and [Object]. @231
codeBlocks
MdCodeBlock
infoString: <empty>
type: CodeBlockType.fenced
lines
MdCodeBlockLine
offset: 179
length: 3
MdCodeBlockLine
offset: 187
length: 35
MdCodeBlockLine
offset: 227
length: 3
metadata
Annotation
atSign: @ @45
expression: ParsedUnqualifiedName
name: Annotation @46
name: SimpleIdentifier
token: Annotation @46
abstractKeyword: abstract @249
classKeyword: class @258
namePart: NameWithTypeParameters
typeName: A @264
body: BlockClassBody
leftBracket: { @266
rightBracket: } @267
''', withOffsets: true);
}
test_commentReference_empty() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// [].
class A {}
''');
var node = parseResult.findNode.comment('[]');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
components
CommentReferenceComponent
name: <empty> <synthetic>
expression: SimpleIdentifier
token: <empty> <synthetic>
tokens
/// [].
''');
}
test_commentReference_followedByColon() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// Regarding [a]: it's an A.
class A {}
''');
var node = parseResult.findNode.comment('[a]');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
components
CommentReferenceComponent
name: a
expression: SimpleIdentifier
token: a
tokens
/// Regarding [a]: it's an A.
''');
}
test_commentReference_incomplete_prefixed() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// [p.A.]
void f() {}
''');
assertParsedNodeText(parseResult.findNode.singleCommentReference, r'''
CommentReference
components
CommentReferenceComponent
name: p @5
CommentReferenceComponent
period: . @6
name: A @7
CommentReferenceComponent
period: . @8
name: <empty> @9 <synthetic>
expression: PropertyAccess
target: PrefixedIdentifier
prefix: SimpleIdentifier
token: p @5
period: . @6
identifier: SimpleIdentifier
token: A @7
operator: . @8
propertyName: SimpleIdentifier
token: <empty> @9 <synthetic>
''', withOffsets: true);
}
test_commentReference_multiple() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// [a] and [b].
class A {}
''');
var node = parseResult.findNode.comment('[a]');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
components
CommentReferenceComponent
name: a
expression: SimpleIdentifier
token: a
CommentReference
components
CommentReferenceComponent
name: b
expression: SimpleIdentifier
token: b
tokens
/// [a] and [b].
''');
}
test_commentReference_multiple_blockComment() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/** [a] and [b]. */
class A {}
''');
var node = parseResult.findNode.comment('[a]');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
components
CommentReferenceComponent
name: a
expression: SimpleIdentifier
token: a
CommentReference
components
CommentReferenceComponent
name: b
expression: SimpleIdentifier
token: b
tokens
/** [a] and [b]. */
''');
}
test_commentReference_new_prefixed() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// [new a.A].
class B {}
''');
var node = parseResult.findNode.comment('new');
assertParsedNodeText(node, r'''
Comment
tokens
/// [new a.A].
''');
}
test_commentReference_new_simple() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// [new A].
class B {}
''');
var node = parseResult.findNode.comment('new');
assertParsedNodeText(node, r'''
Comment
tokens
/// [new A].
''');
}
test_commentReference_operator_threeComponents() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// [p.A.operator +]
void f() {}
''');
assertParsedNodeText(parseResult.findNode.singleCommentReference, r'''
CommentReference
components
CommentReferenceComponent
name: p @5
CommentReferenceComponent
period: . @6
name: A @7
CommentReferenceComponent
period: . @8
operatorKeyword: operator @9
name: + @18
expression: PropertyAccess
target: PrefixedIdentifier
prefix: SimpleIdentifier
token: p @5
period: . @6
identifier: SimpleIdentifier
token: A @7
operator: . @8
propertyName: SimpleIdentifier
token: + @18
''', withOffsets: true);
}
test_commentReference_operator_withKeyword_notPrefixed() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// [operator ==].
class A {}
''');
var node = parseResult.findNode.comment('==');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
components
CommentReferenceComponent
operatorKeyword: operator
name: ==
expression: SimpleIdentifier
token: ==
tokens
/// [operator ==].
''');
}
test_commentReference_operator_withKeyword_prefixed() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// [Object.operator ==].
class A {}
''');
var node = parseResult.findNode.comment('==');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
components
CommentReferenceComponent
name: Object
CommentReferenceComponent
period: .
operatorKeyword: operator
name: ==
expression: PrefixedIdentifier
prefix: SimpleIdentifier
token: Object
period: .
identifier: SimpleIdentifier
token: ==
tokens
/// [Object.operator ==].
''');
}
test_commentReference_operator_withoutKeyword_notPrefixed() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// [==].
class A {}
''');
var node = parseResult.findNode.comment('==');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
components
CommentReferenceComponent
name: ==
expression: SimpleIdentifier
token: ==
tokens
/// [==].
''');
}
test_commentReference_operator_withoutKeyword_prefixed() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// [Object.==].
class A {}
''');
var node = parseResult.findNode.comment('==');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
components
CommentReferenceComponent
name: Object
CommentReferenceComponent
period: .
name: ==
expression: PrefixedIdentifier
prefix: SimpleIdentifier
token: Object
period: .
identifier: SimpleIdentifier
token: ==
tokens
/// [Object.==].
''');
}
test_commentReference_prefixedIdentifier() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// [a.b].
class A {}
''');
var node = parseResult.findNode.comment('a.b');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
components
CommentReferenceComponent
name: a
CommentReferenceComponent
period: .
name: b
expression: PrefixedIdentifier
prefix: SimpleIdentifier
token: a
period: .
identifier: SimpleIdentifier
token: b
tokens
/// [a.b].
''');
}
test_commentReference_simpleIdentifier() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// [a].
class A {}
''');
var node = parseResult.findNode.comment('[a]');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
components
CommentReferenceComponent
name: a
expression: SimpleIdentifier
token: a
tokens
/// [a].
''');
}
test_commentReference_this() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// [this].
class A {}
''');
var node = parseResult.findNode.comment('this');
// TODO(srawlins): I think there is an intention to parse this as a comment
// reference.
assertParsedNodeText(node, r'''
Comment
tokens
/// [this].
''');
}
test_docImport() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// @docImport 'dart:html';
class A {}
''');
var node = parseResult.findNode.comment('docImport');
assertParsedNodeText(node, r'''
Comment
tokens
/// @docImport 'dart:html';
docImports
DocImport
offset: 4
import: ImportDirective
importKeyword: import
uri: SimpleStringLiteral
literal: 'dart:html'
semicolon: ;
''');
}
test_docImport_multiple() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// One.
/// @docImport 'dart:html';
/// @docImport 'dart:io';
class A {}
''');
var node = parseResult.findNode.comment('dart:html');
assertParsedNodeText(node, r'''
Comment
tokens
/// One.
/// @docImport 'dart:html';
/// @docImport 'dart:io';
docImports
DocImport
offset: 13
import: ImportDirective
importKeyword: import
uri: SimpleStringLiteral
literal: 'dart:html'
semicolon: ;
DocImport
offset: 41
import: ImportDirective
importKeyword: import
uri: SimpleStringLiteral
literal: 'dart:io'
semicolon: ;
''');
}
test_docImport_nonTerminated() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// @docImport 'dart:html'
// ^^^^^^^^^^^
// [diag.expectedToken] Expected to find ';'.
class A {}
''');
var node = parseResult.findNode.comment('docImport');
assertParsedNodeText(node, r'''
Comment
tokens
/// @docImport 'dart:html'
docImports
DocImport
offset: 4
import: ImportDirective
importKeyword: import
uri: SimpleStringLiteral
literal: 'dart:html'
semicolon: ; <synthetic>
''');
}
test_docImport_parseError() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// @docImport html
// ^^^^^^
// [diag.expectedToken] Expected to find ';'.
// ^^^^
// [diag.expectedStringLiteral] Expected a string literal.
// [diag.missingConstFinalVarOrType] Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
// [diag.expectedToken] Expected to find ';'.
class A {}
''');
var node = parseResult.findNode.comment('docImport');
assertParsedNodeText(node, r'''
Comment
tokens
/// @docImport html
docImports
DocImport
offset: 4
import: ImportDirective
importKeyword: import
uri: SimpleStringLiteral
literal: "" <synthetic>
semicolon: ; <synthetic>
''');
}
test_docImport_prefixed() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// @docImport 'dart:html' as html;
class A {}
''');
var node = parseResult.findNode.comment('docImport');
assertParsedNodeText(node, r'''
Comment
tokens
/// @docImport 'dart:html' as html;
docImports
DocImport
offset: 4
import: ImportDirective
importKeyword: import
uri: SimpleStringLiteral
literal: 'dart:html'
asKeyword: as
prefixName: html
semicolon: ;
prefix: SimpleIdentifier
token: html
''');
}
test_docImport_show() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// @docImport 'dart:html' show Element, HtmlElement;
class A {}
''');
var node = parseResult.findNode.comment('docImport');
assertParsedNodeText(node, r'''
Comment
tokens
/// @docImport 'dart:html' show Element, HtmlElement;
docImports
DocImport
offset: 4
import: ImportDirective
importKeyword: import
uri: SimpleStringLiteral
literal: 'dart:html'
combinators
ShowCombinator
keyword: show
names
CombinatorName
name: Element
CombinatorName
name: HtmlElement
shownNames
SimpleIdentifier
token: Element
SimpleIdentifier
token: HtmlElement
semicolon: ;
''');
}
test_docImport_unterminatedString() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// @docImport 'dart:html;
// ^^^^^^^^^^^
// [diag.expectedToken] Expected to find ';'.
// ^
// [diag.unterminatedStringLiteral] Unterminated string literal.
class A {}
''');
var node = parseResult.findNode.comment('docImport');
assertParsedNodeText(node, r'''
Comment
tokens
/// @docImport 'dart:html;
docImports
DocImport
offset: 4
import: ImportDirective
importKeyword: import
uri: SimpleStringLiteral
literal: 'dart:html;' <synthetic>
semicolon: ; <synthetic>
''');
}
test_docImport_withOtherData() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// ```dart
/// x;
/// ```
/// @docImport 'dart:html';
/// ```dart
/// y;
/// ```
class A {}
''');
var node = parseResult.findNode.comment('docImport');
assertParsedNodeText(node, r'''
Comment
tokens
/// ```dart
/// x;
/// ```
/// @docImport 'dart:html';
/// ```dart
/// y;
/// ```
codeBlocks
MdCodeBlock
infoString: dart
type: CodeBlockType.fenced
lines
MdCodeBlockLine
offset: 4
length: 7
MdCodeBlockLine
offset: 16
length: 2
MdCodeBlockLine
offset: 23
length: 3
MdCodeBlock
infoString: dart
type: CodeBlockType.fenced
lines
MdCodeBlockLine
offset: 59
length: 7
MdCodeBlockLine
offset: 71
length: 2
MdCodeBlockLine
offset: 78
length: 3
docImports
DocImport
offset: 31
import: ImportDirective
importKeyword: import
uri: SimpleStringLiteral
literal: 'dart:html'
semicolon: ;
''');
}
test_endTemplate_missingOpeningTag() {
var parseResult = parseTestCodeWithDiagnostics(r'''
int x = 0;
/// Text.
/// {@endtemplate}
// ^^^^^^^^^^^^^^
// [diag.docDirectiveMissingOpeningTag] Doc directive is missing an opening tag.
/// More text.
class A {}
''');
var node = parseResult.findNode.comment('endtemplate');
assertParsedNodeText(node, r'''
Comment
tokens
/// Text.
/// {@endtemplate}
/// More text.
docDirectives
SimpleDocDirective
tag
offset: [26, 40]
type: [DocDirectiveType.endTemplate]
''');
}
test_exampleDirective() {
var parseResult = parseTestCodeWithDiagnostics(r'''
int x = 0;
/// Text.
/// {@example /path/to/file.dart#region}
class A {}
''');
var node = parseResult.findNode.comment('example');
assertParsedNodeText(node, r'''
Comment
tokens
/// Text.
/// {@example /path/to/file.dart#region}
docDirectives
SimpleDocDirective
tag
offset: [26, 62]
type: [DocDirectiveType.example]
positionalArguments
/path/to/file.dart#region
''');
}
test_exampleDirective_args() {
var parseResult = parseTestCodeWithDiagnostics(r'''
int x = 0;
/// Text.
/// {@example /path/to/file.dart#region lang=dart indent=keep}
class A {}
''');
var node = parseResult.findNode.comment('example');
assertParsedNodeText(node, r'''
Comment
tokens
/// Text.
/// {@example /path/to/file.dart#region lang=dart indent=keep}
docDirectives
SimpleDocDirective
tag
offset: [26, 84]
type: [DocDirectiveType.example]
positionalArguments
/path/to/file.dart#region
namedArguments
lang=dart
indent=keep
''');
}
test_fencedCodeBlock_atStart() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// ```
/// Two.
/// ```
class A {}
''');
var node = parseResult.findNode.comment('Two.');
assertParsedNodeText(node, r'''
Comment
tokens
/// ```
/// Two.
/// ```
codeBlocks
MdCodeBlock
infoString: <empty>
type: CodeBlockType.fenced
lines
MdCodeBlockLine
offset: 4
length: 3
MdCodeBlockLine
offset: 12
length: 4
MdCodeBlockLine
offset: 21
length: 3
''');
}
test_fencedCodeBlock_blockComment() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/**
* One.
* ```
* a[i] = b[i];
* ```
* Two.
* ```dart
* code;
* ```
* Three.
*/
class A {}
''');
var node = parseResult.findNode.comment('a[i]');
assertParsedNodeText(node, r'''
Comment
tokens
/**
* One.
* ```
* a[i] = b[i];
* ```
* Two.
* ```dart
* code;
* ```
* Three.
*/
codeBlocks
MdCodeBlock
infoString: <empty>
type: CodeBlockType.fenced
lines
MdCodeBlockLine
offset: 15
length: 3
MdCodeBlockLine
offset: 22
length: 12
MdCodeBlockLine
offset: 38
length: 3
MdCodeBlock
infoString: dart
type: CodeBlockType.fenced
lines
MdCodeBlockLine
offset: 53
length: 7
MdCodeBlockLine
offset: 64
length: 5
MdCodeBlockLine
offset: 73
length: 3
''');
}
test_fencedCodeBlock_blockComment_atStart() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/**
* ```
* a[i] = b[i];
* ```
*/
class A {}
''');
var node = parseResult.findNode.comment('a[i]');
assertParsedNodeText(node, r'''
Comment
tokens
/**
* ```
* a[i] = b[i];
* ```
*/
codeBlocks
MdCodeBlock
infoString: <empty>
type: CodeBlockType.fenced
lines
MdCodeBlockLine
offset: 7
length: 3
MdCodeBlockLine
offset: 14
length: 12
MdCodeBlockLine
offset: 30
length: 3
''');
}
test_fencedCodeBlock_empty() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// ```
/// ```
/// Text.
class A {}
''');
var node = parseResult.findNode.comment('Text.');
assertParsedNodeText(node, r'''
Comment
tokens
/// ```
/// ```
/// Text.
codeBlocks
MdCodeBlock
infoString: <empty>
type: CodeBlockType.fenced
lines
MdCodeBlockLine
offset: 4
length: 3
MdCodeBlockLine
offset: 12
length: 3
''');
}
test_fencedCodeBlock_leadingSpaces() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// ```
/// a[i] = b[i];
/// ```
class A {}
''');
var node = parseResult.findNode.comment('a[i]');
assertParsedNodeText(node, r'''
Comment
tokens
/// ```
/// a[i] = b[i];
/// ```
codeBlocks
MdCodeBlock
infoString: <empty>
type: CodeBlockType.fenced
lines
MdCodeBlockLine
offset: 4
length: 5
MdCodeBlockLine
offset: 14
length: 14
MdCodeBlockLine
offset: 33
length: 5
''');
}
test_fencedCodeBlock_moreThanThreeBackticks() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// ````dart
/// A code block can contain multiple backticks, as long as it is fewer than
/// the amount in the opening:
/// ```
/// `````
class A {}
''');
var node = parseResult.findNode.comment('A code');
assertParsedNodeText(node, r'''
Comment
tokens
/// ````dart
/// A code block can contain multiple backticks, as long as it is fewer than
/// the amount in the opening:
/// ```
/// `````
codeBlocks
MdCodeBlock
infoString: dart
type: CodeBlockType.fenced
lines
MdCodeBlockLine
offset: 4
length: 8
MdCodeBlockLine
offset: 17
length: 72
MdCodeBlockLine
offset: 94
length: 26
MdCodeBlockLine
offset: 125
length: 3
MdCodeBlockLine
offset: 133
length: 5
''');
}
test_fencedCodeBlock_noLeadingSpaces() {
var parseResult = parseTestCodeWithDiagnostics(r'''
///```
///a[i] = b[i];
///```
class A {}
''');
var node = parseResult.findNode.comment('a[i]');
assertParsedNodeText(node, r'''
Comment
tokens
///```
///a[i] = b[i];
///```
codeBlocks
MdCodeBlock
infoString: <empty>
type: CodeBlockType.fenced
lines
MdCodeBlockLine
offset: 3
length: 3
MdCodeBlockLine
offset: 10
length: 12
MdCodeBlockLine
offset: 26
length: 3
''');
}
test_fencedCodeBlock_nonDocCommentLines() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// One.
/// ```
// This is not part of the doc comment.
/// a[i] = b[i];
/// ```
/// Two.
class A {}
''');
var node = parseResult.findNode.comment('a[i]');
assertParsedNodeText(node, r'''
Comment
tokens
/// One.
/// ```
/// a[i] = b[i];
/// ```
/// Two.
codeBlocks
MdCodeBlock
infoString: <empty>
type: CodeBlockType.fenced
lines
MdCodeBlockLine
offset: 13
length: 3
MdCodeBlockLine
offset: 61
length: 12
MdCodeBlockLine
offset: 79
length: 3
''');
}
test_fencedCodeBlock_nonTerminating() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// One.
/// ```
/// a[i] = b[i];
class A {}
''');
var node = parseResult.findNode.comment('a[i]');
assertParsedNodeText(node, r'''
Comment
tokens
/// One.
/// ```
/// a[i] = b[i];
codeBlocks
MdCodeBlock
infoString: <empty>
type: CodeBlockType.fenced
lines
MdCodeBlockLine
offset: 13
length: 3
MdCodeBlockLine
offset: 21
length: 12
''');
}
test_fencedCodeBlock_nonZeroOffset() {
var parseResult = parseTestCodeWithDiagnostics(r'''
int x = 0;
/// One.
/// ```
/// a[i] = b[i];
/// ```
/// Two.
class A {}
''');
var node = parseResult.findNode.comment('a[i]');
assertParsedNodeText(node, r'''
Comment
tokens
/// One.
/// ```
/// a[i] = b[i];
/// ```
/// Two.
codeBlocks
MdCodeBlock
infoString: <empty>
type: CodeBlockType.fenced
lines
MdCodeBlockLine
offset: 25
length: 3
MdCodeBlockLine
offset: 33
length: 12
MdCodeBlockLine
offset: 50
length: 3
''');
}
test_fencedCodeBlock_precededByText() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// One. ```
/// Two.
/// ```
/// Three.
class A {}
''');
var node = parseResult.findNode.comment('Two.');
assertParsedNodeText(node, r'''
Comment
tokens
/// One. ```
/// Two.
/// ```
/// Three.
codeBlocks
MdCodeBlock
infoString: <empty>
type: CodeBlockType.fenced
lines
MdCodeBlockLine
offset: 26
length: 3
MdCodeBlockLine
offset: 34
length: 6
''');
}
/// Simple fenced code block to verify the offset/length of code block lines
/// for each comment type and line ending type.
test_fencedCodeBlock_simple_blockComment_crlf() {
var parseResult = parseTestCodeWithDiagnostics(
r'''
/**
* ```
* CODE
* ```
*/
class A {}
'''
.withCrLf,
);
var node = parseResult.findNode.comment('CODE');
assertParsedNodeText(node, '''
Comment
tokens
${"""/**
* ```
* CODE
* ```
*/""".withCrLf}
codeBlocks
MdCodeBlock
infoString: <empty>
type: CodeBlockType.fenced
lines
MdCodeBlockLine
offset: 8
length: 3
MdCodeBlockLine
offset: 16
length: 4
MdCodeBlockLine
offset: 25
length: 3
''');
}
/// Simple fenced code block to verify the offset/length of code block lines
/// for each comment type and line ending type.
test_fencedCodeBlock_simple_blockComment_lf() {
var parseResult = parseTestCodeWithDiagnostics(
r'''
/**
* ```
* CODE
* ```
*/
class A {}
'''
.withLf,
);
var node = parseResult.findNode.comment('CODE');
assertParsedNodeText(node, r'''
Comment
tokens
/**
* ```
* CODE
* ```
*/
codeBlocks
MdCodeBlock
infoString: <empty>
type: CodeBlockType.fenced
lines
MdCodeBlockLine
offset: 7
length: 3
MdCodeBlockLine
offset: 14
length: 4
MdCodeBlockLine
offset: 22
length: 3
''');
}
/// Simple fenced code block to verify the offset/length of code block lines
/// for each comment type and line ending type.
test_fencedCodeBlock_simple_crlf() {
var parseResult = parseTestCodeWithDiagnostics(
r'''
/// ```
/// CODE
/// ```
class A {}
'''
.withCrLf,
);
var node = parseResult.findNode.comment('CODE');
assertParsedNodeText(node, r'''
Comment
tokens
/// ```
/// CODE
/// ```
codeBlocks
MdCodeBlock
infoString: <empty>
type: CodeBlockType.fenced
lines
MdCodeBlockLine
offset: 4
length: 3
MdCodeBlockLine
offset: 13
length: 4
MdCodeBlockLine
offset: 23
length: 3
''');
}
/// Simple fenced code block to verify the offset/length of code block lines
/// for each comment type and line ending type.
test_fencedCodeBlock_simple_lf() {
var parseResult = parseTestCodeWithDiagnostics(
r'''
/// ```
/// CODE
/// ```
class A {}
'''
.withLf,
);
var node = parseResult.findNode.comment('CODE');
assertParsedNodeText(node, r'''
Comment
tokens
/// ```
/// CODE
/// ```
codeBlocks
MdCodeBlock
infoString: <empty>
type: CodeBlockType.fenced
lines
MdCodeBlockLine
offset: 4
length: 3
MdCodeBlockLine
offset: 12
length: 4
MdCodeBlockLine
offset: 21
length: 3
''');
}
test_fencedCodeBlocks() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// One.
/// ```
/// a[i] = b[i];
/// ```
/// Two.
/// ```dart
/// code;
/// ```
/// Three.
class A {}
''');
var node = parseResult.findNode.comment('a[i]');
assertParsedNodeText(node, r'''
Comment
tokens
/// One.
/// ```
/// a[i] = b[i];
/// ```
/// Two.
/// ```dart
/// code;
/// ```
/// Three.
codeBlocks
MdCodeBlock
infoString: <empty>
type: CodeBlockType.fenced
lines
MdCodeBlockLine
offset: 13
length: 3
MdCodeBlockLine
offset: 21
length: 12
MdCodeBlockLine
offset: 38
length: 3
MdCodeBlock
infoString: dart
type: CodeBlockType.fenced
lines
MdCodeBlockLine
offset: 55
length: 7
MdCodeBlockLine
offset: 67
length: 5
MdCodeBlockLine
offset: 77
length: 3
''');
}
test_indentedCodeBlock_afterBlankLine() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// Text.
///
/// a[i] = b[i];
class A {}
''');
var node = parseResult.findNode.comment('Text');
assertParsedNodeText(node, r'''
Comment
tokens
/// Text.
///
/// a[i] = b[i];
codeBlocks
MdCodeBlock
infoString: <empty>
type: CodeBlockType.indented
lines
MdCodeBlockLine
offset: 18
length: 16
''');
}
test_indentedCodeBlock_afterTextLine_notCodeBlock() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// Text.
/// a[i] = b[i];
class A {}
''');
var node = parseResult.findNode.comment('Text');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
components
CommentReferenceComponent
name: i
expression: SimpleIdentifier
token: i
CommentReference
components
CommentReferenceComponent
name: i
expression: SimpleIdentifier
token: i
tokens
/// Text.
/// a[i] = b[i];
''');
}
test_indentedCodeBlock_atStart() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// Two.
class A {}
''');
var node = parseResult.findNode.comment('Two.');
assertParsedNodeText(node, r'''
Comment
tokens
/// Two.
codeBlocks
MdCodeBlock
infoString: <empty>
type: CodeBlockType.indented
lines
MdCodeBlockLine
offset: 4
length: 8
''');
}
test_indentedCodeBlock_blockComment_atStart() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/**
* a[i] = b[i];
*/
class A {}
''');
var node = parseResult.findNode.comment('a[i]');
assertParsedNodeText(node, r'''
Comment
tokens
/**
* a[i] = b[i];
*/
codeBlocks
MdCodeBlock
infoString: <empty>
type: CodeBlockType.indented
lines
MdCodeBlockLine
offset: 7
length: 16
''');
}
test_indentedCodeBlock_firstLine() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// a[i] = b[i];
class A {}
''');
var node = parseResult.findNode.comment('a[i]');
assertParsedNodeText(node, r'''
Comment
tokens
/// a[i] = b[i];
codeBlocks
MdCodeBlock
infoString: <empty>
type: CodeBlockType.indented
lines
MdCodeBlockLine
offset: 4
length: 16
''');
}
test_indentedCodeBlock_firstLine_blockComment() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/**
*
* a[i] = b[i];
* [c].
*/
class A {}
''');
var node = parseResult.findNode.comment('a[i]');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
components
CommentReferenceComponent
name: c
expression: SimpleIdentifier
token: c
tokens
/**
*
* a[i] = b[i];
* [c].
*/
codeBlocks
MdCodeBlock
infoString: <empty>
type: CodeBlockType.indented
lines
MdCodeBlockLine
offset: 10
length: 16
''');
}
test_indentedCodeBlock_withFencedCodeBlock() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// Text.
/// ```
/// a[i] = b[i];
/// ```
/// More text.
class A {}
''');
var node = parseResult.findNode.comment('Text');
assertParsedNodeText(node, r'''
Comment
tokens
/// Text.
/// ```
/// a[i] = b[i];
/// ```
/// More text.
codeBlocks
MdCodeBlock
infoString: <empty>
type: CodeBlockType.fenced
lines
MdCodeBlockLine
offset: 14
length: 7
MdCodeBlockLine
offset: 26
length: 16
MdCodeBlockLine
offset: 47
length: 7
''');
}
test_inlineLink() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// [a](http://www.google.com) [b].
class A {}
''');
var node = parseResult.findNode.comment('[a]');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
components
CommentReferenceComponent
name: b
expression: SimpleIdentifier
token: b
tokens
/// [a](http://www.google.com) [b].
''');
}
test_linkReference() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// [a]: http://www.google.com Google [b]
class A {}
''');
var node = parseResult.findNode.comment('[a]');
// TODO(srawlins): Ideally this should not parse `[b]` as a comment
// reference.
assertParsedNodeText(node, r'''
Comment
references
CommentReference
components
CommentReferenceComponent
name: b
expression: SimpleIdentifier
token: b
tokens
/// [a]: http://www.google.com Google [b]
''');
}
test_nodoc_eol() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// Text.
///
/// @nodoc
class A {}
''');
var node = parseResult.findNode.comment('Text.');
assertParsedNodeText(node, r'''
Comment
tokens
/// Text.
///
/// @nodoc
hasNodoc: true
''');
}
test_nodoc_more() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// Text.
///
/// @nodocxx
class A {}
''');
var node = parseResult.findNode.comment('Text.');
assertParsedNodeText(node, r'''
Comment
tokens
/// Text.
///
/// @nodocxx
''');
}
test_nodoc_space() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// Text.
///
/// @nodoc This is not super public.
class A {}
''');
var node = parseResult.findNode.comment('Text.');
assertParsedNodeText(node, r'''
Comment
tokens
/// Text.
///
/// @nodoc This is not super public.
hasNodoc: true
''');
}
test_onlyWhitespace() {
var parseResult = parseTestCodeWithDiagnostics('''
///${" "}
class A {}
''');
var node = parseResult.findNode.comment(' ');
assertParsedNodeText(node, '''
Comment
tokens
///${" "}
''');
}
test_referenceLink() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// [a link][c] [b].
class A {}
''');
var node = parseResult.findNode.comment('[a');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
components
CommentReferenceComponent
name: b
expression: SimpleIdentifier
token: b
tokens
/// [a link][c] [b].
''');
}
test_referenceLink_multiline() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// [a link split across multiple
/// lines][c] [b].
class A {}
''');
var node = parseResult.findNode.comment('[a');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
components
CommentReferenceComponent
name: a
expression: SimpleIdentifier
token: a
CommentReference
components
CommentReferenceComponent
name: b
expression: SimpleIdentifier
token: b
tokens
/// [a link split across multiple
/// lines][c] [b].
''');
}
test_template() {
var parseResult = parseTestCodeWithDiagnostics(r'''
int x = 0;
/// Text.
/// {@template name}
/// More text.
/// {@endtemplate}
class A {}
''');
var node = parseResult.findNode.comment('template name');
assertParsedNodeText(node, r'''
Comment
tokens
/// Text.
/// {@template name}
/// More text.
/// {@endtemplate}
docDirectives
BlockDocDirective
openingTag
offset: [26, 42]
type: [DocDirectiveType.template]
positionalArguments
name
closingTag
offset: [62, 76]
type: [DocDirectiveType.endTemplate]
''');
}
test_template_containingInnerTags() {
var parseResult = parseTestCodeWithDiagnostics(r'''
int x = 0;
/// Text.
/// {@template name}
/// More text.
/// {@macro name}
/// {@endtemplate}
class A {}
''');
var node = parseResult.findNode.comment('template name');
assertParsedNodeText(node, r'''
Comment
tokens
/// Text.
/// {@template name}
/// More text.
/// {@macro name}
/// {@endtemplate}
docDirectives
BlockDocDirective
openingTag
offset: [26, 42]
type: [DocDirectiveType.template]
positionalArguments
name
closingTag
offset: [80, 94]
type: [DocDirectiveType.endTemplate]
SimpleDocDirective
tag
offset: [62, 75]
type: [DocDirectiveType.macro]
positionalArguments
name
''');
}
test_template_containingInnerTemplate() {
var parseResult = parseTestCodeWithDiagnostics(r'''
int x = 0;
/// Text.
/// {@template name}
/// More text.
/// {@template name2}
/// Text three.
/// {@endtemplate}
/// Text four.
/// {@endtemplate}
class A {}
''');
var node = parseResult.findNode.comment('template name2');
assertParsedNodeText(node, r'''
Comment
tokens
/// Text.
/// {@template name}
/// More text.
/// {@template name2}
/// Text three.
/// {@endtemplate}
/// Text four.
/// {@endtemplate}
docDirectives
BlockDocDirective
openingTag
offset: [26, 42]
type: [DocDirectiveType.template]
positionalArguments
name
closingTag
offset: [134, 148]
type: [DocDirectiveType.endTemplate]
BlockDocDirective
openingTag
offset: [62, 79]
type: [DocDirectiveType.template]
positionalArguments
name2
closingTag
offset: [100, 114]
type: [DocDirectiveType.endTemplate]
''');
}
test_template_missingClosingTag() {
var parseResult = parseTestCodeWithDiagnostics(r'''
int x = 0;
/// Text.
/// {@template name}
// ^^^^^^^^^^^^^^^^
// [diag.docDirectiveMissingClosingTag] Doc directive is missing a closing tag.
/// More text.
class A {}
''');
var node = parseResult.findNode.comment('template name');
assertParsedNodeText(node, r'''
Comment
tokens
/// Text.
/// {@template name}
/// More text.
docDirectives
BlockDocDirective
openingTag
offset: [26, 42]
type: [DocDirectiveType.template]
positionalArguments
name
''');
}
test_template_missingClosingTag_multiple() {
var parseResult = parseTestCodeWithDiagnostics(r'''
int x = 0;
/// Text.
/// {@template name}
// ^^^^^^^^^^^^^^^^
// [diag.docDirectiveMissingClosingTag] Doc directive is missing a closing tag.
/// More text.
/// {@template name2}
// ^^^^^^^^^^^^^^^^^
// [diag.docDirectiveMissingClosingTag] Doc directive is missing a closing tag.
/// More text.
class A {}
''');
var node = parseResult.findNode.comment('template name2');
assertParsedNodeText(node, r'''
Comment
tokens
/// Text.
/// {@template name}
/// More text.
/// {@template name2}
/// More text.
docDirectives
BlockDocDirective
openingTag
offset: [26, 42]
type: [DocDirectiveType.template]
positionalArguments
name
BlockDocDirective
openingTag
offset: [62, 79]
type: [DocDirectiveType.template]
positionalArguments
name2
''');
}
test_template_missingClosingTag_withInnerTag() {
var parseResult = parseTestCodeWithDiagnostics(r'''
int x = 0;
/// Text.
/// {@template name}
// ^^^^^^^^^^^^^^^^
// [diag.docDirectiveMissingClosingTag] Doc directive is missing a closing tag.
/// More text.
/// {@animation 600 400 http://google.com}
class A {}
''');
var node = parseResult.findNode.comment('template name');
assertParsedNodeText(node, r'''
Comment
tokens
/// Text.
/// {@template name}
/// More text.
/// {@animation 600 400 http://google.com}
docDirectives
BlockDocDirective
openingTag
offset: [26, 42]
type: [DocDirectiveType.template]
positionalArguments
name
SimpleDocDirective
tag
offset: [62, 100]
type: [DocDirectiveType.animation]
positionalArguments
600
400
http://google.com
''');
}
test_template_outOfOrderClosingTag() {
var parseResult = parseTestCodeWithDiagnostics(r'''
int x = 0;
/// Text.
/// {@template name}
/// More text.
/// {@inject-html}
// ^^^^^^^^^^^^^^
// [diag.docDirectiveMissingClosingTag] Doc directive is missing a closing tag.
/// HTML.
/// {@endtemplate}
/// {@end-inject-html}
// ^^^^^^^^^^^^^^^^^^
// [diag.docDirectiveMissingOpeningTag] Doc directive is missing an opening tag.
class A {}
''');
var node = parseResult.findNode.comment('template name');
assertParsedNodeText(node, r'''
Comment
tokens
/// Text.
/// {@template name}
/// More text.
/// {@inject-html}
/// HTML.
/// {@endtemplate}
/// {@end-inject-html}
docDirectives
BlockDocDirective
openingTag
offset: [26, 42]
type: [DocDirectiveType.template]
positionalArguments
name
closingTag
offset: [91, 105]
type: [DocDirectiveType.endTemplate]
BlockDocDirective
openingTag
offset: [62, 76]
type: [DocDirectiveType.injectHtml]
SimpleDocDirective
tag
offset: [110, 128]
type: [DocDirectiveType.endInjectHtml]
''');
}
test_tool_withRestArguments() {
var parseResult = parseTestCodeWithDiagnostics(r'''
int x = 0;
/// Text.
/// {@tool snippets one two three}
/// More text.
/// {@end-tool}
class A {}
''');
var node = parseResult.findNode.comment('tool snippets');
assertParsedNodeText(node, r'''
Comment
tokens
/// Text.
/// {@tool snippets one two three}
/// More text.
/// {@end-tool}
docDirectives
BlockDocDirective
openingTag
offset: [26, 56]
type: [DocDirectiveType.tool]
positionalArguments
snippets
one
two
three
closingTag
offset: [76, 87]
type: [DocDirectiveType.endTool]
''');
}
test_unknownDocDirective() {
var parseResult = parseTestCodeWithDiagnostics(r'''
int x = 0;
/// Text.
/// {@yotube 123}
// ^^^^^^
// [diag.docDirectiveUnknown] Doc directive 'yotube' is unknown.
class A {}
''');
var node = parseResult.findNode.comment('yotube');
assertParsedNodeText(node, r'''
Comment
tokens
/// Text.
/// {@yotube 123}
''');
}
test_youTubeDirective() {
var parseResult = parseTestCodeWithDiagnostics(r'''
int x = 0;
/// Text.
/// {@youtube 600 400 http://google.com}
class A {}
''');
var node = parseResult.findNode.comment('youtube');
assertParsedNodeText(node, r'''
Comment
tokens
/// Text.
/// {@youtube 600 400 http://google.com}
docDirectives
SimpleDocDirective
tag
offset: [26, 62]
type: [DocDirectiveType.youtube]
positionalArguments
600
400
http://google.com
''');
}
test_youTubeDirective_missingEndBrace() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// {@youtube 600 400 http://google.com
// ^
// [diag.docDirectiveMissingClosingBrace] Doc directive is missing a closing curly brace ('}').
class A {}
''');
var node = parseResult.findNode.comment('youtube');
assertParsedNodeText(node, r'''
Comment
tokens
/// {@youtube 600 400 http://google.com
docDirectives
SimpleDocDirective
tag
offset: [4, 39]
type: [DocDirectiveType.youtube]
positionalArguments
600
400
http://google.com
''');
}
test_youTubeDirective_missingUrl() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// {@youtube 600 400}
class A {}
''');
var node = parseResult.findNode.comment('youtube');
assertParsedNodeText(node, r'''
Comment
tokens
/// {@youtube 600 400}
docDirectives
SimpleDocDirective
tag
offset: [4, 22]
type: [DocDirectiveType.youtube]
positionalArguments
600
400
''');
}
test_youTubeDirective_missingUrlAndHeight() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// {@youtube 600}
class A {}
''');
var node = parseResult.findNode.comment('youtube');
assertParsedNodeText(node, r'''
Comment
tokens
/// {@youtube 600}
docDirectives
SimpleDocDirective
tag
offset: [4, 18]
type: [DocDirectiveType.youtube]
positionalArguments
600
''');
}
test_youTubeDirective_missingUrlAndHeightAndWidth() {
var parseResult = parseTestCodeWithDiagnostics(r'''
/// {@youtube }
class A {}
''');
var node = parseResult.findNode.comment('youtube');
assertParsedNodeText(node, r'''
Comment
tokens
/// {@youtube }
docDirectives
SimpleDocDirective
tag
offset: [4, 15]
type: [DocDirectiveType.youtube]
''');
}
}
extension on String {
String get withCrLf {
return replaceAll('\r', '').replaceAll('\n', '\r\n');
}
String get withLf {
return replaceAll('\r', '');
}
}