@@ -15,7 +15,6 @@ import lspStatusBar from "components/lspStatusBar";
1515import NotificationManager from "lib/notificationManager" ;
1616import Uri from "utils/Uri" ;
1717import { clearDiagnosticsEffect } from "./diagnostics" ;
18- import { documentHighlightsExtension } from "./documentHighlights" ;
1918import { supportsBuiltinFormatting } from "./formattingSupport" ;
2019import { inlayHintsExtension } from "./inlayHints" ;
2120import { acodeRenameKeymap } from "./rename" ;
@@ -27,7 +26,7 @@ import type {
2726 BuiltinExtensionsConfig ,
2827 ClientManagerOptions ,
2928 ClientState ,
30- EnsureServerResult ,
29+ DocumentUriContext ,
3130 FileMetadata ,
3231 FormattingOptions ,
3332 LspServerDefinition ,
@@ -160,7 +159,6 @@ function buildBuiltinExtensions(
160159 keymaps : includeKeymaps = true ,
161160 diagnostics : includeDiagnostics = true ,
162161 inlayHints : includeInlayHints = false ,
163- documentHighlights : includeDocumentHighlights = true ,
164162 formatting : includeFormatting = true ,
165163 } = config ;
166164
@@ -190,10 +188,6 @@ function buildBuiltinExtensions(
190188 const hintsExt = inlayHintsExtension ( ) ;
191189 extensions . push ( hintsExt as LSPClientExtension as Extension ) ;
192190 }
193- if ( includeDocumentHighlights ) {
194- const highlightsExt = documentHighlightsExtension ( ) ;
195- extensions . push ( highlightsExt as LSPClientExtension as Extension ) ;
196- }
197191
198192 return { extensions, diagnosticsExtension } ;
199193}
@@ -248,30 +242,23 @@ export class LspClientManager {
248242 const servers = serverRegistry . getServersForLanguage ( effectiveLang ) ;
249243 if ( ! servers . length ) return [ ] ;
250244
251- // Normalize the document URI for LSP (convert content:// to file://)
252- let normalizedUri = normalizeDocumentUri ( originalUri ) ;
253- if ( ! normalizedUri ) {
254- // Fall back to cache file path for unrecognized URIs
255- // This allows LSP to work with any file system provider using the local cache
256- const cacheFile = file ?. cacheFile ;
257- if ( cacheFile && typeof cacheFile === "string" ) {
258- normalizedUri = buildFileUri ( cacheFile . replace ( / ^ f i l e : \/ \/ / , "" ) ) ;
259- if ( normalizedUri ) {
260- console . info (
261- `LSP using cache path for unrecognized URI: ${ originalUri } -> ${ normalizedUri } ` ,
262- ) ;
263- }
264- }
265- if ( ! normalizedUri ) {
266- console . warn ( `Cannot normalize document URI for LSP: ${ originalUri } ` ) ;
267- return [ ] ;
268- }
269- }
270-
271245 const lspExtensions : Extension [ ] = [ ] ;
272246 const diagnosticsUiExtension = this . options . diagnosticsUiExtension ;
273247
274248 for ( const server of servers ) {
249+ const normalizedUri = await this . #resolveDocumentUri( server , {
250+ uri : originalUri ,
251+ file,
252+ view,
253+ languageId : effectiveLang ,
254+ rootUri,
255+ } ) ;
256+ if ( ! normalizedUri ) {
257+ console . warn (
258+ `Cannot resolve document URI for LSP server ${ server . id } : ${ originalUri } ` ,
259+ ) ;
260+ continue ;
261+ }
275262 let targetLanguageId = effectiveLang ;
276263 if ( server . resolveLanguageId ) {
277264 try {
@@ -302,7 +289,9 @@ export class LspClientManager {
302289 normalizedUri ,
303290 targetLanguageId ,
304291 ) ;
305- clientState . attach ( normalizedUri , view as EditorView ) ;
292+ const aliases =
293+ originalUri && originalUri !== normalizedUri ? [ originalUri ] : [ ] ;
294+ clientState . attach ( normalizedUri , view as EditorView , aliases ) ;
306295 lspExtensions . push ( plugin ) ;
307296 } catch ( error ) {
308297 const lspError = error as LSPError ;
@@ -334,26 +323,25 @@ export class LspClientManager {
334323 const effectiveLang = safeString ( languageId ?? languageName ) . toLowerCase ( ) ;
335324 if ( ! effectiveLang || ! view ) return false ;
336325
337- let normalizedUri = normalizeDocumentUri ( originalUri ) ;
338- if ( ! normalizedUri ) {
339- const cacheFile = file ?. cacheFile ;
340- if ( cacheFile && typeof cacheFile === "string" ) {
341- normalizedUri = buildFileUri ( cacheFile . replace ( / ^ f i l e : \/ \/ / , "" ) ) ;
342- }
343- if ( ! normalizedUri ) {
344- console . warn (
345- `Cannot normalize document URI for formatting: ${ originalUri } ` ,
346- ) ;
347- return false ;
348- }
349- }
350-
351326 const servers = serverRegistry . getServersForLanguage ( effectiveLang ) ;
352327 if ( ! servers . length ) return false ;
353328
354329 for ( const server of servers ) {
355330 if ( ! supportsBuiltinFormatting ( server ) ) continue ;
356331 try {
332+ const normalizedUri = await this . #resolveDocumentUri( server , {
333+ uri : originalUri ,
334+ file,
335+ view,
336+ languageId : effectiveLang ,
337+ rootUri : metadata . rootUri ,
338+ } ) ;
339+ if ( ! normalizedUri ) {
340+ console . warn (
341+ `Cannot resolve document URI for formatting with ${ server . id } : ${ originalUri } ` ,
342+ ) ;
343+ continue ;
344+ }
357345 const context : RootUriContext = {
358346 uri : normalizedUri ,
359347 languageId : effectiveLang ,
@@ -530,7 +518,6 @@ export class LspClientManager {
530518 keymaps : builtinConfig . keymaps !== false ,
531519 diagnostics : builtinConfig . diagnostics !== false ,
532520 inlayHints : builtinConfig . inlayHints === true ,
533- documentHighlights : builtinConfig . documentHighlights !== false ,
534521 formatting : builtinConfig . formatting !== false ,
535522 } )
536523 : { extensions : [ ] , diagnosticsExtension : null } ;
@@ -841,28 +828,44 @@ export class LspClientManager {
841828 originalRootUri,
842829 } = params ;
843830 const fileRefs = new Map < string , Set < EditorView > > ( ) ;
831+ const uriAliases = new Map < string , string > ( ) ;
844832 const effectiveRoot = normalizedRootUri ?? originalRootUri ?? null ;
845833
846- const attach = ( uri : string , view : EditorView ) : void => {
834+ const attach = (
835+ uri : string ,
836+ view : EditorView ,
837+ aliases : string [ ] = [ ] ,
838+ ) : void => {
847839 const existing = fileRefs . get ( uri ) ?? new Set ( ) ;
848840 existing . add ( view ) ;
849841 fileRefs . set ( uri , existing ) ;
842+ uriAliases . set ( uri , uri ) ;
843+ for ( const alias of aliases ) {
844+ if ( ! alias || alias === uri ) continue ;
845+ uriAliases . set ( alias , uri ) ;
846+ }
850847 const suffix = effectiveRoot ? ` (root ${ effectiveRoot } )` : "" ;
851848 logLspInfo ( `[LSP:${ server . id } ] attached to ${ uri } ${ suffix } ` ) ;
852849 } ;
853850
854851 const detach = ( uri : string , view ?: EditorView ) : void => {
855- const existing = fileRefs . get ( uri ) ;
852+ const actualUri = uriAliases . get ( uri ) ?? uri ;
853+ const existing = fileRefs . get ( actualUri ) ;
856854 if ( ! existing ) return ;
857855 if ( view ) existing . delete ( view ) ;
858856 if ( ! view || ! existing . size ) {
859- fileRefs . delete ( uri ) ;
857+ fileRefs . delete ( actualUri ) ;
858+ for ( const [ alias , target ] of uriAliases . entries ( ) ) {
859+ if ( target === actualUri ) {
860+ uriAliases . delete ( alias ) ;
861+ }
862+ }
860863 try {
861864 // Only pass uri to closeFile - view is not needed for closing
862865 // and passing it may cause issues if the view is already disposed
863- ( client . workspace as AcodeWorkspace ) ?. closeFile ?.( uri ) ;
866+ ( client . workspace as AcodeWorkspace ) ?. closeFile ?.( actualUri ) ;
864867 } catch ( error ) {
865- console . warn ( `Failed to close LSP file ${ uri } ` , error ) ;
868+ console . warn ( `Failed to close LSP file ${ actualUri } ` , error ) ;
866869 }
867870 }
868871
@@ -904,8 +907,6 @@ export class LspClientManager {
904907 server : LspServerDefinition ,
905908 context : RootUriContext ,
906909 ) : Promise < string | null > {
907- if ( context ?. rootUri ) return context . rootUri ;
908-
909910 if ( typeof server . rootUri === "function" ) {
910911 try {
911912 const value = await server . rootUri ( context ?. uri ?? "" , context ) ;
@@ -915,6 +916,8 @@ export class LspClientManager {
915916 }
916917 }
917918
919+ if ( context ?. rootUri ) return safeString ( context . rootUri ) ;
920+
918921 if ( typeof this . options . resolveRoot === "function" ) {
919922 try {
920923 const value = await this . options . resolveRoot ( context ) ;
@@ -926,6 +929,45 @@ export class LspClientManager {
926929
927930 return null ;
928931 }
932+
933+ async #resolveDocumentUri(
934+ server : LspServerDefinition ,
935+ context : RootUriContext ,
936+ ) : Promise < string | null > {
937+ const originalUri = context ?. uri ;
938+ if ( ! originalUri ) return null ;
939+
940+ let normalizedUri = normalizeDocumentUri ( originalUri ) ;
941+ if ( ! normalizedUri ) {
942+ // Fall back to cache file path for providers that do not expose a file:// URI.
943+ const cacheFile = context . file ?. cacheFile ;
944+ if ( cacheFile && typeof cacheFile === "string" ) {
945+ normalizedUri = buildFileUri ( cacheFile . replace ( / ^ f i l e : \/ \/ / , "" ) ) ;
946+ if ( normalizedUri ) {
947+ console . info (
948+ `LSP using cache path for unrecognized URI: ${ originalUri } -> ${ normalizedUri } ` ,
949+ ) ;
950+ }
951+ }
952+ }
953+
954+ if ( typeof server . documentUri === "function" ) {
955+ try {
956+ const value = await server . documentUri ( originalUri , {
957+ ...context ,
958+ normalizedUri,
959+ } as DocumentUriContext ) ;
960+ if ( value ) return safeString ( value ) ;
961+ } catch ( error ) {
962+ console . warn (
963+ `Server document URI resolver failed for ${ server . id } ` ,
964+ error ,
965+ ) ;
966+ }
967+ }
968+
969+ return normalizedUri ;
970+ }
929971}
930972
931973interface Change {
0 commit comments