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

🐛 Quickfix slows down saving files in VSCode #229

Closed
1 of 3 tasks
jansedlon opened this issue May 29, 2024 · 36 comments
Closed
1 of 3 tasks

🐛 Quickfix slows down saving files in VSCode #229

jansedlon opened this issue May 29, 2024 · 36 comments
Labels
Triage Waiting for response Waiting for a response from the author of the issue

Comments

@jansedlon
Copy link

jansedlon commented May 29, 2024

VS Code version

1.90.0-insiders

Extension version

2.2.3

Biome version

1.7.3

Operating system

  • Windows
  • macOS
  • Linux

Description

When this config is enabled in vscode settings

    "quickfix.biome": "explicit"

it slows down saving files in vscode. But not always 😅. When i type something and immediately hit Cmd + Save, there's like a second delay before the file is saved.

Interestingly enough, if i type something and wait a second and hit save, the file is saved immediately.

Steps to reproduce

  1. Enable "quickfix.biome": "explicit",
  2. Hit Cmd + Save immediately after typing something

Expected behavior

It should save immediately

Does this issue occur when using the CLI directly?

Not sure / Not applicable

Logs

Logs contain actions that happened when i entered "Enter" and immediately save

[Trace - 8:36:03 AM] Sending notification 'textDocument/didChange'.
Params: {
    "textDocument": {
        "uri": "file:///Users/jansedlon/Work/Flixy/flixy/packages/prisma/index.ts",
        "version": 174
    },
    "contentChanges": [
        {
            "range": {
                "start": {
                    "line": 22,
                    "character": 20
                },
                "end": {
                    "line": 22,
                    "character": 20
                }
            },
            "rangeLength": 0,
            "text": "\n  "
        }
    ]
}


[Trace - 8:36:03 AM] Received notification 'textDocument/publishDiagnostics'.
Params: {
    "uri": "file:///Users/jansedlon/Work/Flixy/flixy/packages/prisma/index.ts",
    "diagnostics": [],
    "version": 174
}


[Trace - 8:36:03 AM] Sending request 'textDocument/codeAction - (409)'.
Params: {
    "textDocument": {
        "uri": "file:///Users/jansedlon/Work/Flixy/flixy/packages/prisma/index.ts"
    },
    "range": {
        "start": {
            "line": 0,
            "character": 0
        },
        "end": {
            "line": 95,
            "character": 0
        }
    },
    "context": {
        "diagnostics": [],
        "only": [
            "source.fixAll"
        ],
        "triggerKind": 2
    }
}


[Trace - 8:36:03 AM] Received response 'textDocument/codeAction - (409)' in 1ms.
Result: []


[Trace - 8:36:03 AM] Sending request 'textDocument/codeAction - (410)'.
Params: {
    "textDocument": {
        "uri": "file:///Users/jansedlon/Work/Flixy/flixy/packages/prisma/index.ts"
    },
    "range": {
        "start": {
            "line": 0,
            "character": 0
        },
        "end": {
            "line": 95,
            "character": 0
        }
    },
    "context": {
        "diagnostics": [],
        "only": [
            "source.organizeImports"
        ],
        "triggerKind": 2
    }
}


[Trace - 8:36:03 AM] Received response 'textDocument/codeAction - (410)' in 0ms.
Result: []


[Trace - 8:36:03 AM] Sending request 'textDocument/codeAction - (411)'.
Params: {
    "textDocument": {
        "uri": "file:///Users/jansedlon/Work/Flixy/flixy/packages/prisma/index.ts"
    },
    "range": {
        "start": {
            "line": 0,
            "character": 0
        },
        "end": {
            "line": 95,
            "character": 0
        }
    },
    "context": {
        "diagnostics": [],
        "only": [
            "quickfix.biome"
        ],
        "triggerKind": 2
    }
}


[Trace - 8:36:03 AM] Received response 'textDocument/codeAction - (411)' in 0ms.
Result: []


