@@ -60,7 +60,7 @@ export interface LSPClient extends Unsubscribable {
6060 * Ensures a connection with the given workspace root, passes it to the given function.
6161 * If the workspace is not currently open in Sourcegraph, the connection is closed again after the Promise returned by the function resolved.
6262 *
63- * @param workspaceRoot The workspace folder root URI that will be ensured to be open before calling the function.
63+ * @param workspaceRoot The client workspace folder root URI that will be ensured to be open before calling the function.
6464 * @param fn Callback that is called with the connection.
6565 */
6666 withConnection < R > ( workspaceRoot : URL , fn : ( connection : LSPConnection ) => Promise < R > ) : Promise < R >
@@ -128,7 +128,7 @@ export async function register({
128128
129129 const registrationSubscriptions = new Map < string , Unsubscribable > ( )
130130 /**
131- * @param scopeRootUri A workspace folder root URI to scope the providers to. If `null`, the provider is registered for all workspace folders.
131+ * @param scopeRootUri A client workspace folder root URI to scope the providers to. If `null`, the provider is registered for all workspace folders.
132132 */
133133 function registerCapabilities (
134134 connection : LSPConnection ,
@@ -153,7 +153,7 @@ export async function register({
153153 }
154154 }
155155
156- async function connect ( ) : Promise < LSPConnection > {
156+ async function connect ( clientRootUri : URL | null , initParams : InitializeParams ) : Promise < LSPConnection > {
157157 const subscriptions = new Subscription ( )
158158 const decorationType = sourcegraph . app . createDecorationType ( )
159159 const connection = await createConnection ( )
@@ -256,12 +256,13 @@ export async function register({
256256 }
257257 } )
258258 )
259+ await initializeConnection ( connection , clientRootUri , initParams )
259260 return connection
260261 }
261262
262263 async function initializeConnection (
263264 connection : LSPConnection ,
264- rootUri : URL | null ,
265+ clientRootUri : URL | null ,
265266 initParams : InitializeParams
266267 ) : Promise < void > {
267268 const initializeResult = await connection . sendRequest ( InitializeRequest . type , initParams )
@@ -273,18 +274,26 @@ export async function register({
273274
274275 // Listen for dynamic capabilities
275276 connection . setRequestHandler ( RegistrationRequest . type , params => {
276- registerCapabilities ( connection , rootUri , params . registrations )
277+ registerCapabilities ( connection , clientRootUri , params . registrations )
277278 } )
278279 // Register static capabilities
279- registerCapabilities ( connection , rootUri , staticRegistrations )
280+ registerCapabilities ( connection , clientRootUri , staticRegistrations )
280281
281282 await afterInitialize ( initializeResult )
282283 }
283284
284285 let withConnection : < R > ( workspaceFolder : URL , fn : ( connection : LSPConnection ) => Promise < R > ) => Promise < R >
285286
286287 if ( supportsWorkspaceFolders ) {
287- const connection = await connect ( )
288+ const connection = await connect (
289+ null ,
290+ {
291+ processId : null ,
292+ rootUri : null ,
293+ capabilities : clientCapabilities ,
294+ workspaceFolders : sourcegraph . workspace . roots . map ( toLSPWorkspaceFolder ( { clientToServerURI } ) ) ,
295+ }
296+ )
288297 subscriptions . add ( connection )
289298 withConnection = async ( workspaceFolder , fn ) => {
290299 let tempWorkspaceFolder : WorkspaceFolder | undefined
@@ -310,12 +319,6 @@ export async function register({
310319 }
311320 }
312321 }
313- await initializeConnection ( connection , null , {
314- processId : null ,
315- rootUri : null ,
316- capabilities : clientCapabilities ,
317- workspaceFolders : sourcegraph . workspace . roots . map ( toLSPWorkspaceFolder ) ,
318- } )
319322
320323 // Forward root changes
321324 subscriptions . add (
@@ -328,8 +331,12 @@ export async function register({
328331 after,
329332 } ) ) ,
330333 map ( ( { before, after } ) => ( {
331- added : differenceBy ( after , before , root => root . uri . toString ( ) ) . map ( toLSPWorkspaceFolder ) ,
332- removed : differenceBy ( before , after , root => root . uri . toString ( ) ) . map ( toLSPWorkspaceFolder ) ,
334+ added : differenceBy ( after , before , root => root . uri . toString ( ) ) . map (
335+ toLSPWorkspaceFolder ( { clientToServerURI } )
336+ ) ,
337+ removed : differenceBy ( before , after , root => root . uri . toString ( ) ) . map (
338+ toLSPWorkspaceFolder ( { clientToServerURI } )
339+ ) ,
333340 } ) )
334341 )
335342 . subscribe ( event => {
@@ -338,31 +345,47 @@ export async function register({
338345 )
339346 } else {
340347 // Supports only one workspace root
348+ // TODO this should store a refcount to avoid closing connections other consumers have a reference to
349+ /** Map from client root URI to connection */
341350 const connectionsByRootUri = new Map < string , Promise < LSPConnection > > ( )
342351 withConnection = async ( workspaceFolder , fn ) => {
343352 let connection = await connectionsByRootUri . get ( workspaceFolder . href )
344- if ( ! connection ) {
345- connection = await connect ( )
346- subscriptions . add ( connection )
353+ if ( connection ) {
354+ return await fn ( connection )
347355 }
356+ const serverRootUri = clientToServerURI ( workspaceFolder )
357+ connection = await connect (
358+ workspaceFolder ,
359+ {
360+ processId : null ,
361+ rootUri : serverRootUri . href ,
362+ capabilities : clientCapabilities ,
363+ workspaceFolders : null ,
364+ }
365+ )
366+ subscriptions . add ( connection )
348367 try {
349368 return await fn ( connection )
350369 } finally {
370+ connectionsByRootUri . delete ( workspaceFolder . href )
351371 connection . unsubscribe ( )
352372 }
353373 }
354374 function addRoots ( added : ReadonlyArray < WorkspaceRoot > ) : void {
355375 for ( const root of added ) {
356376 const connectionPromise = ( async ( ) => {
357377 try {
358- const connection = await connect ( )
378+ const serverRootUri = clientToServerURI ( new URL ( root . uri . toString ( ) ) )
379+ const connection = await connect (
380+ new URL ( root . uri . toString ( ) ) ,
381+ {
382+ processId : null ,
383+ rootUri : serverRootUri . href ,
384+ capabilities : clientCapabilities ,
385+ workspaceFolders : null ,
386+ }
387+ )
359388 subscriptions . add ( connection )
360- await initializeConnection ( connection , new URL ( root . uri . toString ( ) ) , {
361- processId : null ,
362- rootUri : root . uri . toString ( ) ,
363- capabilities : clientCapabilities ,
364- workspaceFolders : null ,
365- } )
366389 return connection
367390 } catch ( err ) {
368391 logger . error ( 'Error creating connection' , err )
0 commit comments