biomejs / biome-vscode

Biome extension for Visual Studio Code and VSCodium
https://marketplace.visualstudio.com/items?itemName=biomejs.biome
Apache License 2.0
183 stars 21 forks source link

🐛 Quickfix slows down saving files in VSCode #229

Open jansedlon opened 3 months ago

jansedlon commented 3 months ago

VS Code version

1.90.0-insiders

Extension version

2.2.3

Biome version

1.7.3

Operating system

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 commented 3 months ago

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 commented 3 months ago

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 commented 3 months ago

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.

colinhacks commented 3 months ago

There appears to be a decent repro in this issue: https://github.com/biomejs/biome-vscode/issues/214

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"?