[Trace - 8:36:03 AM] Sending request 'textDocument/codeAction - (412)'.
Params: {
    "textDocument": {
        "uri": "file:///Users/jansedlon/Work/Flixy/flixy/packages/prisma/index.ts"
    },
    "range": {
        "start": {
            "line": 23,
            "character": 2
        },
        "end": {
            "line": 23,
            "character": 2
        }
    },
    "context": {
        "diagnostics": [],
        "triggerKind": 2
    }
}


[Trace - 8:36:03 AM] Received response 'textDocument/codeAction - (412)' in 1ms.
Result: []


[Trace - 8:36:04 AM] Sending request 'textDocument/formatting - (413)'.
Params: {
    "textDocument": {
        "uri": "file:///Users/jansedlon/Work/Flixy/flixy/packages/prisma/index.ts"
    },
    "options": {
        "tabSize": 2,
        "insertSpaces": true
    }
}


[Trace - 8:36:04 AM] Received response 'textDocument/formatting - (413)' in 2ms.
Result: [
    {
        "range": {
            "start": {
                "line": 0,
                "character": 0
            },
            "end": {
                "line": 96,
                "character": 0
            }
        },
        "newText": "import { remember } from \"@epic-web/remember\";\nimport { handlePrismaLogging, logger } from \"@flixydev/logger\";\nimport { Prisma, PrismaClient, type Subscription } from \"@prisma/client\";\nimport { type Result, ResultAsync, errAsync } from \"neverthrow\";\n\nexport const prisma = remember(\"prisma\", () => {\n  const client = new PrismaClient({\n    log: [\n      {\n        level: \"query\",\n        emit: \"event\",\n      },\n    ],\n  });\n\n  handlePrismaLogging({\n    db: client,\n    logger: logger,\n    logLevels: [\"query\"],\n    slowQueryThresholdMs: 20,\n  });\n\n  client.$connect();\n\n  return client.$extends({\n    result: {\n      user: {\n        stripeActivated: {\n          needs: {\n            stripeConnectAccountId: true,\n            stripeDetailsSubmitted: true,\n          },\n          compute(data) {\n            return (\n              !!data.stripeConnectAccountId && !!data.stripeDetailsSubmitted\n            );\n          },\n        },\n      },\n    },\n    model: {\n      $allModels: {\n        async exists<T>(\n          this: T,\n          where: Prisma.Args<T, \"findFirst\">[\"where\"],\n        ): Promise<boolean> {\n          const context = Prisma.getExtensionContext(this);\n          // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n          const result = await (context as any).findFirst({ where });\n\n          return result !== null;\n        },\n      },\n      user: {\n        async findActiveSubscription(userId: string) {\n          return prisma.subscription.findFirst({\n            where: {\n              userId,\n              status: {\n                in: [\"active\", \"trialing\"],\n              },\n              deletedAt: null,\n            },\n          });\n        },\n        async cancelActiveSubscription(\n          userId: string,\n        ): Promise<Result<Subscription, Error>> {\n          const activeSubscription = await this.findActiveSubscription(userId);\n\n          if (!activeSubscription) {\n            return errAsync(new Error(\"No active subscription found\"));\n          }\n\n          const update = await ResultAsync.fromPromise(\n            prisma.subscription.update({\n              where: {\n                id: activeSubscription.id,\n              },\n              data: {\n                cancelledAt: new Date(),\n              },\n            }),\n            (e) => e as Error,\n          );\n\n          return update;\n        },\n      },\n    },\n  });\n});\n\nexport * from \"@prisma/client\";\n"
    }
]


[Trace - 8:36:04 AM] Sending notification 'textDocument/didChange'.
Params: {
    "textDocument": {
        "uri": "file:///Users/jansedlon/Work/Flixy/flixy/packages/prisma/index.ts",
        "version": 175
    },
    "contentChanges": [
        {
            "range": {
                "start": {
                    "line": 23,
                    "character": 0
                },
                "end": {
                    "line": 24,
                    "character": 0
                }
            },
            "rangeLength": 3,
            "text": ""
        }
    ]
}


