jscheid / prettier.el

Prettier code formatting for Emacs.
GNU General Public License v3.0
164 stars 11 forks source link

Unexpected Token with Typescript type assertion in JSX files #37

Closed btoconnor closed 3 years ago

btoconnor commented 3 years ago

Describe the bug When using prettier.el with a typescript file (.tsx extension), I get an error with something like "SyntaxError: Unexpected token, expected "}" (55:32)"

Link to M-x prettier-info output https://gist.github.com/btoconnor/5cff712d5a20c7583c797137387d34ba (this has some filepath redactions - let me know if i removed something important.

To Reproduce Using a project with Typescript tsx files, save. Receive the following errors:

<filepath>Layout.tsx: SyntaxError: Unexpected token, expected "}" (55:32)
  53 |             <Component
  54 |                 currentUserId={currentOccupant.user.id}
> 55 |                 game={room.game! as MyObject}
     |                                ^
  56 |                 // other stuff
  57 |             />
  58 |         );

It seems to work fine with files that don't contain !.

Expected behavior I expect prettier.el to be able to format these files without syntax errors.

Additional context Running yarn prettier on the same file produces output without erroring. It's unclear to me why prettier.el is not working properly on this file.

I have run prettier.el on .ts files with type assertions, and it works fine. It seems to be isolated to just .tsx files.

I am almost positive I have this configured improperly. I'm just looking to get unstuck on files that contain non-null assertion operators.

Let me know if I can provide anymore information.

I'm wondering if this has to do with prettier.el's attempt at figuring out the file type from the major mode? I'm using web-mode for tsx, but typescript-mode for .ts files.

jscheid commented 3 years ago

Thanks for the bug report, I can confirm prettier.el doesn't detect the correct parser when used with web-mode for typescript files. I'll try and take a look at fixing this soon.

As a workaround you can set prettier-parsers explicitly, something like the following:

(add-hook
 'web-mode-hook
 (lambda ()
   (when (string-match "\.tsx?$" buffer-file-name)
     (setq-local prettier-parsers '(typescript)))))

For what it's worth, I'm using typescript-mode (instead of web-mode) for tsx files myself, with good results. That's working fine with prettier.el, without any workarounds.

btoconnor commented 3 years ago

Thanks for confirming. I will give typescript-mode a shot - I thought I had tried it in the past and it wasn't working well, but always worth another shot.

jscheid commented 3 years ago

Yeah give it a try. I'm using Emacs 27.1 though -- not sure if it works as well in 26.3.

jscheid commented 3 years ago

Also, prettier.el should detect the parser correctly in web-mode if you setup tide-mode for web-mode.

btoconnor commented 3 years ago

Ah - yeah - I'm using lsp-mode not tide-mode with typescript. typescript-mode might do the trick in the meantime (web-mode seems a little better - or maybe I'm just used to it) - so it would be nice to have the bug fixed, but there's no urgency on my end.

jscheid commented 3 years ago

I'll take a look sometime soon. Did you get a chance to try the workaround? It should let you use web-mode for now.

btoconnor commented 3 years ago

Sorry about the delay - I just tested this on my project. This appears to solve my problem and I can use web-mode with .tsx files. Appreciate the help!

claytonrcarter commented 3 years ago

Hi, FWIW I had a similar issue which may be related. I am working w/ .vue files in vue-mode, which uses mmm to use multiple major modes in different parts of a file. If I had the point outside of the template/script/style tags, it would correctly format for vue. If I had it inside the template tag, it would format for html; inside the the script tag, it would format JS (which would cause a "SyntaxError: Unexpected token" like @btoconnor experience); and inside the style tag, it would format for CSS.

Results of eval'ing (prettier--parsers) in various parts of file:

Outside any tag/top level: (vue)
Inside <template>: (html)
Inside <script>: (babel flow babel-flow)
Inside <script>: (css)

I'm using use-package, so I added a :hook which seems to work as a workaround:

(use-package vue-mode
  :after lsp-mode
  :mode "\\.vue$"
  :hook
  ((vue-mode . (lambda ()
                 (when (string-match "\.vue$" buffer-file-name)
                   (setq-local prettier-parsers '(vue)))))))

This causes (prettier--parsers) to return (vue) for all parts of the file, as expected.

jscheid commented 3 years ago

Fixes for these two bugs have landed in 20201113.1038. Thanks for reporting these, let me know how you go.

@btoconnor I've decided to fix this by looking at (lsp-buffer-language) rather than file extension.

@claytonrcarter I wasn't aware that vue-mode sits on top of mmm-mode. It should work better now. It made me wonder how well piecewise prettification might work for mmm-modes that do not have holistic support from prettier, such as noweb. I might experiment a bit with this idea.

btoconnor commented 3 years ago

Just confirmed this is working for me. Thanks for fixing this (and for the quick workaround in the meantime)!

arjan commented 3 years ago

Yes, thanks!!

claytonrcarter commented 3 years ago

Working for me, too! Thanks for the quick fix!