@@ -19,8 +19,9 @@ import * as chokidar from "chokidar";
19
19
import { assert } from "console" ;
20
20
import { fileURLToPath } from "url" ;
21
21
import { ChildProcess } from "child_process" ;
22
- import { WorkspaceEdit } from "vscode-languageserver" ;
22
+ import { WorkspaceEdit } from "vscode-languageserver" ;
23
23
import { TextEdit } from "vscode-languageserver-types" ;
24
+ import { OnReadOpts } from "node:net" ;
24
25
25
26
// https://microsoft.github.io/language-server-protocol/specification#initialize
26
27
// According to the spec, there could be requests before the 'initialize' request. Link in comment tells how to handle them.
@@ -243,6 +244,111 @@ if (process.argv.includes("--stdio")) {
243
244
send = ( msg : m . Message ) => process . send ! ( msg ) ;
244
245
process . on ( "message" , onMessage ) ;
245
246
}
247
+
248
+ function hover ( msg : p . RequestMessage ) {
249
+ let params = msg . params as p . HoverParams ;
250
+ let filePath = fileURLToPath ( params . textDocument . uri ) ;
251
+ let response = utils . runAnalysisCommand (
252
+ filePath ,
253
+ [ "hover" , filePath , params . position . line , params . position . character ] ,
254
+ msg
255
+ ) ;
256
+ return response ;
257
+ }
258
+
259
+ function definition ( msg : p . RequestMessage ) {
260
+ // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_definition
261
+ let params = msg . params as p . DefinitionParams ;
262
+ let filePath = fileURLToPath ( params . textDocument . uri ) ;
263
+ let response = utils . runAnalysisCommand (
264
+ filePath ,
265
+ [ "definition" , filePath , params . position . line , params . position . character ] ,
266
+ msg
267
+ ) ;
268
+ return response ;
269
+ }
270
+
271
+ function references ( msg : p . RequestMessage ) {
272
+ // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references
273
+ let params = msg . params as p . ReferenceParams ;
274
+ let filePath = fileURLToPath ( params . textDocument . uri ) ;
275
+ let result : typeof p . ReferencesRequest . type = utils . getReferencesForPosition (
276
+ filePath ,
277
+ params . position
278
+ ) ;
279
+ let response : m . ResponseMessage = {
280
+ jsonrpc : c . jsonrpcVersion ,
281
+ id : msg . id ,
282
+ result,
283
+ // error: code and message set in case an exception happens during the definition request.
284
+ } ;
285
+ return response ;
286
+ }
287
+
288
+ function rename ( msg : p . RequestMessage ) {
289
+ // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rename
290
+ let params = msg . params as p . RenameParams ;
291
+ let filePath = fileURLToPath ( params . textDocument . uri ) ;
292
+ let locations : p . Location [ ] | null = utils . getReferencesForPosition (
293
+ filePath ,
294
+ params . position
295
+ ) ;
296
+ let result : WorkspaceEdit | null ;
297
+ if ( locations === null ) {
298
+ result = null ;
299
+ } else {
300
+ let changes : { [ uri : string ] : TextEdit [ ] } = { } ;
301
+ locations . forEach ( ( { uri, range } ) => {
302
+ let textEdit : TextEdit = { range, newText : params . newName } ;
303
+ if ( uri in changes ) {
304
+ changes [ uri ] . push ( textEdit ) ;
305
+ } else {
306
+ changes [ uri ] = [ textEdit ] ;
307
+ }
308
+ } ) ;
309
+ result = { changes } ;
310
+ }
311
+ let response : m . ResponseMessage = {
312
+ jsonrpc : c . jsonrpcVersion ,
313
+ id : msg . id ,
314
+ result,
315
+ } ;
316
+ return response ;
317
+ }
318
+
319
+ function documentSymbol ( msg : p . RequestMessage ) {
320
+ // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentSymbol
321
+ let params = msg . params as p . DocumentSymbolParams ;
322
+ let filePath = fileURLToPath ( params . textDocument . uri ) ;
323
+ let response = utils . runAnalysisCommand (
324
+ filePath ,
325
+ [ "documentSymbol" , filePath ] ,
326
+ msg
327
+ ) ;
328
+ return response ;
329
+ }
330
+
331
+ function completion ( msg : p . RequestMessage ) {
332
+ let params = msg . params as p . ReferenceParams ;
333
+ let filePath = fileURLToPath ( params . textDocument . uri ) ;
334
+ let code = getOpenedFileContent ( params . textDocument . uri ) ;
335
+ let tmpname = utils . createFileInTempDir ( ) ;
336
+ fs . writeFileSync ( tmpname , code , { encoding : "utf-8" } ) ;
337
+ let response = utils . runAnalysisCommand (
338
+ filePath ,
339
+ [
340
+ "completion" ,
341
+ filePath ,
342
+ params . position . line ,
343
+ params . position . character ,
344
+ tmpname ,
345
+ ] ,
346
+ msg
347
+ ) ;
348
+ fs . unlink ( tmpname , ( ) => null ) ;
349
+ return response ;
350
+ }
351
+
246
352
function onMessage ( msg : m . Message ) {
247
353
if ( m . isNotificationMessage ( msg ) ) {
248
354
// notification message, aka the client ends it and doesn't want a reply
@@ -353,118 +459,17 @@ function onMessage(msg: m.Message) {
353
459
send ( response ) ;
354
460
}
355
461
} else if ( msg . method === p . HoverRequest . method ) {
356
- let params = msg . params as p . HoverParams ;
357
- let filePath = fileURLToPath ( params . textDocument . uri ) ;
358
- let result : typeof p . HoverRequest . type = utils . runAnalysisAfterSanityCheck (
359
- filePath ,
360
- [ "hover" , filePath , params . position . line , params . position . character ]
361
- ) ;
362
- let hoverResponse : m . ResponseMessage = {
363
- jsonrpc : c . jsonrpcVersion ,
364
- id : msg . id ,
365
- // type result = Hover | null
366
- // type Hover = {contents: MarkedString | MarkedString[] | MarkupContent, range?: Range}
367
- result,
368
- } ;
369
- send ( hoverResponse ) ;
462
+ send ( hover ( msg ) ) ;
370
463
} else if ( msg . method === p . DefinitionRequest . method ) {
371
- // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_definition
372
- let params = msg . params as p . DefinitionParams ;
373
- let filePath = fileURLToPath ( params . textDocument . uri ) ;
374
- let result : typeof p . DefinitionRequest . type = utils . runAnalysisAfterSanityCheck (
375
- filePath ,
376
- [
377
- "definition" ,
378
- filePath ,
379
- params . position . line ,
380
- params . position . character ,
381
- ]
382
- ) ;
383
- let definitionResponse : m . ResponseMessage = {
384
- jsonrpc : c . jsonrpcVersion ,
385
- id : msg . id ,
386
- result,
387
- // error: code and message set in case an exception happens during the definition request.
388
- } ;
389
- send ( definitionResponse ) ;
390
- } else if ( msg . method === p . RenameRequest . method ) {
391
- // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rename
392
- let params = msg . params as p . RenameParams ;
393
- let filePath = fileURLToPath ( params . textDocument . uri ) ;
394
- let locations : p . Location [ ] | null = utils . getReferencesForPosition ( filePath , params . position ) ;
395
- let result : WorkspaceEdit | null ;
396
- if ( locations === null ) {
397
- result = null ;
398
- } else {
399
- let changes : { [ uri : string ] : TextEdit [ ] } = { } ;
400
- locations . forEach ( ( { uri, range } ) => {
401
- let textEdit : TextEdit = { range, newText : params . newName } ;
402
- if ( uri in changes ) {
403
- changes [ uri ] . push ( textEdit ) ;
404
- } else {
405
- changes [ uri ] = [ textEdit ]
406
- }
407
- } ) ;
408
-
409
- result = { changes} ;
410
- }
411
-
412
- let renameResponse : m . ResponseMessage = {
413
- jsonrpc : c . jsonrpcVersion ,
414
- id : msg . id ,
415
- result,
416
- } ;
417
-
418
- send ( renameResponse ) ;
464
+ send ( definition ( msg ) ) ;
419
465
} else if ( msg . method === p . ReferencesRequest . method ) {
420
- // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references
421
- let params = msg . params as p . ReferenceParams ;
422
- let filePath = fileURLToPath ( params . textDocument . uri ) ;
423
- let result : typeof p . ReferencesRequest . type = utils . getReferencesForPosition ( filePath , params . position ) ;
424
- let definitionResponse : m . ResponseMessage = {
425
- jsonrpc : c . jsonrpcVersion ,
426
- id : msg . id ,
427
- result,
428
- // error: code and message set in case an exception happens during the definition request.
429
- } ;
430
- send ( definitionResponse ) ;
466
+ send ( references ( msg ) ) ;
467
+ } else if ( msg . method === p . RenameRequest . method ) {
468
+ send ( rename ( msg ) ) ;
431
469
} else if ( msg . method === p . DocumentSymbolRequest . method ) {
432
- // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentSymbol
433
- let params = msg . params as p . DocumentSymbolParams ;
434
- let filePath = fileURLToPath ( params . textDocument . uri ) ;
435
- let result : typeof p . DocumentSymbolRequest . type = utils . runAnalysisAfterSanityCheck (
436
- filePath ,
437
- [ "documentSymbol" , filePath ]
438
- ) ;
439
- let definitionResponse : m . ResponseMessage = {
440
- jsonrpc : c . jsonrpcVersion ,
441
- id : msg . id ,
442
- result,
443
- } ;
444
- send ( definitionResponse ) ;
470
+ send ( documentSymbol ( msg ) ) ;
445
471
} else if ( msg . method === p . CompletionRequest . method ) {
446
- let params = msg . params as p . ReferenceParams ;
447
- let filePath = fileURLToPath ( params . textDocument . uri ) ;
448
- let code = getOpenedFileContent ( params . textDocument . uri ) ;
449
- let tmpname = utils . createFileInTempDir ( ) ;
450
- fs . writeFileSync ( tmpname , code , { encoding : "utf-8" } ) ;
451
- let result : typeof p . CompletionRequest . type = utils . runAnalysisAfterSanityCheck (
452
- filePath ,
453
- [
454
- "completion" ,
455
- filePath ,
456
- params . position . line ,
457
- params . position . character ,
458
- tmpname ,
459
- ]
460
- ) ;
461
- fs . unlink ( tmpname , ( ) => null ) ;
462
- let completionResponse : m . ResponseMessage = {
463
- jsonrpc : c . jsonrpcVersion ,
464
- id : msg . id ,
465
- result,
466
- } ;
467
- send ( completionResponse ) ;
472
+ send ( completion ( msg ) ) ;
468
473
} else if ( msg . method === p . DocumentFormattingRequest . method ) {
469
474
// technically, a formatting failure should reply with the error. Sadly
470
475
// the LSP alert box for these error replies sucks (e.g. doesn't actually
0 commit comments