From db8eacd7e21a8bc945481cd235ff4cd0929e661a Mon Sep 17 00:00:00 2001 From: "Oleksandr T." Date: Wed, 23 Oct 2024 21:34:23 +0300 Subject: [PATCH] fix(59397): JsDoc is missing/duplicated in declarations for overloads declared in classes declared in functions (#59675) --- src/compiler/checker.ts | 10 ++-- .../signatureOverloadsWithComments.js | 45 ++++++++++++++++++ .../signatureOverloadsWithComments.symbols | 36 ++++++++++++++ .../signatureOverloadsWithComments.types | 47 +++++++++++++++++++ .../signatureOverloadsWithComments.ts | 23 +++++++++ 5 files changed, 156 insertions(+), 5 deletions(-) create mode 100644 tests/baselines/reference/signatureOverloadsWithComments.js create mode 100644 tests/baselines/reference/signatureOverloadsWithComments.symbols create mode 100644 tests/baselines/reference/signatureOverloadsWithComments.types create mode 100644 tests/cases/compiler/signatureOverloadsWithComments.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e4efe7ca59799..2d373bc6ece4c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7369,7 +7369,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const signatures = getSignaturesOfType(filterType(propertyType, t => !(t.flags & TypeFlags.Undefined)), SignatureKind.Call); for (const signature of signatures) { const methodDeclaration = signatureToSignatureDeclarationHelper(signature, SyntaxKind.MethodSignature, context, { name: propertyName, questionToken: optionalToken }) as MethodSignature; - typeElements.push(preserveCommentsOn(methodDeclaration)); + typeElements.push(preserveCommentsOn(methodDeclaration, signature.declaration || propertySymbol.valueDeclaration)); } if (signatures.length || !optionalToken) { return; @@ -7401,9 +7401,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { propertyTypeNode, ); - typeElements.push(preserveCommentsOn(propertySignature)); + typeElements.push(preserveCommentsOn(propertySignature, propertySymbol.valueDeclaration)); - function preserveCommentsOn(node: T) { + function preserveCommentsOn(node: T, range: Node | undefined) { const jsdocPropertyTag = propertySymbol.declarations?.find((d): d is JSDocPropertyTag => d.kind === SyntaxKind.JSDocPropertyTag); if (jsdocPropertyTag) { const commentText = getTextOfJSDocComment(jsdocPropertyTag.comment); @@ -7411,9 +7411,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { setSyntheticLeadingComments(node, [{ kind: SyntaxKind.MultiLineCommentTrivia, text: "*\n * " + commentText.replace(/\n/g, "\n * ") + "\n ", pos: -1, end: -1, hasTrailingNewLine: true }]); } } - else if (propertySymbol.valueDeclaration) { + else if (range) { // Copy comments to node for declaration emit - setCommentRange(context, node, propertySymbol.valueDeclaration); + setCommentRange(context, node, range); } return node; } diff --git a/tests/baselines/reference/signatureOverloadsWithComments.js b/tests/baselines/reference/signatureOverloadsWithComments.js new file mode 100644 index 0000000000000..a66e4a1cadc8d --- /dev/null +++ b/tests/baselines/reference/signatureOverloadsWithComments.js @@ -0,0 +1,45 @@ +//// [tests/cases/compiler/signatureOverloadsWithComments.ts] //// + +//// [signatureOverloadsWithComments.ts] +/** + * Docs + */ +function Foo() { + return class Bar { + /** + * comment 1 + */ + foo(bar: string): void; + /** + * @deprecated This signature is deprecated + * + * comment 2 + */ + foo(): string; + foo(bar?: string): string | void { + return 'hi' + } + } +} + + + + +//// [signatureOverloadsWithComments.d.ts] +/** + * Docs + */ +declare function Foo(): { + new (): { + /** + * comment 1 + */ + foo(bar: string): void; + /** + * @deprecated This signature is deprecated + * + * comment 2 + */ + foo(): string; + }; +}; diff --git a/tests/baselines/reference/signatureOverloadsWithComments.symbols b/tests/baselines/reference/signatureOverloadsWithComments.symbols new file mode 100644 index 0000000000000..3d04d7bb43cc2 --- /dev/null +++ b/tests/baselines/reference/signatureOverloadsWithComments.symbols @@ -0,0 +1,36 @@ +//// [tests/cases/compiler/signatureOverloadsWithComments.ts] //// + +=== signatureOverloadsWithComments.ts === +/** + * Docs + */ +function Foo() { +>Foo : Symbol(Foo, Decl(signatureOverloadsWithComments.ts, 0, 0)) + + return class Bar { +>Bar : Symbol(Bar, Decl(signatureOverloadsWithComments.ts, 4, 10)) + + /** + * comment 1 + */ + foo(bar: string): void; +>foo : Symbol(Bar.foo, Decl(signatureOverloadsWithComments.ts, 4, 22), Decl(signatureOverloadsWithComments.ts, 8, 31), Decl(signatureOverloadsWithComments.ts, 14, 22)) +>bar : Symbol(bar, Decl(signatureOverloadsWithComments.ts, 8, 12)) + + /** + * @deprecated This signature is deprecated + * + * comment 2 + */ + foo(): string; +>foo : Symbol(Bar.foo, Decl(signatureOverloadsWithComments.ts, 4, 22), Decl(signatureOverloadsWithComments.ts, 8, 31), Decl(signatureOverloadsWithComments.ts, 14, 22)) + + foo(bar?: string): string | void { +>foo : Symbol(Bar.foo, Decl(signatureOverloadsWithComments.ts, 4, 22), Decl(signatureOverloadsWithComments.ts, 8, 31), Decl(signatureOverloadsWithComments.ts, 14, 22)) +>bar : Symbol(bar, Decl(signatureOverloadsWithComments.ts, 15, 12)) + + return 'hi' + } + } +} + diff --git a/tests/baselines/reference/signatureOverloadsWithComments.types b/tests/baselines/reference/signatureOverloadsWithComments.types new file mode 100644 index 0000000000000..6742e001f3481 --- /dev/null +++ b/tests/baselines/reference/signatureOverloadsWithComments.types @@ -0,0 +1,47 @@ +//// [tests/cases/compiler/signatureOverloadsWithComments.ts] //// + +=== signatureOverloadsWithComments.ts === +/** + * Docs + */ +function Foo() { +>Foo : () => typeof Bar +> : ^^^^^^^^^^^^^^^^ + + return class Bar { +>class Bar { /** * comment 1 */ foo(bar: string): void; /** * @deprecated This signature is deprecated * * comment 2 */ foo(): string; foo(bar?: string): string | void { return 'hi' } } : typeof Bar +> : ^^^^^^^^^^ +>Bar : typeof Bar +> : ^^^^^^^^^^ + + /** + * comment 1 + */ + foo(bar: string): void; +>foo : { (bar: string): void; (): string; } +> : ^^^ ^^ ^^^ ^^^^^^ ^^^ +>bar : string +> : ^^^^^^ + + /** + * @deprecated This signature is deprecated + * + * comment 2 + */ + foo(): string; +>foo : { (bar: string): void; (): string; } +> : ^^^ ^^ ^^^ ^^^^^^ ^^^ + + foo(bar?: string): string | void { +>foo : { (bar: string): void; (): string; } +> : ^^^ ^^ ^^^ ^^^^^^ ^^^ +>bar : string +> : ^^^^^^ + + return 'hi' +>'hi' : "hi" +> : ^^^^ + } + } +} + diff --git a/tests/cases/compiler/signatureOverloadsWithComments.ts b/tests/cases/compiler/signatureOverloadsWithComments.ts new file mode 100644 index 0000000000000..61101f1b046d7 --- /dev/null +++ b/tests/cases/compiler/signatureOverloadsWithComments.ts @@ -0,0 +1,23 @@ +// @declaration: true +// @emitDeclarationOnly: true + +/** + * Docs + */ +function Foo() { + return class Bar { + /** + * comment 1 + */ + foo(bar: string): void; + /** + * @deprecated This signature is deprecated + * + * comment 2 + */ + foo(): string; + foo(bar?: string): string | void { + return 'hi' + } + } +}