Skip to content

JSDoc ?Type adds optionality to parameters#22646

Merged
sandersn merged 4 commits into
masterfrom
jsdoc-question-adds-optionality
Mar 16, 2018
Merged

JSDoc ?Type adds optionality to parameters#22646
sandersn merged 4 commits into
masterfrom
jsdoc-question-adds-optionality

Conversation

@sandersn
Copy link
Copy Markdown
Member

chrome-devtools-frontend expects that parameters with type ?T (or T?) add null to T and optionality to the parameter. Previously it only added null to the type.

Currently the PR does not add undefined to the type of T, which is expected by chrome-devtools-frontend, but is inconsistent with typescript's rules. The implementation achieves this inconsistency by exploiting the fact that checking the signature adds optionality and checking the parameter adds undefined.

Chrome devtools expects that parameters with type `?T` (or `T?`) add
null to `T` and optionality to the parameter. Previously it only added
null to the type.

Currently the PR does *not* add undefined to the type of
`T`, which is expected by chrome-devtools-frontend, but is inconsistent
with typescript's rules. The implementation achieves this inconsistency by
exploiting the fact that checking the signature adds optionality and
checking the parameter adds `undefined`.
@sandersn sandersn requested review from a user and weswigham March 16, 2018 17:58
Comment thread src/compiler/checker.ts
function isJSDocOptionalParameter(node: ParameterDeclaration) {
function isJSDocOptionalParameter(node: ParameterDeclaration, skipType?: boolean) {
return isInJavaScriptFile(node) && (
node.type && node.type.kind === SyntaxKind.JSDocOptionalType
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might want to comment that this case is only for the parameters of a JSDocFunctionType, otherwise .type should always be TS syntax
Also, why does this one not look for JSDocNullableType too?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added. The comment. See @weswigham's report of our discussion for why skipType is incorrect — I'll push an update shortly.

f(undefined) // should not be allowed
f(1)

/** @param {number?} a */
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This parses to the same node kind as ?number ?

function g(a) {
a = 1
a = null
a = undefined // should not be allowed
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we remove the assignments and return a; presumably that should include undefined, because a might not have been provided?

@weswigham
Copy link
Copy Markdown
Member

Just to remark on what we just discussed in person: On inspection, we're pretty sure the part making ? confer optionality isn't actually required (or even desirable), the other half of the change that fixes postfix = is all that was needed.

Previously isJSDocOptionalParameter was incorrect for types like
`?number=`, which are optional but have JSDocNullableType as their root
type node.
Comment thread src/compiler/checker.ts
isBracketed || !!typeExpression && skipJSDocPrefixTypes(typeExpression.type).kind === SyntaxKind.JSDocOptionalType));
}

function skipJSDocPrefixTypes(type: TypeNode): TypeNode {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In ?!a=, maybe this should be parsed as (?!a)= and this wouldn't be necessary?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I considered that and will look at that next. The reason is that, for ?T= the parser does

  1. parsePostfix
  2. parseNonArrayType
  3. parseJSDocNullableType
  4. parseType
  5. ...
  6. parsePostfix

parsePostfix at step (1) doesn't parse the trailing = in this case like we would want, the one at step (6) does. This might be fixed by changing step (4) to be parseNonArrayType. I'll try that and see what breaks.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In fact, parseJSDocNodeWithType(SyntaxKind.JSDocNonNullable) does this already, so it's probably a mistake that parseJSDocNullableType doesn't.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This breaks the existing parsing test in a way that I think is good (... is no longer allowed in the middle of a type), but I want to test more and maybe revise the parsing of ... too. I'll do that in a separate PR.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, it also changes how tightly ?T binds -- if it's tighter than =, then it's tighter than [] too. So ?T[] is now (T | null)[] where before it was T[] | null.

@sandersn sandersn merged commit 3b6ae85 into master Mar 16, 2018
@ghost ghost deleted the jsdoc-question-adds-optionality branch March 16, 2018 20:48
@microsoft microsoft locked and limited conversation to collaborators Jul 25, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants