Skip to content

expose jsdoc factory #29539

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 13 commits into from
May 6, 2020
125 changes: 108 additions & 17 deletions src/compiler/factoryPublic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2464,64 +2464,155 @@ namespace ts {

// JSDoc

/* @internal */
export function createJSDocTypeExpression(type: TypeNode): JSDocTypeExpression {
const node = createSynthesizedNode(SyntaxKind.JSDocTypeExpression) as JSDocTypeExpression;
node.type = type;
return node;
}

/* @internal */
export function createJSDocTypeTag(typeExpression: JSDocTypeExpression, comment?: string): JSDocTypeTag {
const tag = createJSDocTag<JSDocTypeTag>(SyntaxKind.JSDocTypeTag, "type");
const tag = createJSDocTag<JSDocTypeTag>(SyntaxKind.JSDocTypeTag, "type", comment);
tag.typeExpression = typeExpression;
tag.comment = comment;
return tag;
}

/* @internal */
export function createJSDocReturnTag(typeExpression?: JSDocTypeExpression, comment?: string): JSDocReturnTag {
const tag = createJSDocTag<JSDocReturnTag>(SyntaxKind.JSDocReturnTag, "returns");
const tag = createJSDocTag<JSDocReturnTag>(SyntaxKind.JSDocReturnTag, "returns", comment);
tag.typeExpression = typeExpression;
tag.comment = comment;
return tag;
}

/** @internal */
export function createJSDocThisTag(typeExpression?: JSDocTypeExpression): JSDocThisTag {
const tag = createJSDocTag<JSDocThisTag>(SyntaxKind.JSDocThisTag, "this");
tag.typeExpression = typeExpression;
return tag;
}

/* @internal */
/**
* @deprecated Use `createJSDocParameterTag` to create jsDoc param tag.
*/
export function createJSDocParamTag(name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, comment?: string): JSDocParameterTag {
const tag = createJSDocTag<JSDocParameterTag>(SyntaxKind.JSDocParameterTag, "param");
const tag = createJSDocTag<JSDocParameterTag>(SyntaxKind.JSDocParameterTag, "param", comment);
tag.typeExpression = typeExpression;
tag.name = name;
tag.isBracketed = isBracketed;
tag.comment = comment;
return tag;
}

/* @internal */
export function createJSDocClassTag(): JSDocClassTag {
return createJSDocTag<JSDocClassTag>(SyntaxKind.JSDocClassTag, "class");
export function createJSDocClassTag(comment?: string): JSDocClassTag {
return createJSDocTag<JSDocClassTag>(SyntaxKind.JSDocClassTag, "class", comment);
}


/* @internal */
export function createJSDocComment(comment?: string | undefined, tags?: NodeArray<JSDocTag> | undefined) {
const node = createSynthesizedNode(SyntaxKind.JSDocComment) as JSDoc;
node.comment = comment;
node.tags = tags;
return node;
}

/* @internal */
function createJSDocTag<T extends JSDocTag>(kind: T["kind"], tagName: string): T {
export function createJSDocTag<T extends JSDocTag>(kind: T["kind"], tagName: string, comment?: string): T {
const node = createSynthesizedNode(kind) as T;
node.tagName = createIdentifier(tagName);
node.comment = comment;
return node;
}

export function createJSDocAugmentsTag(classExpression: JSDocAugmentsTag["class"], comment?: string) {
const tag = createJSDocTag<JSDocAugmentsTag>(SyntaxKind.JSDocAugmentsTag, "augments", comment);
tag.class = classExpression;
return tag;
}

export function createJSDocEnumTag(typeExpression?: JSDocTypeExpression, comment?: string) {
const tag = createJSDocTag<JSDocEnumTag>(SyntaxKind.JSDocEnumTag, "enum", comment);
tag.typeExpression = typeExpression;
return tag;
}

export function createJSDocTemplateTag(constraint: JSDocTypeExpression | undefined, typeParameters: readonly TypeParameterDeclaration[], comment?: string) {
const tag = createJSDocTag<JSDocTemplateTag>(SyntaxKind.JSDocTemplateTag, "template", comment);
tag.constraint = constraint;
tag.typeParameters = asNodeArray(typeParameters);
return tag;
}

export function createJSDocTypedefTag(fullName?: JSDocNamespaceDeclaration | Identifier, name?: Identifier, comment?: string, typeExpression?: JSDocTypeExpression | JSDocTypeLiteral) {
const tag = createJSDocTag<JSDocTypedefTag>(SyntaxKind.JSDocTypedefTag, "typedef", comment);
tag.fullName = fullName;
tag.name = name;
tag.typeExpression = typeExpression;
return tag;
}

export function createJSDocCallbackTag(fullName: JSDocNamespaceDeclaration | Identifier | undefined, name: Identifier | undefined, comment: string | undefined, typeExpression: JSDocSignature) {
const tag = createJSDocTag<JSDocCallbackTag>(SyntaxKind.JSDocCallbackTag, "callback", comment);
tag.fullName = fullName;
tag.name = name;
tag.typeExpression = typeExpression;
return tag;
}

export function createJSDocSignature(typeParameters: readonly JSDocTemplateTag[] | undefined, parameters: readonly JSDocParameterTag[], type?: JSDocReturnTag) {
const tag = createSynthesizedNode(SyntaxKind.JSDocSignature) as JSDocSignature;
tag.typeParameters = typeParameters;
tag.parameters = parameters;
tag.type = type;
return tag;
}

function createJSDocPropertyLikeTag<T extends JSDocPropertyLikeTag>(kind: T["kind"], tagName: "arg" | "argument" | "param", typeExpression: JSDocTypeExpression | undefined, name: EntityName, isNameFirst: boolean, isBracketed: boolean, comment?: string) {
const tag = createJSDocTag<T>(kind, tagName, comment);
tag.typeExpression = typeExpression;
tag.name = name;
tag.isNameFirst = isNameFirst;
tag.isBracketed = isBracketed;
return tag;
}

export function createJSDocPropertyTag(typeExpression: JSDocTypeExpression | undefined, name: EntityName, isNameFirst: boolean, isBracketed: boolean, comment?: string) {
return createJSDocPropertyLikeTag<JSDocPropertyTag>(SyntaxKind.JSDocPropertyTag, "param", typeExpression, name, isNameFirst, isBracketed, comment);
}

export function createJSDocParameterTag(typeExpression: JSDocTypeExpression | undefined, name: EntityName, isNameFirst: boolean, isBracketed: boolean, comment?: string) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why have both createJSDocParameterTag and createJSDocParamTag. The only real difference is that this sets isNameFirst but createJSDocParamTag doesn't.

Naively, it feels to me like we should only have one, which uses this code but is named createJSDocParamTag.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, except that we shouldn't break the API unnecessarily. Ugh. Can you add documentation saying that createJSDocParamTag is deprecated and that this is the preferred function now?

return createJSDocPropertyLikeTag<JSDocParameterTag>(SyntaxKind.JSDocParameterTag, "param", typeExpression, name, isNameFirst, isBracketed, comment);
}

export function createJSDocTypeLiteral(jsDocPropertyTags?: readonly JSDocPropertyLikeTag[], isArrayType?: boolean) {
const tag = createSynthesizedNode(SyntaxKind.JSDocTypeLiteral) as JSDocTypeLiteral;
tag.jsDocPropertyTags = jsDocPropertyTags;
tag.isArrayType = isArrayType;
return tag;
}

export function createJSDocImplementsTag(classExpression: JSDocImplementsTag["class"], comment?: string) {
const tag = createJSDocTag<JSDocImplementsTag>(SyntaxKind.JSDocImplementsTag, "implements", comment);
tag.class = classExpression;
return tag;
}

export function createJSDocAuthorTag(comment?: string) {
return createJSDocTag(SyntaxKind.JSDocAuthorTag, "author", comment);
}

export function createJSDocPublicTag() {
return createJSDocTag(SyntaxKind.JSDocPublicTag, "public");
}

export function createJSDocPrivateTag() {
return createJSDocTag(SyntaxKind.JSDocPrivateTag, "private");
}

export function createJSDocProtectedTag() {
return createJSDocTag(SyntaxKind.JSDocProtectedTag, "protected");
}

export function createJSDocReadonlyTag() {
return createJSDocTag(SyntaxKind.JSDocReadonlyTag, "readonly");
}

export function appendJSDocToContainer(node: JSDocContainer, jsdoc: JSDoc) {
node.jsDoc = append(node.jsDoc, jsdoc);
return node;
}

Expand Down
4 changes: 2 additions & 2 deletions src/services/codefixes/inferFromUsage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ namespace ts.codefix {
const typeNode = inference.type && getTypeNodeIfAccessible(inference.type, param, program, host);
const name = getSynthesizedClone(param.name);
setEmitFlags(name, EmitFlags.NoComments | EmitFlags.NoNestedComments);
return typeNode && createJSDocParamTag(name, !!inference.isOptional, createJSDocTypeExpression(typeNode), "");
return typeNode && createJSDocParameterTag(createJSDocTypeExpression(typeNode), name, /* isNameFirst */ false, !!inference.isOptional, "");
});
addJSDocTags(changes, sourceFile, signature, paramTags);
}
Expand Down Expand Up @@ -382,7 +382,7 @@ namespace ts.codefix {
const oldParam = oldTag as JSDocParameterTag;
const newParam = newTag as JSDocParameterTag;
return isIdentifier(oldParam.name) && isIdentifier(newParam.name) && oldParam.name.escapedText === newParam.name.escapedText
? createJSDocParamTag(newParam.name, newParam.isBracketed, newParam.typeExpression, oldParam.comment)
? createJSDocParameterTag(newParam.typeExpression, newParam.name, newParam.isNameFirst, newParam.isBracketed, oldParam.comment)
: undefined;
}
case SyntaxKind.JSDocReturnTag:
Expand Down
27 changes: 27 additions & 0 deletions tests/baselines/reference/api/tsserverlibrary.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4247,6 +4247,33 @@ declare namespace ts {
function updateExportSpecifier(node: ExportSpecifier, propertyName: Identifier | undefined, name: Identifier): ExportSpecifier;
function createExternalModuleReference(expression: Expression): ExternalModuleReference;
function updateExternalModuleReference(node: ExternalModuleReference, expression: Expression): ExternalModuleReference;
function createJSDocTypeExpression(type: TypeNode): JSDocTypeExpression;
function createJSDocTypeTag(typeExpression: JSDocTypeExpression, comment?: string): JSDocTypeTag;
function createJSDocReturnTag(typeExpression?: JSDocTypeExpression, comment?: string): JSDocReturnTag;
function createJSDocThisTag(typeExpression?: JSDocTypeExpression): JSDocThisTag;
/**
* @deprecated Use `createJSDocParameterTag` to create jsDoc param tag.
*/
function createJSDocParamTag(name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, comment?: string): JSDocParameterTag;
function createJSDocClassTag(comment?: string): JSDocClassTag;
function createJSDocComment(comment?: string | undefined, tags?: NodeArray<JSDocTag> | undefined): JSDoc;
function createJSDocTag<T extends JSDocTag>(kind: T["kind"], tagName: string, comment?: string): T;
function createJSDocAugmentsTag(classExpression: JSDocAugmentsTag["class"], comment?: string): JSDocAugmentsTag;
function createJSDocEnumTag(typeExpression?: JSDocTypeExpression, comment?: string): JSDocEnumTag;
function createJSDocTemplateTag(constraint: JSDocTypeExpression | undefined, typeParameters: readonly TypeParameterDeclaration[], comment?: string): JSDocTemplateTag;
function createJSDocTypedefTag(fullName?: JSDocNamespaceDeclaration | Identifier, name?: Identifier, comment?: string, typeExpression?: JSDocTypeExpression | JSDocTypeLiteral): JSDocTypedefTag;
function createJSDocCallbackTag(fullName: JSDocNamespaceDeclaration | Identifier | undefined, name: Identifier | undefined, comment: string | undefined, typeExpression: JSDocSignature): JSDocCallbackTag;
function createJSDocSignature(typeParameters: readonly JSDocTemplateTag[] | undefined, parameters: readonly JSDocParameterTag[], type?: JSDocReturnTag): JSDocSignature;
function createJSDocPropertyTag(typeExpression: JSDocTypeExpression | undefined, name: EntityName, isNameFirst: boolean, isBracketed: boolean, comment?: string): JSDocPropertyTag;
function createJSDocParameterTag(typeExpression: JSDocTypeExpression | undefined, name: EntityName, isNameFirst: boolean, isBracketed: boolean, comment?: string): JSDocParameterTag;
function createJSDocTypeLiteral(jsDocPropertyTags?: readonly JSDocPropertyLikeTag[], isArrayType?: boolean): JSDocTypeLiteral;
function createJSDocImplementsTag(classExpression: JSDocImplementsTag["class"], comment?: string): JSDocImplementsTag;
function createJSDocAuthorTag(comment?: string): JSDocTag;
function createJSDocPublicTag(): JSDocTag;
function createJSDocPrivateTag(): JSDocTag;
function createJSDocProtectedTag(): JSDocTag;
function createJSDocReadonlyTag(): JSDocTag;
function appendJSDocToContainer(node: JSDocContainer, jsdoc: JSDoc): JSDocContainer;
function createJsxElement(openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement): JsxElement;
function updateJsxElement(node: JsxElement, openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement): JsxElement;
function createJsxSelfClosingElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxSelfClosingElement;
Expand Down
27 changes: 27 additions & 0 deletions tests/baselines/reference/api/typescript.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4247,6 +4247,33 @@ declare namespace ts {
function updateExportSpecifier(node: ExportSpecifier, propertyName: Identifier | undefined, name: Identifier): ExportSpecifier;
function createExternalModuleReference(expression: Expression): ExternalModuleReference;
function updateExternalModuleReference(node: ExternalModuleReference, expression: Expression): ExternalModuleReference;
function createJSDocTypeExpression(type: TypeNode): JSDocTypeExpression;
function createJSDocTypeTag(typeExpression: JSDocTypeExpression, comment?: string): JSDocTypeTag;
function createJSDocReturnTag(typeExpression?: JSDocTypeExpression, comment?: string): JSDocReturnTag;
function createJSDocThisTag(typeExpression?: JSDocTypeExpression): JSDocThisTag;
/**
* @deprecated Use `createJSDocParameterTag` to create jsDoc param tag.
*/
function createJSDocParamTag(name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, comment?: string): JSDocParameterTag;
function createJSDocClassTag(comment?: string): JSDocClassTag;
function createJSDocComment(comment?: string | undefined, tags?: NodeArray<JSDocTag> | undefined): JSDoc;
function createJSDocTag<T extends JSDocTag>(kind: T["kind"], tagName: string, comment?: string): T;
function createJSDocAugmentsTag(classExpression: JSDocAugmentsTag["class"], comment?: string): JSDocAugmentsTag;
function createJSDocEnumTag(typeExpression?: JSDocTypeExpression, comment?: string): JSDocEnumTag;
function createJSDocTemplateTag(constraint: JSDocTypeExpression | undefined, typeParameters: readonly TypeParameterDeclaration[], comment?: string): JSDocTemplateTag;
function createJSDocTypedefTag(fullName?: JSDocNamespaceDeclaration | Identifier, name?: Identifier, comment?: string, typeExpression?: JSDocTypeExpression | JSDocTypeLiteral): JSDocTypedefTag;
function createJSDocCallbackTag(fullName: JSDocNamespaceDeclaration | Identifier | undefined, name: Identifier | undefined, comment: string | undefined, typeExpression: JSDocSignature): JSDocCallbackTag;
function createJSDocSignature(typeParameters: readonly JSDocTemplateTag[] | undefined, parameters: readonly JSDocParameterTag[], type?: JSDocReturnTag): JSDocSignature;
function createJSDocPropertyTag(typeExpression: JSDocTypeExpression | undefined, name: EntityName, isNameFirst: boolean, isBracketed: boolean, comment?: string): JSDocPropertyTag;
function createJSDocParameterTag(typeExpression: JSDocTypeExpression | undefined, name: EntityName, isNameFirst: boolean, isBracketed: boolean, comment?: string): JSDocParameterTag;
function createJSDocTypeLiteral(jsDocPropertyTags?: readonly JSDocPropertyLikeTag[], isArrayType?: boolean): JSDocTypeLiteral;
function createJSDocImplementsTag(classExpression: JSDocImplementsTag["class"], comment?: string): JSDocImplementsTag;
function createJSDocAuthorTag(comment?: string): JSDocTag;
function createJSDocPublicTag(): JSDocTag;
function createJSDocPrivateTag(): JSDocTag;
function createJSDocProtectedTag(): JSDocTag;
function createJSDocReadonlyTag(): JSDocTag;
function appendJSDocToContainer(node: JSDocContainer, jsdoc: JSDoc): JSDocContainer;
function createJsxElement(openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement): JsxElement;
function updateJsxElement(node: JsxElement, openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement): JsxElement;
function createJsxSelfClosingElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes): JsxSelfClosingElement;
Expand Down