@@ -93,7 +93,7 @@ class CommentReferenceParser {
9393 /// ```text
9494 /// <rawCommentReference> ::= <prefix>?<commentReference><suffix>?
9595 ///
96- /// <commentReference> ::= (<packageName> '.')? (<libraryName> '.')? <dartdocIdentifier> ('.' <identifier>)*
96+ /// <commentReference> ::= (<packageName> '.')? (<libraryName> '.')? <dartdocIdentifier> <typeArguments> ('.' <identifier> <typeArguments >)*
9797 /// ```
9898 List <CommentReferenceNode > _parseRawCommentReference () {
9999 var children = < CommentReferenceNode > [];
@@ -121,6 +121,17 @@ class CommentReferenceParser {
121121 } else if (identifierResult.type ==
122122 _IdentifierResultType .parsedIdentifier) {
123123 children.add (identifierResult.node);
124+ var typeVariablesResult = _parseTypeVariables ();
125+ if (typeVariablesResult.type == _TypeVariablesResultType .endOfFile) {
126+ break ;
127+ } else if (typeVariablesResult.type ==
128+ _TypeVariablesResultType .notTypeVariables) {
129+ // Do nothing, _index has not moved.
130+ ;
131+ } else if (typeVariablesResult.type ==
132+ _TypeVariablesResultType .parsedTypeVariables) {
133+ children.add (typeVariablesResult.node);
134+ }
124135 }
125136 if (_atEnd || _thisChar != $dot) {
126137 break ;
@@ -236,6 +247,22 @@ class CommentReferenceParser {
236247 IdentifierNode (codeRef.substring (startIndex, _index)));
237248 }
238249
250+ /// Parse a list of type variables (arguments or parameters).
251+ ///
252+ /// Dartdoc isolates these where present and potentially valid, but we don't
253+ /// break them down.
254+ _TypeVariablesParseResult _parseTypeVariables () {
255+ if (_atEnd) {
256+ return _TypeVariablesParseResult .endOfFile;
257+ }
258+ var startIndex = _index;
259+ if (_matchBraces ($lt, $gt)) {
260+ return _TypeVariablesParseResult .ok (
261+ TypeVariablesNode (codeRef.substring (startIndex + 1 , _index - 1 )));
262+ }
263+ return _TypeVariablesParseResult .notIdentifier;
264+ }
265+
239266 static const _callableHintSuffix = '()' ;
240267
241268 /// ```text
@@ -267,7 +294,7 @@ class CommentReferenceParser {
267294 if ((_thisChar == $exclamation || _thisChar == $question) && _nextAtEnd) {
268295 return _SuffixParseResult .junk;
269296 }
270- if (_matchBraces ($lparen, $rparen) || _matchBraces ($lt, $gt) ) {
297+ if (_matchBraces ($lparen, $rparen)) {
271298 return _SuffixParseResult .junk;
272299 }
273300
@@ -331,8 +358,10 @@ class CommentReferenceParser {
331358 while (! _atEnd) {
332359 if (_thisChar == startChar) braceCount++ ;
333360 if (_thisChar == endChar) braceCount-- ;
334- ++ _index;
335- if (braceCount == 0 ) return true ;
361+ _index++ ;
362+ if (braceCount == 0 ) {
363+ return true ;
364+ }
336365 }
337366 _index = startIndex;
338367 return false ;
@@ -392,6 +421,32 @@ class _IdentifierParseResult {
392421 _IdentifierParseResult ._(_IdentifierResultType .notIdentifier, null );
393422}
394423
424+ enum _TypeVariablesResultType {
425+ endOfFile, // Found end of file instead of the beginning of a list of type
426+ // variables.
427+ notTypeVariables, // Found something, but it isn't type variables.
428+ parsedTypeVariables, // Found type variables.
429+ }
430+
431+ class _TypeVariablesParseResult {
432+ final _TypeVariablesResultType type;
433+
434+ final TypeVariablesNode node;
435+
436+ const _TypeVariablesParseResult ._(this .type, this .node);
437+
438+ factory _TypeVariablesParseResult .ok (TypeVariablesNode node) =>
439+ _TypeVariablesParseResult ._(
440+ _TypeVariablesResultType .parsedTypeVariables, node);
441+
442+ static const _TypeVariablesParseResult endOfFile =
443+ _TypeVariablesParseResult ._(_TypeVariablesResultType .endOfFile, null );
444+
445+ static const _TypeVariablesParseResult notIdentifier =
446+ _TypeVariablesParseResult ._(
447+ _TypeVariablesResultType .notTypeVariables, null );
448+ }
449+
395450enum _SuffixResultType {
396451 junk, // Found known types of junk it is OK to ignore.
397452 missing, // There is no suffix here. Same as EOF as this is a suffix.
@@ -456,3 +511,19 @@ class IdentifierNode extends CommentReferenceNode {
456511 @override
457512 String toString () => 'Identifier["$text "]' ;
458513}
514+
515+ /// Represents one or more type variables, may be
516+ /// comma separated.
517+ class TypeVariablesNode extends CommentReferenceNode {
518+ @override
519+
520+ /// Note that this will contain commas, spaces, and other text, as
521+ /// generally type variables are a form of junk that comment references
522+ /// should ignore.
523+ final String text;
524+
525+ TypeVariablesNode (this .text);
526+
527+ @override
528+ String toString () => 'TypeVariablesNode["$text "]' ;
529+ }
0 commit comments