From 0dd9a99fbf938265c308ae111d898d0b040cde40 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 13 Mar 2018 10:43:12 -0700 Subject: [PATCH 1/5] No errr on unmatchable `@param` tags Such as when the initializer is not a function, or when the function mentions `arguments` in its body. --- src/compiler/checker.ts | 3 +- .../paramTagOnCallExpression.symbols | 14 +++++++ .../reference/paramTagOnCallExpression.types | 17 ++++++++ .../paramTagOnFunctionUsingArguments.symbols | 34 ++++++++++++++++ .../paramTagOnFunctionUsingArguments.types | 40 +++++++++++++++++++ .../jsdoc/paramTagOnCallExpression.ts | 11 +++++ .../jsdoc/paramTagOnFunctionUsingArguments.ts | 18 +++++++++ 7 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/paramTagOnCallExpression.symbols create mode 100644 tests/baselines/reference/paramTagOnCallExpression.types create mode 100644 tests/baselines/reference/paramTagOnFunctionUsingArguments.symbols create mode 100644 tests/baselines/reference/paramTagOnFunctionUsingArguments.types create mode 100644 tests/cases/conformance/jsdoc/paramTagOnCallExpression.ts create mode 100644 tests/cases/conformance/jsdoc/paramTagOnFunctionUsingArguments.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a86f18e4cceac..9fb643f135697 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -21447,7 +21447,8 @@ namespace ts { function checkJSDocParameterTag(node: JSDocParameterTag) { checkSourceElement(node.typeExpression); - if (!getParameterSymbolFromJSDoc(node)) { + const decl = getHostSignatureFromJSDoc(node); + if (!getParameterSymbolFromJSDoc(node) && decl && !containsArgumentsReference(decl)) { error(node.name, Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name, idText(node.name.kind === SyntaxKind.QualifiedName ? node.name.right : node.name)); diff --git a/tests/baselines/reference/paramTagOnCallExpression.symbols b/tests/baselines/reference/paramTagOnCallExpression.symbols new file mode 100644 index 0000000000000..0ac0f3d60a622 --- /dev/null +++ b/tests/baselines/reference/paramTagOnCallExpression.symbols @@ -0,0 +1,14 @@ +=== tests/cases/conformance/jsdoc/decls.d.ts === +declare function factory(type: string): {}; +>factory : Symbol(factory, Decl(decls.d.ts, 0, 0)) +>type : Symbol(type, Decl(decls.d.ts, 0, 25)) + +=== tests/cases/conformance/jsdoc/a.js === +// from util +/** @param {function} ctor - A big long explanation follows */ +exports.inherits = factory('inherits') +>exports.inherits : Symbol(inherits, Decl(a.js, 0, 0)) +>exports : Symbol(inherits, Decl(a.js, 0, 0)) +>inherits : Symbol(inherits, Decl(a.js, 0, 0)) +>factory : Symbol(factory, Decl(decls.d.ts, 0, 0)) + diff --git a/tests/baselines/reference/paramTagOnCallExpression.types b/tests/baselines/reference/paramTagOnCallExpression.types new file mode 100644 index 0000000000000..c5aa2c7c61130 --- /dev/null +++ b/tests/baselines/reference/paramTagOnCallExpression.types @@ -0,0 +1,17 @@ +=== tests/cases/conformance/jsdoc/decls.d.ts === +declare function factory(type: string): {}; +>factory : (type: string) => {} +>type : string + +=== tests/cases/conformance/jsdoc/a.js === +// from util +/** @param {function} ctor - A big long explanation follows */ +exports.inherits = factory('inherits') +>exports.inherits = factory('inherits') : {} +>exports.inherits : {} +>exports : typeof "tests/cases/conformance/jsdoc/a" +>inherits : {} +>factory('inherits') : {} +>factory : (type: string) => {} +>'inherits' : "inherits" + diff --git a/tests/baselines/reference/paramTagOnFunctionUsingArguments.symbols b/tests/baselines/reference/paramTagOnFunctionUsingArguments.symbols new file mode 100644 index 0000000000000..d6c98febc57d0 --- /dev/null +++ b/tests/baselines/reference/paramTagOnFunctionUsingArguments.symbols @@ -0,0 +1,34 @@ +=== tests/cases/conformance/jsdoc/decls.d.ts === +declare function factory(type: string): {}; +>factory : Symbol(factory, Decl(decls.d.ts, 0, 0)) +>type : Symbol(type, Decl(decls.d.ts, 0, 25)) + +=== tests/cases/conformance/jsdoc/a.js === +/** + * @param {string} first + */ +function concat(/* first, second, ... */) { +>concat : Symbol(concat, Decl(a.js, 0, 0)) + + var s = '' +>s : Symbol(s, Decl(a.js, 4, 5)) + + for (var i = 0, l = arguments.length; i < l; i++) { +>i : Symbol(i, Decl(a.js, 5, 10)) +>l : Symbol(l, Decl(a.js, 5, 17)) +>arguments.length : Symbol(IArguments.length, Decl(lib.d.ts, --, --)) +>arguments : Symbol(arguments) +>length : Symbol(IArguments.length, Decl(lib.d.ts, --, --)) +>i : Symbol(i, Decl(a.js, 5, 10)) +>l : Symbol(l, Decl(a.js, 5, 17)) +>i : Symbol(i, Decl(a.js, 5, 10)) + + s += arguments[i] +>s : Symbol(s, Decl(a.js, 4, 5)) +>arguments : Symbol(arguments) +>i : Symbol(i, Decl(a.js, 5, 10)) + } + return s +>s : Symbol(s, Decl(a.js, 4, 5)) +} + diff --git a/tests/baselines/reference/paramTagOnFunctionUsingArguments.types b/tests/baselines/reference/paramTagOnFunctionUsingArguments.types new file mode 100644 index 0000000000000..04702c80f4fce --- /dev/null +++ b/tests/baselines/reference/paramTagOnFunctionUsingArguments.types @@ -0,0 +1,40 @@ +=== tests/cases/conformance/jsdoc/decls.d.ts === +declare function factory(type: string): {}; +>factory : (type: string) => {} +>type : string + +=== tests/cases/conformance/jsdoc/a.js === +/** + * @param {string} first + */ +function concat(/* first, second, ... */) { +>concat : (...args: any[]) => string + + var s = '' +>s : string +>'' : "" + + for (var i = 0, l = arguments.length; i < l; i++) { +>i : number +>0 : 0 +>l : number +>arguments.length : number +>arguments : IArguments +>length : number +>i < l : boolean +>i : number +>l : number +>i++ : number +>i : number + + s += arguments[i] +>s += arguments[i] : string +>s : string +>arguments[i] : any +>arguments : IArguments +>i : number + } + return s +>s : string +} + diff --git a/tests/cases/conformance/jsdoc/paramTagOnCallExpression.ts b/tests/cases/conformance/jsdoc/paramTagOnCallExpression.ts new file mode 100644 index 0000000000000..78a971d1b7d60 --- /dev/null +++ b/tests/cases/conformance/jsdoc/paramTagOnCallExpression.ts @@ -0,0 +1,11 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @strict: true +// @Filename: decls.d.ts +declare function factory(type: string): {}; +// @Filename: a.js + +// from util +/** @param {function} ctor - A big long explanation follows */ +exports.inherits = factory('inherits') diff --git a/tests/cases/conformance/jsdoc/paramTagOnFunctionUsingArguments.ts b/tests/cases/conformance/jsdoc/paramTagOnFunctionUsingArguments.ts new file mode 100644 index 0000000000000..13691f611170a --- /dev/null +++ b/tests/cases/conformance/jsdoc/paramTagOnFunctionUsingArguments.ts @@ -0,0 +1,18 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @strict: true +// @Filename: decls.d.ts +declare function factory(type: string): {}; +// @Filename: a.js + +/** + * @param {string} first + */ +function concat(/* first, second, ... */) { + var s = '' + for (var i = 0, l = arguments.length; i < l; i++) { + s += arguments[i] + } + return s +} From 2d3440cf101d7f7439ed6bb4680472802a09691d Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Tue, 13 Mar 2018 15:08:41 -0700 Subject: [PATCH 2/5] Do not require dummy param for JS uses of arguments 1. JS functions that use `arguments` do not require a dummy parameter in order to get a type for the synthetic `args` parameter if there is an `@param` with a `...` type. 2.JS functions that use `arguments` and have an `@param` must have a type that is a `...` type. --- src/compiler/checker.ts | 38 +++++++++++++------ src/compiler/diagnosticMessages.json | 4 ++ .../reference/jsdocPrefixPostfixParsing.types | 2 +- ...aramTagOnFunctionUsingArguments.errors.txt | 31 +++++++++++++++ .../paramTagOnFunctionUsingArguments.symbols | 13 +++++++ .../paramTagOnFunctionUsingArguments.types | 17 +++++++++ .../jsdoc/paramTagOnCallExpression.ts | 1 - .../jsdoc/paramTagOnFunctionUsingArguments.ts | 9 +++++ 8 files changed, 101 insertions(+), 14 deletions(-) create mode 100644 tests/baselines/reference/paramTagOnFunctionUsingArguments.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9fb643f135697..bcf572c6c92f4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6761,17 +6761,20 @@ namespace ts { return links.resolvedSignature; } + /** + * A JS function gets a synthetic rest parameter if it references `arguments` AND: + * 1. It has no parameters and at least one `@param` and the first `@param` has a type and the type starts with `...` + * OR + * 2. It has at least one parameter, and the last parameter has a matching `@param` with a type and the type starts with `...` + */ function maybeAddJsSyntheticRestParameter(declaration: SignatureDeclaration, parameters: Symbol[]): boolean { - // JS functions get a free rest parameter if: - // a) The last parameter has `...` preceding its type - // b) It references `arguments` somewhere + if (!containsArgumentsReference(declaration)) { + return false; + } const lastParam = lastOrUndefined(declaration.parameters); - const lastParamTags = lastParam && getJSDocParameterTags(lastParam); + const lastParamTags = lastParam ? getJSDocParameterTags(lastParam) : getJSDocTags(declaration).filter((tag): tag is JSDocParameterTag => isJSDocParameterTag(tag)); const lastParamVariadicType = firstDefined(lastParamTags, p => p.typeExpression && isJSDocVariadicType(p.typeExpression.type) ? p.typeExpression.type : undefined); - if (!lastParamVariadicType && !containsArgumentsReference(declaration)) { - return false; - } const syntheticArgsSymbol = createSymbol(SymbolFlags.Variable, "args" as __String); syntheticArgsSymbol.type = lastParamVariadicType ? createArrayType(getTypeFromTypeNode(lastParamVariadicType.type)) : anyArrayType; @@ -21447,11 +21450,22 @@ namespace ts { function checkJSDocParameterTag(node: JSDocParameterTag) { checkSourceElement(node.typeExpression); - const decl = getHostSignatureFromJSDoc(node); - if (!getParameterSymbolFromJSDoc(node) && decl && !containsArgumentsReference(decl)) { - error(node.name, - Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name, - idText(node.name.kind === SyntaxKind.QualifiedName ? node.name.right : node.name)); + if (!getParameterSymbolFromJSDoc(node)) { + const decl = getHostSignatureFromJSDoc(node); + if (decl) { + if (!containsArgumentsReference(decl)) { + error(node.name, + Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name, + idText(node.name.kind === SyntaxKind.QualifiedName ? node.name.right : node.name)); + } + else if (lastOrUndefined(getJSDocTags(decl).filter((tag): tag is JSDocParameterTag => isJSDocParameterTag(tag))) === node && + node.typeExpression && node.typeExpression.type && + node.typeExpression.type.kind !== SyntaxKind.JSDocVariadicType) { + error(node.name, + Diagnostics.JSDoc_must_appear_on_the_last_param_tag_of_a_function_that_uses_arguments, + idText(node.name.kind === SyntaxKind.QualifiedName ? node.name.right : node.name)); + } + } } } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 9f95a66711b75..c622cb4b1d7ca 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3720,6 +3720,10 @@ "category": "Error", "code": 8028 }, + "JSDoc '...' must appear on the last @param tag of a function that uses 'arguments'.": { + "category": "Error", + "code": 8029 + }, "Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clause.": { "category": "Error", "code": 9002 diff --git a/tests/baselines/reference/jsdocPrefixPostfixParsing.types b/tests/baselines/reference/jsdocPrefixPostfixParsing.types index cf69cf9d40c09..733a266391eac 100644 --- a/tests/baselines/reference/jsdocPrefixPostfixParsing.types +++ b/tests/baselines/reference/jsdocPrefixPostfixParsing.types @@ -16,7 +16,7 @@ * @param {...number?[]!} k - (number[] | null)[] */ function f(x, y, z, a, b, c, d, e, f, g, h, i, j, k) { ->f : (x: number[], y: number[], z: number[], a: (number | null)[], b: number[] | null, c: number[] | null, d: number | null | undefined, e: number | null | undefined, f: number | null | undefined, g: number | null | undefined, h: number | null | undefined, i: number[] | undefined, j: number[] | null | undefined, ...args: (number | null)[][]) => void +>f : (x: number[], y: number[], z: number[], a: (number | null)[], b: number[] | null, c: number[] | null, d: number | null | undefined, e: number | null | undefined, f: number | null | undefined, g: number | null | undefined, h: number | null | undefined, i: number[] | undefined, j: number[] | null | undefined, k: (number | null)[] | undefined) => void >x : number[] >y : number[] >z : number[] diff --git a/tests/baselines/reference/paramTagOnFunctionUsingArguments.errors.txt b/tests/baselines/reference/paramTagOnFunctionUsingArguments.errors.txt new file mode 100644 index 0000000000000..b9cd887cd6603 --- /dev/null +++ b/tests/baselines/reference/paramTagOnFunctionUsingArguments.errors.txt @@ -0,0 +1,31 @@ +tests/cases/conformance/jsdoc/a.js(2,20): error TS8029: JSDoc '...' must appear on the last @param tag of a function that uses 'arguments'. +tests/cases/conformance/jsdoc/a.js(19,9): error TS2345: Argument of type '1' is not assignable to parameter of type 'string'. + + +==== tests/cases/conformance/jsdoc/decls.d.ts (0 errors) ==== + declare function factory(type: string): {}; +==== tests/cases/conformance/jsdoc/a.js (2 errors) ==== + /** + * @param {string} first + ~~~~~ +!!! error TS8029: JSDoc '...' must appear on the last @param tag of a function that uses 'arguments'. + */ + function concat(/* first, second, ... */) { + var s = '' + for (var i = 0, l = arguments.length; i < l; i++) { + s += arguments[i] + } + return s + } + + /** + * @param {...string} strings + */ + function correct() { + arguments + } + + correct(1,2,3) // oh no + ~ +!!! error TS2345: Argument of type '1' is not assignable to parameter of type 'string'. + \ No newline at end of file diff --git a/tests/baselines/reference/paramTagOnFunctionUsingArguments.symbols b/tests/baselines/reference/paramTagOnFunctionUsingArguments.symbols index d6c98febc57d0..4d8688e987769 100644 --- a/tests/baselines/reference/paramTagOnFunctionUsingArguments.symbols +++ b/tests/baselines/reference/paramTagOnFunctionUsingArguments.symbols @@ -32,3 +32,16 @@ function concat(/* first, second, ... */) { >s : Symbol(s, Decl(a.js, 4, 5)) } +/** + * @param {...string} strings + */ +function correct() { +>correct : Symbol(correct, Decl(a.js, 9, 1)) + + arguments +>arguments : Symbol(arguments) +} + +correct(1,2,3) // oh no +>correct : Symbol(correct, Decl(a.js, 9, 1)) + diff --git a/tests/baselines/reference/paramTagOnFunctionUsingArguments.types b/tests/baselines/reference/paramTagOnFunctionUsingArguments.types index 04702c80f4fce..275e248291cc8 100644 --- a/tests/baselines/reference/paramTagOnFunctionUsingArguments.types +++ b/tests/baselines/reference/paramTagOnFunctionUsingArguments.types @@ -38,3 +38,20 @@ function concat(/* first, second, ... */) { >s : string } +/** + * @param {...string} strings + */ +function correct() { +>correct : (...args: string[]) => void + + arguments +>arguments : IArguments +} + +correct(1,2,3) // oh no +>correct(1,2,3) : void +>correct : (...args: string[]) => void +>1 : 1 +>2 : 2 +>3 : 3 + diff --git a/tests/cases/conformance/jsdoc/paramTagOnCallExpression.ts b/tests/cases/conformance/jsdoc/paramTagOnCallExpression.ts index 78a971d1b7d60..6a00f7db8bf82 100644 --- a/tests/cases/conformance/jsdoc/paramTagOnCallExpression.ts +++ b/tests/cases/conformance/jsdoc/paramTagOnCallExpression.ts @@ -1,7 +1,6 @@ // @noEmit: true // @allowJs: true // @checkJs: true -// @strict: true // @Filename: decls.d.ts declare function factory(type: string): {}; // @Filename: a.js diff --git a/tests/cases/conformance/jsdoc/paramTagOnFunctionUsingArguments.ts b/tests/cases/conformance/jsdoc/paramTagOnFunctionUsingArguments.ts index 13691f611170a..0c5b0fbb365f7 100644 --- a/tests/cases/conformance/jsdoc/paramTagOnFunctionUsingArguments.ts +++ b/tests/cases/conformance/jsdoc/paramTagOnFunctionUsingArguments.ts @@ -16,3 +16,12 @@ function concat(/* first, second, ... */) { } return s } + +/** + * @param {...string} strings + */ +function correct() { + arguments +} + +correct(1,2,3) // oh no From 43e20d05e02622ab9e93239a0e207663a20736ed Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 14 Mar 2018 09:31:18 -0700 Subject: [PATCH 3/5] Check for array type instead of syntactic `...` --- src/compiler/checker.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index bcf572c6c92f4..e31ae916ccbba 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -21460,7 +21460,7 @@ namespace ts { } else if (lastOrUndefined(getJSDocTags(decl).filter((tag): tag is JSDocParameterTag => isJSDocParameterTag(tag))) === node && node.typeExpression && node.typeExpression.type && - node.typeExpression.type.kind !== SyntaxKind.JSDocVariadicType) { + !isArrayType(getTypeFromTypeNode(node.typeExpression.type))) { error(node.name, Diagnostics.JSDoc_must_appear_on_the_last_param_tag_of_a_function_that_uses_arguments, idText(node.name.kind === SyntaxKind.QualifiedName ? node.name.right : node.name)); @@ -24492,18 +24492,19 @@ namespace ts { const paramTag = parent.parent; if (isJSDocTypeExpression(parent) && isJSDocParameterTag(paramTag)) { // Else we will add a diagnostic, see `checkJSDocVariadicType`. - const param = getParameterSymbolFromJSDoc(paramTag); - if (param) { - const host = getHostSignatureFromJSDoc(paramTag); + const host = getHostSignatureFromJSDoc(paramTag); + if (host) { /* - Only return an array type if the corresponding parameter is marked as a rest parameter. + Only return an array type if the corresponding parameter is marked as a rest parameter, or if there are no parameters. So in the following situation we will not create an array type: /** @param {...number} a * / function f(a) {} Because `a` will just be of type `number | undefined`. A synthetic `...args` will also be added, which *will* get an array type. */ - const lastParamDeclaration = host && last(host.parameters); - if (lastParamDeclaration.symbol === param && isRestParameter(lastParamDeclaration)) { + const lastParamDeclaration = host.parameters.length > 0 && last(host.parameters); + const symbol = getParameterSymbolFromJSDoc(paramTag); + if (!lastParamDeclaration || + symbol && lastParamDeclaration.symbol === symbol && isRestParameter(lastParamDeclaration)) { return createArrayType(type); } } From 24e014d07569f2b25e8ea751f11eff6076d5c096 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 14 Mar 2018 09:49:29 -0700 Subject: [PATCH 4/5] Address PR comments --- src/compiler/checker.ts | 15 +++++++++------ src/compiler/diagnosticMessages.json | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9d2dd28912a34..0e023fc2ac5b9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6755,16 +6755,16 @@ namespace ts { /** * A JS function gets a synthetic rest parameter if it references `arguments` AND: - * 1. It has no parameters and at least one `@param` and the first `@param` has a type and the type starts with `...` + * 1. It has no parameters but at least one `@param` with a type that starts with `...` * OR - * 2. It has at least one parameter, and the last parameter has a matching `@param` with a type and the type starts with `...` + * 2. It has at least one parameter, and the last parameter has a matching `@param` with a type that starts with `...` */ function maybeAddJsSyntheticRestParameter(declaration: SignatureDeclaration, parameters: Symbol[]): boolean { if (!containsArgumentsReference(declaration)) { return false; } const lastParam = lastOrUndefined(declaration.parameters); - const lastParamTags = lastParam ? getJSDocParameterTags(lastParam) : getJSDocTags(declaration).filter((tag): tag is JSDocParameterTag => isJSDocParameterTag(tag)); + const lastParamTags = lastParam ? getJSDocParameterTags(lastParam) : getJSDocTags(declaration).filter(isJSDocParameterTag); const lastParamVariadicType = firstDefined(lastParamTags, p => p.typeExpression && isJSDocVariadicType(p.typeExpression.type) ? p.typeExpression.type : undefined); @@ -21444,17 +21444,20 @@ namespace ts { checkSourceElement(node.typeExpression); if (!getParameterSymbolFromJSDoc(node)) { const decl = getHostSignatureFromJSDoc(node); + // don't issue an error for invalid hosts -- just functions -- + // and give a better error message when the host function mentions `arguments` + // but the tag doesn't have an array type if (decl) { if (!containsArgumentsReference(decl)) { error(node.name, Diagnostics.JSDoc_param_tag_has_name_0_but_there_is_no_parameter_with_that_name, idText(node.name.kind === SyntaxKind.QualifiedName ? node.name.right : node.name)); } - else if (lastOrUndefined(getJSDocTags(decl).filter((tag): tag is JSDocParameterTag => isJSDocParameterTag(tag))) === node && + else if (findLast(getJSDocTags(decl), isJSDocParameterTag) === node && node.typeExpression && node.typeExpression.type && !isArrayType(getTypeFromTypeNode(node.typeExpression.type))) { error(node.name, - Diagnostics.JSDoc_must_appear_on_the_last_param_tag_of_a_function_that_uses_arguments, + Diagnostics.The_last_param_tag_of_a_function_that_uses_arguments_must_have_an_array_type, idText(node.name.kind === SyntaxKind.QualifiedName ? node.name.right : node.name)); } } @@ -24494,7 +24497,7 @@ namespace ts { function f(a) {} Because `a` will just be of type `number | undefined`. A synthetic `...args` will also be added, which *will* get an array type. */ - const lastParamDeclaration = host.parameters.length > 0 && last(host.parameters); + const lastParamDeclaration = lastOrUndefined(host.parameters); const symbol = getParameterSymbolFromJSDoc(paramTag); if (!lastParamDeclaration || symbol && lastParamDeclaration.symbol === symbol && isRestParameter(lastParamDeclaration)) { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index c622cb4b1d7ca..d0e97d188a316 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3720,7 +3720,7 @@ "category": "Error", "code": 8028 }, - "JSDoc '...' must appear on the last @param tag of a function that uses 'arguments'.": { + "The last @param tag of a function that uses 'arguments' must have an array type.": { "category": "Error", "code": 8029 }, From 70af333eec176e1fc19c8f8eb00f63b18ee5a964 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Wed, 14 Mar 2018 09:52:55 -0700 Subject: [PATCH 5/5] Update baselines --- .../reference/paramTagOnFunctionUsingArguments.errors.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/paramTagOnFunctionUsingArguments.errors.txt b/tests/baselines/reference/paramTagOnFunctionUsingArguments.errors.txt index b9cd887cd6603..f9ad715c49b66 100644 --- a/tests/baselines/reference/paramTagOnFunctionUsingArguments.errors.txt +++ b/tests/baselines/reference/paramTagOnFunctionUsingArguments.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/jsdoc/a.js(2,20): error TS8029: JSDoc '...' must appear on the last @param tag of a function that uses 'arguments'. +tests/cases/conformance/jsdoc/a.js(2,20): error TS8029: The last @param tag of a function that uses 'arguments' must have an array type. tests/cases/conformance/jsdoc/a.js(19,9): error TS2345: Argument of type '1' is not assignable to parameter of type 'string'. @@ -8,7 +8,7 @@ tests/cases/conformance/jsdoc/a.js(19,9): error TS2345: Argument of type '1' is /** * @param {string} first ~~~~~ -!!! error TS8029: JSDoc '...' must appear on the last @param tag of a function that uses 'arguments'. +!!! error TS8029: The last @param tag of a function that uses 'arguments' must have an array type. */ function concat(/* first, second, ... */) { var s = ''