ast-grep-vscode
ast-grep-vscode copied to clipboard
[bug] incorrect AST for TSX
I'm having issues with the code in the playground below - I've tried to do a minimal repro but unfortunately couldn't really pinpoint the issue.
The problem is that this error does not appear in the playground. Yet when I use ast-grep TS API - it produces an incorrect AST.
I also have the same issue when using VSCode extension - I'm using [email protected]
⏯ Playground Link
🙁 Actual behavior
The error is that searching for export default $A pattern produces no results - the issue seems to be with the const defined on line 18. Instead of being represented a single lexical declaration all its children nodes get dumped into the root node which causes AST eventually to report an error which prevents it from detecting a default export.
I was able to pinpoint the issue to line 94 - if you remove all 3 & from the className the error disappears. But deleting everything below line 153 works too.
I could provide a repo link if that would help - this could be an issue with tsx gramar, not ast-grep but given that I have the error with API/VSCode extension but not in playground I would assume all of them use the same grammar and thus the issue is with ast-grep. If there's any other info I could provide please let me know
Hi @HugeLetters , can you try the query
ast-grep -p 'export default $A' src/pages/scan.tsx
# or
ast-grep -p 'export default $A'
in your terminal?
Also, what's your extension version, OS and its version, VSCode version?
@HerringtonDarkholme running the command also gives nothing. Btw I could fix the error by just wrapping className in {} so it's not a critical problem for me.
VSCode extension - @0.1.3 OS - Ubuntu 22.04.04 VSCode - 1.87.2
Also using tree-sitter for node directly has the same issue so maybe the error is outside of ast-grep scope - I'm curious why it works in the playground though
I do believe this is a tree-sitter problem.
This is the minimal reproduction I can give. @HugeLetters would you like to submit a ticket to tree-sitter-typescript? Thanks!
const Page = () => (
<div
className="relative isolate flex w-full touch-pan-y touch-pinch-zoom flex-col items-center justify-end gap-6 overflow-x-hidden px-10"
>
<div
id={'13'}
className="!absolute -z-10 flex size-full justify-center [&>video]:!w-auto [&>video]:max-w-none [&>video]:!shrink-0"
/>
</div>
);
Page.x = {};
export default Page;
Deleting any tailwind class will invalidate the repro, curiously.
@HerringtonDarkholme yeah, sure, I will submit it to them
Thanks to yours example I could trim down the repro to this
const A = () => (
<>
<d c="&>v]" />
</>
);
export default A;
I've tried to run this with tree-sitter CLI directly and it also doesn't have this problem :|
I'm not sure where I should submit this problem at this point
Would you like to check the version of tre-sitter-typescript? ast-grep uses 0.20.5
Yup, same
this is what I got
(ERROR (identifier) parameters: (formal_parameters) (jsx_opening_element) (jsx_element open_tag: (jsx_opening_element name: (identifier) attribute: (jsx_attribute (property_identifier)) (ERROR)) (jsx_text) (ERROR) close_tag: (jsx_closing_element)) (jsx_text))
@HugeLetters how are you using tree-sitter-typescript? I cannot figure out a way to run typescript-tsx instead of typescript.
the tree-sitter parse only does the TS parse not tsx.
I've tried to run this with tree-sitter CLI directly and it also doesn't have this problem :|
I'm pretty sure this is because you are using typescript instead of tsx.
Also using tree-sitter for node directly has the same issue so maybe the error is outside of ast-grep scope
the tree-sitter for node should reflect the correct usage.
@HerringtonDarkholme
pnpm i -g tree-sitter-cli
pnpm i tree-sitter-typescript
cd ./node_modules/tree-sitter-typescript/tsx
tree-sitter build
tree-sitter parse ~/<path>/scan.tsx
outputs
(program [0, 0] - [7, 0]
(lexical_declaration [0, 0] - [4, 2]
(variable_declarator [0, 6] - [4, 1]
name: (identifier [0, 6] - [0, 7])
value: (arrow_function [0, 10] - [4, 1]
parameters: (formal_parameters [0, 10] - [0, 12])
body: (parenthesized_expression [0, 16] - [4, 1]
(jsx_element [1, 2] - [3, 5]
open_tag: (jsx_opening_element [1, 2] - [1, 4])
(jsx_self_closing_element [2, 4] - [2, 18]
name: (identifier [2, 5] - [2, 6])
attribute: (jsx_attribute [2, 7] - [2, 15]
(property_identifier [2, 7] - [2, 8])
(string [2, 9] - [2, 15]
(string_fragment [2, 10] - [2, 14]))))
close_tag: (jsx_closing_element [3, 2] - [3, 5]))))))
(export_statement [6, 0] - [6, 17]
value: (identifier [6, 15] - [6, 16])))
It looks close to the tree produced by ast-grep playground but there're some minor differences around the fragment opening and closing tags
Tried to run it with typescript instead of tsx and I get a different errors from yours
(program [0, 0] - [7, 0]
(lexical_declaration [0, 0] - [6, 17]
(variable_declarator [0, 6] - [0, 7]
name: (identifier [0, 6] - [0, 7]))
(ERROR [0, 8] - [6, 16]
parameters: (formal_parameters [0, 10] - [0, 12])
(ERROR [1, 3] - [6, 14]
(type_parameters [2, 4] - [3, 5]
(ERROR [2, 5] - [2, 6]
(identifier [2, 5] - [2, 6]))
(type_parameter [2, 7] - [2, 15]
name: (type_identifier [2, 7] - [2, 8])
value: (default_type [2, 8] - [2, 15]
(literal_type [2, 9] - [2, 15]
(string [2, 9] - [2, 15]
(string_fragment [2, 10] - [2, 14])))))
(ERROR [2, 16] - [3, 4])))
(identifier [6, 15] - [6, 16]))))