@@ -87,13 +87,26 @@ defmodule NextLS do
8787 dynamic_supervisor: dynamic_supervisor ,
8888 extension_registry: extension_registry ,
8989 extensions: extensions ,
90- runtime_task: nil ,
91- ready: false
90+ runtime_tasks: nil ,
91+ ready: false ,
92+ client_capabilities: nil
9293 ) }
9394 end
9495
9596 @ impl true
96- def handle_request ( % Initialize { params: % InitializeParams { root_uri: root_uri } } , lsp ) do
97+ def handle_request (
98+ % Initialize {
99+ params: % InitializeParams { root_uri: root_uri , workspace_folders: workspace_folders , capabilities: caps }
100+ } ,
101+ lsp
102+ ) do
103+ workspace_folders =
104+ if caps . workspace . workspace_folders do
105+ workspace_folders
106+ else
107+ % { name: Path . basename ( root_uri ) , uri: root_uri }
108+ end
109+
97110 { :reply ,
98111 % InitializeResult {
99112 capabilities: % ServerCapabilities {
@@ -105,10 +118,16 @@ defmodule NextLS do
105118 document_formatting_provider: true ,
106119 workspace_symbol_provider: true ,
107120 document_symbol_provider: true ,
108- definition_provider: true
121+ definition_provider: true ,
122+ workspace: % {
123+ workspace_folders: % GenLSP.Structures.WorkspaceFoldersServerCapabilities {
124+ supported: true ,
125+ change_notifications: true
126+ }
127+ }
109128 } ,
110- server_info: % { name: "NextLS " }
111- } , assign ( lsp , root_uri: root_uri ) }
129+ server_info: % { name: "Next LS " }
130+ } , assign ( lsp , root_uri: root_uri , workspace_folders: workspace_folders , client_capabilities: caps ) }
112131 end
113132
114133 def handle_request ( % TextDocumentDefinition { params: % { text_document: % { uri: uri } , position: position } } , lsp ) do
@@ -201,7 +220,9 @@ defmodule NextLS do
201220
202221 def handle_request ( % TextDocumentFormatting { params: % { text_document: % { uri: uri } } } , lsp ) do
203222 document = lsp . assigns . documents [ uri ]
204- runtime = lsp . assigns . runtime
223+
224+ { _ , % { runtime: runtime } } =
225+ lsp . assigns . runtimes |> Enum . find ( fn { _name , % { uri: wuri } } -> String . starts_with? ( uri , wuri ) end )
205226
206227 with { :ok , { formatter , _ } } <- Runtime . call ( runtime , { Mix.Tasks.Format , :formatter_for_file , [ ".formatter.exs" ] } ) ,
207228 { :ok , response } when is_binary ( response ) or is_list ( response ) <-
@@ -255,8 +276,6 @@ defmodule NextLS do
255276 def handle_notification ( % Initialized { } , lsp ) do
256277 GenLSP . log ( lsp , "[NextLS] NextLS v#{ version ( ) } has initialized!" )
257278
258- working_dir = URI . parse ( lsp . assigns . root_uri ) . path
259-
260279 for extension <- lsp . assigns . extensions do
261280 { :ok , _ } =
262281 DynamicSupervisor . start_child (
@@ -267,44 +286,51 @@ defmodule NextLS do
267286
268287 GenLSP . log ( lsp , "[NextLS] Booting runtime..." )
269288
270- token = token ( )
271-
272- progress_start ( lsp , token , "Initializing NextLS runtime..." )
273-
274- { :ok , runtime } =
275- DynamicSupervisor . start_child (
276- lsp . assigns . dynamic_supervisor ,
277- { NextLS.Runtime ,
278- task_supervisor: lsp . assigns . runtime_task_supervisor ,
279- extension_registry: lsp . assigns . extension_registry ,
280- working_dir: working_dir ,
281- parent: self ( ) ,
282- logger: lsp . assigns . logger }
283- )
289+ runtimes =
290+ for % { uri: uri , name: name } <- lsp . assigns . workspace_folders do
291+ token = token ( )
292+ progress_start ( lsp , token , "Initializing NextLS runtime for folder #{ name } ..." )
293+
294+ { :ok , runtime } =
295+ DynamicSupervisor . start_child (
296+ lsp . assigns . dynamic_supervisor ,
297+ { NextLS.Runtime ,
298+ task_supervisor: lsp . assigns . runtime_task_supervisor ,
299+ extension_registry: lsp . assigns . extension_registry ,
300+ working_dir: URI . parse ( uri ) . path ,
301+ parent: self ( ) ,
302+ logger: lsp . assigns . logger }
303+ )
304+
305+ Process . monitor ( runtime )
306+
307+ { name ,
308+ % { uri: uri , runtime: runtime , refresh_ref: { token , "NextLS runtime for folder #{ name } has initialized!" } } }
309+ end
284310
285- Process . monitor ( runtime )
311+ lsp = assign ( lsp , runtimes: Map . new ( runtimes ) )
286312
287- lsp = assign ( lsp , runtime: runtime )
313+ tasks =
314+ for { name , workspace } <- runtimes do
315+ Task.Supervisor . async_nolink ( lsp . assigns . task_supervisor , fn ->
316+ with false <- wait_until ( fn -> NextLS.Runtime . ready? ( workspace . runtime ) end ) do
317+ GenLSP . error ( lsp , "[NextLS] Failed to start runtime for folder #{ name } " )
318+ raise "Failed to boot runtime"
319+ end
288320
289- task =
290- Task.Supervisor . async_nolink ( lsp . assigns . task_supervisor , fn ->
291- with false <-
292- wait_until ( fn ->
293- NextLS.Runtime . ready? ( runtime )
294- end ) do
295- GenLSP . error ( lsp , "[NextLS] Failed to start runtime" )
296- raise "Failed to boot runtime"
297- end
321+ GenLSP . log ( lsp , "[NextLS] Runtime for folder #{ name } is ready..." )
298322
299- GenLSP . log ( lsp , "[NextLS] Runtime ready..." )
323+ { name , :ready }
324+ end )
325+ end
300326
301- :ready
302- end )
327+ refresh_refs =
328+ Enum . zip_with ( tasks , runtimes , fn task , { _name , runtime } -> { task . ref , runtime . refresh_ref } end ) |> Map . new ( )
303329
304330 { :noreply ,
305331 assign ( lsp ,
306- refresh_refs: Map . put ( lsp . assigns . refresh_refs , task . ref , { token , "NextLS runtime has initialized!" } ) ,
307- runtime_task: task
332+ refresh_refs: Map . merge ( lsp . assigns . refresh_refs , refresh_refs ) ,
333+ runtime_tasks: tasks
308334 ) }
309335 end
310336
@@ -322,23 +348,27 @@ defmodule NextLS do
322348 % { assigns: % { ready: true } } = lsp
323349 ) do
324350 for task <- Task.Supervisor . children ( lsp . assigns . task_supervisor ) ,
325- task != lsp . assigns . runtime_task . pid do
351+ task not in for ( t <- lsp . assigns . runtime_tasks , do: t . pid ) do
326352 Process . exit ( task , :kill )
327353 end
328354
329355 token = token ( )
330356
331357 progress_start ( lsp , token , "Compiling..." )
358+ runtimes = Enum . to_list ( lsp . assigns . runtimes )
359+
360+ tasks =
361+ for { name , r } <- runtimes do
362+ Task.Supervisor . async_nolink ( lsp . assigns . task_supervisor , fn -> { name , Runtime . compile ( r . runtime ) } end )
363+ end
332364
333- task =
334- Task.Supervisor . async_nolink ( lsp . assigns . task_supervisor , fn ->
335- Runtime . compile ( lsp . assigns . runtime )
336- end )
365+ refresh_refs =
366+ Enum . zip_with ( tasks , runtimes , fn task , { _name , runtime } -> { task . ref , runtime . refresh_ref } end ) |> Map . new ( )
337367
338368 { :noreply ,
339369 lsp
340370 |> then ( & put_in ( & 1 . assigns . documents [ uri ] , String . split ( text , "\n " ) ) )
341- |> then ( & put_in ( & 1 . assigns . refresh_refs [ task . ref ] , { token , "Compiled!" } ) ) }
371+ |> then ( & put_in ( & 1 . assigns . refresh_refs , refresh_refs ) ) }
342372 end
343373
344374 def handle_notification ( % TextDocumentDidChange { } , % { assigns: % { ready: false } } = lsp ) do
@@ -355,7 +385,7 @@ defmodule NextLS do
355385 lsp
356386 ) do
357387 for task <- Task.Supervisor . children ( lsp . assigns . task_supervisor ) ,
358- task != lsp . assigns . runtime_task . pid do
388+ task not in for ( t <- lsp . assigns . runtime_tasks , do: t . pid ) do
359389 Process . exit ( task , :kill )
360390 end
361391
@@ -421,13 +451,13 @@ defmodule NextLS do
421451
422452 lsp =
423453 case resp do
424- :ready ->
454+ { name , :ready } ->
425455 token = token ( )
426456 progress_start ( lsp , token , "Compiling..." )
427457
428458 task =
429459 Task.Supervisor . async_nolink ( lsp . assigns . task_supervisor , fn ->
430- Runtime . compile ( lsp . assigns . runtime )
460+ { name , Runtime . compile ( lsp . assigns . runtimes [ name ] . runtime ) }
431461 end )
432462
433463 assign ( lsp , ready: true , refresh_refs: Map . put ( refs , task . ref , { token , "Compiled!" } ) )
@@ -448,13 +478,11 @@ defmodule NextLS do
448478 { :noreply , assign ( lsp , refresh_refs: refs ) }
449479 end
450480
451- def handle_info (
452- { :DOWN , _ref , :process , runtime , _reason } ,
453- % { assigns: % { runtime: runtime } } = lsp
454- ) do
455- GenLSP . error ( lsp , "[NextLS] The runtime has crashed" )
481+ def handle_info ( { :DOWN , _ref , :process , runtime , _reason } , % { assigns: % { runtimes: runtimes } } = lsp ) do
482+ { name , _ } = Enum . find ( runtimes , fn { _name , % { runtime: r } } -> r == runtime end )
483+ GenLSP . error ( lsp , "[NextLS] The runtime for #{ name } has crashed" )
456484
457- { :noreply , assign ( lsp , runtime: nil ) }
485+ { :noreply , assign ( lsp , runtimes: Map . drop ( runtimes , name ) ) }
458486 end
459487
460488 def handle_info ( message , lsp ) do
0 commit comments