Bläddra i källkod

fix(lsp): preserve workspace cancellation reason

Tianyi Cui 2 månader sedan
förälder
incheckning
4d63552d00
2 ändrade filer med 24 tillägg och 1 borttagningar
  1. 4 1
      packages/lsp/lsp-local/src/host.ts
  2. 20 0
      packages/lsp/lsp-local/tests/host.spec.ts

+ 4 - 1
packages/lsp/lsp-local/src/host.ts

@@ -42,7 +42,10 @@ export async function canonicalizeWorkspace(
     throw new Error(`workspace root "${workspaceRoot}" cannot be resolved: ${messageOf(error)}`, { cause: error })
     throw new Error(`workspace root "${workspaceRoot}" cannot be resolved: ${messageOf(error)}`, { cause: error })
   }
   }
   throwIfAborted(signal)
   throwIfAborted(signal)
-  const info = await fs.stat(target, signal)
+  const info = await fs.stat(target, signal).catch((error: unknown) => {
+    throwIfAborted(signal)
+    throw error
+  })
   throwIfAborted(signal)
   throwIfAborted(signal)
   if (info?.type !== 'directory') {
   if (info?.type !== 'directory') {
     throw new Error(`workspace root "${workspaceRoot}" is not a directory`)
     throw new Error(`workspace root "${workspaceRoot}" is not a directory`)

+ 20 - 0
packages/lsp/lsp-local/tests/host.spec.ts

@@ -57,11 +57,31 @@ describe('canonicalizeWorkspace', () => {
     await expect(canonicalizeWorkspace(fs, join(root, 'nope'))).rejects.toThrow(/not a directory/)
     await expect(canonicalizeWorkspace(fs, join(root, 'nope'))).rejects.toThrow(/not a directory/)
   })
   })
 
 
+  it('wraps a provider failure while resolving the workspace', async () => {
+    fs.resolve = async () => { throw 'raw workspace resolve failure' }
+    await expect(canonicalizeWorkspace(fs, ws))
+      .rejects.toThrow(`workspace root "${ws}" cannot be resolved: raw workspace resolve failure`)
+  })
+
   it('rejects a non-directory workspace', async () => {
   it('rejects a non-directory workspace', async () => {
     const file = join(root, 'file.txt')
     const file = join(root, 'file.txt')
     await writeFile(file, 'x')
     await writeFile(file, 'x')
     await expect(canonicalizeWorkspace(fs, file)).rejects.toThrow(/not a directory/)
     await expect(canonicalizeWorkspace(fs, file)).rejects.toThrow(/not a directory/)
   })
   })
+
+  it('normalizes workspace metadata cancellation and preserves other provider failures', async () => {
+    const providerFailure = new Error('workspace metadata failed')
+    fs.stat = async () => { throw providerFailure }
+    await expect(canonicalizeWorkspace(fs, ws)).rejects.toBe(providerFailure)
+
+    const controller = new AbortController()
+    fs.stat = async () => {
+      controller.abort(new Error('workspace metadata cancelled'))
+      throw providerFailure
+    }
+    await expect(canonicalizeWorkspace(fs, ws, controller.signal))
+      .rejects.toThrow('workspace metadata cancelled')
+  })
 })
 })
 
 
 describe('readHostSource', () => {
 describe('readHostSource', () => {