-
-
Notifications
You must be signed in to change notification settings - Fork 5.8k
Fix JSXIdentifier handling in isReferencedIdentifier
#17503
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
|
Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/59905 |
| if (path.parentPath.isUpdateExpression()) continue; | ||
| // It will be handled after transforming the loop | ||
| if (path.parentPath.isFor({ left: path.node })) continue; | ||
| if (path.parentPath.isForXStatement({ left: path.node })) continue; |
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 is caught by the new typing because left does not present in ForStatement node. Here we can narrow isFor to isForXStatement.
| this: NodePath, | ||
| opts?: Opts<VirtualTypeAliases["Flow"]>, | ||
| ): this is NodePath<t.Flow>; | ||
| isExpression(this: NodePath): this is NodePath<t.Expression>; |
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.
The opts parameter is removed to align with the implementation.
| } | ||
|
|
||
| // check if node is referenced | ||
| return nodeIsReferenced(node, parent, this.parentPath.parent); |
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.
Previously this branch also handles the JSXIdentifier-in-JSXMemberExpression case, however at this point the opts are no longer checked against the JSXIdentifier node, so NodePath(<A.B/>).get(path to A).isReferencedIdentifier({ name: "NotA" }) would incorrectly return true. This is also fixed in the new implementation.
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.
Could you update the PR title so that it properly describes this in the changelog?
|
commit: |
is* and assert* helpers typingJSXIdentifier handling in isReferencedIdentifier
| opts?: Options<VirtualTypeAliases["ReferencedIdentifier"]>, | ||
| ): boolean { | ||
| const { node, parent } = this; | ||
| if (!isIdentifier(node, opts) && !isJSXMemberExpression(parent, opts)) { |
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.
Previously we passed opts to isJSXMemberExpression, which will always return false when opts is e.g. { name: "foo" } because the JSXMemberExpression does not have a name property. This is fixed in the new implementation.
|
|
||
| for (const type of [...t.TYPES].sort()) { | ||
| output += `is${type}(this: NodePath, opts?: Opts<t.${type}>): this is NodePath<t.${type}>;`; | ||
| output += `is${type}(this: NodePath): this is NodePath<t.${type}>;`; |
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.
Here we provided an overload signature, because otherwise TS will throw
TS2684: The 'this' context of type 'NodePath | NodePath | NodePath | NodePath<...> | NodePath<...> | NodePath<...>' is not assignable to method's 'this' of type 'NodePath'.
Type 'NodePath' is not assignable to type 'NodePath'.
Property 'expression' is missing in type 'ClassMethod' but required in type 'ArrowFunctionExpression'.
in line 1114
babel/packages/babel-traverse/src/scope/index.ts
Lines 1103 to 1114 in 092d2e2
| if ( | |
| !init && | |
| !unique && | |
| (kind === "var" || kind === "let") && | |
| path.isFunction() && | |
| // @ts-expect-error ArrowFunctionExpression never has a name | |
| !path.node.name && | |
| isCallExpression(path.parent, { callee: path.node }) && | |
| path.parent.arguments.length <= path.node.params.length && | |
| isIdentifier(id) | |
| ) { | |
| path.pushContainer("params", id); |
I think we may have to do it for the t.is* helpers as well.
| // Signature overload to avoid issues like https://github.com/babel/babel/pull/17503#discussion_r2325598609 | ||
| `export function is${type}(node: t.Node | null | undefined): ${result};`, | ||
| `export function is${type}<Opts extends Options<t.${type}>>(node: t.Node | null | undefined, opts?: Opts | null): ${resultWithOpts};`, | ||
| `export function is${type}<Opts extends Options<t.${type}>>(node: t.Node | null | undefined, opts?: Opts | null): ${resultWithOpts} { |
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 last one can probably just return boolean now, since its type is not actually exposed externally but only used to check the return type.
(NodePath("<div.A>").get(path to div).isReferencedIdentifier({ name: "div" })returnsfalsewhileNodePath("<div.A>").get(path to div).isReferencedIdentifier()returnstrue.In this PR we improved the
is*andassert*helper typings: The assertion type is now narrowed by the providedoptionskey, given that theoptionskey is a partial AST match. We also excluded thetypeproperty in theoptionskey since it makes no sense to providetypein the isHelper: e.g.t.isFor(node, { type: "ForStatement" })should have beent.isForStatement(node).The improved typings yields better helper usage in the codebase and we can remove a few
@ts-expect-error.Also fixed a
isReferencedIdentifierimplementation bug where we passedoptsto the parent AST helper. Previously it will yield very confusing behaviour as mentioned above and I think it should be fixed in a patch release.