[Trace - 8:36:04 AM] Received notification 'textDocument/publishDiagnostics'.
Params: {
    "uri": "file:///Users/jansedlon/Work/Flixy/flixy/packages/prisma/index.ts",
    "diagnostics": [],
    "version": 175
}


[Trace - 8:36:04 AM] Sending notification 'textDocument/didSave'.
Params: {
    "textDocument": {
        "uri": "file:///Users/jansedlon/Work/Flixy/flixy/packages/prisma/index.ts"
    }
}


[Trace - 8:36:04 AM] Sending request 'textDocument/codeAction - (414)'.
Params: {
    "textDocument": {
        "uri": "file:///Users/jansedlon/Work/Flixy/flixy/packages/prisma/index.ts"
    },
    "range": {
        "start": {
            "line": 23,
            "character": 0
        },
        "end": {
            "line": 23,
            "character": 0
        }
    },
    "context": {
        "diagnostics": [],
        "triggerKind": 2
    }
}


[Trace - 8:36:04 AM] Received response 'textDocument/codeAction - (414)' in 1ms.
Result: []
@nhedger
Copy link
Member

nhedger commented May 29, 2024

Do you have other extensions that run actions on save ? - If so, could try disabling them and try again to make sure that the Biome extension is the one causing the delay.

@jansedlon
Copy link
Author

I disabled everything except biome and it was still happening.

PS: hmmm.. Interesting, when everything is disabled, it's still happening, sorry! How's that possible? That configuration should be biome specific?

@nhedger
Copy link
Member

nhedger commented May 29, 2024

What I meant is when you save a file, VS Code will run all "on save" actions, and sometimes other extensions register their own actions which can have an impact.

I see you mentioned using the insiders version of VS Code. Does that also happen in the stable version ?

Also, if you're able to, a link to a reproduction repo would help troubleshooting.

@nhedger nhedger added the Waiting for response Waiting for a response from the author of the issue label May 29, 2024
@colinhacks
Copy link

There appears to be a decent repro in this issue: biomejs/biome#4680

Link: https://github.com/OliverJAsh/biome-vscode-quickfix-import-issue/compare/1.7.3

I've also experienced this in Zod. You can pull down this branch to repro: https://github.com/colinhacks/zod/tree/slow-quickfix

$ gh repo clone colinhacks/zod
$ cd zod
$ git checkout slow-quickfix
$ yarn 
$ code .

I've introduced a formatting issue at the top of src/index.ts. Saving that file in VS Code should trigger the slow quickfixing. Interestingly I get faster fix-on-save with "source.fixAll": "always". Does that behave in a meaningfully different way than "quickfix.biome": "always"?

@ragrag
Copy link

ragrag commented Sep 10, 2024

@nhedger i am experiencing the same issue in .vue files, quick save is very slow (3 second delay) when i have those settings

  "editor.codeActionsOnSave": {
    "quickfix.biome": "explicit"
  },

in extension host output i also see those messages

image

disabling the vue extension or removing those settings makes saving very fast again

@nhedger
Copy link
Member

nhedger commented Sep 10, 2024

Interesting, I'll definitely have a look, thanks for the details.

@emilte
Copy link

emilte commented Sep 12, 2024

I believe I'm experiencing the same thing. Something feels slow, but I have to mention that biome is very new for me still

@leotroche
Copy link

I'm experiencing the same thing in:

Software Versión
VS Code 1.93.1
Extension 2.3.0
Biome 1.9.1
Operating System Windows

I set this setting in my vscode and apparently it works perfect, no lag:

"editor.codeActionsOnSave": {
  // "quickfix.biome": "explicit",
  "source.fixAll.biome": "explicit",
  "source.organizeImports.biome": "explicit"
},

