diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 64fbdbce0e572..250b71b146d35 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -212,6 +212,7 @@ import { JSDocClassTag, JSDocEnumTag, JSDocFunctionType, + JSDocOverloadTag, JSDocParameterTag, JSDocPropertyLikeTag, JSDocSignature, @@ -3027,6 +3028,8 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { case SyntaxKind.JSDocCallbackTag: case SyntaxKind.JSDocEnumTag: return (delayedTypeAliases || (delayedTypeAliases = [])).push(node as JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag); + case SyntaxKind.JSDocOverloadTag: + return bind((node as JSDocOverloadTag).typeExpression); } } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 62a15349dec20..0c0012f33fa98 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -537,6 +537,7 @@ import { isJSDocNullableType, isJSDocOptionalParameter, isJSDocOptionalType, + isJSDocOverloadTag, isJSDocParameterTag, isJSDocPropertyLikeTag, isJSDocPropertyTag, @@ -14276,6 +14277,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { continue; } } + if (isInJSFile(decl) && decl.jsDoc) { + let hasJSDocOverloads = false; + for (const node of decl.jsDoc) { + if (node.tags) { + for (const tag of node.tags) { + if (isJSDocOverloadTag(tag)) { + result.push(getSignatureFromDeclaration(tag.typeExpression)); + hasJSDocOverloads = true; + } + } + } + } + if (hasJSDocOverloads) { + continue; + } + } // If this is a function or method declaration, get the signature from the @type tag for the sake of optional parameters. // Exclude contextually-typed kinds because we already apply the @type tag to the context, plus applying it here to the initializer would supress checks that the two are compatible. result.push( diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 447da12e438f8..ba5eea2b31ffd 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -259,6 +259,7 @@ import { JSDocNonNullableType, JSDocNullableType, JSDocOptionalType, + JSDocOverloadTag, JSDocPropertyLikeTag, JSDocReturnTag, JSDocSeeTag, @@ -2114,6 +2115,8 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri return; case SyntaxKind.JSDocCallbackTag: return emitJSDocCallbackTag(node as JSDocCallbackTag); + case SyntaxKind.JSDocOverloadTag: + return emitJSDocOverloadTag(node as JSDocOverloadTag); // SyntaxKind.JSDocEnumTag (see below) case SyntaxKind.JSDocParameterTag: case SyntaxKind.JSDocPropertyTag: @@ -4373,6 +4376,11 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri emitJSDocSignature(tag.typeExpression); } + function emitJSDocOverloadTag(tag: JSDocOverloadTag) { + emitJSDocComment(tag.comment); + emitJSDocSignature(tag.typeExpression); + } + function emitJSDocSimpleTag(tag: JSDocTag) { emitJSDocTagName(tag.tagName); emitJSDocComment(tag.comment); diff --git a/src/compiler/factory/nodeFactory.ts b/src/compiler/factory/nodeFactory.ts index bfe41875a84c8..f1ade12ad08e5 100644 --- a/src/compiler/factory/nodeFactory.ts +++ b/src/compiler/factory/nodeFactory.ts @@ -240,6 +240,7 @@ import { JSDocNonNullableType, JSDocNullableType, JSDocOptionalType, + JSDocOverloadTag, JSDocOverrideTag, JSDocParameterTag, JSDocPrivateTag, @@ -831,6 +832,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode updateJSDocPropertyTag, createJSDocCallbackTag, updateJSDocCallbackTag, + createJSDocOverloadTag, + updateJSDocOverloadTag, createJSDocAugmentsTag, updateJSDocAugmentsTag, createJSDocImplementsTag, @@ -5161,6 +5164,22 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode : node; } + // @api + function createJSDocOverloadTag(tagName: Identifier | undefined, typeExpression: JSDocSignature, comment?: string | NodeArray): JSDocOverloadTag { + const node = createBaseJSDocTag(SyntaxKind.JSDocOverloadTag, tagName ?? createIdentifier("overload"), comment); + node.typeExpression = typeExpression; + return node; + } + + // @api + function updateJSDocOverloadTag(node: JSDocOverloadTag, tagName: Identifier = getDefaultTagName(node), typeExpression: JSDocSignature, comment: string | NodeArray | undefined): JSDocOverloadTag { + return node.tagName !== tagName + || node.typeExpression !== typeExpression + || node.comment !== comment + ? update(createJSDocOverloadTag(tagName, typeExpression, comment), node) + : node; + } + // @api function createJSDocAugmentsTag(tagName: Identifier | undefined, className: JSDocAugmentsTag["class"], comment?: string | NodeArray): JSDocAugmentsTag { const node = createBaseJSDocTag(SyntaxKind.JSDocAugmentsTag, tagName ?? createIdentifier("augments"), comment); @@ -6870,6 +6889,7 @@ function getDefaultTagNameForKind(kind: JSDocTag["kind"]): string { case SyntaxKind.JSDocParameterTag: return "param"; case SyntaxKind.JSDocPropertyTag: return "prop"; case SyntaxKind.JSDocCallbackTag: return "callback"; + case SyntaxKind.JSDocOverloadTag: return "overload"; case SyntaxKind.JSDocAugmentsTag: return "augments"; case SyntaxKind.JSDocImplementsTag: return "implements"; default: diff --git a/src/compiler/factory/nodeTests.ts b/src/compiler/factory/nodeTests.ts index 89c05748a9ebf..c384f465168ea 100644 --- a/src/compiler/factory/nodeTests.ts +++ b/src/compiler/factory/nodeTests.ts @@ -97,6 +97,7 @@ import { JSDocNonNullableType, JSDocNullableType, JSDocOptionalType, + JSDocOverloadTag, JSDocOverrideTag, JSDocParameterTag, JSDocPrivateTag, @@ -1129,6 +1130,10 @@ export function isJSDocOverrideTag(node: Node): node is JSDocOverrideTag { return node.kind === SyntaxKind.JSDocOverrideTag; } +export function isJSDocOverloadTag(node: Node): node is JSDocOverloadTag { + return node.kind === SyntaxKind.JSDocOverloadTag; +} + export function isJSDocDeprecatedTag(node: Node): node is JSDocDeprecatedTag { return node.kind === SyntaxKind.JSDocDeprecatedTag; } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 49faf20bed233..412036e4a6fc5 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -180,6 +180,7 @@ import { JSDocNonNullableType, JSDocNullableType, JSDocOptionalType, + JSDocOverloadTag, JSDocOverrideTag, JSDocParameterTag, JSDocPrivateTag, @@ -8784,6 +8785,9 @@ namespace Parser { case "callback": tag = parseCallbackTag(start, tagName, margin, indentText); break; + case "overload": + tag = parseOverloadTag(start, tagName, margin, indentText); + break; case "see": tag = parseSeeTag(start, tagName, margin, indentText); break; @@ -9277,10 +9281,7 @@ namespace Parser { return createNodeArray(parameters || [], pos); } - function parseCallbackTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocCallbackTag { - const fullName = parseJSDocTypeNameWithNamespace(); - skipWhitespace(); - let comment = parseTagComments(indent); + function parseJSDocSignature(start: number, indent: number): JSDocSignature { const parameters = parseCallbackTagParameters(indent); const returnTag = tryParse(() => { if (parseOptionalJsdoc(SyntaxKind.AtToken)) { @@ -9290,7 +9291,14 @@ namespace Parser { } } }); - const typeExpression = finishNode(factory.createJSDocSignature(/*typeParameters*/ undefined, parameters, returnTag), start); + return finishNode(factory.createJSDocSignature(/*typeParameters*/ undefined, parameters, returnTag), start); + } + + function parseCallbackTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocCallbackTag { + const fullName = parseJSDocTypeNameWithNamespace(); + skipWhitespace(); + let comment = parseTagComments(indent); + const typeExpression = parseJSDocSignature(start, indent); if (!comment) { comment = parseTrailingTagComments(start, getNodePos(), indent, indentText); } @@ -9298,6 +9306,17 @@ namespace Parser { return finishNode(factory.createJSDocCallbackTag(tagName, typeExpression, fullName, comment), start, end); } + function parseOverloadTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocOverloadTag { + skipWhitespace(); + let comment = parseTagComments(indent); + const typeExpression = parseJSDocSignature(start, indent); + if (!comment) { + comment = parseTrailingTagComments(start, getNodePos(), indent, indentText); + } + const end = comment !== undefined ? getNodePos() : typeExpression.end; + return finishNode(factory.createJSDocOverloadTag(tagName, typeExpression, comment), start, end); + } + function escapedTextsEqual(a: EntityName, b: EntityName): boolean { while (!ts.isIdentifier(a) || !ts.isIdentifier(b)) { if (!ts.isIdentifier(a) && !ts.isIdentifier(b) && a.right.escapedText === b.right.escapedText) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index fcfb940152086..53c1b76973f4a 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -422,6 +422,7 @@ export const enum SyntaxKind { JSDocReadonlyTag, JSDocOverrideTag, JSDocCallbackTag, + JSDocOverloadTag, JSDocEnumTag, JSDocParameterTag, JSDocReturnTag, @@ -3829,6 +3830,13 @@ export interface JSDocCallbackTag extends JSDocTag, NamedDeclaration { readonly typeExpression: JSDocSignature; } + +export interface JSDocOverloadTag extends JSDocTag { + readonly kind: SyntaxKind.JSDocOverloadTag; + readonly parent: JSDoc; + readonly typeExpression: JSDocSignature; +} + export interface JSDocThrowsTag extends JSDocTag { readonly kind: SyntaxKind.JSDocThrowsTag; readonly typeExpression?: JSDocTypeExpression; @@ -8242,6 +8250,8 @@ export interface NodeFactory { updateJSDocEnumTag(node: JSDocEnumTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment: string | NodeArray | undefined): JSDocEnumTag; createJSDocCallbackTag(tagName: Identifier | undefined, typeExpression: JSDocSignature, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string | NodeArray): JSDocCallbackTag; updateJSDocCallbackTag(node: JSDocCallbackTag, tagName: Identifier | undefined, typeExpression: JSDocSignature, fullName: Identifier | JSDocNamespaceDeclaration | undefined, comment: string | NodeArray | undefined): JSDocCallbackTag; + createJSDocOverloadTag(tagName: Identifier | undefined, typeExpression: JSDocSignature, comment?: string | NodeArray): JSDocOverloadTag; + updateJSDocOverloadTag(node: JSDocOverloadTag, tagName: Identifier | undefined, typeExpression: JSDocSignature, comment: string | NodeArray | undefined): JSDocOverloadTag; createJSDocAugmentsTag(tagName: Identifier | undefined, className: JSDocAugmentsTag["class"], comment?: string | NodeArray): JSDocAugmentsTag; updateJSDocAugmentsTag(node: JSDocAugmentsTag, tagName: Identifier | undefined, className: JSDocAugmentsTag["class"], comment: string | NodeArray | undefined): JSDocAugmentsTag; createJSDocImplementsTag(tagName: Identifier | undefined, className: JSDocImplementsTag["class"], comment?: string | NodeArray): JSDocImplementsTag; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 7ce2c8be94389..dc50c1f892477 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -266,6 +266,7 @@ import { isJSDocMemberName, isJSDocNameReference, isJSDocNode, + isJSDocOverloadTag, isJSDocParameterTag, isJSDocPropertyLikeTag, isJSDocSignature, @@ -5645,7 +5646,7 @@ export function getJSDocTypeParameterDeclarations(node: DeclarationWithTypeParam /** template tags are only available when a typedef isn't already using them */ function isNonTypeAliasTemplate(tag: JSDocTag): tag is JSDocTemplateTag { - return isJSDocTemplateTag(tag) && !(tag.parent.kind === SyntaxKind.JSDoc && tag.parent.tags!.some(isJSDocTypeAlias)); + return isJSDocTemplateTag(tag) && !(tag.parent.kind === SyntaxKind.JSDoc && (tag.parent.tags!.some(isJSDocTypeAlias) || tag.parent.tags!.some(isJSDocOverloadTag))); } /** diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index e6c0c5a05602a..99e1ad3065481 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -122,6 +122,7 @@ import { isJSDocEnumTag, isJSDocFunctionType, isJSDocImplementsTag, + isJSDocOverloadTag, isJSDocOverrideTag, isJSDocParameterTag, isJSDocPrivateTag, @@ -1207,6 +1208,14 @@ function formatJSDocLink(link: JSDocLink | JSDocLinkCode | JSDocLinkPlain) { */ export function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters): readonly TypeParameterDeclaration[] { if (isJSDocSignature(node)) { + if (isJSDoc(node.parent)) { + const overloadTag = find(node.parent.tags, (tag) => { + return isJSDocOverloadTag(tag) && tag.typeExpression === node; + }); + if (overloadTag) { + return flatMap(node.parent.tags, tag => isJSDocTemplateTag(tag) ? tag.typeParameters : undefined); + } + } return emptyArray; } if (isJSDocTypeAlias(node)) { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index be4bf4cb7a4d7..ead886266f07d 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4338,24 +4338,25 @@ declare namespace ts { JSDocReadonlyTag = 339, JSDocOverrideTag = 340, JSDocCallbackTag = 341, - JSDocEnumTag = 342, - JSDocParameterTag = 343, - JSDocReturnTag = 344, - JSDocThisTag = 345, - JSDocTypeTag = 346, - JSDocTemplateTag = 347, - JSDocTypedefTag = 348, - JSDocSeeTag = 349, - JSDocPropertyTag = 350, - JSDocThrowsTag = 351, - SyntaxList = 352, - NotEmittedStatement = 353, - PartiallyEmittedExpression = 354, - CommaListExpression = 355, - MergeDeclarationMarker = 356, - EndOfDeclarationMarker = 357, - SyntheticReferenceExpression = 358, - Count = 359, + JSDocOverloadTag = 342, + JSDocEnumTag = 343, + JSDocParameterTag = 344, + JSDocReturnTag = 345, + JSDocThisTag = 346, + JSDocTypeTag = 347, + JSDocTemplateTag = 348, + JSDocTypedefTag = 349, + JSDocSeeTag = 350, + JSDocPropertyTag = 351, + JSDocThrowsTag = 352, + SyntaxList = 353, + NotEmittedStatement = 354, + PartiallyEmittedExpression = 355, + CommaListExpression = 356, + MergeDeclarationMarker = 357, + EndOfDeclarationMarker = 358, + SyntheticReferenceExpression = 359, + Count = 360, FirstAssignment = 63, LastAssignment = 78, FirstCompoundAssignment = 64, @@ -4384,9 +4385,9 @@ declare namespace ts { LastStatement = 256, FirstNode = 163, FirstJSDocNode = 312, - LastJSDocNode = 351, + LastJSDocNode = 352, FirstJSDocTagNode = 330, - LastJSDocTagNode = 351 + LastJSDocTagNode = 352 } type TriviaSyntaxKind = SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia | SyntaxKind.NewLineTrivia | SyntaxKind.WhitespaceTrivia | SyntaxKind.ShebangTrivia | SyntaxKind.ConflictMarkerTrivia; type LiteralSyntaxKind = SyntaxKind.NumericLiteral | SyntaxKind.BigIntLiteral | SyntaxKind.StringLiteral | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.RegularExpressionLiteral | SyntaxKind.NoSubstitutionTemplateLiteral; @@ -5939,6 +5940,11 @@ declare namespace ts { readonly name?: Identifier; readonly typeExpression: JSDocSignature; } + interface JSDocOverloadTag extends JSDocTag { + readonly kind: SyntaxKind.JSDocOverloadTag; + readonly parent: JSDoc; + readonly typeExpression: JSDocSignature; + } interface JSDocThrowsTag extends JSDocTag { readonly kind: SyntaxKind.JSDocThrowsTag; readonly typeExpression?: JSDocTypeExpression; @@ -7782,6 +7788,8 @@ declare namespace ts { updateJSDocEnumTag(node: JSDocEnumTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment: string | NodeArray | undefined): JSDocEnumTag; createJSDocCallbackTag(tagName: Identifier | undefined, typeExpression: JSDocSignature, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string | NodeArray): JSDocCallbackTag; updateJSDocCallbackTag(node: JSDocCallbackTag, tagName: Identifier | undefined, typeExpression: JSDocSignature, fullName: Identifier | JSDocNamespaceDeclaration | undefined, comment: string | NodeArray | undefined): JSDocCallbackTag; + createJSDocOverloadTag(tagName: Identifier | undefined, typeExpression: JSDocSignature, comment?: string | NodeArray): JSDocOverloadTag; + updateJSDocOverloadTag(node: JSDocOverloadTag, tagName: Identifier | undefined, typeExpression: JSDocSignature, comment: string | NodeArray | undefined): JSDocOverloadTag; createJSDocAugmentsTag(tagName: Identifier | undefined, className: JSDocAugmentsTag["class"], comment?: string | NodeArray): JSDocAugmentsTag; updateJSDocAugmentsTag(node: JSDocAugmentsTag, tagName: Identifier | undefined, className: JSDocAugmentsTag["class"], comment: string | NodeArray | undefined): JSDocAugmentsTag; createJSDocImplementsTag(tagName: Identifier | undefined, className: JSDocImplementsTag["class"], comment?: string | NodeArray): JSDocImplementsTag; @@ -9036,6 +9044,7 @@ declare namespace ts { function isJSDocProtectedTag(node: Node): node is JSDocProtectedTag; function isJSDocReadonlyTag(node: Node): node is JSDocReadonlyTag; function isJSDocOverrideTag(node: Node): node is JSDocOverrideTag; + function isJSDocOverloadTag(node: Node): node is JSDocOverloadTag; function isJSDocDeprecatedTag(node: Node): node is JSDocDeprecatedTag; function isJSDocSeeTag(node: Node): node is JSDocSeeTag; function isJSDocEnumTag(node: Node): node is JSDocEnumTag; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 8ddf62571c5a9..935dadd17f544 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -404,24 +404,25 @@ declare namespace ts { JSDocReadonlyTag = 339, JSDocOverrideTag = 340, JSDocCallbackTag = 341, - JSDocEnumTag = 342, - JSDocParameterTag = 343, - JSDocReturnTag = 344, - JSDocThisTag = 345, - JSDocTypeTag = 346, - JSDocTemplateTag = 347, - JSDocTypedefTag = 348, - JSDocSeeTag = 349, - JSDocPropertyTag = 350, - JSDocThrowsTag = 351, - SyntaxList = 352, - NotEmittedStatement = 353, - PartiallyEmittedExpression = 354, - CommaListExpression = 355, - MergeDeclarationMarker = 356, - EndOfDeclarationMarker = 357, - SyntheticReferenceExpression = 358, - Count = 359, + JSDocOverloadTag = 342, + JSDocEnumTag = 343, + JSDocParameterTag = 344, + JSDocReturnTag = 345, + JSDocThisTag = 346, + JSDocTypeTag = 347, + JSDocTemplateTag = 348, + JSDocTypedefTag = 349, + JSDocSeeTag = 350, + JSDocPropertyTag = 351, + JSDocThrowsTag = 352, + SyntaxList = 353, + NotEmittedStatement = 354, + PartiallyEmittedExpression = 355, + CommaListExpression = 356, + MergeDeclarationMarker = 357, + EndOfDeclarationMarker = 358, + SyntheticReferenceExpression = 359, + Count = 360, FirstAssignment = 63, LastAssignment = 78, FirstCompoundAssignment = 64, @@ -450,9 +451,9 @@ declare namespace ts { LastStatement = 256, FirstNode = 163, FirstJSDocNode = 312, - LastJSDocNode = 351, + LastJSDocNode = 352, FirstJSDocTagNode = 330, - LastJSDocTagNode = 351 + LastJSDocTagNode = 352 } type TriviaSyntaxKind = SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia | SyntaxKind.NewLineTrivia | SyntaxKind.WhitespaceTrivia | SyntaxKind.ShebangTrivia | SyntaxKind.ConflictMarkerTrivia; type LiteralSyntaxKind = SyntaxKind.NumericLiteral | SyntaxKind.BigIntLiteral | SyntaxKind.StringLiteral | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.RegularExpressionLiteral | SyntaxKind.NoSubstitutionTemplateLiteral; @@ -2005,6 +2006,11 @@ declare namespace ts { readonly name?: Identifier; readonly typeExpression: JSDocSignature; } + interface JSDocOverloadTag extends JSDocTag { + readonly kind: SyntaxKind.JSDocOverloadTag; + readonly parent: JSDoc; + readonly typeExpression: JSDocSignature; + } interface JSDocThrowsTag extends JSDocTag { readonly kind: SyntaxKind.JSDocThrowsTag; readonly typeExpression?: JSDocTypeExpression; @@ -3848,6 +3854,8 @@ declare namespace ts { updateJSDocEnumTag(node: JSDocEnumTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment: string | NodeArray | undefined): JSDocEnumTag; createJSDocCallbackTag(tagName: Identifier | undefined, typeExpression: JSDocSignature, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string | NodeArray): JSDocCallbackTag; updateJSDocCallbackTag(node: JSDocCallbackTag, tagName: Identifier | undefined, typeExpression: JSDocSignature, fullName: Identifier | JSDocNamespaceDeclaration | undefined, comment: string | NodeArray | undefined): JSDocCallbackTag; + createJSDocOverloadTag(tagName: Identifier | undefined, typeExpression: JSDocSignature, comment?: string | NodeArray): JSDocOverloadTag; + updateJSDocOverloadTag(node: JSDocOverloadTag, tagName: Identifier | undefined, typeExpression: JSDocSignature, comment: string | NodeArray | undefined): JSDocOverloadTag; createJSDocAugmentsTag(tagName: Identifier | undefined, className: JSDocAugmentsTag["class"], comment?: string | NodeArray): JSDocAugmentsTag; updateJSDocAugmentsTag(node: JSDocAugmentsTag, tagName: Identifier | undefined, className: JSDocAugmentsTag["class"], comment: string | NodeArray | undefined): JSDocAugmentsTag; createJSDocImplementsTag(tagName: Identifier | undefined, className: JSDocImplementsTag["class"], comment?: string | NodeArray): JSDocImplementsTag; @@ -5102,6 +5110,7 @@ declare namespace ts { function isJSDocProtectedTag(node: Node): node is JSDocProtectedTag; function isJSDocReadonlyTag(node: Node): node is JSDocReadonlyTag; function isJSDocOverrideTag(node: Node): node is JSDocOverrideTag; + function isJSDocOverloadTag(node: Node): node is JSDocOverloadTag; function isJSDocDeprecatedTag(node: Node): node is JSDocDeprecatedTag; function isJSDocSeeTag(node: Node): node is JSDocSeeTag; function isJSDocEnumTag(node: Node): node is JSDocEnumTag; diff --git a/tests/baselines/reference/findAllReferencesJsOverloadedFunctionParameter.baseline.jsonc b/tests/baselines/reference/findAllReferencesJsOverloadedFunctionParameter.baseline.jsonc new file mode 100644 index 0000000000000..0b985c4cb6c89 --- /dev/null +++ b/tests/baselines/reference/findAllReferencesJsOverloadedFunctionParameter.baseline.jsonc @@ -0,0 +1,95 @@ +// === /tests/cases/fourslash/foo.js === +// /** +// * @overload +// * @param {number} x +// * @returns {number} +// * +// * @overload +// * @param {string} x +// * @returns {string} +// * +// * @param {unknown} [|x|] +// * @returns {unknown} +// */ +// function foo([|x|]/*FIND ALL REFS*/) { +// return [|x|]; +// } + +[ + { + "definition": { + "containerKind": "", + "containerName": "", + "fileName": "/tests/cases/fourslash/foo.js", + "kind": "parameter", + "name": "(parameter) x: unknown", + "textSpan": { + "start": 183, + "length": 1 + }, + "displayParts": [ + { + "text": "(", + "kind": "punctuation" + }, + { + "text": "parameter", + "kind": "text" + }, + { + "text": ")", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "x", + "kind": "parameterName" + }, + { + "text": ":", + "kind": "punctuation" + }, + { + "text": " ", + "kind": "space" + }, + { + "text": "unknown", + "kind": "keyword" + } + ] + }, + "references": [ + { + "textSpan": { + "start": 141, + "length": 1 + }, + "fileName": "/tests/cases/fourslash/foo.js", + "isWriteAccess": false, + "isDefinition": false + }, + { + "textSpan": { + "start": 183, + "length": 1 + }, + "fileName": "/tests/cases/fourslash/foo.js", + "isWriteAccess": true, + "isDefinition": true + }, + { + "textSpan": { + "start": 197, + "length": 1 + }, + "fileName": "/tests/cases/fourslash/foo.js", + "isWriteAccess": false, + "isDefinition": false + } + ] + } +] \ No newline at end of file diff --git a/tests/baselines/reference/jsFileAlternativeUseOfOverloadTag.js b/tests/baselines/reference/jsFileAlternativeUseOfOverloadTag.js new file mode 100644 index 0000000000000..e34b9c77c5379 --- /dev/null +++ b/tests/baselines/reference/jsFileAlternativeUseOfOverloadTag.js @@ -0,0 +1,121 @@ +//// [jsFileAlternativeUseOfOverloadTag.js] +// These are a few examples of existing alternative uses of @overload tag. +// They will not work as expected with our implementation, but we are +// trying to make sure that our changes do not result in any crashes here. + +const example1 = { + /** + * @overload Example1(value) + * Creates Example1 + * @param value [String] + */ + constructor: function Example1(value, options) {}, +}; + +const example2 = { + /** + * Example 2 + * + * @overload Example2(value) + * Creates Example2 + * @param value [String] + * @param secretAccessKey [String] + * @param sessionToken [String] + * @example Creates with string value + * const example = new Example(''); + * @overload Example2(options) + * Creates Example2 + * @option options value [String] + * @example Creates with options object + * const example = new Example2({ + * value: '', + * }); + */ + constructor: function Example2() {}, +}; + +const example3 = { + /** + * @overload evaluate(options = {}, [callback]) + * Evaluate something + * @note Something interesting + * @param options [map] + * @return [string] returns evaluation result + * @return [null] returns nothing if callback provided + * @callback callback function (error, result) + * If callback is provided it will be called with evaluation result + * @param error [Error] + * @param result [String] + * @see callback + */ + evaluate: function evaluate(options, callback) {}, +}; + + +//// [jsFileAlternativeUseOfOverloadTag.js] +// These are a few examples of existing alternative uses of @overload tag. +// They will not work as expected with our implementation, but we are +// trying to make sure that our changes do not result in any crashes here. +var example1 = { + /** + * @overload Example1(value) + * Creates Example1 + * @param value [String] + */ + constructor: function Example1(value, options) { }, +}; +var example2 = { + /** + * Example 2 + * + * @overload Example2(value) + * Creates Example2 + * @param value [String] + * @param secretAccessKey [String] + * @param sessionToken [String] + * @example Creates with string value + * const example = new Example(''); + * @overload Example2(options) + * Creates Example2 + * @option options value [String] + * @example Creates with options object + * const example = new Example2({ + * value: '', + * }); + */ + constructor: function Example2() { }, +}; +var example3 = { + /** + * @overload evaluate(options = {}, [callback]) + * Evaluate something + * @note Something interesting + * @param options [map] + * @return [string] returns evaluation result + * @return [null] returns nothing if callback provided + * @callback callback function (error, result) + * If callback is provided it will be called with evaluation result + * @param error [Error] + * @param result [String] + * @see callback + */ + evaluate: function evaluate(options, callback) { }, +}; + + +//// [jsFileAlternativeUseOfOverloadTag.d.ts] +declare namespace example1 { + function constructor(value: any, options: any): void; +} +declare namespace example2 { + export function constructor_1(): void; + export { constructor_1 as constructor }; +} +declare namespace example3 { + function evaluate(options: any, callback: any): void; +} +/** + * function (error, result) + * If callback is provided it will be called with evaluation result + */ +type callback = (error: any, result: any) => any; diff --git a/tests/baselines/reference/jsFileAlternativeUseOfOverloadTag.symbols b/tests/baselines/reference/jsFileAlternativeUseOfOverloadTag.symbols new file mode 100644 index 0000000000000..3f378d40e61e7 --- /dev/null +++ b/tests/baselines/reference/jsFileAlternativeUseOfOverloadTag.symbols @@ -0,0 +1,72 @@ +=== tests/cases/compiler/jsFileAlternativeUseOfOverloadTag.js === +// These are a few examples of existing alternative uses of @overload tag. +// They will not work as expected with our implementation, but we are +// trying to make sure that our changes do not result in any crashes here. + +const example1 = { +>example1 : Symbol(example1, Decl(jsFileAlternativeUseOfOverloadTag.js, 4, 5)) + + /** + * @overload Example1(value) + * Creates Example1 + * @param value [String] + */ + constructor: function Example1(value, options) {}, +>constructor : Symbol(constructor, Decl(jsFileAlternativeUseOfOverloadTag.js, 4, 18)) +>Example1 : Symbol(Example1, Decl(jsFileAlternativeUseOfOverloadTag.js, 10, 14)) +>value : Symbol(value, Decl(jsFileAlternativeUseOfOverloadTag.js, 10, 33)) +>options : Symbol(options, Decl(jsFileAlternativeUseOfOverloadTag.js, 10, 39)) + +}; + +const example2 = { +>example2 : Symbol(example2, Decl(jsFileAlternativeUseOfOverloadTag.js, 13, 5)) + + /** + * Example 2 + * + * @overload Example2(value) + * Creates Example2 + * @param value [String] + * @param secretAccessKey [String] + * @param sessionToken [String] + * @example Creates with string value + * const example = new Example(''); + * @overload Example2(options) + * Creates Example2 + * @option options value [String] + * @example Creates with options object + * const example = new Example2({ + * value: '', + * }); + */ + constructor: function Example2() {}, +>constructor : Symbol(constructor, Decl(jsFileAlternativeUseOfOverloadTag.js, 13, 18)) +>Example2 : Symbol(Example2, Decl(jsFileAlternativeUseOfOverloadTag.js, 32, 14)) + +}; + +const example3 = { +>example3 : Symbol(example3, Decl(jsFileAlternativeUseOfOverloadTag.js, 35, 5)) + + /** + * @overload evaluate(options = {}, [callback]) + * Evaluate something + * @note Something interesting + * @param options [map] + * @return [string] returns evaluation result + * @return [null] returns nothing if callback provided + * @callback callback function (error, result) + * If callback is provided it will be called with evaluation result + * @param error [Error] + * @param result [String] + * @see callback + */ + evaluate: function evaluate(options, callback) {}, +>evaluate : Symbol(evaluate, Decl(jsFileAlternativeUseOfOverloadTag.js, 35, 18)) +>evaluate : Symbol(evaluate, Decl(jsFileAlternativeUseOfOverloadTag.js, 49, 11)) +>options : Symbol(options, Decl(jsFileAlternativeUseOfOverloadTag.js, 49, 30)) +>callback : Symbol(callback, Decl(jsFileAlternativeUseOfOverloadTag.js, 49, 38)) + +}; + diff --git a/tests/baselines/reference/jsFileAlternativeUseOfOverloadTag.types b/tests/baselines/reference/jsFileAlternativeUseOfOverloadTag.types new file mode 100644 index 0000000000000..aa606c5ade669 --- /dev/null +++ b/tests/baselines/reference/jsFileAlternativeUseOfOverloadTag.types @@ -0,0 +1,78 @@ +=== tests/cases/compiler/jsFileAlternativeUseOfOverloadTag.js === +// These are a few examples of existing alternative uses of @overload tag. +// They will not work as expected with our implementation, but we are +// trying to make sure that our changes do not result in any crashes here. + +const example1 = { +>example1 : { constructor: (value: any, options: any) => void; } +>{ /** * @overload Example1(value) * Creates Example1 * @param value [String] */ constructor: function Example1(value, options) {},} : { constructor: (value: any, options: any) => void; } + + /** + * @overload Example1(value) + * Creates Example1 + * @param value [String] + */ + constructor: function Example1(value, options) {}, +>constructor : (value: any, options: any) => void +>function Example1(value, options) {} : (value: any, options: any) => void +>Example1 : (value: any, options: any) => void +>value : any +>options : any + +}; + +const example2 = { +>example2 : { constructor: () => void; } +>{ /** * Example 2 * * @overload Example2(value) * Creates Example2 * @param value [String] * @param secretAccessKey [String] * @param sessionToken [String] * @example Creates with string value * const example = new Example(''); * @overload Example2(options) * Creates Example2 * @option options value [String] * @example Creates with options object * const example = new Example2({ * value: '', * }); */ constructor: function Example2() {},} : { constructor: () => void; } + + /** + * Example 2 + * + * @overload Example2(value) + * Creates Example2 + * @param value [String] + * @param secretAccessKey [String] + * @param sessionToken [String] + * @example Creates with string value + * const example = new Example(''); + * @overload Example2(options) + * Creates Example2 + * @option options value [String] + * @example Creates with options object + * const example = new Example2({ + * value: '', + * }); + */ + constructor: function Example2() {}, +>constructor : () => void +>function Example2() {} : () => void +>Example2 : () => void + +}; + +const example3 = { +>example3 : { evaluate: (options: any, callback: any) => void; } +>{ /** * @overload evaluate(options = {}, [callback]) * Evaluate something * @note Something interesting * @param options [map] * @return [string] returns evaluation result * @return [null] returns nothing if callback provided * @callback callback function (error, result) * If callback is provided it will be called with evaluation result * @param error [Error] * @param result [String] * @see callback */ evaluate: function evaluate(options, callback) {},} : { evaluate: (options: any, callback: any) => void; } + + /** + * @overload evaluate(options = {}, [callback]) + * Evaluate something + * @note Something interesting + * @param options [map] + * @return [string] returns evaluation result + * @return [null] returns nothing if callback provided + * @callback callback function (error, result) + * If callback is provided it will be called with evaluation result + * @param error [Error] + * @param result [String] + * @see callback + */ + evaluate: function evaluate(options, callback) {}, +>evaluate : (options: any, callback: any) => void +>function evaluate(options, callback) {} : (options: any, callback: any) => void +>evaluate : (options: any, callback: any) => void +>options : any +>callback : any + +}; + diff --git a/tests/baselines/reference/jsFileFunctionOverloads.js b/tests/baselines/reference/jsFileFunctionOverloads.js new file mode 100644 index 0000000000000..a49b87851b0d9 --- /dev/null +++ b/tests/baselines/reference/jsFileFunctionOverloads.js @@ -0,0 +1,131 @@ +//// [jsFileFunctionOverloads.js] +/** + * @overload + * @param {number} x + * @returns {'number'} + */ +/** + * @overload + * @param {string} x + * @returns {'string'} + */ +/** + * @overload + * @param {boolean} x + * @returns {'boolean'} + */ +/** + * @param {unknown} x + * @returns {string} + */ + function getTypeName(x) { + return typeof x; +} + +/** + * @template T + * @param {T} x + * @returns {T} + */ +const identity = x => x; + +/** + * @template T + * @template U + * @overload + * @param {T[]} array + * @param {(x: T) => U[]} iterable + * @returns {U[]} + */ +/** + * @template T + * @overload + * @param {T[][]} array + * @returns {T[]} + */ +/** + * @param {unknown[]} array + * @param {(x: unknown) => unknown} iterable + * @returns {unknown[]} + */ +function flatMap(array, iterable = identity) { + /** @type {unknown[]} */ + const result = []; + for (let i = 0; i < array.length; i += 1) { + result.push(.../** @type {unknown[]} */(iterable(array[i]))); + } + return result; +} + + +//// [jsFileFunctionOverloads.js] +/** + * @overload + * @param {number} x + * @returns {'number'} + */ +/** + * @overload + * @param {string} x + * @returns {'string'} + */ +/** + * @overload + * @param {boolean} x + * @returns {'boolean'} + */ +/** + * @param {unknown} x + * @returns {string} + */ +function getTypeName(x) { + return typeof x; +} +/** + * @template T + * @param {T} x + * @returns {T} + */ +var identity = function (x) { return x; }; +/** + * @template T + * @template U + * @overload + * @param {T[]} array + * @param {(x: T) => U[]} iterable + * @returns {U[]} + */ +/** + * @template T + * @overload + * @param {T[][]} array + * @returns {T[]} + */ +/** + * @param {unknown[]} array + * @param {(x: unknown) => unknown} iterable + * @returns {unknown[]} + */ +function flatMap(array, iterable) { + if (iterable === void 0) { iterable = identity; } + /** @type {unknown[]} */ + var result = []; + for (var i = 0; i < array.length; i += 1) { + result.push.apply(result, /** @type {unknown[]} */ (iterable(array[i]))); + } + return result; +} + + +//// [jsFileFunctionOverloads.d.ts] +declare function getTypeName(x: number): 'number'; +declare function getTypeName(x: string): 'string'; +declare function getTypeName(x: boolean): 'boolean'; +declare function flatMap(array: T[], iterable: (x: T) => U[]): U[]; +declare function flatMap(array: T[][]): T[]; +/** + * @template T + * @param {T} x + * @returns {T} + */ +declare function identity(x: T): T; diff --git a/tests/baselines/reference/jsFileFunctionOverloads.symbols b/tests/baselines/reference/jsFileFunctionOverloads.symbols new file mode 100644 index 0000000000000..2ed307bca6dc1 --- /dev/null +++ b/tests/baselines/reference/jsFileFunctionOverloads.symbols @@ -0,0 +1,87 @@ +=== tests/cases/compiler/jsFileFunctionOverloads.js === +/** + * @overload + * @param {number} x + * @returns {'number'} + */ +/** + * @overload + * @param {string} x + * @returns {'string'} + */ +/** + * @overload + * @param {boolean} x + * @returns {'boolean'} + */ +/** + * @param {unknown} x + * @returns {string} + */ + function getTypeName(x) { +>getTypeName : Symbol(getTypeName, Decl(jsFileFunctionOverloads.js, 0, 0)) +>x : Symbol(x, Decl(jsFileFunctionOverloads.js, 19, 22)) + + return typeof x; +>x : Symbol(x, Decl(jsFileFunctionOverloads.js, 19, 22)) +} + +/** + * @template T + * @param {T} x + * @returns {T} + */ +const identity = x => x; +>identity : Symbol(identity, Decl(jsFileFunctionOverloads.js, 28, 5)) +>x : Symbol(x, Decl(jsFileFunctionOverloads.js, 28, 16)) +>x : Symbol(x, Decl(jsFileFunctionOverloads.js, 28, 16)) + +/** + * @template T + * @template U + * @overload + * @param {T[]} array + * @param {(x: T) => U[]} iterable + * @returns {U[]} + */ +/** + * @template T + * @overload + * @param {T[][]} array + * @returns {T[]} + */ +/** + * @param {unknown[]} array + * @param {(x: unknown) => unknown} iterable + * @returns {unknown[]} + */ +function flatMap(array, iterable = identity) { +>flatMap : Symbol(flatMap, Decl(jsFileFunctionOverloads.js, 28, 24)) +>array : Symbol(array, Decl(jsFileFunctionOverloads.js, 49, 17)) +>iterable : Symbol(iterable, Decl(jsFileFunctionOverloads.js, 49, 23)) +>identity : Symbol(identity, Decl(jsFileFunctionOverloads.js, 28, 5)) + + /** @type {unknown[]} */ + const result = []; +>result : Symbol(result, Decl(jsFileFunctionOverloads.js, 51, 7)) + + for (let i = 0; i < array.length; i += 1) { +>i : Symbol(i, Decl(jsFileFunctionOverloads.js, 52, 10)) +>i : Symbol(i, Decl(jsFileFunctionOverloads.js, 52, 10)) +>array.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>array : Symbol(array, Decl(jsFileFunctionOverloads.js, 49, 17)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>i : Symbol(i, Decl(jsFileFunctionOverloads.js, 52, 10)) + + result.push(.../** @type {unknown[]} */(iterable(array[i]))); +>result.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>result : Symbol(result, Decl(jsFileFunctionOverloads.js, 51, 7)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>iterable : Symbol(iterable, Decl(jsFileFunctionOverloads.js, 49, 23)) +>array : Symbol(array, Decl(jsFileFunctionOverloads.js, 49, 17)) +>i : Symbol(i, Decl(jsFileFunctionOverloads.js, 52, 10)) + } + return result; +>result : Symbol(result, Decl(jsFileFunctionOverloads.js, 51, 7)) +} + diff --git a/tests/baselines/reference/jsFileFunctionOverloads.types b/tests/baselines/reference/jsFileFunctionOverloads.types new file mode 100644 index 0000000000000..a22495f41b18d --- /dev/null +++ b/tests/baselines/reference/jsFileFunctionOverloads.types @@ -0,0 +1,99 @@ +=== tests/cases/compiler/jsFileFunctionOverloads.js === +/** + * @overload + * @param {number} x + * @returns {'number'} + */ +/** + * @overload + * @param {string} x + * @returns {'string'} + */ +/** + * @overload + * @param {boolean} x + * @returns {'boolean'} + */ +/** + * @param {unknown} x + * @returns {string} + */ + function getTypeName(x) { +>getTypeName : { (x: number): 'number'; (x: string): 'string'; (x: boolean): 'boolean'; } +>x : unknown + + return typeof x; +>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>x : unknown +} + +/** + * @template T + * @param {T} x + * @returns {T} + */ +const identity = x => x; +>identity : (x: T) => T +>x => x : (x: T) => T +>x : T +>x : T + +/** + * @template T + * @template U + * @overload + * @param {T[]} array + * @param {(x: T) => U[]} iterable + * @returns {U[]} + */ +/** + * @template T + * @overload + * @param {T[][]} array + * @returns {T[]} + */ +/** + * @param {unknown[]} array + * @param {(x: unknown) => unknown} iterable + * @returns {unknown[]} + */ +function flatMap(array, iterable = identity) { +>flatMap : { (array: T[], iterable: (x: T) => U[]): U[]; (array: T[][]): T[]; } +>array : unknown[] +>iterable : (x: unknown) => unknown +>identity : (x: T) => T + + /** @type {unknown[]} */ + const result = []; +>result : unknown[] +>[] : undefined[] + + for (let i = 0; i < array.length; i += 1) { +>i : number +>0 : 0 +>i < array.length : boolean +>i : number +>array.length : number +>array : unknown[] +>length : number +>i += 1 : number +>i : number +>1 : 1 + + result.push(.../** @type {unknown[]} */(iterable(array[i]))); +>result.push(.../** @type {unknown[]} */(iterable(array[i]))) : number +>result.push : (...items: unknown[]) => number +>result : unknown[] +>push : (...items: unknown[]) => number +>.../** @type {unknown[]} */(iterable(array[i])) : unknown +>(iterable(array[i])) : unknown[] +>iterable(array[i]) : unknown +>iterable : (x: unknown) => unknown +>array[i] : unknown +>array : unknown[] +>i : number + } + return result; +>result : unknown[] +} + diff --git a/tests/baselines/reference/jsFileFunctionOverloads2.js b/tests/baselines/reference/jsFileFunctionOverloads2.js new file mode 100644 index 0000000000000..55f9289a277be --- /dev/null +++ b/tests/baselines/reference/jsFileFunctionOverloads2.js @@ -0,0 +1,121 @@ +//// [jsFileFunctionOverloads2.js] +// Also works if all @overload tags are combined in one comment. +/** + * @overload + * @param {number} x + * @returns {'number'} + * + * @overload + * @param {string} x + * @returns {'string'} + * + * @overload + * @param {boolean} x + * @returns {'boolean'} + * + * @param {unknown} x + * @returns {string} + */ + function getTypeName(x) { + return typeof x; +} + +/** + * @template T + * @param {T} x + * @returns {T} + */ +const identity = x => x; + +/** + * @template T + * @template U + * @overload + * @param {T[]} array + * @param {(x: T) => U[]} iterable + * @returns {U[]} + * + * @overload + * @param {T[][]} array + * @returns {T[]} + * + * @param {unknown[]} array + * @param {(x: unknown) => unknown} iterable + * @returns {unknown[]} + */ +function flatMap(array, iterable = identity) { + /** @type {unknown[]} */ + const result = []; + for (let i = 0; i < array.length; i += 1) { + result.push(.../** @type {unknown[]} */(iterable(array[i]))); + } + return result; +} + + +//// [jsFileFunctionOverloads2.js] +// Also works if all @overload tags are combined in one comment. +/** + * @overload + * @param {number} x + * @returns {'number'} + * + * @overload + * @param {string} x + * @returns {'string'} + * + * @overload + * @param {boolean} x + * @returns {'boolean'} + * + * @param {unknown} x + * @returns {string} + */ +function getTypeName(x) { + return typeof x; +} +/** + * @template T + * @param {T} x + * @returns {T} + */ +var identity = function (x) { return x; }; +/** + * @template T + * @template U + * @overload + * @param {T[]} array + * @param {(x: T) => U[]} iterable + * @returns {U[]} + * + * @overload + * @param {T[][]} array + * @returns {T[]} + * + * @param {unknown[]} array + * @param {(x: unknown) => unknown} iterable + * @returns {unknown[]} + */ +function flatMap(array, iterable) { + if (iterable === void 0) { iterable = identity; } + /** @type {unknown[]} */ + var result = []; + for (var i = 0; i < array.length; i += 1) { + result.push.apply(result, /** @type {unknown[]} */ (iterable(array[i]))); + } + return result; +} + + +//// [jsFileFunctionOverloads2.d.ts] +declare function getTypeName(x: number): 'number'; +declare function getTypeName(x: string): 'string'; +declare function getTypeName(x: boolean): 'boolean'; +declare function flatMap(array: T[], iterable: (x: T) => U[]): U[]; +declare function flatMap(array: T[][]): T[]; +/** + * @template T + * @param {T} x + * @returns {T} + */ +declare function identity(x: T): T; diff --git a/tests/baselines/reference/jsFileFunctionOverloads2.symbols b/tests/baselines/reference/jsFileFunctionOverloads2.symbols new file mode 100644 index 0000000000000..37dd3797504ae --- /dev/null +++ b/tests/baselines/reference/jsFileFunctionOverloads2.symbols @@ -0,0 +1,82 @@ +=== tests/cases/compiler/jsFileFunctionOverloads2.js === +// Also works if all @overload tags are combined in one comment. +/** + * @overload + * @param {number} x + * @returns {'number'} + * + * @overload + * @param {string} x + * @returns {'string'} + * + * @overload + * @param {boolean} x + * @returns {'boolean'} + * + * @param {unknown} x + * @returns {string} + */ + function getTypeName(x) { +>getTypeName : Symbol(getTypeName, Decl(jsFileFunctionOverloads2.js, 0, 0)) +>x : Symbol(x, Decl(jsFileFunctionOverloads2.js, 17, 22)) + + return typeof x; +>x : Symbol(x, Decl(jsFileFunctionOverloads2.js, 17, 22)) +} + +/** + * @template T + * @param {T} x + * @returns {T} + */ +const identity = x => x; +>identity : Symbol(identity, Decl(jsFileFunctionOverloads2.js, 26, 5)) +>x : Symbol(x, Decl(jsFileFunctionOverloads2.js, 26, 16)) +>x : Symbol(x, Decl(jsFileFunctionOverloads2.js, 26, 16)) + +/** + * @template T + * @template U + * @overload + * @param {T[]} array + * @param {(x: T) => U[]} iterable + * @returns {U[]} + * + * @overload + * @param {T[][]} array + * @returns {T[]} + * + * @param {unknown[]} array + * @param {(x: unknown) => unknown} iterable + * @returns {unknown[]} + */ +function flatMap(array, iterable = identity) { +>flatMap : Symbol(flatMap, Decl(jsFileFunctionOverloads2.js, 26, 24)) +>array : Symbol(array, Decl(jsFileFunctionOverloads2.js, 44, 17)) +>iterable : Symbol(iterable, Decl(jsFileFunctionOverloads2.js, 44, 23)) +>identity : Symbol(identity, Decl(jsFileFunctionOverloads2.js, 26, 5)) + + /** @type {unknown[]} */ + const result = []; +>result : Symbol(result, Decl(jsFileFunctionOverloads2.js, 46, 7)) + + for (let i = 0; i < array.length; i += 1) { +>i : Symbol(i, Decl(jsFileFunctionOverloads2.js, 47, 10)) +>i : Symbol(i, Decl(jsFileFunctionOverloads2.js, 47, 10)) +>array.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>array : Symbol(array, Decl(jsFileFunctionOverloads2.js, 44, 17)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>i : Symbol(i, Decl(jsFileFunctionOverloads2.js, 47, 10)) + + result.push(.../** @type {unknown[]} */(iterable(array[i]))); +>result.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>result : Symbol(result, Decl(jsFileFunctionOverloads2.js, 46, 7)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>iterable : Symbol(iterable, Decl(jsFileFunctionOverloads2.js, 44, 23)) +>array : Symbol(array, Decl(jsFileFunctionOverloads2.js, 44, 17)) +>i : Symbol(i, Decl(jsFileFunctionOverloads2.js, 47, 10)) + } + return result; +>result : Symbol(result, Decl(jsFileFunctionOverloads2.js, 46, 7)) +} + diff --git a/tests/baselines/reference/jsFileFunctionOverloads2.types b/tests/baselines/reference/jsFileFunctionOverloads2.types new file mode 100644 index 0000000000000..d3ded3c9d64d3 --- /dev/null +++ b/tests/baselines/reference/jsFileFunctionOverloads2.types @@ -0,0 +1,94 @@ +=== tests/cases/compiler/jsFileFunctionOverloads2.js === +// Also works if all @overload tags are combined in one comment. +/** + * @overload + * @param {number} x + * @returns {'number'} + * + * @overload + * @param {string} x + * @returns {'string'} + * + * @overload + * @param {boolean} x + * @returns {'boolean'} + * + * @param {unknown} x + * @returns {string} + */ + function getTypeName(x) { +>getTypeName : { (x: number): 'number'; (x: string): 'string'; (x: boolean): 'boolean'; } +>x : unknown + + return typeof x; +>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>x : unknown +} + +/** + * @template T + * @param {T} x + * @returns {T} + */ +const identity = x => x; +>identity : (x: T) => T +>x => x : (x: T) => T +>x : T +>x : T + +/** + * @template T + * @template U + * @overload + * @param {T[]} array + * @param {(x: T) => U[]} iterable + * @returns {U[]} + * + * @overload + * @param {T[][]} array + * @returns {T[]} + * + * @param {unknown[]} array + * @param {(x: unknown) => unknown} iterable + * @returns {unknown[]} + */ +function flatMap(array, iterable = identity) { +>flatMap : { (array: T[], iterable: (x: T) => U[]): U[]; (array: T[][]): T[]; } +>array : unknown[] +>iterable : (x: unknown) => unknown +>identity : (x: T) => T + + /** @type {unknown[]} */ + const result = []; +>result : unknown[] +>[] : undefined[] + + for (let i = 0; i < array.length; i += 1) { +>i : number +>0 : 0 +>i < array.length : boolean +>i : number +>array.length : number +>array : unknown[] +>length : number +>i += 1 : number +>i : number +>1 : 1 + + result.push(.../** @type {unknown[]} */(iterable(array[i]))); +>result.push(.../** @type {unknown[]} */(iterable(array[i]))) : number +>result.push : (...items: unknown[]) => number +>result : unknown[] +>push : (...items: unknown[]) => number +>.../** @type {unknown[]} */(iterable(array[i])) : unknown +>(iterable(array[i])) : unknown[] +>iterable(array[i]) : unknown +>iterable : (x: unknown) => unknown +>array[i] : unknown +>array : unknown[] +>i : number + } + return result; +>result : unknown[] +} + diff --git a/tests/baselines/reference/jsFileMethodOverloads.js b/tests/baselines/reference/jsFileMethodOverloads.js new file mode 100644 index 0000000000000..c911e0bd8ca88 --- /dev/null +++ b/tests/baselines/reference/jsFileMethodOverloads.js @@ -0,0 +1,112 @@ +//// [jsFileMethodOverloads.js] +/** + * @template T + */ + class Example { + /** + * @param {T} value + */ + constructor(value) { + this.value = value; + } + + /** + * @overload + * @param {Example} this + * @returns {'number'} + */ + /** + * @overload + * @param {Example} this + * @returns {'string'} + */ + /** + * @returns {string} + */ + getTypeName() { + return typeof this.value; + } + + /** + * @template U + * @overload + * @param {(y: T) => U} fn + * @returns {U} + */ + /** + * @overload + * @returns {T} + */ + /** + * @param {(y: T) => unknown} [fn] + * @returns {unknown} + */ + transform(fn) { + return fn ? fn(this.value) : this.value; + } +} + + +//// [jsFileMethodOverloads.js] +/** + * @template T + */ +var Example = /** @class */ (function () { + /** + * @param {T} value + */ + function Example(value) { + this.value = value; + } + /** + * @overload + * @param {Example} this + * @returns {'number'} + */ + /** + * @overload + * @param {Example} this + * @returns {'string'} + */ + /** + * @returns {string} + */ + Example.prototype.getTypeName = function () { + return typeof this.value; + }; + /** + * @template U + * @overload + * @param {(y: T) => U} fn + * @returns {U} + */ + /** + * @overload + * @returns {T} + */ + /** + * @param {(y: T) => unknown} [fn] + * @returns {unknown} + */ + Example.prototype.transform = function (fn) { + return fn ? fn(this.value) : this.value; + }; + return Example; +}()); + + +//// [jsFileMethodOverloads.d.ts] +/** + * @template T + */ +declare class Example { + /** + * @param {T} value + */ + constructor(value: T); + value: T; + getTypeName(this: Example): 'number'; + getTypeName(this: Example): 'string'; + transform(fn: (y: T) => U): U; + transform(): T; +} diff --git a/tests/baselines/reference/jsFileMethodOverloads.symbols b/tests/baselines/reference/jsFileMethodOverloads.symbols new file mode 100644 index 0000000000000..4bbd06ccf9b2e --- /dev/null +++ b/tests/baselines/reference/jsFileMethodOverloads.symbols @@ -0,0 +1,72 @@ +=== tests/cases/compiler/jsFileMethodOverloads.js === +/** + * @template T + */ + class Example { +>Example : Symbol(Example, Decl(jsFileMethodOverloads.js, 0, 0)) + + /** + * @param {T} value + */ + constructor(value) { +>value : Symbol(value, Decl(jsFileMethodOverloads.js, 7, 14)) + + this.value = value; +>this.value : Symbol(Example.value, Decl(jsFileMethodOverloads.js, 7, 22)) +>this : Symbol(Example, Decl(jsFileMethodOverloads.js, 0, 0)) +>value : Symbol(Example.value, Decl(jsFileMethodOverloads.js, 7, 22)) +>value : Symbol(value, Decl(jsFileMethodOverloads.js, 7, 14)) + } + + /** + * @overload + * @param {Example} this + * @returns {'number'} + */ + /** + * @overload + * @param {Example} this + * @returns {'string'} + */ + /** + * @returns {string} + */ + getTypeName() { +>getTypeName : Symbol(Example.getTypeName, Decl(jsFileMethodOverloads.js, 9, 3)) + + return typeof this.value; +>this.value : Symbol(Example.value, Decl(jsFileMethodOverloads.js, 7, 22)) +>this : Symbol(Example, Decl(jsFileMethodOverloads.js, 0, 0)) +>value : Symbol(Example.value, Decl(jsFileMethodOverloads.js, 7, 22)) + } + + /** + * @template U + * @overload + * @param {(y: T) => U} fn + * @returns {U} + */ + /** + * @overload + * @returns {T} + */ + /** + * @param {(y: T) => unknown} [fn] + * @returns {unknown} + */ + transform(fn) { +>transform : Symbol(Example.transform, Decl(jsFileMethodOverloads.js, 26, 3)) +>fn : Symbol(fn, Decl(jsFileMethodOverloads.js, 42, 12)) + + return fn ? fn(this.value) : this.value; +>fn : Symbol(fn, Decl(jsFileMethodOverloads.js, 42, 12)) +>fn : Symbol(fn, Decl(jsFileMethodOverloads.js, 42, 12)) +>this.value : Symbol(Example.value, Decl(jsFileMethodOverloads.js, 7, 22)) +>this : Symbol(Example, Decl(jsFileMethodOverloads.js, 0, 0)) +>value : Symbol(Example.value, Decl(jsFileMethodOverloads.js, 7, 22)) +>this.value : Symbol(Example.value, Decl(jsFileMethodOverloads.js, 7, 22)) +>this : Symbol(Example, Decl(jsFileMethodOverloads.js, 0, 0)) +>value : Symbol(Example.value, Decl(jsFileMethodOverloads.js, 7, 22)) + } +} + diff --git a/tests/baselines/reference/jsFileMethodOverloads.types b/tests/baselines/reference/jsFileMethodOverloads.types new file mode 100644 index 0000000000000..7cce51446af70 --- /dev/null +++ b/tests/baselines/reference/jsFileMethodOverloads.types @@ -0,0 +1,76 @@ +=== tests/cases/compiler/jsFileMethodOverloads.js === +/** + * @template T + */ + class Example { +>Example : Example + + /** + * @param {T} value + */ + constructor(value) { +>value : T + + this.value = value; +>this.value = value : T +>this.value : any +>this : this +>value : any +>value : T + } + + /** + * @overload + * @param {Example} this + * @returns {'number'} + */ + /** + * @overload + * @param {Example} this + * @returns {'string'} + */ + /** + * @returns {string} + */ + getTypeName() { +>getTypeName : { (this: Example): 'number'; (this: Example): 'string'; } + + return typeof this.value; +>typeof this.value : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>this.value : T +>this : this +>value : T + } + + /** + * @template U + * @overload + * @param {(y: T) => U} fn + * @returns {U} + */ + /** + * @overload + * @returns {T} + */ + /** + * @param {(y: T) => unknown} [fn] + * @returns {unknown} + */ + transform(fn) { +>transform : { (fn: (y: T) => U): U; (): T; } +>fn : (y: T) => unknown + + return fn ? fn(this.value) : this.value; +>fn ? fn(this.value) : this.value : unknown +>fn : (y: T) => unknown +>fn(this.value) : unknown +>fn : (y: T) => unknown +>this.value : T +>this : this +>value : T +>this.value : T +>this : this +>value : T + } +} + diff --git a/tests/baselines/reference/jsFileMethodOverloads2.js b/tests/baselines/reference/jsFileMethodOverloads2.js new file mode 100644 index 0000000000000..f1d960b2d0d91 --- /dev/null +++ b/tests/baselines/reference/jsFileMethodOverloads2.js @@ -0,0 +1,106 @@ +//// [jsFileMethodOverloads2.js] +// Also works if all @overload tags are combined in one comment. +/** + * @template T + */ + class Example { + /** + * @param {T} value + */ + constructor(value) { + this.value = value; + } + + /** + * @overload + * @param {Example} this + * @returns {'number'} + * + * @overload + * @param {Example} this + * @returns {'string'} + * + * @returns {string} + */ + getTypeName() { + return typeof this.value; + } + + /** + * @template U + * @overload + * @param {(y: T) => U} fn + * @returns {U} + * + * @overload + * @returns {T} + * + * @param {(y: T) => unknown} [fn] + * @returns {unknown} + */ + transform(fn) { + return fn ? fn(this.value) : this.value; + } +} + + +//// [jsFileMethodOverloads2.js] +// Also works if all @overload tags are combined in one comment. +/** + * @template T + */ +var Example = /** @class */ (function () { + /** + * @param {T} value + */ + function Example(value) { + this.value = value; + } + /** + * @overload + * @param {Example} this + * @returns {'number'} + * + * @overload + * @param {Example} this + * @returns {'string'} + * + * @returns {string} + */ + Example.prototype.getTypeName = function () { + return typeof this.value; + }; + /** + * @template U + * @overload + * @param {(y: T) => U} fn + * @returns {U} + * + * @overload + * @returns {T} + * + * @param {(y: T) => unknown} [fn] + * @returns {unknown} + */ + Example.prototype.transform = function (fn) { + return fn ? fn(this.value) : this.value; + }; + return Example; +}()); + + +//// [jsFileMethodOverloads2.d.ts] +/** + * @template T + */ +declare class Example { + /** + * @param {T} value + */ + constructor(value: T); + value: T; + getTypeName(this: Example): 'number'; + getTypeName(this: Example): 'string'; + transform(fn: (y: T) => U): U; + transform(): T; +} diff --git a/tests/baselines/reference/jsFileMethodOverloads2.symbols b/tests/baselines/reference/jsFileMethodOverloads2.symbols new file mode 100644 index 0000000000000..68dbaa4ef07f8 --- /dev/null +++ b/tests/baselines/reference/jsFileMethodOverloads2.symbols @@ -0,0 +1,69 @@ +=== tests/cases/compiler/jsFileMethodOverloads2.js === +// Also works if all @overload tags are combined in one comment. +/** + * @template T + */ + class Example { +>Example : Symbol(Example, Decl(jsFileMethodOverloads2.js, 0, 0)) + + /** + * @param {T} value + */ + constructor(value) { +>value : Symbol(value, Decl(jsFileMethodOverloads2.js, 8, 14)) + + this.value = value; +>this.value : Symbol(Example.value, Decl(jsFileMethodOverloads2.js, 8, 22)) +>this : Symbol(Example, Decl(jsFileMethodOverloads2.js, 0, 0)) +>value : Symbol(Example.value, Decl(jsFileMethodOverloads2.js, 8, 22)) +>value : Symbol(value, Decl(jsFileMethodOverloads2.js, 8, 14)) + } + + /** + * @overload + * @param {Example} this + * @returns {'number'} + * + * @overload + * @param {Example} this + * @returns {'string'} + * + * @returns {string} + */ + getTypeName() { +>getTypeName : Symbol(Example.getTypeName, Decl(jsFileMethodOverloads2.js, 10, 3)) + + return typeof this.value; +>this.value : Symbol(Example.value, Decl(jsFileMethodOverloads2.js, 8, 22)) +>this : Symbol(Example, Decl(jsFileMethodOverloads2.js, 0, 0)) +>value : Symbol(Example.value, Decl(jsFileMethodOverloads2.js, 8, 22)) + } + + /** + * @template U + * @overload + * @param {(y: T) => U} fn + * @returns {U} + * + * @overload + * @returns {T} + * + * @param {(y: T) => unknown} [fn] + * @returns {unknown} + */ + transform(fn) { +>transform : Symbol(Example.transform, Decl(jsFileMethodOverloads2.js, 25, 3)) +>fn : Symbol(fn, Decl(jsFileMethodOverloads2.js, 39, 12)) + + return fn ? fn(this.value) : this.value; +>fn : Symbol(fn, Decl(jsFileMethodOverloads2.js, 39, 12)) +>fn : Symbol(fn, Decl(jsFileMethodOverloads2.js, 39, 12)) +>this.value : Symbol(Example.value, Decl(jsFileMethodOverloads2.js, 8, 22)) +>this : Symbol(Example, Decl(jsFileMethodOverloads2.js, 0, 0)) +>value : Symbol(Example.value, Decl(jsFileMethodOverloads2.js, 8, 22)) +>this.value : Symbol(Example.value, Decl(jsFileMethodOverloads2.js, 8, 22)) +>this : Symbol(Example, Decl(jsFileMethodOverloads2.js, 0, 0)) +>value : Symbol(Example.value, Decl(jsFileMethodOverloads2.js, 8, 22)) + } +} + diff --git a/tests/baselines/reference/jsFileMethodOverloads2.types b/tests/baselines/reference/jsFileMethodOverloads2.types new file mode 100644 index 0000000000000..497e35261490d --- /dev/null +++ b/tests/baselines/reference/jsFileMethodOverloads2.types @@ -0,0 +1,73 @@ +=== tests/cases/compiler/jsFileMethodOverloads2.js === +// Also works if all @overload tags are combined in one comment. +/** + * @template T + */ + class Example { +>Example : Example + + /** + * @param {T} value + */ + constructor(value) { +>value : T + + this.value = value; +>this.value = value : T +>this.value : any +>this : this +>value : any +>value : T + } + + /** + * @overload + * @param {Example} this + * @returns {'number'} + * + * @overload + * @param {Example} this + * @returns {'string'} + * + * @returns {string} + */ + getTypeName() { +>getTypeName : { (this: Example): 'number'; (this: Example): 'string'; } + + return typeof this.value; +>typeof this.value : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>this.value : T +>this : this +>value : T + } + + /** + * @template U + * @overload + * @param {(y: T) => U} fn + * @returns {U} + * + * @overload + * @returns {T} + * + * @param {(y: T) => unknown} [fn] + * @returns {unknown} + */ + transform(fn) { +>transform : { (fn: (y: T) => U): U; (): T; } +>fn : (y: T) => unknown + + return fn ? fn(this.value) : this.value; +>fn ? fn(this.value) : this.value : unknown +>fn : (y: T) => unknown +>fn(this.value) : unknown +>fn : (y: T) => unknown +>this.value : T +>this : this +>value : T +>this.value : T +>this : this +>value : T + } +} + diff --git a/tests/baselines/reference/renameJsOverloadedFunctionParameter.baseline b/tests/baselines/reference/renameJsOverloadedFunctionParameter.baseline new file mode 100644 index 0000000000000..9844b0824d24b --- /dev/null +++ b/tests/baselines/reference/renameJsOverloadedFunctionParameter.baseline @@ -0,0 +1,17 @@ +/*====== /tests/cases/fourslash/foo.js ======*/ + +/** + * @overload + * @param {number} x + * @returns {number} + * + * @overload + * @param {string} x + * @returns {string} + * + * @param {unknown} RENAME + * @returns {unknown} + */ +function foo([|RENAME|]) { + return RENAME; +} diff --git a/tests/cases/compiler/jsFileAlternativeUseOfOverloadTag.ts b/tests/cases/compiler/jsFileAlternativeUseOfOverloadTag.ts new file mode 100644 index 0000000000000..d3554f529c1e4 --- /dev/null +++ b/tests/cases/compiler/jsFileAlternativeUseOfOverloadTag.ts @@ -0,0 +1,56 @@ +// @allowJs: true +// @outDir: dist/ +// @declaration: true +// @filename: jsFileAlternativeUseOfOverloadTag.js + +// These are a few examples of existing alternative uses of @overload tag. +// They will not work as expected with our implementation, but we are +// trying to make sure that our changes do not result in any crashes here. + +const example1 = { + /** + * @overload Example1(value) + * Creates Example1 + * @param value [String] + */ + constructor: function Example1(value, options) {}, +}; + +const example2 = { + /** + * Example 2 + * + * @overload Example2(value) + * Creates Example2 + * @param value [String] + * @param secretAccessKey [String] + * @param sessionToken [String] + * @example Creates with string value + * const example = new Example(''); + * @overload Example2(options) + * Creates Example2 + * @option options value [String] + * @example Creates with options object + * const example = new Example2({ + * value: '', + * }); + */ + constructor: function Example2() {}, +}; + +const example3 = { + /** + * @overload evaluate(options = {}, [callback]) + * Evaluate something + * @note Something interesting + * @param options [map] + * @return [string] returns evaluation result + * @return [null] returns nothing if callback provided + * @callback callback function (error, result) + * If callback is provided it will be called with evaluation result + * @param error [Error] + * @param result [String] + * @see callback + */ + evaluate: function evaluate(options, callback) {}, +}; diff --git a/tests/cases/compiler/jsFileFunctionOverloads.ts b/tests/cases/compiler/jsFileFunctionOverloads.ts new file mode 100644 index 0000000000000..2bb575af1ec58 --- /dev/null +++ b/tests/cases/compiler/jsFileFunctionOverloads.ts @@ -0,0 +1,62 @@ +// @allowJs: true +// @outDir: dist/ +// @declaration: true +// @filename: jsFileFunctionOverloads.js + +/** + * @overload + * @param {number} x + * @returns {'number'} + */ +/** + * @overload + * @param {string} x + * @returns {'string'} + */ +/** + * @overload + * @param {boolean} x + * @returns {'boolean'} + */ +/** + * @param {unknown} x + * @returns {string} + */ + function getTypeName(x) { + return typeof x; +} + +/** + * @template T + * @param {T} x + * @returns {T} + */ +const identity = x => x; + +/** + * @template T + * @template U + * @overload + * @param {T[]} array + * @param {(x: T) => U[]} iterable + * @returns {U[]} + */ +/** + * @template T + * @overload + * @param {T[][]} array + * @returns {T[]} + */ +/** + * @param {unknown[]} array + * @param {(x: unknown) => unknown} iterable + * @returns {unknown[]} + */ +function flatMap(array, iterable = identity) { + /** @type {unknown[]} */ + const result = []; + for (let i = 0; i < array.length; i += 1) { + result.push(.../** @type {unknown[]} */(iterable(array[i]))); + } + return result; +} diff --git a/tests/cases/compiler/jsFileFunctionOverloads2.ts b/tests/cases/compiler/jsFileFunctionOverloads2.ts new file mode 100644 index 0000000000000..74b0164623eb6 --- /dev/null +++ b/tests/cases/compiler/jsFileFunctionOverloads2.ts @@ -0,0 +1,57 @@ +// @allowJs: true +// @outDir: dist/ +// @declaration: true +// @filename: jsFileFunctionOverloads2.js + +// Also works if all @overload tags are combined in one comment. +/** + * @overload + * @param {number} x + * @returns {'number'} + * + * @overload + * @param {string} x + * @returns {'string'} + * + * @overload + * @param {boolean} x + * @returns {'boolean'} + * + * @param {unknown} x + * @returns {string} + */ + function getTypeName(x) { + return typeof x; +} + +/** + * @template T + * @param {T} x + * @returns {T} + */ +const identity = x => x; + +/** + * @template T + * @template U + * @overload + * @param {T[]} array + * @param {(x: T) => U[]} iterable + * @returns {U[]} + * + * @overload + * @param {T[][]} array + * @returns {T[]} + * + * @param {unknown[]} array + * @param {(x: unknown) => unknown} iterable + * @returns {unknown[]} + */ +function flatMap(array, iterable = identity) { + /** @type {unknown[]} */ + const result = []; + for (let i = 0; i < array.length; i += 1) { + result.push(.../** @type {unknown[]} */(iterable(array[i]))); + } + return result; +} diff --git a/tests/cases/compiler/jsFileMethodOverloads.ts b/tests/cases/compiler/jsFileMethodOverloads.ts new file mode 100644 index 0000000000000..fccdeae12502e --- /dev/null +++ b/tests/cases/compiler/jsFileMethodOverloads.ts @@ -0,0 +1,51 @@ +// @allowJs: true +// @outDir: dist/ +// @declaration: true +// @filename: jsFileMethodOverloads.js + +/** + * @template T + */ + class Example { + /** + * @param {T} value + */ + constructor(value) { + this.value = value; + } + + /** + * @overload + * @param {Example} this + * @returns {'number'} + */ + /** + * @overload + * @param {Example} this + * @returns {'string'} + */ + /** + * @returns {string} + */ + getTypeName() { + return typeof this.value; + } + + /** + * @template U + * @overload + * @param {(y: T) => U} fn + * @returns {U} + */ + /** + * @overload + * @returns {T} + */ + /** + * @param {(y: T) => unknown} [fn] + * @returns {unknown} + */ + transform(fn) { + return fn ? fn(this.value) : this.value; + } +} diff --git a/tests/cases/compiler/jsFileMethodOverloads2.ts b/tests/cases/compiler/jsFileMethodOverloads2.ts new file mode 100644 index 0000000000000..872225dc29d21 --- /dev/null +++ b/tests/cases/compiler/jsFileMethodOverloads2.ts @@ -0,0 +1,48 @@ +// @allowJs: true +// @outDir: dist/ +// @declaration: true +// @filename: jsFileMethodOverloads2.js + +// Also works if all @overload tags are combined in one comment. +/** + * @template T + */ + class Example { + /** + * @param {T} value + */ + constructor(value) { + this.value = value; + } + + /** + * @overload + * @param {Example} this + * @returns {'number'} + * + * @overload + * @param {Example} this + * @returns {'string'} + * + * @returns {string} + */ + getTypeName() { + return typeof this.value; + } + + /** + * @template U + * @overload + * @param {(y: T) => U} fn + * @returns {U} + * + * @overload + * @returns {T} + * + * @param {(y: T) => unknown} [fn] + * @returns {unknown} + */ + transform(fn) { + return fn ? fn(this.value) : this.value; + } +} diff --git a/tests/cases/fourslash/findAllReferencesJsOverloadedFunctionParameter.ts b/tests/cases/fourslash/findAllReferencesJsOverloadedFunctionParameter.ts new file mode 100644 index 0000000000000..92d7af736afb6 --- /dev/null +++ b/tests/cases/fourslash/findAllReferencesJsOverloadedFunctionParameter.ts @@ -0,0 +1,22 @@ +/// + +// @allowJs: true +// @checkJs: true +// @Filename: foo.js +/////** +//// * @overload +//// * @param {number} x +//// * @returns {number} +//// * +//// * @overload +//// * @param {string} x +//// * @returns {string} +//// * +//// * @param {unknown} x +//// * @returns {unknown} +//// */ +////function foo(x/*1*/) { +//// return x; +////} + +verify.baselineFindAllReferences("1"); diff --git a/tests/cases/fourslash/renameJsOverloadedFunctionParameter.ts b/tests/cases/fourslash/renameJsOverloadedFunctionParameter.ts new file mode 100644 index 0000000000000..2a7ea5bbd649d --- /dev/null +++ b/tests/cases/fourslash/renameJsOverloadedFunctionParameter.ts @@ -0,0 +1,22 @@ +/// + +// @allowJs: true +// @checkJs: true +// @Filename: foo.js +/////** +//// * @overload +//// * @param {number} x +//// * @returns {number} +//// * +//// * @overload +//// * @param {string} x +//// * @returns {string} +//// * +//// * @param {unknown} x +//// * @returns {unknown} +//// */ +////function foo(x/**/) { +//// return x; +////} + +verify.baselineRename("", {});