-
Notifications
You must be signed in to change notification settings - Fork 12.8k
No error on unmatchable @param
tags
#22510
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Such as when the initializer is not a function, or when the function mentions `arguments` in its body.
@param
tags@param
tags
// @noEmit: true | ||
// @allowJs: true | ||
// @checkJs: true | ||
// @strict: true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this matter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. It was part of my template when generating a bunch of these similar JSDoc bugs. I removed it.
src/compiler/checker.ts
Outdated
@@ -21447,7 +21447,8 @@ namespace ts { | |||
|
|||
function checkJSDocParameterTag(node: JSDocParameterTag) { | |||
checkSourceElement(node.typeExpression); | |||
if (!getParameterSymbolFromJSDoc(node)) { | |||
const decl = getHostSignatureFromJSDoc(node); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getHostSignatureFromJSDoc
looks expensive and we won't use it if the param has a symbol; better to put it in an inner if
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, good idea. It's also called twice -- once in getParameterSymbolFromJSDoc -- but I don't know that it's worthwhile to fix that.
// @Filename: a.js | ||
|
||
/** | ||
* @param {string} first |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This case I'm not so sure about supporting since people will think they're getting typing, when we just throw the type definition away without telling them and accept any
. Instead we could add a better message telling them to use a rest parameter instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rest parameters don't exist in ES5, so the error would only apply to ES2015 and later. And we don't usually know whether a .js file targets ES2015 or later.
As for throwing away typing, I don't think there's much we can do -- maybe a noImplicitAny error instead?
I think it would be easier to error (to info-error?) whenever there's a reference to arguments
. That error would be a lot easier to write, and would apply to both ES2015+ and TS, and should come with an associated quick fix. I'll open a separate issue for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently we require the user to place a dummy-parameter and type it as a rest parameter:
/** @param {...string} x */
function f(x) {
return arguments[0];
}
f(1); // error, 1 is not a string
We could make a codefix to convert @param {string} first
to @param {...string} args
and add the dummy parameter -- we could also stop requiring the dumy parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like that. I'll see how hard it is to get the error for the {string} x
case and then remove it when it's changed to {...string} x
. We can do the code fix later, since @mhegazy wants to get this into 2.8.1.
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.
OK, I improved the error message and type for functions that use |
src/compiler/checker.ts
Outdated
const lastParam = lastOrUndefined(declaration.parameters); | ||
const lastParamTags = lastParam && getJSDocParameterTags(lastParam); | ||
const lastParamTags = lastParam ? getJSDocParameterTags(lastParam) : getJSDocTags(declaration).filter((tag): tag is JSDocParameterTag => isJSDocParameterTag(tag)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(tag): tag is JSDocParameterTag => isJSDocParameterTag(tag)
=== isJSDocParameterTag
src/compiler/checker.ts
Outdated
@@ -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 `...` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment says the first @param
, but we are looping over all of them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. I decided to change the comment in order to continue sharing most of the code here.
src/compiler/checker.ts
Outdated
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)); | ||
const decl = getHostSignatureFromJSDoc(node); | ||
if (decl) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might want to explicitly comment that we decided not to issue errors on @param
tags in invalid locations.
src/compiler/diagnosticMessages.json
Outdated
@@ -3720,6 +3720,10 @@ | |||
"category": "Error", | |||
"code": 8028 | |||
}, | |||
"JSDoc '...' must appear on the last @param tag of a function that uses 'arguments'.": { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sounds like it's complaining about ...
in an invalid location. Would write this backwards: the last tag must have ...
.
src/compiler/checker.ts
Outdated
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 && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(tag): tag is JSDocParameterTag => isJSDocParameterTag(tag)
=== isJSDocParameterTag
. Also, inefficient to filter entire array then take the last element, instead of findLast
.
src/compiler/checker.ts
Outdated
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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lastOrUndefined
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess so. lastOrUndefined
is surprisingly complicated though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could just make the implementation simpler? #22572
No errors and The error reporting in |
The error message currently says |
Or maybe just "The last unmatched I like "JSDoc |
* No errr on unmatchable `@param` tags Such as when the initializer is not a function, or when the function mentions `arguments` in its body. * 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. * Check for array type instead of syntactic `...` * Address PR comments * Update baselines
This is now in release 2.8. |
👍 |
#22577 improves the message. |
Such as when the initializer is not a function, or when the function mentions
arguments
in its body.Fixes #22410
Fixes #22411
This will need to be ported to 2.8 as well.