Skip to content

Commit 895855a

Browse files
committed
squash some merges out
1 parent 4e73d72 commit 895855a

File tree

3 files changed

+101
-4
lines changed

3 files changed

+101
-4
lines changed

lib/src/comment_references/parser.dart

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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> <typeParameters> ('.' <identifier> <typeParameters>)*
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 typeParametersResult = _parseTypeParameters();
125+
if (typeParametersResult.type == _TypeParametersResultType.endOfFile) {
126+
break;
127+
} else if (typeParametersResult.type ==
128+
_TypeParametersResultType.notTypeParameters) {
129+
// Do nothing, _index has not moved.
130+
;
131+
} else if (typeParametersResult.type ==
132+
_TypeParametersResultType.parsedTypeParameters) {
133+
children.add(typeParametersResult.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 parameters.
251+
///
252+
/// Dartdoc isolates these where present and potentially valid, but we don't
253+
/// break them down.
254+
_TypeParametersParseResult _parseTypeParameters() {
255+
if (_atEnd) {
256+
return _TypeParametersParseResult.endOfFile;
257+
}
258+
var startIndex = _index;
259+
if (_matchBraces($lt, $gt)) {
260+
return _TypeParametersParseResult.ok(
261+
TypeParametersNode(codeRef.substring(startIndex + 1, _index - 1)));
262+
}
263+
return _TypeParametersParseResult.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 _TypeParametersResultType {
425+
endOfFile, // Found end of file instead of the beginning of a list of type
426+
// parameters.
427+
notTypeParameters, // Found something, but it isn't type parameters.
428+
parsedTypeParameters, // Found type parameters.
429+
}
430+
431+
class _TypeParametersParseResult {
432+
final _TypeParametersResultType type;
433+
434+
final TypeParametersNode node;
435+
436+
const _TypeParametersParseResult._(this.type, this.node);
437+
438+
factory _TypeParametersParseResult.ok(TypeParametersNode node) =>
439+
_TypeParametersParseResult._(
440+
_TypeParametersResultType.parsedTypeParameters, node);
441+
442+
static const _TypeParametersParseResult endOfFile =
443+
_TypeParametersParseResult._(_TypeParametersResultType.endOfFile, null);
444+
445+
static const _TypeParametersParseResult notIdentifier =
446+
_TypeParametersParseResult._(
447+
_TypeParametersResultType.notTypeParameters, null);
448+
}
449+
395450
enum _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 parameters, may be
516+
/// comma separated.
517+
class TypeParametersNode extends CommentReferenceNode {
518+
@override
519+
520+
/// Note that this will contain commas, spaces, and other text, as
521+
/// generally type parameters are a form of junk that comment references
522+
/// should ignore.
523+
final String text;
524+
525+
TypeParametersNode(this.text);
526+
527+
@override
528+
String toString() => 'TypeParametersNode["$text"]';
529+
}

test/comment_referable/parser_test.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,16 @@ void main() {
8181
['ThisThingy', '[]', 'parameter']);
8282
});
8383

84+
test('Check that embedded types within tearoff-like constructs parse', () {
85+
expectParseEquivalent('this<stuff>.isValid', ['this', 'isValid']);
86+
expectParseEquivalent('this<stuff<that<is, real>, complicated>>.isValid',
87+
['this', 'isValid']);
88+
expectParseError('this<stuff.isntValid');
89+
expectParseError('this<stuff>, notBeingValid>.isntValid');
90+
expectParseError('(AndThisMayBeValidDart.butIt).isntValidInReferences');
91+
expectParseError('<NotActually>.valid');
92+
});
93+
8494
test('Basic negative tests', () {
8595
expectParseError(r'.');
8696
expectParseError(r'');

test/end2end/model_special_cases_test.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,22 @@ void main() {
203203
expect(referenceLookup(constructorTearoffs, 'Ft.new'),
204204
equals(MatchingLinkResult(Fnew)));
205205
});
206+
207+
test('we can use (ignored) type parameters in references', () {
208+
expect(referenceLookup(E, 'D<String>.new'),
209+
equals(MatchingLinkResult(Dnew)));
210+
expect(referenceLookup(constructorTearoffs, 'F<T>.new'),
211+
equals(MatchingLinkResult(Fnew)));
212+
expect(
213+
referenceLookup(
214+
constructorTearoffs, 'F<InvalidThings, DoNotMatterHere>.new'),
215+
equals(MatchingLinkResult(Fnew)));
216+
});
217+
218+
test('negative tests', () {
219+
expect(referenceLookup(constructorTearoffs, 'M.new'),
220+
equals(MatchingLinkResult(null)));
221+
});
206222
}, skip: !_constructorTearoffsAllowed.allows(utils.platformVersion));
207223
});
208224

0 commit comments

Comments
 (0)