[Analyzer] Add folding regions for comment blocks
Change-Id: Iafe70e977065dc68230503349b8ba3abe9b4c0c0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/179777
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 0bce9d2..3bf7d05 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -109,7 +109,7 @@
<body>
<h1>Analysis Server API Specification</h1>
<h1 style="color:#999999">Version
- 1.32.1
+ 1.32.2
</h1>
<p>
This document contains a specification of the API provided by the
@@ -236,9 +236,13 @@
ignoring the item or treating it with some default/fallback handling.
</p>
<h3>Changelog</h3>
+<h4>1.32.2</h4>
+<ul>
+ <li>Added <tt>FoldingKind.COMMENT</tt> for folding regions for blocks of comments.</li>
+</ul>
<h4>1.32.1</h4>
<ul>
- <li>Added <tt>CompletionSuggestionKind.PACKAGE_NAME</tt> for Pub package name completions in <tt>pubspec.yaml</tt></li>
+ <li>Added <tt>CompletionSuggestionKind.PACKAGE_NAME</tt> for Pub package name completions in <tt>pubspec.yaml</tt>.</li>
</ul>
<h3>Domains</h3>
<p>
@@ -4226,7 +4230,7 @@
An enumeration of the kinds of folding regions.
</p>
- <dl><dt class="value">ANNOTATIONS</dt><dt class="value">BLOCK</dt><dt class="value">CLASS_BODY</dt><dt class="value">DIRECTIVES</dt><dt class="value">DOCUMENTATION_COMMENT</dt><dt class="value">FILE_HEADER</dt><dt class="value">FUNCTION_BODY</dt><dt class="value">INVOCATION</dt><dt class="value">LITERAL</dt></dl></dd><dt class="typeDefinition"><a name="type_FoldingRegion">FoldingRegion: object</a></dt><dd>
+ <dl><dt class="value">ANNOTATIONS</dt><dt class="value">BLOCK</dt><dt class="value">CLASS_BODY</dt><dt class="value">COMMENT</dt><dt class="value">DIRECTIVES</dt><dt class="value">DOCUMENTATION_COMMENT</dt><dt class="value">FILE_HEADER</dt><dt class="value">FUNCTION_BODY</dt><dt class="value">INVOCATION</dt><dt class="value">LITERAL</dt></dl></dd><dt class="typeDefinition"><a name="type_FoldingRegion">FoldingRegion: object</a></dt><dd>
<p>
A description of a region that can be folded.
</p>
diff --git a/pkg/analysis_server/lib/protocol/protocol_constants.dart b/pkg/analysis_server/lib/protocol/protocol_constants.dart
index 4ad5e63..68ea10f 100644
--- a/pkg/analysis_server/lib/protocol/protocol_constants.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_constants.dart
@@ -6,7 +6,7 @@
// To regenerate the file, use the script
// "pkg/analysis_server/tool/spec/generate_files".
-const String PROTOCOL_VERSION = '1.32.1';
+const String PROTOCOL_VERSION = '1.32.2';
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
diff --git a/pkg/analysis_server/lib/src/computer/computer_folding.dart b/pkg/analysis_server/lib/src/computer/computer_folding.dart
index 725ea9a..2a8bc96 100644
--- a/pkg/analysis_server/lib/src/computer/computer_folding.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_folding.dart
@@ -49,7 +49,6 @@
/// Returns a list of folding regions, not `null`.
List<FoldingRegion> compute() {
- _addFileHeaderRegion();
_unit.accept(_DartUnitFoldingComputerVisitor(this));
if (_firstDirective != null &&
@@ -61,39 +60,90 @@
_lastDirective.end - _firstDirective.keyword.end));
}
+ _addCommentRegions();
+
return _foldingRegions;
}
- void _addFileHeaderRegion() {
- var firstToken = _unit.beginToken;
- while (firstToken?.type == TokenType.SCRIPT_TAG) {
- firstToken = firstToken.next;
+ /// Create a folding region for the provided comment, reading forwards if neccesary.
+ ///
+ /// If [mayBeFileHeader] is true, the token will be considered a file header
+ /// if comment is a single-line-comment and there is a blank line or another
+ /// comment type after it.
+ ///
+ /// Returns the next comment to be processed or null if there are no more comments
+ /// to process in the chain.
+ Token _addCommentRegion(Token commentToken, {bool mayBeFileHeader = false}) {
+ int offset, end;
+ var isFileHeader = false;
+ Token nextComment;
+
+ if (commentToken.type == TokenType.MULTI_LINE_COMMENT) {
+ // Multiline comments already span all of their lines but the folding
+ // region should start at the end of the first line.
+ offset = commentToken.offset + (commentToken.eolOffset ?? 0);
+ end = commentToken.end;
+ nextComment = commentToken.next;
+ } else {
+ // Single line comments need grouping together explicitly but should
+ // only group if the prefix is the same and up to any blank line.
+ final isTripleSlash = commentToken.isTripleSlash;
+ // Track the last comment that belongs to this folding region.
+ var lastComment = commentToken;
+ var current = lastComment.next;
+ while (current != null &&
+ current.type == lastComment.type &&
+ current.isTripleSlash == isTripleSlash &&
+ !_hasBlankLineBetween(lastComment.end, current.offset)) {
+ lastComment = current;
+ current = current.next;
+ }
+
+ // For single line comments we prefer to start the range at the end of
+ // first token so the first line is still visible when the range is
+ // collapsed.
+ offset = commentToken.end;
+ end = lastComment.end;
+ nextComment = lastComment.next;
+
+ // Single line comments are file headers if they're followed by a different
+ // comment type of there's a blank line between them and the first token.
+ isFileHeader = mayBeFileHeader &&
+ (nextComment != null ||
+ _hasBlankLineBetween(end, _unit.beginToken.offset));
}
- final Token firstComment = firstToken?.precedingComments;
- if (firstComment == null ||
- firstComment.type != TokenType.SINGLE_LINE_COMMENT) {
- return;
+ final kind = isFileHeader
+ ? FoldingKind.FILE_HEADER
+ : (commentToken.lexeme.startsWith('///') ||
+ commentToken.lexeme.startsWith('/**'))
+ ? FoldingKind.DOCUMENTATION_COMMENT
+ : FoldingKind.COMMENT;
+
+ _addRegion(offset, end, kind);
+
+ return nextComment;
+ }
+
+ void _addCommentRegions() {
+ var token = _unit.beginToken;
+ if (token.type == TokenType.SCRIPT_TAG) {
+ token = token.next;
}
-
- // Walk through the comments looking for a blank line to signal the end of
- // the file header.
- var lastComment = firstComment;
- while (lastComment.next != null) {
- lastComment = lastComment.next;
-
- // If we ran out of tokens, use the original token as starting position.
- final hasBlankLine =
- _hasBlankLineBetween(lastComment, lastComment.next ?? firstToken);
-
- // Also considered non-single-line-comments as the end
- final nextCommentIsDifferentType = lastComment.next != null &&
- lastComment.next.type != TokenType.SINGLE_LINE_COMMENT;
-
- if (hasBlankLine || nextCommentIsDifferentType) {
- _addRegion(firstComment.end, lastComment.end, FoldingKind.FILE_HEADER);
+ var isFirstToken = true;
+ while (token != null) {
+ Token commentToken = token.precedingComments;
+ while (commentToken != null) {
+ commentToken =
+ _addCommentRegion(commentToken, mayBeFileHeader: isFirstToken);
+ }
+ isFirstToken = false;
+ // Only exit the loop when hitting EOF *after* processing the token as
+ // the EOF token may have preceeding comments.
+ if (token.type == TokenType.EOF) {
break;
}
+ token = token.next;
}
}
@@ -114,9 +164,9 @@
}
}
- bool _hasBlankLineBetween(Token first, Token second) {
- final CharacterLocation firstLoc = _lineInfo.getLocation(first.end);
- final CharacterLocation secondLoc = _lineInfo.getLocation(second.offset);
+ bool _hasBlankLineBetween(int offset, int end) {
+ final CharacterLocation firstLoc = _lineInfo.getLocation(offset);
+ final CharacterLocation secondLoc = _lineInfo.getLocation(end);
return secondLoc.lineNumber - firstLoc.lineNumber > 1;
}
@@ -162,15 +212,6 @@
}
@override
- void visitComment(Comment node) {
- if (node.isDocumentation) {
- _computer._addRegion(
- node.offset, node.end, FoldingKind.DOCUMENTATION_COMMENT);
- }
- super.visitComment(node);
- }
-
- @override
void visitConstructorDeclaration(ConstructorDeclaration node) {
_computer._addRegionForAnnotations(node.metadata);
super.visitConstructorDeclaration(node);
@@ -303,3 +344,17 @@
super.visitWhileStatement(node);
}
}
+
+extension _CommentTokenExtensions on Token {
+ static final _newlinePattern = RegExp(r'[\r\n]');
+
+ /// The offset of the first eol character or null
+ /// if no newlines were found.
+ int get eolOffset {
+ final offset = lexeme.indexOf(_newlinePattern);
+ return offset != -1 ? offset : null;
+ }
+
+ /// Whether this comment is a triple-slash single line comment.
+ bool get isTripleSlash => lexeme.startsWith('///');
+}
diff --git a/pkg/analysis_server/lib/src/lsp/mapping.dart b/pkg/analysis_server/lib/src/lsp/mapping.dart
index d02da72..fdde79c 100644
--- a/pkg/analysis_server/lib/src/lsp/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/mapping.dart
@@ -1055,6 +1055,7 @@
lsp.FoldingRangeKind toFoldingRangeKind(server.FoldingKind kind) {
switch (kind) {
+ case server.FoldingKind.COMMENT:
case server.FoldingKind.DOCUMENTATION_COMMENT:
case server.FoldingKind.FILE_HEADER:
return lsp.FoldingRangeKind.Comment;
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index de9314a..cf6abe57 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -723,6 +723,7 @@
/// ANNOTATIONS
/// BLOCK
/// CLASS_BODY
+/// COMMENT
/// DIRECTIVES
/// DOCUMENTATION_COMMENT
/// FILE_HEADER
@@ -734,6 +735,7 @@
'ANNOTATIONS',
'BLOCK',
'CLASS_BODY',
+ 'COMMENT',
'DIRECTIVES',
'DOCUMENTATION_COMMENT',
'FILE_HEADER',
diff --git a/pkg/analysis_server/test/lsp/folding_test.dart b/pkg/analysis_server/test/lsp/folding_test.dart
index 1caf00a..8b4e389 100644
--- a/pkg/analysis_server/test/lsp/folding_test.dart
+++ b/pkg/analysis_server/test/lsp/folding_test.dart
@@ -44,7 +44,7 @@
Future<void> test_comments() async {
final content = '''
- [[/// This is a comment
+ /// This is a comment[[
/// that spans many lines]]
class MyClass2 {}
''';
@@ -164,13 +164,6 @@
}
Future<void> test_headersImportsComments() async {
- // TODO(dantup): Review why the file header and the method comment ranges
- // are different... one spans only the range to collapse, but the other
- // just starts at the logical block.
- // The LSP spec doesn't give any guidance on whether the first part of
- // the surrounded content should be visible or not after folding
- // so we'll need to revisit this once there's clarification:
- // https://github.com/Microsoft/language-server-protocol/issues/659
final content = '''
// Copyright some year by some people[[
// See LICENCE etc.]]
@@ -178,7 +171,7 @@
import[[ 'dart:io';
import 'dart:async';]]
- [[/// This is not the file header
+ /// This is not the file header[[
/// It's just a comment]]
main() {}
''';
diff --git a/pkg/analysis_server/test/src/computer/folding_computer_test.dart b/pkg/analysis_server/test/src/computer/folding_computer_test.dart
index 0f3fa04..03534e7 100644
--- a/pkg/analysis_server/test/src/computer/folding_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/folding_computer_test.dart
@@ -17,6 +17,12 @@
@reflectiveTest
class FoldingComputerTest extends AbstractContextTest {
+ static const commentKinds = {
+ FoldingKind.FILE_HEADER,
+ FoldingKind.COMMENT,
+ FoldingKind.DOCUMENTATION_COMMENT
+ };
+
String sourcePath;
@override
@@ -125,15 +131,72 @@
Future<void> test_comment_is_not_considered_file_header() async {
var content = """
-// This is not the file header
-// It's just a comment
+// This is not the file header/*1:EXC*/
+// It's just a comment/*1:INC:COMMENT*/
main() {}
""";
// Since there are no region comment markers above
// just check the length instead of the contents
final regions = await _computeRegions(content);
- expect(regions, hasLength(0));
+ _compareRegions(regions, content);
+ }
+
+ Future<void> test_comment_multiline() async {
+ var content = '''
+main() {
+/*/*1:EXC*/
+ * comment 1
+ *//*1:EXC:COMMENT*/
+
+/* this comment starts on the same line as delimeters/*2:EXC*/
+ * second line
+ *//*2:EXC:COMMENT*/
+}
+''';
+
+ final regions = await _computeRegions(content);
+ _compareRegions(regions, content, commentKinds);
+ }
+
+ Future<void> test_comment_singleFollowedByBlankLine() async {
+ var content = '''
+main() {
+// this is/*1:EXC*/
+// a comment/*1:INC:COMMENT*/
+/// this is not part of it
+}
+''';
+
+ final regions = await _computeRegions(content);
+ _compareRegions(regions, content, commentKinds);
+ }
+
+ Future<void> test_comment_singleFollowedByMulti() async {
+ var content = '''
+main() {
+ // this is/*1:EXC*/
+ // a comment/*1:INC:COMMENT*/
+ /* this is not part of it */
+ String foo;
+}
+''';
+
+ final regions = await _computeRegions(content);
+ _compareRegions(regions, content, commentKinds);
+ }
+
+ Future<void> test_comment_singleFollowedByTripleSlash() async {
+ var content = '''
+main() {
+// this is/*1:EXC*/
+// a comment/*1:INC:COMMENT*/
+/// this is not part of it
+}
+''';
+
+ final regions = await _computeRegions(content);
+ _compareRegions(regions, content, commentKinds);
}
Future<void> test_constructor_invocations() async {
@@ -164,7 +227,7 @@
""";
final regions = await _computeRegions(content);
- _compareRegions(regions, content);
+ _compareRegions(regions, content, {FoldingKind.FILE_HEADER});
}
Future<void> test_file_header_does_not_include_block_comments() async {
@@ -179,7 +242,7 @@
""";
final regions = await _computeRegions(content);
- expect(regions, hasLength(0));
+ _compareRegions(regions, content, {FoldingKind.FILE_HEADER});
}
Future<void> test_file_header_with_no_function_comment() async {
@@ -191,7 +254,7 @@
''';
final regions = await _computeRegions(content);
- _compareRegions(regions, content);
+ _compareRegions(regions, content, {FoldingKind.FILE_HEADER});
}
Future<void> test_file_header_with_non_end_of_line_comment() async {
@@ -204,7 +267,7 @@
""";
final regions = await _computeRegions(content);
- _compareRegions(regions, content);
+ _compareRegions(regions, content, {FoldingKind.FILE_HEADER});
}
Future<void> test_file_header_with_script_prefix() async {
@@ -219,6 +282,19 @@
""";
final regions = await _computeRegions(content);
+ _compareRegions(regions, content, {FoldingKind.FILE_HEADER});
+ }
+
+ Future<void> test_fileHeader_singleFollowedByBlank() async {
+ var content = '''
+// this is/*1:EXC*/
+// a file header/*1:INC:FILE_HEADER*/
+
+// this is not part of it
+main() {}
+''';
+
+ final regions = await _computeRegions(content);
_compareRegions(regions, content);
}
@@ -263,7 +339,7 @@
var content = '''
// Content before
-/*1:EXC*//// This is a doc comment
+/// This is a doc comment/*1:EXC*/
/// that spans lines/*1:INC:DOCUMENTATION_COMMENT*/
main() {/*2:INC*/
print("Hello, world!");
@@ -434,11 +510,19 @@
/// Compares provided folding regions with expected
/// regions extracted from the comments in the provided content.
- void _compareRegions(List<FoldingRegion> regions, String content) {
+ ///
+ /// If [onlyKinds] is supplied only regions of that type will be compared.
+ void _compareRegions(List<FoldingRegion> regions, String content,
+ [Set<FoldingKind> onlyKinds]) {
// Find all numeric markers for region starts.
final regex = RegExp(r'/\*(\d+):(INC|EXC)\*/');
final expectedRegions = regex.allMatches(content);
+ if (onlyKinds != null) {
+ regions =
+ regions.where((region) => onlyKinds.contains(region.kind)).toList();
+ }
+
// Check we didn't get more than expected, since the loop below only
// checks for the presence of matches, not absence.
expect(regions, hasLength(expectedRegions.length));
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/FoldingKind.java b/pkg/analysis_server/tool/spec/generated/java/types/FoldingKind.java
index be9f538..3b8b236 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/FoldingKind.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/FoldingKind.java
@@ -21,6 +21,8 @@
public static final String CLASS_BODY = "CLASS_BODY";
+ public static final String COMMENT = "COMMENT";
+
public static final String DIRECTIVES = "DIRECTIVES";
public static final String DOCUMENTATION_COMMENT = "DOCUMENTATION_COMMENT";
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index 47b9e8f..7d118ec 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -7,7 +7,7 @@
<body>
<h1>Analysis Server API Specification</h1>
<h1 style="color:#999999">Version
- <version>1.32.1</version>
+ <version>1.32.2</version>
</h1>
<p>
This document contains a specification of the API provided by the
@@ -134,9 +134,13 @@
ignoring the item or treating it with some default/fallback handling.
</p>
<h3>Changelog</h3>
+<h4>1.32.2</h4>
+<ul>
+ <li>Added <tt>FoldingKind.COMMENT</tt> for folding regions for blocks of comments.</li>
+</ul>
<h4>1.32.1</h4>
<ul>
- <li>Added <tt>CompletionSuggestionKind.PACKAGE_NAME</tt> for Pub package name completions in <tt>pubspec.yaml</tt></li>
+ <li>Added <tt>CompletionSuggestionKind.PACKAGE_NAME</tt> for Pub package name completions in <tt>pubspec.yaml</tt>.</li>
</ul>
<h3>Domains</h3>
<p>
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
index 346847c..2b61453 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
@@ -1904,6 +1904,7 @@
/// ANNOTATIONS
/// BLOCK
/// CLASS_BODY
+/// COMMENT
/// DIRECTIVES
/// DOCUMENTATION_COMMENT
/// FILE_HEADER
@@ -1920,6 +1921,8 @@
static const FoldingKind CLASS_BODY = FoldingKind._('CLASS_BODY');
+ static const FoldingKind COMMENT = FoldingKind._('COMMENT');
+
static const FoldingKind DIRECTIVES = FoldingKind._('DIRECTIVES');
static const FoldingKind DOCUMENTATION_COMMENT =
@@ -1938,6 +1941,7 @@
ANNOTATIONS,
BLOCK,
CLASS_BODY,
+ COMMENT,
DIRECTIVES,
DOCUMENTATION_COMMENT,
FILE_HEADER,
@@ -1959,6 +1963,8 @@
return BLOCK;
case 'CLASS_BODY':
return CLASS_BODY;
+ case 'COMMENT':
+ return COMMENT;
case 'DIRECTIVES':
return DIRECTIVES;
case 'DOCUMENTATION_COMMENT':
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
index 4ad5e63..68ea10f 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
@@ -6,7 +6,7 @@
// To regenerate the file, use the script
// "pkg/analysis_server/tool/spec/generate_files".
-const String PROTOCOL_VERSION = '1.32.1';
+const String PROTOCOL_VERSION = '1.32.2';
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
diff --git a/pkg/analyzer_plugin/doc/api.html b/pkg/analyzer_plugin/doc/api.html
index 6aaac51..dd53e3b 100644
--- a/pkg/analyzer_plugin/doc/api.html
+++ b/pkg/analyzer_plugin/doc/api.html
@@ -1309,7 +1309,7 @@
An enumeration of the kinds of folding regions.
</p>
- <dl><dt class="value">ANNOTATIONS</dt><dt class="value">BLOCK</dt><dt class="value">CLASS_BODY</dt><dt class="value">DIRECTIVES</dt><dt class="value">DOCUMENTATION_COMMENT</dt><dt class="value">FILE_HEADER</dt><dt class="value">FUNCTION_BODY</dt><dt class="value">INVOCATION</dt><dt class="value">LITERAL</dt></dl></dd><dt class="typeDefinition"><a name="type_FoldingRegion">FoldingRegion: object</a></dt><dd>
+ <dl><dt class="value">ANNOTATIONS</dt><dt class="value">BLOCK</dt><dt class="value">CLASS_BODY</dt><dt class="value">COMMENT</dt><dt class="value">DIRECTIVES</dt><dt class="value">DOCUMENTATION_COMMENT</dt><dt class="value">FILE_HEADER</dt><dt class="value">FUNCTION_BODY</dt><dt class="value">INVOCATION</dt><dt class="value">LITERAL</dt></dl></dd><dt class="typeDefinition"><a name="type_FoldingRegion">FoldingRegion: object</a></dt><dd>
<p>
A description of a region that can be folded.
</p>
diff --git a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
index 56bcadd..89b8f94 100644
--- a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
+++ b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
@@ -1904,6 +1904,7 @@
/// ANNOTATIONS
/// BLOCK
/// CLASS_BODY
+/// COMMENT
/// DIRECTIVES
/// DOCUMENTATION_COMMENT
/// FILE_HEADER
@@ -1920,6 +1921,8 @@
static const FoldingKind CLASS_BODY = FoldingKind._('CLASS_BODY');
+ static const FoldingKind COMMENT = FoldingKind._('COMMENT');
+
static const FoldingKind DIRECTIVES = FoldingKind._('DIRECTIVES');
static const FoldingKind DOCUMENTATION_COMMENT =
@@ -1938,6 +1941,7 @@
ANNOTATIONS,
BLOCK,
CLASS_BODY,
+ COMMENT,
DIRECTIVES,
DOCUMENTATION_COMMENT,
FILE_HEADER,
@@ -1959,6 +1963,8 @@
return BLOCK;
case 'CLASS_BODY':
return CLASS_BODY;
+ case 'COMMENT':
+ return COMMENT;
case 'DIRECTIVES':
return DIRECTIVES;
case 'DOCUMENTATION_COMMENT':
diff --git a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
index d495c4f..3ac543a 100644
--- a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
+++ b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
@@ -305,6 +305,7 @@
/// ANNOTATIONS
/// BLOCK
/// CLASS_BODY
+/// COMMENT
/// DIRECTIVES
/// DOCUMENTATION_COMMENT
/// FILE_HEADER
@@ -316,6 +317,7 @@
'ANNOTATIONS',
'BLOCK',
'CLASS_BODY',
+ 'COMMENT',
'DIRECTIVES',
'DOCUMENTATION_COMMENT',
'FILE_HEADER',
diff --git a/pkg/analyzer_plugin/tool/spec/common_types_spec.html b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
index b1c7056..df7fa1c 100644
--- a/pkg/analyzer_plugin/tool/spec/common_types_spec.html
+++ b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
@@ -6,7 +6,7 @@
</head>
<body>
<h1>Common Types</h1>
-<version>1.4.0</version>
+<version>1.4.1</version>
<p>
This document contains a specification of the types that are common between
the analysis server wire protocol and the analysis server plugin wire
@@ -575,6 +575,7 @@
<value><code>ANNOTATIONS</code></value>
<value><code>BLOCK</code></value>
<value><code>CLASS_BODY</code></value>
+ <value><code>COMMENT</code></value>
<value><code>DIRECTIVES</code></value>
<value><code>DOCUMENTATION_COMMENT</code></value>
<value><code>FILE_HEADER</code></value>