Skip to content

Commit a772448

Browse files
committed
fix: handle non-file URI schemes gracefully in shellcheck linting
When opening files via virtual filesystems (WebDAV, kio-fuse, etc.), the document URI may not use the file: scheme. Previously, calling fileURLToPath() on such URIs would throw ERR_INVALID_URL_SCHEME. This change adds a safeFileURLToPath helper that: - Returns the file path for valid file: URIs - Returns null for non-file URIs or invalid URIs - Allows linting to proceed without the document directory in source paths Closes #1370
1 parent 7992220 commit a772448

File tree

2 files changed

+38
-2
lines changed

2 files changed

+38
-2
lines changed

server/src/shellcheck/__tests__/index.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,4 +295,22 @@ describe('linter', () => {
295295
diagnostics: [],
296296
})
297297
})
298+
299+
it('should handle non-file URI schemes gracefully', async () => {
300+
const shell = [
301+
'#!/bin/bash',
302+
'echo "hello"',
303+
].join('\n')
304+
305+
const nonFileUri = 'webdav://example.com/path/to/script.sh'
306+
const document = TextDocument.create(nonFileUri, 'bash', 0, shell)
307+
308+
const [result] = await getLintingResult({
309+
document,
310+
sourcePaths: [],
311+
})
312+
313+
expect(result.diagnostics).toEqual([])
314+
expect(result.codeActions).toEqual({})
315+
})
298316
})

server/src/shellcheck/index.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { dirname } from 'node:path'
2-
import { fileURLToPath } from 'node:url'
2+
import { fileURLToPath, URL } from 'node:url'
33

44
import { spawn } from 'child_process'
55
import * as LSP from 'vscode-languageserver/node'
@@ -17,6 +17,19 @@ import {
1717
} from './types'
1818

1919
const DEBOUNCE_MS = 500
20+
21+
function safeFileURLToPath(uri: string): string | null {
22+
try {
23+
const url = new URL(uri)
24+
if (url.protocol !== 'file:') {
25+
return null
26+
}
27+
return fileURLToPath(uri)
28+
} catch {
29+
return null
30+
}
31+
}
32+
2033
type LinterOptions = {
2134
executablePath: string
2235
cwd?: string
@@ -91,10 +104,15 @@ export class Linter {
91104
return { diagnostics: [], codeActions: {} }
92105
}
93106

107+
const documentPath = safeFileURLToPath(document.uri)
108+
const effectiveSourcePaths = documentPath
109+
? [...sourcePaths, dirname(documentPath)]
110+
: sourcePaths
111+
94112
const result = await this.runShellCheck(
95113
documentText,
96114
shellName,
97-
[...sourcePaths, dirname(fileURLToPath(document.uri))],
115+
effectiveSourcePaths,
98116
additionalShellCheckArguments,
99117
)
100118

0 commit comments

Comments
 (0)