From 7f31b7ae036d8b271a26ac5784117c02cbb89916 Mon Sep 17 00:00:00 2001 From: Tomasz Lenarcik Date: Thu, 15 Sep 2022 12:32:00 +0200 Subject: [PATCH 1/7] Add support for JSDocOverloadTag --- src/compiler/emitter.ts | 8 ++++++++ src/compiler/factory/nodeFactory.ts | 20 ++++++++++++++++++++ src/compiler/factory/nodeTests.ts | 5 +++++ src/compiler/parser.ts | 29 ++++++++++++++++++++++++----- src/compiler/types.ts | 9 +++++++++ 5 files changed, 66 insertions(+), 5 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index d6da4d7d1f4f8..ed2cbd662a8f3 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: @@ -4372,6 +4375,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 4e872d7babb73..c153f032f9afd 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, @@ -830,6 +831,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode updateJSDocPropertyTag, createJSDocCallbackTag, updateJSDocCallbackTag, + createJSDocOverloadTag, + updateJSDocOverloadTag, createJSDocAugmentsTag, updateJSDocAugmentsTag, createJSDocImplementsTag, @@ -5158,6 +5161,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); @@ -6867,6 +6886,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 14e296610c54f..d63bc1d7066ef 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, @@ -1128,6 +1129,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 f1f8bd002e875..acdd409f653e8 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -180,6 +180,7 @@ import { JSDocNonNullableType, JSDocNullableType, JSDocOptionalType, + JSDocOverloadTag, JSDocOverrideTag, JSDocParameterTag, JSDocPrivateTag, @@ -8782,6 +8783,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; @@ -9265,10 +9269,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)) { @@ -9278,7 +9279,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); } @@ -9286,6 +9294,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 7ce54d3dd6c02..27099ff3e48df 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -421,6 +421,7 @@ export const enum SyntaxKind { JSDocReadonlyTag, JSDocOverrideTag, JSDocCallbackTag, + JSDocOverloadTag, JSDocEnumTag, JSDocParameterTag, JSDocReturnTag, @@ -3826,6 +3827,12 @@ 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 JSDocSignature extends JSDocType, Declaration { readonly kind: SyntaxKind.JSDocSignature; readonly typeParameters?: readonly JSDocTemplateTag[]; @@ -8215,6 +8222,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; From a6cb51908a807f420a9ac401aa34340cb2c53257 Mon Sep 17 00:00:00 2001 From: Tomasz Lenarcik Date: Sun, 16 Oct 2022 21:37:40 +0200 Subject: [PATCH 2/7] Use overload tag to determine function type --- src/compiler/binder.ts | 3 +++ src/compiler/checker.ts | 17 +++++++++++++++++ src/compiler/utilities.ts | 3 ++- src/compiler/utilitiesPublic.ts | 9 +++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) 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 11164845ba139..0c82a45094aef 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -536,6 +536,7 @@ import { isJSDocNonNullableType, isJSDocNullableType, isJSDocOptionalType, + isJSDocOverloadTag, isJSDocParameterTag, isJSDocPropertyLikeTag, isJSDocReturnTag, @@ -14272,6 +14273,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/utilities.ts b/src/compiler/utilities.ts index 36cfe74f91e01..b41173f187613 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -268,6 +268,7 @@ import { isJSDocMemberName, isJSDocNameReference, isJSDocNode, + isJSDocOverloadTag, isJSDocParameterTag, isJSDocPropertyLikeTag, isJSDocSignature, @@ -5633,7 +5634,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)) { From dd65e9a7b68fbf792f18c92b3947ffee92636d83 Mon Sep 17 00:00:00 2001 From: Tomasz Lenarcik Date: Sat, 3 Dec 2022 23:34:21 +0100 Subject: [PATCH 3/7] Update baselines --- .../reference/api/tsserverlibrary.d.ts | 47 +++++++++++-------- tests/baselines/reference/api/typescript.d.ts | 47 +++++++++++-------- 2 files changed, 56 insertions(+), 38 deletions(-) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index e3e8466ccd1e7..d0d823e2d23a2 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4340,23 +4340,24 @@ 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, - SyntaxList = 351, - NotEmittedStatement = 352, - PartiallyEmittedExpression = 353, - CommaListExpression = 354, - MergeDeclarationMarker = 355, - EndOfDeclarationMarker = 356, - SyntheticReferenceExpression = 357, - Count = 358, + JSDocOverloadTag = 342, + JSDocEnumTag = 343, + JSDocParameterTag = 344, + JSDocReturnTag = 345, + JSDocThisTag = 346, + JSDocTypeTag = 347, + JSDocTemplateTag = 348, + JSDocTypedefTag = 349, + JSDocSeeTag = 350, + JSDocPropertyTag = 351, + SyntaxList = 352, + NotEmittedStatement = 353, + PartiallyEmittedExpression = 354, + CommaListExpression = 355, + MergeDeclarationMarker = 356, + EndOfDeclarationMarker = 357, + SyntheticReferenceExpression = 358, + Count = 359, FirstAssignment = 63, LastAssignment = 78, FirstCompoundAssignment = 64, @@ -4385,9 +4386,9 @@ declare namespace ts { LastStatement = 256, FirstNode = 163, FirstJSDocNode = 312, - LastJSDocNode = 350, + LastJSDocNode = 351, FirstJSDocTagNode = 330, - LastJSDocTagNode = 350 + LastJSDocTagNode = 351 } 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; @@ -5940,6 +5941,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 JSDocSignature extends JSDocType, Declaration { readonly kind: SyntaxKind.JSDocSignature; readonly typeParameters?: readonly JSDocTemplateTag[]; @@ -7781,6 +7787,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; @@ -9031,6 +9039,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 7bc06c330da8a..db34c9b4b62a4 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -404,23 +404,24 @@ 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, - SyntaxList = 351, - NotEmittedStatement = 352, - PartiallyEmittedExpression = 353, - CommaListExpression = 354, - MergeDeclarationMarker = 355, - EndOfDeclarationMarker = 356, - SyntheticReferenceExpression = 357, - Count = 358, + JSDocOverloadTag = 342, + JSDocEnumTag = 343, + JSDocParameterTag = 344, + JSDocReturnTag = 345, + JSDocThisTag = 346, + JSDocTypeTag = 347, + JSDocTemplateTag = 348, + JSDocTypedefTag = 349, + JSDocSeeTag = 350, + JSDocPropertyTag = 351, + SyntaxList = 352, + NotEmittedStatement = 353, + PartiallyEmittedExpression = 354, + CommaListExpression = 355, + MergeDeclarationMarker = 356, + EndOfDeclarationMarker = 357, + SyntheticReferenceExpression = 358, + Count = 359, FirstAssignment = 63, LastAssignment = 78, FirstCompoundAssignment = 64, @@ -449,9 +450,9 @@ declare namespace ts { LastStatement = 256, FirstNode = 163, FirstJSDocNode = 312, - LastJSDocNode = 350, + LastJSDocNode = 351, FirstJSDocTagNode = 330, - LastJSDocTagNode = 350 + LastJSDocTagNode = 351 } 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; @@ -2004,6 +2005,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 JSDocSignature extends JSDocType, Declaration { readonly kind: SyntaxKind.JSDocSignature; readonly typeParameters?: readonly JSDocTemplateTag[]; @@ -3845,6 +3851,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; @@ -5095,6 +5103,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; From f659657b4e23e6a09b5294571c83777e484b9bfd Mon Sep 17 00:00:00 2001 From: Tomasz Lenarcik Date: Thu, 15 Sep 2022 16:20:38 +0200 Subject: [PATCH 4/7] Add new tests along with baselines --- .../reference/jsFileFunctionOverloads.js | 131 ++++++++++++++++++ .../reference/jsFileFunctionOverloads.symbols | 87 ++++++++++++ .../reference/jsFileFunctionOverloads.types | 99 +++++++++++++ .../reference/jsFileMethodOverloads.js | 112 +++++++++++++++ .../reference/jsFileMethodOverloads.symbols | 72 ++++++++++ .../reference/jsFileMethodOverloads.types | 76 ++++++++++ .../cases/compiler/jsFileFunctionOverloads.ts | 62 +++++++++ tests/cases/compiler/jsFileMethodOverloads.ts | 51 +++++++ 8 files changed, 690 insertions(+) create mode 100644 tests/baselines/reference/jsFileFunctionOverloads.js create mode 100644 tests/baselines/reference/jsFileFunctionOverloads.symbols create mode 100644 tests/baselines/reference/jsFileFunctionOverloads.types create mode 100644 tests/baselines/reference/jsFileMethodOverloads.js create mode 100644 tests/baselines/reference/jsFileMethodOverloads.symbols create mode 100644 tests/baselines/reference/jsFileMethodOverloads.types create mode 100644 tests/cases/compiler/jsFileFunctionOverloads.ts create mode 100644 tests/cases/compiler/jsFileMethodOverloads.ts 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/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/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/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; + } +} From 7db2335714a243e2e9aa83a16ecae8bfe1a8e054 Mon Sep 17 00:00:00 2001 From: Tomasz Lenarcik Date: Sat, 3 Dec 2022 15:03:09 +0100 Subject: [PATCH 5/7] Add tests for all @overload tags in one comment --- .../reference/jsFileFunctionOverloads2.js | 121 ++++++++++++++++++ .../jsFileFunctionOverloads2.symbols | 82 ++++++++++++ .../reference/jsFileFunctionOverloads2.types | 94 ++++++++++++++ .../reference/jsFileMethodOverloads2.js | 106 +++++++++++++++ .../reference/jsFileMethodOverloads2.symbols | 69 ++++++++++ .../reference/jsFileMethodOverloads2.types | 73 +++++++++++ .../compiler/jsFileFunctionOverloads2.ts | 57 +++++++++ .../cases/compiler/jsFileMethodOverloads2.ts | 48 +++++++ 8 files changed, 650 insertions(+) create mode 100644 tests/baselines/reference/jsFileFunctionOverloads2.js create mode 100644 tests/baselines/reference/jsFileFunctionOverloads2.symbols create mode 100644 tests/baselines/reference/jsFileFunctionOverloads2.types create mode 100644 tests/baselines/reference/jsFileMethodOverloads2.js create mode 100644 tests/baselines/reference/jsFileMethodOverloads2.symbols create mode 100644 tests/baselines/reference/jsFileMethodOverloads2.types create mode 100644 tests/cases/compiler/jsFileFunctionOverloads2.ts create mode 100644 tests/cases/compiler/jsFileMethodOverloads2.ts 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/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/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/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; + } +} From 52a94ca9bad64939ac23f2fa1d89dc88c1530551 Mon Sep 17 00:00:00 2001 From: Tomasz Lenarcik Date: Sat, 3 Dec 2022 15:04:29 +0100 Subject: [PATCH 6/7] Add tests for find-all-ref and rename operations --- ...OverloadedFunctionParameter.baseline.jsonc | 95 +++++++++++++++++++ ...nameJsOverloadedFunctionParameter.baseline | 17 ++++ ...ReferencesJsOverloadedFunctionParameter.ts | 22 +++++ .../renameJsOverloadedFunctionParameter.ts | 22 +++++ 4 files changed, 156 insertions(+) create mode 100644 tests/baselines/reference/findAllReferencesJsOverloadedFunctionParameter.baseline.jsonc create mode 100644 tests/baselines/reference/renameJsOverloadedFunctionParameter.baseline create mode 100644 tests/cases/fourslash/findAllReferencesJsOverloadedFunctionParameter.ts create mode 100644 tests/cases/fourslash/renameJsOverloadedFunctionParameter.ts 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/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/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("", {}); From f0ec97c59e9f64b231d13b4b05d06ecb2b735b73 Mon Sep 17 00:00:00 2001 From: Tomasz Lenarcik Date: Sat, 3 Dec 2022 22:46:13 +0100 Subject: [PATCH 7/7] Add tests for alternative uses of @overload tag --- .../jsFileAlternativeUseOfOverloadTag.js | 121 ++++++++++++++++++ .../jsFileAlternativeUseOfOverloadTag.symbols | 72 +++++++++++ .../jsFileAlternativeUseOfOverloadTag.types | 78 +++++++++++ .../jsFileAlternativeUseOfOverloadTag.ts | 56 ++++++++ 4 files changed, 327 insertions(+) create mode 100644 tests/baselines/reference/jsFileAlternativeUseOfOverloadTag.js create mode 100644 tests/baselines/reference/jsFileAlternativeUseOfOverloadTag.symbols create mode 100644 tests/baselines/reference/jsFileAlternativeUseOfOverloadTag.types create mode 100644 tests/cases/compiler/jsFileAlternativeUseOfOverloadTag.ts diff --git a/tests/baselines/reference/jsFileAlternativeUseOfOverloadTag.js b/tests/baselines/reference/jsFileAlternativeUseOfOverloadTag.js new file mode 100644 index 0000000000000..a7e4cee8b4e96 --- /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/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) {}, +};