mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Loosen author tag parsing (#41820)
* Loosen author tag parsing Also make the code more efficient and easier to read. 1. Arbitrary text, except for newline and @, is allowed for the author name. 2. Arbirtrary text, except for newline, is allowed for the email address. 3. Newline is treated as a match for an open < I tried to allow newlines in the author and email, but it was ambiguous with the end of the tag. I also got rid of the two lookaheads and unified the trailing comment handling. Fixes #41804 * remove hardmode test since it did not reveal anything new
This commit is contained in:
+17
-49
@@ -7740,63 +7740,31 @@ namespace ts {
|
||||
}
|
||||
|
||||
function parseAuthorTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocAuthorTag {
|
||||
const authorInfoWithEmail = tryParse(() => tryParseAuthorNameAndEmail());
|
||||
if (!authorInfoWithEmail) {
|
||||
const end = getNodePos();
|
||||
return finishNode(factory.createJSDocAuthorTag(tagName, parseTrailingTagComments(start, end, indent, indentText)), start, end);
|
||||
}
|
||||
|
||||
let comments = authorInfoWithEmail;
|
||||
if (lookAhead(() => nextToken() !== SyntaxKind.NewLineTrivia)) {
|
||||
const comment = parseTagComments(indent);
|
||||
if (comment) {
|
||||
comments += comment;
|
||||
}
|
||||
}
|
||||
|
||||
return finishNode(factory.createJSDocAuthorTag(tagName, comments), start);
|
||||
const comments = parseAuthorNameAndEmail() + (parseTrailingTagComments(start, end, indent, indentText) || "");
|
||||
return finishNode(factory.createJSDocAuthorTag(tagName, comments || undefined), start);
|
||||
}
|
||||
|
||||
function tryParseAuthorNameAndEmail(): string | undefined {
|
||||
function parseAuthorNameAndEmail(): string {
|
||||
const comments: string[] = [];
|
||||
let seenLessThan = false;
|
||||
let seenGreaterThan = false;
|
||||
let inEmail = false;
|
||||
let token = scanner.getToken();
|
||||
|
||||
loop: while (true) {
|
||||
switch (token) {
|
||||
case SyntaxKind.Identifier:
|
||||
case SyntaxKind.WhitespaceTrivia:
|
||||
case SyntaxKind.DotToken:
|
||||
case SyntaxKind.AtToken:
|
||||
comments.push(scanner.getTokenText());
|
||||
break;
|
||||
case SyntaxKind.LessThanToken:
|
||||
if (seenLessThan || seenGreaterThan) {
|
||||
return;
|
||||
}
|
||||
seenLessThan = true;
|
||||
comments.push(scanner.getTokenText());
|
||||
break;
|
||||
case SyntaxKind.GreaterThanToken:
|
||||
if (!seenLessThan || seenGreaterThan) {
|
||||
return;
|
||||
}
|
||||
seenGreaterThan = true;
|
||||
comments.push(scanner.getTokenText());
|
||||
scanner.setTextPos(scanner.getTokenPos() + 1);
|
||||
break loop;
|
||||
case SyntaxKind.NewLineTrivia:
|
||||
case SyntaxKind.EndOfFileToken:
|
||||
break loop;
|
||||
while (token !== SyntaxKind.EndOfFileToken && token !== SyntaxKind.NewLineTrivia) {
|
||||
if (token === SyntaxKind.LessThanToken) {
|
||||
inEmail = true;
|
||||
}
|
||||
|
||||
else if (token === SyntaxKind.AtToken && !inEmail) {
|
||||
break;
|
||||
}
|
||||
else if (token === SyntaxKind.GreaterThanToken && inEmail) {
|
||||
comments.push(scanner.getTokenText());
|
||||
scanner.setTextPos(scanner.getTokenPos() + 1);
|
||||
break;
|
||||
}
|
||||
comments.push(scanner.getTokenText());
|
||||
token = nextTokenJSDoc();
|
||||
}
|
||||
|
||||
if (seenLessThan && seenGreaterThan) {
|
||||
return comments.length === 0 ? undefined : comments.join("");
|
||||
}
|
||||
return comments.join("");
|
||||
}
|
||||
|
||||
function parseImplementsTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocImplementsTag {
|
||||
|
||||
@@ -319,6 +319,21 @@ namespace ts {
|
||||
`/**
|
||||
* @author John Doe <john.doe@example.com>
|
||||
* @author John Doe <john.doe@example.com> unexpected comment
|
||||
* @author 108 <108@actionbutton.net> Video Games Forever
|
||||
* @author Multiple Ats <email@quoting@how@does@it@work>
|
||||
* @author Multiple Open Carets <hi<there@<>
|
||||
* @author Multiple Close Carets <probably>invalid>but>who>cares>
|
||||
* @author Unclosed Carets <joe@sloppy.gov
|
||||
* @author Multiple @author On One <one@two.three> @author Line
|
||||
* @author @author @author Empty authors
|
||||
* @author
|
||||
* @author
|
||||
* Comments
|
||||
* @author Early Close Caret > <a@b>
|
||||
* @author No Line Breaks:
|
||||
* <the.email@address> must be on the same line to parse
|
||||
* @author Long Comment <long@comment.org> I
|
||||
* want to keep commenting down here, I dunno.
|
||||
*/`);
|
||||
|
||||
parsesCorrectly("consecutive newline tokens",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"kind": "JSDocComment",
|
||||
"pos": 0,
|
||||
"end": 112,
|
||||
"end": 738,
|
||||
"flags": "JSDoc",
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
@@ -25,7 +25,7 @@
|
||||
"1": {
|
||||
"kind": "JSDocAuthorTag",
|
||||
"pos": 50,
|
||||
"end": 110,
|
||||
"end": 112,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"tagName": {
|
||||
@@ -38,9 +38,278 @@
|
||||
},
|
||||
"comment": "John Doe <john.doe@example.com> unexpected comment"
|
||||
},
|
||||
"length": 2,
|
||||
"2": {
|
||||
"kind": "JSDocAuthorTag",
|
||||
"pos": 112,
|
||||
"end": 170,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"tagName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 113,
|
||||
"end": 119,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"escapedText": "author"
|
||||
},
|
||||
"comment": "108 <108@actionbutton.net> Video Games Forever"
|
||||
},
|
||||
"3": {
|
||||
"kind": "JSDocAuthorTag",
|
||||
"pos": 170,
|
||||
"end": 227,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"tagName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 171,
|
||||
"end": 177,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"escapedText": "author"
|
||||
},
|
||||
"comment": "Multiple Ats <email@quoting@how@does@it@work>"
|
||||
},
|
||||
"4": {
|
||||
"kind": "JSDocAuthorTag",
|
||||
"pos": 227,
|
||||
"end": 272,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"tagName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 228,
|
||||
"end": 234,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"escapedText": "author"
|
||||
},
|
||||
"comment": "Multiple Open Carets <hi<there@<>"
|
||||
},
|
||||
"5": {
|
||||
"kind": "JSDocAuthorTag",
|
||||
"pos": 272,
|
||||
"end": 338,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"tagName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 273,
|
||||
"end": 279,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"escapedText": "author"
|
||||
},
|
||||
"comment": "Multiple Close Carets <probably>invalid>but>who>cares>"
|
||||
},
|
||||
"6": {
|
||||
"kind": "JSDocAuthorTag",
|
||||
"pos": 338,
|
||||
"end": 381,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"tagName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 339,
|
||||
"end": 345,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"escapedText": "author"
|
||||
},
|
||||
"comment": "Unclosed Carets <joe@sloppy.gov"
|
||||
},
|
||||
"7": {
|
||||
"kind": "JSDocAuthorTag",
|
||||
"pos": 381,
|
||||
"end": 398,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"tagName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 382,
|
||||
"end": 388,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"escapedText": "author"
|
||||
},
|
||||
"comment": "Multiple "
|
||||
},
|
||||
"8": {
|
||||
"kind": "JSDocAuthorTag",
|
||||
"pos": 398,
|
||||
"end": 429,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"tagName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 399,
|
||||
"end": 405,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"escapedText": "author"
|
||||
},
|
||||
"comment": "On One <one@two.three>"
|
||||
},
|
||||
"9": {
|
||||
"kind": "JSDocAuthorTag",
|
||||
"pos": 429,
|
||||
"end": 445,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"tagName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 430,
|
||||
"end": 436,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"escapedText": "author"
|
||||
},
|
||||
"comment": "Line"
|
||||
},
|
||||
"10": {
|
||||
"kind": "JSDocAuthorTag",
|
||||
"pos": 445,
|
||||
"end": 453,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"tagName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 446,
|
||||
"end": 452,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"escapedText": "author"
|
||||
}
|
||||
},
|
||||
"11": {
|
||||
"kind": "JSDocAuthorTag",
|
||||
"pos": 453,
|
||||
"end": 461,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"tagName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 454,
|
||||
"end": 460,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"escapedText": "author"
|
||||
}
|
||||
},
|
||||
"12": {
|
||||
"kind": "JSDocAuthorTag",
|
||||
"pos": 461,
|
||||
"end": 486,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"tagName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 462,
|
||||
"end": 468,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"escapedText": "author"
|
||||
},
|
||||
"comment": "Empty authors"
|
||||
},
|
||||
"13": {
|
||||
"kind": "JSDocAuthorTag",
|
||||
"pos": 486,
|
||||
"end": 497,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"tagName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 487,
|
||||
"end": 493,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"escapedText": "author"
|
||||
}
|
||||
},
|
||||
"14": {
|
||||
"kind": "JSDocAuthorTag",
|
||||
"pos": 497,
|
||||
"end": 522,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"tagName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 498,
|
||||
"end": 504,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"escapedText": "author"
|
||||
},
|
||||
"comment": "Comments"
|
||||
},
|
||||
"15": {
|
||||
"kind": "JSDocAuthorTag",
|
||||
"pos": 522,
|
||||
"end": 559,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"tagName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 523,
|
||||
"end": 529,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"escapedText": "author"
|
||||
},
|
||||
"comment": "Early Close Caret > <a@b>"
|
||||
},
|
||||
"16": {
|
||||
"kind": "JSDocAuthorTag",
|
||||
"pos": 559,
|
||||
"end": 598,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"tagName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 560,
|
||||
"end": 566,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"escapedText": "author"
|
||||
},
|
||||
"comment": "No Line Breaks:<the.email"
|
||||
},
|
||||
"17": {
|
||||
"kind": "JSDocTag",
|
||||
"pos": 598,
|
||||
"end": 606,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"tagName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 599,
|
||||
"end": 606,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"escapedText": "address"
|
||||
},
|
||||
"comment": "> must be on the same line to parse"
|
||||
},
|
||||
"18": {
|
||||
"kind": "JSDocAuthorTag",
|
||||
"pos": 645,
|
||||
"end": 736,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"tagName": {
|
||||
"kind": "Identifier",
|
||||
"pos": 646,
|
||||
"end": 652,
|
||||
"modifierFlagsCache": 0,
|
||||
"transformFlags": 0,
|
||||
"escapedText": "author"
|
||||
},
|
||||
"comment": "Long Comment <long@comment.org> I\nwant to keep commenting down here, I dunno."
|
||||
},
|
||||
"length": 19,
|
||||
"pos": 7,
|
||||
"end": 110,
|
||||
"end": 736,
|
||||
"hasTrailingComma": false,
|
||||
"transformFlags": 0
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user