Skip to content

Commit ea9d519

Browse files
committed
Support email in author JSDoc tag
- fixes microsoft#17244
1 parent 2eea216 commit ea9d519

File tree

10 files changed

+118
-6
lines changed

10 files changed

+118
-6
lines changed

src/compiler/parser.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6611,6 +6611,9 @@ namespace ts {
66116611

66126612
let tag: JSDocTag | undefined;
66136613
switch (tagName.escapedText) {
6614+
case "author":
6615+
tag = parseAuthorTag(start, tagName);
6616+
break;
66146617
case "augments":
66156618
case "extends":
66166619
tag = parseAugmentsTag(start, tagName);
@@ -6874,6 +6877,69 @@ namespace ts {
68746877
return finishNode(result);
68756878
}
68766879

6880+
function parseAuthorTag(start: number, tagName: Identifier): JSDocAuthorTag {
6881+
const result = <JSDocAuthorTag>createNode(SyntaxKind.JSDocAuthorTag, start);
6882+
result.tagName = tagName;
6883+
6884+
const comment = tryParse(() => tryParseAuthorNameAndEmail());
6885+
6886+
if (comment) {
6887+
result.comment = comment;
6888+
}
6889+
6890+
return finishNode(result);
6891+
}
6892+
6893+
function tryParseAuthorNameAndEmail(): string | undefined {
6894+
const comments: string[] = [];
6895+
let seenLessThan = false;
6896+
let seenGreaterThan = false;
6897+
let seenAtToken = false;
6898+
let token = scanner.getToken();
6899+
6900+
loop: while (true) {
6901+
switch (token) {
6902+
case SyntaxKind.Identifier:
6903+
case SyntaxKind.WhitespaceTrivia:
6904+
case SyntaxKind.DotToken:
6905+
comments.push(scanner.getTokenText());
6906+
break;
6907+
case SyntaxKind.LessThanToken:
6908+
if (seenLessThan || seenAtToken || seenGreaterThan) {
6909+
return;
6910+
}
6911+
seenLessThan = true;
6912+
comments.push(scanner.getTokenText());
6913+
break;
6914+
case SyntaxKind.GreaterThanToken:
6915+
if (!seenLessThan || !seenAtToken || seenGreaterThan) {
6916+
return;
6917+
}
6918+
6919+
seenGreaterThan = true;
6920+
comments.push(scanner.getTokenText());
6921+
break loop;
6922+
case SyntaxKind.AtToken:
6923+
if (seenAtToken || !seenLessThan || seenGreaterThan) {
6924+
return;
6925+
}
6926+
6927+
seenAtToken = true;
6928+
comments.push(scanner.getTokenText());
6929+
break;
6930+
case SyntaxKind.NewLineTrivia:
6931+
case SyntaxKind.EndOfFileToken:
6932+
break loop;
6933+
}
6934+
6935+
token = nextJSDocToken();
6936+
}
6937+
6938+
if (seenLessThan && seenAtToken && seenGreaterThan) {
6939+
return comments.length === 0 ? undefined : comments.join("");
6940+
}
6941+
}
6942+
68776943
function parseAugmentsTag(start: number, tagName: Identifier): JSDocAugmentsTag {
68786944
const result = <JSDocAugmentsTag>createNode(SyntaxKind.JSDocAugmentsTag, start);
68796945
result.tagName = tagName;

src/compiler/scanner.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2086,6 +2086,8 @@ namespace ts {
20862086
return token = SyntaxKind.CloseBracketToken;
20872087
case CharacterCodes.lessThan:
20882088
return token = SyntaxKind.LessThanToken;
2089+
case CharacterCodes.greaterThan:
2090+
return token = SyntaxKind.GreaterThanToken;
20892091
case CharacterCodes.equals:
20902092
return token = SyntaxKind.EqualsToken;
20912093
case CharacterCodes.comma:

src/compiler/types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ namespace ts {
1717
| SyntaxKind.OpenBraceToken
1818
| SyntaxKind.CloseBraceToken
1919
| SyntaxKind.LessThanToken
20+
| SyntaxKind.GreaterThanToken
2021
| SyntaxKind.OpenBracketToken
2122
| SyntaxKind.CloseBracketToken
2223
| SyntaxKind.EqualsToken
@@ -459,6 +460,7 @@ namespace ts {
459460
JSDocSignature,
460461
JSDocTag,
461462
JSDocAugmentsTag,
463+
JSDocAuthorTag,
462464
JSDocClassTag,
463465
JSDocCallbackTag,
464466
JSDocEnumTag,
@@ -2455,6 +2457,10 @@ namespace ts {
24552457
class: ExpressionWithTypeArguments & { expression: Identifier | PropertyAccessEntityNameExpression };
24562458
}
24572459

2460+
export interface JSDocAuthorTag extends JSDocTag {
2461+
kind: SyntaxKind.JSDocAuthorTag;
2462+
}
2463+
24582464
export interface JSDocClassTag extends JSDocTag {
24592465
kind: SyntaxKind.JSDocClassTag;
24602466
}

src/compiler/utilities.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6116,6 +6116,10 @@ namespace ts {
61166116
return node.kind === SyntaxKind.JSDocComment;
61176117
}
61186118

6119+
export function isJSDocAuthorTag(node: Node): node is JSDocAuthorTag {
6120+
return node.kind === SyntaxKind.JSDocAuthorTag;
6121+
}
6122+
61196123
export function isJSDocAugmentsTag(node: Node): node is JSDocAugmentsTag {
61206124
return node.kind === SyntaxKind.JSDocAugmentsTag;
61216125
}

src/testRunner/unittests/jsDocParsing.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,10 @@ namespace ts {
313313
* {@link first link}
314314
* Inside {@link link text} thing
315315
* @see {@link second link text} and {@link Foo|a foo} as well.
316+
*/`);
317+
parsesCorrectly("authorTag",
318+
`/**
319+
* @author John Doe <[email protected]>
316320
*/`);
317321
});
318322
});
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"kind": "JSDocComment",
3+
"pos": 0,
4+
"end": 50,
5+
"tags": {
6+
"0": {
7+
"kind": "JSDocAuthorTag",
8+
"pos": 7,
9+
"end": 45,
10+
"tagName": {
11+
"kind": "Identifier",
12+
"pos": 8,
13+
"end": 14,
14+
"escapedText": "author"
15+
},
16+
"comment": "John Doe <[email protected]>"
17+
},
18+
"length": 1,
19+
"pos": 7,
20+
"end": 45
21+
}
22+
}

tests/baselines/reference/api/tsserverlibrary.d.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ declare namespace ts {
7272
pos: number;
7373
end: number;
7474
}
75-
type JSDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.BacktickToken | SyntaxKind.Unknown | KeywordSyntaxKind;
75+
type JSDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.GreaterThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.BacktickToken | SyntaxKind.Unknown | KeywordSyntaxKind;
7676
type KeywordSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AnyKeyword | SyntaxKind.AsKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.BreakKeyword | SyntaxKind.CaseKeyword | SyntaxKind.CatchKeyword | SyntaxKind.ClassKeyword | SyntaxKind.ContinueKeyword | SyntaxKind.ConstKeyword | SyntaxKind.ConstructorKeyword | SyntaxKind.DebuggerKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.DeleteKeyword | SyntaxKind.DoKeyword | SyntaxKind.ElseKeyword | SyntaxKind.EnumKeyword | SyntaxKind.ExportKeyword | SyntaxKind.ExtendsKeyword | SyntaxKind.FalseKeyword | SyntaxKind.FinallyKeyword | SyntaxKind.ForKeyword | SyntaxKind.FromKeyword | SyntaxKind.FunctionKeyword | SyntaxKind.GetKeyword | SyntaxKind.IfKeyword | SyntaxKind.ImplementsKeyword | SyntaxKind.ImportKeyword | SyntaxKind.InKeyword | SyntaxKind.InferKeyword | SyntaxKind.InstanceOfKeyword | SyntaxKind.InterfaceKeyword | SyntaxKind.IsKeyword | SyntaxKind.KeyOfKeyword | SyntaxKind.LetKeyword | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NewKeyword | SyntaxKind.NullKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.PackageKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.RequireKeyword | SyntaxKind.GlobalKeyword | SyntaxKind.ReturnKeyword | SyntaxKind.SetKeyword | SyntaxKind.StaticKeyword | SyntaxKind.StringKeyword | SyntaxKind.SuperKeyword | SyntaxKind.SwitchKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.ThrowKeyword | SyntaxKind.TrueKeyword | SyntaxKind.TryKeyword | SyntaxKind.TypeKeyword | SyntaxKind.TypeOfKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VarKeyword | SyntaxKind.VoidKeyword | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.AwaitKeyword | SyntaxKind.OfKeyword;
7777
type JsxTokenSyntaxKind = SyntaxKind.LessThanSlashToken | SyntaxKind.EndOfFileToken | SyntaxKind.ConflictMarkerTrivia | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.OpenBraceToken | SyntaxKind.LessThanToken;
7878
enum SyntaxKind {
@@ -1581,6 +1581,9 @@ declare namespace ts {
15811581
expression: Identifier | PropertyAccessEntityNameExpression;
15821582
};
15831583
}
1584+
interface JSDocAuthorTag extends JSDocTag {
1585+
kind: SyntaxKind.JSDocAuthorTag;
1586+
}
15841587
interface JSDocClassTag extends JSDocTag {
15851588
kind: SyntaxKind.JSDocClassTag;
15861589
}
@@ -3521,6 +3524,7 @@ declare namespace ts {
35213524
function isJSDocFunctionType(node: Node): node is JSDocFunctionType;
35223525
function isJSDocVariadicType(node: Node): node is JSDocVariadicType;
35233526
function isJSDoc(node: Node): node is JSDoc;
3527+
function isJSDocAuthorTag(node: Node): node is JSDocAuthorTag;
35243528
function isJSDocAugmentsTag(node: Node): node is JSDocAugmentsTag;
35253529
function isJSDocClassTag(node: Node): node is JSDocClassTag;
35263530
function isJSDocEnumTag(node: Node): node is JSDocEnumTag;

tests/baselines/reference/api/typescript.d.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ declare namespace ts {
7272
pos: number;
7373
end: number;
7474
}
75-
type JSDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.BacktickToken | SyntaxKind.Unknown | KeywordSyntaxKind;
75+
type JSDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.GreaterThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.BacktickToken | SyntaxKind.Unknown | KeywordSyntaxKind;
7676
type KeywordSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AnyKeyword | SyntaxKind.AsKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.BreakKeyword | SyntaxKind.CaseKeyword | SyntaxKind.CatchKeyword | SyntaxKind.ClassKeyword | SyntaxKind.ContinueKeyword | SyntaxKind.ConstKeyword | SyntaxKind.ConstructorKeyword | SyntaxKind.DebuggerKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.DeleteKeyword | SyntaxKind.DoKeyword | SyntaxKind.ElseKeyword | SyntaxKind.EnumKeyword | SyntaxKind.ExportKeyword | SyntaxKind.ExtendsKeyword | SyntaxKind.FalseKeyword | SyntaxKind.FinallyKeyword | SyntaxKind.ForKeyword | SyntaxKind.FromKeyword | SyntaxKind.FunctionKeyword | SyntaxKind.GetKeyword | SyntaxKind.IfKeyword | SyntaxKind.ImplementsKeyword | SyntaxKind.ImportKeyword | SyntaxKind.InKeyword | SyntaxKind.InferKeyword | SyntaxKind.InstanceOfKeyword | SyntaxKind.InterfaceKeyword | SyntaxKind.IsKeyword | SyntaxKind.KeyOfKeyword | SyntaxKind.LetKeyword | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NewKeyword | SyntaxKind.NullKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.PackageKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.RequireKeyword | SyntaxKind.GlobalKeyword | SyntaxKind.ReturnKeyword | SyntaxKind.SetKeyword | SyntaxKind.StaticKeyword | SyntaxKind.StringKeyword | SyntaxKind.SuperKeyword | SyntaxKind.SwitchKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.ThrowKeyword | SyntaxKind.TrueKeyword | SyntaxKind.TryKeyword | SyntaxKind.TypeKeyword | SyntaxKind.TypeOfKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VarKeyword | SyntaxKind.VoidKeyword | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.AwaitKeyword | SyntaxKind.OfKeyword;
7777
type JsxTokenSyntaxKind = SyntaxKind.LessThanSlashToken | SyntaxKind.EndOfFileToken | SyntaxKind.ConflictMarkerTrivia | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.OpenBraceToken | SyntaxKind.LessThanToken;
7878
enum SyntaxKind {
@@ -1581,6 +1581,9 @@ declare namespace ts {
15811581
expression: Identifier | PropertyAccessEntityNameExpression;
15821582
};
15831583
}
1584+
interface JSDocAuthorTag extends JSDocTag {
1585+
kind: SyntaxKind.JSDocAuthorTag;
1586+
}
15841587
interface JSDocClassTag extends JSDocTag {
15851588
kind: SyntaxKind.JSDocClassTag;
15861589
}
@@ -3521,6 +3524,7 @@ declare namespace ts {
35213524
function isJSDocFunctionType(node: Node): node is JSDocFunctionType;
35223525
function isJSDocVariadicType(node: Node): node is JSDocVariadicType;
35233526
function isJSDoc(node: Node): node is JSDoc;
3527+
function isJSDocAuthorTag(node: Node): node is JSDocAuthorTag;
35243528
function isJSDocAugmentsTag(node: Node): node is JSDocAugmentsTag;
35253529
function isJSDocClassTag(node: Node): node is JSDocClassTag;
35263530
function isJSDocEnumTag(node: Node): node is JSDocEnumTag;

tests/baselines/reference/quickInfoJsDocTags.baseline

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
{
33
"marker": {
44
"fileName": "/tests/cases/fourslash/quickInfoJsDocTags.ts",
5-
"position": 256
5+
"position": 272
66
},
77
"quickInfo": {
88
"kind": "function",
99
"kindModifiers": "",
1010
"textSpan": {
11-
"start": 256,
11+
"start": 272,
1212
"length": 3
1313
},
1414
"displayParts": [
@@ -70,7 +70,7 @@
7070
"tags": [
7171
{
7272
"name": "author",
73-
"text": "Me"
73+
"text": "Me <[email protected]>"
7474
},
7575
{
7676
"name": "augments",

tests/cases/fourslash/quickInfoJsDocTags.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// @Filename: quickInfoJsDocTags.ts
44
/////**
55
//// * Doc
6-
//// * @author Me
6+
//// * @author Me <[email protected]>
77
//// * @augments {C<T>} Augments it
88
//// * @template T A template
99
//// * @type {number | string} A type

0 commit comments

Comments
 (0)