Explorar el Código

feat: eslint lsp (#1744)

Aiden Cline hace 6 meses
padre
commit
1954b59167

+ 60 - 0
packages/opencode/src/lsp/server.ts

@@ -65,6 +65,66 @@ export namespace LSPServer {
     },
   }
 
+  export const ESLint: Info = {
+    id: "eslint",
+    root: NearestRoot([
+      "eslint.config.js",
+      "eslint.config.mjs",
+      "eslint.config.cjs",
+      "eslint.config.ts",
+      "eslint.config.mts",
+      "eslint.config.cts",
+      ".eslintrc.js",
+      ".eslintrc.cjs",
+      ".eslintrc.yaml",
+      ".eslintrc.yml",
+      ".eslintrc.json",
+      "package.json",
+    ]),
+    extensions: [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".mts", ".cts"],
+    async spawn(app, root) {
+      const eslint = await Bun.resolve("eslint", app.path.cwd).catch(() => {})
+      if (!eslint) return
+      const serverPath = path.join(Global.Path.bin, "vscode-eslint", "server", "out", "eslintServer.js")
+      if (!(await Bun.file(serverPath).exists())) {
+        log.info("downloading and building VS Code ESLint server")
+        const response = await fetch("https://github.com/microsoft/vscode-eslint/archive/refs/heads/main.zip")
+        if (!response.ok) return
+
+        const zipPath = path.join(Global.Path.bin, "vscode-eslint.zip")
+        await Bun.file(zipPath).write(response)
+
+        await $`unzip -o -q ${zipPath}`.cwd(Global.Path.bin).nothrow()
+        await fs.rm(zipPath, { force: true })
+
+        const extractedPath = path.join(Global.Path.bin, "vscode-eslint-main")
+        const finalPath = path.join(Global.Path.bin, "vscode-eslint")
+
+        if (await Bun.file(finalPath).exists()) {
+          await fs.rm(finalPath, { force: true, recursive: true })
+        }
+        await fs.rename(extractedPath, finalPath)
+
+        await $`npm install`.cwd(finalPath).quiet()
+        await $`npm run compile`.cwd(finalPath).quiet()
+
+        log.info("installed VS Code ESLint server", { serverPath })
+      }
+
+      const proc = spawn(BunProc.which(), ["--max-old-space-size=8192", serverPath, "--stdio"], {
+        cwd: root,
+        env: {
+          ...process.env,
+          BUN_BE_BUN: "1",
+        },
+      })
+
+      return {
+        process: proc,
+      }
+    },
+  }
+
   export const Gopls: Info = {
     id: "golang",
     root: async (file, app) => {

+ 1 - 0
packages/opencode/src/tool/edit.ts

@@ -111,6 +111,7 @@ export const EditTool = Tool.define("edit", {
         continue
       }
       output += `\n<project_diagnostics>\n${file}\n${issues
+        // TODO: may want to make more leniant for eslint
         .filter((item) => item.severity === 1)
         .map(LSP.Diagnostic.pretty)
         .join("\n")}\n</project_diagnostics>\n`

+ 4 - 3
packages/web/src/content/docs/docs/lsp.mdx

@@ -11,9 +11,10 @@ opencode integrates with your Language Server Protocol (LSP) to help the LLM int
 
 opencode comes with several built-in LSP servers for popular languages:
 
-| LSP Server | Extensions                         | Requirements                        |
+| LSP Server | Extensions                                   | Requirements                        |
 | ---------- | -------------------------------------------- | ----------------------------------- |
 | typescript | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts | `typescript` dependency in project  |
+| eslint     | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts | `eslint` dependency in project      |
 | gopls      | .go                                          | `go` command available              |
 | ruby-lsp   | .rb, .rake, .gemspec, .ru                    | `ruby` and `gem` commands available |
 | pyright    | .py, .pyi                                    | `pyright` dependency installed      |
@@ -41,7 +42,7 @@ You can customize LSP servers through the `lsp` section in your opencode config.
 ```json title="opencode.json"
 {
   "$schema": "https://opencode.ai/config.json",
-  "lsp": { }
+  "lsp": {}
 }
 ```
 
@@ -49,7 +50,7 @@ Each LSP server supports the following:
 
 | Property         | Type     | Description                                       |
 | ---------------- | -------- | ------------------------------------------------- |
-| `disabled`       | boolean  | Set this to `true` to disable the LSP server           |
+| `disabled`       | boolean  | Set this to `true` to disable the LSP server      |
 | `command`        | string[] | The command to start the LSP server               |
 | `extensions`     | string[] | File extensions this LSP server should handle     |
 | `env`            | object   | Environment variables to set when starting server |