blob: 664b3f03c3d2ea292b24a20cc24b3a358cccf6be [file] [log] [blame]
// 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';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(DocCommentParserTest);
});
}
@reflectiveTest
class DocCommentParserTest extends ParserDiagnosticsTest {
test_codeSpan() {
final parseResult = parseStringWithErrors(r'''
/// `a[i]` and [b].
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('a[i]');
// TODO(srawlins): Parse code into its own node.
assertParsedNodeText(node, r'''
Comment
references
CommentReference
expression: SimpleIdentifier
token: b
tokens
/// `a[i]` and [b].
''');
}
test_codeSpan_legacy_blockComment() {
// TODO(srawlins): I believe we should drop support for `[:` `:]`.
final parseResult = parseStringWithErrors(r'''
/** [:xxx [a] yyy:] [b] zzz */
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('[a]');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
expression: SimpleIdentifier
token: b
tokens
/** [:xxx [a] yyy:] [b] zzz */
''');
}
test_codeSpan_unterminated_blockComment() {
final parseResult = parseStringWithErrors(r'''
/** `a[i] and [b] */
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('a[');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
expression: SimpleIdentifier
token: i
CommentReference
expression: SimpleIdentifier
token: b
tokens
/** `a[i] and [b] */
''');
}
test_commentReference_blockComment() {
final parseResult = parseStringWithErrors(r'''
/** [a]. */
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('[a]');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
expression: SimpleIdentifier
token: a
tokens
/** [a]. */
''');
}
test_commentReference_empty() {
final parseResult = parseStringWithErrors(r'''
/// [].
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('[]');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
expression: SimpleIdentifier
token: <empty> <synthetic>
tokens
/// [].
''');
}
test_commentReference_multiple() {
final parseResult = parseStringWithErrors(r'''
/// [a] and [b].
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('[a]');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
expression: SimpleIdentifier
token: a
CommentReference
expression: SimpleIdentifier
token: b
tokens
/// [a] and [b].
''');
}
test_commentReference_multiple_blockComment() {
final parseResult = parseStringWithErrors(r'''
/** [a] and [b]. */
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('[a]');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
expression: SimpleIdentifier
token: a
CommentReference
expression: SimpleIdentifier
token: b
tokens
/** [a] and [b]. */
''');
}
test_commentReference_new_prefixed() {
final parseResult = parseStringWithErrors(r'''
/// [new a.A].
class B {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('new');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
newKeyword: new
expression: PrefixedIdentifier
prefix: SimpleIdentifier
token: a
period: .
identifier: SimpleIdentifier
token: A
tokens
/// [new a.A].
''');
}
test_commentReference_new_simple() {
final parseResult = parseStringWithErrors(r'''
/// [new A].
class B {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('new');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
newKeyword: new
expression: SimpleIdentifier
token: A
tokens
/// [new A].
''');
}
test_commentReference_operator_withKeyword_notPrefixed() {
final parseResult = parseStringWithErrors(r'''
/// [operator ==].
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('==');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
expression: SimpleIdentifier
token: ==
tokens
/// [operator ==].
''');
}
test_commentReference_operator_withKeyword_prefixed() {
final parseResult = parseStringWithErrors(r'''
/// [Object.operator ==].
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('==');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
expression: PrefixedIdentifier
prefix: SimpleIdentifier
token: Object
period: .
identifier: SimpleIdentifier
token: ==
tokens
/// [Object.operator ==].
''');
}
test_commentReference_operator_withoutKeyword_notPrefixed() {
final parseResult = parseStringWithErrors(r'''
/// [==].
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('==');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
expression: SimpleIdentifier
token: ==
tokens
/// [==].
''');
}
test_commentReference_operator_withoutKeyword_prefixed() {
final parseResult = parseStringWithErrors(r'''
/// [Object.==].
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('==');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
expression: PrefixedIdentifier
prefix: SimpleIdentifier
token: Object
period: .
identifier: SimpleIdentifier
token: ==
tokens
/// [Object.==].
''');
}
test_commentReference_prefixedIdentifier() {
final parseResult = parseStringWithErrors(r'''
/// [a.b].
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('a.b');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
expression: PrefixedIdentifier
prefix: SimpleIdentifier
token: a
period: .
identifier: SimpleIdentifier
token: b
tokens
/// [a.b].
''');
}
test_commentReference_simpleIdentifier() {
final parseResult = parseStringWithErrors(r'''
/// [a].
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('[a]');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
expression: SimpleIdentifier
token: a
tokens
/// [a].
''');
}
test_commentReference_this() {
final parseResult = parseStringWithErrors(r'''
/// [this].
class A {}
''');
parseResult.assertNoErrors();
final 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_fencedCodeBlock_blockComment() {
final parseResult = parseStringWithErrors(r'''
/**
* One.
* ```
* a[i] = b[i];
* ```
* Two.
* ```dart
* code;
* ```
* Three.
*/
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('a[i]');
assertParsedNodeText(node, r'''
Comment
tokens
/**
* One.
* ```
* a[i] = b[i];
* ```
* Two.
* ```dart
* code;
* ```
* Three.
*/
fencedCodeBlocks
MdFencedCodeBlock
infoString: <empty>
lines
MdFencedCodeBlockLine
offset: 15
length: 3
MdFencedCodeBlockLine
offset: 22
length: 12
MdFencedCodeBlockLine
offset: 38
length: 3
MdFencedCodeBlock
infoString: dart
lines
MdFencedCodeBlockLine
offset: 53
length: 7
MdFencedCodeBlockLine
offset: 64
length: 5
MdFencedCodeBlockLine
offset: 73
length: 3
''');
}
test_fencedCodeBlock_empty() {
final parseResult = parseStringWithErrors(r'''
/// ```
/// ```
/// Text.
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('Text.');
assertParsedNodeText(node, r'''
Comment
tokens
/// ```
/// ```
/// Text.
fencedCodeBlocks
MdFencedCodeBlock
infoString: <empty>
lines
MdFencedCodeBlockLine
offset: 3
length: 4
MdFencedCodeBlockLine
offset: 11
length: 4
''');
}
test_fencedCodeBlock_leadingSpaces() {
final parseResult = parseStringWithErrors(r'''
/// ```
/// a[i] = b[i];
/// ```
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('a[i]');
assertParsedNodeText(node, r'''
Comment
tokens
/// ```
/// a[i] = b[i];
/// ```
fencedCodeBlocks
MdFencedCodeBlock
infoString: <empty>
lines
MdFencedCodeBlockLine
offset: 3
length: 6
MdFencedCodeBlockLine
offset: 13
length: 15
MdFencedCodeBlockLine
offset: 32
length: 6
''');
}
test_fencedCodeBlock_moreThanThreeBackticks() {
final parseResult = parseStringWithErrors(r'''
/// ````dart
/// A code block can contain multiple backticks, as long as it is fewer than
/// the amount in the opening:
/// ```
/// `````
class A {}
''');
parseResult.assertNoErrors();
final 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:
/// ```
/// `````
fencedCodeBlocks
MdFencedCodeBlock
infoString: dart
lines
MdFencedCodeBlockLine
offset: 3
length: 9
MdFencedCodeBlockLine
offset: 16
length: 73
MdFencedCodeBlockLine
offset: 93
length: 27
MdFencedCodeBlockLine
offset: 124
length: 4
MdFencedCodeBlockLine
offset: 132
length: 6
''');
}
test_fencedCodeBlock_noLeadingSpaces() {
final parseResult = parseStringWithErrors(r'''
///```
///a[i] = b[i];
///```
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('a[i]');
assertParsedNodeText(node, r'''
Comment
tokens
///```
///a[i] = b[i];
///```
fencedCodeBlocks
MdFencedCodeBlock
infoString: <empty>
lines
MdFencedCodeBlockLine
offset: 3
length: 3
MdFencedCodeBlockLine
offset: 10
length: 12
MdFencedCodeBlockLine
offset: 26
length: 3
''');
}
test_fencedCodeBlock_nonDocCommentLines() {
final parseResult = parseStringWithErrors(r'''
/// One.
/// ```
// This is not part of the doc comment.
/// a[i] = b[i];
/// ```
/// Two.
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('a[i]');
assertParsedNodeText(node, r'''
Comment
tokens
/// One.
/// ```
/// a[i] = b[i];
/// ```
/// Two.
fencedCodeBlocks
MdFencedCodeBlock
infoString: <empty>
lines
MdFencedCodeBlockLine
offset: 12
length: 4
MdFencedCodeBlockLine
offset: 60
length: 13
MdFencedCodeBlockLine
offset: 78
length: 4
''');
}
test_fencedCodeBlock_nonTerminating() {
final parseResult = parseStringWithErrors(r'''
/// One.
/// ```
/// a[i] = b[i];
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('a[i]');
assertParsedNodeText(node, r'''
Comment
tokens
/// One.
/// ```
/// a[i] = b[i];
fencedCodeBlocks
MdFencedCodeBlock
infoString: <empty>
lines
MdFencedCodeBlockLine
offset: 12
length: 4
MdFencedCodeBlockLine
offset: 20
length: 13
''');
}
test_fencedCodeBlock_nonZeroOffset() {
final parseResult = parseStringWithErrors(r'''
int x = 0;
/// One.
/// ```
/// a[i] = b[i];
/// ```
/// Two.
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('a[i]');
assertParsedNodeText(node, r'''
Comment
tokens
/// One.
/// ```
/// a[i] = b[i];
/// ```
/// Two.
fencedCodeBlocks
MdFencedCodeBlock
infoString: <empty>
lines
MdFencedCodeBlockLine
offset: 24
length: 4
MdFencedCodeBlockLine
offset: 32
length: 13
MdFencedCodeBlockLine
offset: 49
length: 4
''');
}
test_fencedCodeBlock_precededByText() {
final parseResult = parseStringWithErrors(r'''
/// One. ```
/// Two.
/// ```
/// Three.
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('Two.');
assertParsedNodeText(node, r'''
Comment
tokens
/// One. ```
/// Two.
/// ```
/// Three.
fencedCodeBlocks
MdFencedCodeBlock
infoString: <empty>
lines
MdFencedCodeBlockLine
offset: 25
length: 4
MdFencedCodeBlockLine
offset: 33
length: 7
''');
}
test_fencedCodeBlocks() {
final parseResult = parseStringWithErrors(r'''
/// One.
/// ```
/// a[i] = b[i];
/// ```
/// Two.
/// ```dart
/// code;
/// ```
/// Three.
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('a[i]');
assertParsedNodeText(node, r'''
Comment
tokens
/// One.
/// ```
/// a[i] = b[i];
/// ```
/// Two.
/// ```dart
/// code;
/// ```
/// Three.
fencedCodeBlocks
MdFencedCodeBlock
infoString: <empty>
lines
MdFencedCodeBlockLine
offset: 12
length: 4
MdFencedCodeBlockLine
offset: 20
length: 13
MdFencedCodeBlockLine
offset: 37
length: 4
MdFencedCodeBlock
infoString: dart
lines
MdFencedCodeBlockLine
offset: 54
length: 8
MdFencedCodeBlockLine
offset: 66
length: 6
MdFencedCodeBlockLine
offset: 76
length: 4
''');
}
test_indentedCodeBlock_afterBlankLine() {
final parseResult = parseStringWithErrors(r'''
/// Text.
///
/// a[i] = b[i];
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('Text');
assertParsedNodeText(node, r'''
Comment
tokens
/// Text.
///
/// a[i] = b[i];
''');
}
test_indentedCodeBlock_afterTextLine_notCodeBlock() {
final parseResult = parseStringWithErrors(r'''
/// Text.
/// a[i] = b[i];
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('Text');
// TODO(srawlins): Parse an indented code block into its own node.
assertParsedNodeText(node, r'''
Comment
references
CommentReference
expression: SimpleIdentifier
token: i
CommentReference
expression: SimpleIdentifier
token: i
tokens
/// Text.
/// a[i] = b[i];
''');
}
test_indentedCodeBlock_firstLine() {
final parseResult = parseStringWithErrors(r'''
/// a[i] = b[i];
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('a[i]');
// TODO(srawlins): Parse an indented code block into its own node.
assertParsedNodeText(node, r'''
Comment
tokens
/// a[i] = b[i];
''');
}
test_indentedCodeBlock_firstLine_blockComment() {
final parseResult = parseStringWithErrors(r'''
/**
* a[i] = b[i];
* [c].
*/
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('a[i]');
// TODO(srawlins): Parse an indented code block into its own node.
assertParsedNodeText(node, r'''
Comment
references
CommentReference
expression: SimpleIdentifier
token: c
tokens
/**
* a[i] = b[i];
* [c].
*/
''');
}
test_inlineLink() {
final parseResult = parseStringWithErrors(r'''
/// [a](http://www.google.com) [b].
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('[a]');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
expression: SimpleIdentifier
token: b
tokens
/// [a](http://www.google.com) [b].
''');
}
test_linkReference() {
final parseResult = parseStringWithErrors(r'''
/// [a]: http://www.google.com Google [b]
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('[a]');
// TODO(srawlins): Ideally this should not parse `[b]` as a comment
// reference.
assertParsedNodeText(node, r'''
Comment
references
CommentReference
expression: SimpleIdentifier
token: b
tokens
/// [a]: http://www.google.com Google [b]
''');
}
test_referenceLink() {
final parseResult = parseStringWithErrors(r'''
/// [a link][c] [b].
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('[a');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
expression: SimpleIdentifier
token: b
tokens
/// [a link][c] [b].
''');
}
test_referenceLink_multiline() {
final parseResult = parseStringWithErrors(r'''
/// [a link split across multiple
/// lines][c] [b].
class A {}
''');
parseResult.assertNoErrors();
final node = parseResult.findNode.comment('[a');
assertParsedNodeText(node, r'''
Comment
references
CommentReference
expression: SimpleIdentifier
token: a
CommentReference
expression: SimpleIdentifier
token: b
tokens
/// [a link split across multiple
/// lines][c] [b].
''');
}
}