@@ -21,6 +21,7 @@ import { fileURLToPath } from "url";
2121import { ChildProcess } from "child_process" ;
2222import { WorkspaceEdit } from "vscode-languageserver" ;
2323import { TextEdit } from "vscode-languageserver-types" ;
24+ import { OnReadOpts } from "node:net" ;
2425
2526// https://microsoft.github.io/language-server-protocol/specification#initialize
2627// 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")) {
243244 send = ( msg : m . Message ) => process . send ! ( msg ) ;
244245 process . on ( "message" , onMessage ) ;
245246}
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+ send ( 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+ send ( response ) ;
269+ }
270+
271+ function rename ( msg : p . RequestMessage ) {
272+ // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rename
273+ let params = msg . params as p . RenameParams ;
274+ let filePath = fileURLToPath ( params . textDocument . uri ) ;
275+ let locations : p . Location [ ] | null = utils . getReferencesForPosition (
276+ filePath ,
277+ params . position
278+ ) ;
279+ let result : WorkspaceEdit | null ;
280+ if ( locations === null ) {
281+ result = null ;
282+ } else {
283+ let changes : { [ uri : string ] : TextEdit [ ] } = { } ;
284+ locations . forEach ( ( { uri, range } ) => {
285+ let textEdit : TextEdit = { range, newText : params . newName } ;
286+ if ( uri in changes ) {
287+ changes [ uri ] . push ( textEdit ) ;
288+ } else {
289+ changes [ uri ] = [ textEdit ] ;
290+ }
291+ } ) ;
292+ result = { changes } ;
293+ }
294+ let renameResponse : m . ResponseMessage = {
295+ jsonrpc : c . jsonrpcVersion ,
296+ id : msg . id ,
297+ result,
298+ } ;
299+ send ( renameResponse ) ;
300+ }
301+
302+ function references ( msg : p . RequestMessage ) {
303+ // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references
304+ let params = msg . params as p . ReferenceParams ;
305+ let filePath = fileURLToPath ( params . textDocument . uri ) ;
306+ let result : typeof p . ReferencesRequest . type = utils . getReferencesForPosition (
307+ filePath ,
308+ params . position
309+ ) ;
310+ let definitionResponse : m . ResponseMessage = {
311+ jsonrpc : c . jsonrpcVersion ,
312+ id : msg . id ,
313+ result,
314+ // error: code and message set in case an exception happens during the definition request.
315+ } ;
316+ send ( definitionResponse ) ;
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+ send ( 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+ send ( response ) ;
350+ }
351+
246352function onMessage ( msg : m . Message ) {
247353 if ( m . isNotificationMessage ( msg ) ) {
248354 // notification message, aka the client ends it and doesn't want a reply
@@ -353,105 +459,17 @@ function onMessage(msg: m.Message) {
353459 send ( response ) ;
354460 }
355461 } else if ( msg . method === p . HoverRequest . method ) {
356- let params = msg . params as p . HoverParams ;
357- let filePath = fileURLToPath ( params . textDocument . uri ) ;
358- let response = utils . runAnalysisCommand (
359- filePath ,
360- [ "hover" , filePath , params . position . line , params . position . character ] ,
361- msg
362- ) ;
363- send ( response ) ;
462+ hover ( msg ) ;
364463 } else if ( msg . method === p . DefinitionRequest . method ) {
365- // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_definition
366- let params = msg . params as p . DefinitionParams ;
367- let filePath = fileURLToPath ( params . textDocument . uri ) ;
368- let response = utils . runAnalysisCommand (
369- filePath ,
370- [
371- "definition" ,
372- filePath ,
373- params . position . line ,
374- params . position . character ,
375- ] ,
376- msg
377- ) ;
378- send ( response ) ;
464+ definition ( msg ) ;
379465 } else if ( msg . method === p . RenameRequest . method ) {
380- // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rename
381- let params = msg . params as p . RenameParams ;
382- let filePath = fileURLToPath ( params . textDocument . uri ) ;
383- let locations : p . Location [ ] | null = utils . getReferencesForPosition (
384- filePath ,
385- params . position
386- ) ;
387- let result : WorkspaceEdit | null ;
388- if ( locations === null ) {
389- result = null ;
390- } else {
391- let changes : { [ uri : string ] : TextEdit [ ] } = { } ;
392- locations . forEach ( ( { uri, range } ) => {
393- let textEdit : TextEdit = { range, newText : params . newName } ;
394- if ( uri in changes ) {
395- changes [ uri ] . push ( textEdit ) ;
396- } else {
397- changes [ uri ] = [ textEdit ] ;
398- }
399- } ) ;
400-
401- result = { changes } ;
402- }
403-
404- let renameResponse : m . ResponseMessage = {
405- jsonrpc : c . jsonrpcVersion ,
406- id : msg . id ,
407- result,
408- } ;
409-
410- send ( renameResponse ) ;
466+ rename ( msg ) ;
411467 } else if ( msg . method === p . ReferencesRequest . method ) {
412- // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references
413- let params = msg . params as p . ReferenceParams ;
414- let filePath = fileURLToPath ( params . textDocument . uri ) ;
415- let result : typeof p . ReferencesRequest . type = utils . getReferencesForPosition (
416- filePath ,
417- params . position
418- ) ;
419- let definitionResponse : m . ResponseMessage = {
420- jsonrpc : c . jsonrpcVersion ,
421- id : msg . id ,
422- result,
423- // error: code and message set in case an exception happens during the definition request.
424- } ;
425- send ( definitionResponse ) ;
468+ references ( msg ) ;
426469 } else if ( msg . method === p . DocumentSymbolRequest . method ) {
427- // https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentSymbol
428- let params = msg . params as p . DocumentSymbolParams ;
429- let filePath = fileURLToPath ( params . textDocument . uri ) ;
430- let response = utils . runAnalysisCommand (
431- filePath ,
432- [ "documentSymbol" , filePath ] ,
433- msg
434- ) ;
435- send ( response ) ;
470+ documentSymbol ( msg ) ;
436471 } else if ( msg . method === p . CompletionRequest . method ) {
437- let params = msg . params as p . ReferenceParams ;
438- let filePath = fileURLToPath ( params . textDocument . uri ) ;
439- let code = getOpenedFileContent ( params . textDocument . uri ) ;
440- let tmpname = utils . createFileInTempDir ( ) ;
441- fs . writeFileSync ( tmpname , code , { encoding : "utf-8" } ) ;
442- let response = utils . runAnalysisCommand (
443- filePath ,
444- [
445- "completion" ,
446- filePath ,
447- params . position . line ,
448- params . position . character ,
449- tmpname ,
450- ] ,
451- msg
452- ) ;
453- fs . unlink ( tmpname , ( ) => null ) ;
454- send ( response ) ;
472+ completion ( msg ) ;
455473 } else if ( msg . method === p . DocumentFormattingRequest . method ) {
456474 // technically, a formatting failure should reply with the error. Sadly
457475 // the LSP alert box for these error replies sucks (e.g. doesn't actually
0 commit comments