Skip to content

Commit

Permalink
analyzer: Support tool doc directive
Browse files Browse the repository at this point in the history
Fixes #52705

Change-Id: I15f8f4d9b989df75600ae589366126ed0c2fcb33
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/327284
Commit-Queue: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
  • Loading branch information
srawlins authored and Commit Queue committed Sep 25, 2023
1 parent 4963955 commit 8042d09
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3479,6 +3479,8 @@ WarningCode.DOC_DIRECTIVE_MISSING_THREE_ARGUMENTS:
status: noFix
WarningCode.DOC_DIRECTIVE_MISSING_TWO_ARGUMENTS:
status: noFix
WarningCode.DOC_DIRECTIVE_UNKNOWN:
status: noFix
WarningCode.DOC_IMPORT_CANNOT_BE_DEFERRED:
status: needsFix
WarningCode.DOC_IMPORT_CANNOT_HAVE_CONFIGURATIONS:
Expand Down
28 changes: 26 additions & 2 deletions pkg/analyzer/lib/dart/ast/doc_comment.dart
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,13 @@ enum DocDirectiveType {
/// are included. This also allows us to parse (erroneous) dangling end tags.
endInjectHtml.end('end-inject-html', openingTag: 'inject-html'),

/// The end tag for the [DocDirectiveType.tool] tag.
///
/// This tag should not really constitute a "type" of doc directive, but this
/// implementation is a one-to-one mapping of "types" and "tags", so end tags
/// are included. This also allows us to parse (erroneous) dangling end tags.
endTool.end('end-tool', openingTag: 'tool'),

/// The end tag for the [DocDirectiveType.template] tag.
///
/// This tag should not really constitute a "type" of doc directive, but this
Expand Down Expand Up @@ -293,6 +300,23 @@ enum DocDirectiveType {
],
),

/// A [DocDirective] declaring a tool.
///
/// A tool directive invokes an external tool, with the text between the
/// opening and closing tags as stdin, and replaces the directive with the
/// output of the tool.
///
/// See documentation at
/// https://github.com/dart-lang/dartdoc/wiki/Doc-comment-directives#external-tools.
tool.block(
'tool',
'end-tool',
positionalParameters: [
DocDirectiveParameter('name', DocDirectiveParameterFormat.any),
],
restParametersAllowed: true,
),

/// A [DocDirective] declaring an embedded YouTube video.
///
/// This directive has three required arguments: the width, the height, and
Expand Down Expand Up @@ -350,9 +374,9 @@ enum DocDirectiveType {
this.name,
this.opposingName, {
this.positionalParameters = const <DocDirectiveParameter>[],
this.restParametersAllowed = false,
}) : isBlock = true,
namedParameters = const <DocDirectiveParameter>[],
restParametersAllowed = false;
namedParameters = const <DocDirectiveParameter>[];