Another thing I noticed is that the "quickfix.biome": "explicit" lag only affects JS, JSX, TS, TSX files.
No lag in CSS files.

@emilte
Copy link

emilte commented Sep 16, 2024

I'm not sure I have understood the difference between these settings, and I can't find clarity in the docs.
May I ask if anyone knows? I have posted a question here #342

@ragrag
Copy link

ragrag commented Sep 16, 2024

I'm experiencing the same thing in:

Software Versión
VS Code 1.93.1
Extension 2.3.0
Biome 1.9.1
Operating System Windows
I set this setting in my vscode and apparently it works perfect, no lag:

"editor.codeActionsOnSave": {
  // "quickfix.biome": "explicit",
  "source.fixAll.biome": "explicit",
  "source.organizeImports.biome": "explicit"
},

Another thing I noticed is that the "quickfix.biome": "explicit" lag only affects JS, JSX, TS, TSX files. No lag in CSS files.

doesn't seem to work (atleast not in vue projects w/vue extension) with same warning in my previous comment

@nhedger
Copy link
Member

nhedger commented Sep 16, 2024

I wasn't able to reproduce using the previously provided reproductions. For those experiencing the same issue right now, please provide a minimal reproduction that triggers it.

@leotroche
Copy link

leotroche commented Sep 17, 2024

https://github.com/leotroche/biome-repro-1726568917139

  1. In the cloned repository you will find the index.js file:

{EB54CAA9-BECF-4C77-AB63-6FB31EBE66DF}

  1. How to activate the bug?
    If you press Enter to make line breaks and quickly press Control + S to save, you will see a delay between the time you save the file and the time the fix is ​​executed

{A159C850-B34B-4094-AE97-2BDCA59EDBF2}

After saving

{EB54CAA9-BECF-4C77-AB63-6FB31EBE66DF}

The bug is present regardless of the biome.json configuration.

Important:
You have to be fast, if you do the line break and wait more than a second before tapping Control + S, you will not see the delay.
I recommend to try it several times.

@mizdra
Copy link

mizdra commented Sep 17, 2024

I have investigated this problem. I hope it is useful.

reproduction repository: https://github.com/mizdra/quickfix-biome-slow

Reproduction Test: Part 1

Apparently, the problem reproduces without any 3rd-party extensions. Surprisingly, it reproduces without biome-vscode.

The workspace used for reproduction is as follows:

.vscode/settings.json:

{
    "editor.codeActionsOnSave": {
        "quickfix.biome": "explicit"
      }
}

index.ts:

function fn(){
    console.log('hello');
}
2024-09-18.0.10.20.mov

This suggests that the problem is caused by something other than the biome-vscode.

Reproduction Test: Part 2

The problem does not seem to reproduce with .css.

The workspace used for reproduction is as follows:

.vscode/settings.json:

{
    "editor.codeActionsOnSave": {
        "quickfix.biome": "explicit"
      }
}

index.css:

.foo {
    background: black;
}
2024-09-18.0.15.42.mov

This suggests that the problem is .ts specific.

Reproduction Test: Part 3

If you disable VS Code's built-in js/ts extension, the problem does not reproduce.

How to disable VS Code's built-in js/ts extension:

  1. Select Side Bar > ... > Show Running Extensions
    • image
  2. Right-click TypeScript and JavaScript Language Features and select Disable
    • image
  3. Restart VS Code
2024-09-18.0.22.29.mov

From these tests, I believe the problem is caused by VS Code, VS Code's built-in js/ts extension (TypeScript and JavaScript Language Features), or tsserver.

I don't think biome-vscode has anything to do with this problem.

@leotroche
Copy link

I confirm the contribution of @mizdra

  • Uninstall biome
  • Install prettier
  • Set this .vscode/settings.json:
{
  "editor.codeActionsOnSave": {
    "quickfix.biome": "explicit"
  },
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode"
}

