From fb383a801e526871a5252b0ad9d3b0281d95a54a Mon Sep 17 00:00:00 2001 From: Mitchell Hanberg Date: Thu, 22 Jun 2023 21:18:57 -0400 Subject: [PATCH] feat: progress messages --- lib/next_ls.ex | 59 ++++++++++++++++++++++++++++++++++++++----- test/next_ls_test.exs | 34 +++++++++++++++++-------- 2 files changed, 75 insertions(+), 18 deletions(-) diff --git a/lib/next_ls.ex b/lib/next_ls.ex index b326e066..58724239 100644 --- a/lib/next_ls.ex +++ b/lib/next_ls.ex @@ -33,7 +33,9 @@ defmodule NextLS do ServerCapabilities, TextDocumentItem, TextDocumentSyncOptions, - TextEdit + TextEdit, + WorkDoneProgressBegin, + WorkDoneProgressEnd } alias NextLS.Runtime @@ -156,6 +158,10 @@ defmodule NextLS do GenLSP.log(lsp, "[NextLS] Booting runime...") + token = token() + + progress_start(lsp, token, "Initializing NextLS runtime...") + {:ok, runtime} = DynamicSupervisor.start_child( lsp.assigns.dynamic_supervisor, @@ -181,7 +187,11 @@ defmodule NextLS do :ready end) - {:noreply, assign(lsp, refresh_refs: Map.put(lsp.assigns.refresh_refs, task.ref, task.ref), runtime_task: task)} + {:noreply, + assign(lsp, + refresh_refs: Map.put(lsp.assigns.refresh_refs, task.ref, {token, "NextLS runtime has initialized!"}), + runtime_task: task + )} end def handle_notification(%TextDocumentDidSave{}, %{assigns: %{ready: false}} = lsp) do @@ -197,6 +207,10 @@ defmodule NextLS do }, %{assigns: %{ready: true}} = lsp ) do + token = token() + + progress_start(lsp, token, "Compiling...") + task = Task.Supervisor.async_nolink(lsp.assigns.task_supervisor, fn -> Runtime.compile(lsp.assigns.runtime) @@ -205,7 +219,7 @@ defmodule NextLS do {:noreply, lsp |> then(&put_in(&1.assigns.documents[uri], String.split(text, "\n"))) - |> then(&put_in(&1.assigns.refresh_refs[task.ref], task.ref))} + |> then(&put_in(&1.assigns.refresh_refs[task.ref], {token, "Compiled!"}))} end def handle_notification(%TextDocumentDidChange{}, %{assigns: %{ready: false}} = lsp) do @@ -268,20 +282,32 @@ defmodule NextLS do {:noreply, lsp} end - def handle_info({ref, resp}, %{assigns: %{refresh_refs: refs}} = lsp) - when is_map_key(refs, ref) do + def handle_info({ref, resp}, %{assigns: %{refresh_refs: refs}} = lsp) when is_map_key(refs, ref) do Process.demonitor(ref, [:flush]) - {_token, refs} = Map.pop(refs, ref) + {{token, msg}, refs} = Map.pop(refs, ref) + + GenLSP.notify(lsp, %GenLSP.Notifications.DollarProgress{ + params: %GenLSP.Structures.ProgressParams{ + token: token, + value: %WorkDoneProgressEnd{ + kind: "end", + message: msg + } + } + }) lsp = case resp do :ready -> + token = token() + progress_start(lsp, token, "Compiling...") + task = Task.Supervisor.async_nolink(lsp.assigns.task_supervisor, fn -> Runtime.compile(lsp.assigns.runtime) end) - assign(lsp, ready: true, refresh_refs: Map.put(refs, task.ref, task.ref)) + assign(lsp, ready: true, refresh_refs: Map.put(refs, task.ref, {token, "Compiled!"})) _ -> assign(lsp, refresh_refs: refs) @@ -332,4 +358,23 @@ defmodule NextLS do wait_until(n - 1, cb) end end + + defp progress_start(lsp, token, msg) do + GenLSP.notify(lsp, %GenLSP.Notifications.DollarProgress{ + params: %GenLSP.Structures.ProgressParams{ + token: token, + value: %WorkDoneProgressBegin{ + kind: "begin", + title: msg + } + } + }) + end + + defp token() do + 8 + |> :crypto.strong_rand_bytes() + |> Base.url_encode64(padding: false) + |> binary_part(0, 8) + end end diff --git a/test/next_ls_test.exs b/test/next_ls_test.exs index bda2c1d9..a29f1d7a 100644 --- a/test/next_ls_test.exs +++ b/test/next_ls_test.exs @@ -141,7 +141,29 @@ defmodule NextLSTest do } ) - # assert_notification("$/progress", %{"value" => %{"kind" => "begin"}}) + assert_notification("$/progress", %{"value" => %{"kind" => "begin", "title" => "Initializing NextLS runtime..."}}) + + assert_notification( + "$/progress", + %{ + "value" => %{ + "kind" => "end", + "message" => "NextLS runtime has initialized!" + } + } + ) + + assert_notification("$/progress", %{"value" => %{"kind" => "begin", "title" => "Compiling..."}}) + + assert_notification( + "$/progress", + %{ + "value" => %{ + "kind" => "end", + "message" => "Compiled!" + } + } + ) for file <- ["bar.ex"] do uri = @@ -170,16 +192,6 @@ defmodule NextLSTest do } ) end - - # assert_notification( - # "$/progress", - # %{ - # "value" => %{ - # "kind" => "end", - # "message" => "Found 5 issues" - # } - # } - # ) end test "formats", %{client: client} do