Skip to content

Add support for jsdoc function tag #40031

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

Closed
wants to merge 1 commit into from
Closed
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
3 changes: 3 additions & 0 deletions src/compat/deprecations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,9 @@ namespace ts {
/** @deprecated Use `factory.createJSDocCallbackTag` or the factory supplied by your transformation context instead. */
export const createJSDocCallbackTag = Debug.deprecate(factory.createJSDocCallbackTag, factoryDeprecation);

/** @deprecated Use `factory.createJSDocFunctionTag` or the factory supplied by your transformation context instead. */
export const createJSDocFunctionTag = Debug.deprecate(factory.createJSDocFunctionTag, factoryDeprecation);

/** @deprecated Use `factory.createJSDocSignature` or the factory supplied by your transformation context instead. */
export const createJSDocSignature = Debug.deprecate(factory.createJSDocSignature, factoryDeprecation);

Expand Down
10 changes: 6 additions & 4 deletions src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ namespace ts {
let thisParentContainer: Node; // Container one level up
let blockScopeContainer: Node;
let lastContainer: Node;
let delayedTypeAliases: (JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag)[];
let delayedTypeAliases: (JSDocTypedefTag | JSDocCallbackTag | JSDocFunctionTag | JSDocEnumTag)[];
let seenThisKeyword: boolean;

// state used by control flow analysis
Expand Down Expand Up @@ -809,7 +809,7 @@ namespace ts {
case SyntaxKind.JSDocTypedefTag:
case SyntaxKind.JSDocCallbackTag:
case SyntaxKind.JSDocEnumTag:
bindJSDocTypeAlias(node as JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag);
bindJSDocTypeAlias(node as JSDocTypedefTag | JSDocCallbackTag | JSDocFunctionTag | JSDocFunctionTag | JSDocEnumTag);
break;
// In source files and blocks, bind functions first to match hoisting that occurs at runtime
case SyntaxKind.SourceFile: {
Expand Down Expand Up @@ -1610,7 +1610,7 @@ namespace ts {
}
}

function bindJSDocTypeAlias(node: JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag) {
function bindJSDocTypeAlias(node: JSDocTypedefTag | JSDocCallbackTag | JSDocFunctionTag | JSDocEnumTag) {
setParent(node.tagName, node);
if (node.kind !== SyntaxKind.JSDocEnumTag && node.fullName) {
setParent(node.fullName, node);
Expand Down Expand Up @@ -1870,6 +1870,7 @@ namespace ts {
case SyntaxKind.JSDocFunctionType:
case SyntaxKind.JSDocTypedefTag:
case SyntaxKind.JSDocCallbackTag:
case SyntaxKind.JSDocFunctionTag:
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.MappedType:
// All the children of these container types are never visible through another
Expand Down Expand Up @@ -2672,8 +2673,9 @@ namespace ts {
return declareSymbolAndAddToSymbolTable(propTag, flags, SymbolFlags.PropertyExcludes);
case SyntaxKind.JSDocTypedefTag:
case SyntaxKind.JSDocCallbackTag:
case SyntaxKind.JSDocFunctionTag:
case SyntaxKind.JSDocEnumTag:
return (delayedTypeAliases || (delayedTypeAliases = [])).push(node as JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag);
return (delayedTypeAliases || (delayedTypeAliases = [])).push(node as JSDocTypedefTag | JSDocCallbackTag | JSDocFunctionTag | JSDocEnumTag);
}
}

Expand Down
12 changes: 9 additions & 3 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1902,6 +1902,7 @@ namespace ts {
break;
case SyntaxKind.JSDocTypedefTag:
case SyntaxKind.JSDocCallbackTag:
case SyntaxKind.JSDocFunctionTag:
case SyntaxKind.JSDocEnumTag:
// js type aliases do not resolve names from their host, so skip past it
location = getJSDocHost(location);
Expand Down Expand Up @@ -7323,6 +7324,7 @@ namespace ts {
function determineIfDeclarationIsVisible() {
switch (node.kind) {
case SyntaxKind.JSDocCallbackTag:
case SyntaxKind.JSDocFunctionTag:
case SyntaxKind.JSDocTypedefTag:
case SyntaxKind.JSDocEnumTag:
// Top-level jsdoc type aliases are considered exported
Expand Down Expand Up @@ -8773,6 +8775,7 @@ namespace ts {
case SyntaxKind.JSDocTypedefTag:
case SyntaxKind.JSDocEnumTag:
case SyntaxKind.JSDocCallbackTag:
case SyntaxKind.JSDocFunctionTag:
case SyntaxKind.MappedType:
case SyntaxKind.ConditionalType:
const outerTypeParameters = getOuterTypeParameters(node, includeThisTypes);
Expand Down Expand Up @@ -8817,7 +8820,7 @@ namespace ts {
node.kind === SyntaxKind.ClassExpression ||
isJSConstructor(node) ||
isTypeAlias(node)) {
const declaration = <InterfaceDeclaration | TypeAliasDeclaration | JSDocTypedefTag | JSDocCallbackTag>node;
const declaration = <InterfaceDeclaration | TypeAliasDeclaration | JSDocTypedefTag | JSDocCallbackTag | JSDocFunctionTag>node;
result = appendTypeParameters(result, getEffectiveTypeParameterDeclarations(declaration));
}
}
Expand Down Expand Up @@ -31522,6 +31525,7 @@ namespace ts {
// falls through
case SyntaxKind.JSDocTypedefTag:
case SyntaxKind.JSDocCallbackTag:
case SyntaxKind.JSDocFunctionTag:
case SyntaxKind.JSDocEnumTag:
return DeclarationSpaces.ExportType;
case SyntaxKind.ModuleDeclaration:
Expand Down Expand Up @@ -32097,7 +32101,7 @@ namespace ts {
}
}

function checkJSDocTypeAliasTag(node: JSDocTypedefTag | JSDocCallbackTag) {
function checkJSDocTypeAliasTag(node: JSDocTypedefTag | JSDocCallbackTag | JSDocFunctionTag) {
if (!node.typeExpression) {
// If the node had `@property` tags, `typeExpression` would have been set to the first property tag.
error(node.name, Diagnostics.JSDoc_typedef_tag_should_either_have_a_type_annotation_or_be_followed_by_property_or_member_tags);
Expand Down Expand Up @@ -35778,6 +35782,7 @@ namespace ts {
return checkJSDocImplementsTag(node as JSDocImplementsTag);
case SyntaxKind.JSDocTypedefTag:
case SyntaxKind.JSDocCallbackTag:
case SyntaxKind.JSDocFunctionTag:
case SyntaxKind.JSDocEnumTag:
return checkJSDocTypeAliasTag(node as JSDocTypedefTag);
case SyntaxKind.JSDocTemplateTag:
Expand Down Expand Up @@ -36258,7 +36263,7 @@ namespace ts {
getNameOfDeclaration(name.parent) === name;
}

function isTypeDeclaration(node: Node): node is TypeParameterDeclaration | ClassDeclaration | InterfaceDeclaration | TypeAliasDeclaration | JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag | EnumDeclaration | ImportClause | ImportSpecifier | ExportSpecifier {
function isTypeDeclaration(node: Node): node is TypeParameterDeclaration | ClassDeclaration | InterfaceDeclaration | TypeAliasDeclaration | JSDocTypedefTag | JSDocCallbackTag | JSDocFunctionTag | JSDocEnumTag | EnumDeclaration | ImportClause | ImportSpecifier | ExportSpecifier {
switch (node.kind) {
case SyntaxKind.TypeParameter:
case SyntaxKind.ClassDeclaration:
Expand All @@ -36267,6 +36272,7 @@ namespace ts {
case SyntaxKind.EnumDeclaration:
case SyntaxKind.JSDocTypedefTag:
case SyntaxKind.JSDocCallbackTag:
case SyntaxKind.JSDocFunctionTag:
case SyntaxKind.JSDocEnumTag:
return true;
case SyntaxKind.ImportClause:
Expand Down
5 changes: 3 additions & 2 deletions src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1538,7 +1538,8 @@ namespace ts {
case SyntaxKind.JSDocTypedefTag:
return emitJSDocTypedefTag(node as JSDocTypedefTag);
case SyntaxKind.JSDocCallbackTag:
return emitJSDocCallbackTag(node as JSDocCallbackTag);
case SyntaxKind.JSDocFunctionTag:
return emitJSDocCallbackOrFunctionTag(node as JSDocCallbackTag | JSDocFunctionTag);
case SyntaxKind.JSDocSignature:
return emitJSDocSignature(node as JSDocSignature);
case SyntaxKind.JSDocTypeLiteral:
Expand Down Expand Up @@ -3545,7 +3546,7 @@ namespace ts {
}
}

function emitJSDocCallbackTag(tag: JSDocCallbackTag) {
function emitJSDocCallbackOrFunctionTag(tag: JSDocCallbackTag | JSDocFunctionTag) {
emitJSDocTagName(tag.tagName);
if (tag.name) {
writeSpace();
Expand Down
22 changes: 22 additions & 0 deletions src/compiler/factory/nodeFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,8 @@ namespace ts {
updateJSDocPropertyTag,
createJSDocCallbackTag,
updateJSDocCallbackTag,
createJSDocFunctionTag,
updateJSDocFunctionTag,
createJSDocAugmentsTag,
updateJSDocAugmentsTag,
createJSDocImplementsTag,
Expand Down Expand Up @@ -4234,6 +4236,25 @@ namespace ts {
: node;
}

// @api
function createJSDocFunctionTag(tagName: Identifier | undefined, typeExpression: JSDocSignature, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string): JSDocFunctionTag {
const node = createBaseJSDocTag<JSDocFunctionTag>(SyntaxKind.JSDocFunctionTag, tagName ?? createIdentifier("function"), comment);
node.typeExpression = typeExpression;
node.fullName = fullName;
node.name = getJSDocTypeAliasName(fullName);
return node;
}

// @api
function updateJSDocFunctionTag(node: JSDocFunctionTag, tagName: Identifier = getDefaultTagName(node), typeExpression: JSDocSignature, fullName: Identifier | JSDocNamespaceDeclaration | undefined, comment: string | undefined): JSDocFunctionTag {
return node.tagName !== tagName
|| node.typeExpression !== typeExpression
|| node.fullName !== fullName
|| node.comment !== comment
? update(createJSDocFunctionTag(tagName, typeExpression, fullName, comment), node)
: node;
}

// @api
function createJSDocAugmentsTag(tagName: Identifier | undefined, className: JSDocAugmentsTag["class"], comment?: string): JSDocAugmentsTag {
const node = createBaseJSDocTag<JSDocAugmentsTag>(SyntaxKind.JSDocAugmentsTag, tagName ?? createIdentifier("augments"), comment);
Expand Down Expand Up @@ -5767,6 +5788,7 @@ namespace ts {
case SyntaxKind.JSDocParameterTag: return "param";
case SyntaxKind.JSDocPropertyTag: return "prop";
case SyntaxKind.JSDocCallbackTag: return "callback";
case SyntaxKind.JSDocFunctionTag: return "function";
case SyntaxKind.JSDocAugmentsTag: return "augments";
case SyntaxKind.JSDocImplementsTag: return "implements";
default:
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/factory/nodeTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,10 @@ namespace ts {
return node.kind === SyntaxKind.JSDocCallbackTag;
}

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

export function isJSDocPublicTag(node: Node): node is JSDocPublicTag {
return node.kind === SyntaxKind.JSDocPublicTag;
}
Expand Down
12 changes: 7 additions & 5 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -506,9 +506,10 @@ namespace ts {
: visitNode(cbNode, (<JSDocTypedefTag>node).fullName) ||
visitNode(cbNode, (<JSDocTypedefTag>node).typeExpression));
case SyntaxKind.JSDocCallbackTag:
case SyntaxKind.JSDocFunctionTag:
return visitNode(cbNode, (node as JSDocTag).tagName) ||
visitNode(cbNode, (node as JSDocCallbackTag).fullName) ||
visitNode(cbNode, (node as JSDocCallbackTag).typeExpression);
visitNode(cbNode, (node as JSDocCallbackTag | JSDocFunctionTag).fullName) ||
visitNode(cbNode, (node as JSDocCallbackTag | JSDocFunctionTag).typeExpression);
case SyntaxKind.JSDocReturnTag:
case SyntaxKind.JSDocTypeTag:
case SyntaxKind.JSDocThisTag:
Expand Down Expand Up @@ -7426,7 +7427,8 @@ namespace ts {
tag = parseTypedefTag(start, tagName, margin, indentText);
break;
case "callback":
tag = parseCallbackTag(start, tagName, margin, indentText);
case "function":
tag = parseCallbackOrFunctionTag(start, tagName, margin, indentText);
break;
default:
tag = parseUnknownTag(start, tagName, margin, indentText);
Expand Down Expand Up @@ -7866,7 +7868,7 @@ namespace ts {
return createNodeArray(parameters || [], pos);
}

function parseCallbackTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocCallbackTag {
function parseCallbackOrFunctionTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocCallbackTag | JSDocFunctionTag {
const fullName = parseJSDocTypeNameWithNamespace();
skipWhitespace();
let comment = parseTagComments(indent);
Expand All @@ -7884,7 +7886,7 @@ namespace ts {
if (!comment) {
comment = parseTrailingTagComments(start, end, indent, indentText);
}
return finishNode(factory.createJSDocCallbackTag(tagName, typeExpression, fullName, comment), start, end);
return finishNode((tagName.escapedText === "callback" ? factory.createJSDocCallbackTag : factory.createJSDocFunctionTag)(tagName, typeExpression, fullName, comment), start, end);
}

function escapedTextsEqual(a: EntityName, b: EntityName): boolean {
Expand Down
12 changes: 12 additions & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ namespace ts {
JSDocProtectedTag,
JSDocReadonlyTag,
JSDocCallbackTag,
JSDocFunctionTag,
JSDocEnumTag,
JSDocParameterTag,
JSDocReturnTag,
Expand Down Expand Up @@ -2756,6 +2757,7 @@ namespace ts {
| DeclarationWithTypeParameterChildren
| JSDocTypedefTag
| JSDocCallbackTag
| JSDocFunctionTag
| JSDocSignature
;

Expand Down Expand Up @@ -3205,6 +3207,14 @@ namespace ts {
readonly typeExpression: JSDocSignature;
}

export interface JSDocFunctionTag extends JSDocTag, NamedDeclaration {
readonly kind: SyntaxKind.JSDocFunctionTag;
readonly parent: JSDoc;
readonly fullName?: JSDocNamespaceDeclaration | Identifier;
readonly name?: Identifier;
readonly typeExpression: JSDocSignature;
}

export interface JSDocSignature extends JSDocType, Declaration {
readonly kind: SyntaxKind.JSDocSignature;
readonly typeParameters?: readonly JSDocTemplateTag[];
Expand Down Expand Up @@ -6979,6 +6989,8 @@ namespace ts {
updateJSDocEnumTag(node: JSDocEnumTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment: string | undefined): JSDocEnumTag;
createJSDocCallbackTag(tagName: Identifier | undefined, typeExpression: JSDocSignature, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string): JSDocCallbackTag;
updateJSDocCallbackTag(node: JSDocCallbackTag, tagName: Identifier | undefined, typeExpression: JSDocSignature, fullName: Identifier | JSDocNamespaceDeclaration | undefined, comment: string | undefined): JSDocCallbackTag;
createJSDocFunctionTag(tagName: Identifier | undefined, typeExpression: JSDocSignature, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string): JSDocFunctionTag;
updateJSDocFunctionTag(node: JSDocFunctionTag, tagName: Identifier | undefined, typeExpression: JSDocSignature, fullName: Identifier | JSDocNamespaceDeclaration | undefined, comment: string | undefined): JSDocFunctionTag;
createJSDocAugmentsTag(tagName: Identifier | undefined, className: JSDocAugmentsTag["class"], comment?: string): JSDocAugmentsTag;
updateJSDocAugmentsTag(node: JSDocAugmentsTag, tagName: Identifier | undefined, className: JSDocAugmentsTag["class"], comment: string | undefined): JSDocAugmentsTag;
createJSDocImplementsTag(tagName: Identifier | undefined, className: JSDocImplementsTag["class"], comment?: string): JSDocImplementsTag;
Expand Down
7 changes: 4 additions & 3 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,7 @@ namespace ts {
export function isDeclarationWithTypeParameters(node: DeclarationWithTypeParameters): node is DeclarationWithTypeParameters {
switch (node.kind) {
case SyntaxKind.JSDocCallbackTag:
case SyntaxKind.JSDocFunctionTag:
case SyntaxKind.JSDocTypedefTag:
case SyntaxKind.JSDocSignature:
return true;
Expand Down Expand Up @@ -2423,11 +2424,11 @@ namespace ts {
return !!name && name.escapedText === "new";
}

export function isJSDocTypeAlias(node: Node): node is JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag {
return node.kind === SyntaxKind.JSDocTypedefTag || node.kind === SyntaxKind.JSDocCallbackTag || node.kind === SyntaxKind.JSDocEnumTag;
export function isJSDocTypeAlias(node: Node): node is JSDocTypedefTag | JSDocCallbackTag | JSDocFunctionTag | JSDocEnumTag {
return node.kind === SyntaxKind.JSDocTypedefTag || node.kind === SyntaxKind.JSDocCallbackTag || node.kind === SyntaxKind.JSDocFunctionTag || node.kind === SyntaxKind.JSDocEnumTag;
}

export function isTypeAlias(node: Node): node is JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag | TypeAliasDeclaration {
export function isTypeAlias(node: Node): node is JSDocTypedefTag | JSDocCallbackTag | JSDocFunctionTag | JSDocEnumTag | TypeAliasDeclaration {
return isJSDocTypeAlias(node) || isTypeAliasDeclaration(node);
}

Expand Down
1 change: 1 addition & 0 deletions src/compiler/utilitiesPublic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1661,6 +1661,7 @@ namespace ts {
|| kind === SyntaxKind.VariableDeclaration
|| kind === SyntaxKind.JSDocTypedefTag
|| kind === SyntaxKind.JSDocCallbackTag
|| kind === SyntaxKind.JSDocFunctionTag
|| kind === SyntaxKind.JSDocPropertyTag;
}

Expand Down
1 change: 1 addition & 0 deletions src/services/findAllReferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,7 @@ namespace ts.FindAllReferences {
case SyntaxKind.ImportSpecifier:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.JSDocCallbackTag:
case SyntaxKind.JSDocFunctionTag:
case SyntaxKind.JSDocTypedefTag:
case SyntaxKind.JsxAttribute:
case SyntaxKind.ModuleDeclaration:
Expand Down
2 changes: 2 additions & 0 deletions src/services/jsDoc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ namespace ts.JsDoc {
case SyntaxKind.JSDocPropertyTag:
return [declaration as JSDocPropertyTag];
case SyntaxKind.JSDocCallbackTag:
case SyntaxKind.JSDocFunctionTag:
case SyntaxKind.JSDocTypedefTag:
return [(declaration as JSDocTypedefTag), (declaration as JSDocTypedefTag).parent];
default:
Expand Down Expand Up @@ -136,6 +137,7 @@ namespace ts.JsDoc {
return withNode((tag as JSDocTypeTag).typeExpression);
case SyntaxKind.JSDocTypedefTag:
case SyntaxKind.JSDocCallbackTag:
case SyntaxKind.JSDocFunctionTag:
case SyntaxKind.JSDocPropertyTag:
case SyntaxKind.JSDocParameterTag:
const { name } = tag as JSDocTypedefTag | JSDocPropertyTag | JSDocParameterTag;
Expand Down
1 change: 1 addition & 0 deletions src/services/navigationBar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,7 @@ namespace ts.NavigationBar {
case SyntaxKind.TypeAliasDeclaration:
case SyntaxKind.JSDocTypedefTag:
case SyntaxKind.JSDocCallbackTag:
case SyntaxKind.JSDocFunctionTag:
return true;

case SyntaxKind.ArrowFunction:
Expand Down
Loading