Skip to content

Commit d26e29c

Browse files
authored
feat: adding/removing workspace folders (#126)
1 parent 1103d01 commit d26e29c

File tree

4 files changed

+213
-42
lines changed

4 files changed

+213
-42
lines changed

Diff for: lib/next_ls.ex

+59-3
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@ defmodule NextLS do
1010
alias GenLSP.Notifications.TextDocumentDidChange
1111
alias GenLSP.Notifications.TextDocumentDidOpen
1212
alias GenLSP.Notifications.TextDocumentDidSave
13+
alias GenLSP.Notifications.WorkspaceDidChangeWorkspaceFolders
1314
alias GenLSP.Requests.Initialize
1415
alias GenLSP.Requests.Shutdown
1516
alias GenLSP.Requests.TextDocumentDefinition
1617
alias GenLSP.Requests.TextDocumentDocumentSymbol
1718
alias GenLSP.Requests.TextDocumentFormatting
1819
alias GenLSP.Requests.WorkspaceSymbol
20+
alias GenLSP.Structures.DidChangeWorkspaceFoldersParams
1921
alias GenLSP.Structures.DidOpenTextDocumentParams
2022
alias GenLSP.Structures.InitializeParams
2123
alias GenLSP.Structures.InitializeResult
@@ -28,6 +30,7 @@ defmodule NextLS do
2830
alias GenLSP.Structures.TextDocumentItem
2931
alias GenLSP.Structures.TextDocumentSyncOptions
3032
alias GenLSP.Structures.TextEdit
33+
alias GenLSP.Structures.WorkspaceFoldersChangeEvent
3134
alias NextLS.Definition
3235
alias NextLS.DiagnosticCache
3336
alias NextLS.Progress
@@ -288,7 +291,7 @@ defmodule NextLS do
288291
parent = self()
289292
working_dir = URI.parse(uri).path
290293

291-
{:ok, runtime} =
294+
{:ok, _} =
292295
DynamicSupervisor.start_child(
293296
lsp.assigns.dynamic_supervisor,
294297
{NextLS.Runtime.Supervisor,
@@ -312,8 +315,6 @@ defmodule NextLS do
312315
logger: lsp.assigns.logger
313316
]}
314317
)
315-
316-
{name, %{uri: uri, runtime: runtime}}
317318
end
318319

319320
{:noreply, lsp}
@@ -379,6 +380,61 @@ defmodule NextLS do
379380
{:noreply, put_in(lsp.assigns.documents[uri], String.split(text, "\n"))}
380381
end
381382

383+
def handle_notification(
384+
%WorkspaceDidChangeWorkspaceFolders{
385+
params: %DidChangeWorkspaceFoldersParams{event: %WorkspaceFoldersChangeEvent{added: added, removed: removed}}
386+
},
387+
lsp
388+
) do
389+
dispatch(lsp.assigns.registry, :runtime_supervisors, fn entries ->
390+
names = Enum.map(entries, fn {_, %{name: name}} -> name end)
391+
392+
for %{name: name, uri: uri} <- added, name not in names do
393+
GenLSP.log(lsp, "[NextLS] Adding workspace folder #{name}")
394+
token = token()
395+
Progress.start(lsp, token, "Initializing NextLS runtime for folder #{name}...")
396+
parent = self()
397+
working_dir = URI.parse(uri).path
398+
399+
# TODO: probably extract this to the Runtime module
400+
{:ok, _} =
401+
DynamicSupervisor.start_child(
402+
lsp.assigns.dynamic_supervisor,
403+
{NextLS.Runtime.Supervisor,
404+
path: Path.join(working_dir, ".elixir-tools"),
405+
name: name,
406+
registry: lsp.assigns.registry,
407+
runtime: [
408+
task_supervisor: lsp.assigns.runtime_task_supervisor,
409+
working_dir: working_dir,
410+
uri: uri,
411+
on_initialized: fn status ->
412+
if status == :ready do
413+
Progress.stop(lsp, token, "NextLS runtime for folder #{name} has initialized!")
414+
GenLSP.log(lsp, "[NextLS] Runtime for folder #{name} is ready...")
415+
send(parent, {:runtime_ready, name, self()})
416+
else
417+
Progress.stop(lsp, token)
418+
GenLSP.error(lsp, "[NextLS] Runtime for folder #{name} failed to initialize")
419+
end
420+
end,
421+
logger: lsp.assigns.logger
422+
]}
423+
)
424+
end
425+
426+
names = Enum.map(removed, & &1.name)
427+
428+
for {pid, %{name: name}} <- entries, name in names do
429+
GenLSP.log(lsp, "[NextLS] Removing workspace folder #{name}")
430+
# TODO: probably extract this to the Runtime module
431+
DynamicSupervisor.terminate_child(lsp.assigns.dynamic_supervisor, pid)
432+
end
433+
end)
434+
435+
{:noreply, lsp}
436+
end
437+
382438
def handle_notification(%Exit{}, lsp) do
383439
System.halt(lsp.assigns.exit_code)
384440

Diff for: lib/next_ls/runtime.ex

+8-2
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,14 @@ defmodule NextLS.Runtime do
101101
ref = Process.monitor(me)
102102

103103
receive do
104-
{:DOWN, ^ref, :process, ^me, _reason} ->
105-
NextLS.Logger.error(logger, "[NextLS] The runtime for #{name} has crashed")
104+
{:DOWN, ^ref, :process, ^me, reason} ->
105+
case reason do
106+
:shutdown ->
107+
NextLS.Logger.log(logger, "The runtime for #{name} has successfully shutdown.")
108+
109+
reason ->
110+
NextLS.Logger.error(logger, "The runtime for #{name} has crashed with reason: #{reason}.")
111+
end
106112
end
107113
end)
108114

Diff for: lib/next_ls/runtime/supervisor.ex

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ defmodule NextLS.Runtime.Supervisor do
1818
symbol_table_name = :"symbol-table-#{name}"
1919
sidecar_name = :"sidecar-#{name}"
2020

21+
Registry.register(registry, :runtime_supervisors, %{name: name})
22+
2123
children = [
2224
{NextLS.SymbolTable, workspace: name, path: hidden_folder, registry: registry, name: symbol_table_name},
2325
{NextLS.Runtime.Sidecar, name: sidecar_name, symbol_table: symbol_table_name},

0 commit comments

Comments
 (0)