Skip to content

Add @linkcode and @linkplain tags #44208

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39316,7 +39316,7 @@ namespace ts {
return undefined;
}

const isJSDoc = findAncestor(name, or(isJSDocLink, isJSDocNameReference, isJSDocMemberName));
const isJSDoc = findAncestor(name, or(isJSDocLinkLike, isJSDocNameReference, isJSDocMemberName));
const meaning = isJSDoc ? SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Value : SymbolFlags.Value;
if (name.kind === SyntaxKind.Identifier) {
if (isJSXTagName(name) && isJsxIntrinsicIdentifier(name)) {
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3785,7 +3785,7 @@ namespace ts {
emit(tagName);
}

function emitJSDocComment(comment: string | NodeArray<JSDocText | JSDocLink> | undefined) {
function emitJSDocComment(comment: string | NodeArray<JSDocComment> | undefined) {
const text = getTextOfJSDocComment(comment);
if (text) {
writeSpace();
Expand Down
92 changes: 63 additions & 29 deletions src/compiler/factory/nodeFactory.ts

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions src/compiler/factory/nodeTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,14 @@ namespace ts {
return node.kind === SyntaxKind.JSDocLink;
}

export function isJSDocLinkCode(node: Node): node is JSDocLinkCode {
return node.kind === SyntaxKind.JSDocLinkCode;
}

export function isJSDocLinkPlain(node: Node): node is JSDocLinkPlain {
return node.kind === SyntaxKind.JSDocLinkPlain;
}

export function isJSDocAllType(node: Node): node is JSDocAllType {
return node.kind === SyntaxKind.JSDocAllType;
}
Expand Down
58 changes: 34 additions & 24 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -481,12 +481,12 @@ namespace ts {
return visitNodes(cbNode, cbNodes, (node as JSDocFunctionType).parameters) ||
visitNode(cbNode, (node as JSDocFunctionType).type);
case SyntaxKind.JSDocComment:
return (typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray<JSDocText | JSDocLink> | undefined))
return (typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray<JSDocComment> | undefined))
|| visitNodes(cbNode, cbNodes, (node as JSDoc).tags);
case SyntaxKind.JSDocSeeTag:
return visitNode(cbNode, (node as JSDocSeeTag).tagName) ||
visitNode(cbNode, (node as JSDocSeeTag).name) ||
(typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray<JSDocText | JSDocLink> | undefined));
(typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray<JSDocComment> | undefined));
case SyntaxKind.JSDocNameReference:
return visitNode(cbNode, (node as JSDocNameReference).name);
case SyntaxKind.JSDocMemberName:
Expand All @@ -498,54 +498,56 @@ namespace ts {
((node as JSDocPropertyLikeTag).isNameFirst
? visitNode(cbNode, (node as JSDocPropertyLikeTag).name) ||
visitNode(cbNode, (node as JSDocPropertyLikeTag).typeExpression) ||
(typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray<JSDocText | JSDocLink> | undefined))
(typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray<JSDocComment> | undefined))
: visitNode(cbNode, (node as JSDocPropertyLikeTag).typeExpression) ||
visitNode(cbNode, (node as JSDocPropertyLikeTag).name)) ||
(typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray<JSDocText | JSDocLink> | undefined));
(typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray<JSDocComment> | undefined));
case SyntaxKind.JSDocAuthorTag:
return visitNode(cbNode, (node as JSDocTag).tagName) ||
(typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray<JSDocText | JSDocLink> | undefined));
(typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray<JSDocComment> | undefined));
case SyntaxKind.JSDocImplementsTag:
return visitNode(cbNode, (node as JSDocTag).tagName) ||
visitNode(cbNode, (node as JSDocImplementsTag).class) ||
(typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray<JSDocText | JSDocLink> | undefined));
(typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray<JSDocComment> | undefined));
case SyntaxKind.JSDocAugmentsTag:
return visitNode(cbNode, (node as JSDocTag).tagName) ||
visitNode(cbNode, (node as JSDocAugmentsTag).class) ||
(typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray<JSDocText | JSDocLink> | undefined));
(typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray<JSDocComment> | undefined));
case SyntaxKind.JSDocTemplateTag:
return visitNode(cbNode, (node as JSDocTag).tagName) ||
visitNode(cbNode, (node as JSDocTemplateTag).constraint) ||
visitNodes(cbNode, cbNodes, (node as JSDocTemplateTag).typeParameters) ||
(typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray<JSDocText | JSDocLink> | undefined));
(typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray<JSDocComment> | undefined));
case SyntaxKind.JSDocTypedefTag:
return visitNode(cbNode, (node as JSDocTag).tagName) ||
((node as JSDocTypedefTag).typeExpression &&
(node as JSDocTypedefTag).typeExpression!.kind === SyntaxKind.JSDocTypeExpression
? visitNode(cbNode, (node as JSDocTypedefTag).typeExpression) ||
visitNode(cbNode, (node as JSDocTypedefTag).fullName) ||
(typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray<JSDocText | JSDocLink> | undefined))
(typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray<JSDocComment> | undefined))
: visitNode(cbNode, (node as JSDocTypedefTag).fullName) ||
visitNode(cbNode, (node as JSDocTypedefTag).typeExpression)) ||
(typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray<JSDocText | JSDocLink> | undefined));
(typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray<JSDocComment> | undefined));
case SyntaxKind.JSDocCallbackTag:
return visitNode(cbNode, (node as JSDocTag).tagName) ||
visitNode(cbNode, (node as JSDocCallbackTag).fullName) ||
visitNode(cbNode, (node as JSDocCallbackTag).typeExpression) ||
(typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray<JSDocText | JSDocLink> | undefined));
(typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray<JSDocComment> | undefined));
case SyntaxKind.JSDocReturnTag:
case SyntaxKind.JSDocTypeTag:
case SyntaxKind.JSDocThisTag:
case SyntaxKind.JSDocEnumTag:
return visitNode(cbNode, (node as JSDocTag).tagName) ||
visitNode(cbNode, (node as JSDocReturnTag | JSDocTypeTag | JSDocThisTag | JSDocEnumTag).typeExpression) ||
(typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray<JSDocText | JSDocLink> | undefined));
(typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray<JSDocComment> | undefined));
case SyntaxKind.JSDocSignature:
return forEach((node as JSDocSignature).typeParameters, cbNode) ||
forEach((node as JSDocSignature).parameters, cbNode) ||
visitNode(cbNode, (node as JSDocSignature).type);
case SyntaxKind.JSDocLink:
return visitNode(cbNode, (node as JSDocLink).name);
case SyntaxKind.JSDocLinkCode:
case SyntaxKind.JSDocLinkPlain:
return visitNode(cbNode, (node as JSDocLink | JSDocLinkCode | JSDocLinkPlain).name);
case SyntaxKind.JSDocTypeLiteral:
return forEach((node as JSDocTypeLiteral).jsDocPropertyTags, cbNode);
case SyntaxKind.JSDocTag:
Expand All @@ -556,7 +558,7 @@ namespace ts {
case SyntaxKind.JSDocReadonlyTag:
case SyntaxKind.JSDocDeprecatedTag:
return visitNode(cbNode, (node as JSDocTag).tagName)
|| (typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray<JSDocText | JSDocLink> | undefined));
|| (typeof (node as JSDoc).comment === "string" ? undefined : visitNodes(cbNode, cbNodes, (node as JSDoc).comment as NodeArray<JSDocComment> | undefined));
case SyntaxKind.PartiallyEmittedExpression:
return visitNode(cbNode, (node as PartiallyEmittedExpression).expression);
}
Expand Down Expand Up @@ -7425,7 +7427,7 @@ namespace ts {
let linkEnd: number;
let commentsPos: number | undefined;
let comments: string[] = [];
const parts: (JSDocLink | JSDocText)[] = [];
const parts: JSDocComment[] = [];

// + 3 for leading /**, - 5 in total for /** */
return scanner.scanRange(start + 3, length - 5, () => {
Expand Down Expand Up @@ -7681,10 +7683,10 @@ namespace ts {
return parseTagComments(margin, indentText.slice(margin));
}

function parseTagComments(indent: number, initialMargin?: string): string | NodeArray<JSDocText | JSDocLink> | undefined {
function parseTagComments(indent: number, initialMargin?: string): string | NodeArray<JSDocComment> | undefined {
const commentsPos = getNodePos();
let comments: string[] = [];
const parts: (JSDocLink | JSDocText)[] = [];
const parts: JSDocComment[] = [];
let linkEnd;
let state = JSDocState.BeginningOfLine;
let previousWhitespace = true;
Expand Down Expand Up @@ -7800,7 +7802,8 @@ namespace ts {
}

function parseJSDocLink(start: number) {
if (!tryParse(parseJSDocLinkPrefix)) {
const linkType = tryParse(parseJSDocLinkPrefix);
if (!linkType) {
return undefined;
}
nextTokenJSDoc(); // start at token after link, then skip any whitespace
Expand All @@ -7822,15 +7825,22 @@ namespace ts {
text.push(scanner.getTokenText());
nextTokenJSDoc();
}
return finishNode(factory.createJSDocLink(name, text.join("")), start, scanner.getTextPos());
const create = linkType === "link" ? factory.createJSDocLink
: linkType === "linkcode" ? factory.createJSDocLinkCode
: factory.createJSDocLinkPlain;
return finishNode(create(name, text.join("")), start, scanner.getTextPos());
}

function parseJSDocLinkPrefix() {
skipWhitespaceOrAsterisk();
return token() === SyntaxKind.OpenBraceToken
if (token() === SyntaxKind.OpenBraceToken
&& nextTokenJSDoc() === SyntaxKind.AtToken
&& tokenIsIdentifierOrKeyword(nextTokenJSDoc())
&& scanner.getTokenValue() === "link";
&& tokenIsIdentifierOrKeyword(nextTokenJSDoc())) {
const kind = scanner.getTokenValue();
if(kind === "link" || kind === "linkcode" || kind === "linkplain") {
return kind;
}
}
}

function parseUnknownTag(start: number, tagName: Identifier, indent: number, indentText: string) {
Expand Down Expand Up @@ -7969,7 +7979,7 @@ namespace ts {
commentEnd = scanner.getStartPos();
}
const allParts = typeof comments !== "string"
? createNodeArray(concatenate([finishNode(textOnly, commentStart, commentEnd)], comments) as (JSDocText | JSDocLink)[], commentStart) // cast away readonly
? createNodeArray(concatenate([finishNode(textOnly, commentStart, commentEnd)], comments) as JSDocComment[], commentStart) // cast away readonly
: textOnly.text + comments;
return finishNode(factory.createJSDocAuthorTag(tagName, allParts), start);
}
Expand Down Expand Up @@ -8030,7 +8040,7 @@ namespace ts {
return node;
}

function parseSimpleTag(start: number, createTag: (tagName: Identifier | undefined, comment?: string | NodeArray<JSDocText | JSDocLink>) => JSDocTag, tagName: Identifier, margin: number, indentText: string): JSDocTag {
function parseSimpleTag(start: number, createTag: (tagName: Identifier | undefined, comment?: string | NodeArray<JSDocComment>) => JSDocTag, tagName: Identifier, margin: number, indentText: string): JSDocTag {
return finishNode(createTag(tagName, parseTrailingTagComments(start, getNodePos(), margin, indentText)), start);
}

Expand Down
Loading