From a7724484a0b9f03083b4641b475509c9bf512ac3 Mon Sep 17 00:00:00 2001 From: Taron Sung Date: Thu, 29 Jan 2026 18:35:26 +0900 Subject: [PATCH 1/2] 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 --- server/src/shellcheck/__tests__/index.test.ts | 18 +++++++++++++++ server/src/shellcheck/index.ts | 22 +++++++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/server/src/shellcheck/__tests__/index.test.ts b/server/src/shellcheck/__tests__/index.test.ts index c2ad2a698..b3625b285 100644 --- a/server/src/shellcheck/__tests__/index.test.ts +++ b/server/src/shellcheck/__tests__/index.test.ts @@ -295,4 +295,22 @@ describe('linter', () => { diagnostics: [], }) }) + + it('should handle non-file URI schemes gracefully', async () => { + const shell = [ + '#!/bin/bash', + 'echo "hello"', + ].join('\n') + + const nonFileUri = 'webdav://example.com/path/to/script.sh' + const document = TextDocument.create(nonFileUri, 'bash', 0, shell) + + const [result] = await getLintingResult({ + document, + sourcePaths: [], + }) + + expect(result.diagnostics).toEqual([]) + expect(result.codeActions).toEqual({}) + }) }) diff --git a/server/src/shellcheck/index.ts b/server/src/shellcheck/index.ts index f0409af8d..4aa7ee15b 100644 --- a/server/src/shellcheck/index.ts +++ b/server/src/shellcheck/index.ts @@ -1,5 +1,5 @@ import { dirname } from 'node:path' -import { fileURLToPath } from 'node:url' +import { fileURLToPath, URL } from 'node:url' import { spawn } from 'child_process' import * as LSP from 'vscode-languageserver/node' @@ -17,6 +17,19 @@ import { } from './types' const DEBOUNCE_MS = 500 + +function safeFileURLToPath(uri: string): string | null { + try { + const url = new URL(uri) + if (url.protocol !== 'file:') { + return null + } + return fileURLToPath(uri) + } catch { + return null + } +} + type LinterOptions = { executablePath: string cwd?: string @@ -91,10 +104,15 @@ export class Linter { return { diagnostics: [], codeActions: {} } } + const documentPath = safeFileURLToPath(document.uri) + const effectiveSourcePaths = documentPath + ? [...sourcePaths, dirname(documentPath)] + : sourcePaths + const result = await this.runShellCheck( documentText, shellName, - [...sourcePaths, dirname(fileURLToPath(document.uri))], + effectiveSourcePaths, additionalShellCheckArguments, ) From 84ec668d343bc6475032b16ce2610eb1b1a03eaf Mon Sep 17 00:00:00 2001 From: Taron Sung Date: Thu, 29 Jan 2026 21:17:36 +0900 Subject: [PATCH 2/2] style: apply lint formatting --- server/src/shellcheck/__tests__/index.test.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/server/src/shellcheck/__tests__/index.test.ts b/server/src/shellcheck/__tests__/index.test.ts index b3625b285..3e91203bc 100644 --- a/server/src/shellcheck/__tests__/index.test.ts +++ b/server/src/shellcheck/__tests__/index.test.ts @@ -297,10 +297,7 @@ describe('linter', () => { }) it('should handle non-file URI schemes gracefully', async () => { - const shell = [ - '#!/bin/bash', - 'echo "hello"', - ].join('\n') + const shell = ['#!/bin/bash', 'echo "hello"'].join('\n') const nonFileUri = 'webdav://example.com/path/to/script.sh' const document = TextDocument.create(nonFileUri, 'bash', 0, shell)