The problem is still present only in JS and TS files, it does not seem to affect either JSON or CSS

@mizdra
Copy link

mizdra commented Sep 22, 2024

I have investigated this issue further. It appears to be a compatibility issue between typescript-language-features and the Biome extension.

However, I think I need to know about the editor.codeActionsOnSave spec to determine a solution to this problem. Therefore, I have written a question to the VS Code team. You can find it at

@nhedger
Copy link
Member

nhedger commented Sep 22, 2024

Really appreciate the investigation @mizdra, I'll be following along!

@ragrag
Copy link

ragrag commented Sep 22, 2024

it's worth noting that this issue also happens not only with typescript-language-features but also others like .vue and Vue.volar extension in similar fashion.
(issue i already created on official vue tooling repo vuejs/language-tools#4833)

Also from my experiments , replacing quickfix.biome with source.fixAll.biome doesn't fix the issue in those cases

@mizdra
Copy link

mizdra commented Sep 22, 2024

@ragrag You are misunderstanding the problem. This problem is specific to typescript-language-features. The problem occurs because you have enabled both Vue.volar and typescript-language-features. If you enable Vue.volar and disable typescript-language-features, this problem will not occur. Of course, if you disable both, the problem will not occur.

typescript-language-features is not a 3rd-party extension, but a built-in extension of VS Code. To disable typescript-language-features, you need to perform a special operation. For details, please see #229 (comment).

@ragrag
Copy link

ragrag commented Sep 22, 2024

@mizdra what i'm trying to say is that i can confirm that the problem is still reproducible in my case when enabling Vue.volar and disabling typescript-language-features

also disabling Vue.volar and enabling typescript-language-features fixes the issue in my case. thus its not only exclusive (at-least in my case) to some incompatibility with typescript-language-features

@mizdra
Copy link

mizdra commented Sep 22, 2024

@ragrag Really? I couldn't reproduce it.

2024-09-22.23.37.24-1.mov
2024-09-22.23.37.24-2.mov

repo: https://github.com/mizdra/vue-quickfix-biome-test

Have you forgotten to restart VS Code? Even if you press the button to disable the extension, the extension will continue to activate until you restart VS Code. To completely disable the extension, you must restart VS Code.

@ragrag
Copy link

ragrag commented Sep 22, 2024

@ragrag Really? I couldn't reproduce it.

2024-09-22.23.09.13.mov

Have you forgotten to restart VS Code? Even if you press the button to disable the extension, the extension will continue to activate until you restart VS Code. To completely disable the extension, you must restart VS Code.

Yeah i did.

I can reproduce this consistently on multiple medium-sized vue apps residing in a medium sized monorepo.

I can't seem to reproduce it on fresh vue apps so it's hard for me to isolate it and create a minimal repro but i will try when i have some time later

I will atleast try to create a screen capture for demonstration maybe that will help?

@mizdra
Copy link

mizdra commented Sep 22, 2024

@ragrag

I can reproduce this consistently on multiple medium-sized vue apps residing in a medium sized monorepo.

Hmm. That's strange.

I can't seem to reproduce it on fresh vue apps so it's hard for me to isolate it and create a minimal repro but i will try when i have some time later

Yes, it would be helpful if you could create a reproduction. :) I added my reproduction to #229 (comment).

@vlinder
Copy link

vlinder commented Sep 24, 2024

I have this same problem with the quickfix. It appears to me that it is waiting for the typescript check to complete before running. The longer the type checking takes the longer the delay appears to be before it saves the file.
Perhaps there could be a way to move the quickfixing before the type checking, maybe into the formatting step, instead?

@vlechemin
Copy link

I have the same problem, but it seems that source.organizeImports.biome doesnt do anything, that's why it fixes the slowness. Does it fix imports for you?

@vlinder
Copy link

vlinder commented Sep 24, 2024

