Skip to content

Commit

Permalink
Fix CreateWorkDoneProgress for VScode and Emacs (#161)
Browse files Browse the repository at this point in the history
CreateWorkDoneProgress is a request, not a notification, requiring a unique ID and expecting a response.
  • Loading branch information
scottming authored May 16, 2023
1 parent 67238ef commit fe6ccbe
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 28 deletions.
6 changes: 0 additions & 6 deletions apps/protocol/lib/lexical/protocol/notifications.ex
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,6 @@ defmodule Lexical.Protocol.Notifications do
end
end

defmodule WorkDone.Progress.Create do
use Proto

defnotification "window/workDoneProgress/create", Types.WorkDone.Progress.Create.Params
end

defmodule Progress do
use Proto

Expand Down
6 changes: 6 additions & 0 deletions apps/protocol/lib/lexical/protocol/requests.ex
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ defmodule Lexical.Protocol.Requests do
defrequest "textDocument/definition", Types.Definition.Params
end

defmodule CreateWorkDoneProgress do
use Proto

defrequest "window/workDoneProgress/create", Types.WorkDone.Progress.Create.Params
end

defmodule Formatting do
use Proto

Expand Down
8 changes: 7 additions & 1 deletion apps/server/lib/lexical/server.ex
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,15 @@ defmodule Lexical.Server do
State.apply(state, message)
end

def handle_message(nil, %State{} = state) do
# NOTE: This deals with the response after a request is requested by the server,
# such as the response of `CreateWorkDoneProgress`.
{:ok, state}
end

def handle_message(request, %State{} = state) do
Provider.Queue.add(request, state.configuration)

{:ok, %State{} = state}
{:ok, state}
end
end
27 changes: 16 additions & 11 deletions apps/server/lib/lexical/server/configuration.ex
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ defmodule Lexical.Server.Configuration do
def new(root_uri, %ClientCapabilities{} = client_capabilities) do
support = Support.new(client_capabilities)
project = Project.new(root_uri)
%__MODULE__{support: support, project: project}
%__MODULE__{support: support, project: project} |> tap(&set/1)
end

@spec default(t | nil) ::
Expand Down Expand Up @@ -53,20 +53,11 @@ defmodule Lexical.Server.Configuration do
end

defp apply_config_change(%__MODULE__{} = old_config, %{} = settings) do
with {:ok, new_config} <- maybe_set_env_vars(old_config, settings),
{:ok, new_config} <- maybe_enable_dialyzer(new_config, settings) do
with {:ok, new_config} <- maybe_enable_dialyzer(old_config, settings) do
maybe_add_watched_extensions(new_config, settings)
end
end

defp maybe_set_env_vars(%__MODULE__{} = old_config, settings) do
env_vars = Map.get(settings, "envVariables")

with {:ok, new_project} <- Project.set_env_vars(old_config.project, env_vars) do
{:ok, %__MODULE__{old_config | project: new_project}}
end
end

defp maybe_enable_dialyzer(%__MODULE__{} = old_config, settings) do
enabled? =
case Dialyzer.check_support() do
Expand Down Expand Up @@ -110,4 +101,18 @@ defmodule Lexical.Server.Configuration do
defp maybe_add_watched_extensions(%__MODULE__{} = old_config, _) do
{:ok, old_config}
end

@supports_keys ~w(work_done_progress?)a

def supports?(key) when key in @supports_keys do
get_in(get(), [Access.key(:support), Access.key(key)]) || false
end

def get do
:persistent_term.get(__MODULE__, %__MODULE__{})
end

defp set(%__MODULE__{} = config) do
:persistent_term.put(__MODULE__, config)
end
end
11 changes: 9 additions & 2 deletions apps/server/lib/lexical/server/configuration/support.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ defmodule Lexical.Server.Configuration.Support do
snippet?: false,
deprecated?: false,
tags?: false,
signature_help?: false
signature_help?: false,
work_done_progress?: false

def new(%ClientCapabilities{} = client_capabilities) do
dynamic_registration? =
Expand Down Expand Up @@ -39,13 +40,19 @@ defmodule Lexical.Server.Configuration.Support do
|> get_in([:text_document, :signature_help])
|> bool()

work_done_progress? =
client_capabilities
|> get_in([:window, :work_done_progress])
|> bool()

%__MODULE__{
code_action_dynamic_registration?: dynamic_registration?,
hierarchical_document_symbols?: hierarchical_symbols?,
snippet?: snippet?,
deprecated?: deprecated?,
tags?: tags?,
signature_help?: signature_help?
signature_help?: signature_help?,
work_done_progress?: work_done_progress?
}
end

Expand Down
14 changes: 10 additions & 4 deletions apps/server/lib/lexical/server/project/progress/state.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
defmodule Lexical.Server.Project.Progress.State do
alias Lexical.Project
alias Lexical.Protocol.Notifications
alias Lexical.Protocol.Id
alias Lexical.Protocol.Requests
alias Lexical.Server.Configuration
alias Lexical.Server.Project.Progress.Value
alias Lexical.Server.Transport

Expand Down Expand Up @@ -42,12 +44,16 @@ defmodule Lexical.Server.Project.Progress.State do
end

defp write_work_done(token) do
progress = Notifications.WorkDone.Progress.Create.new(token: token)
Transport.write(progress)
if Configuration.supports?(:work_done_progress?) do
progress = Requests.CreateWorkDoneProgress.new(id: Id.next(), token: token)
Transport.write(progress)
end
end

defp write(%{token: token} = progress) when not is_nil(token) do
progress |> Value.to_protocol() |> Transport.write()
if Configuration.supports?(:work_done_progress?) do
progress |> Value.to_protocol() |> Transport.write()
end
end

defp write(_), do: :ok
Expand Down
3 changes: 0 additions & 3 deletions apps/server/lib/lexical/server/state.ex
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,6 @@ defmodule Lexical.Server.State do
{:ok, config, response} ->
Transport.write(response)
{:ok, %__MODULE__{state | configuration: config}}

error ->
error
end

{:ok, state}
Expand Down
15 changes: 14 additions & 1 deletion apps/server/test/lexical/server/project/progress_test.exs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
defmodule Lexical.Server.Project.ProgressTest do
alias Lexical.Protocol.Notifications
alias Lexical.Protocol.Requests
alias Lexical.RemoteControl
alias Lexical.Server.Configuration
alias Lexical.Server.Project
alias Lexical.Server.Transport

Expand Down Expand Up @@ -38,10 +40,12 @@ defmodule Lexical.Server.Project.ProgressTest do
setup [:with_patched_tranport]

test "it should be able to send the report progress", %{project: project} do
patch(Configuration, :supports?, fn :work_done_progress? -> true end)

begin_message = progress(:begin, "mix compile")
Project.Dispatch.broadcast(project, begin_message)

assert_receive {:transport, %Notifications.WorkDone.Progress.Create{lsp: %{token: token}}}
assert_receive {:transport, %Requests.CreateWorkDoneProgress{lsp: %{token: token}}}
assert_receive {:transport, %Notifications.Progress{}}

report_message = progress(:report, "mix compile", "lib/file.ex")
Expand All @@ -53,5 +57,14 @@ defmodule Lexical.Server.Project.ProgressTest do
assert value.percentage == nil
assert value.cancellable == nil
end

test "it should write nothing when the client does not support work done", %{project: project} do
patch(Configuration, :supports?, fn :work_done_progress? -> false end)

begin_message = progress(:begin, "mix compile")
Project.Dispatch.broadcast(project, begin_message)

refute_receive {:transport, %Requests.CreateWorkDoneProgress{lsp: %{}}}
end
end
end

0 comments on commit fe6ccbe

Please sign in to comment.