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

Print trailing comma after a single TS generic in arrow fns #14113

Merged
merged 5 commits into from Jan 10, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/babel-generator/src/generators/typescript.ts
Expand Up @@ -15,6 +15,7 @@ export function TSTypeParameterInstantiation(
): void {
this.token("<");
this.printList(node.params, node, {});
if(node.extra?.trailingComma) this.token(",");
Copy link
Member

Choose a reason for hiding this comment

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

Thanks for that PR!
I think it would be safer to always print the comma if node.params.length === 1, so that it also works when the node has been modified/generated by a plugin. For example:
https://astexplorer.net/#/gist/ef9b1bdad45421b25b826a06f3a707e1/latest

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If I do it like that, now generator starts adding comma end of every conditional node.params.length === 1 type inside every angle bracket. But some of those usages are not compatible with typescript, such as this one.

// IN
// *****************************************************

const useState = <T>(x: T): T => x;

const foo = <T>(a: T) => {
  const x = useState<number>(2);
};


// OUT
// *****************************************************

const useState = <T,>(x: T): T => x;

const foo = <T,>(a: T) => {
  const x = useState<number,>(2); // now this becomes incompatible due to <number,>
};

Or am I missing something?

Copy link
Member

Choose a reason for hiding this comment

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

Oh true. TSTypeParameterInstantiation is called with an additional argument, parent: t.Node: you can check if parent.type === "ArrowFunctionExpression".

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We also need to find the type of FunctionDeclaration right?

function foo<T>(a: T) {} // AST says this is ArrowFunctionExpression (init type)
const foo= <T>(x: T): T => x; // and says this is FunctionDeclaration (type)

They both should be generated with at least one comma inside their angle brackets.

Copy link
Member

Choose a reason for hiding this comment

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

I don't think the first one needs a trailing comma, because it's not ambiguous with JSX.

Copy link
Member

Choose a reason for hiding this comment

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

If you are interested, I have another bug for you which can be fixed after that this PR is merged (we first need a second review)!

We currently parse <T>() => {} without problems even when both the JSX and TypeScript plugins are enabled. If there is a single type parameter and there isn't a trailing comma, we should report a parser error. It can probably be reported in

parseMaybeAssign(...args): N.Expression {
, using this.raise (see how it's used in other parts of that file). OVERWRITE=true yarn jest parser will then probably update some existing (wrong) tests: I would be surprised if we need new tests for this.

(Note: that function is probably one of the most complex parser functions 😬)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Absolutely, I want to work on this case. please assign it to me.
When do you think other reviewer can review this PR?

Copy link
Member

Choose a reason for hiding this comment

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

Probably @JLHwung or @existentialism can review this tomorrow or on Monday.

I haven't created an issue for that bug; feel free to consider it assigned to you and just link my comment in the new PR 🙂

Btw, you don't need to wait for this to be merged because it's a parser bug, but you will then need to rebase your new PR after that this is merged to check if any related @babel/generator tests need to be merged.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Absolutely, will start to work on it ASAP. Thanks @nicolo-ribaudo

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If you are interested, I have another bug for you which can be fixed after that this PR is merged (we first need a second review)!

We currently parse <T>() => {} without problems even when both the JSX and TypeScript plugins are enabled. If there is a single type parameter and there isn't a trailing comma, we should report a parser error. It can probably be reported in

parseMaybeAssign(...args): N.Expression {

, using this.raise (see how it's used in other parts of that file). OVERWRITE=true yarn jest parser will then probably update some existing (wrong) tests: I would be surprised if we need new tests for this.
(Note: that function is probably one of the most complex parser functions 😬)

Hi @nicolo-ribaudo
I start to work on this bug today, will quote reply once I create a PR

this.token(">");
}

Expand Down
@@ -0,0 +1,2 @@
// Verify typescript doesn't change anything inside type angel brackets
const foo = <T,>(a: T): T => a;
@@ -0,0 +1,3 @@
{
"plugins": ["jsx", "typescript"]
}
@@ -0,0 +1,2 @@
// Verify typescript doesn't change anything inside type angel brackets
const foo = <T,>(a: T): T => a;