1- import { createWebSocketConnection , ConsoleLogger , toSocket , MessageSignature } from '@codingame/monaco-jsonrpc'
1+ import { MessageSignature , MessageConnection } from '@codingame/monaco-jsonrpc'
22import { Uri } from 'monaco-editor'
33import {
44 MonacoLanguageClient ,
@@ -7,97 +7,81 @@ import {
77import once from 'once'
88import { registerExtensionFeatures } from './extensions'
99import { LanguageClientId } from './languageClientOptions'
10+ import { Infrastructure } from './infrastructure'
1011
11- async function openConnection ( url : URL | string , errorHandler : ConnectionErrorHandler , closeHandler : ( ) => void ) : Promise < IConnection > {
12- return new Promise ( ( resolve , reject ) => {
13- const webSocket = new WebSocket ( url )
12+ async function messageConnectionToConnection ( messageConnection : MessageConnection , errorHandler : ConnectionErrorHandler , closeHandler : ( ) => void ) : Promise < IConnection > {
13+ const connection = createConnection ( messageConnection , errorHandler , closeHandler )
1414
15- webSocket . onopen = ( ) => {
16- const socket = toSocket ( webSocket )
17- const webSocketConnection = createWebSocketConnection ( socket , new ConsoleLogger ( ) )
18- webSocketConnection . onDispose ( ( ) => {
19- webSocket . close ( )
20- } )
21-
22- const connection = createConnection ( webSocketConnection , errorHandler , closeHandler )
23-
24- const existingRegistrations = new Set < string > ( )
25- const fixedConnection : IConnection = {
26- ...connection ,
27- initialize : ( params : InitializeParams ) => {
28- // Hack to fix url converted from /toto/tata to \\toto\tata in windows
29- const rootPath = params . rootPath ?. replace ( / \\ / g, '/' )
30- const fixedParams : InitializeParams = {
31- ...params ,
32- rootPath : rootPath ,
33- rootUri : rootPath != null ? Uri . from ( { scheme : 'file' , path : rootPath } ) . toString ( ) : null
34- }
35- return connection . initialize ( fixedParams )
36- } ,
37- onRequest ( ...args : Parameters < typeof connection . onRequest > ) {
38- return connection . onRequest ( args [ 0 ] , ( ...params ) => {
39- // Hack for https://github.com/OmniSharp/omnisharp-roslyn/issues/2119
40- const method = ( args [ 0 ] as MessageSignature ) . method
41- if ( method === RegistrationRequest . type . method ) {
42- const registrationParams = params [ 0 ] as unknown as RegistrationParams
43- registrationParams . registrations = registrationParams . registrations . filter ( registration => {
44- const alreadyExisting = existingRegistrations . has ( registration . id )
45- if ( alreadyExisting ) {
46- console . warn ( 'Registration already existing' , registration . id , registration . method )
47- }
48- return ! alreadyExisting
49- } )
50- registrationParams . registrations . forEach ( registration => {
51- existingRegistrations . add ( registration . id )
52- } )
53- }
54- if ( method === UnregistrationRequest . type . method ) {
55- const unregistrationParams = params [ 0 ] as unknown as UnregistrationParams
56- for ( const unregistration of unregistrationParams . unregisterations ) {
57- existingRegistrations . delete ( unregistration . id )
58- }
15+ const existingRegistrations = new Set < string > ( )
16+ const fixedConnection : IConnection = {
17+ ...connection ,
18+ initialize : ( params : InitializeParams ) => {
19+ // Hack to fix url converted from /toto/tata to \\toto\tata in windows
20+ const rootPath = params . rootPath ?. replace ( / \\ / g, '/' )
21+ const fixedParams : InitializeParams = {
22+ ...params ,
23+ rootPath : rootPath ,
24+ rootUri : rootPath != null ? Uri . from ( { scheme : 'file' , path : rootPath } ) . toString ( ) : null
25+ }
26+ return connection . initialize ( fixedParams )
27+ } ,
28+ onRequest ( ...args : Parameters < typeof connection . onRequest > ) {
29+ return connection . onRequest ( args [ 0 ] , ( ...params ) => {
30+ // Hack for https://github.com/OmniSharp/omnisharp-roslyn/issues/2119
31+ const method = ( args [ 0 ] as MessageSignature ) . method
32+ if ( method === RegistrationRequest . type . method ) {
33+ const registrationParams = params [ 0 ] as unknown as RegistrationParams
34+ registrationParams . registrations = registrationParams . registrations . filter ( registration => {
35+ const alreadyExisting = existingRegistrations . has ( registration . id )
36+ if ( alreadyExisting ) {
37+ console . warn ( 'Registration already existing' , registration . id , registration . method )
5938 }
60- return args [ 1 ] ( ... params )
39+ return ! alreadyExisting
6140 } )
62- } ,
63- dispose : ( ) => {
64- try {
65- connection . dispose ( )
66- } catch ( error ) {
67- // The dispose should NEVER fail or the lsp client is not properly cleaned
68- // see https://github.com/microsoft/vscode-languageserver-node/blob/master/client/src/client.ts#L3105
69- console . warn ( '[LSP]' , 'Error while disposing connection' , error )
70- }
71- // Hack, when the language client is removed, the connection is disposed but the closeHandler is not always properly called
72- // The language client is then still active but without a proper connection and errors will occurs
73- closeHandler ( )
74- } ,
75- shutdown : async ( ) => {
76- // The shutdown should NEVER fail or the connection is not closed and the lsp client is not properly cleaned
77- // see https://github.com/microsoft/vscode-languageserver-node/blob/master/client/src/client.ts#L3103
78- try {
79- await connection . shutdown ( )
80- } catch ( error ) {
81- console . warn ( '[LSP]' , 'Error while shutdown lsp' , error )
41+ registrationParams . registrations . forEach ( registration => {
42+ existingRegistrations . add ( registration . id )
43+ } )
44+ }
45+ if ( method === UnregistrationRequest . type . method ) {
46+ const unregistrationParams = params [ 0 ] as unknown as UnregistrationParams
47+ for ( const unregistration of unregistrationParams . unregisterations ) {
48+ existingRegistrations . delete ( unregistration . id )
8249 }
8350 }
51+ return args [ 1 ] ( ...params )
52+ } )
53+ } ,
54+ dispose : ( ) => {
55+ try {
56+ connection . dispose ( )
57+ } catch ( error ) {
58+ // The dispose should NEVER fail or the lsp client is not properly cleaned
59+ // see https://github.com/microsoft/vscode-languageserver-node/blob/master/client/src/client.ts#L3105
60+ console . warn ( '[LSP]' , 'Error while disposing connection' , error )
61+ }
62+ // Hack, when the language client is removed, the connection is disposed but the closeHandler is not always properly called
63+ // The language client is then still active but without a proper connection and errors will occurs
64+ closeHandler ( )
65+ } ,
66+ shutdown : async ( ) => {
67+ // The shutdown should NEVER fail or the connection is not closed and the lsp client is not properly cleaned
68+ // see https://github.com/microsoft/vscode-languageserver-node/blob/master/client/src/client.ts#L3103
69+ try {
70+ await connection . shutdown ( )
71+ } catch ( error ) {
72+ console . warn ( '[LSP]' , 'Error while shutdown lsp' , error )
8473 }
85- resolve ( fixedConnection )
86- }
87- webSocket . onerror = ( ) => {
88- reject ( new Error ( 'Unable to connect to server' ) )
8974 }
90- } )
75+ }
76+
77+ return fixedConnection
9178}
9279
9380const RETRY_DELAY = 3000
9481class CGLSPConnectionProvider implements IConnectionProvider {
9582 constructor (
96- private serverAddress : string ,
9783 private id : LanguageClientId ,
98- private sessionId : string | undefined ,
99- private libraryUrls : string [ ] ,
100- private getSecurityToken : ( ) => Promise < string >
84+ private infrastructure : Infrastructure
10185 ) {
10286 }
10387
@@ -108,12 +92,9 @@ class CGLSPConnectionProvider implements IConnectionProvider {
10892 } , RETRY_DELAY )
10993 } )
11094 try {
111- const path = this . sessionId != null ? `run/${ this . sessionId } /${ this . id } ` : `run/${ this . id } `
112- const url = new URL ( path , this . serverAddress )
113- this . libraryUrls . forEach ( libraryUrl => url . searchParams . append ( 'libraryUrl' , libraryUrl ) )
114- url . searchParams . append ( 'token' , await this . getSecurityToken ( ) )
95+ const connection = await this . infrastructure . openConnection ( this . id )
11596
116- return await openConnection ( url , errorHandler , onceDelayedCloseHandler )
97+ return await messageConnectionToConnection ( connection , errorHandler , onceDelayedCloseHandler )
11798 } catch ( err ) {
11899 onceDelayedCloseHandler ( )
119100 throw err
@@ -123,15 +104,12 @@ class CGLSPConnectionProvider implements IConnectionProvider {
123104
124105function createLanguageClient (
125106 id : LanguageClientId ,
126- sessionId : string | undefined ,
107+ infrastructure : Infrastructure ,
127108 {
128109 documentSelector,
129110 synchronize,
130111 initializationOptions
131112 } : LanguageClientOptions ,
132- languageServerAddress : string ,
133- getSecurityToken : ( ) => Promise < string > ,
134- libraryUrls : string [ ] ,
135113 errorHandler : ErrorHandler ,
136114 middleware ?: Middleware
137115) : MonacoLanguageClient {
@@ -147,7 +125,7 @@ function createLanguageClient (
147125 synchronize,
148126 initializationOptions
149127 } ,
150- connectionProvider : new CGLSPConnectionProvider ( languageServerAddress , id , sessionId , libraryUrls , getSecurityToken )
128+ connectionProvider : new CGLSPConnectionProvider ( id , infrastructure )
151129 } )
152130
153131 client . registerProposedFeatures ( )
0 commit comments