Skip to content

Jsdoc ... binds tighter than postfix ?!#18117

Merged
sandersn merged 8 commits into
masterfrom
jsdoc-dotdotdot-binds-tighter-than-postfix
Oct 3, 2017
Merged

Jsdoc ... binds tighter than postfix ?!#18117
sandersn merged 8 commits into
masterfrom
jsdoc-dotdotdot-binds-tighter-than-postfix

Conversation

@sandersn

@sandersn sandersn commented Aug 29, 2017

Copy link
Copy Markdown
Member

Fixes #18104

  1. Previously ...X? mistakenly parsed as ...(X?) instead of (...X)?
  2. Previously X?!?!? mistakenly failed to parse the postfix tokens
    ? ! ? ! ? at the same level of precedence.

The fix is to

  1. Make ... parsing call parseNonArrayType instead of parseType.
  2. Combine postfix jsdoc parsing into the postfix array loop instead of only parsing one token.

1. Previously ...X? mistakenly parsed as ...(X?) instead of (...X)?
2. Previously X?!?!? mistakenly failed to parse the postfix tokens
   ? ! ? ! ? at the same level of precedence.

The fix is to
1. Make ... parsing call parseNonArrayType instead of parseType.
2. Make postfix jsdoc parsing parse in a loop instead of only parsing
one token.

@weswigham weswigham left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Certainly an improvement - do we have tests covering cases like ...foo[], ...foo?[]!, and ...foo![]? (mostly so we know what they parse to)?

This combines parseArrayType and parseJSDocPostfixType into
parsePostfixType.
@sandersn

Copy link
Copy Markdown
Member Author

Good idea. Those tests failed to parse the trailing postfix jsdoc type, so I combined parseJSDocPostfixType and parseArrayType into parsePostfixType. Now these postfix syntaxes are all parsed at the same level of precedence. Mind taking a look?

@DanielRosenwasser

Copy link
Copy Markdown
Member

I don't know how to read the title of this issue without laughing.

Comment thread src/compiler/parser.ts Outdated
function parsePostfixTypeOrHigher(): TypeNode {
let kind: SyntaxKind | undefined;
let type = parseNonArrayType();
while (!scanner.hasPrecedingLineBreak() && (kind = getPostfixTypeKind(token()))) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do an explicit === undefined check here because who knows what a SyntaxKind of 0 is.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Potentally just move the defined-ness check into the body.

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.

who knows what a SyntaxKind of 0 is

SyntaxKind.Unknown

(good idea, I'll switch to an undefined check)

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.

Actually, returning 0 is even better since 0 is falsy too.

Comment thread src/compiler/parser.ts Outdated
case SyntaxKind.QuestionToken:
return SyntaxKind.JSDocNullableType;
case SyntaxKind.OpenBracketToken:
return SyntaxKind.ArrayType;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is slightly misleading - in actuality, you are potentially parsing out an IndexedAccessTypeNode. Is it fair to say that this function determines gives you a JSDocPostfixType, a TypeScriptPostfixType, or None?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What if you just inlined this switch/case to the function itself?

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.

Inlining makes the jsdoc cases really inconvenient because the mapping between tokens and jsdoc types has to happen in the switch, but the createNode code is shared between all three. I could separate out just the token → jsdoc-type mapping code, but that would essentially duplicate the switch.

@sandersn

sandersn commented Sep 6, 2017

Copy link
Copy Markdown
Member Author

@DanielRosenwasser can you take another look?

Comment thread src/compiler/parser.ts Outdated
switch (tokenKind) {
case SyntaxKind.EqualsToken:
// only parse postfix = inside jsdoc, because it's ambiguous elsewhere
return contextFlags & NodeFlags.JSDoc ? SyntaxKind.JSDocOptionalType : 0;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If you are trying to prevent boxing, there's a SyntaxKind.Unknown

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 was trying to prevent boxing and SyntaxKind.Unknown at the same time. Actually, there's not much point, because 0 requires a falsy check later, and functions automatically union their return types these days. I might as well return false here.

Inline the switch, but extract the function that creates jsdoc nodes.
@sandersn

sandersn commented Sep 7, 2017

Copy link
Copy Markdown
Member Author

Thanks to some discussion with @rbuckton, I inlined the switch into parsePostfixTypeOrHigher. Care to take another look @DanielRosenwasser ?

@sandersn

sandersn commented Sep 7, 2017

Copy link
Copy Markdown
Member Author

Travis failed because my quickfix-fix now reports more fixes in a fourslash test that has precedence changes from this PR. I need to merge from master and update the test.

@sandersn

sandersn commented Sep 8, 2017

Copy link
Copy Markdown
Member Author

OK, I merged from master and updated the new test.

@sandersn sandersn merged commit 4d8663c into master Oct 3, 2017
@sandersn sandersn deleted the jsdoc-dotdotdot-binds-tighter-than-postfix branch October 3, 2017 15:45
@microsoft microsoft locked and limited conversation to collaborators Jun 14, 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.

Question on JSDoc array type precedence with '!' and '?'

5 participants