const DocDirectiveType.end(
this.name, {
Expand Down
8 changes: 8 additions & 0 deletions pkg/analyzer/lib/src/error/codes.g.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6143,6 +6143,14 @@ class WarningCode extends AnalyzerErrorCode {
uniqueName: 'DOC_DIRECTIVE_MISSING_TWO_ARGUMENTS',
);

/// Parameters:
/// 0: the name of the unknown doc directive.
static const WarningCode DOC_DIRECTIVE_UNKNOWN = WarningCode(
'DOC_DIRECTIVE_UNKNOWN',
"Doc directive '{0}' is unknown.",
correctionMessage: "Try using one of the supported doc directives.",
);

static const WarningCode DOC_IMPORT_CANNOT_BE_DEFERRED = WarningCode(
'DOC_IMPORT_CANNOT_BE_DEFERRED',
"Doc imports can't be deferred.",
Expand Down
1 change: 1 addition & 0 deletions pkg/analyzer/lib/src/error/error_code_values.g.dart
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,7 @@ const List<ErrorCode> errorCodeValues = [
WarningCode.DOC_DIRECTIVE_MISSING_OPENING_TAG,
WarningCode.DOC_DIRECTIVE_MISSING_THREE_ARGUMENTS,
WarningCode.DOC_DIRECTIVE_MISSING_TWO_ARGUMENTS,
WarningCode.DOC_DIRECTIVE_UNKNOWN,
WarningCode.DOC_IMPORT_CANNOT_BE_DEFERRED,
WarningCode.DOC_IMPORT_CANNOT_HAVE_CONFIGURATIONS,
WarningCode.DUPLICATE_EXPORT,
Expand Down
16 changes: 15 additions & 1 deletion pkg/analyzer/lib/src/fasta/doc_comment_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,9 @@ final class DocCommentBuilder {
case 'end-inject-html':
_endBlockDocDirectiveTag(parser, DocDirectiveType.endInjectHtml);
return true;
case 'end-tool':
_endBlockDocDirectiveTag(parser, DocDirectiveType.endTool);
return true;
case 'endtemplate':
_endBlockDocDirectiveTag(parser, DocDirectiveType.endTemplate);
return true;
Expand All @@ -403,17 +406,28 @@ final class DocCommentBuilder {
case 'inject-html':
_parseBlockDocDirectiveTag(parser, DocDirectiveType.injectHtml);
return true;
case 'macro':
_pushDocDirective(parser.simpleDirective(DocDirectiveType.macro));
return true;
case 'subCategory':
_pushDocDirective(parser.simpleDirective(DocDirectiveType.subCategory));
return true;
case 'template':
_parseBlockDocDirectiveTag(parser, DocDirectiveType.template);
return true;
case 'tool':
_parseBlockDocDirectiveTag(parser, DocDirectiveType.tool);
return true;
case 'youtube':
_pushDocDirective(parser.simpleDirective(DocDirectiveType.youtube));
return true;
}
// TODO(srawlins): Handle unknown (misspelled?) directive.
_errorReporter?.reportErrorForOffset(
WarningCode.DOC_DIRECTIVE_UNKNOWN,
_characterSequence._offset + nameIndex,
nameEnd - nameIndex,
[name],
);
return false;
}

Expand Down
23 changes: 15 additions & 8 deletions pkg/analyzer/messages.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22116,14 +22116,6 @@ WarningCode:
C.c();
}
```
DOC_IMPORT_CANNOT_BE_DEFERRED:
problemMessage: "Doc imports can't be deferred."
correctionMessage: Try removing the 'deferred' keyword.
hasPublishedDocs: false
DOC_IMPORT_CANNOT_HAVE_CONFIGURATIONS:
problemMessage: "Doc imports can't have configurations."
correctionMessage: Try removing the configurations.
hasPublishedDocs: false
DOC_DIRECTIVE_HAS_EXTRA_ARGUMENTS:
problemMessage: "The '{0}' directive has '{1}' arguments, but only '{2}' are expected."
correctionMessage: Try removing the extra arguments.
Expand Down Expand Up @@ -22197,6 +22189,21 @@ WarningCode:
0: the name of the doc directive
1: the name of the first missing argument
2: the name of the second missing argument
DOC_DIRECTIVE_UNKNOWN:
problemMessage: "Doc directive '{0}' is unknown."
correctionMessage: 'Try using one of the supported doc directives.'
hasPublishedDocs: false
comment: |-
Parameters:
0: the name of the unknown doc directive.
DOC_IMPORT_CANNOT_BE_DEFERRED:
problemMessage: "Doc imports can't be deferred."
correctionMessage: Try removing the 'deferred' keyword.
hasPublishedDocs: false
DOC_IMPORT_CANNOT_HAVE_CONFIGURATIONS:
problemMessage: "Doc imports can't have configurations."
correctionMessage: Try removing the configurations.
hasPublishedDocs: false
DUPLICATE_EXPORT:
problemMessage: Duplicate export.
correctionMessage: Try removing all but one export of the library.
Expand Down
57 changes: 57 additions & 0 deletions pkg/analyzer/test/src/dart/parser/doc_comment_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1693,6 +1693,63 @@ Comment
''');
}

test_tool_withRestArguments() {
final parseResult = parseStringWithErrors(r'''
int x = 0;
/// Text.
/// {@tool snippets one two three}
/// More text.
/// {@end-tool}
class A {}
''');
parseResult.assertNoErrors();

final 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, 57]
type: [DocDirectiveType.tool]
positionalArguments
snippets
one
two
three
closingTag
offset: [76, 88]
type: [DocDirectiveType.endTool]
''');
}

test_unknownDocDirective() {
final parseResult = parseStringWithErrors(r'''
int x = 0;
/// Text.
/// {@yotube 123}
class A {}
''');
parseResult.assertErrors([
error(WarningCode.DOC_DIRECTIVE_UNKNOWN, 28, 6),
]);

final node = parseResult.findNode.comment('yotube');
assertParsedNodeText(node, r'''
Comment
tokens
/// Text.
/// {@yotube 123}
''');
}

test_youTubeDirective() {
final parseResult = parseStringWithErrors(r'''
int x = 0;
Expand Down

0 comments on commit 8042d09

Please sign in to comment.