prettier-plugin-svelte
prettier-plugin-svelte copied to clipboard
"Crash" when used with prettier and eslint
Please see https://github.com/sveltejs/svelte/issues/3550 for details, though is closed there. I copied the original bug report here, thanks
Describe the bug With this template where we want ESLint to co exist with prettier I have 2 problems when the plugins are nebale with this config
As described in the prettier docs this enable ESLint to call prettier
- Lint crashes in the svlte compile - see stack trace
- Prettier fails to format on save the App.svelte file - and error flashes up in the status bar
Logs see stack trace
To Reproduce Uncommented the line aboveand comment the one above it
- Run npm run lint from the command line
- edit the App.svelte and save the file
Expected behavior
- no error and llinter succeeds
- File is reformated via prettier
Stacktraces
Stack trace
$ npm run lint
[email protected] lint C:\projects\svelte-code-cypress-project eslint src/*
ParseError: Expected } 1 | export let name 2 |
3 | {name;name=0} | ^ Occurred while linting C:\projects\svelte-code-cypress-project\src\App.svelte:3 at error$1 (C:\projects\svelte-code-cypress-project\node_modules\svelte\compiler.js:13329:20) at Parser$2.error (C:\projects\svelte-code-cypress-project\node_modules\svelte\compiler.js:13405:10) at Parser$2.eat (C:\projects\svelte-code-cypress-project\node_modules\svelte\compiler.js:13419:19) at mustache (C:\projects\svelte-code-cypress-project\node_modules\svelte\compiler.js:13220:17) at new Parser$2 (C:\projects\svelte-code-cypress-project\node_modules\svelte\compiler.js:13364:22) at Object.parse$1 [as parse] (C:\projects\svelte-code-cypress-project\node_modules\svelte\compiler.js:13495:21) at Object.parse (C:\projects\svelte-code-cypress-project\node_modules\prettier-plugin-svelte\plugin.js:669:51) at Object.parse$2 [as parse] (C:\projects\svelte-code-cypress-project\node_modules\prettier\index.js:10629:19) at coreFormat (C:\projects\svelte-code-cypress-project\node_modules\prettier\index.js:13888:23) at format (C:\projects\svelte-code-cypress-project\node_modules\prettier\index.js:14146:73) npm ERR! code ELIFECYCLE npm ERR! errno 2 npm ERR! [email protected] lint:
eslint src/*
npm ERR! Exit status 2 npm ERR! npm ERR! Failed at the [email protected] lint script. npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in: npm ERR! C:\Users\steve\AppData\Roaming\npm-cache_logs\2019-09-11T17_00_42_583Z-debug.log
Information about your Svelte project:
-
Your browser and the version: (e.x. Chrome 52.1, Firefox 48.0, IE 10) Not relevant - build error
-
Your operating system: (e.x. OS X 10, Ubuntu Linux 19.10, Windows XP, etc) Windows 10 latest 1903
-
Svelte version (Please check you can reproduce the issue with the latest release!) 3.12.1
-
Whether your project uses Webpack or Rollup Roll up
Severity How severe an issue is this bug to you? Is this annoying, blocking some users, blocking an upgrade or blocking your usage of Svelte entirely?
Serious - can't lint or run prettier on svelte files
Additional context Add any other context about the problem here.
I faced with the same issue. Any update on this?
Me too!
It seems like prettier-plugin-svelte
isn't compatible with eslint-plugin-svelte3
via eslint-plugin-prettier
, however meanwhile we can still extend eslint-config-prettier
and call prettier separately from eslint i.e. directly from the editor.
For those using vim and w0rp/ale, this works with let g_ale_linter_aliases = { 'svelte': ['javascript'] }
and let g:ale_fixers = { ..., 'svelte': ['eslint', 'prettier'] }
(eslint as both linter and fixer to get both warnings and fixes). Also with w0rp/ale it replaces the buffer with any log output from prettier on syntax error (!), so open node_modules/prettier-plugin-svelte/plugin.js
and comment out the console.log
line.
I have the same problem, which means I am not using eslint-plugin-prettier
although I would like to. I am also using vim and ALE but have a slightly different workaround; I don't get fixes from eslint, but for me this is perhaps simpler:
let b:ale_linter_aliases = {'svelte': 'javascript'}
let b:ale_linters = ['eslint',]
let b:ale_fixers = ['prettier',]
I haven't got as far as figuring out where to start with a fix for the underlying issue.
Did some debugging, seems like eslint-plugin-svelte3
only extracts JS from the <script>
part and returns this (through eslint-plugin-prettier
) for prettier to parse, meanwhile prettier-plugin-svelte
expects a whole .svelte file to break down into an AST, and crashes.
I'm trying to get this confirmed in the Prettier community but it seems to me like the eslint plugin is at fault here for not sending the whole file, which Prettier is capable of parsing (with the plugin). The JSX in the template part of .svelte files should also be formatted by Prettier, and if we look at eslint-plugin-react
it indeed sends the whole .jsx file through eslint-plugin-prettier
.
I'd like to ask the Svelte community why they say that prettier-plugin-svelte
is wrong (see issue #3550 linked above) + that we should disable eslint-plugin-prettier
when using their eslint plugin. Is it a misunderstanding, or was it just too difficult to implement the eslint plugin differently at the time...?
@torndev I found the same and worked around this in VS Code -
see https://github.com/SteveALee/svelte-code-cypress-project/blob/master/README.md
I created a bug with more details here https://github.com/sveltejs/svelte/issues/3550 but seems it was the wrong place.
Also https://github.com/UnwrittenFun/svelte-vscode/issues/74
Also see
@SteveALee Yeah the answer to sveltejs/svelte#3550 is what's making me confused. It would seem like exactly the right place to resolve the problem. Maybe we can try to get it reopened.
EDIT: In the TypeScript roadmap they already mention separation of the Svelte core from tooling and taking inspiration from Vue, and UnwrittenFun seems involved in this. So focusing on eslint-plugin-prettier
now might be missing the bigger picture.
Thought I'd share my findings so far. Perhaps someone knows more and/or would like to join the search for a solution! I haven't worked with eslint plugins before, I'm just digging in node_modules trying to trace the plugin call order.
We have eslint calling eslint-plugin-svelte3
which has preprocess, postprocess
functions (see Working with Plugins in ESLint's developer guide). preprocess
receives the whole file and calls svelte3/compiler
to generate an AST, and returns a shorter string of pure JS extracted from the script part. This is then forwarded eslint-plugin-prettier -> prettier -> prettier-plugin-svelte
where the latter is expecting a .svelte file and crashes.
The maintainers of eslint-plugin-svelte3
(which is the official plugin maintained by the Svelte team) have pointed at this plugin (prettier-plugin-svelte
) and didn't seem very interested in discussing another approach. But I believe it's the eslint plugin that's not behaving as expected in the big picture.
I haven't used Vue before but I looked into their solution for eslint/prettier because the .vue file structure looks very similar to Svelte's: JSX and script + style + template.
What Vue does, is that eslint first calls vue-eslint-parser
(see ESLint's Working with Custom Parsers), then eslint-plugin-vue: preprocess
which simply returns the entire input, thus the whole .vue file is then sent to their Prettier plugin.
Next step is to determine how hard it would be to move the svelte3/compiler
AST stuff to a separate parser library, and have the plugin be much simpler, just like eslint-plugin-vue
which mostly contains lots of rule definitions and only 70 lines for the actual processors.
The Vue parser & plugin seem to be written by eslint maintainers though, so in the worst case this approach requires support from the main eslint lib.
Also I could only see vue-eslint-parser
being called for files imported by the main .vue file, so it's still unclear where the main file's AST is built.
TL;DR: lots of intrigue simply because I don't know how any of this works... :laughing:
I think that I'm facing the same issue. I'm linting with eslint
taking advantage of the prettier/recommended
rules set. After adding eslint-plugin-svelte3
everything was still working as it should. As soon as I added prettier-plugin-svelte
it stopped. This snippet:
<script>
export let name
</script>
... is causing eslint
to fail with:
npx eslint --fix ./src/**/*.{js,svelte}
Expected }
1 | export let name
2 |
> 3 | {name;name=0}
| ^
Occurred while linting /home/boojum/code/playground/parcel-svelte/src/containers/App/App.svelte:3
Repo with the minimal setup required to reproduce is here. To reproduce, simply run npx eslint --fix ./src/**/*.{js,svelte}
- it will fail with the above error. Then uninstal prettier-plugin-svelte
and run eslint
again - no problems at all.
As stated in the newest Prettier docs, using packages like eslint-plugin-prettier
is no longer recommended. Instead, use a preset configuration which turns off all Eslint rules which conflict with prettier and then just format first with prettier and run the linter afterwards.
As stated in the newest Prettier docs, using packages like
eslint-plugin-prettier
is no longer recommended…
@dummdidumm But only eslint plugins provide "realtime" linting inside the IDE, or not? In my workflow I'm gettung linting errors etc. highlighted while i'm typing. With the plugin I also get prettier "errors" highlighted while typing. It's a thing of preference, but I prefer it this way instead of constantly getting my code reformatted on save e.g.
I'm getting this error, too. It would be really annoying to use Prettier separately because every single non-svelte project has Prettier integrated with ESLint. So Svelte projects are the only projects requiring me to setup extra tooling.
https://stackoverflow.com/questions/66804739/using-prettier-plugins-with-eslint-plugin-prettier?noredirect=1#comment118107753_66804739
The problem is neither eslint-plugin-svelte3
nor prettier-plugin-svelte
, it's eslint-plugin-prettier
not making them play nice together. The problem is that eslint-plugin-svelte3
needs to extract the JS parts of the Svelte file, because ESLint can only run on that. This means that something like export let foo
is passed to prettier-plugin-svelte
, which then throws, because that is invalid Svelte code. Looking at the code it seems that enhancing this line with svelte
may be enough (maybe that list should also be made enhancable through configuration on their side). I suggest you try that out and see if my hunch is correct. I suggest you also open an issue on their side with a reproduction so they can look into it.
@dummdidumm I tried your suggestion and it seems to resolve the crash issue. However the linter still reports false positive errors for prettier/prettier:
<script lang="ts">
interface Foo {
baz: string[];
foo: boolean;
}
export let properties: Foo
</script>
{#if properties.foo}
{#each properties.baz as bar}
<p>
{bar}
</p>
{/each}
{/if}
Foo.svelte
11:12 error Insert `··` prettier/prettier
That is the line: {#each properties.baz as bar}
where eslint/prettier wants to fix it with extra whitepaces between the #each
and properties.baz
which does not help to get rid of the error. It will just keep complaining and --fix will just keep adding more whitespaces as prettier is still not running on the source but the transpiled code given from the eslint-plugin-svelte3
.
From https://github.com/prettier/eslint-plugin-prettier/issues/472#issuecomment-1167337964
It should be easy to fix this by adding
svelte
intohttps://github.com/prettier/eslint-plugin-prettier/blob/551dd0e29840f189df71bfc9bd3fd5aa74f2b8f1/eslint-plugin-prettier.js#L215-L225
Would you like to raise a PR?
I think this can be closed in favor of https://github.com/prettier/eslint-plugin-prettier/pull/483
I think this can be closed in favor of https://github.com/prettier/eslint-plugin-prettier/pull/483
I don't think so, I am still getting this error with the [email protected] and the official eslint-plugin-svelte3:
which doesn't make any sense.
I have not tried this with the recommended eslint-plugin-svelte package yet.