Skip to content
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

Handle exception in needs parens with optional chaining #16500

Conversation

syi0808
Copy link
Contributor

@syi0808 syi0808 commented Jul 22, 2024

Description

This PR is just an exception handling that determines that parentheses are necessary when there is tagged template expression and optional chaining.

Fix: #16455

Checklist

  • I’ve added tests to confirm my change works.
  • (If changing the API or CLI) I’ve documented the changes I’ve made (in the docs/ directory).
  • (If the change is user-facing) I’ve added my changes to changelog_unreleased/*/XXXX.md file following changelog_unreleased/TEMPLATE.md.
  • I’ve read the contributing guidelines.

Try the playground for this PR

@fisker
Copy link
Member

fisker commented Jul 22, 2024

Prettier pr-16500
Playground link

--parser babel

Input:

(getConsoleLog?.())``

Output:

getConsoleLog?.()``;

Second Output:

SyntaxError: Tagged Template Literals are not allowed in optionalChain. (1:1)
> 1 | getConsoleLog?.()``;
    | ^
  2 |

@syi0808
Copy link
Contributor Author

syi0808 commented Jul 22, 2024

In addition to the case you mentioned, i considered a few more exceptional cases.

@fisker
Copy link
Member

fisker commented Jul 23, 2024

Moved to shouldAddParenthesesToChainElement ac50078

@fisker
Copy link
Member

fisker commented Jul 23, 2024

There are two other cases need to fix.

(a?.b)!``;

(a?.b!)``;

Can you try to fix them?

@syi0808
Copy link
Contributor Author

syi0808 commented Jul 23, 2024

There are two other cases need to fix.

(a?.b)!``;

(a?.b!)``;

Can you try to fix them?

Okay. I will try this.

@syi0808
Copy link
Contributor Author

syi0808 commented Jul 23, 2024

@fisker
I have added exception handling.
But there are many cases (about 3) and it's too complicated to remove the duplication.
Would this implementation be okay now?

@fisker
Copy link
Member

fisker commented Jul 23, 2024

Looks good, I'll take another look later.

Copy link
Member

@fisker fisker left a comment

Choose a reason for hiding this comment

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

@syi0808
Copy link
Contributor Author

syi0808 commented Jul 24, 2024

Please add a changelog entry https://github.com/prettier/prettier/blob/main/CONTRIBUTING.md#pull-requests

I added changelog. But what should I do about duplication error in lint? Should I combine js and ts changelog?

Copy link
Member

@fisker fisker left a comment

Choose a reason for hiding this comment

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

Good job, thanks.

@fisker fisker marked this pull request as draft July 26, 2024 18:49
@fisker
Copy link
Member

fisker commented Jul 26, 2024

@syi0808

Looks like I found 4 cases that failed

((a?.b!)())``;
((a?.b)!())``;
((a?.())!())``;
((a?.()!)())``;

@fisker
Copy link
Member

fisker commented Jul 26, 2024

But should not related to tagged template literals.

Prettier pr-16500
Playground link

--parser babel-ts

Input:

(a?.b!)()

Output:

a?.b!();

This is wrong, it changed the call to optional chainning.

But we format

(a?.b!).c

correctly, so we missed some checks for babel parser, can you try to fix? (Can be separate PR, since it's different case)

@fisker
Copy link
Member

fisker commented Jul 26, 2024

Maybe it's here

(parent.type === "TSNonNullExpression" &&
grandparent.type === "MemberExpression" &&
grandparent.object === parent))

@fisker
Copy link
Member

fisker commented Jul 26, 2024

Also, can you move these tests to chain-expression? Because I feel we are doing things wrong in for the NewExpressions too, we need the same tests for NewExpressions, after this get merged.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining#invalid_optional_chaining

@syi0808
Copy link
Contributor Author

syi0808 commented Jul 27, 2024

correctly, so we missed some checks for babel parser, can you try to fix? (Can be separate PR, since it's different case)

Separating PR may reduce the scope of work and make it easier to manage, but this actually seems to be handling with the exception of chain expression not only related to tagged template literals. I'll fix it soon.

Also, can you move these tests to chain-expression? Because I feel we are doing things wrong in for the NewExpressions too, we need the same tests for NewExpressions, after this get merged.

I'll move test. and we can also move new expression also into chain expression in this pr?

@syi0808
Copy link
Contributor Author

syi0808 commented Jul 27, 2024

But should not related to tagged template literals.

Prettier pr-16500 Playground link

--parser babel-ts

Input:

(a?.b!)()

Output:

a?.b!();

This is wrong, it changed the call to optional chainning.

But we format

(a?.b!).c

correctly, so we missed some checks for babel parser, can you try to fix? (Can be separate PR, since it's different case)

I modified existing implementation it to cover this.

@syi0808 syi0808 force-pushed the fix/tagged-template-expression-with-optional-chaining branch from 2a29e60 to e004478 Compare July 27, 2024 05:12
@fisker
Copy link
Member

fisker commented Jul 27, 2024

we can also move new expression also into chain expression in this pr?

Let's not make this huge. We don't know what we will face. I'm going to merge this first.

@fisker fisker marked this pull request as ready for review July 27, 2024 07:04
@fisker
Copy link
Member

fisker commented Jul 27, 2024

Would like to continue work on this?

In next PR, we duplicate tests in this PR. And change

For NewExpression

- ... ``;
  new ...;

For MemberExpression (second one make sure we checking .object not .property)

- ... ``;
  ... . foo;
  foo [...];

For CallExpression (second one make sure we checking .callee not .arguments)

- ... ``;
  ... (foo);
  foo(...);

@fisker fisker merged commit 4a39c11 into prettier:main Jul 27, 2024
27 checks passed
@fisker fisker changed the title fix: handle exception in needs parens with optional chaining Handle exception in needs parens with optional chaining Jul 27, 2024
@syi0808
Copy link
Contributor Author

syi0808 commented Jul 27, 2024

Would like to continue work on this?

In next PR, we duplicate tests in this PR. And change

For NewExpression

- ... ``;
  new ...;

For MemberExpression (second one make sure we checking .object not .property)

- ... ``;
  ... . foo;
  foo [...];

For CallExpression (second one make sure we checking .callee not .arguments)

- ... ``;
  ... (foo);
  foo(...);

Thank you for organizing. I'll research this and submit PR soon.

@fisker
Copy link
Member

fisker commented Jul 27, 2024

After we add/fix all tests.

We need rewrite the existing logic, currently it's a mess.

The logic should be:

  1. Check if it's root element of ChainExpression (Need two version, one for babel, one for estree)
  2. Skip TSNonNullExpession
  3. Check if it's TemplateLiteral.tag / NewExpression.callee / CallExpression.callee / MemberExpression.object

This can be done in the followup PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Parenthesized optional chain in template tag should not remove parentheses
2 participants