diff --git a/packages/lsp/tool-lsp/src/render.ts b/packages/lsp/tool-lsp/src/render.ts index 3f49d1edfd..4613312c87 100644 --- a/packages/lsp/tool-lsp/src/render.ts +++ b/packages/lsp/tool-lsp/src/render.ts @@ -148,7 +148,7 @@ export function renderUri(uri: string, workspaceUri: string): string { const workspaceSegments = decodeFileSegments(workspace) if (targetSegments === undefined || workspaceSegments === undefined) return uri const sameAuthority = target.hostname === workspace.hostname - const windowsWorld = /^[A-Za-z]:$/.test(workspaceSegments[0] ?? '') + const windowsWorld = isWindowsFileWorld(workspace, workspaceSegments) const inside = sameAuthority && targetSegments.length >= workspaceSegments.length && workspaceSegments.every((segment, index) => samePathSegment(segment, targetSegments[index] as string, windowsWorld)) @@ -159,6 +159,11 @@ export function renderUri(uri: string, workspaceUri: string): string { return absoluteUriPath(target, targetSegments, workspaceSegments) } +/** Whether a canonical file URI names a drive path or UNC path in a Windows execution world. */ +function isWindowsFileWorld(url: URL, segments: readonly string[]): boolean { + return url.hostname.length > 0 || /^[A-Za-z]:$/.test(segments[0] ?? '') +} + /** Decode URI path segments while rejecting encoded separators that would change path structure. */ function decodeFileSegments(url: URL): string[] | undefined { try { diff --git a/packages/lsp/tool-lsp/tests/render.spec.ts b/packages/lsp/tool-lsp/tests/render.spec.ts index 9f87d663fb..d76600ea6f 100644 --- a/packages/lsp/tool-lsp/tests/render.spec.ts +++ b/packages/lsp/tool-lsp/tests/render.spec.ts @@ -75,8 +75,10 @@ describe('renderUri', () => { it('renders remote file authorities without host path conversion', () => { expect(renderUri('file://server/share/workspace/a.ts', 'file://server/share/workspace')).toBe('a.ts') + expect(renderUri('file://SERVER/share/workspace/src/A.ts', 'file://server/Share/Workspace')).toBe('src/A.ts') expect(renderUri('file://other/share/b.ts', 'file://server/share/workspace')).toBe('//other/share/b.ts') expect(renderUri('file:///a.ts', 'file://server/')).toBe('/a.ts') + expect(renderUri('file:///a.ts', 'file:///')).toBe('a.ts') }) it('keeps malformed or mismatched URI coordinates verbatim', () => {