I have no problems with source.organizeImports.biome. It is the quickfix setting that seems to cause the slowness.

Organize imports only sorts and "organizes" the imports, it does not remove unused imports. That is the biggest reason we did want to use the quickfix setting. To remove unused imports.

The fixAll setting does not seem to have the slow save issue.

@vlechemin
Copy link

biome 1.9.2 fixed source.organizeImports.biome not doing anything :)

@ematipico
Copy link
Member

ematipico commented Sep 24, 2024

Users should start adding the *.biome suffix to the code actions e.g. source.fixAll.biome. This should instruct the clients to only run code actions that belong to Biome. Not adding the suffix e.g. source.fixAll would mean telling the clients to run ALL the code actions of all the language servers that listen to that filter.

If the client (VSCode, Zed, etc.) sends the correct payload, Biome LSP should apply the changes.

@ragrag
Copy link

ragrag commented Oct 5, 2024

is there a guide on how to debug this issue or introspect biome trace logs?

i can reproduce it in a private monorepo but only when opening the full workspace in vscode,
if i have only the vue app folder open in vscode this issue is not happening

@nhedger
Copy link
Member

nhedger commented Nov 30, 2024

I think it's fair to say that this issue is not specific to the biome extension, so I will close it. Feel free to circle back if new information comes to light.

@JavaScriptBach
Copy link

I take it that the underlying issue is being tracked here: microsoft/vscode#232480

Asking the VSCode team to chime in so we can understand the problem is great, but has the Biome team considered re-implementing the LSP with a different incantation, e.g. source.fixAll.biome instead of quickfix.biome? Other language servers like vscode-eslint don't seem to have this issue, so this could be an easy way to sidestep the problem.

This issue is blocking my company from migrating to Biome, which is a bummer because we would otherwise love to use it.

@mizdra
Copy link

mizdra commented Dec 3, 2024

As you say, I think the problem will be solved if Biome uses source.fixAll.biome instead of quickfix.biome.

Then, We need to guide users to modify .vscode/settings.json as follows. But this is a breaking change.

 {
   "editor.codeActionsOnSave": {
-    "quickfix.biome": "explicit"
+    "source.fixAll.biome": "explicit"
   }
   // ...
 }

Even if typescript-language-features delays source.fixAll.ts by 500 ms (see Q3), it will not affect users who use source.fixAll.biome. I don't think Biome will be affected by whatever decision the VS Code development team makes.

@JavaScriptBach
Copy link

I get the reluctance to ship a new major version as a maintainer. All I can say as an interested potential user is that I'd love to see this problem get solved sooner. (We have a large Typescript mono-repo that we unsuccessfully tried to migrate to Biome earlier this year, and it was blocked only by the VSCode extension performance, as the CLI itself is very fast.)

I did some digging in the docs. The LSP protocol doesn't say anything about the distinction between a quickfix and a fixall, except that they are different code actions.

However, the VSCode Typescript docs suggest that "fixall" is the action intended to be used on save because it will compute all the fixes in one round.

By contrast, a quickfix is mentioned as an individual suggestion designed to be handled one at a time, and it seems to be listed as an alternative to a "refactor" code action.

@JavaScriptBach
Copy link

@mizdra would you accept a patch to use source.fixAll.biome if it results in better performance? Trying to see if there's anything I can do here to help move things along.

@mizdra
Copy link

mizdra commented Dec 9, 2024

@JavaScriptBach I am not sure what you mean by "patch." However, you are free to use all the code I used to report this issue and the vscode team. I disclaim their copyright:)

@JavaScriptBach
Copy link

I just saw there is biomejs/biome#3339. Does this mean that source.fixAll.biome was already implemented?

@OliverJAsh
Copy link

source.fixAll.biome seems to work on my end. I think the documentation needs updating.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Triage Waiting for response Waiting for a response from the author of the issue
Projects
None yet
Development

No branches or pull requests