From 18a5c35648ad1d0384416d32aefe460ba1ecec03 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 29 Jul 2020 12:13:09 -0700 Subject: [PATCH 1/2] Fix this parameter emit for JSDocFunction types Previously, parameters with names that were not `new` were treated like rest parameters. This is incorrect: parameters with the name `this` should emit a `this` parameter. Fixes #38550 --- src/compiler/checker.ts | 11 +++++-- ...ionsRestArgsWithThisTypeInJSDocFunction.js | 32 +++++++++++++++++++ ...estArgsWithThisTypeInJSDocFunction.symbols | 12 +++++++ ...sRestArgsWithThisTypeInJSDocFunction.types | 12 +++++++ .../jsdocDisallowedInTypescript.types | 2 +- .../reference/jsdocFunctionType.types | 2 +- ...ionsRestArgsWithThisTypeInJSDocFunction.ts | 12 +++++++ 7 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/jsDeclarationsRestArgsWithThisTypeInJSDocFunction.js create mode 100644 tests/baselines/reference/jsDeclarationsRestArgsWithThisTypeInJSDocFunction.symbols create mode 100644 tests/baselines/reference/jsDeclarationsRestArgsWithThisTypeInJSDocFunction.types create mode 100644 tests/cases/conformance/jsdoc/declarations/jsDeclarationsRestArgsWithThisTypeInJSDocFunction.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1f8f8190f0b25..8d5d48302a2ac 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5777,7 +5777,7 @@ namespace ts { /*decorators*/ undefined, /*modifiers*/ undefined, getEffectiveDotDotDotForParameter(p), - p.name || getEffectiveDotDotDotForParameter(p) ? `args` : `arg${i}`, + getNameForJSDocFunctionParameter(p, i), p.questionToken, visitNode(p.type, visitExistingNodeTreeSymbols), /*initializer*/ undefined @@ -5792,7 +5792,7 @@ namespace ts { /*decorators*/ undefined, /*modifiers*/ undefined, getEffectiveDotDotDotForParameter(p), - p.name || getEffectiveDotDotDotForParameter(p) ? `args` : `arg${i}`, + getNameForJSDocFunctionParameter(p, i), p.questionToken, visitNode(p.type, visitExistingNodeTreeSymbols), /*initializer*/ undefined @@ -5847,6 +5847,13 @@ namespace ts { return p.dotDotDotToken || (p.type && isJSDocVariadicType(p.type) ? factory.createToken(SyntaxKind.DotDotDotToken) : undefined); } + /** Note that `new:T` parameters are not handled, but should be before calling this function. */ + function getNameForJSDocFunctionParameter(p: ParameterDeclaration, index: number) { + return p.name && isIdentifier(p.name) && p.name.escapedText === 'this' ? 'this' + : getEffectiveDotDotDotForParameter(p) ? `args` + : `arg${index}`; + } + function rewriteModuleSpecifier(parent: ImportTypeNode, lit: StringLiteral) { if (bundled) { if (context.tracker && context.tracker.moduleResolverHost) { diff --git a/tests/baselines/reference/jsDeclarationsRestArgsWithThisTypeInJSDocFunction.js b/tests/baselines/reference/jsDeclarationsRestArgsWithThisTypeInJSDocFunction.js new file mode 100644 index 0000000000000..d7f4ef518a601 --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsRestArgsWithThisTypeInJSDocFunction.js @@ -0,0 +1,32 @@ +//// [bug38550.js] +export class Clazz { + /** + * @param {function(this:Object, ...*):*} functionDeclaration + */ + method(functionDeclaration) {} +} + + +//// [bug38550.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Clazz = void 0; +var Clazz = /** @class */ (function () { + function Clazz() { + } + /** + * @param {function(this:Object, ...*):*} functionDeclaration + */ + Clazz.prototype.method = function (functionDeclaration) { }; + return Clazz; +}()); +exports.Clazz = Clazz; + + +//// [bug38550.d.ts] +export class Clazz { + /** + * @param {function(this:Object, ...*):*} functionDeclaration + */ + method(functionDeclaration: (this: any, ...args: any[]) => any): void; +} diff --git a/tests/baselines/reference/jsDeclarationsRestArgsWithThisTypeInJSDocFunction.symbols b/tests/baselines/reference/jsDeclarationsRestArgsWithThisTypeInJSDocFunction.symbols new file mode 100644 index 0000000000000..a2cbdfb5c668e --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsRestArgsWithThisTypeInJSDocFunction.symbols @@ -0,0 +1,12 @@ +=== tests/cases/conformance/jsdoc/declarations/bug38550.js === +export class Clazz { +>Clazz : Symbol(Clazz, Decl(bug38550.js, 0, 0)) + + /** + * @param {function(this:Object, ...*):*} functionDeclaration + */ + method(functionDeclaration) {} +>method : Symbol(Clazz.method, Decl(bug38550.js, 0, 20)) +>functionDeclaration : Symbol(functionDeclaration, Decl(bug38550.js, 4, 9)) +} + diff --git a/tests/baselines/reference/jsDeclarationsRestArgsWithThisTypeInJSDocFunction.types b/tests/baselines/reference/jsDeclarationsRestArgsWithThisTypeInJSDocFunction.types new file mode 100644 index 0000000000000..efc88cfe5150d --- /dev/null +++ b/tests/baselines/reference/jsDeclarationsRestArgsWithThisTypeInJSDocFunction.types @@ -0,0 +1,12 @@ +=== tests/cases/conformance/jsdoc/declarations/bug38550.js === +export class Clazz { +>Clazz : Clazz + + /** + * @param {function(this:Object, ...*):*} functionDeclaration + */ + method(functionDeclaration) {} +>method : (functionDeclaration: (this: any, ...args: any[]) => any) => void +>functionDeclaration : (this: any, ...arg1: any[]) => any +} + diff --git a/tests/baselines/reference/jsdocDisallowedInTypescript.types b/tests/baselines/reference/jsdocDisallowedInTypescript.types index bf2ac65c7224e..107b3f2ed0b23 100644 --- a/tests/baselines/reference/jsdocDisallowedInTypescript.types +++ b/tests/baselines/reference/jsdocDisallowedInTypescript.types @@ -35,7 +35,7 @@ function hof(ctor: function(new: number, string)) { >'hi' : "hi" } function hof2(f: function(this: number, string): string) { ->hof2 : (f: (args: number, arg1: string) => string) => string +>hof2 : (f: (this: number, arg1: string) => string) => string >f : (this: number, arg1: string) => string >this : number diff --git a/tests/baselines/reference/jsdocFunctionType.types b/tests/baselines/reference/jsdocFunctionType.types index d58213ab1ca3a..faa5e03072e04 100644 --- a/tests/baselines/reference/jsdocFunctionType.types +++ b/tests/baselines/reference/jsdocFunctionType.types @@ -4,7 +4,7 @@ * @return {function(this: string, number): number} */ function id1(c) { ->id1 : (c: (args: string, arg1: number) => number) => (args: string, arg1: number) => number +>id1 : (c: (this: string, arg1: number) => number) => (this: string, arg1: number) => number >c : (this: string, arg1: number) => number return c diff --git a/tests/cases/conformance/jsdoc/declarations/jsDeclarationsRestArgsWithThisTypeInJSDocFunction.ts b/tests/cases/conformance/jsdoc/declarations/jsDeclarationsRestArgsWithThisTypeInJSDocFunction.ts new file mode 100644 index 0000000000000..be77a661807de --- /dev/null +++ b/tests/cases/conformance/jsdoc/declarations/jsDeclarationsRestArgsWithThisTypeInJSDocFunction.ts @@ -0,0 +1,12 @@ +// @allowJs: true +// @checkJs: true +// @target: es5 +// @outDir: ./out +// @declaration: true +// @filename: bug38550.js +export class Clazz { + /** + * @param {function(this:Object, ...*):*} functionDeclaration + */ + method(functionDeclaration) {} +} From 7afa1b557eead77283ebf2f04a638398adeb3d3f Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 29 Jul 2020 13:29:14 -0700 Subject: [PATCH 2/2] :heart: quote style --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8d5d48302a2ac..70e9897fbb624 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5849,7 +5849,7 @@ namespace ts { /** Note that `new:T` parameters are not handled, but should be before calling this function. */ function getNameForJSDocFunctionParameter(p: ParameterDeclaration, index: number) { - return p.name && isIdentifier(p.name) && p.name.escapedText === 'this' ? 'this' + return p.name && isIdentifier(p.name) && p.name.escapedText === "this" ? "this" : getEffectiveDotDotDotForParameter(p) ? `args` : `arg${index}`; }