diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eb20b5838..9857fa0d7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -90,24 +90,34 @@ jobs: include: - elixir: 1.14.x otp: 23.x + tests_may_fail: false - elixir: 1.14.x otp: 24.x + tests_may_fail: false - elixir: 1.14.x otp: 25.x + tests_may_fail: false - elixir: 1.14.x otp: 26.x + tests_may_fail: false - elixir: 1.15.x otp: 24.x + tests_may_fail: false - elixir: 1.15.x otp: 25.x + tests_may_fail: false - elixir: 1.15.x otp: 26.x + tests_may_fail: false - elixir: 1.16.x otp: 24.x + tests_may_fail: false - elixir: 1.16.x otp: 25.x + tests_may_fail: false - elixir: 1.16.x otp: 26.x + tests_may_fail: false - elixir: 1.17.x otp: 25.x tests_may_fail: false diff --git a/apps/debug_adapter/lib/debug_adapter/breakpoint_condition.ex b/apps/debug_adapter/lib/debug_adapter/breakpoint_condition.ex index ca7d0cc51..95c08629c 100644 --- a/apps/debug_adapter/lib/debug_adapter/breakpoint_condition.ex +++ b/apps/debug_adapter/lib/debug_adapter/breakpoint_condition.ex @@ -17,6 +17,7 @@ defmodule ElixirLS.DebugAdapter.BreakpointCondition do module, module, non_neg_integer, + Macro.Env.t(), String.t(), String.t() | nil, String.t() @@ -29,7 +30,7 @@ defmodule ElixirLS.DebugAdapter.BreakpointCondition do ) end - @spec unregister_condition(module, module, non_neg_integer) :: :ok + @spec unregister_condition(module, module, [non_neg_integer]) :: :ok def unregister_condition(name \\ __MODULE__, module, line) do GenServer.cast(name, {:unregister_condition, {module, line}}) end @@ -40,7 +41,7 @@ defmodule ElixirLS.DebugAdapter.BreakpointCondition do end @spec get_condition(module, non_neg_integer) :: - {String.t(), String.t(), non_neg_integer, non_neg_integer} + {Macro.Env.t(), String.t(), String.t(), String.t(), non_neg_integer} def get_condition(name \\ __MODULE__, number) do GenServer.call(name, {:get_condition, number}) end diff --git a/apps/debug_adapter/lib/debug_adapter/completions.ex b/apps/debug_adapter/lib/debug_adapter/completions.ex index 2f051cfde..32e7fdc9e 100644 --- a/apps/debug_adapter/lib/debug_adapter/completions.ex +++ b/apps/debug_adapter/lib/debug_adapter/completions.ex @@ -10,7 +10,7 @@ defmodule ElixirLS.DebugAdapter.Completions do snippet: snippet }) when type in [:function, :macro] do - %{ + %GenDAP.Structures.CompletionItem{ type: "function", detail: Atom.to_string(type), label: "#{name}/#{arity}", @@ -29,7 +29,7 @@ defmodule ElixirLS.DebugAdapter.Completions do other -> other end - %{ + %GenDAP.Structures.CompletionItem{ type: "module", detail: if(subtype != nil, do: Atom.to_string(subtype)), label: name, @@ -41,7 +41,7 @@ defmodule ElixirLS.DebugAdapter.Completions do type: :variable, name: name }) do - %{ + %GenDAP.Structures.CompletionItem{ type: "variable", label: name } @@ -58,7 +58,7 @@ defmodule ElixirLS.DebugAdapter.Completions do :map_key -> "map key" end - %{ + %GenDAP.Structures.CompletionItem{ type: "field", detail: detail, label: name diff --git a/apps/debug_adapter/lib/debug_adapter/id_manager.ex b/apps/debug_adapter/lib/debug_adapter/id_manager.ex new file mode 100644 index 000000000..3cd1e0006 --- /dev/null +++ b/apps/debug_adapter/lib/debug_adapter/id_manager.ex @@ -0,0 +1,59 @@ +defmodule ElixirLS.DebugAdapter.IdManager do + @moduledoc """ + Global ID manager for Debug Adapter Protocol objects. + + Uses ERTS :atomics module for thread-safe, shared mutable counters + that can be accessed from any process without blocking. + """ + + @counter_ref :dap_id_counter + + @doc """ + Initializes the global ID counter. + Should be called once during server startup. + """ + def init do + # Create a single atomic counter starting at 1 + counter = :atomics.new(1, []) + :atomics.put(counter, 1, 1) + :persistent_term.put(@counter_ref, counter) + :ok + end + + @doc """ + Gets the next unique ID atomically. + This is thread-safe and can be called from any process. + """ + def next_id do + case :persistent_term.get(@counter_ref, nil) do + nil -> + raise "IdManager not initialized. Call IdManager.init/0 first." + + counter -> + :atomics.add_get(counter, 1, 1) + end + end + + @doc """ + Cleans up the global ID counter. + Should be called during server shutdown. + """ + def cleanup do + :persistent_term.erase(@counter_ref) + :ok + end + + @doc """ + Gets the current ID value without incrementing. + Mainly for testing/debugging purposes. + """ + def current_id do + case :persistent_term.get(@counter_ref, nil) do + nil -> + raise "IdManager not initialized. Call IdManager.init/0 first." + + counter -> + :atomics.get(counter, 1) + end + end +end diff --git a/apps/debug_adapter/lib/debug_adapter/output.ex b/apps/debug_adapter/lib/debug_adapter/output.ex index 9984b4472..f102e90e3 100644 --- a/apps/debug_adapter/lib/debug_adapter/output.ex +++ b/apps/debug_adapter/lib/debug_adapter/output.ex @@ -9,7 +9,7 @@ defmodule ElixirLS.DebugAdapter.Output do """ alias ElixirLS.Utils.WireProtocol use GenServer - use ElixirLS.DebugAdapter.Protocol + import ElixirLS.DebugAdapter.Protocol.Basic ## Client API @@ -38,31 +38,46 @@ defmodule ElixirLS.DebugAdapter.Output do ) end - def send_event(server \\ __MODULE__, event, body) do - GenServer.call(server, {:send_event, event, body}, :infinity) + def send_event(server \\ __MODULE__, body) do + GenServer.call(server, {:send_event, body}, :infinity) end def debugger_console(server \\ __MODULE__, str) when is_binary(str) do - send_event(server, "output", %{"category" => "console", "output" => maybe_append_newline(str)}) + send_event(server, %GenDAP.Events.OutputEvent{ + seq: nil, + body: %{category: "console", output: maybe_append_newline(str)} + }) end def debugger_important(server \\ __MODULE__, str) when is_binary(str) do - send_event(server, "output", %{ - "category" => "important", - "output" => maybe_append_newline(str) + send_event(server, %GenDAP.Events.OutputEvent{ + seq: nil, + body: %{ + category: "important", + output: maybe_append_newline(str) + } }) end def debuggee_out(server \\ __MODULE__, str) when is_binary(str) do - send_event(server, "output", %{"category" => "stdout", "output" => maybe_append_newline(str)}) + send_event(server, %GenDAP.Events.OutputEvent{ + seq: nil, + body: %{category: "stdout", output: maybe_append_newline(str)} + }) end def debuggee_err(server \\ __MODULE__, str) when is_binary(str) do - send_event(server, "output", %{"category" => "stderr", "output" => maybe_append_newline(str)}) + send_event(server, %GenDAP.Events.OutputEvent{ + seq: nil, + body: %{category: "stderr", output: maybe_append_newline(str)} + }) end def ex_unit_event(server \\ __MODULE__, data) when is_map(data) do - send_event(server, "output", %{"category" => "ex_unit", "output" => "", "data" => data}) + send_event(server, %GenDAP.Events.OutputEvent{ + seq: nil, + body: %{category: "ex_unit", output: "", data: data} + }) end def telemetry(server \\ __MODULE__, event, properties, measurements) @@ -82,13 +97,16 @@ defmodule ElixirLS.DebugAdapter.Output do "elixir_ls.mix_target" => Mix.target() } - send_event(server, "output", %{ - "category" => "telemetry", - "output" => event, - "data" => %{ - "name" => event, - "properties" => Map.merge(common_properties, properties), - "measurements" => measurements + send_event(server, %GenDAP.Events.OutputEvent{ + seq: nil, + body: %{ + category: "telemetry", + output: event, + data: %{ + "name" => event, + "properties" => Map.merge(common_properties, properties), + "measurements" => measurements + } } }) end @@ -109,6 +127,15 @@ defmodule ElixirLS.DebugAdapter.Output do end @impl GenServer + def handle_call({:send_response, request_packet, body = %struct{}}, _from, seq) do + {:ok, dumped_body} = + SchematicV.dump(struct.schematic(), %{body | seq: seq, request_seq: request_packet["seq"]}) + + res = WireProtocol.send(dumped_body) + + {:reply, res, seq + 1} + end + def handle_call({:send_response, request_packet, body}, _from, seq) do res = WireProtocol.send(response(seq, request_packet["seq"], request_packet["command"], body)) {:reply, res, seq + 1} @@ -120,25 +147,39 @@ defmodule ElixirLS.DebugAdapter.Output do _from, seq ) do - res = - WireProtocol.send( - error_response( - seq, - request_packet["seq"], - request_packet["command"], - message, - format, - variables, - send_telemetry, - show_user - ) + {:ok, dumped_error} = + SchematicV.dump( + GenDAP.Structures.ErrorResponse.schematic(), + %GenDAP.Structures.ErrorResponse{ + seq: seq, + request_seq: request_packet["seq"], + command: request_packet["command"], + type: "response", + success: false, + message: message, + body: %{ + error: %GenDAP.Structures.Message{ + # TODO unique ids + id: 1, + format: format, + variables: variables, + send_telemetry: send_telemetry, + show_user: show_user + } + } + } ) + res = WireProtocol.send(dumped_error) + {:reply, res, seq + 1} end - def handle_call({:send_event, event, body}, _from, seq) do - res = WireProtocol.send(event(seq, event, body)) + def handle_call({:send_event, body = %struct{seq: _}}, _from, seq) do + # IO.warn(inspect(%{body | seq: seq})) + {:ok, dumped_event} = SchematicV.dump(struct.schematic(), %{body | seq: seq}) + # IO.warn(inspect(dumped_event)) + res = WireProtocol.send(dumped_event) {:reply, res, seq + 1} end end diff --git a/apps/debug_adapter/lib/debug_adapter/protocol.basic.ex b/apps/debug_adapter/lib/debug_adapter/protocol.basic.ex index b9d71ba41..8cd68a1d6 100644 --- a/apps/debug_adapter/lib/debug_adapter/protocol.basic.ex +++ b/apps/debug_adapter/lib/debug_adapter/protocol.basic.ex @@ -23,6 +23,18 @@ defmodule ElixirLS.DebugAdapter.Protocol.Basic do end end + defmacro response(seq, request_seq, command) do + quote do + %{ + "type" => "response", + "command" => unquote(command), + "seq" => unquote(seq), + "request_seq" => unquote(request_seq), + "success" => true + } + end + end + defmacro response(seq, request_seq, command, body) do quote do %{ @@ -77,4 +89,14 @@ defmodule ElixirLS.DebugAdapter.Protocol.Basic do } end end + + defmacro event(seq, event) do + quote do + %{ + "type" => "event", + "event" => unquote(event), + "seq" => unquote(seq) + } + end + end end diff --git a/apps/debug_adapter/lib/debug_adapter/server.ex b/apps/debug_adapter/lib/debug_adapter/server.ex index 5edc1a3f8..af49e044e 100644 --- a/apps/debug_adapter/lib/debug_adapter/server.ex +++ b/apps/debug_adapter/lib/debug_adapter/server.ex @@ -19,51 +19,43 @@ defmodule ElixirLS.DebugAdapter.Server do alias ElixirLS.DebugAdapter.{ Output, Stacktrace, - Protocol, Variables, Utils, BreakpointCondition, Binding, - ModuleInfoCache + ModuleInfoCache, + IdManager, + VariableRegistry, + ThreadRegistry } alias ElixirLS.DebugAdapter.Stacktrace.Frame alias ElixirLS.Utils.Launch + import ElixirLS.DebugAdapter.Protocol.Basic use GenServer - use Protocol @temp_beam_dir ".elixir_ls/temp_beams" + defmodule PausedProcess do + defstruct stack: nil, + registry: %ElixirLS.DebugAdapter.VariableRegistry{}, + ref: nil + end + defstruct client_info: nil, config: %{}, dbg_session: nil, task_ref: nil, update_threads_ref: nil, - thread_ids_to_pids: %{}, - pids_to_thread_ids: %{}, - paused_processes: %{ - evaluator: %{ - var_ids_to_vars: %{}, - vars_to_var_ids: %{} - } - }, + thread_registry: %ThreadRegistry{}, + paused_processes: %{}, requests: %{}, requests_seqs_by_pid: %{}, progresses: MapSet.new(), - next_id: 1, output: Output, breakpoints: %{}, function_breakpoints: %{} - defmodule PausedProcess do - defstruct stack: nil, - frame_ids_to_frames: %{}, - frames_to_frame_ids: %{}, - var_ids_to_vars: %{}, - vars_to_var_ids: %{}, - ref: nil - end - ## Client API def start_link(opts \\ []) do @@ -177,12 +169,20 @@ defmodule ElixirLS.DebugAdapter.Server do @impl GenServer def init(opts) do + IdManager.init() state = if opts[:output], do: %__MODULE__{output: opts[:output]}, else: %__MODULE__{} + + # Initialize the evaluator process entry + evaluator_process = %PausedProcess{} + state = put_in(state.paused_processes[:evaluator], evaluator_process) + {:ok, state} end @impl GenServer def terminate(reason, _state) do + IdManager.cleanup() + case reason do :normal -> :ok @@ -305,8 +305,10 @@ defmodule ElixirLS.DebugAdapter.Server do paused_process = %PausedProcess{stack: stacktrace, ref: ref} state = put_in(state.paused_processes[pid], paused_process) - body = %{"reason" => "breakpoint", "threadId" => thread_id, "allThreadsStopped" => false} - Output.send_event("stopped", body) + Output.send_event(%GenDAP.Events.StoppedEvent{ + seq: nil, + body: %{reason: "breakpoint", thread_id: thread_id, all_threads_stopped: false} + }) {:noreply, %{state | dbg_session: from}} end @@ -328,8 +330,11 @@ defmodule ElixirLS.DebugAdapter.Server do updated_progresses = if MapSet.member?(state.progresses, seq) do - Output.send_event("progressEnd", %{ - "progressId" => seq + Output.send_event(%GenDAP.Events.ProgressEndEvent{ + seq: nil, + body: %{ + progress_id: to_string(seq) + } }) MapSet.delete(state.progresses, seq) @@ -376,21 +381,26 @@ defmodule ElixirLS.DebugAdapter.Server do {:reply, :ok, state} end - def handle_call( - {:get_variable_reference, child_type, pid, value}, - _from, + @impl GenServer + def handle_cast( + {:receive_packet, request(seq, "disconnect" = command) = packet}, state = %__MODULE__{} ) do - if Map.has_key?(state.paused_processes, pid) do - {state, var_id} = get_variable_reference(child_type, state, pid, value) - {:reply, {:ok, var_id}, state} - else - {:reply, {:error, :not_paused}, state} + case GenDAP.Requests.new(packet) do + {:ok, _} -> + :ok + + {:error, "unexpected request payload"} -> + :ok + + {:error, e} -> + e |> IO.inspect(label: "#{command}: #{seq}") + # Process.sleep(200) + System.halt(1) + # raise "#{command}: #{seq}" + e |> IO.inspect(label: "#{command}: #{seq}") end - end - @impl GenServer - def handle_cast({:receive_packet, request(_, "disconnect") = packet}, state = %__MODULE__{}) do Output.debugger_console("Received disconnect request\n") Output.telemetry("dap_request", %{"elixir_ls.dap_command" => "disconnect"}, %{ @@ -413,7 +423,7 @@ defmodule ElixirLS.DebugAdapter.Server do # disable logger so we do not get unexpected # [notice] SIGTERM received - shutting down Logger.configure(level: :none) - Output.send_response(packet, %{}) + Output.send_response(packet, %GenDAP.Requests.DisconnectResponse{seq: 0, request_seq: 0}) {:noreply, state, {:continue, :disconnect}} end @@ -421,11 +431,20 @@ defmodule ElixirLS.DebugAdapter.Server do def handle_cast({:receive_packet, request(seq, command) = packet}, state = %__MODULE__{}) do start_time = System.monotonic_time(:millisecond) + struct = + case GenDAP.Requests.new(packet) do + {:ok, struct} -> + struct + + {:error, "unexpected request payload"} -> + packet + end + try do if state.client_info == nil do case packet do request(_, "initialize") -> - {response_body, state} = handle_request(packet, state) + {response_body, state} = handle_request(struct, state) elapsed = System.monotonic_time(:millisecond) - start_time Output.send_response(packet, response_body) @@ -447,7 +466,7 @@ defmodule ElixirLS.DebugAdapter.Server do end else state = - case handle_request(packet, state) do + case handle_request(struct, state) do {response_body, state} -> elapsed = System.monotonic_time(:millisecond) - start_time Output.send_response(packet, response_body) @@ -488,7 +507,21 @@ defmodule ElixirLS.DebugAdapter.Server do {:noreply, state} catch kind, error -> - {payload, stacktrace} = Exception.blame(kind, error, __STACKTRACE__) + stacktrace = __STACKTRACE__ + + {payload, stacktrace} = + try do + Exception.blame(kind, error, stacktrace) + catch + kind_1, error_1 -> + # in case of error in Exception.blame we want to use the original error and stacktrace + Output.debugger_console( + "Exception.blame failed: #{Exception.format(kind_1, error_1, __STACKTRACE__)}" + ) + + {error, stacktrace} + end + message = Exception.format(kind, payload, stacktrace) Output.debugger_console(message) Output.send_error_response(packet, "internalServerError", message, %{}, true, false) @@ -497,6 +530,20 @@ defmodule ElixirLS.DebugAdapter.Server do end @impl GenServer + def handle_cast({:merge_registry, pid, registry}, state = %__MODULE__{}) do + case Map.fetch(state.paused_processes, pid) do + {:ok, paused_process = %PausedProcess{}} -> + merged_registry = VariableRegistry.merge(paused_process.registry, registry) + paused_process = %{paused_process | registry: merged_registry} + state = put_in(state.paused_processes[pid], paused_process) + {:noreply, state} + + :error -> + # Process might have been resumed or exited, ignore + {:noreply, state} + end + end + def handle_cast({event, pid}, state = %__MODULE__{}) when event in [:breakpoint_reached, :paused] do # when debugged pid exits we get another breakpoint reached message (at least on OTP 23) @@ -522,8 +569,11 @@ defmodule ElixirLS.DebugAdapter.Server do reason = get_stop_reason(state, event, paused_process.stack) - body = %{"reason" => reason, "threadId" => thread_id, "allThreadsStopped" => false} - Output.send_event("stopped", body) + Output.send_event(%GenDAP.Events.StoppedEvent{ + seq: nil, + body: %{reason: reason, thread_id: thread_id, all_threads_stopped: false} + }) + state else Process.monitor(pid) @@ -564,8 +614,8 @@ defmodule ElixirLS.DebugAdapter.Server do ) end - Output.send_event("terminated", %{"restart" => false}) - Output.send_event("exited", %{"exitCode" => exit_code}) + Output.send_event(%GenDAP.Events.TerminatedEvent{seq: nil, body: %{restart: false}}) + Output.send_event(%GenDAP.Events.ExitedEvent{seq: nil, body: %{exit_code: exit_code}}) {:noreply, %{state | task_ref: nil}} end @@ -601,8 +651,11 @@ defmodule ElixirLS.DebugAdapter.Server do # no MapSet.pop... updated_progresses = if MapSet.member?(state.progresses, seq) do - Output.send_event("progressEnd", %{ - "progressId" => seq + Output.send_event(%GenDAP.Events.ProgressEndEvent{ + seq: nil, + body: %{ + progress_id: to_string(seq) + } }) MapSet.delete(state.progresses, seq) @@ -669,9 +722,14 @@ defmodule ElixirLS.DebugAdapter.Server do ## Helpers - defp handle_request(initialize_req(_, client_info), %__MODULE__{client_info: nil} = state) do + defp handle_request( + %GenDAP.Requests.InitializeRequest{ + arguments: %GenDAP.Structures.InitializeRequestArguments{} = args + }, + %__MODULE__{client_info: nil} = state + ) do # linesStartAt1 is true by default and we only support 1-based indexing - if client_info["linesStartAt1"] == false do + if args.lines_start_at1 == false do raise ServerError, message: "invalidRequest", format: "0-based lines are not supported", @@ -680,7 +738,7 @@ defmodule ElixirLS.DebugAdapter.Server do end # columnsStartAt1 is true by default and we only support 1-based indexing - if client_info["columnsStartAt1"] == false do + if args.columns_start_at1 == false do raise ServerError, message: "invalidRequest", format: "0-based columns are not supported", @@ -689,27 +747,38 @@ defmodule ElixirLS.DebugAdapter.Server do end # pathFormat is `path` by default and we do not support other, e.g. `uri` - if client_info["pathFormat"] not in [nil, "path"] do + if args.path_format not in [nil, "path"] do raise ServerError, message: "invalidRequest", format: "pathFormat {pathFormat} is not supported", - variables: %{"pathFormat" => client_info["pathFormat"]}, + variables: %{"pathFormat" => args.path_format}, show_user: true end - {capabilities(), %{state | client_info: client_info}} + {%GenDAP.Requests.InitializeResponse{seq: 0, request_seq: 0, body: capabilities()}, + %{state | client_info: args}} end - defp handle_request(initialize_req(_, _client_info), _state = %__MODULE__{}) do + defp handle_request(%GenDAP.Requests.InitializeRequest{}, _state = %__MODULE__{}) do raise ServerError, message: "invalidRequest", format: "Debugger request initialize was not expected", variables: %{} end - defp handle_request(cancel_req(_, args), %__MODULE__{requests: requests} = state) do + defp handle_request( + %GenDAP.Requests.CancelRequest{arguments: args = %GenDAP.Structures.CancelArguments{}}, + %__MODULE__{requests: requests} = state + ) do # in or case progressId is requestId so choose first not null - request_or_progress_id = args["requestId"] || args["progressId"] + request_or_progress_id = args.request_id || args.progress_id + + request_or_progress_id = + if is_binary(request_or_progress_id) do + String.to_integer(request_or_progress_id) + else + request_or_progress_id + end {request, updated_requests} = Map.pop(requests, request_or_progress_id) @@ -724,8 +793,11 @@ defmodule ElixirLS.DebugAdapter.Server do # send progressEnd if cancelling a progress updated_progresses = if MapSet.member?(state.progresses, request_or_progress_id) do - Output.send_event("progressEnd", %{ - "progressId" => request_or_progress_id + Output.send_event(%GenDAP.Events.ProgressEndEvent{ + seq: nil, + body: %{ + progress_id: to_string(request_or_progress_id) + } }) MapSet.delete(state.progresses, request_or_progress_id) @@ -751,10 +823,10 @@ defmodule ElixirLS.DebugAdapter.Server do progresses: updated_progresses } - {%{}, state} + {%GenDAP.Requests.CancelResponse{seq: 0, request_seq: 0}, state} end - defp handle_request(launch_req(_, config), state = %__MODULE__{}) do + defp handle_request(%GenDAP.Requests.LaunchRequest{arguments: config}, state = %__MODULE__{}) do server = self() {_, ref} = spawn_monitor(fn -> launch(config, server) end) @@ -764,7 +836,8 @@ defmodule ElixirLS.DebugAdapter.Server do {:ok, config} -> # sending `initialized` signals that we are ready to receive configuration requests # setBreakpoints, setFunctionBreakpoints and configurationDone - Output.send_event("initialized", %{}) + Output.send_event(%GenDAP.Events.InitializedEvent{seq: nil}) + # Process.sleep(30000) send(self(), :update_threads) Output.telemetry( @@ -799,8 +872,12 @@ defmodule ElixirLS.DebugAdapter.Server do {%ServerError{} = error, stack} -> exit_code = 1 - Output.send_event("terminated", %{"restart" => false}) - Output.send_event("exited", %{"exitCode" => exit_code}) + Output.send_event(%GenDAP.Events.TerminatedEvent{seq: nil, body: %{restart: false}}) + + Output.send_event(%GenDAP.Events.ExitedEvent{ + seq: nil, + body: %{exit_code: exit_code} + }) reraise error, stack @@ -810,8 +887,12 @@ defmodule ElixirLS.DebugAdapter.Server do Output.debugger_console(message) exit_code = 1 - Output.send_event("terminated", %{"restart" => false}) - Output.send_event("exited", %{"exitCode" => exit_code}) + Output.send_event(%GenDAP.Events.TerminatedEvent{seq: nil, body: %{restart: false}}) + + Output.send_event(%GenDAP.Events.ExitedEvent{ + seq: nil, + body: %{exit_code: exit_code} + }) raise ServerError, message: "launchError", @@ -822,10 +903,10 @@ defmodule ElixirLS.DebugAdapter.Server do end end - {%{}, %{state | config: config}} + {%GenDAP.Requests.LaunchResponse{seq: 0, request_seq: 0}, %{state | config: config}} end - defp handle_request(attach_req(_, config), state = %__MODULE__{}) do + defp handle_request(%GenDAP.Requests.AttachRequest{arguments: config}, state = %__MODULE__{}) do server = self() :net_kernel.monitor_nodes(true, %{ @@ -841,7 +922,7 @@ defmodule ElixirLS.DebugAdapter.Server do {:ok, config} -> # sending `initialized` signals that we are ready to receive configuration requests # setBreakpoints, setFunctionBreakpoints and configurationDone - Output.send_event("initialized", %{}) + Output.send_event(%GenDAP.Events.InitializedEvent{seq: nil}) send(self(), :update_threads) Output.telemetry( @@ -868,7 +949,10 @@ defmodule ElixirLS.DebugAdapter.Server do :ok {%ServerError{} = error, stack} -> - Output.send_event("terminated", %{"restart" => false}) + Output.send_event(%GenDAP.Events.TerminatedEvent{ + seq: nil, + body: %{restart: false} + }) reraise error, stack @@ -877,7 +961,10 @@ defmodule ElixirLS.DebugAdapter.Server do Output.debugger_console(message) - Output.send_event("terminated", %{"restart" => false}) + Output.send_event(%GenDAP.Events.TerminatedEvent{ + seq: nil, + body: %{restart: false} + }) raise ServerError, message: "attachError", @@ -888,14 +975,15 @@ defmodule ElixirLS.DebugAdapter.Server do end end - {%{}, %{state | config: config}} + {%GenDAP.Requests.AttachResponse{seq: 0, request_seq: 0}, %{state | config: config}} end defp handle_request( - source_req(_, args), + %GenDAP.Requests.SourceRequest{arguments: args = %GenDAP.Structures.SourceArguments{}}, state = %__MODULE__{} ) do - path = args["source"]["path"] + source = %GenDAP.Structures.Source{} = args.source + path = source.path content = cond do @@ -913,11 +1001,11 @@ defmodule ElixirLS.DebugAdapter.Server do File.read!(path) end - {%{"content" => content}, state} + {%GenDAP.Requests.SourceResponse{seq: 0, request_seq: 0, body: %{content: content}}, state} end defp handle_request( - set_breakpoints_req(_, %{"path" => _path}, _breakpoints), + %GenDAP.Requests.SetBreakpointsRequest{}, %__MODULE__{config: %{"noDebug" => true}} ) do raise ServerError, @@ -928,14 +1016,18 @@ defmodule ElixirLS.DebugAdapter.Server do end defp handle_request( - set_breakpoints_req(_, %{"path" => path}, breakpoints), + %GenDAP.Requests.SetBreakpointsRequest{ + arguments: args = %GenDAP.Structures.SetBreakpointsArguments{} + }, state = %__MODULE__{} ) do - path = Path.absname(path) - new_lines = for %{"line" => line} <- breakpoints, do: line + source = %GenDAP.Structures.Source{} = args.source + path = Path.absname(source.path) + new_lines = for %GenDAP.Structures.SourceBreakpoint{line: line} <- args.breakpoints, do: line new_conditions = - for b <- breakpoints, do: {b["condition"], b["logMessage"], b["hitCondition"]} + for b = %GenDAP.Structures.SourceBreakpoint{} <- args.breakpoints, + do: {b.condition, b.log_message, b.hit_condition} existing_bps = state.breakpoints[path] || [] existing_bp_lines = for {_modules, line} <- existing_bps, do: line @@ -957,17 +1049,24 @@ defmodule ElixirLS.DebugAdapter.Server do put_in(state.breakpoints[path], new_bps) end - breakpoints_json = + breakpoints_result = Enum.map(result, fn - {:ok, _, _} -> %{"verified" => true} - {:error, error} -> %{"verified" => false, "message" => error, "reason" => "failed"} + {:ok, _, _} -> + %GenDAP.Structures.Breakpoint{verified: true} + + {:error, error} -> + %GenDAP.Structures.Breakpoint{verified: false, message: error, reason: "failed"} end) - {%{"breakpoints" => breakpoints_json}, state} + {%GenDAP.Requests.SetBreakpointsResponse{ + seq: 0, + request_seq: 0, + body: %{breakpoints: breakpoints_result} + }, state} end defp handle_request( - set_function_breakpoints_req(_, _breakpoints), + %GenDAP.Requests.SetFunctionBreakpointsRequest{}, %__MODULE__{config: %{"noDebug" => true}} ) do raise ServerError, @@ -978,12 +1077,14 @@ defmodule ElixirLS.DebugAdapter.Server do end defp handle_request( - set_function_breakpoints_req(_, breakpoints), + %GenDAP.Requests.SetFunctionBreakpointsRequest{ + arguments: args = %GenDAP.Structures.SetFunctionBreakpointsArguments{} + }, state = %__MODULE__{} ) do mfas = - for %{"name" => name} = breakpoint <- breakpoints do - {Utils.parse_mfa(name), {breakpoint["condition"], breakpoint["hitCondition"]}} + for %GenDAP.Structures.FunctionBreakpoint{name: name} = breakpoint <- args.breakpoints do + {Utils.parse_mfa(name), {breakpoint.condition, breakpoint.hit_condition}} end parsed_mfas_conditions = for {{:ok, mfa}, condition} <- mfas, into: %{}, do: {mfa, condition} @@ -1089,64 +1190,90 @@ defmodule ElixirLS.DebugAdapter.Server do | function_breakpoints: successful } - breakpoints_json = + breakpoints_result = Enum.map(mfas, fn {{:ok, mfa}, _} -> case results[mfa] do {:ok, _} -> - %{"verified" => true} + %GenDAP.Structures.Breakpoint{verified: true} {:error, error} -> - %{"verified" => false, "message" => inspect(error), "reason" => "failed"} + %GenDAP.Structures.Breakpoint{ + verified: false, + message: inspect(error), + reason: "failed" + } end {{:error, error}, _} -> - %{"verified" => false, "message" => error, "reason" => "failed"} + %GenDAP.Structures.Breakpoint{verified: false, message: error, reason: "failed"} end) - {%{"breakpoints" => breakpoints_json}, state} + {%GenDAP.Requests.SetFunctionBreakpointsResponse{ + seq: 0, + request_seq: 0, + body: %{breakpoints: breakpoints_result} + }, state} end - defp handle_request(configuration_done_req(_), state = %__MODULE__{}) do + defp handle_request( + %GenDAP.Requests.ConfigurationDoneRequest{}, + state = %__MODULE__{} + ) do unless state.config["noDebug"] do :int.auto_attach([:break], build_attach_mfa(:breakpoint_reached)) end {_pid, task_ref} = spawn_monitor(fn -> launch_task(state.config) end) - {%{}, %{state | task_ref: task_ref}} + {%GenDAP.Requests.ConfigurationDoneResponse{seq: 0, request_seq: 0}, + %{state | task_ref: task_ref}} end - defp handle_request(threads_req(_), state = %__MODULE__{}) do + defp handle_request( + %GenDAP.Requests.ThreadsRequest{}, + state = %__MODULE__{} + ) do snapshot_by_pid = get_snapshot_by_pid() {state, thread_ids} = update_threads(state, snapshot_by_pid) threads = for thread_id <- thread_ids, - pid = state.thread_ids_to_pids[thread_id], + {:ok, pid} = ThreadRegistry.get_pid_by_thread_id(state.thread_registry, thread_id), (process_name = get_process_name(pid, snapshot_by_pid)) != nil do full_name = "#{process_name} #{:erlang.pid_to_list(pid)}" - %{"id" => thread_id, "name" => full_name} + %GenDAP.Structures.Thread{id: thread_id, name: full_name} end - |> Enum.sort_by(fn %{"name" => name} -> name end) + |> Enum.sort_by(fn %GenDAP.Structures.Thread{name: name} -> name end) - {%{"threads" => threads}, state} + {%GenDAP.Requests.ThreadsResponse{seq: 0, request_seq: 0, body: %{threads: threads}}, state} end - defp handle_request(terminate_threads_req(_, thread_ids), state = %__MODULE__{}) do - for {id, pid} <- state.thread_ids_to_pids, - id in thread_ids do - # :kill is untrappable - # do not need to cleanup here, :DOWN message handler will do it - Process.monitor(pid) - Process.exit(pid, :kill) + defp handle_request( + %GenDAP.Requests.TerminateThreadsRequest{ + arguments: args = %GenDAP.Structures.TerminateThreadsArguments{} + }, + state = %__MODULE__{} + ) do + for thread_id <- args.thread_ids do + case ThreadRegistry.get_pid_by_thread_id(state.thread_registry, thread_id) do + {:ok, pid} -> + # :kill is untrappable + # do not need to cleanup here, :DOWN message handler will do it + Process.monitor(pid) + Process.exit(pid, :kill) + + :error -> + # thread_id not found, treat as already terminated + :ok + end end - {%{}, state} + {%GenDAP.Requests.TerminateThreadsResponse{seq: 0, request_seq: 0}, state} end defp handle_request( - pause_req(_, _thread_id), + %GenDAP.Requests.PauseRequest{}, %__MODULE__{config: %{"noDebug" => true}} ) do raise ServerError, @@ -1157,19 +1284,24 @@ defmodule ElixirLS.DebugAdapter.Server do show_user: true end - defp handle_request(pause_req(_, thread_id), state = %__MODULE__{}) do - pid = get_pid_by_thread_id!(state, thread_id, true) + defp handle_request( + %GenDAP.Requests.PauseRequest{arguments: args = %GenDAP.Structures.PauseArguments{}}, + state = %__MODULE__{} + ) do + pid = get_pid_by_thread_id!(state, args.thread_id, true) :int.attach(pid, build_attach_mfa(:paused)) - {%{}, state} + {%GenDAP.Requests.PauseResponse{seq: 0, request_seq: 0}, state} end defp handle_request( - request(_, "stackTrace", %{"threadId" => thread_id} = args), + %GenDAP.Requests.StackTraceRequest{ + arguments: args = %GenDAP.Structures.StackTraceArguments{} + }, state = %__MODULE__{} ) do - pid = get_pid_by_thread_id!(state, thread_id, false) + pid = get_pid_by_thread_id!(state, args.thread_id, false) case state.paused_processes[pid] do %PausedProcess{} = paused_process -> @@ -1177,67 +1309,82 @@ defmodule ElixirLS.DebugAdapter.Server do start_frame = case args do - %{"startFrame" => start_frame} when is_integer(start_frame) -> start_frame - _ -> 0 + %GenDAP.Structures.StackTraceArguments{start_frame: start_frame} + when is_integer(start_frame) -> + start_frame + + _ -> + 0 end end_frame = case args do - %{"levels" => levels} when is_integer(levels) and levels > 0 -> start_frame + levels - _ -> -1 + %GenDAP.Structures.StackTraceArguments{levels: levels} + when is_integer(levels) and levels > 0 -> + start_frame + levels + + _ -> + -1 end stack_frames = Enum.slice(paused_process.stack, start_frame..end_frame//1) {state, frame_ids} = ensure_frame_ids(state, pid, stack_frames) - stack_frames_json = + stack_frames_result = for {%Frame{} = stack_frame, frame_id} <- Enum.zip([stack_frames, frame_ids]) do - %{ - "id" => frame_id, - "name" => Stacktrace.Frame.name(stack_frame), - "line" => stack_frame.line, - "column" => 0, - "source" => %{"path" => stack_frame.file} + %GenDAP.Structures.StackFrame{ + id: frame_id, + name: Stacktrace.Frame.name(stack_frame), + line: stack_frame.line, + column: 0, + source: %GenDAP.Structures.Source{path: stack_frame.file} } end - {%{"stackFrames" => stack_frames_json, "totalFrames" => total_frames}, state} + {%GenDAP.Requests.StackTraceResponse{ + seq: 0, + request_seq: 0, + body: %{stack_frames: stack_frames_result, total_frames: total_frames} + }, state} nil -> raise ServerError, message: "invalidArgument", format: "Process with threadId {threadId} and pid {pid} is not paused", variables: %{ - "threadId" => inspect(thread_id), + "threadId" => inspect(args.thread_id), "pid" => inspect(pid) }, send_telemetry: false end end - defp handle_request(request(_, "scopes", %{"frameId" => frame_id}), state = %__MODULE__{}) do + defp handle_request( + %GenDAP.Requests.ScopesRequest{arguments: args = %GenDAP.Structures.ScopesArguments{}}, + state = %__MODULE__{} + ) do {state, scopes} = - case find_frame(state.paused_processes, frame_id) do + case find_frame(state.paused_processes, args.frame_id) do {pid, %Frame{dbg_frame?: true} = frame} -> {state, bindings_id} = ensure_var_id(state, pid, frame.bindings) - process_info = Process.info(pid) + process_info = Process.info(pid) || [] {state, process_info_id} = ensure_var_id(state, pid, process_info) - vars_scope = %{ - "name" => "variables", - "presentationHint" => "locals", - "variablesReference" => bindings_id, - "namedVariables" => Enum.count(frame.bindings), - "indexedVariables" => 0, - "expensive" => false + vars_scope = %GenDAP.Structures.Scope{ + name: "variables", + presentation_hint: "locals", + variables_reference: bindings_id, + named_variables: Enum.count(frame.bindings), + indexed_variables: 0, + expensive: false } - process_info_scope = %{ - "name" => "process info", - "variablesReference" => process_info_id, - "namedVariables" => length(process_info), - "indexedVariables" => 0, - "expensive" => false + process_info_scope = %GenDAP.Structures.Scope{ + name: "process info", + variables_reference: process_info_id, + named_variables: length(process_info), + indexed_variables: 0, + expensive: false } scopes = @@ -1254,7 +1401,7 @@ defmodule ElixirLS.DebugAdapter.Server do process_info = try do - Process.info(pid) + Process.info(pid) || [] rescue ArgumentError -> # remote pid @@ -1263,51 +1410,51 @@ defmodule ElixirLS.DebugAdapter.Server do {state, process_info_id} = ensure_var_id(state, pid, process_info) - vars_scope = %{ - "name" => "variables", - "presentationHint" => "locals", - "variablesReference" => vars_id, - "namedVariables" => map_size(variables), - "indexedVariables" => 0, - "expensive" => false + vars_scope = %GenDAP.Structures.Scope{ + name: "variables", + presentation_hint: "locals", + variables_reference: vars_id, + named_variables: map_size(variables), + indexed_variables: 0, + expensive: false } - versioned_vars_scope = %{ - "name" => "versioned variables", - "presentationHint" => "locals", - "variablesReference" => versioned_vars_id, - "namedVariables" => Enum.count(frame.bindings), - "indexedVariables" => 0, - "expensive" => false + versioned_vars_scope = %GenDAP.Structures.Scope{ + name: "versioned variables", + presentation_hint: "locals", + variables_reference: versioned_vars_id, + named_variables: Enum.count(frame.bindings), + indexed_variables: 0, + expensive: false } args_scope = if frame.args != :undefined do - %{ - "name" => "arguments", - "presentationHint" => "arguments", - "variablesReference" => args_id, - "namedVariables" => 0, - "indexedVariables" => Enum.count(frame.args), - "expensive" => false + %GenDAP.Structures.Scope{ + name: "arguments", + presentation_hint: "arguments", + variables_reference: args_id, + named_variables: 0, + indexed_variables: Enum.count(frame.args), + expensive: false } end - messages_scope = %{ - "name" => "messages", - "variablesReference" => messages_id, - "namedVariables" => 0, - "indexedVariables" => Enum.count(frame.messages), - "expensive" => false + messages_scope = %GenDAP.Structures.Scope{ + name: "messages", + variables_reference: messages_id, + named_variables: 0, + indexed_variables: Enum.count(frame.messages), + expensive: false } - process_info_scope = %{ - "name" => "process info", - "presentationHint" => "registers", - "variablesReference" => process_info_id, - "namedVariables" => length(process_info), - "indexedVariables" => 0, - "expensive" => false + process_info_scope = %GenDAP.Structures.Scope{ + name: "process info", + presentation_hint: "registers", + variables_reference: process_info_id, + named_variables: length(process_info), + indexed_variables: 0, + expensive: false } scopes = @@ -1326,39 +1473,68 @@ defmodule ElixirLS.DebugAdapter.Server do message: "invalidArgument", format: "frameId not found: {frameId}", variables: %{ - "frameId" => inspect(frame_id) + "frameId" => inspect(args.frame_id) }, send_telemetry: false end - {%{"scopes" => scopes}, state} + {%GenDAP.Requests.ScopesResponse{seq: 0, request_seq: 0, body: %{scopes: scopes}}, state} end defp handle_request( - request(_, "variables", %{"variablesReference" => var_id} = args), + %GenDAP.Requests.VariablesRequest{ + arguments: args = %GenDAP.Structures.VariablesArguments{} + }, state = %__MODULE__{} ) do async_fn = fn -> - {pid, var} = find_var!(state.paused_processes, var_id) - vars_json = variables(state, pid, var, args["start"], args["count"], args["filter"]) - %{"variables" => vars_json} + {pid, var} = find_var!(state.paused_processes, args.variables_reference) + + # Get the existing registry from the paused process + existing_registry = + case Map.fetch!(state.paused_processes, pid) do + %PausedProcess{registry: registry} -> registry + end + + {updated_registry, variables} = + variables_async( + var, + args.start, + args.count, + args.filter, + state.client_info, + existing_registry + ) + + # Merge the registry back to the server state + GenServer.cast(__MODULE__, {:merge_registry, pid, updated_registry}) + + %GenDAP.Requests.VariablesResponse{seq: 0, request_seq: 0, body: %{variables: variables}} end {:async, async_fn, state} end defp handle_request( - request(seq, "evaluate", %{"expression" => expr} = args), - state = %__MODULE__{} + %GenDAP.Requests.EvaluateRequest{ + arguments: args = %GenDAP.Structures.EvaluateArguments{}, + seq: seq + }, + state = %__MODULE__{ + client_info: client_info = %GenDAP.Structures.InitializeRequestArguments{} + } ) do state = - if state.client_info["supportsProgressReporting"] do - Output.send_event("progressStart", %{ - "progressId" => seq, - "title" => "Evaluating expression", - "message" => expr, - "requestId" => seq, - "cancellable" => true + if client_info.supports_progress_reporting do + Output.send_event(%GenDAP.Events.ProgressStartEvent{ + seq: nil, + body: %{ + progress_id: to_string(seq), + title: "Evaluating expression", + message: args.expression, + request_id: seq, + cancellable: true + } }) %{state | progresses: MapSet.put(state.progresses, seq)} @@ -1367,32 +1543,48 @@ defmodule ElixirLS.DebugAdapter.Server do end async_fn = fn -> - frame = frame_for_eval(state.paused_processes, args["frameId"]) + frame = frame_for_eval(state.paused_processes, args.frame_id) {_metadata, _env, binding, env_for_eval} = binding_and_env(state.paused_processes, frame) - value = evaluate_code_expression(expr, binding, env_for_eval) + value = evaluate_code_expression(args.expression, binding, env_for_eval) + + # Get the existing evaluator registry + existing_registry = + case Map.fetch!(state.paused_processes, :evaluator) do + %PausedProcess{registry: registry} -> registry + end + + {updated_registry, var_id} = + VariableRegistry.get_variable_reference(existing_registry, value) + + # Merge the registry back to the server state + GenServer.cast(__MODULE__, {:merge_registry, :evaluator, updated_registry}) child_type = Variables.child_type(value) - # we need to call here as get_variable_reference modifies the state - {:ok, var_id} = - GenServer.call( - __MODULE__, - {:get_variable_reference, child_type, :evaluator, value}, - 60_000 - ) - %{ - "result" => inspect(value), - "variablesReference" => var_id - } - |> maybe_append_children_number(state.client_info, child_type, value) - |> maybe_append_variable_type(state.client_info, value) + variable = + %{ + result: inspect(value), + variables_reference: var_id, + type: nil, + indexed_variables: nil, + named_variables: nil + } + |> maybe_append_children_number(state.client_info, child_type, value) + |> maybe_append_variable_type(state.client_info, value) + + %GenDAP.Requests.EvaluateResponse{seq: 0, request_seq: 0, body: variable} end {:async, async_fn, state} end - defp handle_request(continue_req(_, thread_id) = args, state = %__MODULE__{}) do - pid = get_pid_by_thread_id!(state, thread_id, true) + defp handle_request( + %GenDAP.Requests.ContinueRequest{ + arguments: args = %GenDAP.Structures.ContinueArguments{} + }, + state = %__MODULE__{} + ) do + pid = get_pid_by_thread_id!(state, args.thread_id, true) state = case state.dbg_session do @@ -1412,11 +1604,18 @@ defmodule ElixirLS.DebugAdapter.Server do processes_paused? = state.paused_processes |> Map.keys() |> Enum.any?(&is_pid/1) - {%{"allThreadsContinued" => not processes_paused?}, state} + {%GenDAP.Requests.ContinueResponse{ + seq: 0, + request_seq: 0, + body: %{all_threads_continued: not processes_paused?} + }, state} end - defp handle_request(next_req(_, thread_id) = args, state = %__MODULE__{}) do - pid = get_pid_by_thread_id!(state, thread_id, true) + defp handle_request( + %GenDAP.Requests.NextRequest{arguments: args = %GenDAP.Structures.NextArguments{}}, + state = %__MODULE__{} + ) do + pid = get_pid_by_thread_id!(state, args.thread_id, true) state = if match?({^pid, _ref}, state.dbg_session) do @@ -1432,13 +1631,19 @@ defmodule ElixirLS.DebugAdapter.Server do |> remove_paused_process(pid) |> maybe_continue_other_processes(args) - {%{}, state} + {%GenDAP.Requests.NextResponse{seq: 0, request_seq: 0}, state} end - defp handle_request(step_in_req(_, thread_id) = args, state = %__MODULE__{}) do - pid = get_pid_by_thread_id!(state, thread_id, true) + defp handle_request( + %GenDAP.Requests.StepInRequest{ + command: command, + arguments: args = %GenDAP.Structures.StepInArguments{} + }, + state = %__MODULE__{} + ) do + pid = get_pid_by_thread_id!(state, args.thread_id, true) - validate_dbg_pid!(state, pid, "stepIn") + validate_dbg_pid!(state, pid, command) safe_int_action(pid, :step) @@ -1447,13 +1652,19 @@ defmodule ElixirLS.DebugAdapter.Server do |> remove_paused_process(pid) |> maybe_continue_other_processes(args) - {%{}, state} + {%GenDAP.Requests.StepInResponse{seq: 0, request_seq: 0}, state} end - defp handle_request(step_out_req(_, thread_id) = args, state = %__MODULE__{}) do - pid = get_pid_by_thread_id!(state, thread_id, true) + defp handle_request( + %GenDAP.Requests.StepOutRequest{ + command: command, + arguments: args = %GenDAP.Structures.StepOutArguments{} + }, + state = %__MODULE__{} + ) do + pid = get_pid_by_thread_id!(state, args.thread_id, true) - validate_dbg_pid!(state, pid, "stepOut") + validate_dbg_pid!(state, pid, command) safe_int_action(pid, :finish) @@ -1462,18 +1673,23 @@ defmodule ElixirLS.DebugAdapter.Server do |> remove_paused_process(pid) |> maybe_continue_other_processes(args) - {%{}, state} + {%GenDAP.Requests.StepOutResponse{seq: 0, request_seq: 0}, state} end - defp handle_request(completions_req(_, text) = args, state = %__MODULE__{}) do + defp handle_request( + %GenDAP.Requests.CompletionsRequest{ + arguments: args = %GenDAP.Structures.CompletionsArguments{} + }, + state = %__MODULE__{} + ) do async_fn = fn -> # assume that the position is 1-based - line = (args["arguments"]["line"] || 1) - 1 - column = (args["arguments"]["column"] || 1) - 1 + line = (args.line || 1) - 1 + column = (args.column || 1) - 1 # for simplicity take only text from the given line up to column line = - text + args.text |> String.split(["\r\n", "\n", "\r"]) |> Enum.at(line, "") @@ -1482,7 +1698,7 @@ defmodule ElixirLS.DebugAdapter.Server do column = Utils.dap_character_to_elixir(line, column) prefix = String.slice(line, 0, column) - frame = frame_for_eval(state.paused_processes, args["arguments"]["frameId"]) + frame = frame_for_eval(state.paused_processes, args.frame_id) {metadata, env, _binding, _env_for_eval} = binding_and_env(state.paused_processes, frame) @@ -1497,13 +1713,21 @@ defmodule ElixirLS.DebugAdapter.Server do |> Enum.map(&ElixirLS.DebugAdapter.Completions.map/1) |> Enum.reject(&is_nil/1) - %{"targets" => results} + %GenDAP.Requests.CompletionsResponse{seq: 0, request_seq: 0, body: %{targets: results}} end {:async, async_fn, state} end - defp handle_request(request(_, command), %__MODULE__{}) when is_binary(command) do + defp handle_request(%_{command: command}, %__MODULE__{}) do + raise ServerError, + message: "notSupported", + format: "Debugger request #{command} is currently not supported", + variables: %{}, + show_user: true + end + + defp handle_request(request(_seq, command), %__MODULE__{}) do raise ServerError, message: "notSupported", format: "Debugger request #{command} is currently not supported", @@ -1511,7 +1735,7 @@ defmodule ElixirLS.DebugAdapter.Server do show_user: true end - defp maybe_continue_other_processes(state, %{"singleThread" => true}) do + defp maybe_continue_other_processes(state, %{single_thread: true}) do # continue dbg debug session state = case state.dbg_session do @@ -1556,8 +1780,11 @@ defmodule ElixirLS.DebugAdapter.Server do end defp get_pid_by_thread_id!(state = %__MODULE__{}, thread_id, show_message_on_error?) do - case state.thread_ids_to_pids[thread_id] do - nil -> + case ThreadRegistry.get_pid_by_thread_id(state.thread_registry, thread_id) do + {:ok, pid} -> + pid + + :error -> raise ServerError, message: "invalidArgument", format: "Unable to find process pid for DAP threadId {threadId}", @@ -1566,9 +1793,6 @@ defmodule ElixirLS.DebugAdapter.Server do }, send_telemetry: false, show_user: show_message_on_error? - - pid -> - pid end end @@ -1582,59 +1806,63 @@ defmodule ElixirLS.DebugAdapter.Server do %{state | paused_processes: paused_processes} end - defp variables(state = %__MODULE__{}, pid, var, start, count, filter) do + defp variables_async(var, start, count, filter, client_info, registry) do var_child_type = Variables.child_type(var) - if var_child_type == nil or (filter != nil and Atom.to_string(var_child_type) != filter) do - [] - else - Variables.children(var, start, count) - end - |> Enum.reduce([], fn {name, value}, acc -> - child_type = Variables.child_type(value) + children = + if var_child_type == nil or (filter != nil and Atom.to_string(var_child_type) != filter) do + [] + else + Variables.children(var, start, count) + end - case GenServer.call(__MODULE__, {:get_variable_reference, child_type, pid, value}, 60_000) do - {:ok, var_id} -> - json = - %{ - "name" => to_string(name), - "value" => inspect(value), - "variablesReference" => var_id - } - |> maybe_append_children_number(state.client_info, child_type, value) - |> maybe_append_variable_type(state.client_info, value) + {updated_registry, variables} = + Enum.reduce(children, {registry, []}, fn {name, value}, {registry_acc, acc} -> + {registry_acc, var_id} = VariableRegistry.get_variable_reference(registry_acc, value) + child_type = Variables.child_type(value) - [json | acc] + json = + %GenDAP.Structures.Variable{ + name: to_string(name), + value: inspect(value), + variables_reference: var_id + } + |> maybe_append_children_number(client_info, child_type, value) + |> maybe_append_variable_type(client_info, value) - {:error, :not_paused} -> - raise ServerError, - message: "runtimeError", - format: "process with pid {pid} is not paused", - variables: %{ - "pid" => inspect(pid) - }, - send_telemetry: false - end - end) - |> Enum.reverse() - end + {registry_acc, [json | acc]} + end) - defp get_variable_reference(nil, state, _pid, _value), do: {state, 0} + {updated_registry, Enum.reverse(variables)} + end - defp get_variable_reference(_child_type, state, pid, value), - do: ensure_var_id(state, pid, value) + defp maybe_append_children_number( + variable, + %GenDAP.Structures.InitializeRequestArguments{supports_variable_paging: true}, + :indexed, + value + ), + do: %{variable | indexed_variables: Variables.num_children(value)} - defp maybe_append_children_number(map, %{"supportsVariablePaging" => true}, atom, value) - when atom in [:indexed, :named], - do: Map.put(map, Atom.to_string(atom) <> "Variables", Variables.num_children(value)) + defp maybe_append_children_number( + variable, + %GenDAP.Structures.InitializeRequestArguments{supports_variable_paging: true}, + :named, + value + ), + do: %{variable | named_variables: Variables.num_children(value)} - defp maybe_append_children_number(map, _, _, _value), do: map + defp maybe_append_children_number(variable, _, _, _value), do: variable - defp maybe_append_variable_type(map, %{"supportsVariableType" => true}, value) do - Map.put(map, "type", Variables.type(value)) + defp maybe_append_variable_type( + variable, + %GenDAP.Structures.InitializeRequestArguments{supports_variable_type: true}, + value + ) do + %{variable | type: Variables.type(value)} end - defp maybe_append_variable_type(map, _, _value), do: map + defp maybe_append_variable_type(variable, _, _value), do: variable defp evaluate_code_expression(expr, binding, env_or_opts) do try do @@ -1644,7 +1872,21 @@ defmodule ElixirLS.DebugAdapter.Server do term catch kind, error -> - {payload, stacktrace} = Exception.blame(kind, error, prune_stacktrace(__STACKTRACE__)) + stacktrace = prune_stacktrace(__STACKTRACE__) + + {payload, stacktrace} = + try do + Exception.blame(kind, error, stacktrace) + catch + kind_1, error_1 -> + # in case of error in Exception.blame we want to use the original error and stacktrace + Output.debugger_console( + "Exception.blame failed: #{Exception.format(kind_1, error_1, __STACKTRACE__)}" + ) + + {error, stacktrace} + end + message = Exception.format(kind, payload, stacktrace) reraise( @@ -1687,7 +1929,7 @@ defmodule ElixirLS.DebugAdapter.Server do [] {_pid, %PausedProcess{} = paused_process} -> - Map.values(paused_process.frame_ids_to_frames) + Map.values(paused_process.registry.frame_ids_to_frames) end) |> Enum.filter(&match?(%Frame{bindings: bindings} when is_map(bindings), &1)) |> Enum.flat_map(fn %Frame{bindings: bindings} -> @@ -1732,8 +1974,11 @@ defmodule ElixirLS.DebugAdapter.Server do defp find_var!(paused_processes, var_id) do result = Enum.find_value(paused_processes, fn - {pid, %{var_ids_to_vars: %{^var_id => var}}} -> - {pid, var} + {pid, %PausedProcess{registry: registry}} -> + case VariableRegistry.find_var(registry, var_id) do + {:ok, var} -> {pid, var} + :error -> nil + end _ -> nil @@ -1756,8 +2001,11 @@ defmodule ElixirLS.DebugAdapter.Server do defp find_frame(paused_processes, frame_id) do Enum.find_value(paused_processes, fn - {pid, %{frame_ids_to_frames: %{^frame_id => frame}}} when is_pid(pid) -> - {pid, frame} + {pid, %{registry: registry}} when is_pid(pid) -> + case VariableRegistry.find_frame(registry, frame_id) do + {:ok, frame} -> {pid, frame} + :error -> nil + end _ -> nil @@ -1765,44 +2013,27 @@ defmodule ElixirLS.DebugAdapter.Server do end defp ensure_thread_id(state = %__MODULE__{}, pid, new_ids) when is_pid(pid) do - case state.pids_to_thread_ids do - %{^pid => thread_id} -> - {state, thread_id, new_ids} + {updated_registry, thread_id, new_ids} = + ThreadRegistry.ensure_thread_id(state.thread_registry, pid, new_ids) - _ -> - id = state.next_id - state = put_in(state.thread_ids_to_pids[id], pid) - state = put_in(state.pids_to_thread_ids[pid], id) - state = put_in(state.next_id, id + 1) - {state, id, [id | new_ids]} - end + state = %{state | thread_registry: updated_registry} + {state, thread_id, new_ids} end defp ensure_thread_ids(state = %__MODULE__{}, pids) do - {state, ids, new_ids} = - Enum.reduce(pids, {state, [], []}, fn pid, {state, ids, new_ids} -> - {state, id, new_ids} = ensure_thread_id(state, pid, new_ids) - {state, [id | ids], new_ids} - end) + {updated_registry, thread_ids, new_ids} = + ThreadRegistry.ensure_thread_ids(state.thread_registry, pids) - {state, Enum.reverse(ids), Enum.reverse(new_ids)} + state = %{state | thread_registry: updated_registry} + {state, thread_ids, new_ids} end defp ensure_var_id(state = %__MODULE__{}, pid, var) when is_pid(pid) or pid == :evaluator do - paused_process = Map.fetch!(state.paused_processes, pid) - - case paused_process.vars_to_var_ids do - %{^var => var_id} -> - {state, var_id} - - _ -> - id = state.next_id - paused_process = put_in(paused_process.var_ids_to_vars[id], var) - paused_process = put_in(paused_process.vars_to_var_ids[var], id) - state = put_in(state.paused_processes[pid], paused_process) - state = put_in(state.next_id, id + 1) - {state, id} - end + paused_process = %PausedProcess{} = Map.fetch!(state.paused_processes, pid) + {registry, var_id} = VariableRegistry.ensure_var_id(paused_process.registry, var) + paused_process = %{paused_process | registry: registry} + state = put_in(state.paused_processes[pid], paused_process) + {state, var_id} end defp ensure_frame_ids(state = %__MODULE__{}, pid, stack_frames) do @@ -1813,23 +2044,15 @@ defmodule ElixirLS.DebugAdapter.Server do end defp ensure_frame_id(state = %__MODULE__{}, pid, %Frame{} = frame) when is_pid(pid) do - paused_process = Map.fetch!(state.paused_processes, pid) - - case paused_process.frames_to_frame_ids do - %{^frame => frame_id} -> - {state, frame_id} - - _ -> - id = state.next_id - paused_process = put_in(paused_process.frame_ids_to_frames[id], frame) - paused_process = put_in(paused_process.frames_to_frame_ids[frame], id) - state = put_in(state.paused_processes[pid], paused_process) - state = put_in(state.next_id, id + 1) - {state, id} - end + paused_process = %PausedProcess{} = Map.fetch!(state.paused_processes, pid) + {registry, frame_id} = VariableRegistry.ensure_frame_id(paused_process.registry, frame) + paused_process = %{paused_process | registry: registry} + state = put_in(state.paused_processes[pid], paused_process) + {state, frame_id} end defp launch(config, server) do + # IO.warn(config |> Map.from_struct |> inspect) project_dir = config["projectDir"] project_dir = @@ -2269,33 +2492,33 @@ defmodule ElixirLS.DebugAdapter.Server do end defp capabilities do - %{ - "supportsConfigurationDoneRequest" => true, - "supportsFunctionBreakpoints" => true, - "supportsConditionalBreakpoints" => true, - "supportsHitConditionalBreakpoints" => true, - "supportsLogPoints" => true, - "exceptionBreakpointFilters" => [], - "supportsStepBack" => false, - "supportsSetVariable" => false, - "supportsRestartFrame" => false, - "supportsGotoTargetsRequest" => false, - "supportsStepInTargetsRequest" => false, - "supportsCompletionsRequest" => true, - "completionTriggerCharacters" => [".", "&", "%", "^", ":", "!", "-", "~"], - "supportsModulesRequest" => false, - "additionalModuleColumns" => [], - "supportedChecksumAlgorithms" => [], - "supportsRestartRequest" => false, - "supportsExceptionOptions" => false, - "supportsValueFormattingOptions" => false, - "supportsExceptionInfoRequest" => false, - "supportsTerminateThreadsRequest" => true, - "supportsSingleThreadExecutionRequests" => true, - "supportsEvaluateForHovers" => true, - "supportsClipboardContext" => true, - "supportTerminateDebuggee" => false, - "supportsCancelRequest" => true + %GenDAP.Structures.Capabilities{ + supports_configuration_done_request: true, + supports_function_breakpoints: true, + supports_conditional_breakpoints: true, + supports_hit_conditional_breakpoints: true, + supports_log_points: true, + exception_breakpoint_filters: [], + supports_step_back: false, + supports_set_variable: false, + supports_restart_frame: false, + supports_goto_targets_request: false, + supports_step_in_targets_request: false, + supports_completions_request: true, + completion_trigger_characters: [".", "&", "%", "^", ":", "!", "-", "~"], + supports_modules_request: false, + additional_module_columns: [], + supported_checksum_algorithms: [], + supports_restart_request: false, + supports_exception_options: false, + supports_value_formatting_options: false, + supports_exception_info_request: false, + supports_terminate_threads_request: true, + supports_single_thread_execution_requests: true, + supports_evaluate_for_hovers: true, + supports_clipboard_context: true, + support_terminate_debuggee: false, + supports_cancel_request: true } end @@ -2668,13 +2891,16 @@ defmodule ElixirLS.DebugAdapter.Server do {state, thread_ids, new_ids} = ensure_thread_ids(state, pids) for thread_id <- new_ids do - Output.send_event("thread", %{ - "reason" => "started", - "threadId" => thread_id + Output.send_event(%GenDAP.Events.ThreadEvent{ + seq: nil, + body: %{ + reason: "started", + thread_id: thread_id + } }) end - exited_pids = Map.keys(state.pids_to_thread_ids) -- pids + exited_pids = ThreadRegistry.all_pids(state.thread_registry) -- pids state = Enum.reduce(exited_pids, state, fn pid, state -> @@ -2685,19 +2911,20 @@ defmodule ElixirLS.DebugAdapter.Server do end defp handle_process_exit(state = %__MODULE__{}, pid) when is_pid(pid) do - {thread_id, pids_to_thread_ids} = Map.pop(state.pids_to_thread_ids, pid) - state = remove_paused_process(state, pid) + # Get thread_id before removing from registry + {thread_id, updated_registry} = ThreadRegistry.remove_pid(state.thread_registry, pid) + state = %{state | thread_registry: updated_registry} - state = %__MODULE__{ - state - | thread_ids_to_pids: Map.delete(state.thread_ids_to_pids, thread_id), - pids_to_thread_ids: pids_to_thread_ids - } + # Remove from paused processes + state = remove_paused_process(state, pid) if thread_id do - Output.send_event("thread", %{ - "reason" => "exited", - "threadId" => thread_id + Output.send_event(%GenDAP.Events.ThreadEvent{ + seq: nil, + body: %{ + reason: "exited", + thread_id: thread_id + } }) end @@ -2836,7 +3063,21 @@ defmodule ElixirLS.DebugAdapter.Server do # ** (MatchError) no match of right hand side value: {:error, :on_load_failure} # (debugger 5.3) int.erl:531: anonymous fn_3 in :int.load_2 # (debugger 5.3) int.erl:527: :int.load_2 - {payload, stacktrace} = Exception.blame(kind, error, __STACKTRACE__) + stacktrace = __STACKTRACE__ + + {payload, stacktrace} = + try do + Exception.blame(kind, error, stacktrace) + catch + kind_1, error_1 -> + # in case of error in Exception.blame we want to use the original error and stacktrace + Output.debugger_console( + "Exception.blame failed: #{Exception.format(kind_1, error_1, __STACKTRACE__)}" + ) + + {error, stacktrace} + end + message = Exception.format(kind, payload, stacktrace) Output.debugger_console( @@ -2926,7 +3167,21 @@ defmodule ElixirLS.DebugAdapter.Server do {:error, e} catch kind, error -> - {payload, stacktrace} = Exception.blame(kind, error, __STACKTRACE__) + stacktrace = __STACKTRACE__ + + {payload, stacktrace} = + try do + Exception.blame(kind, error, stacktrace) + catch + kind_1, error_1 -> + # in case of error in Exception.blame we want to use the original error and stacktrace + Output.debugger_console( + "Exception.blame failed: #{Exception.format(kind_1, error_1, __STACKTRACE__)}" + ) + + {error, stacktrace} + end + message = Exception.format(kind, payload, stacktrace) Output.debugger_console(message) @@ -2952,7 +3207,21 @@ defmodule ElixirLS.DebugAdapter.Server do end rescue error -> - {payload, stacktrace} = Exception.blame(:error, error, __STACKTRACE__) + stacktrace = __STACKTRACE__ + + {payload, stacktrace} = + try do + Exception.blame(:error, error, stacktrace) + catch + kind_1, error_1 -> + # in case of error in Exception.blame we want to use the original error and stacktrace + Output.debugger_console( + "Exception.blame failed: #{Exception.format(kind_1, error_1, __STACKTRACE__)}" + ) + + {error, stacktrace} + end + message = Exception.format(:error, payload, stacktrace) Output.debugger_console( diff --git a/apps/debug_adapter/lib/debug_adapter/thread_registry.ex b/apps/debug_adapter/lib/debug_adapter/thread_registry.ex new file mode 100644 index 000000000..fd7f09076 --- /dev/null +++ b/apps/debug_adapter/lib/debug_adapter/thread_registry.ex @@ -0,0 +1,105 @@ +defmodule ElixirLS.DebugAdapter.ThreadRegistry do + @moduledoc """ + Registry for managing thread ID to PID mappings. + + This module provides bidirectional mapping between Debug Adapter Protocol + thread IDs and Erlang PIDs, using the global IdManager for ID allocation. + """ + + alias ElixirLS.DebugAdapter.IdManager + + defstruct thread_ids_to_pids: %{}, + pids_to_thread_ids: %{} + + @type t :: %__MODULE__{ + thread_ids_to_pids: %{integer() => pid()}, + pids_to_thread_ids: %{pid() => integer()} + } + + @doc """ + Creates a new empty thread registry. + """ + def new, do: %__MODULE__{} + + @doc """ + Ensures a PID has a thread ID, creating one if necessary. + Returns {registry, thread_id, new_ids}. + """ + def ensure_thread_id(registry = %__MODULE__{}, pid, new_ids) when is_pid(pid) do + case registry.pids_to_thread_ids do + %{^pid => thread_id} -> + {registry, thread_id, new_ids} + + _ -> + id = IdManager.next_id() + + registry = %{ + registry + | thread_ids_to_pids: Map.put(registry.thread_ids_to_pids, id, pid), + pids_to_thread_ids: Map.put(registry.pids_to_thread_ids, pid, id) + } + + {registry, id, [id | new_ids]} + end + end + + @doc """ + Ensures multiple PIDs have thread IDs. + Returns {registry, thread_ids, new_ids}. + """ + def ensure_thread_ids(registry = %__MODULE__{}, pids) do + {registry, ids, new_ids} = + Enum.reduce(pids, {registry, [], []}, fn pid, {registry, ids, new_ids} -> + {registry, id, new_ids} = ensure_thread_id(registry, pid, new_ids) + {registry, [id | ids], new_ids} + end) + + {registry, Enum.reverse(ids), Enum.reverse(new_ids)} + end + + @doc """ + Gets the PID for a given thread ID. + Returns {:ok, pid} or :error. + """ + def get_pid_by_thread_id(registry = %__MODULE__{}, thread_id) do + Map.fetch(registry.thread_ids_to_pids, thread_id) + end + + @doc """ + Gets the thread ID for a given PID. + Returns {:ok, thread_id} or :error. + """ + def get_thread_id_by_pid(registry = %__MODULE__{}, pid) do + Map.fetch(registry.pids_to_thread_ids, pid) + end + + @doc """ + Removes a PID and its associated thread ID from the registry. + Returns {thread_id, updated_registry}. + """ + def remove_pid(registry = %__MODULE__{}, pid) do + {thread_id, pids_to_thread_ids} = Map.pop(registry.pids_to_thread_ids, pid) + + registry = %{ + registry + | thread_ids_to_pids: Map.delete(registry.thread_ids_to_pids, thread_id), + pids_to_thread_ids: pids_to_thread_ids + } + + {thread_id, registry} + end + + @doc """ + Gets all thread IDs currently in the registry. + """ + def all_thread_ids(registry = %__MODULE__{}) do + Map.keys(registry.thread_ids_to_pids) + end + + @doc """ + Gets all PIDs currently in the registry. + """ + def all_pids(registry = %__MODULE__{}) do + Map.keys(registry.pids_to_thread_ids) + end +end diff --git a/apps/debug_adapter/lib/debug_adapter/variable_registry.ex b/apps/debug_adapter/lib/debug_adapter/variable_registry.ex new file mode 100644 index 000000000..9be2481c7 --- /dev/null +++ b/apps/debug_adapter/lib/debug_adapter/variable_registry.ex @@ -0,0 +1,109 @@ +defmodule ElixirLS.DebugAdapter.VariableRegistry do + @moduledoc """ + Process-local registry for managing variable and frame references. + + This module provides a way to manage DAP object IDs without needing + to call back to the main GenServer, enabling better async workflows. + """ + + alias ElixirLS.DebugAdapter.{IdManager, Variables} + + defstruct var_ids_to_vars: %{}, + vars_to_var_ids: %{}, + frame_ids_to_frames: %{}, + frames_to_frame_ids: %{} + + @type t :: %__MODULE__{ + var_ids_to_vars: %{integer() => any()}, + vars_to_var_ids: %{any() => integer()}, + frame_ids_to_frames: %{integer() => any()}, + frames_to_frame_ids: %{any() => integer()} + } + + @doc """ + Ensures a variable has an ID, creating one if necessary. + Returns {registry, var_id}. + """ + def ensure_var_id(registry = %__MODULE__{}, var) do + case registry.vars_to_var_ids do + %{^var => var_id} -> + {registry, var_id} + + _ -> + id = IdManager.next_id() + + registry = %{ + registry + | var_ids_to_vars: Map.put(registry.var_ids_to_vars, id, var), + vars_to_var_ids: Map.put(registry.vars_to_var_ids, var, id) + } + + {registry, id} + end + end + + @doc """ + Ensures a frame has an ID, creating one if necessary. + Returns {registry, frame_id}. + """ + def ensure_frame_id(registry = %__MODULE__{}, frame) do + case registry.frames_to_frame_ids do + %{^frame => frame_id} -> + {registry, frame_id} + + _ -> + id = IdManager.next_id() + + registry = %{ + registry + | frame_ids_to_frames: Map.put(registry.frame_ids_to_frames, id, frame), + frames_to_frame_ids: Map.put(registry.frames_to_frame_ids, frame, id) + } + + {registry, id} + end + end + + @doc """ + Gets a variable reference for a value, returning 0 if no children. + This is the async-friendly version that doesn't require GenServer calls. + """ + def get_variable_reference(registry = %__MODULE__{}, value) do + child_type = Variables.child_type(value) + + case child_type do + nil -> {registry, 0} + _ -> ensure_var_id(registry, value) + end + end + + @doc """ + Finds a variable by its ID. + Returns {:ok, var} or :error. + """ + def find_var(registry = %__MODULE__{}, var_id) do + Map.fetch(registry.var_ids_to_vars, var_id) + end + + @doc """ + Finds a frame by its ID. + Returns {:ok, frame} or :error. + """ + def find_frame(registry = %__MODULE__{}, frame_id) do + Map.fetch(registry.frame_ids_to_frames, frame_id) + end + + @doc """ + Merges another registry into this one. + Useful when combining results from async operations. + """ + def merge(registry1 = %__MODULE__{}, registry2 = %__MODULE__{}) do + %__MODULE__{ + var_ids_to_vars: Map.merge(registry1.var_ids_to_vars, registry2.var_ids_to_vars), + vars_to_var_ids: Map.merge(registry1.vars_to_var_ids, registry2.vars_to_var_ids), + frame_ids_to_frames: + Map.merge(registry1.frame_ids_to_frames, registry2.frame_ids_to_frames), + frames_to_frame_ids: Map.merge(registry1.frames_to_frame_ids, registry2.frames_to_frame_ids) + } + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/enumerations/breakpoint_mode_applicability.ex b/apps/debug_adapter/lib/protocol/dap/enumerations/breakpoint_mode_applicability.ex new file mode 100644 index 000000000..9772b82b5 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/enumerations/breakpoint_mode_applicability.ex @@ -0,0 +1,47 @@ +# codegen: do not edit +defmodule GenDAP.Enumerations.BreakpointModeApplicability do + @moduledoc """ + Describes one or more type of breakpoint a `BreakpointMode` applies to. This is a non-exhaustive enumeration and may expand as future breakpoint types are added. + """ + + @typedoc "A type defining DAP enumeration BreakpointModeApplicability" + @type t :: String.t() + + import SchematicV, warn: false + + @doc """ + In `SourceBreakpoint`s + """ + @spec source() :: String.t() + def source, do: "source" + + @doc """ + In exception breakpoints applied in the `ExceptionFilterOptions` + """ + @spec exception() :: String.t() + def exception, do: "exception" + + @doc """ + In data breakpoints requested in the `DataBreakpointInfo` request + """ + @spec data() :: String.t() + def data, do: "data" + + @doc """ + In `InstructionBreakpoint`s + """ + @spec instruction() :: String.t() + def instruction, do: "instruction" + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + "source", + "exception", + "data", + "instruction", + str() + ]) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/enumerations/checksum_algorithm.ex b/apps/debug_adapter/lib/protocol/dap/enumerations/checksum_algorithm.ex new file mode 100644 index 000000000..2e8885109 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/enumerations/checksum_algorithm.ex @@ -0,0 +1,34 @@ +# codegen: do not edit +defmodule GenDAP.Enumerations.ChecksumAlgorithm do + @moduledoc """ + Names of checksum algorithms that may be supported by a debug adapter. + """ + + @typedoc "A type defining DAP enumeration ChecksumAlgorithm" + @type t :: String.t() + + import SchematicV, warn: false + + @spec md5() :: String.t() + def md5, do: "MD5" + + @spec sha1() :: String.t() + def sha1, do: "SHA1" + + @spec sha256() :: String.t() + def sha256, do: "SHA256" + + @spec timestamp() :: String.t() + def timestamp, do: "timestamp" + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + "MD5", + "SHA1", + "SHA256", + "timestamp" + ]) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/enumerations/completion_item_type.ex b/apps/debug_adapter/lib/protocol/dap/enumerations/completion_item_type.ex new file mode 100644 index 000000000..14cd5309c --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/enumerations/completion_item_type.ex @@ -0,0 +1,94 @@ +# codegen: do not edit +defmodule GenDAP.Enumerations.CompletionItemType do + @moduledoc """ + Some predefined types for the CompletionItem. Please note that not all clients have specific icons for all of them. + """ + + @typedoc "A type defining DAP enumeration CompletionItemType" + @type t :: String.t() + + import SchematicV, warn: false + + @spec method() :: String.t() + def method, do: "method" + + @spec function() :: String.t() + def function, do: "function" + + @spec constructor() :: String.t() + def constructor, do: "constructor" + + @spec field() :: String.t() + def field, do: "field" + + @spec variable() :: String.t() + def variable, do: "variable" + + @spec class() :: String.t() + def class, do: "class" + + @spec interface() :: String.t() + def interface, do: "interface" + + @spec module() :: String.t() + def module, do: "module" + + @spec property() :: String.t() + def property, do: "property" + + @spec unit() :: String.t() + def unit, do: "unit" + + @spec value() :: String.t() + def value, do: "value" + + @spec enum() :: String.t() + def enum, do: "enum" + + @spec keyword() :: String.t() + def keyword, do: "keyword" + + @spec snippet() :: String.t() + def snippet, do: "snippet" + + @spec text() :: String.t() + def text, do: "text" + + @spec color() :: String.t() + def color, do: "color" + + @spec file() :: String.t() + def file, do: "file" + + @spec reference() :: String.t() + def reference, do: "reference" + + @spec customcolor() :: String.t() + def customcolor, do: "customcolor" + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + "method", + "function", + "constructor", + "field", + "variable", + "class", + "interface", + "module", + "property", + "unit", + "value", + "enum", + "keyword", + "snippet", + "text", + "color", + "file", + "reference", + "customcolor" + ]) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/enumerations/data_breakpoint_access_type.ex b/apps/debug_adapter/lib/protocol/dap/enumerations/data_breakpoint_access_type.ex new file mode 100644 index 000000000..a996ec222 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/enumerations/data_breakpoint_access_type.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenDAP.Enumerations.DataBreakpointAccessType do + @moduledoc """ + This enumeration defines all possible access types for data breakpoints. + """ + + @typedoc "A type defining DAP enumeration DataBreakpointAccessType" + @type t :: String.t() + + import SchematicV, warn: false + + @spec read() :: String.t() + def read, do: "read" + + @spec write() :: String.t() + def write, do: "write" + + @spec read_write() :: String.t() + def read_write, do: "readWrite" + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + "read", + "write", + "readWrite" + ]) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/enumerations/exception_break_mode.ex b/apps/debug_adapter/lib/protocol/dap/enumerations/exception_break_mode.ex new file mode 100644 index 000000000..a1415eb8a --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/enumerations/exception_break_mode.ex @@ -0,0 +1,38 @@ +# codegen: do not edit +defmodule GenDAP.Enumerations.ExceptionBreakMode do + @moduledoc """ + This enumeration defines all possible conditions when a thrown exception should result in a break. + never: never breaks, + always: always breaks, + unhandled: breaks when exception unhandled, + userUnhandled: breaks if the exception is not handled by user code. + """ + + @typedoc "A type defining DAP enumeration ExceptionBreakMode" + @type t :: String.t() + + import SchematicV, warn: false + + @spec never() :: String.t() + def never, do: "never" + + @spec always() :: String.t() + def always, do: "always" + + @spec unhandled() :: String.t() + def unhandled, do: "unhandled" + + @spec user_unhandled() :: String.t() + def user_unhandled, do: "userUnhandled" + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + "never", + "always", + "unhandled", + "userUnhandled" + ]) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/enumerations/invalidated_areas.ex b/apps/debug_adapter/lib/protocol/dap/enumerations/invalidated_areas.ex new file mode 100644 index 000000000..8cde0e711 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/enumerations/invalidated_areas.ex @@ -0,0 +1,47 @@ +# codegen: do not edit +defmodule GenDAP.Enumerations.InvalidatedAreas do + @moduledoc """ + Logical areas that can be invalidated by the `invalidated` event. + """ + + @typedoc "A type defining DAP enumeration InvalidatedAreas" + @type t :: String.t() + + import SchematicV, warn: false + + @doc """ + All previously fetched data has become invalid and needs to be refetched. + """ + @spec all() :: String.t() + def all, do: "all" + + @doc """ + Previously fetched stack related data has become invalid and needs to be refetched. + """ + @spec stacks() :: String.t() + def stacks, do: "stacks" + + @doc """ + Previously fetched thread related data has become invalid and needs to be refetched. + """ + @spec threads() :: String.t() + def threads, do: "threads" + + @doc """ + Previously fetched variable data has become invalid and needs to be refetched. + """ + @spec variables() :: String.t() + def variables, do: "variables" + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + "all", + "stacks", + "threads", + "variables", + str() + ]) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/enumerations/stepping_granularity.ex b/apps/debug_adapter/lib/protocol/dap/enumerations/stepping_granularity.ex new file mode 100644 index 000000000..e29062f6f --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/enumerations/stepping_granularity.ex @@ -0,0 +1,41 @@ +# codegen: do not edit +defmodule GenDAP.Enumerations.SteppingGranularity do + @moduledoc """ + The granularity of one 'step' in the stepping requests `next`, `stepIn`, `stepOut`, and `stepBack`. + """ + + @typedoc "A type defining DAP enumeration SteppingGranularity" + @type t :: String.t() + + import SchematicV, warn: false + + @doc """ + The step should allow the program to run until the current statement has finished executing. + The meaning of a statement is determined by the adapter and it may be considered equivalent to a line. + For example 'for(int i = 0; i < 10; i++)' could be considered to have 3 statements 'int i = 0', 'i < 10', and 'i++'. + """ + @spec statement() :: String.t() + def statement, do: "statement" + + @doc """ + The step should allow the program to run until the current source line has executed. + """ + @spec line() :: String.t() + def line, do: "line" + + @doc """ + The step should allow one instruction to execute (e.g. one x86 instruction). + """ + @spec instruction() :: String.t() + def instruction, do: "instruction" + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + "statement", + "line", + "instruction" + ]) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/events.ex b/apps/debug_adapter/lib/protocol/dap/events.ex new file mode 100644 index 000000000..8a7a60519 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/events.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenDAP.Events do + import SchematicV + + def new(event) do + unify( + oneof(fn + %{"event" => "breakpoint"} -> GenDAP.Events.BreakpointEvent.schematic() + %{"event" => "capabilities"} -> GenDAP.Events.CapabilitiesEvent.schematic() + %{"event" => "continued"} -> GenDAP.Events.ContinuedEvent.schematic() + %{"event" => "exited"} -> GenDAP.Events.ExitedEvent.schematic() + %{"event" => "initialized"} -> GenDAP.Events.InitializedEvent.schematic() + %{"event" => "invalidated"} -> GenDAP.Events.InvalidatedEvent.schematic() + %{"event" => "loadedSource"} -> GenDAP.Events.LoadedSourceEvent.schematic() + %{"event" => "memory"} -> GenDAP.Events.MemoryEvent.schematic() + %{"event" => "module"} -> GenDAP.Events.ModuleEvent.schematic() + %{"event" => "output"} -> GenDAP.Events.OutputEvent.schematic() + %{"event" => "process"} -> GenDAP.Events.ProcessEvent.schematic() + %{"event" => "progressEnd"} -> GenDAP.Events.ProgressEndEvent.schematic() + %{"event" => "progressStart"} -> GenDAP.Events.ProgressStartEvent.schematic() + %{"event" => "progressUpdate"} -> GenDAP.Events.ProgressUpdateEvent.schematic() + %{"event" => "stopped"} -> GenDAP.Events.StoppedEvent.schematic() + %{"event" => "terminated"} -> GenDAP.Events.TerminatedEvent.schematic() + %{"event" => "thread"} -> GenDAP.Events.ThreadEvent.schematic() + _ -> {:error, "unexpected event payload"} + end), + event + ) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/events/breakpoint_event.ex b/apps/debug_adapter/lib/protocol/dap/events/breakpoint_event.ex new file mode 100644 index 000000000..705ea53c8 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/events/breakpoint_event.ex @@ -0,0 +1,54 @@ +# codegen: do not edit + +defmodule GenDAP.Events.BreakpointEvent do + @moduledoc """ + The event indicates that some information about a breakpoint has changed. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Event-specific information. + * event: Type of event. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP event breakpoint" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "event") + field(:event, String.t(), default: "breakpoint") + + field( + :body, + %{ + required(:breakpoint) => GenDAP.Structures.Breakpoint.t(), + required(:reason) => String.t() + }, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "event", + :event => "breakpoint", + :body => + map(%{ + {"breakpoint", :breakpoint} => GenDAP.Structures.Breakpoint.schematic(), + {"reason", :reason} => oneof(["changed", "new", "removed", str()]) + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/events/capabilities_event.ex b/apps/debug_adapter/lib/protocol/dap/events/capabilities_event.ex new file mode 100644 index 000000000..cb4eae913 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/events/capabilities_event.ex @@ -0,0 +1,48 @@ +# codegen: do not edit + +defmodule GenDAP.Events.CapabilitiesEvent do + @moduledoc """ + The event indicates that one or more capabilities have changed. + Since the capabilities are dependent on the client and its UI, it might not be possible to change that at random times (or too late). + Consequently this event has a hint characteristic: a client can only be expected to make a 'best effort' in honoring individual capabilities but there are no guarantees. + Only changed capabilities need to be included, all other capabilities keep their values. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Event-specific information. + * event: Type of event. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP event capabilities" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "event") + field(:event, String.t(), default: "capabilities") + field(:body, %{required(:capabilities) => GenDAP.Structures.Capabilities.t()}, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "event", + :event => "capabilities", + :body => + map(%{ + {"capabilities", :capabilities} => GenDAP.Structures.Capabilities.schematic() + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/events/continued_event.ex b/apps/debug_adapter/lib/protocol/dap/events/continued_event.ex new file mode 100644 index 000000000..84ad679d0 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/events/continued_event.ex @@ -0,0 +1,53 @@ +# codegen: do not edit + +defmodule GenDAP.Events.ContinuedEvent do + @moduledoc """ + The event indicates that the execution of the debuggee has continued. + Please note: a debug adapter is not expected to send this event in response to a request that implies that execution continues, e.g. `launch` or `continue`. + It is only necessary to send a `continued` event if there was no previous request that implied this. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Event-specific information. + * event: Type of event. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP event continued" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "event") + field(:event, String.t(), default: "continued") + + field( + :body, + %{required(:thread_id) => integer(), optional(:all_threads_continued) => boolean()}, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "event", + :event => "continued", + :body => + map(%{ + {"threadId", :thread_id} => int(), + optional({"allThreadsContinued", :all_threads_continued}) => bool() + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/events/exited_event.ex b/apps/debug_adapter/lib/protocol/dap/events/exited_event.ex new file mode 100644 index 000000000..9c9f688b2 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/events/exited_event.ex @@ -0,0 +1,45 @@ +# codegen: do not edit + +defmodule GenDAP.Events.ExitedEvent do + @moduledoc """ + The event indicates that the debuggee has exited and returns its exit code. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Event-specific information. + * event: Type of event. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP event exited" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "event") + field(:event, String.t(), default: "exited") + field(:body, %{required(:exit_code) => integer()}, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "event", + :event => "exited", + :body => + map(%{ + {"exitCode", :exit_code} => int() + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/events/initialized_event.ex b/apps/debug_adapter/lib/protocol/dap/events/initialized_event.ex new file mode 100644 index 000000000..0721a5737 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/events/initialized_event.ex @@ -0,0 +1,54 @@ +# codegen: do not edit + +defmodule GenDAP.Events.InitializedEvent do + @moduledoc """ + This event indicates that the debug adapter is ready to accept configuration requests (e.g. `setBreakpoints`, `setExceptionBreakpoints`). + A debug adapter is expected to send this event when it is ready to accept configuration requests (but not before the `initialize` request has finished). + The sequence of events/requests is as follows: + - adapters sends `initialized` event (after the `initialize` request has returned) + - client sends zero or more `setBreakpoints` requests + - client sends one `setFunctionBreakpoints` request (if corresponding capability `supportsFunctionBreakpoints` is true) + - client sends a `setExceptionBreakpoints` request if one or more `exceptionBreakpointFilters` have been defined (or if `supportsConfigurationDoneRequest` is not true) + - client sends other future configuration requests + - client sends one `configurationDone` request to indicate the end of the configuration. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Event-specific information. + * event: Type of event. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP event initialized" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "event") + field(:event, String.t(), default: "initialized") + + field(:body, list() | boolean() | integer() | nil | number() | map() | String.t(), + enforce: false + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "event", + :event => "initialized", + optional(:body) => + oneof([list(), bool(), int(), nil, oneof([int(), float()]), map(), str()]) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/events/invalidated_event.ex b/apps/debug_adapter/lib/protocol/dap/events/invalidated_event.ex new file mode 100644 index 000000000..e07c1b370 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/events/invalidated_event.ex @@ -0,0 +1,58 @@ +# codegen: do not edit + +defmodule GenDAP.Events.InvalidatedEvent do + @moduledoc """ + This event signals that some state in the debug adapter has changed and requires that the client needs to re-render the data snapshot previously requested. + Debug adapters do not have to emit this event for runtime changes like stopped or thread events because in that case the client refetches the new state anyway. But the event can be used for example to refresh the UI after rendering formatting has changed in the debug adapter. + This event should only be sent if the corresponding capability `supportsInvalidatedEvent` is true. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Event-specific information. + * event: Type of event. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP event invalidated" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "event") + field(:event, String.t(), default: "invalidated") + + field( + :body, + %{ + optional(:thread_id) => integer(), + optional(:areas) => list(GenDAP.Enumerations.InvalidatedAreas.t()), + optional(:stack_frame_id) => integer() + }, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "event", + :event => "invalidated", + :body => + map(%{ + optional({"threadId", :thread_id}) => int(), + optional({"areas", :areas}) => list(GenDAP.Enumerations.InvalidatedAreas.schematic()), + optional({"stackFrameId", :stack_frame_id}) => int() + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/events/loaded_source_event.ex b/apps/debug_adapter/lib/protocol/dap/events/loaded_source_event.ex new file mode 100644 index 000000000..7a471abde --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/events/loaded_source_event.ex @@ -0,0 +1,51 @@ +# codegen: do not edit + +defmodule GenDAP.Events.LoadedSourceEvent do + @moduledoc """ + The event indicates that some source has been added, changed, or removed from the set of all loaded sources. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Event-specific information. + * event: Type of event. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP event loadedSource" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "event") + field(:event, String.t(), default: "loadedSource") + + field( + :body, + %{required(:reason) => String.t(), required(:source) => GenDAP.Structures.Source.t()}, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "event", + :event => "loadedSource", + :body => + map(%{ + {"reason", :reason} => oneof(["new", "changed", "removed"]), + {"source", :source} => GenDAP.Structures.Source.schematic() + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/events/memory_event.ex b/apps/debug_adapter/lib/protocol/dap/events/memory_event.ex new file mode 100644 index 000000000..e490acfb7 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/events/memory_event.ex @@ -0,0 +1,58 @@ +# codegen: do not edit + +defmodule GenDAP.Events.MemoryEvent do + @moduledoc """ + This event indicates that some memory range has been updated. It should only be sent if the corresponding capability `supportsMemoryEvent` is true. + Clients typically react to the event by re-issuing a `readMemory` request if they show the memory identified by the `memoryReference` and if the updated memory range overlaps the displayed range. Clients should not make assumptions how individual memory references relate to each other, so they should not assume that they are part of a single continuous address range and might overlap. + Debug adapters can use this event to indicate that the contents of a memory range has changed due to some other request like `setVariable` or `setExpression`. Debug adapters are not expected to emit this event for each and every memory change of a running program, because that information is typically not available from debuggers and it would flood clients with too many events. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Event-specific information. + * event: Type of event. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP event memory" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "event") + field(:event, String.t(), default: "memory") + + field( + :body, + %{ + required(:count) => integer(), + required(:offset) => integer(), + required(:memory_reference) => String.t() + }, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "event", + :event => "memory", + :body => + map(%{ + {"count", :count} => int(), + {"offset", :offset} => int(), + {"memoryReference", :memory_reference} => str() + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/events/module_event.ex b/apps/debug_adapter/lib/protocol/dap/events/module_event.ex new file mode 100644 index 000000000..9a3fab753 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/events/module_event.ex @@ -0,0 +1,51 @@ +# codegen: do not edit + +defmodule GenDAP.Events.ModuleEvent do + @moduledoc """ + The event indicates that some information about a module has changed. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Event-specific information. + * event: Type of event. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP event module" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "event") + field(:event, String.t(), default: "module") + + field( + :body, + %{required(:module) => GenDAP.Structures.Module.t(), required(:reason) => String.t()}, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "event", + :event => "module", + :body => + map(%{ + {"module", :module} => GenDAP.Structures.Module.schematic(), + {"reason", :reason} => oneof(["new", "changed", "removed"]) + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/events/output_event.ex b/apps/debug_adapter/lib/protocol/dap/events/output_event.ex new file mode 100644 index 000000000..016beec4a --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/events/output_event.ex @@ -0,0 +1,70 @@ +# codegen: do not edit + +defmodule GenDAP.Events.OutputEvent do + @moduledoc """ + The event indicates that the target has produced some output. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Event-specific information. + * event: Type of event. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP event output" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "event") + field(:event, String.t(), default: "output") + + field( + :body, + %{ + optional(:data) => list() | boolean() | integer() | nil | number() | map() | String.t(), + optional(:line) => integer(), + required(:output) => String.t(), + optional(:group) => String.t(), + optional(:column) => integer(), + optional(:category) => String.t(), + optional(:source) => GenDAP.Structures.Source.t(), + optional(:variables_reference) => integer(), + optional(:location_reference) => integer() + }, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "event", + :event => "output", + :body => + map(%{ + optional({"data", :data}) => + oneof([list(), bool(), int(), nil, oneof([int(), float()]), map(), str()]), + optional({"line", :line}) => int(), + {"output", :output} => str(), + optional({"group", :group}) => oneof(["start", "startCollapsed", "end"]), + optional({"column", :column}) => int(), + optional({"category", :category}) => + oneof(["console", "important", "stdout", "stderr", "telemetry", str()]), + optional({"source", :source}) => GenDAP.Structures.Source.schematic(), + optional({"variablesReference", :variables_reference}) => int(), + optional({"locationReference", :location_reference}) => int() + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/events/process_event.ex b/apps/debug_adapter/lib/protocol/dap/events/process_event.ex new file mode 100644 index 000000000..b933354eb --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/events/process_event.ex @@ -0,0 +1,61 @@ +# codegen: do not edit + +defmodule GenDAP.Events.ProcessEvent do + @moduledoc """ + The event indicates that the debugger has begun debugging a new process. Either one that it has launched, or one that it has attached to. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Event-specific information. + * event: Type of event. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP event process" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "event") + field(:event, String.t(), default: "process") + + field( + :body, + %{ + required(:name) => String.t(), + optional(:system_process_id) => integer(), + optional(:is_local_process) => boolean(), + optional(:start_method) => String.t(), + optional(:pointer_size) => integer() + }, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "event", + :event => "process", + :body => + map(%{ + {"name", :name} => str(), + optional({"systemProcessId", :system_process_id}) => int(), + optional({"isLocalProcess", :is_local_process}) => bool(), + optional({"startMethod", :start_method}) => + oneof(["launch", "attach", "attachForSuspendedLaunch"]), + optional({"pointerSize", :pointer_size}) => int() + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/events/progress_end_event.ex b/apps/debug_adapter/lib/protocol/dap/events/progress_end_event.ex new file mode 100644 index 000000000..bd5dc8b9c --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/events/progress_end_event.ex @@ -0,0 +1,50 @@ +# codegen: do not edit + +defmodule GenDAP.Events.ProgressEndEvent do + @moduledoc """ + The event signals the end of the progress reporting with a final message. + This event should only be sent if the corresponding capability `supportsProgressReporting` is true. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Event-specific information. + * event: Type of event. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP event progressEnd" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "event") + field(:event, String.t(), default: "progressEnd") + + field(:body, %{optional(:message) => String.t(), required(:progress_id) => String.t()}, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "event", + :event => "progressEnd", + :body => + map(%{ + optional({"message", :message}) => str(), + {"progressId", :progress_id} => str() + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/events/progress_start_event.ex b/apps/debug_adapter/lib/protocol/dap/events/progress_start_event.ex new file mode 100644 index 000000000..88ece4d82 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/events/progress_start_event.ex @@ -0,0 +1,64 @@ +# codegen: do not edit + +defmodule GenDAP.Events.ProgressStartEvent do + @moduledoc """ + The event signals that a long running operation is about to start and provides additional information for the client to set up a corresponding progress and cancellation UI. + The client is free to delay the showing of the UI in order to reduce flicker. + This event should only be sent if the corresponding capability `supportsProgressReporting` is true. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Event-specific information. + * event: Type of event. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP event progressStart" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "event") + field(:event, String.t(), default: "progressStart") + + field( + :body, + %{ + optional(:message) => String.t(), + required(:title) => String.t(), + optional(:request_id) => integer(), + required(:progress_id) => String.t(), + optional(:cancellable) => boolean(), + optional(:percentage) => number() + }, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "event", + :event => "progressStart", + :body => + map(%{ + optional({"message", :message}) => str(), + {"title", :title} => str(), + optional({"requestId", :request_id}) => int(), + {"progressId", :progress_id} => str(), + optional({"cancellable", :cancellable}) => bool(), + optional({"percentage", :percentage}) => oneof([int(), float()]) + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/events/progress_update_event.ex b/apps/debug_adapter/lib/protocol/dap/events/progress_update_event.ex new file mode 100644 index 000000000..62ddd4b1a --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/events/progress_update_event.ex @@ -0,0 +1,58 @@ +# codegen: do not edit + +defmodule GenDAP.Events.ProgressUpdateEvent do + @moduledoc """ + The event signals that the progress reporting needs to be updated with a new message and/or percentage. + The client does not have to update the UI immediately, but the clients needs to keep track of the message and/or percentage values. + This event should only be sent if the corresponding capability `supportsProgressReporting` is true. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Event-specific information. + * event: Type of event. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP event progressUpdate" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "event") + field(:event, String.t(), default: "progressUpdate") + + field( + :body, + %{ + optional(:message) => String.t(), + required(:progress_id) => String.t(), + optional(:percentage) => number() + }, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "event", + :event => "progressUpdate", + :body => + map(%{ + optional({"message", :message}) => str(), + {"progressId", :progress_id} => str(), + optional({"percentage", :percentage}) => oneof([int(), float()]) + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/events/stopped_event.ex b/apps/debug_adapter/lib/protocol/dap/events/stopped_event.ex new file mode 100644 index 000000000..b6979e434 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/events/stopped_event.ex @@ -0,0 +1,77 @@ +# codegen: do not edit + +defmodule GenDAP.Events.StoppedEvent do + @moduledoc """ + The event indicates that the execution of the debuggee has stopped due to some condition. + This can be caused by a breakpoint previously set, a stepping request has completed, by executing a debugger statement etc. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Event-specific information. + * event: Type of event. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP event stopped" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "event") + field(:event, String.t(), default: "stopped") + + field( + :body, + %{ + required(:reason) => String.t(), + optional(:description) => String.t(), + optional(:text) => String.t(), + optional(:thread_id) => integer(), + optional(:preserve_focus_hint) => boolean(), + optional(:all_threads_stopped) => boolean(), + optional(:hit_breakpoint_ids) => list(integer()) + }, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "event", + :event => "stopped", + :body => + map(%{ + {"reason", :reason} => + oneof([ + "step", + "breakpoint", + "exception", + "pause", + "entry", + "goto", + "function breakpoint", + "data breakpoint", + "instruction breakpoint", + str() + ]), + optional({"description", :description}) => str(), + optional({"text", :text}) => str(), + optional({"threadId", :thread_id}) => int(), + optional({"preserveFocusHint", :preserve_focus_hint}) => bool(), + optional({"allThreadsStopped", :all_threads_stopped}) => bool(), + optional({"hitBreakpointIds", :hit_breakpoint_ids}) => list(int()) + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/events/terminated_event.ex b/apps/debug_adapter/lib/protocol/dap/events/terminated_event.ex new file mode 100644 index 000000000..fa42c5ee5 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/events/terminated_event.ex @@ -0,0 +1,53 @@ +# codegen: do not edit + +defmodule GenDAP.Events.TerminatedEvent do + @moduledoc """ + The event indicates that debugging of the debuggee has terminated. This does **not** mean that the debuggee itself has exited. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Event-specific information. + * event: Type of event. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP event terminated" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "event") + field(:event, String.t(), default: "terminated") + + field( + :body, + %{ + optional(:restart) => list() | boolean() | integer() | nil | number() | map() | String.t() + }, + enforce: false + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "event", + :event => "terminated", + optional(:body) => + map(%{ + optional({"restart", :restart}) => + oneof([list(), bool(), int(), nil, oneof([int(), float()]), map(), str()]) + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/events/thread_event.ex b/apps/debug_adapter/lib/protocol/dap/events/thread_event.ex new file mode 100644 index 000000000..fa361b153 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/events/thread_event.ex @@ -0,0 +1,49 @@ +# codegen: do not edit + +defmodule GenDAP.Events.ThreadEvent do + @moduledoc """ + The event indicates that a thread has started or exited. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Event-specific information. + * event: Type of event. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP event thread" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "event") + field(:event, String.t(), default: "thread") + + field(:body, %{required(:reason) => String.t(), required(:thread_id) => integer()}, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "event", + :event => "thread", + :body => + map(%{ + {"reason", :reason} => oneof(["started", "exited", str()]), + {"threadId", :thread_id} => int() + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests.ex b/apps/debug_adapter/lib/protocol/dap/requests.ex new file mode 100644 index 000000000..77612b3d1 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests.ex @@ -0,0 +1,149 @@ +# codegen: do not edit +defmodule GenDAP.Requests do + import SchematicV + + def new(request) do + unify( + oneof(fn + %{"command" => "attach"} -> + GenDAP.Requests.AttachRequest.schematic() + + %{"command" => "breakpointLocations"} -> + GenDAP.Requests.BreakpointLocationsRequest.schematic() + + %{"command" => "cancel"} -> + GenDAP.Requests.CancelRequest.schematic() + + %{"command" => "completions"} -> + GenDAP.Requests.CompletionsRequest.schematic() + + %{"command" => "configurationDone"} -> + GenDAP.Requests.ConfigurationDoneRequest.schematic() + + %{"command" => "continue"} -> + GenDAP.Requests.ContinueRequest.schematic() + + %{"command" => "dataBreakpointInfo"} -> + GenDAP.Requests.DataBreakpointInfoRequest.schematic() + + %{"command" => "disassemble"} -> + GenDAP.Requests.DisassembleRequest.schematic() + + %{"command" => "disconnect"} -> + GenDAP.Requests.DisconnectRequest.schematic() + + %{"command" => "evaluate"} -> + GenDAP.Requests.EvaluateRequest.schematic() + + %{"command" => "exceptionInfo"} -> + GenDAP.Requests.ExceptionInfoRequest.schematic() + + %{"command" => "goto"} -> + GenDAP.Requests.GotoRequest.schematic() + + %{"command" => "gotoTargets"} -> + GenDAP.Requests.GotoTargetsRequest.schematic() + + %{"command" => "initialize"} -> + GenDAP.Requests.InitializeRequest.schematic() + + %{"command" => "launch"} -> + GenDAP.Requests.LaunchRequest.schematic() + + %{"command" => "loadedSources"} -> + GenDAP.Requests.LoadedSourcesRequest.schematic() + + %{"command" => "locations"} -> + GenDAP.Requests.LocationsRequest.schematic() + + %{"command" => "modules"} -> + GenDAP.Requests.ModulesRequest.schematic() + + %{"command" => "next"} -> + GenDAP.Requests.NextRequest.schematic() + + %{"command" => "pause"} -> + GenDAP.Requests.PauseRequest.schematic() + + %{"command" => "readMemory"} -> + GenDAP.Requests.ReadMemoryRequest.schematic() + + %{"command" => "restart"} -> + GenDAP.Requests.RestartRequest.schematic() + + %{"command" => "restartFrame"} -> + GenDAP.Requests.RestartFrameRequest.schematic() + + %{"command" => "reverseContinue"} -> + GenDAP.Requests.ReverseContinueRequest.schematic() + + %{"command" => "runInTerminal"} -> + GenDAP.Requests.RunInTerminalRequest.schematic() + + %{"command" => "scopes"} -> + GenDAP.Requests.ScopesRequest.schematic() + + %{"command" => "setBreakpoints"} -> + GenDAP.Requests.SetBreakpointsRequest.schematic() + + %{"command" => "setDataBreakpoints"} -> + GenDAP.Requests.SetDataBreakpointsRequest.schematic() + + %{"command" => "setExceptionBreakpoints"} -> + GenDAP.Requests.SetExceptionBreakpointsRequest.schematic() + + %{"command" => "setExpression"} -> + GenDAP.Requests.SetExpressionRequest.schematic() + + %{"command" => "setFunctionBreakpoints"} -> + GenDAP.Requests.SetFunctionBreakpointsRequest.schematic() + + %{"command" => "setInstructionBreakpoints"} -> + GenDAP.Requests.SetInstructionBreakpointsRequest.schematic() + + %{"command" => "setVariable"} -> + GenDAP.Requests.SetVariableRequest.schematic() + + %{"command" => "source"} -> + GenDAP.Requests.SourceRequest.schematic() + + %{"command" => "stackTrace"} -> + GenDAP.Requests.StackTraceRequest.schematic() + + %{"command" => "startDebugging"} -> + GenDAP.Requests.StartDebuggingRequest.schematic() + + %{"command" => "stepBack"} -> + GenDAP.Requests.StepBackRequest.schematic() + + %{"command" => "stepIn"} -> + GenDAP.Requests.StepInRequest.schematic() + + %{"command" => "stepInTargets"} -> + GenDAP.Requests.StepInTargetsRequest.schematic() + + %{"command" => "stepOut"} -> + GenDAP.Requests.StepOutRequest.schematic() + + %{"command" => "terminate"} -> + GenDAP.Requests.TerminateRequest.schematic() + + %{"command" => "terminateThreads"} -> + GenDAP.Requests.TerminateThreadsRequest.schematic() + + %{"command" => "threads"} -> + GenDAP.Requests.ThreadsRequest.schematic() + + %{"command" => "variables"} -> + GenDAP.Requests.VariablesRequest.schematic() + + %{"command" => "writeMemory"} -> + GenDAP.Requests.WriteMemoryRequest.schematic() + + _ -> + {:error, "unexpected request payload"} + end), + request + ) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/attach.ex b/apps/debug_adapter/lib/protocol/dap/requests/attach.ex new file mode 100644 index 000000000..3c70d4dc8 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/attach.ex @@ -0,0 +1,92 @@ +# codegen: do not edit +defmodule GenDAP.Requests.AttachRequest do + @moduledoc """ + The `attach` request is sent from the client to the debug adapter to attach to a debuggee that is already running. + Since attaching is debugger/runtime specific, the arguments for this request are not part of this specification. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request attach" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "attach") + field(:arguments, GenDAP.Structures.AttachRequestArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "attach", + :arguments => GenDAP.Structures.AttachRequestArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.AttachResponse do + @moduledoc """ + A response to the attach request + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request attach response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "attach") + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "attach" + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/breakpoint_locations.ex b/apps/debug_adapter/lib/protocol/dap/requests/breakpoint_locations.ex new file mode 100644 index 000000000..fd3e0ff7e --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/breakpoint_locations.ex @@ -0,0 +1,101 @@ +# codegen: do not edit +defmodule GenDAP.Requests.BreakpointLocationsRequest do + @moduledoc """ + The `breakpointLocations` request returns all possible locations for source breakpoints in a given range. + Clients should only call this request if the corresponding capability `supportsBreakpointLocationsRequest` is true. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request breakpointLocations" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "breakpointLocations") + field(:arguments, GenDAP.Structures.BreakpointLocationsArguments.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "breakpointLocations", + optional(:arguments) => GenDAP.Structures.BreakpointLocationsArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.BreakpointLocationsResponse do + @moduledoc """ + Response to `breakpointLocations` request. + Contains possible locations for source breakpoints. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request breakpointLocations response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "breakpointLocations") + + field(:body, %{required(:breakpoints) => list(GenDAP.Structures.BreakpointLocation.t())}, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "breakpointLocations", + :body => + map(%{ + {"breakpoints", :breakpoints} => list(GenDAP.Structures.BreakpointLocation.schematic()) + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/cancel.ex b/apps/debug_adapter/lib/protocol/dap/requests/cancel.ex new file mode 100644 index 000000000..b7cd06b44 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/cancel.ex @@ -0,0 +1,100 @@ +# codegen: do not edit +defmodule GenDAP.Requests.CancelRequest do + @moduledoc """ + The `cancel` request is used by the client in two situations: + - to indicate that it is no longer interested in the result produced by a specific request issued earlier + - to cancel a progress sequence. + Clients should only call this request if the corresponding capability `supportsCancelRequest` is true. + This request has a hint characteristic: a debug adapter can only be expected to make a 'best effort' in honoring this request but there are no guarantees. + The `cancel` request may return an error if it could not cancel an operation but a client should refrain from presenting this error to end users. + The request that got cancelled still needs to send a response back. This can either be a normal result (`success` attribute true) or an error response (`success` attribute false and the `message` set to `cancelled`). + Returning partial results from a cancelled request is possible but please note that a client has no generic way for detecting that a response is partial or not. + The progress that got cancelled still needs to send a `progressEnd` event back. + A client should not assume that progress just got cancelled after sending the `cancel` request. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request cancel" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "cancel") + field(:arguments, GenDAP.Structures.CancelArguments.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "cancel", + optional(:arguments) => GenDAP.Structures.CancelArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.CancelResponse do + @moduledoc """ + A response to the cancel request + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request cancel response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "cancel") + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "cancel" + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/completions.ex b/apps/debug_adapter/lib/protocol/dap/requests/completions.ex new file mode 100644 index 000000000..9834aeedb --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/completions.ex @@ -0,0 +1,100 @@ +# codegen: do not edit +defmodule GenDAP.Requests.CompletionsRequest do + @moduledoc """ + Returns a list of possible completions for a given caret position and text. + Clients should only call this request if the corresponding capability `supportsCompletionsRequest` is true. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request completions" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "completions") + field(:arguments, GenDAP.Structures.CompletionsArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "completions", + :arguments => GenDAP.Structures.CompletionsArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.CompletionsResponse do + @moduledoc """ + Response to `completions` request. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request completions response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "completions") + + field(:body, %{required(:targets) => list(GenDAP.Structures.CompletionItem.t())}, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "completions", + :body => + map(%{ + {"targets", :targets} => list(GenDAP.Structures.CompletionItem.schematic()) + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/configuration_done.ex b/apps/debug_adapter/lib/protocol/dap/requests/configuration_done.ex new file mode 100644 index 000000000..707d9d7ff --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/configuration_done.ex @@ -0,0 +1,93 @@ +# codegen: do not edit +defmodule GenDAP.Requests.ConfigurationDoneRequest do + @moduledoc """ + This request indicates that the client has finished initialization of the debug adapter. + So it is the last request in the sequence of configuration requests (which was started by the `initialized` event). + Clients should only call this request if the corresponding capability `supportsConfigurationDoneRequest` is true. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request configurationDone" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "configurationDone") + field(:arguments, GenDAP.Structures.ConfigurationDoneArguments.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "configurationDone", + optional(:arguments) => GenDAP.Structures.ConfigurationDoneArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.ConfigurationDoneResponse do + @moduledoc """ + A response to the configurationDone request + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request configurationDone response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "configurationDone") + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "configurationDone" + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/continue.ex b/apps/debug_adapter/lib/protocol/dap/requests/continue.ex new file mode 100644 index 000000000..68bb4c5df --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/continue.ex @@ -0,0 +1,96 @@ +# codegen: do not edit +defmodule GenDAP.Requests.ContinueRequest do + @moduledoc """ + The request resumes execution of all threads. If the debug adapter supports single thread execution (see capability `supportsSingleThreadExecutionRequests`), setting the `singleThread` argument to true resumes only the specified thread. If not all threads were resumed, the `allThreadsContinued` attribute of the response should be set to false. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request continue" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "continue") + field(:arguments, GenDAP.Structures.ContinueArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "continue", + :arguments => GenDAP.Structures.ContinueArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.ContinueResponse do + @moduledoc """ + Response to `continue` request. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request continue response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "continue") + field(:body, %{optional(:all_threads_continued) => boolean()}, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "continue", + :body => + map(%{ + optional({"allThreadsContinued", :all_threads_continued}) => bool() + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/data_breakpoint_info.ex b/apps/debug_adapter/lib/protocol/dap/requests/data_breakpoint_info.ex new file mode 100644 index 000000000..89e38ad01 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/data_breakpoint_info.ex @@ -0,0 +1,111 @@ +# codegen: do not edit +defmodule GenDAP.Requests.DataBreakpointInfoRequest do + @moduledoc """ + Obtains information on a possible data breakpoint that could be set on an expression or variable. + Clients should only call this request if the corresponding capability `supportsDataBreakpoints` is true. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request dataBreakpointInfo" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "dataBreakpointInfo") + field(:arguments, GenDAP.Structures.DataBreakpointInfoArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "dataBreakpointInfo", + :arguments => GenDAP.Structures.DataBreakpointInfoArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.DataBreakpointInfoResponse do + @moduledoc """ + Response to `dataBreakpointInfo` request. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request dataBreakpointInfo response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "dataBreakpointInfo") + + field( + :body, + %{ + required(:description) => String.t(), + required(:data_id) => String.t() | nil, + optional(:access_types) => list(GenDAP.Enumerations.DataBreakpointAccessType.t()), + optional(:can_persist) => boolean() + }, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "dataBreakpointInfo", + :body => + map(%{ + {"description", :description} => str(), + {"dataId", :data_id} => oneof([str(), nil]), + optional({"accessTypes", :access_types}) => + list(GenDAP.Enumerations.DataBreakpointAccessType.schematic()), + optional({"canPersist", :can_persist}) => bool() + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/disassemble.ex b/apps/debug_adapter/lib/protocol/dap/requests/disassemble.ex new file mode 100644 index 000000000..63d359c5f --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/disassemble.ex @@ -0,0 +1,99 @@ +# codegen: do not edit +defmodule GenDAP.Requests.DisassembleRequest do + @moduledoc """ + Disassembles code stored at the provided location. + Clients should only call this request if the corresponding capability `supportsDisassembleRequest` is true. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request disassemble" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "disassemble") + field(:arguments, GenDAP.Structures.DisassembleArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "disassemble", + :arguments => GenDAP.Structures.DisassembleArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.DisassembleResponse do + @moduledoc """ + Response to `disassemble` request. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request disassemble response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "disassemble") + + field(:body, %{required(:instructions) => list(GenDAP.Structures.DisassembledInstruction.t())}) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "disassemble", + optional(:body) => + map(%{ + {"instructions", :instructions} => + list(GenDAP.Structures.DisassembledInstruction.schematic()) + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/disconnect.ex b/apps/debug_adapter/lib/protocol/dap/requests/disconnect.ex new file mode 100644 index 000000000..00b983050 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/disconnect.ex @@ -0,0 +1,93 @@ +# codegen: do not edit +defmodule GenDAP.Requests.DisconnectRequest do + @moduledoc """ + The `disconnect` request asks the debug adapter to disconnect from the debuggee (thus ending the debug session) and then to shut down itself (the debug adapter). + In addition, the debug adapter must terminate the debuggee if it was started with the `launch` request. If an `attach` request was used to connect to the debuggee, then the debug adapter must not terminate the debuggee. + This implicit behavior of when to terminate the debuggee can be overridden with the `terminateDebuggee` argument (which is only supported by a debug adapter if the corresponding capability `supportTerminateDebuggee` is true). + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request disconnect" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "disconnect") + field(:arguments, GenDAP.Structures.DisconnectArguments.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "disconnect", + optional(:arguments) => GenDAP.Structures.DisconnectArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.DisconnectResponse do + @moduledoc """ + A response to the disconnect request + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request disconnect response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "disconnect") + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "disconnect" + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/evaluate.ex b/apps/debug_adapter/lib/protocol/dap/requests/evaluate.ex new file mode 100644 index 000000000..e1a98b22e --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/evaluate.ex @@ -0,0 +1,119 @@ +# codegen: do not edit +defmodule GenDAP.Requests.EvaluateRequest do + @moduledoc """ + Evaluates the given expression in the context of a stack frame. + The expression has access to any variables and arguments that are in scope. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request evaluate" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "evaluate") + field(:arguments, GenDAP.Structures.EvaluateArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "evaluate", + :arguments => GenDAP.Structures.EvaluateArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.EvaluateResponse do + @moduledoc """ + Response to `evaluate` request. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request evaluate response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "evaluate") + + field( + :body, + %{ + optional(:type) => String.t(), + required(:result) => String.t(), + required(:variables_reference) => integer(), + optional(:memory_reference) => String.t(), + optional(:named_variables) => integer(), + optional(:indexed_variables) => integer(), + optional(:value_location_reference) => integer(), + optional(:presentation_hint) => GenDAP.Structures.VariablePresentationHint.t() + }, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "evaluate", + :body => + map(%{ + optional({"type", :type}) => str(), + {"result", :result} => str(), + {"variablesReference", :variables_reference} => int(), + optional({"memoryReference", :memory_reference}) => str(), + optional({"namedVariables", :named_variables}) => int(), + optional({"indexedVariables", :indexed_variables}) => int(), + optional({"valueLocationReference", :value_location_reference}) => int(), + optional({"presentationHint", :presentation_hint}) => + GenDAP.Structures.VariablePresentationHint.schematic() + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/exception_info.ex b/apps/debug_adapter/lib/protocol/dap/requests/exception_info.ex new file mode 100644 index 000000000..a5b6e0dfc --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/exception_info.ex @@ -0,0 +1,110 @@ +# codegen: do not edit +defmodule GenDAP.Requests.ExceptionInfoRequest do + @moduledoc """ + Retrieves the details of the exception that caused this event to be raised. + Clients should only call this request if the corresponding capability `supportsExceptionInfoRequest` is true. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request exceptionInfo" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "exceptionInfo") + field(:arguments, GenDAP.Structures.ExceptionInfoArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "exceptionInfo", + :arguments => GenDAP.Structures.ExceptionInfoArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.ExceptionInfoResponse do + @moduledoc """ + Response to `exceptionInfo` request. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request exceptionInfo response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "exceptionInfo") + + field( + :body, + %{ + optional(:description) => String.t(), + optional(:details) => GenDAP.Structures.ExceptionDetails.t(), + required(:exception_id) => String.t(), + required(:break_mode) => GenDAP.Enumerations.ExceptionBreakMode.t() + }, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "exceptionInfo", + :body => + map(%{ + optional({"description", :description}) => str(), + optional({"details", :details}) => GenDAP.Structures.ExceptionDetails.schematic(), + {"exceptionId", :exception_id} => str(), + {"breakMode", :break_mode} => GenDAP.Enumerations.ExceptionBreakMode.schematic() + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/goto.ex b/apps/debug_adapter/lib/protocol/dap/requests/goto.ex new file mode 100644 index 000000000..667621257 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/goto.ex @@ -0,0 +1,95 @@ +# codegen: do not edit +defmodule GenDAP.Requests.GotoRequest do + @moduledoc """ + The request sets the location where the debuggee will continue to run. + This makes it possible to skip the execution of code or to execute code again. + The code between the current location and the goto target is not executed but skipped. + The debug adapter first sends the response and then a `stopped` event with reason `goto`. + Clients should only call this request if the corresponding capability `supportsGotoTargetsRequest` is true (because only then goto targets exist that can be passed as arguments). + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request goto" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "goto") + field(:arguments, GenDAP.Structures.GotoArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "goto", + :arguments => GenDAP.Structures.GotoArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.GotoResponse do + @moduledoc """ + A response to the goto request + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request goto response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "goto") + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "goto" + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/goto_targets.ex b/apps/debug_adapter/lib/protocol/dap/requests/goto_targets.ex new file mode 100644 index 000000000..6e7f71d1b --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/goto_targets.ex @@ -0,0 +1,98 @@ +# codegen: do not edit +defmodule GenDAP.Requests.GotoTargetsRequest do + @moduledoc """ + This request retrieves the possible goto targets for the specified source location. + These targets can be used in the `goto` request. + Clients should only call this request if the corresponding capability `supportsGotoTargetsRequest` is true. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request gotoTargets" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "gotoTargets") + field(:arguments, GenDAP.Structures.GotoTargetsArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "gotoTargets", + :arguments => GenDAP.Structures.GotoTargetsArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.GotoTargetsResponse do + @moduledoc """ + Response to `gotoTargets` request. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request gotoTargets response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "gotoTargets") + field(:body, %{required(:targets) => list(GenDAP.Structures.GotoTarget.t())}, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "gotoTargets", + :body => + map(%{ + {"targets", :targets} => list(GenDAP.Structures.GotoTarget.schematic()) + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/initialize.ex b/apps/debug_adapter/lib/protocol/dap/requests/initialize.ex new file mode 100644 index 000000000..3e34ee6d7 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/initialize.ex @@ -0,0 +1,96 @@ +# codegen: do not edit +defmodule GenDAP.Requests.InitializeRequest do + @moduledoc """ + The `initialize` request is sent as the first request from the client to the debug adapter in order to configure it with client capabilities and to retrieve capabilities from the debug adapter. + Until the debug adapter has responded with an `initialize` response, the client must not send any additional requests or events to the debug adapter. + In addition the debug adapter is not allowed to send any requests or events to the client until it has responded with an `initialize` response. + The `initialize` request may only be sent once. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request initialize" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "initialize") + field(:arguments, GenDAP.Structures.InitializeRequestArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "initialize", + :arguments => GenDAP.Structures.InitializeRequestArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.InitializeResponse do + @moduledoc """ + Response to `initialize` request. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request initialize response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "initialize") + field(:body, GenDAP.Structures.Capabilities.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "initialize", + optional(:body) => GenDAP.Structures.Capabilities.schematic() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/launch.ex b/apps/debug_adapter/lib/protocol/dap/requests/launch.ex new file mode 100644 index 000000000..c829053dc --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/launch.ex @@ -0,0 +1,92 @@ +# codegen: do not edit +defmodule GenDAP.Requests.LaunchRequest do + @moduledoc """ + This launch request is sent from the client to the debug adapter to start the debuggee with or without debugging (if `noDebug` is true). + Since launching is debugger/runtime specific, the arguments for this request are not part of this specification. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request launch" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "launch") + field(:arguments, GenDAP.Structures.LaunchRequestArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "launch", + :arguments => GenDAP.Structures.LaunchRequestArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.LaunchResponse do + @moduledoc """ + A response to the launch request + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request launch response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "launch") + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "launch" + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/loaded_sources.ex b/apps/debug_adapter/lib/protocol/dap/requests/loaded_sources.ex new file mode 100644 index 000000000..aad7788ad --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/loaded_sources.ex @@ -0,0 +1,97 @@ +# codegen: do not edit +defmodule GenDAP.Requests.LoadedSourcesRequest do + @moduledoc """ + Retrieves the set of all sources currently loaded by the debugged process. + Clients should only call this request if the corresponding capability `supportsLoadedSourcesRequest` is true. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request loadedSources" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "loadedSources") + field(:arguments, GenDAP.Structures.LoadedSourcesArguments.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "loadedSources", + optional(:arguments) => GenDAP.Structures.LoadedSourcesArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.LoadedSourcesResponse do + @moduledoc """ + Response to `loadedSources` request. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request loadedSources response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "loadedSources") + field(:body, %{required(:sources) => list(GenDAP.Structures.Source.t())}, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "loadedSources", + :body => + map(%{ + {"sources", :sources} => list(GenDAP.Structures.Source.schematic()) + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/locations.ex b/apps/debug_adapter/lib/protocol/dap/requests/locations.ex new file mode 100644 index 000000000..f206bf17a --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/locations.ex @@ -0,0 +1,107 @@ +# codegen: do not edit +defmodule GenDAP.Requests.LocationsRequest do + @moduledoc """ + Looks up information about a location reference previously returned by the debug adapter. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request locations" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "locations") + field(:arguments, GenDAP.Structures.LocationsArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "locations", + :arguments => GenDAP.Structures.LocationsArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.LocationsResponse do + @moduledoc """ + Response to `locations` request. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request locations response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "locations") + + field(:body, %{ + required(:line) => integer(), + optional(:column) => integer(), + required(:source) => GenDAP.Structures.Source.t(), + optional(:end_line) => integer(), + optional(:end_column) => integer() + }) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "locations", + optional(:body) => + map(%{ + {"line", :line} => int(), + optional({"column", :column}) => int(), + {"source", :source} => GenDAP.Structures.Source.schematic(), + optional({"endLine", :end_line}) => int(), + optional({"endColumn", :end_column}) => int() + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/modules.ex b/apps/debug_adapter/lib/protocol/dap/requests/modules.ex new file mode 100644 index 000000000..3e2716248 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/modules.ex @@ -0,0 +1,106 @@ +# codegen: do not edit +defmodule GenDAP.Requests.ModulesRequest do + @moduledoc """ + Modules can be retrieved from the debug adapter with this request which can either return all modules or a range of modules to support paging. + Clients should only call this request if the corresponding capability `supportsModulesRequest` is true. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request modules" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "modules") + field(:arguments, GenDAP.Structures.ModulesArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "modules", + :arguments => GenDAP.Structures.ModulesArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.ModulesResponse do + @moduledoc """ + Response to `modules` request. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request modules response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "modules") + + field( + :body, + %{ + required(:modules) => list(GenDAP.Structures.Module.t()), + optional(:total_modules) => integer() + }, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "modules", + :body => + map(%{ + {"modules", :modules} => list(GenDAP.Structures.Module.schematic()), + optional({"totalModules", :total_modules}) => int() + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/next.ex b/apps/debug_adapter/lib/protocol/dap/requests/next.ex new file mode 100644 index 000000000..38e8dfbe4 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/next.ex @@ -0,0 +1,93 @@ +# codegen: do not edit +defmodule GenDAP.Requests.NextRequest do + @moduledoc """ + The request executes one step (in the given granularity) for the specified thread and allows all other threads to run freely by resuming them. + If the debug adapter supports single thread execution (see capability `supportsSingleThreadExecutionRequests`), setting the `singleThread` argument to true prevents other suspended threads from resuming. + The debug adapter first sends the response and then a `stopped` event (with reason `step`) after the step has completed. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request next" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "next") + field(:arguments, GenDAP.Structures.NextArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "next", + :arguments => GenDAP.Structures.NextArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.NextResponse do + @moduledoc """ + A response to the next request + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request next response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "next") + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "next" + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/pause.ex b/apps/debug_adapter/lib/protocol/dap/requests/pause.ex new file mode 100644 index 000000000..b94da442c --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/pause.ex @@ -0,0 +1,92 @@ +# codegen: do not edit +defmodule GenDAP.Requests.PauseRequest do + @moduledoc """ + The request suspends the debuggee. + The debug adapter first sends the response and then a `stopped` event (with reason `pause`) after the thread has been paused successfully. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request pause" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "pause") + field(:arguments, GenDAP.Structures.PauseArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "pause", + :arguments => GenDAP.Structures.PauseArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.PauseResponse do + @moduledoc """ + A response to the pause request + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request pause response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "pause") + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "pause" + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/read_memory.ex b/apps/debug_adapter/lib/protocol/dap/requests/read_memory.ex new file mode 100644 index 000000000..261c6593a --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/read_memory.ex @@ -0,0 +1,104 @@ +# codegen: do not edit +defmodule GenDAP.Requests.ReadMemoryRequest do + @moduledoc """ + Reads bytes from memory at the provided location. + Clients should only call this request if the corresponding capability `supportsReadMemoryRequest` is true. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request readMemory" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "readMemory") + field(:arguments, GenDAP.Structures.ReadMemoryArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "readMemory", + :arguments => GenDAP.Structures.ReadMemoryArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.ReadMemoryResponse do + @moduledoc """ + Response to `readMemory` request. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request readMemory response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "readMemory") + + field(:body, %{ + optional(:data) => String.t(), + required(:address) => String.t(), + optional(:unreadable_bytes) => integer() + }) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "readMemory", + optional(:body) => + map(%{ + optional({"data", :data}) => str(), + {"address", :address} => str(), + optional({"unreadableBytes", :unreadable_bytes}) => int() + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/restart.ex b/apps/debug_adapter/lib/protocol/dap/requests/restart.ex new file mode 100644 index 000000000..00c91e14a --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/restart.ex @@ -0,0 +1,92 @@ +# codegen: do not edit +defmodule GenDAP.Requests.RestartRequest do + @moduledoc """ + Restarts a debug session. Clients should only call this request if the corresponding capability `supportsRestartRequest` is true. + If the capability is missing or has the value false, a typical client emulates `restart` by terminating the debug adapter first and then launching it anew. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request restart" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "restart") + field(:arguments, GenDAP.Structures.RestartArguments.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "restart", + optional(:arguments) => GenDAP.Structures.RestartArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.RestartResponse do + @moduledoc """ + A response to the restart request + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request restart response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "restart") + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "restart" + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/restart_frame.ex b/apps/debug_adapter/lib/protocol/dap/requests/restart_frame.ex new file mode 100644 index 000000000..671e51124 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/restart_frame.ex @@ -0,0 +1,93 @@ +# codegen: do not edit +defmodule GenDAP.Requests.RestartFrameRequest do + @moduledoc """ + The request restarts execution of the specified stack frame. + The debug adapter first sends the response and then a `stopped` event (with reason `restart`) after the restart has completed. + Clients should only call this request if the corresponding capability `supportsRestartFrame` is true. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request restartFrame" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "restartFrame") + field(:arguments, GenDAP.Structures.RestartFrameArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "restartFrame", + :arguments => GenDAP.Structures.RestartFrameArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.RestartFrameResponse do + @moduledoc """ + A response to the restartFrame request + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request restartFrame response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "restartFrame") + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "restartFrame" + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/reverse_continue.ex b/apps/debug_adapter/lib/protocol/dap/requests/reverse_continue.ex new file mode 100644 index 000000000..653dcb98b --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/reverse_continue.ex @@ -0,0 +1,92 @@ +# codegen: do not edit +defmodule GenDAP.Requests.ReverseContinueRequest do + @moduledoc """ + The request resumes backward execution of all threads. If the debug adapter supports single thread execution (see capability `supportsSingleThreadExecutionRequests`), setting the `singleThread` argument to true resumes only the specified thread. If not all threads were resumed, the `allThreadsContinued` attribute of the response should be set to false. + Clients should only call this request if the corresponding capability `supportsStepBack` is true. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request reverseContinue" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "reverseContinue") + field(:arguments, GenDAP.Structures.ReverseContinueArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "reverseContinue", + :arguments => GenDAP.Structures.ReverseContinueArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.ReverseContinueResponse do + @moduledoc """ + A response to the reverseContinue request + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request reverseContinue response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "reverseContinue") + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "reverseContinue" + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/run_in_terminal.ex b/apps/debug_adapter/lib/protocol/dap/requests/run_in_terminal.ex new file mode 100644 index 000000000..ea101333e --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/run_in_terminal.ex @@ -0,0 +1,104 @@ +# codegen: do not edit +defmodule GenDAP.Requests.RunInTerminalRequest do + @moduledoc """ + This request is sent from the debug adapter to the client to run a command in a terminal. + This is typically used to launch the debuggee in a terminal provided by the client. + This request should only be called if the corresponding client capability `supportsRunInTerminalRequest` is true. + Client implementations of `runInTerminal` are free to run the command however they choose including issuing the command to a command line interpreter (aka 'shell'). Argument strings passed to the `runInTerminal` request must arrive verbatim in the command to be run. As a consequence, clients which use a shell are responsible for escaping any special shell characters in the argument strings to prevent them from being interpreted (and modified) by the shell. + Some users may wish to take advantage of shell processing in the argument strings. For clients which implement `runInTerminal` using an intermediary shell, the `argsCanBeInterpretedByShell` property can be set to true. In this case the client is requested not to escape any special shell characters in the argument strings. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request runInTerminal" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "runInTerminal") + field(:arguments, GenDAP.Structures.RunInTerminalRequestArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "runInTerminal", + :arguments => GenDAP.Structures.RunInTerminalRequestArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.RunInTerminalResponse do + @moduledoc """ + Response to `runInTerminal` request. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request runInTerminal response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "runInTerminal") + + field(:body, %{optional(:process_id) => integer(), optional(:shell_process_id) => integer()}, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "runInTerminal", + :body => + map(%{ + optional({"processId", :process_id}) => int(), + optional({"shellProcessId", :shell_process_id}) => int() + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/scopes.ex b/apps/debug_adapter/lib/protocol/dap/requests/scopes.ex new file mode 100644 index 000000000..de6b2236e --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/scopes.ex @@ -0,0 +1,96 @@ +# codegen: do not edit +defmodule GenDAP.Requests.ScopesRequest do + @moduledoc """ + The request returns the variable scopes for a given stack frame ID. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request scopes" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "scopes") + field(:arguments, GenDAP.Structures.ScopesArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "scopes", + :arguments => GenDAP.Structures.ScopesArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.ScopesResponse do + @moduledoc """ + Response to `scopes` request. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request scopes response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "scopes") + field(:body, %{required(:scopes) => list(GenDAP.Structures.Scope.t())}, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "scopes", + :body => + map(%{ + {"scopes", :scopes} => list(GenDAP.Structures.Scope.schematic()) + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/set_breakpoints.ex b/apps/debug_adapter/lib/protocol/dap/requests/set_breakpoints.ex new file mode 100644 index 000000000..2873ba266 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/set_breakpoints.ex @@ -0,0 +1,105 @@ +# codegen: do not edit +defmodule GenDAP.Requests.SetBreakpointsRequest do + @moduledoc """ + Sets multiple breakpoints for a single source and clears all previous breakpoints in that source. + To clear all breakpoint for a source, specify an empty array. + When a breakpoint is hit, a `stopped` event (with reason `breakpoint`) is generated. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request setBreakpoints" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "setBreakpoints") + field(:arguments, GenDAP.Structures.SetBreakpointsArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "setBreakpoints", + :arguments => GenDAP.Structures.SetBreakpointsArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.SetBreakpointsResponse do + @moduledoc """ + Response to `setBreakpoints` request. + Returned is information about each breakpoint created by this request. + This includes the actual code location and whether the breakpoint could be verified. + The breakpoints returned are in the same order as the elements of the `breakpoints` + (or the deprecated `lines`) array in the arguments. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request setBreakpoints response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "setBreakpoints") + + field(:body, %{required(:breakpoints) => list(GenDAP.Structures.Breakpoint.t())}, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "setBreakpoints", + :body => + map(%{ + {"breakpoints", :breakpoints} => list(GenDAP.Structures.Breakpoint.schematic()) + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/set_data_breakpoints.ex b/apps/debug_adapter/lib/protocol/dap/requests/set_data_breakpoints.ex new file mode 100644 index 000000000..564b650ef --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/set_data_breakpoints.ex @@ -0,0 +1,103 @@ +# codegen: do not edit +defmodule GenDAP.Requests.SetDataBreakpointsRequest do + @moduledoc """ + Replaces all existing data breakpoints with new data breakpoints. + To clear all data breakpoints, specify an empty array. + When a data breakpoint is hit, a `stopped` event (with reason `data breakpoint`) is generated. + Clients should only call this request if the corresponding capability `supportsDataBreakpoints` is true. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request setDataBreakpoints" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "setDataBreakpoints") + field(:arguments, GenDAP.Structures.SetDataBreakpointsArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "setDataBreakpoints", + :arguments => GenDAP.Structures.SetDataBreakpointsArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.SetDataBreakpointsResponse do + @moduledoc """ + Response to `setDataBreakpoints` request. + Returned is information about each breakpoint created by this request. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request setDataBreakpoints response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "setDataBreakpoints") + + field(:body, %{required(:breakpoints) => list(GenDAP.Structures.Breakpoint.t())}, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "setDataBreakpoints", + :body => + map(%{ + {"breakpoints", :breakpoints} => list(GenDAP.Structures.Breakpoint.schematic()) + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/set_exception_breakpoints.ex b/apps/debug_adapter/lib/protocol/dap/requests/set_exception_breakpoints.ex new file mode 100644 index 000000000..4cd37c777 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/set_exception_breakpoints.ex @@ -0,0 +1,101 @@ +# codegen: do not edit +defmodule GenDAP.Requests.SetExceptionBreakpointsRequest do + @moduledoc """ + The request configures the debugger's response to thrown exceptions. Each of the `filters`, `filterOptions`, and `exceptionOptions` in the request are independent configurations to a debug adapter indicating a kind of exception to catch. An exception thrown in a program should result in a `stopped` event from the debug adapter (with reason `exception`) if any of the configured filters match. + Clients should only call this request if the corresponding capability `exceptionBreakpointFilters` returns one or more filters. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request setExceptionBreakpoints" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "setExceptionBreakpoints") + field(:arguments, GenDAP.Structures.SetExceptionBreakpointsArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "setExceptionBreakpoints", + :arguments => GenDAP.Structures.SetExceptionBreakpointsArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.SetExceptionBreakpointsResponse do + @moduledoc """ + Response to `setExceptionBreakpoints` request. + The response contains an array of `Breakpoint` objects with information about each exception breakpoint or filter. The `Breakpoint` objects are in the same order as the elements of the `filters`, `filterOptions`, `exceptionOptions` arrays given as arguments. If both `filters` and `filterOptions` are given, the returned array must start with `filters` information first, followed by `filterOptions` information. + The `verified` property of a `Breakpoint` object signals whether the exception breakpoint or filter could be successfully created and whether the condition is valid. In case of an error the `message` property explains the problem. The `id` property can be used to introduce a unique ID for the exception breakpoint or filter so that it can be updated subsequently by sending breakpoint events. + For backward compatibility both the `breakpoints` array and the enclosing `body` are optional. If these elements are missing a client is not able to show problems for individual exception breakpoints or filters. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request setExceptionBreakpoints response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "setExceptionBreakpoints") + field(:body, %{optional(:breakpoints) => list(GenDAP.Structures.Breakpoint.t())}) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "setExceptionBreakpoints", + optional(:body) => + map(%{ + optional({"breakpoints", :breakpoints}) => + list(GenDAP.Structures.Breakpoint.schematic()) + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/set_expression.ex b/apps/debug_adapter/lib/protocol/dap/requests/set_expression.ex new file mode 100644 index 000000000..cc1bee33c --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/set_expression.ex @@ -0,0 +1,121 @@ +# codegen: do not edit +defmodule GenDAP.Requests.SetExpressionRequest do + @moduledoc """ + Evaluates the given `value` expression and assigns it to the `expression` which must be a modifiable l-value. + The expressions have access to any variables and arguments that are in scope of the specified frame. + Clients should only call this request if the corresponding capability `supportsSetExpression` is true. + If a debug adapter implements both `setExpression` and `setVariable`, a client uses `setExpression` if the variable has an `evaluateName` property. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request setExpression" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "setExpression") + field(:arguments, GenDAP.Structures.SetExpressionArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "setExpression", + :arguments => GenDAP.Structures.SetExpressionArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.SetExpressionResponse do + @moduledoc """ + Response to `setExpression` request. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request setExpression response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "setExpression") + + field( + :body, + %{ + optional(:type) => String.t(), + required(:value) => String.t(), + optional(:variables_reference) => integer(), + optional(:memory_reference) => String.t(), + optional(:named_variables) => integer(), + optional(:indexed_variables) => integer(), + optional(:value_location_reference) => integer(), + optional(:presentation_hint) => GenDAP.Structures.VariablePresentationHint.t() + }, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "setExpression", + :body => + map(%{ + optional({"type", :type}) => str(), + {"value", :value} => str(), + optional({"variablesReference", :variables_reference}) => int(), + optional({"memoryReference", :memory_reference}) => str(), + optional({"namedVariables", :named_variables}) => int(), + optional({"indexedVariables", :indexed_variables}) => int(), + optional({"valueLocationReference", :value_location_reference}) => int(), + optional({"presentationHint", :presentation_hint}) => + GenDAP.Structures.VariablePresentationHint.schematic() + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/set_function_breakpoints.ex b/apps/debug_adapter/lib/protocol/dap/requests/set_function_breakpoints.ex new file mode 100644 index 000000000..0d16447cd --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/set_function_breakpoints.ex @@ -0,0 +1,103 @@ +# codegen: do not edit +defmodule GenDAP.Requests.SetFunctionBreakpointsRequest do + @moduledoc """ + Replaces all existing function breakpoints with new function breakpoints. + To clear all function breakpoints, specify an empty array. + When a function breakpoint is hit, a `stopped` event (with reason `function breakpoint`) is generated. + Clients should only call this request if the corresponding capability `supportsFunctionBreakpoints` is true. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request setFunctionBreakpoints" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "setFunctionBreakpoints") + field(:arguments, GenDAP.Structures.SetFunctionBreakpointsArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "setFunctionBreakpoints", + :arguments => GenDAP.Structures.SetFunctionBreakpointsArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.SetFunctionBreakpointsResponse do + @moduledoc """ + Response to `setFunctionBreakpoints` request. + Returned is information about each breakpoint created by this request. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request setFunctionBreakpoints response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "setFunctionBreakpoints") + + field(:body, %{required(:breakpoints) => list(GenDAP.Structures.Breakpoint.t())}, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "setFunctionBreakpoints", + :body => + map(%{ + {"breakpoints", :breakpoints} => list(GenDAP.Structures.Breakpoint.schematic()) + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/set_instruction_breakpoints.ex b/apps/debug_adapter/lib/protocol/dap/requests/set_instruction_breakpoints.ex new file mode 100644 index 000000000..acc34bd74 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/set_instruction_breakpoints.ex @@ -0,0 +1,102 @@ +# codegen: do not edit +defmodule GenDAP.Requests.SetInstructionBreakpointsRequest do + @moduledoc """ + Replaces all existing instruction breakpoints. Typically, instruction breakpoints would be set from a disassembly window. + To clear all instruction breakpoints, specify an empty array. + When an instruction breakpoint is hit, a `stopped` event (with reason `instruction breakpoint`) is generated. + Clients should only call this request if the corresponding capability `supportsInstructionBreakpoints` is true. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request setInstructionBreakpoints" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "setInstructionBreakpoints") + field(:arguments, GenDAP.Structures.SetInstructionBreakpointsArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "setInstructionBreakpoints", + :arguments => GenDAP.Structures.SetInstructionBreakpointsArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.SetInstructionBreakpointsResponse do + @moduledoc """ + Response to `setInstructionBreakpoints` request + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request setInstructionBreakpoints response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "setInstructionBreakpoints") + + field(:body, %{required(:breakpoints) => list(GenDAP.Structures.Breakpoint.t())}, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "setInstructionBreakpoints", + :body => + map(%{ + {"breakpoints", :breakpoints} => list(GenDAP.Structures.Breakpoint.schematic()) + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/set_variable.ex b/apps/debug_adapter/lib/protocol/dap/requests/set_variable.ex new file mode 100644 index 000000000..c3dc55a87 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/set_variable.ex @@ -0,0 +1,116 @@ +# codegen: do not edit +defmodule GenDAP.Requests.SetVariableRequest do + @moduledoc """ + Set the variable with the given name in the variable container to a new value. Clients should only call this request if the corresponding capability `supportsSetVariable` is true. + If a debug adapter implements both `setVariable` and `setExpression`, a client will only use `setExpression` if the variable has an `evaluateName` property. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request setVariable" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "setVariable") + field(:arguments, GenDAP.Structures.SetVariableArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "setVariable", + :arguments => GenDAP.Structures.SetVariableArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.SetVariableResponse do + @moduledoc """ + Response to `setVariable` request. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request setVariable response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "setVariable") + + field( + :body, + %{ + optional(:type) => String.t(), + required(:value) => String.t(), + optional(:variables_reference) => integer(), + optional(:memory_reference) => String.t(), + optional(:named_variables) => integer(), + optional(:indexed_variables) => integer(), + optional(:value_location_reference) => integer() + }, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "setVariable", + :body => + map(%{ + optional({"type", :type}) => str(), + {"value", :value} => str(), + optional({"variablesReference", :variables_reference}) => int(), + optional({"memoryReference", :memory_reference}) => str(), + optional({"namedVariables", :named_variables}) => int(), + optional({"indexedVariables", :indexed_variables}) => int(), + optional({"valueLocationReference", :value_location_reference}) => int() + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/source.ex b/apps/debug_adapter/lib/protocol/dap/requests/source.ex new file mode 100644 index 000000000..e12f091ab --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/source.ex @@ -0,0 +1,100 @@ +# codegen: do not edit +defmodule GenDAP.Requests.SourceRequest do + @moduledoc """ + The request retrieves the source code for a given source reference. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request source" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "source") + field(:arguments, GenDAP.Structures.SourceArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "source", + :arguments => GenDAP.Structures.SourceArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.SourceResponse do + @moduledoc """ + Response to `source` request. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request source response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "source") + + field(:body, %{required(:content) => String.t(), optional(:mime_type) => String.t()}, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "source", + :body => + map(%{ + {"content", :content} => str(), + optional({"mimeType", :mime_type}) => str() + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/stack_trace.ex b/apps/debug_adapter/lib/protocol/dap/requests/stack_trace.ex new file mode 100644 index 000000000..304633cd6 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/stack_trace.ex @@ -0,0 +1,106 @@ +# codegen: do not edit +defmodule GenDAP.Requests.StackTraceRequest do + @moduledoc """ + The request returns a stacktrace from the current execution state of a given thread. + A client can request all stack frames by omitting the startFrame and levels arguments. For performance-conscious clients and if the corresponding capability `supportsDelayedStackTraceLoading` is true, stack frames can be retrieved in a piecemeal way with the `startFrame` and `levels` arguments. The response of the `stackTrace` request may contain a `totalFrames` property that hints at the total number of frames in the stack. If a client needs this total number upfront, it can issue a request for a single (first) frame and depending on the value of `totalFrames` decide how to proceed. In any case a client should be prepared to receive fewer frames than requested, which is an indication that the end of the stack has been reached. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request stackTrace" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "stackTrace") + field(:arguments, GenDAP.Structures.StackTraceArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "stackTrace", + :arguments => GenDAP.Structures.StackTraceArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.StackTraceResponse do + @moduledoc """ + Response to `stackTrace` request. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request stackTrace response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "stackTrace") + + field( + :body, + %{ + required(:stack_frames) => list(GenDAP.Structures.StackFrame.t()), + optional(:total_frames) => integer() + }, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "stackTrace", + :body => + map(%{ + {"stackFrames", :stack_frames} => list(GenDAP.Structures.StackFrame.schematic()), + optional({"totalFrames", :total_frames}) => int() + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/start_debugging.ex b/apps/debug_adapter/lib/protocol/dap/requests/start_debugging.ex new file mode 100644 index 000000000..c7a6a0479 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/start_debugging.ex @@ -0,0 +1,93 @@ +# codegen: do not edit +defmodule GenDAP.Requests.StartDebuggingRequest do + @moduledoc """ + This request is sent from the debug adapter to the client to start a new debug session of the same type as the caller. + This request should only be sent if the corresponding client capability `supportsStartDebuggingRequest` is true. + A client implementation of `startDebugging` should start a new debug session (of the same type as the caller) in the same way that the caller's session was started. If the client supports hierarchical debug sessions, the newly created session can be treated as a child of the caller session. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request startDebugging" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "startDebugging") + field(:arguments, GenDAP.Structures.StartDebuggingRequestArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "startDebugging", + :arguments => GenDAP.Structures.StartDebuggingRequestArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.StartDebuggingResponse do + @moduledoc """ + A response to the startDebugging request + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request startDebugging response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "startDebugging") + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "startDebugging" + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/step_back.ex b/apps/debug_adapter/lib/protocol/dap/requests/step_back.ex new file mode 100644 index 000000000..2c555dfb5 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/step_back.ex @@ -0,0 +1,94 @@ +# codegen: do not edit +defmodule GenDAP.Requests.StepBackRequest do + @moduledoc """ + The request executes one backward step (in the given granularity) for the specified thread and allows all other threads to run backward freely by resuming them. + If the debug adapter supports single thread execution (see capability `supportsSingleThreadExecutionRequests`), setting the `singleThread` argument to true prevents other suspended threads from resuming. + The debug adapter first sends the response and then a `stopped` event (with reason `step`) after the step has completed. + Clients should only call this request if the corresponding capability `supportsStepBack` is true. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request stepBack" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "stepBack") + field(:arguments, GenDAP.Structures.StepBackArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "stepBack", + :arguments => GenDAP.Structures.StepBackArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.StepBackResponse do + @moduledoc """ + A response to the stepBack request + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request stepBack response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "stepBack") + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "stepBack" + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/step_in.ex b/apps/debug_adapter/lib/protocol/dap/requests/step_in.ex new file mode 100644 index 000000000..78386f0b1 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/step_in.ex @@ -0,0 +1,97 @@ +# codegen: do not edit +defmodule GenDAP.Requests.StepInRequest do + @moduledoc """ + The request resumes the given thread to step into a function/method and allows all other threads to run freely by resuming them. + If the debug adapter supports single thread execution (see capability `supportsSingleThreadExecutionRequests`), setting the `singleThread` argument to true prevents other suspended threads from resuming. + If the request cannot step into a target, `stepIn` behaves like the `next` request. + The debug adapter first sends the response and then a `stopped` event (with reason `step`) after the step has completed. + If there are multiple function/method calls (or other targets) on the source line, + the argument `targetId` can be used to control into which target the `stepIn` should occur. + The list of possible targets for a given source line can be retrieved via the `stepInTargets` request. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request stepIn" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "stepIn") + field(:arguments, GenDAP.Structures.StepInArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "stepIn", + :arguments => GenDAP.Structures.StepInArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.StepInResponse do + @moduledoc """ + A response to the stepIn request + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request stepIn response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "stepIn") + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "stepIn" + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/step_in_targets.ex b/apps/debug_adapter/lib/protocol/dap/requests/step_in_targets.ex new file mode 100644 index 000000000..c64341890 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/step_in_targets.ex @@ -0,0 +1,98 @@ +# codegen: do not edit +defmodule GenDAP.Requests.StepInTargetsRequest do + @moduledoc """ + This request retrieves the possible step-in targets for the specified stack frame. + These targets can be used in the `stepIn` request. + Clients should only call this request if the corresponding capability `supportsStepInTargetsRequest` is true. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request stepInTargets" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "stepInTargets") + field(:arguments, GenDAP.Structures.StepInTargetsArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "stepInTargets", + :arguments => GenDAP.Structures.StepInTargetsArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.StepInTargetsResponse do + @moduledoc """ + Response to `stepInTargets` request. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request stepInTargets response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "stepInTargets") + field(:body, %{required(:targets) => list(GenDAP.Structures.StepInTarget.t())}, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "stepInTargets", + :body => + map(%{ + {"targets", :targets} => list(GenDAP.Structures.StepInTarget.schematic()) + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/step_out.ex b/apps/debug_adapter/lib/protocol/dap/requests/step_out.ex new file mode 100644 index 000000000..78513b73c --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/step_out.ex @@ -0,0 +1,93 @@ +# codegen: do not edit +defmodule GenDAP.Requests.StepOutRequest do + @moduledoc """ + The request resumes the given thread to step out (return) from a function/method and allows all other threads to run freely by resuming them. + If the debug adapter supports single thread execution (see capability `supportsSingleThreadExecutionRequests`), setting the `singleThread` argument to true prevents other suspended threads from resuming. + The debug adapter first sends the response and then a `stopped` event (with reason `step`) after the step has completed. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request stepOut" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "stepOut") + field(:arguments, GenDAP.Structures.StepOutArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "stepOut", + :arguments => GenDAP.Structures.StepOutArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.StepOutResponse do + @moduledoc """ + A response to the stepOut request + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request stepOut response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "stepOut") + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "stepOut" + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/terminate.ex b/apps/debug_adapter/lib/protocol/dap/requests/terminate.ex new file mode 100644 index 000000000..e476a0bc7 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/terminate.ex @@ -0,0 +1,94 @@ +# codegen: do not edit +defmodule GenDAP.Requests.TerminateRequest do + @moduledoc """ + The `terminate` request is sent from the client to the debug adapter in order to shut down the debuggee gracefully. Clients should only call this request if the capability `supportsTerminateRequest` is true. + Typically a debug adapter implements `terminate` by sending a software signal which the debuggee intercepts in order to clean things up properly before terminating itself. + Please note that this request does not directly affect the state of the debug session: if the debuggee decides to veto the graceful shutdown for any reason by not terminating itself, then the debug session just continues. + Clients can surface the `terminate` request as an explicit command or they can integrate it into a two stage Stop command that first sends `terminate` to request a graceful shutdown, and if that fails uses `disconnect` for a forceful shutdown. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request terminate" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "terminate") + field(:arguments, GenDAP.Structures.TerminateArguments.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "terminate", + optional(:arguments) => GenDAP.Structures.TerminateArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.TerminateResponse do + @moduledoc """ + A response to the terminate request + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request terminate response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "terminate") + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "terminate" + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/terminate_threads.ex b/apps/debug_adapter/lib/protocol/dap/requests/terminate_threads.ex new file mode 100644 index 000000000..2160653b5 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/terminate_threads.ex @@ -0,0 +1,92 @@ +# codegen: do not edit +defmodule GenDAP.Requests.TerminateThreadsRequest do + @moduledoc """ + The request terminates the threads with the given ids. + Clients should only call this request if the corresponding capability `supportsTerminateThreadsRequest` is true. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request terminateThreads" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "terminateThreads") + field(:arguments, GenDAP.Structures.TerminateThreadsArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "terminateThreads", + :arguments => GenDAP.Structures.TerminateThreadsArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.TerminateThreadsResponse do + @moduledoc """ + A response to the terminateThreads request + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request terminateThreads response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "terminateThreads") + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "terminateThreads" + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/threads.ex b/apps/debug_adapter/lib/protocol/dap/requests/threads.ex new file mode 100644 index 000000000..32adb44d8 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/threads.ex @@ -0,0 +1,94 @@ +# codegen: do not edit +defmodule GenDAP.Requests.ThreadsRequest do + @moduledoc """ + The request retrieves a list of all threads. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request threads" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "threads") + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "threads" + }) + end +end + +defmodule GenDAP.Requests.ThreadsResponse do + @moduledoc """ + Response to `threads` request. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request threads response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "threads") + field(:body, %{required(:threads) => list(GenDAP.Structures.Thread.t())}, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "threads", + :body => + map(%{ + {"threads", :threads} => list(GenDAP.Structures.Thread.schematic()) + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/variables.ex b/apps/debug_adapter/lib/protocol/dap/requests/variables.ex new file mode 100644 index 000000000..e37c698eb --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/variables.ex @@ -0,0 +1,97 @@ +# codegen: do not edit +defmodule GenDAP.Requests.VariablesRequest do + @moduledoc """ + Retrieves all child variables for the given variable reference. + A filter can be used to limit the fetched children to either named or indexed children. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request variables" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "variables") + field(:arguments, GenDAP.Structures.VariablesArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "variables", + :arguments => GenDAP.Structures.VariablesArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.VariablesResponse do + @moduledoc """ + Response to `variables` request. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request variables response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "variables") + field(:body, %{required(:variables) => list(GenDAP.Structures.Variable.t())}, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "variables", + :body => + map(%{ + {"variables", :variables} => list(GenDAP.Structures.Variable.schematic()) + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/requests/write_memory.ex b/apps/debug_adapter/lib/protocol/dap/requests/write_memory.ex new file mode 100644 index 000000000..ea9193a82 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/requests/write_memory.ex @@ -0,0 +1,98 @@ +# codegen: do not edit +defmodule GenDAP.Requests.WriteMemoryRequest do + @moduledoc """ + Writes bytes to memory at the provided location. + Clients should only call this request if the corresponding capability `supportsWriteMemoryRequest` is true. + + Message Direction: client -> adapter + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: Object containing arguments for the command. + * command: The command to execute. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request writeMemory" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "request") + field(:command, String.t(), default: "writeMemory") + field(:arguments, GenDAP.Structures.WriteMemoryArguments.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "request", + :command => "writeMemory", + :arguments => GenDAP.Structures.WriteMemoryArguments.schematic() + }) + end +end + +defmodule GenDAP.Requests.WriteMemoryResponse do + @moduledoc """ + Response to `writeMemory` request. + + Message Direction: adapter -> client + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP request writeMemory response" + + field(:seq, integer(), enforce: true) + field(:type, String.t(), default: "response") + field(:request_seq, integer(), enforce: true) + field(:success, boolean(), default: true) + field(:command, String.t(), default: "writeMemory") + field(:body, %{optional(:offset) => integer(), optional(:bytes_written) => integer()}) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + :seq => int(), + :type => "response", + :request_seq => int(), + :success => true, + :command => "writeMemory", + optional(:body) => + map(%{ + optional({"offset", :offset}) => int(), + optional({"bytesWritten", :bytes_written}) => int() + }) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/responses.ex b/apps/debug_adapter/lib/protocol/dap/responses.ex new file mode 100644 index 000000000..9adf4a6c4 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/responses.ex @@ -0,0 +1,149 @@ +# codegen: do not edit +defmodule GenDAP.Responses do + import SchematicV + + def new(request) do + unify( + oneof(fn + %{"command" => "attach"} -> + GenDAP.Requests.AttachResponse.schematic() + + %{"command" => "breakpointLocations"} -> + GenDAP.Requests.BreakpointLocationsResponse.schematic() + + %{"command" => "cancel"} -> + GenDAP.Requests.CancelResponse.schematic() + + %{"command" => "completions"} -> + GenDAP.Requests.CompletionsResponse.schematic() + + %{"command" => "configurationDone"} -> + GenDAP.Requests.ConfigurationDoneResponse.schematic() + + %{"command" => "continue"} -> + GenDAP.Requests.ContinueResponse.schematic() + + %{"command" => "dataBreakpointInfo"} -> + GenDAP.Requests.DataBreakpointInfoResponse.schematic() + + %{"command" => "disassemble"} -> + GenDAP.Requests.DisassembleResponse.schematic() + + %{"command" => "disconnect"} -> + GenDAP.Requests.DisconnectResponse.schematic() + + %{"command" => "evaluate"} -> + GenDAP.Requests.EvaluateResponse.schematic() + + %{"command" => "exceptionInfo"} -> + GenDAP.Requests.ExceptionInfoResponse.schematic() + + %{"command" => "goto"} -> + GenDAP.Requests.GotoResponse.schematic() + + %{"command" => "gotoTargets"} -> + GenDAP.Requests.GotoTargetsResponse.schematic() + + %{"command" => "initialize"} -> + GenDAP.Requests.InitializeResponse.schematic() + + %{"command" => "launch"} -> + GenDAP.Requests.LaunchResponse.schematic() + + %{"command" => "loadedSources"} -> + GenDAP.Requests.LoadedSourcesResponse.schematic() + + %{"command" => "locations"} -> + GenDAP.Requests.LocationsResponse.schematic() + + %{"command" => "modules"} -> + GenDAP.Requests.ModulesResponse.schematic() + + %{"command" => "next"} -> + GenDAP.Requests.NextResponse.schematic() + + %{"command" => "pause"} -> + GenDAP.Requests.PauseResponse.schematic() + + %{"command" => "readMemory"} -> + GenDAP.Requests.ReadMemoryResponse.schematic() + + %{"command" => "restart"} -> + GenDAP.Requests.RestartResponse.schematic() + + %{"command" => "restartFrame"} -> + GenDAP.Requests.RestartFrameResponse.schematic() + + %{"command" => "reverseContinue"} -> + GenDAP.Requests.ReverseContinueResponse.schematic() + + %{"command" => "runInTerminal"} -> + GenDAP.Requests.RunInTerminalResponse.schematic() + + %{"command" => "scopes"} -> + GenDAP.Requests.ScopesResponse.schematic() + + %{"command" => "setBreakpoints"} -> + GenDAP.Requests.SetBreakpointsResponse.schematic() + + %{"command" => "setDataBreakpoints"} -> + GenDAP.Requests.SetDataBreakpointsResponse.schematic() + + %{"command" => "setExceptionBreakpoints"} -> + GenDAP.Requests.SetExceptionBreakpointsResponse.schematic() + + %{"command" => "setExpression"} -> + GenDAP.Requests.SetExpressionResponse.schematic() + + %{"command" => "setFunctionBreakpoints"} -> + GenDAP.Requests.SetFunctionBreakpointsResponse.schematic() + + %{"command" => "setInstructionBreakpoints"} -> + GenDAP.Requests.SetInstructionBreakpointsResponse.schematic() + + %{"command" => "setVariable"} -> + GenDAP.Requests.SetVariableResponse.schematic() + + %{"command" => "source"} -> + GenDAP.Requests.SourceResponse.schematic() + + %{"command" => "stackTrace"} -> + GenDAP.Requests.StackTraceResponse.schematic() + + %{"command" => "startDebugging"} -> + GenDAP.Requests.StartDebuggingResponse.schematic() + + %{"command" => "stepBack"} -> + GenDAP.Requests.StepBackResponse.schematic() + + %{"command" => "stepIn"} -> + GenDAP.Requests.StepInResponse.schematic() + + %{"command" => "stepInTargets"} -> + GenDAP.Requests.StepInTargetsResponse.schematic() + + %{"command" => "stepOut"} -> + GenDAP.Requests.StepOutResponse.schematic() + + %{"command" => "terminate"} -> + GenDAP.Requests.TerminateResponse.schematic() + + %{"command" => "terminateThreads"} -> + GenDAP.Requests.TerminateThreadsResponse.schematic() + + %{"command" => "threads"} -> + GenDAP.Requests.ThreadsResponse.schematic() + + %{"command" => "variables"} -> + GenDAP.Requests.VariablesResponse.schematic() + + %{"command" => "writeMemory"} -> + GenDAP.Requests.WriteMemoryResponse.schematic() + + _ -> + {:error, "unexpected response payload"} + end), + request + ) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/attach_request_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/attach_request_arguments.ex new file mode 100644 index 000000000..210df6471 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/attach_request_arguments.ex @@ -0,0 +1,28 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.AttachRequestArguments do + @moduledoc """ + Arguments for `attach` request. Additional attributes are implementation specific. + """ + + import SchematicV, warn: false + + @typedoc "A type defining DAP structure AttachRequestArguments" + @type t() :: %{ + optional(:__restart) => + list() | boolean() | integer() | nil | number() | map() | String.t(), + optional(String.t()) => any() + } + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + all([ + map(%{ + optional({"__restart", :__restart}) => + oneof([list(), bool(), int(), nil, oneof([int(), float()]), map(), str()]) + }), + map() + ]) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/breakpoint.ex b/apps/debug_adapter/lib/protocol/dap/structures/breakpoint.ex new file mode 100644 index 000000000..5c3966b64 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/breakpoint.ex @@ -0,0 +1,66 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.Breakpoint do + @moduledoc """ + Information about a breakpoint created in `setBreakpoints`, `setFunctionBreakpoints`, `setInstructionBreakpoints`, or `setDataBreakpoints` requests. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * column: Start position of the source range covered by the breakpoint. It is measured in UTF-16 code units and the client capability `columnsStartAt1` determines whether it is 0- or 1-based. + * end_column: End position of the source range covered by the breakpoint. It is measured in UTF-16 code units and the client capability `columnsStartAt1` determines whether it is 0- or 1-based. + If no end line is given, then the end column is assumed to be in the start line. + * end_line: The end line of the actual range covered by the breakpoint. + * id: The identifier for the breakpoint. It is needed if breakpoint events are used to update or remove breakpoints. + * instruction_reference: A memory reference to where the breakpoint is set. + * line: The start line of the actual range covered by the breakpoint. + * message: A message about the state of the breakpoint. + This is shown to the user and can be used to explain why a breakpoint could not be verified. + * offset: The offset from the instruction reference. + This can be negative. + * reason: A machine-readable explanation of why a breakpoint may not be verified. If a breakpoint is verified or a specific reason is not known, the adapter should omit this property. Possible values include: + + - `pending`: Indicates a breakpoint might be verified in the future, but the adapter cannot verify it in the current state. + - `failed`: Indicates a breakpoint was not able to be verified, and the adapter does not believe it can be verified without intervention. + * source: The source where the breakpoint is located. + * verified: If true, the breakpoint could be set (but not necessarily at the desired location). + """ + + typedstruct do + @typedoc "A type defining DAP structure Breakpoint" + field(:column, integer()) + field(:end_column, integer()) + field(:end_line, integer()) + field(:id, integer()) + field(:instruction_reference, String.t()) + field(:line, integer()) + field(:message, String.t()) + field(:offset, integer()) + field(:reason, String.t()) + field(:source, GenDAP.Structures.Source.t()) + field(:verified, boolean(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"column", :column}) => int(), + optional({"endColumn", :end_column}) => int(), + optional({"endLine", :end_line}) => int(), + optional({"id", :id}) => int(), + optional({"instructionReference", :instruction_reference}) => str(), + optional({"line", :line}) => int(), + optional({"message", :message}) => str(), + optional({"offset", :offset}) => int(), + optional({"reason", :reason}) => oneof(["pending", "failed"]), + optional({"source", :source}) => GenDAP.Structures.Source.schematic(), + {"verified", :verified} => bool() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/breakpoint_location.ex b/apps/debug_adapter/lib/protocol/dap/structures/breakpoint_location.ex new file mode 100644 index 000000000..4c1e39d58 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/breakpoint_location.ex @@ -0,0 +1,39 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.BreakpointLocation do + @moduledoc """ + Properties of a breakpoint location returned from the `breakpointLocations` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * column: The start position of a breakpoint location. Position is measured in UTF-16 code units and the client capability `columnsStartAt1` determines whether it is 0- or 1-based. + * end_column: The end position of a breakpoint location (if the location covers a range). Position is measured in UTF-16 code units and the client capability `columnsStartAt1` determines whether it is 0- or 1-based. + * end_line: The end line of breakpoint location if the location covers a range. + * line: Start line of breakpoint location. + """ + + typedstruct do + @typedoc "A type defining DAP structure BreakpointLocation" + field(:column, integer()) + field(:end_column, integer()) + field(:end_line, integer()) + field(:line, integer(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"column", :column}) => int(), + optional({"endColumn", :end_column}) => int(), + optional({"endLine", :end_line}) => int(), + {"line", :line} => int() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/breakpoint_locations_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/breakpoint_locations_arguments.ex new file mode 100644 index 000000000..020123d2e --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/breakpoint_locations_arguments.ex @@ -0,0 +1,42 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.BreakpointLocationsArguments do + @moduledoc """ + Arguments for `breakpointLocations` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * column: Start position within `line` to search possible breakpoint locations in. It is measured in UTF-16 code units and the client capability `columnsStartAt1` determines whether it is 0- or 1-based. If no column is given, the first position in the start line is assumed. + * end_column: End position within `endLine` to search possible breakpoint locations in. It is measured in UTF-16 code units and the client capability `columnsStartAt1` determines whether it is 0- or 1-based. If no end column is given, the last position in the end line is assumed. + * end_line: End line of range to search possible breakpoint locations in. If no end line is given, then the end line is assumed to be the start line. + * line: Start line of range to search possible breakpoint locations in. If only the line is specified, the request returns all possible locations in that line. + * source: The source location of the breakpoints; either `source.path` or `source.sourceReference` must be specified. + """ + + typedstruct do + @typedoc "A type defining DAP structure BreakpointLocationsArguments" + field(:column, integer()) + field(:end_column, integer()) + field(:end_line, integer()) + field(:line, integer(), enforce: true) + field(:source, GenDAP.Structures.Source.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"column", :column}) => int(), + optional({"endColumn", :end_column}) => int(), + optional({"endLine", :end_line}) => int(), + {"line", :line} => int(), + {"source", :source} => GenDAP.Structures.Source.schematic() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/breakpoint_mode.ex b/apps/debug_adapter/lib/protocol/dap/structures/breakpoint_mode.ex new file mode 100644 index 000000000..f222c6d97 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/breakpoint_mode.ex @@ -0,0 +1,40 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.BreakpointMode do + @moduledoc """ + A `BreakpointMode` is provided as a option when setting breakpoints on sources or instructions. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * applies_to: Describes one or more type of breakpoint this mode applies to. + * description: A help text providing additional information about the breakpoint mode. This string is typically shown as a hover and can be translated. + * label: The name of the breakpoint mode. This is shown in the UI. + * mode: The internal ID of the mode. This value is passed to the `setBreakpoints` request. + """ + + typedstruct do + @typedoc "A type defining DAP structure BreakpointMode" + field(:applies_to, list(GenDAP.Enumerations.BreakpointModeApplicability.t()), enforce: true) + field(:description, String.t()) + field(:label, String.t(), enforce: true) + field(:mode, String.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"appliesTo", :applies_to} => + list(GenDAP.Enumerations.BreakpointModeApplicability.schematic()), + optional({"description", :description}) => str(), + {"label", :label} => str(), + {"mode", :mode} => str() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/cancel_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/cancel_arguments.ex new file mode 100644 index 000000000..9f21708cb --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/cancel_arguments.ex @@ -0,0 +1,35 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.CancelArguments do + @moduledoc """ + Arguments for `cancel` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * progress_id: The ID (attribute `progressId`) of the progress to cancel. If missing no progress is cancelled. + Both a `requestId` and a `progressId` can be specified in one request. + * request_id: The ID (attribute `seq`) of the request to cancel. If missing no request is cancelled. + Both a `requestId` and a `progressId` can be specified in one request. + """ + + typedstruct do + @typedoc "A type defining DAP structure CancelArguments" + field(:progress_id, String.t()) + field(:request_id, integer()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"progressId", :progress_id}) => str(), + optional({"requestId", :request_id}) => int() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/capabilities.ex b/apps/debug_adapter/lib/protocol/dap/structures/capabilities.ex new file mode 100644 index 000000000..d1bbed3d9 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/capabilities.ex @@ -0,0 +1,166 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.Capabilities do + @moduledoc """ + Information about the capabilities of a debug adapter. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * additional_module_columns: The set of additional module information exposed by the debug adapter. + * breakpoint_modes: Modes of breakpoints supported by the debug adapter, such as 'hardware' or 'software'. If present, the client may allow the user to select a mode and include it in its `setBreakpoints` request. + + Clients may present the first applicable mode in this array as the 'default' mode in gestures that set breakpoints. + * completion_trigger_characters: The set of characters that should trigger completion in a REPL. If not specified, the UI should assume the `.` character. + * exception_breakpoint_filters: Available exception filter options for the `setExceptionBreakpoints` request. + * support_suspend_debuggee: The debug adapter supports the `suspendDebuggee` attribute on the `disconnect` request. + * support_terminate_debuggee: The debug adapter supports the `terminateDebuggee` attribute on the `disconnect` request. + * supported_checksum_algorithms: Checksum algorithms supported by the debug adapter. + * supports_a_n_s_i_styling: The debug adapter supports ANSI escape sequences in styling of `OutputEvent.output` and `Variable.value` fields. + * supports_breakpoint_locations_request: The debug adapter supports the `breakpointLocations` request. + * supports_cancel_request: The debug adapter supports the `cancel` request. + * supports_clipboard_context: The debug adapter supports the `clipboard` context value in the `evaluate` request. + * supports_completions_request: The debug adapter supports the `completions` request. + * supports_conditional_breakpoints: The debug adapter supports conditional breakpoints. + * supports_configuration_done_request: The debug adapter supports the `configurationDone` request. + * supports_data_breakpoint_bytes: The debug adapter supports the `asAddress` and `bytes` fields in the `dataBreakpointInfo` request. + * supports_data_breakpoints: The debug adapter supports data breakpoints. + * supports_delayed_stack_trace_loading: The debug adapter supports the delayed loading of parts of the stack, which requires that both the `startFrame` and `levels` arguments and the `totalFrames` result of the `stackTrace` request are supported. + * supports_disassemble_request: The debug adapter supports the `disassemble` request. + * supports_evaluate_for_hovers: The debug adapter supports a (side effect free) `evaluate` request for data hovers. + * supports_exception_filter_options: The debug adapter supports `filterOptions` as an argument on the `setExceptionBreakpoints` request. + * supports_exception_info_request: The debug adapter supports the `exceptionInfo` request. + * supports_exception_options: The debug adapter supports `exceptionOptions` on the `setExceptionBreakpoints` request. + * supports_function_breakpoints: The debug adapter supports function breakpoints. + * supports_goto_targets_request: The debug adapter supports the `gotoTargets` request. + * supports_hit_conditional_breakpoints: The debug adapter supports breakpoints that break execution after a specified number of hits. + * supports_instruction_breakpoints: The debug adapter supports adding breakpoints based on instruction references. + * supports_loaded_sources_request: The debug adapter supports the `loadedSources` request. + * supports_log_points: The debug adapter supports log points by interpreting the `logMessage` attribute of the `SourceBreakpoint`. + * supports_modules_request: The debug adapter supports the `modules` request. + * supports_read_memory_request: The debug adapter supports the `readMemory` request. + * supports_restart_frame: The debug adapter supports restarting a frame. + * supports_restart_request: The debug adapter supports the `restart` request. In this case a client should not implement `restart` by terminating and relaunching the adapter but by calling the `restart` request. + * supports_set_expression: The debug adapter supports the `setExpression` request. + * supports_set_variable: The debug adapter supports setting a variable to a value. + * supports_single_thread_execution_requests: The debug adapter supports the `singleThread` property on the execution requests (`continue`, `next`, `stepIn`, `stepOut`, `reverseContinue`, `stepBack`). + * supports_step_back: The debug adapter supports stepping back via the `stepBack` and `reverseContinue` requests. + * supports_step_in_targets_request: The debug adapter supports the `stepInTargets` request. + * supports_stepping_granularity: The debug adapter supports stepping granularities (argument `granularity`) for the stepping requests. + * supports_terminate_request: The debug adapter supports the `terminate` request. + * supports_terminate_threads_request: The debug adapter supports the `terminateThreads` request. + * supports_value_formatting_options: The debug adapter supports a `format` attribute on the `stackTrace`, `variables`, and `evaluate` requests. + * supports_write_memory_request: The debug adapter supports the `writeMemory` request. + """ + + typedstruct do + @typedoc "A type defining DAP structure Capabilities" + field(:additional_module_columns, list(GenDAP.Structures.ColumnDescriptor.t())) + field(:breakpoint_modes, list(GenDAP.Structures.BreakpointMode.t())) + field(:completion_trigger_characters, list(String.t())) + field(:exception_breakpoint_filters, list(GenDAP.Structures.ExceptionBreakpointsFilter.t())) + field(:support_suspend_debuggee, boolean()) + field(:support_terminate_debuggee, boolean()) + field(:supported_checksum_algorithms, list(GenDAP.Enumerations.ChecksumAlgorithm.t())) + field(:supports_a_n_s_i_styling, boolean()) + field(:supports_breakpoint_locations_request, boolean()) + field(:supports_cancel_request, boolean()) + field(:supports_clipboard_context, boolean()) + field(:supports_completions_request, boolean()) + field(:supports_conditional_breakpoints, boolean()) + field(:supports_configuration_done_request, boolean()) + field(:supports_data_breakpoint_bytes, boolean()) + field(:supports_data_breakpoints, boolean()) + field(:supports_delayed_stack_trace_loading, boolean()) + field(:supports_disassemble_request, boolean()) + field(:supports_evaluate_for_hovers, boolean()) + field(:supports_exception_filter_options, boolean()) + field(:supports_exception_info_request, boolean()) + field(:supports_exception_options, boolean()) + field(:supports_function_breakpoints, boolean()) + field(:supports_goto_targets_request, boolean()) + field(:supports_hit_conditional_breakpoints, boolean()) + field(:supports_instruction_breakpoints, boolean()) + field(:supports_loaded_sources_request, boolean()) + field(:supports_log_points, boolean()) + field(:supports_modules_request, boolean()) + field(:supports_read_memory_request, boolean()) + field(:supports_restart_frame, boolean()) + field(:supports_restart_request, boolean()) + field(:supports_set_expression, boolean()) + field(:supports_set_variable, boolean()) + field(:supports_single_thread_execution_requests, boolean()) + field(:supports_step_back, boolean()) + field(:supports_step_in_targets_request, boolean()) + field(:supports_stepping_granularity, boolean()) + field(:supports_terminate_request, boolean()) + field(:supports_terminate_threads_request, boolean()) + field(:supports_value_formatting_options, boolean()) + field(:supports_write_memory_request, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"additionalModuleColumns", :additional_module_columns}) => + list(GenDAP.Structures.ColumnDescriptor.schematic()), + optional({"breakpointModes", :breakpoint_modes}) => + list(GenDAP.Structures.BreakpointMode.schematic()), + optional({"completionTriggerCharacters", :completion_trigger_characters}) => list(str()), + optional({"exceptionBreakpointFilters", :exception_breakpoint_filters}) => + list(GenDAP.Structures.ExceptionBreakpointsFilter.schematic()), + optional({"supportSuspendDebuggee", :support_suspend_debuggee}) => bool(), + optional({"supportTerminateDebuggee", :support_terminate_debuggee}) => bool(), + optional({"supportedChecksumAlgorithms", :supported_checksum_algorithms}) => + list(GenDAP.Enumerations.ChecksumAlgorithm.schematic()), + optional({"supportsANSIStyling", :supports_a_n_s_i_styling}) => bool(), + optional({"supportsBreakpointLocationsRequest", :supports_breakpoint_locations_request}) => + bool(), + optional({"supportsCancelRequest", :supports_cancel_request}) => bool(), + optional({"supportsClipboardContext", :supports_clipboard_context}) => bool(), + optional({"supportsCompletionsRequest", :supports_completions_request}) => bool(), + optional({"supportsConditionalBreakpoints", :supports_conditional_breakpoints}) => bool(), + optional({"supportsConfigurationDoneRequest", :supports_configuration_done_request}) => + bool(), + optional({"supportsDataBreakpointBytes", :supports_data_breakpoint_bytes}) => bool(), + optional({"supportsDataBreakpoints", :supports_data_breakpoints}) => bool(), + optional({"supportsDelayedStackTraceLoading", :supports_delayed_stack_trace_loading}) => + bool(), + optional({"supportsDisassembleRequest", :supports_disassemble_request}) => bool(), + optional({"supportsEvaluateForHovers", :supports_evaluate_for_hovers}) => bool(), + optional({"supportsExceptionFilterOptions", :supports_exception_filter_options}) => bool(), + optional({"supportsExceptionInfoRequest", :supports_exception_info_request}) => bool(), + optional({"supportsExceptionOptions", :supports_exception_options}) => bool(), + optional({"supportsFunctionBreakpoints", :supports_function_breakpoints}) => bool(), + optional({"supportsGotoTargetsRequest", :supports_goto_targets_request}) => bool(), + optional({"supportsHitConditionalBreakpoints", :supports_hit_conditional_breakpoints}) => + bool(), + optional({"supportsInstructionBreakpoints", :supports_instruction_breakpoints}) => bool(), + optional({"supportsLoadedSourcesRequest", :supports_loaded_sources_request}) => bool(), + optional({"supportsLogPoints", :supports_log_points}) => bool(), + optional({"supportsModulesRequest", :supports_modules_request}) => bool(), + optional({"supportsReadMemoryRequest", :supports_read_memory_request}) => bool(), + optional({"supportsRestartFrame", :supports_restart_frame}) => bool(), + optional({"supportsRestartRequest", :supports_restart_request}) => bool(), + optional({"supportsSetExpression", :supports_set_expression}) => bool(), + optional({"supportsSetVariable", :supports_set_variable}) => bool(), + optional( + {"supportsSingleThreadExecutionRequests", :supports_single_thread_execution_requests} + ) => bool(), + optional({"supportsStepBack", :supports_step_back}) => bool(), + optional({"supportsStepInTargetsRequest", :supports_step_in_targets_request}) => bool(), + optional({"supportsSteppingGranularity", :supports_stepping_granularity}) => bool(), + optional({"supportsTerminateRequest", :supports_terminate_request}) => bool(), + optional({"supportsTerminateThreadsRequest", :supports_terminate_threads_request}) => + bool(), + optional({"supportsValueFormattingOptions", :supports_value_formatting_options}) => bool(), + optional({"supportsWriteMemoryRequest", :supports_write_memory_request}) => bool() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/checksum.ex b/apps/debug_adapter/lib/protocol/dap/structures/checksum.ex new file mode 100644 index 000000000..6b764f886 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/checksum.ex @@ -0,0 +1,33 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.Checksum do + @moduledoc """ + The checksum of an item calculated by the specified algorithm. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * algorithm: The algorithm used to calculate this checksum. + * checksum: Value of the checksum, encoded as a hexadecimal value. + """ + + typedstruct do + @typedoc "A type defining DAP structure Checksum" + field(:algorithm, GenDAP.Enumerations.ChecksumAlgorithm.t(), enforce: true) + field(:checksum, String.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"algorithm", :algorithm} => GenDAP.Enumerations.ChecksumAlgorithm.schematic(), + {"checksum", :checksum} => str() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/column_descriptor.ex b/apps/debug_adapter/lib/protocol/dap/structures/column_descriptor.ex new file mode 100644 index 000000000..181a860c8 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/column_descriptor.ex @@ -0,0 +1,44 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.ColumnDescriptor do + @moduledoc """ + A `ColumnDescriptor` specifies what module attribute to show in a column of the modules view, how to format it, + and what the column's label should be. + It is only used if the underlying UI actually supports this level of customization. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * attribute_name: Name of the attribute rendered in this column. + * format: Format to use for the rendered values in this column. TBD how the format strings looks like. + * label: Header UI label of column. + * type: Datatype of values in this column. Defaults to `string` if not specified. + * width: Width of this column in characters (hint only). + """ + + typedstruct do + @typedoc "A type defining DAP structure ColumnDescriptor" + field(:attribute_name, String.t(), enforce: true) + field(:format, String.t()) + field(:label, String.t(), enforce: true) + field(:type, String.t()) + field(:width, integer()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"attributeName", :attribute_name} => str(), + optional({"format", :format}) => str(), + {"label", :label} => str(), + optional({"type", :type}) => oneof(["string", "number", "boolean", "unixTimestampUTC"]), + optional({"width", :width}) => int() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/completion_item.ex b/apps/debug_adapter/lib/protocol/dap/structures/completion_item.ex new file mode 100644 index 000000000..4168a5ac9 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/completion_item.ex @@ -0,0 +1,54 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.CompletionItem do + @moduledoc """ + `CompletionItems` are the suggestions returned from the `completions` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * detail: A human-readable string with additional information about this item, like type or symbol information. + * label: The label of this completion item. By default this is also the text that is inserted when selecting this completion. + * length: Length determines how many characters are overwritten by the completion text and it is measured in UTF-16 code units. If missing the value 0 is assumed which results in the completion text being inserted. + * selection_length: Determines the length of the new selection after the text has been inserted (or replaced) and it is measured in UTF-16 code units. The selection can not extend beyond the bounds of the completion text. If omitted the length is assumed to be 0. + * selection_start: Determines the start of the new selection after the text has been inserted (or replaced). `selectionStart` is measured in UTF-16 code units and must be in the range 0 and length of the completion text. If omitted the selection starts at the end of the completion text. + * sort_text: A string that should be used when comparing this item with other items. If not returned or an empty string, the `label` is used instead. + * start: Start position (within the `text` attribute of the `completions` request) where the completion text is added. The position is measured in UTF-16 code units and the client capability `columnsStartAt1` determines whether it is 0- or 1-based. If the start position is omitted the text is added at the location specified by the `column` attribute of the `completions` request. + * text: If text is returned and not an empty string, then it is inserted instead of the label. + * type: The item's type. Typically the client uses this information to render the item in the UI with an icon. + """ + + typedstruct do + @typedoc "A type defining DAP structure CompletionItem" + field(:detail, String.t()) + field(:label, String.t(), enforce: true) + field(:length, integer()) + field(:selection_length, integer()) + field(:selection_start, integer()) + field(:sort_text, String.t()) + field(:start, integer()) + field(:text, String.t()) + field(:type, GenDAP.Enumerations.CompletionItemType.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"detail", :detail}) => str(), + {"label", :label} => str(), + optional({"length", :length}) => int(), + optional({"selectionLength", :selection_length}) => int(), + optional({"selectionStart", :selection_start}) => int(), + optional({"sortText", :sort_text}) => str(), + optional({"start", :start}) => int(), + optional({"text", :text}) => str(), + optional({"type", :type}) => GenDAP.Enumerations.CompletionItemType.schematic() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/completions_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/completions_arguments.ex new file mode 100644 index 000000000..d62a8f9bf --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/completions_arguments.ex @@ -0,0 +1,39 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.CompletionsArguments do + @moduledoc """ + Arguments for `completions` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * column: The position within `text` for which to determine the completion proposals. It is measured in UTF-16 code units and the client capability `columnsStartAt1` determines whether it is 0- or 1-based. + * frame_id: Returns completions in the scope of this stack frame. If not specified, the completions are returned for the global scope. + * line: A line for which to determine the completion proposals. If missing the first line of the text is assumed. + * text: One or more source lines. Typically this is the text users have typed into the debug console before they asked for completion. + """ + + typedstruct do + @typedoc "A type defining DAP structure CompletionsArguments" + field(:column, integer(), enforce: true) + field(:frame_id, integer()) + field(:line, integer()) + field(:text, String.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"column", :column} => int(), + optional({"frameId", :frame_id}) => int(), + optional({"line", :line}) => int(), + {"text", :text} => str() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/configuration_done_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/configuration_done_arguments.ex new file mode 100644 index 000000000..73cbe7c82 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/configuration_done_arguments.ex @@ -0,0 +1,26 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.ConfigurationDoneArguments do + @moduledoc """ + Arguments for `configurationDone` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + """ + + typedstruct do + @typedoc "A type defining DAP structure ConfigurationDoneArguments" + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{}) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/continue_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/continue_arguments.ex new file mode 100644 index 000000000..96e39077a --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/continue_arguments.ex @@ -0,0 +1,33 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.ContinueArguments do + @moduledoc """ + Arguments for `continue` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * single_thread: If this flag is true, execution is resumed only for the thread with given `threadId`. + * thread_id: Specifies the active thread. If the debug adapter supports single thread execution (see `supportsSingleThreadExecutionRequests`) and the argument `singleThread` is true, only the thread with this ID is resumed. + """ + + typedstruct do + @typedoc "A type defining DAP structure ContinueArguments" + field(:single_thread, boolean()) + field(:thread_id, integer(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"singleThread", :single_thread}) => bool(), + {"threadId", :thread_id} => int() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/data_breakpoint.ex b/apps/debug_adapter/lib/protocol/dap/structures/data_breakpoint.ex new file mode 100644 index 000000000..f5c7f4dd7 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/data_breakpoint.ex @@ -0,0 +1,41 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.DataBreakpoint do + @moduledoc """ + Properties of a data breakpoint passed to the `setDataBreakpoints` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * access_type: The access type of the data. + * condition: An expression for conditional breakpoints. + * data_id: An id representing the data. This id is returned from the `dataBreakpointInfo` request. + * hit_condition: An expression that controls how many hits of the breakpoint are ignored. + The debug adapter is expected to interpret the expression as needed. + """ + + typedstruct do + @typedoc "A type defining DAP structure DataBreakpoint" + field(:access_type, GenDAP.Enumerations.DataBreakpointAccessType.t()) + field(:condition, String.t()) + field(:data_id, String.t(), enforce: true) + field(:hit_condition, String.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"accessType", :access_type}) => + GenDAP.Enumerations.DataBreakpointAccessType.schematic(), + optional({"condition", :condition}) => str(), + {"dataId", :data_id} => str(), + optional({"hitCondition", :hit_condition}) => str() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/data_breakpoint_info_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/data_breakpoint_info_arguments.ex new file mode 100644 index 000000000..5a2f1212f --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/data_breakpoint_info_arguments.ex @@ -0,0 +1,51 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.DataBreakpointInfoArguments do + @moduledoc """ + Arguments for `dataBreakpointInfo` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * as_address: If `true`, the `name` is a memory address and the debugger should interpret it as a decimal value, or hex value if it is prefixed with `0x`. + + Clients may set this property only if the `supportsDataBreakpointBytes` + capability is true. + * bytes: If specified, a debug adapter should return information for the range of memory extending `bytes` number of bytes from the address or variable specified by `name`. Breakpoints set using the resulting data ID should pause on data access anywhere within that range. + + Clients may set this property only if the `supportsDataBreakpointBytes` capability is true. + * frame_id: When `name` is an expression, evaluate it in the scope of this stack frame. If not specified, the expression is evaluated in the global scope. When `variablesReference` is specified, this property has no effect. + * mode: The mode of the desired breakpoint. If defined, this must be one of the `breakpointModes` the debug adapter advertised in its `Capabilities`. + * name: The name of the variable's child to obtain data breakpoint information for. + If `variablesReference` isn't specified, this can be an expression, or an address if `asAddress` is also true. + * variables_reference: Reference to the variable container if the data breakpoint is requested for a child of the container. The `variablesReference` must have been obtained in the current suspended state. See 'Lifetime of Object References' in the Overview section for details. + """ + + typedstruct do + @typedoc "A type defining DAP structure DataBreakpointInfoArguments" + field(:as_address, boolean()) + field(:bytes, integer()) + field(:frame_id, integer()) + field(:mode, String.t()) + field(:name, String.t(), enforce: true) + field(:variables_reference, integer()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"asAddress", :as_address}) => bool(), + optional({"bytes", :bytes}) => int(), + optional({"frameId", :frame_id}) => int(), + optional({"mode", :mode}) => str(), + {"name", :name} => str(), + optional({"variablesReference", :variables_reference}) => int() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/disassemble_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/disassemble_arguments.ex new file mode 100644 index 000000000..ecddf1d25 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/disassemble_arguments.ex @@ -0,0 +1,43 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.DisassembleArguments do + @moduledoc """ + Arguments for `disassemble` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * instruction_count: Number of instructions to disassemble starting at the specified location and offset. + An adapter must return exactly this number of instructions - any unavailable instructions should be replaced with an implementation-defined 'invalid instruction' value. + * instruction_offset: Offset (in instructions) to be applied after the byte offset (if any) before disassembling. Can be negative. + * memory_reference: Memory reference to the base location containing the instructions to disassemble. + * offset: Offset (in bytes) to be applied to the reference location before disassembling. Can be negative. + * resolve_symbols: If true, the adapter should attempt to resolve memory addresses and other values to symbolic names. + """ + + typedstruct do + @typedoc "A type defining DAP structure DisassembleArguments" + field(:instruction_count, integer(), enforce: true) + field(:instruction_offset, integer()) + field(:memory_reference, String.t(), enforce: true) + field(:offset, integer()) + field(:resolve_symbols, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"instructionCount", :instruction_count} => int(), + optional({"instructionOffset", :instruction_offset}) => int(), + {"memoryReference", :memory_reference} => str(), + optional({"offset", :offset}) => int(), + optional({"resolveSymbols", :resolve_symbols}) => bool() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/disassembled_instruction.ex b/apps/debug_adapter/lib/protocol/dap/structures/disassembled_instruction.ex new file mode 100644 index 000000000..cb444a270 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/disassembled_instruction.ex @@ -0,0 +1,61 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.DisassembledInstruction do + @moduledoc """ + Represents a single disassembled instruction. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * address: The address of the instruction. Treated as a hex value if prefixed with `0x`, or as a decimal value otherwise. + * column: The column within the line that corresponds to this instruction, if any. + * end_column: The end column of the range that corresponds to this instruction, if any. + * end_line: The end line of the range that corresponds to this instruction, if any. + * instruction: Text representing the instruction and its operands, in an implementation-defined format. + * instruction_bytes: Raw bytes representing the instruction and its operands, in an implementation-defined format. + * line: The line within the source location that corresponds to this instruction, if any. + * location: Source location that corresponds to this instruction, if any. + Should always be set (if available) on the first instruction returned, + but can be omitted afterwards if this instruction maps to the same source file as the previous instruction. + * presentation_hint: A hint for how to present the instruction in the UI. + + A value of `invalid` may be used to indicate this instruction is 'filler' and cannot be reached by the program. For example, unreadable memory addresses may be presented is 'invalid.' + * symbol: Name of the symbol that corresponds with the location of this instruction, if any. + """ + + typedstruct do + @typedoc "A type defining DAP structure DisassembledInstruction" + field(:address, String.t(), enforce: true) + field(:column, integer()) + field(:end_column, integer()) + field(:end_line, integer()) + field(:instruction, String.t(), enforce: true) + field(:instruction_bytes, String.t()) + field(:line, integer()) + field(:location, GenDAP.Structures.Source.t()) + field(:presentation_hint, String.t()) + field(:symbol, String.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"address", :address} => str(), + optional({"column", :column}) => int(), + optional({"endColumn", :end_column}) => int(), + optional({"endLine", :end_line}) => int(), + {"instruction", :instruction} => str(), + optional({"instructionBytes", :instruction_bytes}) => str(), + optional({"line", :line}) => int(), + optional({"location", :location}) => GenDAP.Structures.Source.schematic(), + optional({"presentationHint", :presentation_hint}) => oneof(["normal", "invalid"]), + optional({"symbol", :symbol}) => str() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/disconnect_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/disconnect_arguments.ex new file mode 100644 index 000000000..db956a0f1 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/disconnect_arguments.ex @@ -0,0 +1,40 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.DisconnectArguments do + @moduledoc """ + Arguments for `disconnect` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * restart: A value of true indicates that this `disconnect` request is part of a restart sequence. + * suspend_debuggee: Indicates whether the debuggee should stay suspended when the debugger is disconnected. + If unspecified, the debuggee should resume execution. + The attribute is only honored by a debug adapter if the corresponding capability `supportSuspendDebuggee` is true. + * terminate_debuggee: Indicates whether the debuggee should be terminated when the debugger is disconnected. + If unspecified, the debug adapter is free to do whatever it thinks is best. + The attribute is only honored by a debug adapter if the corresponding capability `supportTerminateDebuggee` is true. + """ + + typedstruct do + @typedoc "A type defining DAP structure DisconnectArguments" + field(:restart, boolean()) + field(:suspend_debuggee, boolean()) + field(:terminate_debuggee, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"restart", :restart}) => bool(), + optional({"suspendDebuggee", :suspend_debuggee}) => bool(), + optional({"terminateDebuggee", :terminate_debuggee}) => bool() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/error_response.ex b/apps/debug_adapter/lib/protocol/dap/structures/error_response.ex new file mode 100644 index 000000000..c4c7ec34e --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/error_response.ex @@ -0,0 +1,55 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.ErrorResponse do + @moduledoc """ + On error (whenever `success` is false), the body can provide more details. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * body: Contains request result if success is true and error details if success is false. + * command: The command requested. + * message: Contains the raw error in short form if `success` is false. + This raw error might be interpreted by the client and is not shown in the UI. + Some predefined values exist. + * request_seq: Sequence number of the corresponding request. + * seq: Sequence number of the message (also known as message ID). The `seq` for the first message sent by a client or debug adapter is 1, and for each subsequent message is 1 greater than the previous message sent by that actor. `seq` can be used to order requests, responses, and events, and to associate requests with their corresponding responses. For protocol messages of type `request` the sequence number can be used to cancel the request. + * success: Outcome of the request. + If true, the request was successful and the `body` attribute may contain the result of the request. + If the value is false, the attribute `message` contains the error in short form and the `body` may contain additional information (see `ErrorResponse.body.error`). + * type: Message type. + """ + + typedstruct do + @typedoc "A type defining DAP structure ErrorResponse" + field(:body, %{optional(:error) => GenDAP.Structures.Message.t()}, enforce: true) + field(:command, String.t(), enforce: true) + field(:message, String.t()) + field(:request_seq, integer(), enforce: true) + field(:seq, integer(), enforce: true) + field(:success, boolean(), enforce: true) + field(:type, String.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"body", :body} => + map(%{ + optional({"error", :error}) => GenDAP.Structures.Message.schematic() + }), + {"command", :command} => str(), + optional({"message", :message}) => oneof(["cancelled", "notStopped", str()]), + {"request_seq", :request_seq} => int(), + {"seq", :seq} => int(), + {"success", :success} => bool(), + {"type", :type} => oneof(["request", "response", "event", str()]) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/evaluate_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/evaluate_arguments.ex new file mode 100644 index 000000000..0d02cce9a --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/evaluate_arguments.ex @@ -0,0 +1,52 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.EvaluateArguments do + @moduledoc """ + Arguments for `evaluate` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * column: The contextual column where the expression should be evaluated. This may be provided if `line` is also provided. + + It is measured in UTF-16 code units and the client capability `columnsStartAt1` determines whether it is 0- or 1-based. + * context: The context in which the evaluate request is used. + * expression: The expression to evaluate. + * format: Specifies details on how to format the result. + The attribute is only honored by a debug adapter if the corresponding capability `supportsValueFormattingOptions` is true. + * frame_id: Evaluate the expression in the scope of this stack frame. If not specified, the expression is evaluated in the global scope. + * line: The contextual line where the expression should be evaluated. In the 'hover' context, this should be set to the start of the expression being hovered. + * source: The contextual source in which the `line` is found. This must be provided if `line` is provided. + """ + + typedstruct do + @typedoc "A type defining DAP structure EvaluateArguments" + field(:column, integer()) + field(:context, String.t()) + field(:expression, String.t(), enforce: true) + field(:format, GenDAP.Structures.ValueFormat.t()) + field(:frame_id, integer()) + field(:line, integer()) + field(:source, GenDAP.Structures.Source.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"column", :column}) => int(), + optional({"context", :context}) => + oneof(["watch", "repl", "hover", "clipboard", "variables", str()]), + {"expression", :expression} => str(), + optional({"format", :format}) => GenDAP.Structures.ValueFormat.schematic(), + optional({"frameId", :frame_id}) => int(), + optional({"line", :line}) => int(), + optional({"source", :source}) => GenDAP.Structures.Source.schematic() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/exception_breakpoints_filter.ex b/apps/debug_adapter/lib/protocol/dap/structures/exception_breakpoints_filter.ex new file mode 100644 index 000000000..21c46426b --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/exception_breakpoints_filter.ex @@ -0,0 +1,45 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.ExceptionBreakpointsFilter do + @moduledoc """ + An `ExceptionBreakpointsFilter` is shown in the UI as an filter option for configuring how exceptions are dealt with. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * condition_description: A help text providing information about the condition. This string is shown as the placeholder text for a text box and can be translated. + * default: Initial value of the filter option. If not specified a value false is assumed. + * description: A help text providing additional information about the exception filter. This string is typically shown as a hover and can be translated. + * filter: The internal ID of the filter option. This value is passed to the `setExceptionBreakpoints` request. + * label: The name of the filter option. This is shown in the UI. + * supports_condition: Controls whether a condition can be specified for this filter option. If false or missing, a condition can not be set. + """ + + typedstruct do + @typedoc "A type defining DAP structure ExceptionBreakpointsFilter" + field(:condition_description, String.t()) + field(:default, boolean()) + field(:description, String.t()) + field(:filter, String.t(), enforce: true) + field(:label, String.t(), enforce: true) + field(:supports_condition, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"conditionDescription", :condition_description}) => str(), + optional({"default", :default}) => bool(), + optional({"description", :description}) => str(), + {"filter", :filter} => str(), + {"label", :label} => str(), + optional({"supportsCondition", :supports_condition}) => bool() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/exception_details.ex b/apps/debug_adapter/lib/protocol/dap/structures/exception_details.ex new file mode 100644 index 000000000..e98958a97 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/exception_details.ex @@ -0,0 +1,45 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.ExceptionDetails do + @moduledoc """ + Detailed information about an exception that has occurred. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * evaluate_name: An expression that can be evaluated in the current scope to obtain the exception object. + * full_type_name: Fully-qualified type name of the exception object. + * inner_exception: Details of the exception contained by this exception, if any. + * message: Message contained in the exception. + * stack_trace: Stack trace at the time the exception was thrown. + * type_name: Short type name of the exception object. + """ + + typedstruct do + @typedoc "A type defining DAP structure ExceptionDetails" + field(:evaluate_name, String.t()) + field(:full_type_name, String.t()) + field(:inner_exception, list(GenDAP.Structures.ExceptionDetails.t())) + field(:message, String.t()) + field(:stack_trace, String.t()) + field(:type_name, String.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"evaluateName", :evaluate_name}) => str(), + optional({"fullTypeName", :full_type_name}) => str(), + optional({"innerException", :inner_exception}) => list({__MODULE__, :schematic, []}), + optional({"message", :message}) => str(), + optional({"stackTrace", :stack_trace}) => str(), + optional({"typeName", :type_name}) => str() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/exception_filter_options.ex b/apps/debug_adapter/lib/protocol/dap/structures/exception_filter_options.ex new file mode 100644 index 000000000..91497d45d --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/exception_filter_options.ex @@ -0,0 +1,37 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.ExceptionFilterOptions do + @moduledoc """ + An `ExceptionFilterOptions` is used to specify an exception filter together with a condition for the `setExceptionBreakpoints` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * condition: An expression for conditional exceptions. + The exception breaks into the debugger if the result of the condition is true. + * filter_id: ID of an exception filter returned by the `exceptionBreakpointFilters` capability. + * mode: The mode of this exception breakpoint. If defined, this must be one of the `breakpointModes` the debug adapter advertised in its `Capabilities`. + """ + + typedstruct do + @typedoc "A type defining DAP structure ExceptionFilterOptions" + field(:condition, String.t()) + field(:filter_id, String.t(), enforce: true) + field(:mode, String.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"condition", :condition}) => str(), + {"filterId", :filter_id} => str(), + optional({"mode", :mode}) => str() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/exception_info_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/exception_info_arguments.ex new file mode 100644 index 000000000..c2a7d020c --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/exception_info_arguments.ex @@ -0,0 +1,30 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.ExceptionInfoArguments do + @moduledoc """ + Arguments for `exceptionInfo` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * thread_id: Thread for which exception information should be retrieved. + """ + + typedstruct do + @typedoc "A type defining DAP structure ExceptionInfoArguments" + field(:thread_id, integer(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"threadId", :thread_id} => int() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/exception_options.ex b/apps/debug_adapter/lib/protocol/dap/structures/exception_options.ex new file mode 100644 index 000000000..e7f359640 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/exception_options.ex @@ -0,0 +1,34 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.ExceptionOptions do + @moduledoc """ + An `ExceptionOptions` assigns configuration options to a set of exceptions. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * break_mode: Condition when a thrown exception should result in a break. + * path: A path that selects a single or multiple exceptions in a tree. If `path` is missing, the whole tree is selected. + By convention the first segment of the path is a category that is used to group exceptions in the UI. + """ + + typedstruct do + @typedoc "A type defining DAP structure ExceptionOptions" + field(:break_mode, GenDAP.Enumerations.ExceptionBreakMode.t(), enforce: true) + field(:path, list(GenDAP.Structures.ExceptionPathSegment.t())) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"breakMode", :break_mode} => GenDAP.Enumerations.ExceptionBreakMode.schematic(), + optional({"path", :path}) => list(GenDAP.Structures.ExceptionPathSegment.schematic()) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/exception_path_segment.ex b/apps/debug_adapter/lib/protocol/dap/structures/exception_path_segment.ex new file mode 100644 index 000000000..4664163b4 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/exception_path_segment.ex @@ -0,0 +1,34 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.ExceptionPathSegment do + @moduledoc """ + An `ExceptionPathSegment` represents a segment in a path that is used to match leafs or nodes in a tree of exceptions. + If a segment consists of more than one name, it matches the names provided if `negate` is false or missing, or it matches anything except the names provided if `negate` is true. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * names: Depending on the value of `negate` the names that should match or not match. + * negate: If false or missing this segment matches the names provided, otherwise it matches anything except the names provided. + """ + + typedstruct do + @typedoc "A type defining DAP structure ExceptionPathSegment" + field(:names, list(String.t()), enforce: true) + field(:negate, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"names", :names} => list(str()), + optional({"negate", :negate}) => bool() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/function_breakpoint.ex b/apps/debug_adapter/lib/protocol/dap/structures/function_breakpoint.ex new file mode 100644 index 000000000..8b91fa7be --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/function_breakpoint.ex @@ -0,0 +1,39 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.FunctionBreakpoint do + @moduledoc """ + Properties of a breakpoint passed to the `setFunctionBreakpoints` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * condition: An expression for conditional breakpoints. + It is only honored by a debug adapter if the corresponding capability `supportsConditionalBreakpoints` is true. + * hit_condition: An expression that controls how many hits of the breakpoint are ignored. + The debug adapter is expected to interpret the expression as needed. + The attribute is only honored by a debug adapter if the corresponding capability `supportsHitConditionalBreakpoints` is true. + * name: The name of the function. + """ + + typedstruct do + @typedoc "A type defining DAP structure FunctionBreakpoint" + field(:condition, String.t()) + field(:hit_condition, String.t()) + field(:name, String.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"condition", :condition}) => str(), + optional({"hitCondition", :hit_condition}) => str(), + {"name", :name} => str() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/goto_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/goto_arguments.ex new file mode 100644 index 000000000..d998837fb --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/goto_arguments.ex @@ -0,0 +1,33 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.GotoArguments do + @moduledoc """ + Arguments for `goto` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * target_id: The location where the debuggee will continue to run. + * thread_id: Set the goto target for this thread. + """ + + typedstruct do + @typedoc "A type defining DAP structure GotoArguments" + field(:target_id, integer(), enforce: true) + field(:thread_id, integer(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"targetId", :target_id} => int(), + {"threadId", :thread_id} => int() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/goto_target.ex b/apps/debug_adapter/lib/protocol/dap/structures/goto_target.ex new file mode 100644 index 000000000..0a99b8984 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/goto_target.ex @@ -0,0 +1,49 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.GotoTarget do + @moduledoc """ + A `GotoTarget` describes a code location that can be used as a target in the `goto` request. + The possible goto targets can be determined via the `gotoTargets` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * column: The column of the goto target. + * end_column: The end column of the range covered by the goto target. + * end_line: The end line of the range covered by the goto target. + * id: Unique identifier for a goto target. This is used in the `goto` request. + * instruction_pointer_reference: A memory reference for the instruction pointer value represented by this target. + * label: The name of the goto target (shown in the UI). + * line: The line of the goto target. + """ + + typedstruct do + @typedoc "A type defining DAP structure GotoTarget" + field(:column, integer()) + field(:end_column, integer()) + field(:end_line, integer()) + field(:id, integer(), enforce: true) + field(:instruction_pointer_reference, String.t()) + field(:label, String.t(), enforce: true) + field(:line, integer(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"column", :column}) => int(), + optional({"endColumn", :end_column}) => int(), + optional({"endLine", :end_line}) => int(), + {"id", :id} => int(), + optional({"instructionPointerReference", :instruction_pointer_reference}) => str(), + {"label", :label} => str(), + {"line", :line} => int() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/goto_targets_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/goto_targets_arguments.ex new file mode 100644 index 000000000..55e7a39d3 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/goto_targets_arguments.ex @@ -0,0 +1,36 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.GotoTargetsArguments do + @moduledoc """ + Arguments for `gotoTargets` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * column: The position within `line` for which the goto targets are determined. It is measured in UTF-16 code units and the client capability `columnsStartAt1` determines whether it is 0- or 1-based. + * line: The line location for which the goto targets are determined. + * source: The source location for which the goto targets are determined. + """ + + typedstruct do + @typedoc "A type defining DAP structure GotoTargetsArguments" + field(:column, integer()) + field(:line, integer(), enforce: true) + field(:source, GenDAP.Structures.Source.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"column", :column}) => int(), + {"line", :line} => int(), + {"source", :source} => GenDAP.Structures.Source.schematic() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/initialize_request_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/initialize_request_arguments.ex new file mode 100644 index 000000000..baf32ed8e --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/initialize_request_arguments.ex @@ -0,0 +1,80 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.InitializeRequestArguments do + @moduledoc """ + Arguments for `initialize` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * adapter_i_d: The ID of the debug adapter. + * client_i_d: The ID of the client using this adapter. + * client_name: The human-readable name of the client using this adapter. + * columns_start_at1: If true all column numbers are 1-based (default). + * lines_start_at1: If true all line numbers are 1-based (default). + * locale: The ISO-639 locale of the client using this adapter, e.g. en-US or de-CH. + * path_format: Determines in what format paths are specified. The default is `path`, which is the native format. + * supports_a_n_s_i_styling: The client will interpret ANSI escape sequences in the display of `OutputEvent.output` and `Variable.value` fields when `Capabilities.supportsANSIStyling` is also enabled. + * supports_args_can_be_interpreted_by_shell: Client supports the `argsCanBeInterpretedByShell` attribute on the `runInTerminal` request. + * supports_invalidated_event: Client supports the `invalidated` event. + * supports_memory_event: Client supports the `memory` event. + * supports_memory_references: Client supports memory references. + * supports_progress_reporting: Client supports progress reporting. + * supports_run_in_terminal_request: Client supports the `runInTerminal` request. + * supports_start_debugging_request: Client supports the `startDebugging` request. + * supports_variable_paging: Client supports the paging of variables. + * supports_variable_type: Client supports the `type` attribute for variables. + """ + + typedstruct do + @typedoc "A type defining DAP structure InitializeRequestArguments" + field(:adapter_i_d, String.t(), enforce: true) + field(:client_i_d, String.t()) + field(:client_name, String.t()) + field(:columns_start_at1, boolean()) + field(:lines_start_at1, boolean()) + field(:locale, String.t()) + field(:path_format, String.t()) + field(:supports_a_n_s_i_styling, boolean()) + field(:supports_args_can_be_interpreted_by_shell, boolean()) + field(:supports_invalidated_event, boolean()) + field(:supports_memory_event, boolean()) + field(:supports_memory_references, boolean()) + field(:supports_progress_reporting, boolean()) + field(:supports_run_in_terminal_request, boolean()) + field(:supports_start_debugging_request, boolean()) + field(:supports_variable_paging, boolean()) + field(:supports_variable_type, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"adapterID", :adapter_i_d} => str(), + optional({"clientID", :client_i_d}) => str(), + optional({"clientName", :client_name}) => str(), + optional({"columnsStartAt1", :columns_start_at1}) => bool(), + optional({"linesStartAt1", :lines_start_at1}) => bool(), + optional({"locale", :locale}) => str(), + optional({"pathFormat", :path_format}) => oneof(["path", "uri", str()]), + optional({"supportsANSIStyling", :supports_a_n_s_i_styling}) => bool(), + optional( + {"supportsArgsCanBeInterpretedByShell", :supports_args_can_be_interpreted_by_shell} + ) => bool(), + optional({"supportsInvalidatedEvent", :supports_invalidated_event}) => bool(), + optional({"supportsMemoryEvent", :supports_memory_event}) => bool(), + optional({"supportsMemoryReferences", :supports_memory_references}) => bool(), + optional({"supportsProgressReporting", :supports_progress_reporting}) => bool(), + optional({"supportsRunInTerminalRequest", :supports_run_in_terminal_request}) => bool(), + optional({"supportsStartDebuggingRequest", :supports_start_debugging_request}) => bool(), + optional({"supportsVariablePaging", :supports_variable_paging}) => bool(), + optional({"supportsVariableType", :supports_variable_type}) => bool() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/instruction_breakpoint.ex b/apps/debug_adapter/lib/protocol/dap/structures/instruction_breakpoint.ex new file mode 100644 index 000000000..b171283e2 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/instruction_breakpoint.ex @@ -0,0 +1,47 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.InstructionBreakpoint do + @moduledoc """ + Properties of a breakpoint passed to the `setInstructionBreakpoints` request + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * condition: An expression for conditional breakpoints. + It is only honored by a debug adapter if the corresponding capability `supportsConditionalBreakpoints` is true. + * hit_condition: An expression that controls how many hits of the breakpoint are ignored. + The debug adapter is expected to interpret the expression as needed. + The attribute is only honored by a debug adapter if the corresponding capability `supportsHitConditionalBreakpoints` is true. + * instruction_reference: The instruction reference of the breakpoint. + This should be a memory or instruction pointer reference from an `EvaluateResponse`, `Variable`, `StackFrame`, `GotoTarget`, or `Breakpoint`. + * mode: The mode of this breakpoint. If defined, this must be one of the `breakpointModes` the debug adapter advertised in its `Capabilities`. + * offset: The offset from the instruction reference in bytes. + This can be negative. + """ + + typedstruct do + @typedoc "A type defining DAP structure InstructionBreakpoint" + field(:condition, String.t()) + field(:hit_condition, String.t()) + field(:instruction_reference, String.t(), enforce: true) + field(:mode, String.t()) + field(:offset, integer()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"condition", :condition}) => str(), + optional({"hitCondition", :hit_condition}) => str(), + {"instructionReference", :instruction_reference} => str(), + optional({"mode", :mode}) => str(), + optional({"offset", :offset}) => int() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/launch_request_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/launch_request_arguments.ex new file mode 100644 index 000000000..7a811879b --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/launch_request_arguments.ex @@ -0,0 +1,30 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.LaunchRequestArguments do + @moduledoc """ + Arguments for `launch` request. Additional attributes are implementation specific. + """ + + import SchematicV, warn: false + + @typedoc "A type defining DAP structure LaunchRequestArguments" + @type t() :: %{ + optional(:__restart) => + list() | boolean() | integer() | nil | number() | map() | String.t(), + optional(:no_debug) => boolean(), + optional(String.t()) => any() + } + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + all([ + map(%{ + optional({"__restart", :__restart}) => + oneof([list(), bool(), int(), nil, oneof([int(), float()]), map(), str()]), + optional({"noDebug", :no_debug}) => bool() + }), + map() + ]) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/loaded_sources_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/loaded_sources_arguments.ex new file mode 100644 index 000000000..c8eebcfac --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/loaded_sources_arguments.ex @@ -0,0 +1,26 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.LoadedSourcesArguments do + @moduledoc """ + Arguments for `loadedSources` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + """ + + typedstruct do + @typedoc "A type defining DAP structure LoadedSourcesArguments" + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{}) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/locations_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/locations_arguments.ex new file mode 100644 index 000000000..060cbc869 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/locations_arguments.ex @@ -0,0 +1,30 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.LocationsArguments do + @moduledoc """ + Arguments for `locations` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * location_reference: Location reference to resolve. + """ + + typedstruct do + @typedoc "A type defining DAP structure LocationsArguments" + field(:location_reference, integer(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"locationReference", :location_reference} => int() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/message.ex b/apps/debug_adapter/lib/protocol/dap/structures/message.ex new file mode 100644 index 000000000..d00ad51af --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/message.ex @@ -0,0 +1,49 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.Message do + @moduledoc """ + A structured message object. Used to return errors from requests. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * format: A format string for the message. Embedded variables have the form `{name}`. + If variable name starts with an underscore character, the variable does not contain user data (PII) and can be safely used for telemetry purposes. + * id: Unique (within a debug adapter implementation) identifier for the message. The purpose of these error IDs is to help extension authors that have the requirement that every user visible error message needs a corresponding error number, so that users or customer support can find information about the specific error more easily. + * send_telemetry: If true send to telemetry. + * show_user: If true show user. + * url: A url where additional information about this message can be found. + * url_label: A label that is presented to the user as the UI for opening the url. + * variables: An object used as a dictionary for looking up the variables in the format string. + """ + + typedstruct do + @typedoc "A type defining DAP structure Message" + field(:format, String.t(), enforce: true) + field(:id, integer(), enforce: true) + field(:send_telemetry, boolean()) + field(:show_user, boolean()) + field(:url, String.t()) + field(:url_label, String.t()) + field(:variables, %{optional(String.t()) => String.t()}) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"format", :format} => str(), + {"id", :id} => int(), + optional({"sendTelemetry", :send_telemetry}) => bool(), + optional({"showUser", :show_user}) => bool(), + optional({"url", :url}) => str(), + optional({"urlLabel", :url_label}) => str(), + optional({"variables", :variables}) => map(keys: str(), values: str()) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/module.ex b/apps/debug_adapter/lib/protocol/dap/structures/module.ex new file mode 100644 index 000000000..a7b9dd148 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/module.ex @@ -0,0 +1,63 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.Module do + @moduledoc """ + A Module object represents a row in the modules view. + The `id` attribute identifies a module in the modules view and is used in a `module` event for identifying a module for adding, updating or deleting. + The `name` attribute is used to minimally render the module in the UI. + + Additional attributes can be added to the module. They show up in the module view if they have a corresponding `ColumnDescriptor`. + + To avoid an unnecessary proliferation of additional attributes with similar semantics but different names, we recommend to re-use attributes from the 'recommended' list below first, and only introduce new attributes if nothing appropriate could be found. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * address_range: Address range covered by this module. + * date_time_stamp: Module created or modified, encoded as a RFC 3339 timestamp. + * id: Unique identifier for the module. + * is_optimized: True if the module is optimized. + * is_user_code: True if the module is considered 'user code' by a debugger that supports 'Just My Code'. + * name: A name of the module. + * path: Logical full path to the module. The exact definition is implementation defined, but usually this would be a full path to the on-disk file for the module. + * symbol_file_path: Logical full path to the symbol file. The exact definition is implementation defined. + * symbol_status: User-understandable description of if symbols were found for the module (ex: 'Symbols Loaded', 'Symbols not found', etc.) + * version: Version of Module. + """ + + typedstruct do + @typedoc "A type defining DAP structure Module" + field(:address_range, String.t()) + field(:date_time_stamp, String.t()) + field(:id, integer() | String.t(), enforce: true) + field(:is_optimized, boolean()) + field(:is_user_code, boolean()) + field(:name, String.t(), enforce: true) + field(:path, String.t()) + field(:symbol_file_path, String.t()) + field(:symbol_status, String.t()) + field(:version, String.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"addressRange", :address_range}) => str(), + optional({"dateTimeStamp", :date_time_stamp}) => str(), + {"id", :id} => oneof([int(), str()]), + optional({"isOptimized", :is_optimized}) => bool(), + optional({"isUserCode", :is_user_code}) => bool(), + {"name", :name} => str(), + optional({"path", :path}) => str(), + optional({"symbolFilePath", :symbol_file_path}) => str(), + optional({"symbolStatus", :symbol_status}) => str(), + optional({"version", :version}) => str() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/modules_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/modules_arguments.ex new file mode 100644 index 000000000..0d5a79b85 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/modules_arguments.ex @@ -0,0 +1,33 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.ModulesArguments do + @moduledoc """ + Arguments for `modules` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * module_count: The number of modules to return. If `moduleCount` is not specified or 0, all modules are returned. + * start_module: The index of the first module to return; if omitted modules start at 0. + """ + + typedstruct do + @typedoc "A type defining DAP structure ModulesArguments" + field(:module_count, integer()) + field(:start_module, integer()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"moduleCount", :module_count}) => int(), + optional({"startModule", :start_module}) => int() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/next_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/next_arguments.ex new file mode 100644 index 000000000..205e88b80 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/next_arguments.ex @@ -0,0 +1,37 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.NextArguments do + @moduledoc """ + Arguments for `next` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * granularity: Stepping granularity. If no granularity is specified, a granularity of `statement` is assumed. + * single_thread: If this flag is true, all other suspended threads are not resumed. + * thread_id: Specifies the thread for which to resume execution for one step (of the given granularity). + """ + + typedstruct do + @typedoc "A type defining DAP structure NextArguments" + field(:granularity, GenDAP.Enumerations.SteppingGranularity.t()) + field(:single_thread, boolean()) + field(:thread_id, integer(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"granularity", :granularity}) => + GenDAP.Enumerations.SteppingGranularity.schematic(), + optional({"singleThread", :single_thread}) => bool(), + {"threadId", :thread_id} => int() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/pause_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/pause_arguments.ex new file mode 100644 index 000000000..4e7d9ec84 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/pause_arguments.ex @@ -0,0 +1,30 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.PauseArguments do + @moduledoc """ + Arguments for `pause` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * thread_id: Pause execution for this thread. + """ + + typedstruct do + @typedoc "A type defining DAP structure PauseArguments" + field(:thread_id, integer(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"threadId", :thread_id} => int() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/read_memory_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/read_memory_arguments.ex new file mode 100644 index 000000000..30144c606 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/read_memory_arguments.ex @@ -0,0 +1,36 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.ReadMemoryArguments do + @moduledoc """ + Arguments for `readMemory` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * count: Number of bytes to read at the specified location and offset. + * memory_reference: Memory reference to the base location from which data should be read. + * offset: Offset (in bytes) to be applied to the reference location before reading data. Can be negative. + """ + + typedstruct do + @typedoc "A type defining DAP structure ReadMemoryArguments" + field(:count, integer(), enforce: true) + field(:memory_reference, String.t(), enforce: true) + field(:offset, integer()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"count", :count} => int(), + {"memoryReference", :memory_reference} => str(), + optional({"offset", :offset}) => int() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/restart_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/restart_arguments.ex new file mode 100644 index 000000000..6912c270d --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/restart_arguments.ex @@ -0,0 +1,37 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.RestartArguments do + @moduledoc """ + Arguments for `restart` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * arguments: The latest version of the `launch` or `attach` configuration. + """ + + typedstruct do + @typedoc "A type defining DAP structure RestartArguments" + field( + :arguments, + GenDAP.Structures.LaunchRequestArguments.t() | GenDAP.Structures.AttachRequestArguments.t() + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"arguments", :arguments}) => + oneof([ + GenDAP.Structures.LaunchRequestArguments.schematic(), + GenDAP.Structures.AttachRequestArguments.schematic() + ]) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/restart_frame_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/restart_frame_arguments.ex new file mode 100644 index 000000000..2f59dfa4f --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/restart_frame_arguments.ex @@ -0,0 +1,30 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.RestartFrameArguments do + @moduledoc """ + Arguments for `restartFrame` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * frame_id: Restart the stack frame identified by `frameId`. The `frameId` must have been obtained in the current suspended state. See 'Lifetime of Object References' in the Overview section for details. + """ + + typedstruct do + @typedoc "A type defining DAP structure RestartFrameArguments" + field(:frame_id, integer(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"frameId", :frame_id} => int() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/reverse_continue_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/reverse_continue_arguments.ex new file mode 100644 index 000000000..c2dbc4fee --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/reverse_continue_arguments.ex @@ -0,0 +1,33 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.ReverseContinueArguments do + @moduledoc """ + Arguments for `reverseContinue` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * single_thread: If this flag is true, backward execution is resumed only for the thread with given `threadId`. + * thread_id: Specifies the active thread. If the debug adapter supports single thread execution (see `supportsSingleThreadExecutionRequests`) and the `singleThread` argument is true, only the thread with this ID is resumed. + """ + + typedstruct do + @typedoc "A type defining DAP structure ReverseContinueArguments" + field(:single_thread, boolean()) + field(:thread_id, integer(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"singleThread", :single_thread}) => bool(), + {"threadId", :thread_id} => int() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/run_in_terminal_request_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/run_in_terminal_request_arguments.ex new file mode 100644 index 000000000..e0494d1a1 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/run_in_terminal_request_arguments.ex @@ -0,0 +1,45 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.RunInTerminalRequestArguments do + @moduledoc """ + Arguments for `runInTerminal` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * args: List of arguments. The first argument is the command to run. + * args_can_be_interpreted_by_shell: This property should only be set if the corresponding capability `supportsArgsCanBeInterpretedByShell` is true. If the client uses an intermediary shell to launch the application, then the client must not attempt to escape characters with special meanings for the shell. The user is fully responsible for escaping as needed and that arguments using special characters may not be portable across shells. + * cwd: Working directory for the command. For non-empty, valid paths this typically results in execution of a change directory command. + * env: Environment key-value pairs that are added to or removed from the default environment. + * kind: What kind of terminal to launch. Defaults to `integrated` if not specified. + * title: Title of the terminal. + """ + + typedstruct do + @typedoc "A type defining DAP structure RunInTerminalRequestArguments" + field(:args, list(String.t()), enforce: true) + field(:args_can_be_interpreted_by_shell, boolean()) + field(:cwd, String.t(), enforce: true) + field(:env, %{optional(String.t()) => String.t() | nil}) + field(:kind, String.t()) + field(:title, String.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"args", :args} => list(str()), + optional({"argsCanBeInterpretedByShell", :args_can_be_interpreted_by_shell}) => bool(), + {"cwd", :cwd} => str(), + optional({"env", :env}) => map(keys: str(), values: oneof([str(), nil])), + optional({"kind", :kind}) => oneof(["integrated", "external"]), + optional({"title", :title}) => str() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/scope.ex b/apps/debug_adapter/lib/protocol/dap/structures/scope.ex new file mode 100644 index 000000000..4b6eae91a --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/scope.ex @@ -0,0 +1,63 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.Scope do + @moduledoc """ + A `Scope` is a named container for variables. Optionally a scope can map to a source or a range within a source. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * column: Start position of the range covered by the scope. It is measured in UTF-16 code units and the client capability `columnsStartAt1` determines whether it is 0- or 1-based. + * end_column: End position of the range covered by the scope. It is measured in UTF-16 code units and the client capability `columnsStartAt1` determines whether it is 0- or 1-based. + * end_line: The end line of the range covered by this scope. + * expensive: If true, the number of variables in this scope is large or expensive to retrieve. + * indexed_variables: The number of indexed variables in this scope. + The client can use this information to present the variables in a paged UI and fetch them in chunks. + * line: The start line of the range covered by this scope. + * name: Name of the scope such as 'Arguments', 'Locals', or 'Registers'. This string is shown in the UI as is and can be translated. + * named_variables: The number of named variables in this scope. + The client can use this information to present the variables in a paged UI and fetch them in chunks. + * presentation_hint: A hint for how to present this scope in the UI. If this attribute is missing, the scope is shown with a generic UI. + * source: The source for this scope. + * variables_reference: The variables of this scope can be retrieved by passing the value of `variablesReference` to the `variables` request as long as execution remains suspended. See 'Lifetime of Object References' in the Overview section for details. + """ + + typedstruct do + @typedoc "A type defining DAP structure Scope" + field(:column, integer()) + field(:end_column, integer()) + field(:end_line, integer()) + field(:expensive, boolean(), enforce: true) + field(:indexed_variables, integer()) + field(:line, integer()) + field(:name, String.t(), enforce: true) + field(:named_variables, integer()) + field(:presentation_hint, String.t()) + field(:source, GenDAP.Structures.Source.t()) + field(:variables_reference, integer(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"column", :column}) => int(), + optional({"endColumn", :end_column}) => int(), + optional({"endLine", :end_line}) => int(), + {"expensive", :expensive} => bool(), + optional({"indexedVariables", :indexed_variables}) => int(), + optional({"line", :line}) => int(), + {"name", :name} => str(), + optional({"namedVariables", :named_variables}) => int(), + optional({"presentationHint", :presentation_hint}) => + oneof(["arguments", "locals", "registers", "returnValue", str()]), + optional({"source", :source}) => GenDAP.Structures.Source.schematic(), + {"variablesReference", :variables_reference} => int() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/scopes_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/scopes_arguments.ex new file mode 100644 index 000000000..1b93dff2f --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/scopes_arguments.ex @@ -0,0 +1,30 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.ScopesArguments do + @moduledoc """ + Arguments for `scopes` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * frame_id: Retrieve the scopes for the stack frame identified by `frameId`. The `frameId` must have been obtained in the current suspended state. See 'Lifetime of Object References' in the Overview section for details. + """ + + typedstruct do + @typedoc "A type defining DAP structure ScopesArguments" + field(:frame_id, integer(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"frameId", :frame_id} => int() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/set_breakpoints_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/set_breakpoints_arguments.ex new file mode 100644 index 000000000..b956917b0 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/set_breakpoints_arguments.ex @@ -0,0 +1,40 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.SetBreakpointsArguments do + @moduledoc """ + Arguments for `setBreakpoints` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * breakpoints: The code locations of the breakpoints. + * lines: Deprecated: The code locations of the breakpoints. + * source: The source location of the breakpoints; either `source.path` or `source.sourceReference` must be specified. + * source_modified: A value of true indicates that the underlying source has been modified which results in new breakpoint locations. + """ + + typedstruct do + @typedoc "A type defining DAP structure SetBreakpointsArguments" + field(:breakpoints, list(GenDAP.Structures.SourceBreakpoint.t())) + field(:lines, list(integer())) + field(:source, GenDAP.Structures.Source.t(), enforce: true) + field(:source_modified, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"breakpoints", :breakpoints}) => + list(GenDAP.Structures.SourceBreakpoint.schematic()), + optional({"lines", :lines}) => list(int()), + {"source", :source} => GenDAP.Structures.Source.schematic(), + optional({"sourceModified", :source_modified}) => bool() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/set_data_breakpoints_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/set_data_breakpoints_arguments.ex new file mode 100644 index 000000000..e9fc2daf2 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/set_data_breakpoints_arguments.ex @@ -0,0 +1,30 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.SetDataBreakpointsArguments do + @moduledoc """ + Arguments for `setDataBreakpoints` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * breakpoints: The contents of this array replaces all existing data breakpoints. An empty array clears all data breakpoints. + """ + + typedstruct do + @typedoc "A type defining DAP structure SetDataBreakpointsArguments" + field(:breakpoints, list(GenDAP.Structures.DataBreakpoint.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"breakpoints", :breakpoints} => list(GenDAP.Structures.DataBreakpoint.schematic()) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/set_exception_breakpoints_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/set_exception_breakpoints_arguments.ex new file mode 100644 index 000000000..fdafd223a --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/set_exception_breakpoints_arguments.ex @@ -0,0 +1,39 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.SetExceptionBreakpointsArguments do + @moduledoc """ + Arguments for `setExceptionBreakpoints` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * exception_options: Configuration options for selected exceptions. + The attribute is only honored by a debug adapter if the corresponding capability `supportsExceptionOptions` is true. + * filter_options: Set of exception filters and their options. The set of all possible exception filters is defined by the `exceptionBreakpointFilters` capability. This attribute is only honored by a debug adapter if the corresponding capability `supportsExceptionFilterOptions` is true. The `filter` and `filterOptions` sets are additive. + * filters: Set of exception filters specified by their ID. The set of all possible exception filters is defined by the `exceptionBreakpointFilters` capability. The `filter` and `filterOptions` sets are additive. + """ + + typedstruct do + @typedoc "A type defining DAP structure SetExceptionBreakpointsArguments" + field(:exception_options, list(GenDAP.Structures.ExceptionOptions.t())) + field(:filter_options, list(GenDAP.Structures.ExceptionFilterOptions.t())) + field(:filters, list(String.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"exceptionOptions", :exception_options}) => + list(GenDAP.Structures.ExceptionOptions.schematic()), + optional({"filterOptions", :filter_options}) => + list(GenDAP.Structures.ExceptionFilterOptions.schematic()), + {"filters", :filters} => list(str()) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/set_expression_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/set_expression_arguments.ex new file mode 100644 index 000000000..fc2eaf2dc --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/set_expression_arguments.ex @@ -0,0 +1,39 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.SetExpressionArguments do + @moduledoc """ + Arguments for `setExpression` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * expression: The l-value expression to assign to. + * format: Specifies how the resulting value should be formatted. + * frame_id: Evaluate the expressions in the scope of this stack frame. If not specified, the expressions are evaluated in the global scope. + * value: The value expression to assign to the l-value expression. + """ + + typedstruct do + @typedoc "A type defining DAP structure SetExpressionArguments" + field(:expression, String.t(), enforce: true) + field(:format, GenDAP.Structures.ValueFormat.t()) + field(:frame_id, integer()) + field(:value, String.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"expression", :expression} => str(), + optional({"format", :format}) => GenDAP.Structures.ValueFormat.schematic(), + optional({"frameId", :frame_id}) => int(), + {"value", :value} => str() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/set_function_breakpoints_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/set_function_breakpoints_arguments.ex new file mode 100644 index 000000000..fca84f49d --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/set_function_breakpoints_arguments.ex @@ -0,0 +1,30 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.SetFunctionBreakpointsArguments do + @moduledoc """ + Arguments for `setFunctionBreakpoints` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * breakpoints: The function names of the breakpoints. + """ + + typedstruct do + @typedoc "A type defining DAP structure SetFunctionBreakpointsArguments" + field(:breakpoints, list(GenDAP.Structures.FunctionBreakpoint.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"breakpoints", :breakpoints} => list(GenDAP.Structures.FunctionBreakpoint.schematic()) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/set_instruction_breakpoints_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/set_instruction_breakpoints_arguments.ex new file mode 100644 index 000000000..d98fa311c --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/set_instruction_breakpoints_arguments.ex @@ -0,0 +1,30 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.SetInstructionBreakpointsArguments do + @moduledoc """ + Arguments for `setInstructionBreakpoints` request + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * breakpoints: The instruction references of the breakpoints + """ + + typedstruct do + @typedoc "A type defining DAP structure SetInstructionBreakpointsArguments" + field(:breakpoints, list(GenDAP.Structures.InstructionBreakpoint.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"breakpoints", :breakpoints} => list(GenDAP.Structures.InstructionBreakpoint.schematic()) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/set_variable_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/set_variable_arguments.ex new file mode 100644 index 000000000..6f0b54303 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/set_variable_arguments.ex @@ -0,0 +1,39 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.SetVariableArguments do + @moduledoc """ + Arguments for `setVariable` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * format: Specifies details on how to format the response value. + * name: The name of the variable in the container. + * value: The value of the variable. + * variables_reference: The reference of the variable container. The `variablesReference` must have been obtained in the current suspended state. See 'Lifetime of Object References' in the Overview section for details. + """ + + typedstruct do + @typedoc "A type defining DAP structure SetVariableArguments" + field(:format, GenDAP.Structures.ValueFormat.t()) + field(:name, String.t(), enforce: true) + field(:value, String.t(), enforce: true) + field(:variables_reference, integer(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"format", :format}) => GenDAP.Structures.ValueFormat.schematic(), + {"name", :name} => str(), + {"value", :value} => str(), + {"variablesReference", :variables_reference} => int() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/source.ex b/apps/debug_adapter/lib/protocol/dap/structures/source.ex new file mode 100644 index 000000000..0fe248577 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/source.ex @@ -0,0 +1,60 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.Source do + @moduledoc """ + A `Source` is a descriptor for source code. + It is returned from the debug adapter as part of a `StackFrame` and it is used by clients when specifying breakpoints. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * adapter_data: Additional data that a debug adapter might want to loop through the client. + The client should leave the data intact and persist it across sessions. The client should not interpret the data. + * checksums: The checksums associated with this file. + * name: The short name of the source. Every source returned from the debug adapter has a name. + When sending a source to the debug adapter this name is optional. + * origin: The origin of this source. For example, 'internal module', 'inlined content from source map', etc. + * path: The path of the source to be shown in the UI. + It is only used to locate and load the content of the source if no `sourceReference` is specified (or its value is 0). + * presentation_hint: A hint for how to present the source in the UI. + A value of `deemphasize` can be used to indicate that the source is not available or that it is skipped on stepping. + * source_reference: If the value > 0 the contents of the source must be retrieved through the `source` request (even if a path is specified). + Since a `sourceReference` is only valid for a session, it can not be used to persist a source. + The value should be less than or equal to 2147483647 (2^31-1). + * sources: A list of sources that are related to this source. These may be the source that generated this source. + """ + + typedstruct do + @typedoc "A type defining DAP structure Source" + field(:adapter_data, list() | boolean() | integer() | nil | number() | map() | String.t()) + field(:checksums, list(GenDAP.Structures.Checksum.t())) + field(:name, String.t()) + field(:origin, String.t()) + field(:path, String.t()) + field(:presentation_hint, String.t()) + field(:source_reference, integer()) + field(:sources, list(GenDAP.Structures.Source.t())) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"adapterData", :adapter_data}) => + oneof([list(), bool(), int(), nil, oneof([int(), float()]), map(), str()]), + optional({"checksums", :checksums}) => list(GenDAP.Structures.Checksum.schematic()), + optional({"name", :name}) => str(), + optional({"origin", :origin}) => str(), + optional({"path", :path}) => str(), + optional({"presentationHint", :presentation_hint}) => + oneof(["normal", "emphasize", "deemphasize"]), + optional({"sourceReference", :source_reference}) => int(), + optional({"sources", :sources}) => list({__MODULE__, :schematic, []}) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/source_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/source_arguments.ex new file mode 100644 index 000000000..bfdfbaf2f --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/source_arguments.ex @@ -0,0 +1,34 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.SourceArguments do + @moduledoc """ + Arguments for `source` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * source: Specifies the source content to load. Either `source.path` or `source.sourceReference` must be specified. + * source_reference: The reference to the source. This is the same as `source.sourceReference`. + This is provided for backward compatibility since old clients do not understand the `source` attribute. + """ + + typedstruct do + @typedoc "A type defining DAP structure SourceArguments" + field(:source, GenDAP.Structures.Source.t()) + field(:source_reference, integer(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"source", :source}) => GenDAP.Structures.Source.schematic(), + {"sourceReference", :source_reference} => int() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/source_breakpoint.ex b/apps/debug_adapter/lib/protocol/dap/structures/source_breakpoint.ex new file mode 100644 index 000000000..19951cb37 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/source_breakpoint.ex @@ -0,0 +1,52 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.SourceBreakpoint do + @moduledoc """ + Properties of a breakpoint or logpoint passed to the `setBreakpoints` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * column: Start position within source line of the breakpoint or logpoint. It is measured in UTF-16 code units and the client capability `columnsStartAt1` determines whether it is 0- or 1-based. + * condition: The expression for conditional breakpoints. + It is only honored by a debug adapter if the corresponding capability `supportsConditionalBreakpoints` is true. + * hit_condition: The expression that controls how many hits of the breakpoint are ignored. + The debug adapter is expected to interpret the expression as needed. + The attribute is only honored by a debug adapter if the corresponding capability `supportsHitConditionalBreakpoints` is true. + If both this property and `condition` are specified, `hitCondition` should be evaluated only if the `condition` is met, and the debug adapter should stop only if both conditions are met. + * line: The source line of the breakpoint or logpoint. + * log_message: If this attribute exists and is non-empty, the debug adapter must not 'break' (stop) + but log the message instead. Expressions within `{}` are interpolated. + The attribute is only honored by a debug adapter if the corresponding capability `supportsLogPoints` is true. + If either `hitCondition` or `condition` is specified, then the message should only be logged if those conditions are met. + * mode: The mode of this breakpoint. If defined, this must be one of the `breakpointModes` the debug adapter advertised in its `Capabilities`. + """ + + typedstruct do + @typedoc "A type defining DAP structure SourceBreakpoint" + field(:column, integer()) + field(:condition, String.t()) + field(:hit_condition, String.t()) + field(:line, integer(), enforce: true) + field(:log_message, String.t()) + field(:mode, String.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"column", :column}) => int(), + optional({"condition", :condition}) => str(), + optional({"hitCondition", :hit_condition}) => str(), + {"line", :line} => int(), + optional({"logMessage", :log_message}) => str(), + optional({"mode", :mode}) => str() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/stack_frame.ex b/apps/debug_adapter/lib/protocol/dap/structures/stack_frame.ex new file mode 100644 index 000000000..0f6b31f02 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/stack_frame.ex @@ -0,0 +1,62 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.StackFrame do + @moduledoc """ + A Stackframe contains the source location. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * can_restart: Indicates whether this frame can be restarted with the `restartFrame` request. Clients should only use this if the debug adapter supports the `restart` request and the corresponding capability `supportsRestartFrame` is true. If a debug adapter has this capability, then `canRestart` defaults to `true` if the property is absent. + * column: Start position of the range covered by the stack frame. It is measured in UTF-16 code units and the client capability `columnsStartAt1` determines whether it is 0- or 1-based. If attribute `source` is missing or doesn't exist, `column` is 0 and should be ignored by the client. + * end_column: End position of the range covered by the stack frame. It is measured in UTF-16 code units and the client capability `columnsStartAt1` determines whether it is 0- or 1-based. + * end_line: The end line of the range covered by the stack frame. + * id: An identifier for the stack frame. It must be unique across all threads. + This id can be used to retrieve the scopes of the frame with the `scopes` request or to restart the execution of a stack frame. + * instruction_pointer_reference: A memory reference for the current instruction pointer in this frame. + * line: The line within the source of the frame. If the source attribute is missing or doesn't exist, `line` is 0 and should be ignored by the client. + * module_id: The module associated with this frame, if any. + * name: The name of the stack frame, typically a method name. + * presentation_hint: A hint for how to present this frame in the UI. + A value of `label` can be used to indicate that the frame is an artificial frame that is used as a visual label or separator. A value of `subtle` can be used to change the appearance of a frame in a 'subtle' way. + * source: The source of the frame. + """ + + typedstruct do + @typedoc "A type defining DAP structure StackFrame" + field(:can_restart, boolean()) + field(:column, integer(), enforce: true) + field(:end_column, integer()) + field(:end_line, integer()) + field(:id, integer(), enforce: true) + field(:instruction_pointer_reference, String.t()) + field(:line, integer(), enforce: true) + field(:module_id, integer() | String.t()) + field(:name, String.t(), enforce: true) + field(:presentation_hint, String.t()) + field(:source, GenDAP.Structures.Source.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"canRestart", :can_restart}) => bool(), + {"column", :column} => int(), + optional({"endColumn", :end_column}) => int(), + optional({"endLine", :end_line}) => int(), + {"id", :id} => int(), + optional({"instructionPointerReference", :instruction_pointer_reference}) => str(), + {"line", :line} => int(), + optional({"moduleId", :module_id}) => oneof([int(), str()]), + {"name", :name} => str(), + optional({"presentationHint", :presentation_hint}) => oneof(["normal", "label", "subtle"]), + optional({"source", :source}) => GenDAP.Structures.Source.schematic() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/stack_frame_format.ex b/apps/debug_adapter/lib/protocol/dap/structures/stack_frame_format.ex new file mode 100644 index 000000000..b0e732b78 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/stack_frame_format.ex @@ -0,0 +1,51 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.StackFrameFormat do + @moduledoc """ + Provides formatting information for a stack frame. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * hex: Display the value in hex. + * include_all: Includes all stack frames, including those the debug adapter might otherwise hide. + * line: Displays the line number of the stack frame. + * module: Displays the module of the stack frame. + * parameter_names: Displays the names of parameters for the stack frame. + * parameter_types: Displays the types of parameters for the stack frame. + * parameter_values: Displays the values of parameters for the stack frame. + * parameters: Displays parameters for the stack frame. + """ + + typedstruct do + @typedoc "A type defining DAP structure StackFrameFormat" + field(:hex, boolean()) + field(:include_all, boolean()) + field(:line, boolean()) + field(:module, boolean()) + field(:parameter_names, boolean()) + field(:parameter_types, boolean()) + field(:parameter_values, boolean()) + field(:parameters, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"hex", :hex}) => bool(), + optional({"includeAll", :include_all}) => bool(), + optional({"line", :line}) => bool(), + optional({"module", :module}) => bool(), + optional({"parameterNames", :parameter_names}) => bool(), + optional({"parameterTypes", :parameter_types}) => bool(), + optional({"parameterValues", :parameter_values}) => bool(), + optional({"parameters", :parameters}) => bool() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/stack_trace_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/stack_trace_arguments.ex new file mode 100644 index 000000000..d5697dda0 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/stack_trace_arguments.ex @@ -0,0 +1,40 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.StackTraceArguments do + @moduledoc """ + Arguments for `stackTrace` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * format: Specifies details on how to format the returned `StackFrame.name`. The debug adapter may format requested details in any way that would make sense to a developer. + The attribute is only honored by a debug adapter if the corresponding capability `supportsValueFormattingOptions` is true. + * levels: The maximum number of frames to return. If levels is not specified or 0, all frames are returned. + * start_frame: The index of the first frame to return; if omitted frames start at 0. + * thread_id: Retrieve the stacktrace for this thread. + """ + + typedstruct do + @typedoc "A type defining DAP structure StackTraceArguments" + field(:format, GenDAP.Structures.StackFrameFormat.t()) + field(:levels, integer()) + field(:start_frame, integer()) + field(:thread_id, integer(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"format", :format}) => GenDAP.Structures.StackFrameFormat.schematic(), + optional({"levels", :levels}) => int(), + optional({"startFrame", :start_frame}) => int(), + {"threadId", :thread_id} => int() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/start_debugging_request_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/start_debugging_request_arguments.ex new file mode 100644 index 000000000..7b575838a --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/start_debugging_request_arguments.ex @@ -0,0 +1,33 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.StartDebuggingRequestArguments do + @moduledoc """ + Arguments for `startDebugging` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * configuration: Arguments passed to the new debug session. The arguments must only contain properties understood by the `launch` or `attach` requests of the debug adapter and they must not contain any client-specific properties (e.g. `type`) or client-specific features (e.g. substitutable 'variables'). + * request: Indicates whether the new debug session should be started with a `launch` or `attach` request. + """ + + typedstruct do + @typedoc "A type defining DAP structure StartDebuggingRequestArguments" + field(:configuration, %{optional(String.t()) => any()}, enforce: true) + field(:request, String.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"configuration", :configuration} => map(keys: str(), values: any()), + {"request", :request} => oneof(["launch", "attach"]) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/step_back_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/step_back_arguments.ex new file mode 100644 index 000000000..86eed3c5f --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/step_back_arguments.ex @@ -0,0 +1,37 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.StepBackArguments do + @moduledoc """ + Arguments for `stepBack` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * granularity: Stepping granularity to step. If no granularity is specified, a granularity of `statement` is assumed. + * single_thread: If this flag is true, all other suspended threads are not resumed. + * thread_id: Specifies the thread for which to resume execution for one step backwards (of the given granularity). + """ + + typedstruct do + @typedoc "A type defining DAP structure StepBackArguments" + field(:granularity, GenDAP.Enumerations.SteppingGranularity.t()) + field(:single_thread, boolean()) + field(:thread_id, integer(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"granularity", :granularity}) => + GenDAP.Enumerations.SteppingGranularity.schematic(), + optional({"singleThread", :single_thread}) => bool(), + {"threadId", :thread_id} => int() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/step_in_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/step_in_arguments.ex new file mode 100644 index 000000000..fade9ecd5 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/step_in_arguments.ex @@ -0,0 +1,40 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.StepInArguments do + @moduledoc """ + Arguments for `stepIn` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * granularity: Stepping granularity. If no granularity is specified, a granularity of `statement` is assumed. + * single_thread: If this flag is true, all other suspended threads are not resumed. + * target_id: Id of the target to step into. + * thread_id: Specifies the thread for which to resume execution for one step-into (of the given granularity). + """ + + typedstruct do + @typedoc "A type defining DAP structure StepInArguments" + field(:granularity, GenDAP.Enumerations.SteppingGranularity.t()) + field(:single_thread, boolean()) + field(:target_id, integer()) + field(:thread_id, integer(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"granularity", :granularity}) => + GenDAP.Enumerations.SteppingGranularity.schematic(), + optional({"singleThread", :single_thread}) => bool(), + optional({"targetId", :target_id}) => int(), + {"threadId", :thread_id} => int() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/step_in_target.ex b/apps/debug_adapter/lib/protocol/dap/structures/step_in_target.ex new file mode 100644 index 000000000..1d3256e18 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/step_in_target.ex @@ -0,0 +1,45 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.StepInTarget do + @moduledoc """ + A `StepInTarget` can be used in the `stepIn` request and determines into which single target the `stepIn` request should step. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * column: Start position of the range covered by the step in target. It is measured in UTF-16 code units and the client capability `columnsStartAt1` determines whether it is 0- or 1-based. + * end_column: End position of the range covered by the step in target. It is measured in UTF-16 code units and the client capability `columnsStartAt1` determines whether it is 0- or 1-based. + * end_line: The end line of the range covered by the step-in target. + * id: Unique identifier for a step-in target. + * label: The name of the step-in target (shown in the UI). + * line: The line of the step-in target. + """ + + typedstruct do + @typedoc "A type defining DAP structure StepInTarget" + field(:column, integer()) + field(:end_column, integer()) + field(:end_line, integer()) + field(:id, integer(), enforce: true) + field(:label, String.t(), enforce: true) + field(:line, integer()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"column", :column}) => int(), + optional({"endColumn", :end_column}) => int(), + optional({"endLine", :end_line}) => int(), + {"id", :id} => int(), + {"label", :label} => str(), + optional({"line", :line}) => int() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/step_in_targets_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/step_in_targets_arguments.ex new file mode 100644 index 000000000..a3a8cc06c --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/step_in_targets_arguments.ex @@ -0,0 +1,30 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.StepInTargetsArguments do + @moduledoc """ + Arguments for `stepInTargets` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * frame_id: The stack frame for which to retrieve the possible step-in targets. + """ + + typedstruct do + @typedoc "A type defining DAP structure StepInTargetsArguments" + field(:frame_id, integer(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"frameId", :frame_id} => int() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/step_out_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/step_out_arguments.ex new file mode 100644 index 000000000..f1e7e7dd9 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/step_out_arguments.ex @@ -0,0 +1,37 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.StepOutArguments do + @moduledoc """ + Arguments for `stepOut` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * granularity: Stepping granularity. If no granularity is specified, a granularity of `statement` is assumed. + * single_thread: If this flag is true, all other suspended threads are not resumed. + * thread_id: Specifies the thread for which to resume execution for one step-out (of the given granularity). + """ + + typedstruct do + @typedoc "A type defining DAP structure StepOutArguments" + field(:granularity, GenDAP.Enumerations.SteppingGranularity.t()) + field(:single_thread, boolean()) + field(:thread_id, integer(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"granularity", :granularity}) => + GenDAP.Enumerations.SteppingGranularity.schematic(), + optional({"singleThread", :single_thread}) => bool(), + {"threadId", :thread_id} => int() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/terminate_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/terminate_arguments.ex new file mode 100644 index 000000000..34ee7d5f1 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/terminate_arguments.ex @@ -0,0 +1,30 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.TerminateArguments do + @moduledoc """ + Arguments for `terminate` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * restart: A value of true indicates that this `terminate` request is part of a restart sequence. + """ + + typedstruct do + @typedoc "A type defining DAP structure TerminateArguments" + field(:restart, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"restart", :restart}) => bool() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/terminate_threads_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/terminate_threads_arguments.ex new file mode 100644 index 000000000..31893b987 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/terminate_threads_arguments.ex @@ -0,0 +1,30 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.TerminateThreadsArguments do + @moduledoc """ + Arguments for `terminateThreads` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * thread_ids: Ids of threads to be terminated. + """ + + typedstruct do + @typedoc "A type defining DAP structure TerminateThreadsArguments" + field(:thread_ids, list(integer())) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"threadIds", :thread_ids}) => list(int()) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/thread.ex b/apps/debug_adapter/lib/protocol/dap/structures/thread.ex new file mode 100644 index 000000000..53b971444 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/thread.ex @@ -0,0 +1,33 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.Thread do + @moduledoc """ + A Thread + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * id: Unique identifier for the thread. + * name: The name of the thread. + """ + + typedstruct do + @typedoc "A type defining DAP structure Thread" + field(:id, integer(), enforce: true) + field(:name, String.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"id", :id} => int(), + {"name", :name} => str() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/value_format.ex b/apps/debug_adapter/lib/protocol/dap/structures/value_format.ex new file mode 100644 index 000000000..07157de5f --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/value_format.ex @@ -0,0 +1,30 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.ValueFormat do + @moduledoc """ + Provides formatting information for a value. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * hex: Display the value in hex. + """ + + typedstruct do + @typedoc "A type defining DAP structure ValueFormat" + field(:hex, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"hex", :hex}) => bool() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/variable.ex b/apps/debug_adapter/lib/protocol/dap/structures/variable.ex new file mode 100644 index 000000000..92693e623 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/variable.ex @@ -0,0 +1,79 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.Variable do + @moduledoc """ + A Variable is a name/value pair. + The `type` attribute is shown if space permits or when hovering over the variable's name. + The `kind` attribute is used to render additional properties of the variable, e.g. different icons can be used to indicate that a variable is public or private. + If the value is structured (has children), a handle is provided to retrieve the children with the `variables` request. + If the number of named or indexed children is large, the numbers should be returned via the `namedVariables` and `indexedVariables` attributes. + The client can use this information to present the children in a paged UI and fetch them in chunks. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * declaration_location_reference: A reference that allows the client to request the location where the variable is declared. This should be present only if the adapter is likely to be able to resolve the location. + + This reference shares the same lifetime as the `variablesReference`. See 'Lifetime of Object References' in the Overview section for details. + * evaluate_name: The evaluatable name of this variable which can be passed to the `evaluate` request to fetch the variable's value. + * indexed_variables: The number of indexed child variables. + The client can use this information to present the children in a paged UI and fetch them in chunks. + * memory_reference: A memory reference associated with this variable. + For pointer type variables, this is generally a reference to the memory address contained in the pointer. + For executable data, this reference may later be used in a `disassemble` request. + This attribute may be returned by a debug adapter if corresponding capability `supportsMemoryReferences` is true. + * name: The variable's name. + * named_variables: The number of named child variables. + The client can use this information to present the children in a paged UI and fetch them in chunks. + * presentation_hint: Properties of a variable that can be used to determine how to render the variable in the UI. + * type: The type of the variable's value. Typically shown in the UI when hovering over the value. + This attribute should only be returned by a debug adapter if the corresponding capability `supportsVariableType` is true. + * value: The variable's value. + This can be a multi-line text, e.g. for a function the body of a function. + For structured variables (which do not have a simple value), it is recommended to provide a one-line representation of the structured object. This helps to identify the structured object in the collapsed state when its children are not yet visible. + An empty string can be used if no value should be shown in the UI. + * value_location_reference: A reference that allows the client to request the location where the variable's value is declared. For example, if the variable contains a function pointer, the adapter may be able to look up the function's location. This should be present only if the adapter is likely to be able to resolve the location. + + This reference shares the same lifetime as the `variablesReference`. See 'Lifetime of Object References' in the Overview section for details. + * variables_reference: If `variablesReference` is > 0, the variable is structured and its children can be retrieved by passing `variablesReference` to the `variables` request as long as execution remains suspended. See 'Lifetime of Object References' in the Overview section for details. + """ + + typedstruct do + @typedoc "A type defining DAP structure Variable" + field(:declaration_location_reference, integer()) + field(:evaluate_name, String.t()) + field(:indexed_variables, integer()) + field(:memory_reference, String.t()) + field(:name, String.t(), enforce: true) + field(:named_variables, integer()) + field(:presentation_hint, GenDAP.Structures.VariablePresentationHint.t()) + field(:type, String.t()) + field(:value, String.t(), enforce: true) + field(:value_location_reference, integer()) + field(:variables_reference, integer(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"declarationLocationReference", :declaration_location_reference}) => int(), + optional({"evaluateName", :evaluate_name}) => str(), + optional({"indexedVariables", :indexed_variables}) => int(), + optional({"memoryReference", :memory_reference}) => str(), + {"name", :name} => str(), + optional({"namedVariables", :named_variables}) => int(), + optional({"presentationHint", :presentation_hint}) => + GenDAP.Structures.VariablePresentationHint.schematic(), + optional({"type", :type}) => str(), + {"value", :value} => str(), + optional({"valueLocationReference", :value_location_reference}) => int(), + {"variablesReference", :variables_reference} => int() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/variable_presentation_hint.ex b/apps/debug_adapter/lib/protocol/dap/structures/variable_presentation_hint.ex new file mode 100644 index 000000000..b3aaeabc8 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/variable_presentation_hint.ex @@ -0,0 +1,69 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.VariablePresentationHint do + @moduledoc """ + Properties of a variable that can be used to determine how to render the variable in the UI. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * attributes: Set of attributes represented as an array of strings. Before introducing additional values, try to use the listed values. + * kind: The kind of variable. Before introducing additional values, try to use the listed values. + * lazy: If true, clients can present the variable with a UI that supports a specific gesture to trigger its evaluation. + This mechanism can be used for properties that require executing code when retrieving their value and where the code execution can be expensive and/or produce side-effects. A typical example are properties based on a getter function. + Please note that in addition to the `lazy` flag, the variable's `variablesReference` is expected to refer to a variable that will provide the value through another `variable` request. + * visibility: Visibility of variable. Before introducing additional values, try to use the listed values. + """ + + typedstruct do + @typedoc "A type defining DAP structure VariablePresentationHint" + field(:attributes, list(String.t())) + field(:kind, String.t()) + field(:lazy, boolean()) + field(:visibility, String.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"attributes", :attributes}) => + list( + oneof([ + "static", + "constant", + "readOnly", + "rawString", + "hasObjectId", + "canHaveObjectId", + "hasSideEffects", + "hasDataBreakpoint", + str() + ]) + ), + optional({"kind", :kind}) => + oneof([ + "property", + "method", + "class", + "data", + "event", + "baseClass", + "innerClass", + "interface", + "mostDerivedClass", + "virtual", + "dataBreakpoint", + str() + ]), + optional({"lazy", :lazy}) => bool(), + optional({"visibility", :visibility}) => + oneof(["public", "private", "protected", "internal", "final", str()]) + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/variables_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/variables_arguments.ex new file mode 100644 index 000000000..f54bca3e0 --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/variables_arguments.ex @@ -0,0 +1,45 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.VariablesArguments do + @moduledoc """ + Arguments for `variables` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * count: The number of variables to return. If count is missing or 0, all variables are returned. + The attribute is only honored by a debug adapter if the corresponding capability `supportsVariablePaging` is true. + * filter: Filter to limit the child variables to either named or indexed. If omitted, both types are fetched. + * format: Specifies details on how to format the Variable values. + The attribute is only honored by a debug adapter if the corresponding capability `supportsValueFormattingOptions` is true. + * start: The index of the first variable to return; if omitted children start at 0. + The attribute is only honored by a debug adapter if the corresponding capability `supportsVariablePaging` is true. + * variables_reference: The variable for which to retrieve its children. The `variablesReference` must have been obtained in the current suspended state. See 'Lifetime of Object References' in the Overview section for details. + """ + + typedstruct do + @typedoc "A type defining DAP structure VariablesArguments" + field(:count, integer()) + field(:filter, String.t()) + field(:format, GenDAP.Structures.ValueFormat.t()) + field(:start, integer()) + field(:variables_reference, integer(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"count", :count}) => int(), + optional({"filter", :filter}) => oneof(["indexed", "named"]), + optional({"format", :format}) => GenDAP.Structures.ValueFormat.schematic(), + optional({"start", :start}) => int(), + {"variablesReference", :variables_reference} => int() + }) + end +end diff --git a/apps/debug_adapter/lib/protocol/dap/structures/write_memory_arguments.ex b/apps/debug_adapter/lib/protocol/dap/structures/write_memory_arguments.ex new file mode 100644 index 000000000..79098abde --- /dev/null +++ b/apps/debug_adapter/lib/protocol/dap/structures/write_memory_arguments.ex @@ -0,0 +1,40 @@ +# codegen: do not edit + +defmodule GenDAP.Structures.WriteMemoryArguments do + @moduledoc """ + Arguments for `writeMemory` request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * allow_partial: Property to control partial writes. If true, the debug adapter should attempt to write memory even if the entire memory region is not writable. In such a case the debug adapter should stop after hitting the first byte of memory that cannot be written and return the number of bytes written in the response via the `offset` and `bytesWritten` properties. + If false or missing, a debug adapter should attempt to verify the region is writable before writing, and fail the response if it is not. + * data: Bytes to write, encoded using base64. + * memory_reference: Memory reference to the base location to which data should be written. + * offset: Offset (in bytes) to be applied to the reference location before writing data. Can be negative. + """ + + typedstruct do + @typedoc "A type defining DAP structure WriteMemoryArguments" + field(:allow_partial, boolean()) + field(:data, String.t(), enforce: true) + field(:memory_reference, String.t(), enforce: true) + field(:offset, integer()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"allowPartial", :allow_partial}) => bool(), + {"data", :data} => str(), + {"memoryReference", :memory_reference} => str(), + optional({"offset", :offset}) => int() + }) + end +end diff --git a/apps/debug_adapter/mix.exs b/apps/debug_adapter/mix.exs index 18e806d1f..7b31b2d3f 100644 --- a/apps/debug_adapter/mix.exs +++ b/apps/debug_adapter/mix.exs @@ -23,6 +23,7 @@ defmodule ElixirLS.DebugAdapter.MixProject do build_embedded: false, start_permanent: true, build_per_environment: false, + elixirc_paths: elixirc_paths(Mix.env()), # if we consolidate here debugged code will not work correctly # and debugged protocol implementation will not be available consolidate_protocols: false, @@ -38,10 +39,16 @@ defmodule ElixirLS.DebugAdapter.MixProject do defp deps do [ {:elixir_sense, github: "elixir-lsp/elixir_sense", ref: @dep_versions[:elixir_sense]}, + {:schematic_v, + github: "elixir-lsp/schematic_vendored", ref: @dep_versions[:schematic_vendored]}, + {:typed_struct, "~> 0.3"}, {:elixir_ls_utils, in_umbrella: true}, {:jason_v, github: "elixir-lsp/jason", ref: @dep_versions[:jason_v]}, {:dialyxir_vendored, github: "elixir-lsp/dialyxir", ref: @dep_versions[:dialyxir_vendored], runtime: false} ] end + + defp elixirc_paths(:test), do: ["lib", "test/support"] + defp elixirc_paths(_), do: ["lib"] end diff --git a/apps/debug_adapter/test/debugger_test.exs b/apps/debug_adapter/test/debugger_test.exs index 89d4852d8..ad12b8efc 100644 --- a/apps/debug_adapter/test/debugger_test.exs +++ b/apps/debug_adapter/test/debugger_test.exs @@ -4,7 +4,15 @@ defmodule ElixirLS.DebugAdapter.ServerTest do # between the debug adapter tests and the fixture project's tests. Expect to see output printed # from both. - alias ElixirLS.DebugAdapter.{Server, Protocol, BreakpointCondition, ModuleInfoCache, Output} + alias ElixirLS.DebugAdapter.{ + Server, + Protocol, + BreakpointCondition, + ModuleInfoCache, + Output, + ThreadRegistry + } + use ElixirLS.Utils.MixTest.Case, async: false use Protocol @@ -40,28 +48,61 @@ defmodule ElixirLS.DebugAdapter.ServerTest do {:ok, %{server: server}} end + defp initialize_req_args() do + %GenDAP.Structures.InitializeRequestArguments{ + client_i_d: "some_client_id", + client_name: "My client", + adapter_i_d: "some_id", + locale: "", + lines_start_at1: true, + columns_start_at1: true, + path_format: "path", + supports_variable_type: false, + supports_variable_paging: false, + supports_run_in_terminal_request: false, + supports_memory_references: false, + supports_progress_reporting: false, + supports_invalidated_event: false, + supports_memory_event: false, + supports_args_can_be_interpreted_by_shell: false, + supports_start_debugging_request: false, + supports_a_n_s_i_styling: false + } + end + + defp initialize_req_(seq, arguments \\ initialize_req_args()) do + {:ok, rex} = + SchematicV.dump( + GenDAP.Requests.InitializeRequest.schematic(), + %GenDAP.Requests.InitializeRequest{seq: seq, arguments: arguments} + ) + + rex + end + describe "initialize" do test "succeeds", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{"clientID" => "some_id"})) + Server.receive_packet(server, initialize_req_(1)) assert_receive( response(_, 1, "initialize", %{"supportsConfigurationDoneRequest" => true}) ) - assert :sys.get_state(server).client_info == %{"clientID" => "some_id"} + assert %GenDAP.Structures.InitializeRequestArguments{client_i_d: "some_client_id"} = + :sys.get_state(server).client_info end) end test "fails when already initialized", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{"clientID" => "some_id"})) + Server.receive_packet(server, initialize_req_(1)) assert_receive( response(_, 1, "initialize", %{"supportsConfigurationDoneRequest" => true}) ) - Server.receive_packet(server, initialize_req(2, %{"clientID" => "some_id"})) + Server.receive_packet(server, initialize_req_(2)) assert_receive( error_response( @@ -82,7 +123,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do in_fixture(__DIR__, "mix_project", fn -> Server.receive_packet( server, - initialize_req(1, %{"clientID" => "some_id", "linesStartAt1" => false}) + initialize_req_(1, %{initialize_req_args() | lines_start_at1: false}) ) assert_receive( @@ -128,7 +169,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do in_fixture(__DIR__, "mix_project", fn -> Process.flag(:trap_exit, true) Server.receive_packet(server, request(1, "disconnect")) - assert_receive(response(_, 1, "disconnect", %{})) + assert_receive(response(_, 1, "disconnect")) assert_receive({:EXIT, ^server, {:exit_code, 0}}) end) after @@ -138,14 +179,14 @@ defmodule ElixirLS.DebugAdapter.ServerTest do test "succeeds when initialized", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> Process.flag(:trap_exit, true) - Server.receive_packet(server, initialize_req(1, %{"clientID" => "some_id"})) + Server.receive_packet(server, initialize_req_(1)) assert_receive( response(_, 1, "initialize", %{"supportsConfigurationDoneRequest" => true}) ) Server.receive_packet(server, request(2, "disconnect")) - assert_receive(response(_, 2, "disconnect", %{})) + assert_receive(response(_, 2, "disconnect")) assert_receive({:EXIT, ^server, {:exit_code, 0}}) end) after @@ -158,9 +199,10 @@ defmodule ElixirLS.DebugAdapter.ServerTest do in_fixture(__DIR__, "mix_project", fn -> Server.receive_packet( server, - initialize_req(1, %{ - "supportsVariablePaging" => true, - "supportsVariableType" => true + initialize_req_(1, %{ + initialize_req_args() + | supports_variable_paging: true, + supports_variable_type: true }) ) @@ -177,8 +219,8 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", %{}), 5000) - assert_receive(event(_, "initialized", %{})) + assert_receive(response(_, 2, "launch"), 5000) + assert_receive(event(_, "initialized", _)) abs_path = Path.absname("lib/mix_project.ex") Server.receive_packet( @@ -192,7 +234,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do ) Server.receive_packet(server, request(5, "configurationDone", %{})) - assert_receive(response(_, 5, "configurationDone", %{})) + assert_receive(response(_, 5, "configurationDone")) Server.receive_packet(server, request(6, "threads", %{})) assert_receive(response(_, 6, "threads", %{"threads" => threads})) @@ -270,10 +312,10 @@ defmodule ElixirLS.DebugAdapter.ServerTest do } ] }), - 1000 + 10000 Server.receive_packet(server, next_req(10, thread_id)) - assert_receive response(_, 10, "next", %{}) + assert_receive response(_, 10, "next") assert_receive event(_, "stopped", %{ "allThreadsStopped" => false, @@ -296,7 +338,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) Server.receive_packet(server, step_in_req(12, thread_id)) - assert_receive response(_, 12, "stepIn", %{}) + assert_receive response(_, 12, "stepIn") assert_receive event(_, "stopped", %{ "allThreadsStopped" => false, @@ -320,7 +362,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) Server.receive_packet(server, step_out_req(14, thread_id)) - assert_receive response(_, 14, "stepOut", %{}) + assert_receive response(_, 14, "stepOut") assert_receive event(_, "stopped", %{ "allThreadsStopped" => false, @@ -360,9 +402,10 @@ defmodule ElixirLS.DebugAdapter.ServerTest do in_fixture(__DIR__, "no_mix_exs", fn -> Server.receive_packet( server, - initialize_req(1, %{ - "supportsVariablePaging" => true, - "supportsVariableType" => true + initialize_req_(1, %{ + initialize_req_args() + | supports_variable_paging: true, + supports_variable_type: true }) ) @@ -383,8 +426,8 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", %{}), 5000) - assert_receive(event(_, "initialized", %{})) + assert_receive(response(_, 2, "launch"), 5000) + assert_receive(event(_, "initialized", _)) abs_path = Path.absname("script.exs") Server.receive_packet( @@ -398,7 +441,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do ) Server.receive_packet(server, request(5, "configurationDone", %{})) - assert_receive(response(_, 5, "configurationDone", %{})) + assert_receive(response(_, 5, "configurationDone")) Server.receive_packet(server, request(6, "threads", %{})) assert_receive(response(_, 6, "threads", %{"threads" => threads})) @@ -481,9 +524,10 @@ defmodule ElixirLS.DebugAdapter.ServerTest do in_fixture(__DIR__, "mix_project", fn -> Server.receive_packet( server, - initialize_req(1, %{ - "supportsVariablePaging" => true, - "supportsVariableType" => true + initialize_req_(1, %{ + initialize_req_args() + | supports_variable_paging: true, + supports_variable_type: true }) ) @@ -501,11 +545,11 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", %{}), 5000) - assert_receive(event(_, "initialized", %{})) + assert_receive(response(_, 2, "launch"), 5000) + assert_receive(event(_, "initialized", _)) Server.receive_packet(server, request(5, "configurationDone", %{})) - assert_receive(response(_, 5, "configurationDone", %{})) + assert_receive(response(_, 5, "configurationDone")) Server.receive_packet(server, request(6, "threads", %{})) assert_receive(response(_, 6, "threads", %{"threads" => threads})) @@ -529,9 +573,10 @@ defmodule ElixirLS.DebugAdapter.ServerTest do in_fixture(__DIR__, "mix_project", fn -> Server.receive_packet( server, - initialize_req(1, %{ - "supportsVariablePaging" => true, - "supportsVariableType" => true + initialize_req_(1, %{ + initialize_req_args() + | supports_variable_paging: true, + supports_variable_type: true }) ) @@ -549,11 +594,11 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", %{}), 5000) - assert_receive(event(_, "initialized", %{})) + assert_receive(response(_, 2, "launch"), 5000) + assert_receive(event(_, "initialized", _)) Server.receive_packet(server, request(5, "configurationDone", %{})) - assert_receive(response(_, 5, "configurationDone", %{})) + assert_receive(response(_, 5, "configurationDone")) assert_receive event(_, "output", %{ "category" => "console", @@ -579,9 +624,10 @@ defmodule ElixirLS.DebugAdapter.ServerTest do in_fixture(__DIR__, "mix_project", fn -> Server.receive_packet( server, - initialize_req(1, %{ - "supportsVariablePaging" => true, - "supportsVariableType" => true + initialize_req_(1, %{ + initialize_req_args() + | supports_variable_paging: true, + supports_variable_type: true }) ) @@ -613,7 +659,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do 5000 ) - refute_receive(event(_, "initialized", %{})) + refute_receive(event(_, "initialized", _)) assert_receive( event(_, "exited", %{ @@ -631,9 +677,10 @@ defmodule ElixirLS.DebugAdapter.ServerTest do in_fixture(__DIR__, "mix_project", fn -> Server.receive_packet( server, - initialize_req(1, %{ - "supportsVariablePaging" => true, - "supportsVariableType" => true + initialize_req_(1, %{ + initialize_req_args() + | supports_variable_paging: true, + supports_variable_type: true }) ) @@ -651,11 +698,11 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", %{}), 5000) - assert_receive(event(_, "initialized", %{})) + assert_receive(response(_, 2, "launch"), 5000) + assert_receive(event(_, "initialized", _)) Server.receive_packet(server, request(5, "configurationDone", %{})) - assert_receive(response(_, 5, "configurationDone", %{})) + assert_receive(response(_, 5, "configurationDone")) assert_receive event(_, "output", %{ "category" => "console", @@ -681,9 +728,10 @@ defmodule ElixirLS.DebugAdapter.ServerTest do in_fixture(__DIR__, "mix_project", fn -> Server.receive_packet( server, - initialize_req(1, %{ - "supportsVariablePaging" => true, - "supportsVariableType" => true + initialize_req_(1, %{ + initialize_req_args() + | supports_variable_paging: true, + supports_variable_type: true }) ) @@ -700,8 +748,8 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", %{}), 5000) - assert_receive(event(_, "initialized", %{})) + assert_receive(response(_, 2, "launch"), 5000) + assert_receive(event(_, "initialized", _)) abs_path = Path.absname("lib/mix_project.ex") Server.receive_packet( @@ -717,7 +765,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do ) Server.receive_packet(server, request(5, "configurationDone", %{})) - assert_receive(response(_, 5, "configurationDone", %{})) + assert_receive(response(_, 5, "configurationDone")) assert_receive event(_, "stopped", %{ "allThreadsStopped" => false, @@ -772,7 +820,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do @tag :fixture test "handles invalid requests", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{})) + Server.receive_packet(server, initialize_req_(1)) assert_receive(response(_, 1, "initialize", %{"supportsConfigurationDoneRequest" => true})) Server.receive_packet( @@ -780,13 +828,14 @@ defmodule ElixirLS.DebugAdapter.ServerTest do launch_req(2, %{ "request" => "launch", "type" => "mix_task", - "task" => "test", + "task" => "run", + "taskArgs" => ["-e", "MixProject.quadruple(1)"], "projectDir" => File.cwd!() }) ) - assert_receive(response(_, 2, "launch", %{}), 5000) - assert_receive(event(_, "initialized", %{})) + assert_receive(response(_, 2, "launch"), 5000) + assert_receive(event(_, "initialized", _)) Server.receive_packet( server, @@ -799,7 +848,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do ) Server.receive_packet(server, request(5, "configurationDone", %{})) - assert_receive(response(_, 5, "configurationDone", %{})) + assert_receive(response(_, 5, "configurationDone")) Server.receive_packet(server, request(6, "threads", %{})) assert_receive(response(_, 6, "threads", %{"threads" => threads})) @@ -814,7 +863,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }), 5_000 - Server.receive_packet(server, stacktrace_req(7, "not existing")) + Server.receive_packet(server, stacktrace_req(7, -6543)) assert_receive error_response( _, @@ -822,12 +871,12 @@ defmodule ElixirLS.DebugAdapter.ServerTest do "stackTrace", "invalidArgument", "Unable to find process pid for DAP threadId {threadId}", - %{"threadId" => "\"not existing\""}, + %{"threadId" => "-6543"}, _, _ ) - Server.receive_packet(server, scopes_req(8, "not existing")) + Server.receive_packet(server, scopes_req(8, -5345)) assert_receive error_response( _, @@ -835,12 +884,12 @@ defmodule ElixirLS.DebugAdapter.ServerTest do "scopes", "invalidArgument", "frameId not found: {frameId}", - %{"frameId" => "\"not existing\""}, + %{"frameId" => "-5345"}, _, _ ) - Server.receive_packet(server, vars_req(9, "not existing")) + Server.receive_packet(server, vars_req(9, -5345)) assert_receive error_response( _, @@ -848,12 +897,12 @@ defmodule ElixirLS.DebugAdapter.ServerTest do "variables", "invalidArgument", "variablesReference not found: {variablesReference}", - %{"variablesReference" => "\"not existing\""}, + %{"variablesReference" => "-5345"}, _, _ ) - Server.receive_packet(server, next_req(10, "not existing")) + Server.receive_packet(server, next_req(10, -5345)) assert_receive error_response( _, @@ -861,12 +910,12 @@ defmodule ElixirLS.DebugAdapter.ServerTest do "next", "invalidArgument", "Unable to find process pid for DAP threadId {threadId}", - %{"threadId" => "\"not existing\""}, + %{"threadId" => "-5345"}, _, _ ) - Server.receive_packet(server, step_in_req(11, "not existing")) + Server.receive_packet(server, step_in_req(11, -5345)) assert_receive error_response( _, @@ -874,12 +923,12 @@ defmodule ElixirLS.DebugAdapter.ServerTest do "stepIn", "invalidArgument", "Unable to find process pid for DAP threadId {threadId}", - %{"threadId" => "\"not existing\""}, + %{"threadId" => "-5345"}, _, _ ) - Server.receive_packet(server, step_out_req(12, "not existing")) + Server.receive_packet(server, step_out_req(12, -5345)) assert_receive error_response( _, @@ -887,12 +936,12 @@ defmodule ElixirLS.DebugAdapter.ServerTest do "stepOut", "invalidArgument", "Unable to find process pid for DAP threadId {threadId}", - %{"threadId" => "\"not existing\""}, + %{"threadId" => "-5345"}, _, _ ) - Server.receive_packet(server, continue_req(13, "not existing")) + Server.receive_packet(server, continue_req(13, -5345)) assert_receive error_response( _, @@ -900,7 +949,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do "continue", "invalidArgument", "Unable to find process pid for DAP threadId {threadId}", - %{"threadId" => "\"not existing\""}, + %{"threadId" => "-5345"}, _, _ ) @@ -940,7 +989,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do @tag :fixture test "notifies about process exit", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{})) + Server.receive_packet(server, initialize_req_(1)) assert_receive(response(_, 1, "initialize", %{"supportsConfigurationDoneRequest" => true})) Server.receive_packet( @@ -954,8 +1003,8 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", %{}), 5000) - assert_receive(event(_, "initialized", %{})) + assert_receive(response(_, 2, "launch"), 5000) + assert_receive(event(_, "initialized", _)) Server.receive_packet( server, @@ -968,7 +1017,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do ) Server.receive_packet(server, request(5, "configurationDone", %{})) - assert_receive(response(_, 5, "configurationDone", %{})) + assert_receive(response(_, 5, "configurationDone")) Server.receive_packet(server, request(6, "threads", %{})) assert_receive(response(_, 6, "threads", %{"threads" => threads}), 1_000) @@ -999,7 +1048,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do @tag :fixture test "notifies about mix task exit", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{})) + Server.receive_packet(server, initialize_req_(1)) assert_receive(response(_, 1, "initialize", %{"supportsConfigurationDoneRequest" => true})) Server.receive_packet( @@ -1013,8 +1062,8 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", %{}), 5000) - assert_receive(event(_, "initialized", %{})) + assert_receive(response(_, 2, "launch"), 5000) + assert_receive(event(_, "initialized", _)) Server.receive_packet( server, @@ -1027,7 +1076,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do ) Server.receive_packet(server, request(5, "configurationDone", %{})) - assert_receive(response(_, 5, "configurationDone", %{})) + assert_receive(response(_, 5, "configurationDone")) Server.receive_packet(server, request(6, "threads", %{})) assert_receive(response(_, 6, "threads", %{"threads" => threads})) @@ -1066,7 +1115,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do @tag :fixture test "terminate threads", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{})) + Server.receive_packet(server, initialize_req_(1)) assert_receive(response(_, 1, "initialize", %{"supportsConfigurationDoneRequest" => true})) Server.receive_packet( @@ -1080,11 +1129,11 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", %{}), 5000) - assert_receive(event(_, "initialized", %{})) + assert_receive(response(_, 2, "launch"), 5000) + assert_receive(event(_, "initialized", _)) Server.receive_packet(server, request(5, "configurationDone", %{})) - assert_receive(response(_, 5, "configurationDone", %{})) + assert_receive(response(_, 5, "configurationDone")) Process.sleep(1000) Server.receive_packet(server, request(6, "threads", %{})) assert_receive(response(_, 6, "threads", %{"threads" => threads}), 1_000) @@ -1095,7 +1144,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do |> Enum.map(& &1["id"]) Server.receive_packet(server, request(7, "terminateThreads", %{"threadIds" => [thread_id]})) - assert_receive(response(_, 7, "terminateThreads", %{}), 500) + assert_receive(response(_, 7, "terminateThreads"), 500) assert_receive event(_, "thread", %{ "reason" => "exited", @@ -1109,7 +1158,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do @tag :fixture test "alive", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{})) + Server.receive_packet(server, initialize_req_(1)) assert_receive( response(_, 1, "initialize", %{"supportsConfigurationDoneRequest" => true}) @@ -1126,11 +1175,11 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", %{}), 5000) - assert_receive(event(_, "initialized", %{})) + assert_receive(response(_, 2, "launch"), 5000) + assert_receive(event(_, "initialized", _)) Server.receive_packet(server, request(5, "configurationDone", %{})) - assert_receive(response(_, 5, "configurationDone", %{})) + assert_receive(response(_, 5, "configurationDone")) Process.sleep(1000) Server.receive_packet(server, request(6, "threads", %{})) assert_receive(response(_, 6, "threads", %{"threads" => threads}), 1_000) @@ -1141,7 +1190,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do |> Enum.map(& &1["id"]) Server.receive_packet(server, request(7, "pause", %{"threadId" => thread_id})) - assert_receive(response(_, 7, "pause", %{}), 500) + assert_receive(response(_, 7, "pause"), 500) assert_receive event(_, "stopped", %{ "allThreadsStopped" => false, @@ -1160,7 +1209,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do @tag :fixture test "dead", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{})) + Server.receive_packet(server, initialize_req_(1)) assert_receive( response(_, 1, "initialize", %{"supportsConfigurationDoneRequest" => true}) @@ -1177,11 +1226,11 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", %{}), 5000) - assert_receive(event(_, "initialized", %{})) + assert_receive(response(_, 2, "launch"), 5000) + assert_receive(event(_, "initialized", _)) Server.receive_packet(server, request(5, "configurationDone", %{})) - assert_receive(response(_, 5, "configurationDone", %{})) + assert_receive(response(_, 5, "configurationDone")) Process.sleep(1000) Server.receive_packet(server, request(6, "threads", %{})) assert_receive(response(_, 6, "threads", %{"threads" => threads}), 1_000) @@ -1195,7 +1244,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do Process.sleep(1000) Server.receive_packet(server, request(7, "pause", %{"threadId" => thread_id})) - assert_receive(response(_, 7, "pause", %{}), 500) + assert_receive(response(_, 7, "pause"), 500) assert_receive event(_, "thread", %{ "reason" => "exited", @@ -1210,7 +1259,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do @tag :fixture test "sets and unsets breakpoints in erlang modules", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{})) + Server.receive_packet(server, initialize_req_(1)) assert_receive(response(_, 1, "initialize", _)) Server.receive_packet( @@ -1225,8 +1274,8 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", _), 3000) - assert_receive(event(_, "initialized", %{}), 5000) + assert_receive(response(_, 2, "launch"), 3000) + assert_receive(event(_, "initialized", _), 5000) Process.sleep(100) @@ -1296,7 +1345,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do @tag :fixture test "handles invalid request", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{})) + Server.receive_packet(server, initialize_req_(1)) assert_receive(response(_, 1, "initialize", _)) Server.receive_packet( @@ -1311,8 +1360,8 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", _), 3000) - assert_receive(event(_, "initialized", %{}), 5000) + assert_receive(response(_, 2, "launch"), 3000) + assert_receive(event(_, "initialized", _), 5000) Process.sleep(100) @@ -1346,7 +1395,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do @tag :fixture test "sets and unsets breakpoints in elixir modules", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{})) + Server.receive_packet(server, initialize_req_(1)) assert_receive(response(_, 1, "initialize", _)) Server.receive_packet( @@ -1361,8 +1410,8 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", _), 3000) - assert_receive(event(_, "initialized", %{}), 5000) + assert_receive(response(_, 2, "launch"), 3000) + assert_receive(event(_, "initialized", _), 5000) Process.sleep(100) @@ -1452,7 +1501,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do @tag :fixture test "sets and unsets breakpoints in different files", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{})) + Server.receive_packet(server, initialize_req_(1)) assert_receive(response(_, 1, "initialize", _)) Server.receive_packet( @@ -1467,8 +1516,8 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", _), 3000) - assert_receive(event(_, "initialized", %{}), 5000) + assert_receive(response(_, 2, "launch"), 3000) + assert_receive(event(_, "initialized", _), 5000) Process.sleep(100) @@ -1548,7 +1597,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do @tag :fixture test "sets, modifies and unsets conditional breakpoints", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{})) + Server.receive_packet(server, initialize_req_(1)) assert_receive(response(_, 1, "initialize", _)) Server.receive_packet( @@ -1563,8 +1612,8 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", _), 3000) - assert_receive(event(_, "initialized", %{}), 5000) + assert_receive(response(_, 2, "launch"), 3000) + assert_receive(event(_, "initialized", _), 5000) Process.sleep(100) @@ -1645,7 +1694,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do @tag :fixture test "sets, modifies and unsets hit conditions", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{})) + Server.receive_packet(server, initialize_req_(1)) assert_receive(response(_, 1, "initialize", _)) Server.receive_packet( @@ -1660,8 +1709,8 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", _), 3000) - assert_receive(event(_, "initialized", %{}), 5000) + assert_receive(response(_, 2, "launch"), 3000) + assert_receive(event(_, "initialized", _), 5000) Process.sleep(100) @@ -1742,7 +1791,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do @tag :fixture test "sets, modifies and unsets log message", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{})) + Server.receive_packet(server, initialize_req_(1)) assert_receive(response(_, 1, "initialize", _)) Server.receive_packet( @@ -1757,8 +1806,8 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", _), 3000) - assert_receive(event(_, "initialized", %{}), 5000) + assert_receive(response(_, 2, "launch"), 3000) + assert_receive(event(_, "initialized", _), 5000) Process.sleep(100) @@ -1842,9 +1891,10 @@ defmodule ElixirLS.DebugAdapter.ServerTest do in_fixture(__DIR__, "mix_project", fn -> Server.receive_packet( server, - initialize_req(1, %{ - "supportsVariablePaging" => true, - "supportsVariableType" => true + initialize_req_(1, %{ + initialize_req_args() + | supports_variable_paging: true, + supports_variable_type: true }) ) @@ -1863,8 +1913,8 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", %{}), 5000) - assert_receive(event(_, "initialized", %{})) + assert_receive(response(_, 2, "launch"), 5000) + assert_receive(event(_, "initialized", _)) abs_path = Path.absname("lib/protocol_breakpoints.ex") Server.receive_packet( @@ -1885,7 +1935,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do :sys.get_state(server).breakpoints Server.receive_packet(server, request(5, "configurationDone", %{})) - assert_receive(response(_, 5, "configurationDone", %{})) + assert_receive(response(_, 5, "configurationDone")) assert_receive event(_, "stopped", %{ "allThreadsStopped" => false, @@ -1952,9 +2002,10 @@ defmodule ElixirLS.DebugAdapter.ServerTest do in_fixture(__DIR__, "mix_project", fn -> Server.receive_packet( server, - initialize_req(1, %{ - "supportsVariablePaging" => true, - "supportsVariableType" => true + initialize_req_(1, %{ + initialize_req_args() + | supports_variable_paging: true, + supports_variable_type: true }) ) @@ -1973,8 +2024,8 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", %{}), 5000) - assert_receive(event(_, "initialized", %{})) + assert_receive(response(_, 2, "launch"), 5000) + assert_receive(event(_, "initialized", _)) abs_path = Path.absname("lib/protocol_breakpoints.ex") Server.receive_packet( @@ -1999,7 +2050,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do :sys.get_state(server).breakpoints Server.receive_packet(server, request(5, "configurationDone", %{})) - assert_receive(response(_, 5, "configurationDone", %{})) + assert_receive(response(_, 5, "configurationDone")) assert_receive event(_, "stopped", %{ "allThreadsStopped" => false, @@ -2066,7 +2117,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do describe "function breakpoints" do test "sets and unsets function breakpoints", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{})) + Server.receive_packet(server, initialize_req_(1)) assert_receive(response(_, 1, "initialize", _)) Server.receive_packet( @@ -2081,8 +2132,8 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", _), 3000) - assert_receive(event(_, "initialized", %{}), 5000) + assert_receive(response(_, 2, "launch"), 3000) + assert_receive(event(_, "initialized", _), 5000) Process.sleep(100) @@ -2142,7 +2193,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do test "handles invalid requests", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{})) + Server.receive_packet(server, initialize_req_(1)) assert_receive(response(_, 1, "initialize", _)) Server.receive_packet( @@ -2157,8 +2208,8 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", _), 3000) - assert_receive(event(_, "initialized", %{}), 5000) + assert_receive(response(_, 2, "launch"), 3000) + assert_receive(event(_, "initialized", _), 5000) Process.sleep(100) @@ -2188,7 +2239,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do test "sets, modifies and unsets conditional function breakpoints", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{})) + Server.receive_packet(server, initialize_req_(1)) assert_receive(response(_, 1, "initialize", _)) Server.receive_packet( @@ -2203,8 +2254,8 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", _), 3000) - assert_receive(event(_, "initialized", %{}), 5000) + assert_receive(response(_, 2, "launch"), 3000) + assert_receive(event(_, "initialized", _), 5000) Process.sleep(100) @@ -2283,7 +2334,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do test "sets, modifies and unsets hit condition on function breakpoints", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{})) + Server.receive_packet(server, initialize_req_(1)) assert_receive(response(_, 1, "initialize", _)) Server.receive_packet( @@ -2298,8 +2349,8 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", _), 3000) - assert_receive(event(_, "initialized", %{}), 5000) + assert_receive(response(_, 2, "launch"), 3000) + assert_receive(event(_, "initialized", _), 5000) Process.sleep(100) @@ -2379,7 +2430,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do @tag :fixture test "breaks on function breakpoint", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{})) + Server.receive_packet(server, initialize_req_(1)) assert_receive( response(_, 1, "initialize", %{"supportsConfigurationDoneRequest" => true}) @@ -2396,8 +2447,8 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", %{}), 5000) - assert_receive(event(_, "initialized", %{})) + assert_receive(response(_, 2, "launch"), 5000) + assert_receive(event(_, "initialized", _)) Server.receive_packet( server, @@ -2410,7 +2461,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do ) Server.receive_packet(server, request(5, "configurationDone", %{})) - assert_receive(response(_, 5, "configurationDone", %{})) + assert_receive(response(_, 5, "configurationDone")) Server.receive_packet(server, request(6, "threads", %{})) assert_receive(response(_, 6, "threads", %{"threads" => threads})) @@ -2432,9 +2483,10 @@ defmodule ElixirLS.DebugAdapter.ServerTest do in_fixture(__DIR__, "mix_project", fn -> Server.receive_packet( server, - initialize_req(1, %{ - "supportsVariablePaging" => true, - "supportsVariableType" => true + initialize_req_(1, %{ + initialize_req_args() + | supports_variable_paging: true, + supports_variable_type: true }) ) @@ -2453,8 +2505,8 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", %{}), 5000) - assert_receive(event(_, "initialized", %{})) + assert_receive(response(_, 2, "launch"), 5000) + assert_receive(event(_, "initialized", _)) abs_path = Path.absname("lib/protocol_breakpoints.ex") Server.receive_packet( @@ -2476,7 +2528,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do assert %{{Proto, :go, 1} => [2]} = :sys.get_state(server).function_breakpoints Server.receive_packet(server, request(5, "configurationDone", %{})) - assert_receive(response(_, 5, "configurationDone", %{})) + assert_receive(response(_, 5, "configurationDone")) assert_receive event(_, "stopped", %{ "allThreadsStopped" => false, @@ -2543,9 +2595,10 @@ defmodule ElixirLS.DebugAdapter.ServerTest do in_fixture(__DIR__, "mix_project", fn -> Server.receive_packet( server, - initialize_req(1, %{ - "supportsVariablePaging" => true, - "supportsVariableType" => true + initialize_req_(1, %{ + initialize_req_args() + | supports_variable_paging: true, + supports_variable_type: true }) ) @@ -2564,8 +2617,8 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", %{}), 5000) - assert_receive(event(_, "initialized", %{})) + assert_receive(response(_, 2, "launch"), 5000) + assert_receive(event(_, "initialized", _)) abs_path = Path.absname("lib/protocol_breakpoints.ex") Server.receive_packet( @@ -2587,7 +2640,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do assert %{{Proto.List, :go, 1} => [7]} = :sys.get_state(server).function_breakpoints Server.receive_packet(server, request(5, "configurationDone", %{})) - assert_receive(response(_, 5, "configurationDone", %{})) + assert_receive(response(_, 5, "configurationDone")) assert_receive event(_, "stopped", %{ "allThreadsStopped" => false, @@ -2629,9 +2682,10 @@ defmodule ElixirLS.DebugAdapter.ServerTest do in_fixture(__DIR__, "mix_project", fn -> Server.receive_packet( server, - initialize_req(1, %{ - "supportsVariablePaging" => true, - "supportsVariableType" => true + initialize_req_(1, %{ + initialize_req_args() + | supports_variable_paging: true, + supports_variable_type: true }) ) @@ -2650,8 +2704,8 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", %{}), 5000) - assert_receive(event(_, "initialized", %{})) + assert_receive(response(_, 2, "launch"), 5000) + assert_receive(event(_, "initialized", _)) abs_path = Path.absname("lib/protocol_breakpoints.ex") Server.receive_packet( @@ -2675,7 +2729,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do :sys.get_state(server).function_breakpoints Server.receive_packet(server, request(5, "configurationDone", %{})) - assert_receive(response(_, 5, "configurationDone", %{})) + assert_receive(response(_, 5, "configurationDone")) assert_receive event(_, "stopped", %{ "allThreadsStopped" => false, @@ -2712,561 +2766,563 @@ defmodule ElixirLS.DebugAdapter.ServerTest do end end - describe "Kernel.dbg breakpoints" do - test "breaks on dbg", %{server: server} do - in_fixture(__DIR__, "mix_project", fn -> - abs_path = Path.absname("lib/dbg.ex") - Server.receive_packet(server, initialize_req(1, %{})) - assert_receive(response(_, 1, "initialize", _)) - - Server.receive_packet( - server, - launch_req(2, %{ - "request" => "launch", - "type" => "mix_task", - "task" => "run", - "taskArgs" => ["-e", "MixProject.Dbg.simple()"], - "projectDir" => File.cwd!() - }) - ) - - assert_receive(response(_, 2, "launch", _), 3000) - assert_receive(event(_, "initialized", %{}), 5000) - - Process.sleep(100) - - assert MixProject.Dbg in :int.interpreted() - - Server.receive_packet(server, request(5, "configurationDone", %{})) - assert_receive(response(_, 5, "configurationDone", %{})) - - Server.receive_packet(server, request(6, "threads", %{})) - assert_receive(response(_, 6, "threads", %{"threads" => threads})) - - # ensure thread ids are unique - thread_ids = Enum.map(threads, & &1["id"]) - assert Enum.count(Enum.uniq(thread_ids)) == Enum.count(thread_ids) - - assert_receive event(_, "stopped", %{ - "allThreadsStopped" => false, - "reason" => "breakpoint", - "threadId" => thread_id - }), - 5_000 - - Server.receive_packet(server, stacktrace_req(7, thread_id)) + if Version.match?(System.version(), ">= 1.14.0") do + describe "Kernel.dbg breakpoints" do + test "breaks on dbg", %{server: server} do + in_fixture(__DIR__, "mix_project", fn -> + abs_path = Path.absname("lib/dbg.ex") + Server.receive_packet(server, initialize_req_(1)) + assert_receive(response(_, 1, "initialize", _)) + + Server.receive_packet( + server, + launch_req(2, %{ + "request" => "launch", + "type" => "mix_task", + "task" => "run", + "taskArgs" => ["-e", "MixProject.Dbg.simple()"], + "projectDir" => File.cwd!() + }) + ) - assert_receive response(_, 7, "stackTrace", %{ - "totalFrames" => 1, - "stackFrames" => [ - %{ - "column" => 0, - "id" => frame_id, - "line" => 5, - "name" => "MixProject.Dbg.simple/0", - "source" => %{"path" => ^abs_path} - } - ] - }) - when is_integer(frame_id) + assert_receive(response(_, 2, "launch"), 3000) + assert_receive(event(_, "initialized", _), 5000) - Server.receive_packet(server, scopes_req(8, frame_id)) + Process.sleep(100) - assert_receive response(_, 8, "scopes", %{ - "scopes" => [ - %{ - "expensive" => false, - "indexedVariables" => 0, - "name" => "variables", - "namedVariables" => 1, - "variablesReference" => vars_id - }, - %{ - "expensive" => false, - "indexedVariables" => 0, - "name" => "process info", - "namedVariables" => _, - "variablesReference" => _ - } - ] - }) + assert MixProject.Dbg in :int.interpreted() - Server.receive_packet(server, vars_req(9, vars_id)) + Server.receive_packet(server, request(5, "configurationDone", %{})) + assert_receive(response(_, 5, "configurationDone")) - assert_receive response(_, 9, "variables", %{ - "variables" => [ - %{ - "name" => "a", - "value" => "5", - "variablesReference" => 0 - } - ] - }), - 1000 + Server.receive_packet(server, request(6, "threads", %{})) + assert_receive(response(_, 6, "threads", %{"threads" => threads})) - # stepIn is not supported - Server.receive_packet(server, step_in_req(12, thread_id)) + # ensure thread ids are unique + thread_ids = Enum.map(threads, & &1["id"]) + assert Enum.count(Enum.uniq(thread_ids)) == Enum.count(thread_ids) - assert_receive( - error_response( - _, - 12, - "stepIn", - "notSupported", - "Kernel.dbg breakpoints do not support {command} command", - %{"command" => "stepIn"}, - _, - _ + assert_receive event(_, "stopped", %{ + "allThreadsStopped" => false, + "reason" => "breakpoint", + "threadId" => thread_id + }), + 5_000 + + Server.receive_packet(server, stacktrace_req(7, thread_id)) + + assert_receive response(_, 7, "stackTrace", %{ + "totalFrames" => 1, + "stackFrames" => [ + %{ + "column" => 0, + "id" => frame_id, + "line" => 5, + "name" => "MixProject.Dbg.simple/0", + "source" => %{"path" => ^abs_path} + } + ] + }) + when is_integer(frame_id) + + Server.receive_packet(server, scopes_req(8, frame_id)) + + assert_receive response(_, 8, "scopes", %{ + "scopes" => [ + %{ + "expensive" => false, + "indexedVariables" => 0, + "name" => "variables", + "namedVariables" => 1, + "variablesReference" => vars_id + }, + %{ + "expensive" => false, + "indexedVariables" => 0, + "name" => "process info", + "namedVariables" => _, + "variablesReference" => _ + } + ] + }) + + Server.receive_packet(server, vars_req(9, vars_id)) + + assert_receive response(_, 9, "variables", %{ + "variables" => [ + %{ + "name" => "a", + "value" => "5", + "variablesReference" => 0 + } + ] + }), + 1000 + + # stepIn is not supported + Server.receive_packet(server, step_in_req(12, thread_id)) + + assert_receive( + error_response( + _, + 12, + "stepIn", + "notSupported", + "Kernel.dbg breakpoints do not support {command} command", + %{"command" => "stepIn"}, + _, + _ + ) ) - ) - - # stepOut is not supported - Server.receive_packet(server, step_out_req(13, thread_id)) - assert_receive( - error_response( - _, - 13, - "stepOut", - "notSupported", - "Kernel.dbg breakpoints do not support {command} command", - %{"command" => "stepOut"}, - _, - _ + # stepOut is not supported + Server.receive_packet(server, step_out_req(13, thread_id)) + + assert_receive( + error_response( + _, + 13, + "stepOut", + "notSupported", + "Kernel.dbg breakpoints do not support {command} command", + %{"command" => "stepOut"}, + _, + _ + ) ) - ) - - # next results in continue - Server.receive_packet(server, next_req(14, thread_id)) - assert_receive response(_, 14, "next", %{}) - - assert_receive event(_, "stopped", %{ - "allThreadsStopped" => false, - "reason" => "breakpoint", - "threadId" => ^thread_id - }), - 5_000 - - Server.receive_packet(server, stacktrace_req(141, thread_id)) - - assert_receive response(_, 141, "stackTrace", %{ - "totalFrames" => 1, - "stackFrames" => [ - %{ - "column" => 0, - "id" => frame_id, - "line" => 6, - "name" => "MixProject.Dbg.simple/0", - "source" => %{"path" => ^abs_path} - } - ] - }) - when is_integer(frame_id) - # continue - Server.receive_packet(server, continue_req(15, thread_id)) - assert_receive response(_, 15, "continue", %{"allThreadsContinued" => true}) - - assert_receive event(_, "stopped", %{ - "allThreadsStopped" => false, - "reason" => "breakpoint", - "threadId" => ^thread_id - }), - 5_000 - - Server.receive_packet(server, stacktrace_req(151, thread_id)) - - assert_receive response(_, 151, "stackTrace", %{ - "totalFrames" => 1, - "stackFrames" => [ - %{ - "column" => 0, - "id" => frame_id, - "line" => 7, - "name" => "MixProject.Dbg.simple/0", - "source" => %{"path" => ^abs_path} - } - ] - }) - when is_integer(frame_id) - - Server.receive_packet(server, continue_req(16, thread_id)) - assert_receive response(_, 16, "continue", %{"allThreadsContinued" => true}) - - refute_receive event(_, "thread", %{ - "reason" => "exited", - "threadId" => ^thread_id - }), - 1_000 - end) - end - - test "stepping through pipe", %{server: server} do - in_fixture(__DIR__, "mix_project", fn -> - abs_path = Path.absname("lib/dbg.ex") - Server.receive_packet(server, initialize_req(1, %{})) - assert_receive(response(_, 1, "initialize", _)) - - Server.receive_packet( - server, - launch_req(2, %{ - "request" => "launch", - "type" => "mix_task", - "task" => "run", - "taskArgs" => ["-e", "MixProject.Dbg.pipe()"], - "projectDir" => File.cwd!() - }) - ) - - assert_receive(response(_, 2, "launch", _), 3000) - assert_receive(event(_, "initialized", %{}), 5000) - - Process.sleep(100) - - assert MixProject.Dbg in :int.interpreted() - - Server.receive_packet(server, request(5, "configurationDone", %{})) - assert_receive(response(_, 5, "configurationDone", %{})) - - Server.receive_packet(server, request(6, "threads", %{})) - assert_receive(response(_, 6, "threads", %{"threads" => threads})) + # next results in continue + Server.receive_packet(server, next_req(14, thread_id)) + assert_receive response(_, 14, "next") - # ensure thread ids are unique - thread_ids = Enum.map(threads, & &1["id"]) - assert Enum.count(Enum.uniq(thread_ids)) == Enum.count(thread_ids) + assert_receive event(_, "stopped", %{ + "allThreadsStopped" => false, + "reason" => "breakpoint", + "threadId" => ^thread_id + }), + 5_000 + + Server.receive_packet(server, stacktrace_req(141, thread_id)) + + assert_receive response(_, 141, "stackTrace", %{ + "totalFrames" => 1, + "stackFrames" => [ + %{ + "column" => 0, + "id" => frame_id, + "line" => 6, + "name" => "MixProject.Dbg.simple/0", + "source" => %{"path" => ^abs_path} + } + ] + }) + when is_integer(frame_id) + + # continue + Server.receive_packet(server, continue_req(15, thread_id)) + assert_receive response(_, 15, "continue", %{"allThreadsContinued" => true}) + + assert_receive event(_, "stopped", %{ + "allThreadsStopped" => false, + "reason" => "breakpoint", + "threadId" => ^thread_id + }), + 5_000 + + Server.receive_packet(server, stacktrace_req(151, thread_id)) + + assert_receive response(_, 151, "stackTrace", %{ + "totalFrames" => 1, + "stackFrames" => [ + %{ + "column" => 0, + "id" => frame_id, + "line" => 7, + "name" => "MixProject.Dbg.simple/0", + "source" => %{"path" => ^abs_path} + } + ] + }) + when is_integer(frame_id) + + Server.receive_packet(server, continue_req(16, thread_id)) + assert_receive response(_, 16, "continue", %{"allThreadsContinued" => true}) + + refute_receive event(_, "thread", %{ + "reason" => "exited", + "threadId" => ^thread_id + }), + 1_000 + end) + end - assert_receive event(_, "stopped", %{ - "allThreadsStopped" => false, - "reason" => "breakpoint", - "threadId" => thread_id - }), - 5_000 + test "stepping through pipe", %{server: server} do + in_fixture(__DIR__, "mix_project", fn -> + abs_path = Path.absname("lib/dbg.ex") + Server.receive_packet(server, initialize_req_(1)) + assert_receive(response(_, 1, "initialize", _)) + + Server.receive_packet( + server, + launch_req(2, %{ + "request" => "launch", + "type" => "mix_task", + "task" => "run", + "taskArgs" => ["-e", "MixProject.Dbg.pipe()"], + "projectDir" => File.cwd!() + }) + ) - Server.receive_packet(server, stacktrace_req(7, thread_id)) + assert_receive(response(_, 2, "launch"), 3000) + assert_receive(event(_, "initialized", _), 5000) - assert_receive response(_, 7, "stackTrace", %{ - "totalFrames" => 1, - "stackFrames" => [ - %{ - "column" => 0, - "id" => frame_id, - "line" => 14, - "name" => "MixProject.Dbg.pipe/0", - "source" => %{"path" => ^abs_path} - } - ] - }) - when is_integer(frame_id) + Process.sleep(100) - Server.receive_packet(server, scopes_req(8, frame_id)) - - assert_receive response(_, 8, "scopes", %{ - "scopes" => [ - %{ - "expensive" => false, - "indexedVariables" => 0, - "name" => "variables", - "namedVariables" => 1, - "variablesReference" => vars_id - }, - %{ - "expensive" => false, - "indexedVariables" => 0, - "name" => "process info", - "namedVariables" => _, - "variablesReference" => _ - } - ] - }) + assert MixProject.Dbg in :int.interpreted() - Server.receive_packet(server, vars_req(9, vars_id)) + Server.receive_packet(server, request(5, "configurationDone", %{})) + assert_receive(response(_, 5, "configurationDone")) - assert_receive response(_, 9, "variables", %{ - "variables" => [ - %{ - "name" => "a", - "value" => "5", - "variablesReference" => 0 - } - ] - }), - 1000 + Server.receive_packet(server, request(6, "threads", %{})) + assert_receive(response(_, 6, "threads", %{"threads" => threads})) - # stepIn is not supported - Server.receive_packet(server, step_in_req(12, thread_id)) + # ensure thread ids are unique + thread_ids = Enum.map(threads, & &1["id"]) + assert Enum.count(Enum.uniq(thread_ids)) == Enum.count(thread_ids) - assert_receive( - error_response( - _, - 12, - "stepIn", - "notSupported", - "Kernel.dbg breakpoints do not support {command} command", - %{"command" => "stepIn"}, - _, - _ + assert_receive event(_, "stopped", %{ + "allThreadsStopped" => false, + "reason" => "breakpoint", + "threadId" => thread_id + }), + 5_000 + + Server.receive_packet(server, stacktrace_req(7, thread_id)) + + assert_receive response(_, 7, "stackTrace", %{ + "totalFrames" => 1, + "stackFrames" => [ + %{ + "column" => 0, + "id" => frame_id, + "line" => 14, + "name" => "MixProject.Dbg.pipe/0", + "source" => %{"path" => ^abs_path} + } + ] + }) + when is_integer(frame_id) + + Server.receive_packet(server, scopes_req(8, frame_id)) + + assert_receive response(_, 8, "scopes", %{ + "scopes" => [ + %{ + "expensive" => false, + "indexedVariables" => 0, + "name" => "variables", + "namedVariables" => 1, + "variablesReference" => vars_id + }, + %{ + "expensive" => false, + "indexedVariables" => 0, + "name" => "process info", + "namedVariables" => _, + "variablesReference" => _ + } + ] + }) + + Server.receive_packet(server, vars_req(9, vars_id)) + + assert_receive response(_, 9, "variables", %{ + "variables" => [ + %{ + "name" => "a", + "value" => "5", + "variablesReference" => 0 + } + ] + }), + 1000 + + # stepIn is not supported + Server.receive_packet(server, step_in_req(12, thread_id)) + + assert_receive( + error_response( + _, + 12, + "stepIn", + "notSupported", + "Kernel.dbg breakpoints do not support {command} command", + %{"command" => "stepIn"}, + _, + _ + ) ) - ) - - # stepOut is not supported - Server.receive_packet(server, step_out_req(13, thread_id)) - assert_receive( - error_response( - _, - 13, - "stepOut", - "notSupported", - "Kernel.dbg breakpoints do not support {command} command", - %{"command" => "stepOut"}, - _, - _ + # stepOut is not supported + Server.receive_packet(server, step_out_req(13, thread_id)) + + assert_receive( + error_response( + _, + 13, + "stepOut", + "notSupported", + "Kernel.dbg breakpoints do not support {command} command", + %{"command" => "stepOut"}, + _, + _ + ) ) - ) - - # next steps through pipe - Server.receive_packet(server, next_req(14, thread_id)) - assert_receive response(_, 14, "next", %{}) - - assert_receive event(_, "stopped", %{ - "allThreadsStopped" => false, - "reason" => "breakpoint", - "threadId" => ^thread_id - }), - 5_000 - - Server.receive_packet(server, stacktrace_req(141, thread_id)) - - assert_receive response(_, 141, "stackTrace", %{ - "totalFrames" => 1, - "stackFrames" => [ - %{ - "column" => 0, - "id" => frame_id, - "line" => 15, - "name" => "MixProject.Dbg.pipe/0", - "source" => %{"path" => ^abs_path} - } - ] - }) - when is_integer(frame_id) - - # continue skips pipe steps - Server.receive_packet(server, continue_req(15, thread_id)) - assert_receive response(_, 15, "continue", %{"allThreadsContinued" => true}) - - refute_receive event(_, "stopped", %{ - "allThreadsStopped" => false, - "reason" => "breakpoint", - "threadId" => ^thread_id - }), - 1_000 - - refute_receive event(_, "thread", %{ - "reason" => "exited", - "threadId" => ^thread_id - }) - end) - end - - test "breaks on dbg when module is not interpreted", %{server: server} do - in_fixture(__DIR__, "mix_project", fn -> - abs_path = Path.absname("lib/dbg.ex") - Server.receive_packet(server, initialize_req(1, %{})) - assert_receive(response(_, 1, "initialize", _)) - - Server.receive_packet( - server, - launch_req(2, %{ - "request" => "launch", - "type" => "mix_task", - "task" => "run", - "taskArgs" => ["-e", "MixProject.Dbg.simple()"], - "projectDir" => File.cwd!(), - # disable auto interpret - "debugAutoInterpretAllModules" => false - }) - ) - assert_receive(response(_, 2, "launch", _), 3000) - assert_receive(event(_, "initialized", %{}), 5000) + # next steps through pipe + Server.receive_packet(server, next_req(14, thread_id)) + assert_receive response(_, 14, "next") - Process.sleep(100) - - refute MixProject.Dbg in :int.interpreted() - - Server.receive_packet(server, request(5, "configurationDone", %{})) - assert_receive(response(_, 5, "configurationDone", %{})) - - Server.receive_packet(server, request(6, "threads", %{})) - assert_receive(response(_, 6, "threads", %{"threads" => threads})) - - # ensure thread ids are unique - thread_ids = Enum.map(threads, & &1["id"]) - assert Enum.count(Enum.uniq(thread_ids)) == Enum.count(thread_ids) + assert_receive event(_, "stopped", %{ + "allThreadsStopped" => false, + "reason" => "breakpoint", + "threadId" => ^thread_id + }), + 5_000 + + Server.receive_packet(server, stacktrace_req(141, thread_id)) + + assert_receive response(_, 141, "stackTrace", %{ + "totalFrames" => 1, + "stackFrames" => [ + %{ + "column" => 0, + "id" => frame_id, + "line" => 15, + "name" => "MixProject.Dbg.pipe/0", + "source" => %{"path" => ^abs_path} + } + ] + }) + when is_integer(frame_id) + + # continue skips pipe steps + Server.receive_packet(server, continue_req(15, thread_id)) + assert_receive response(_, 15, "continue", %{"allThreadsContinued" => true}) + + refute_receive event(_, "stopped", %{ + "allThreadsStopped" => false, + "reason" => "breakpoint", + "threadId" => ^thread_id + }), + 1_000 - assert_receive event(_, "stopped", %{ - "allThreadsStopped" => false, - "reason" => "breakpoint", - "threadId" => thread_id - }), - 5_000 + refute_receive event(_, "thread", %{ + "reason" => "exited", + "threadId" => ^thread_id + }) + end) + end - Server.receive_packet(server, stacktrace_req(7, thread_id)) + test "breaks on dbg when module is not interpreted", %{server: server} do + in_fixture(__DIR__, "mix_project", fn -> + abs_path = Path.absname("lib/dbg.ex") + Server.receive_packet(server, initialize_req_(1)) + assert_receive(response(_, 1, "initialize", _)) + + Server.receive_packet( + server, + launch_req(2, %{ + "request" => "launch", + "type" => "mix_task", + "task" => "run", + "taskArgs" => ["-e", "MixProject.Dbg.simple()"], + "projectDir" => File.cwd!(), + # disable auto interpret + "debugAutoInterpretAllModules" => false + }) + ) - assert_receive response(_, 7, "stackTrace", %{ - "totalFrames" => 7, - "stackFrames" => [ - %{ - "column" => 0, - "id" => frame_id, - "line" => 5, - "name" => "MixProject.Dbg.simple/0", - "source" => %{"path" => ^abs_path} - } - | _ - ] - }) - when is_integer(frame_id) + assert_receive(response(_, 2, "launch"), 3000) + assert_receive(event(_, "initialized", _), 5000) - Server.receive_packet(server, scopes_req(8, frame_id)) + Process.sleep(100) - assert_receive response(_, 8, "scopes", %{ - "scopes" => [ - %{ - "expensive" => false, - "indexedVariables" => 0, - "name" => "variables", - "namedVariables" => 1, - "variablesReference" => vars_id - }, - %{ - "expensive" => false, - "indexedVariables" => 0, - "name" => "process info", - "namedVariables" => _, - "variablesReference" => _ - } - ] - }) + refute MixProject.Dbg in :int.interpreted() - Server.receive_packet(server, vars_req(9, vars_id)) + Server.receive_packet(server, request(5, "configurationDone", %{})) + assert_receive(response(_, 5, "configurationDone")) - assert_receive response(_, 9, "variables", %{ - "variables" => [ - %{ - "name" => "a", - "value" => "5", - "variablesReference" => 0 - } - ] - }), - 1000 + Server.receive_packet(server, request(6, "threads", %{})) + assert_receive(response(_, 6, "threads", %{"threads" => threads})) - # stepIn is not supported - Server.receive_packet(server, step_in_req(12, thread_id)) + # ensure thread ids are unique + thread_ids = Enum.map(threads, & &1["id"]) + assert Enum.count(Enum.uniq(thread_ids)) == Enum.count(thread_ids) - assert_receive( - error_response( - _, - 12, - "stepIn", - "notSupported", - "Kernel.dbg breakpoints do not support {command} command", - %{"command" => "stepIn"}, - _, - _ + assert_receive event(_, "stopped", %{ + "allThreadsStopped" => false, + "reason" => "breakpoint", + "threadId" => thread_id + }), + 5_000 + + Server.receive_packet(server, stacktrace_req(7, thread_id)) + + assert_receive response(_, 7, "stackTrace", %{ + "totalFrames" => 7, + "stackFrames" => [ + %{ + "column" => 0, + "id" => frame_id, + "line" => 5, + "name" => "MixProject.Dbg.simple/0", + "source" => %{"path" => ^abs_path} + } + | _ + ] + }) + when is_integer(frame_id) + + Server.receive_packet(server, scopes_req(8, frame_id)) + + assert_receive response(_, 8, "scopes", %{ + "scopes" => [ + %{ + "expensive" => false, + "indexedVariables" => 0, + "name" => "variables", + "namedVariables" => 1, + "variablesReference" => vars_id + }, + %{ + "expensive" => false, + "indexedVariables" => 0, + "name" => "process info", + "namedVariables" => _, + "variablesReference" => _ + } + ] + }) + + Server.receive_packet(server, vars_req(9, vars_id)) + + assert_receive response(_, 9, "variables", %{ + "variables" => [ + %{ + "name" => "a", + "value" => "5", + "variablesReference" => 0 + } + ] + }), + 1000 + + # stepIn is not supported + Server.receive_packet(server, step_in_req(12, thread_id)) + + assert_receive( + error_response( + _, + 12, + "stepIn", + "notSupported", + "Kernel.dbg breakpoints do not support {command} command", + %{"command" => "stepIn"}, + _, + _ + ) ) - ) - # stepOut is not supported - Server.receive_packet(server, step_out_req(13, thread_id)) - - assert_receive( - error_response( - _, - 13, - "stepOut", - "notSupported", - "Kernel.dbg breakpoints do not support {command} command", - %{"command" => "stepOut"}, - _, - _ + # stepOut is not supported + Server.receive_packet(server, step_out_req(13, thread_id)) + + assert_receive( + error_response( + _, + 13, + "stepOut", + "notSupported", + "Kernel.dbg breakpoints do not support {command} command", + %{"command" => "stepOut"}, + _, + _ + ) ) - ) - - # next results in continue - Server.receive_packet(server, next_req(14, thread_id)) - assert_receive response(_, 14, "next", %{}) - - assert_receive event(_, "stopped", %{ - "allThreadsStopped" => false, - "reason" => "breakpoint", - "threadId" => ^thread_id - }), - 5_000 - - Server.receive_packet(server, stacktrace_req(141, thread_id)) - - assert_receive response(_, 141, "stackTrace", %{ - "totalFrames" => 7, - "stackFrames" => [ - %{ - "column" => 0, - "id" => frame_id, - "line" => 6, - "name" => "MixProject.Dbg.simple/0", - "source" => %{"path" => ^abs_path} - } - | _ - ] - }) - when is_integer(frame_id) - - # continue - Server.receive_packet(server, continue_req(15, thread_id)) - assert_receive response(_, 15, "continue", %{"allThreadsContinued" => true}) - - assert_receive event(_, "stopped", %{ - "allThreadsStopped" => false, - "reason" => "breakpoint", - "threadId" => ^thread_id - }), - 5_000 - Server.receive_packet(server, stacktrace_req(151, thread_id)) + # next results in continue + Server.receive_packet(server, next_req(14, thread_id)) + assert_receive response(_, 14, "next") - assert_receive response(_, 151, "stackTrace", %{ - "totalFrames" => 7, - "stackFrames" => [ - %{ - "column" => 0, - "id" => frame_id, - "line" => 7, - "name" => "MixProject.Dbg.simple/0", - "source" => %{"path" => ^abs_path} - } - | _ - ] - }) - when is_integer(frame_id) - - Server.receive_packet(server, continue_req(16, thread_id)) - assert_receive response(_, 16, "continue", %{"allThreadsContinued" => true}) - - refute_receive event(_, "thread", %{ - "reason" => "exited", - "threadId" => ^thread_id - }), - 1_000 - end) + assert_receive event(_, "stopped", %{ + "allThreadsStopped" => false, + "reason" => "breakpoint", + "threadId" => ^thread_id + }), + 5_000 + + Server.receive_packet(server, stacktrace_req(141, thread_id)) + + assert_receive response(_, 141, "stackTrace", %{ + "totalFrames" => 7, + "stackFrames" => [ + %{ + "column" => 0, + "id" => frame_id, + "line" => 6, + "name" => "MixProject.Dbg.simple/0", + "source" => %{"path" => ^abs_path} + } + | _ + ] + }) + when is_integer(frame_id) + + # continue + Server.receive_packet(server, continue_req(15, thread_id)) + assert_receive response(_, 15, "continue", %{"allThreadsContinued" => true}) + + assert_receive event(_, "stopped", %{ + "allThreadsStopped" => false, + "reason" => "breakpoint", + "threadId" => ^thread_id + }), + 5_000 + + Server.receive_packet(server, stacktrace_req(151, thread_id)) + + assert_receive response(_, 151, "stackTrace", %{ + "totalFrames" => 7, + "stackFrames" => [ + %{ + "column" => 0, + "id" => frame_id, + "line" => 7, + "name" => "MixProject.Dbg.simple/0", + "source" => %{"path" => ^abs_path} + } + | _ + ] + }) + when is_integer(frame_id) + + Server.receive_packet(server, continue_req(16, thread_id)) + assert_receive response(_, 16, "continue", %{"allThreadsContinued" => true}) + + refute_receive event(_, "thread", %{ + "reason" => "exited", + "threadId" => ^thread_id + }), + 1_000 + end) + end end end @tag :fixture test "server tracks running processes", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{})) + Server.receive_packet(server, initialize_req_(1)) assert_receive(response(_, 1, "initialize", %{"supportsConfigurationDoneRequest" => true})) @@ -3281,11 +3337,11 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", %{}), 5000) - assert_receive(event(_, "initialized", %{})) + assert_receive(response(_, 2, "launch"), 5000) + assert_receive(event(_, "initialized", _)) Server.receive_packet(server, request(5, "configurationDone", %{})) - assert_receive(response(_, 5, "configurationDone", %{})) + assert_receive(response(_, 5, "configurationDone")) Process.sleep(1000) {:ok, pid} = @@ -3300,9 +3356,9 @@ defmodule ElixirLS.DebugAdapter.ServerTest do send(server, :update_threads) state = :sys.get_state(server) - thread_id = state.pids_to_thread_ids[pid] + {:ok, thread_id} = ThreadRegistry.get_thread_id_by_pid(state.thread_registry, pid) assert thread_id - assert state.thread_ids_to_pids[thread_id] == pid + assert ThreadRegistry.get_pid_by_thread_id(state.thread_registry, thread_id) == {:ok, pid} Server.receive_packet(server, request(6, "threads", %{})) assert_receive(response(_, 6, "threads", %{"threads" => threads}), 1_000) @@ -3324,8 +3380,8 @@ defmodule ElixirLS.DebugAdapter.ServerTest do send(server, :update_threads) state = :sys.get_state(server) - refute Map.has_key?(state.pids_to_thread_ids, pid) - refute Map.has_key?(state.thread_ids_to_pids, thread_id) + assert ThreadRegistry.get_thread_id_by_pid(state.thread_registry, pid) == :error + assert ThreadRegistry.get_pid_by_thread_id(state.thread_registry, thread_id) == :error Server.receive_packet(server, request(6, "threads", %{})) assert_receive(response(_, 6, "threads", %{"threads" => threads}), 1_000) @@ -3338,7 +3394,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do @tag :fixture test "returns process label", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{})) + Server.receive_packet(server, initialize_req_(1)) assert_receive( response(_, 1, "initialize", %{"supportsConfigurationDoneRequest" => true}) @@ -3355,11 +3411,11 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", %{}), 5000) - assert_receive(event(_, "initialized", %{})) + assert_receive(response(_, 2, "launch"), 5000) + assert_receive(event(_, "initialized", _)) Server.receive_packet(server, request(5, "configurationDone", %{})) - assert_receive(response(_, 5, "configurationDone", %{})) + assert_receive(response(_, 5, "configurationDone")) Process.sleep(1000) {:ok, pid} = @@ -3376,9 +3432,9 @@ defmodule ElixirLS.DebugAdapter.ServerTest do send(server, :update_threads) state = :sys.get_state(server) - thread_id = state.pids_to_thread_ids[pid] + {:ok, thread_id} = ThreadRegistry.get_thread_id_by_pid(state.thread_registry, pid) assert thread_id - assert state.thread_ids_to_pids[thread_id] == pid + assert ThreadRegistry.get_pid_by_thread_id(state.thread_registry, thread_id) == {:ok, pid} Server.receive_packet(server, request(6, "threads", %{})) assert_receive(response(_, 6, "threads", %{"threads" => threads}), 1_000) @@ -3395,8 +3451,8 @@ defmodule ElixirLS.DebugAdapter.ServerTest do send(server, :update_threads) state = :sys.get_state(server) - refute Map.has_key?(state.pids_to_thread_ids, pid) - refute Map.has_key?(state.thread_ids_to_pids, thread_id) + assert ThreadRegistry.get_thread_id_by_pid(state.thread_registry, pid) == :error + assert ThreadRegistry.get_pid_by_thread_id(state.thread_registry, thread_id) == :error Server.receive_packet(server, request(6, "threads", %{})) assert_receive(response(_, 6, "threads", %{"threads" => threads}), 1_000) @@ -3422,7 +3478,11 @@ defmodule ElixirLS.DebugAdapter.ServerTest do test "evaluate expression with OK result", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{"supportsProgressReporting" => true})) + Server.receive_packet( + server, + initialize_req_(1, %{initialize_req_args() | supports_progress_reporting: true}) + ) + assert_receive(response(_, 1, "initialize", _)) Server.receive_packet( @@ -3434,7 +3494,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do event(_, "progressStart", %{ "cancellable" => true, "message" => "1 + 2 + 3 + 4", - "progressId" => 1, + "progressId" => "1", "requestId" => 1, "title" => "Evaluating expression" }) @@ -3442,7 +3502,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do assert_receive(%{"body" => %{"result" => "10"}}, 1000) - assert_receive(event(_, "progressEnd", %{"progressId" => 1})) + assert_receive(event(_, "progressEnd", %{"progressId" => "1"})) assert Process.alive?(server) end) @@ -3452,7 +3512,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do server: server } do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{})) + Server.receive_packet(server, initialize_req_(1)) assert_receive(response(_, 1, "initialize", _)) Server.receive_packet( @@ -3464,7 +3524,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do event(_, "progressStart", %{ "cancellable" => true, "message" => "1 + 2 + 3 + 4", - "progressId" => 1, + "progressId" => "1", "requestId" => 1, "title" => "Evaluating expression" }) @@ -3472,7 +3532,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do assert_receive(%{"body" => %{"result" => "10"}}, 1000) - refute_receive(event(_, "progressEnd", %{"progressId" => 1})) + refute_receive(event(_, "progressEnd", %{"progressId" => "1"})) assert Process.alive?(server) end) @@ -3481,7 +3541,11 @@ defmodule ElixirLS.DebugAdapter.ServerTest do @tag :capture_log test "evaluate expression with exception result", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{"supportsProgressReporting" => true})) + Server.receive_packet( + server, + initialize_req_(1, %{initialize_req_args() | supports_progress_reporting: true}) + ) + assert_receive(response(_, 1, "initialize", _)) Server.receive_packet( @@ -3493,7 +3557,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do event(_, "progressStart", %{ "cancellable" => true, "message" => "1 = 2", - "progressId" => 1, + "progressId" => "1", "requestId" => 1, "title" => "Evaluating expression" }) @@ -3512,7 +3576,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do ) ) - assert_receive(event(_, "progressEnd", %{"progressId" => 1})) + assert_receive(event(_, "progressEnd", %{"progressId" => "1"})) assert Process.alive?(server) end) @@ -3520,7 +3584,11 @@ defmodule ElixirLS.DebugAdapter.ServerTest do test "evaluate expression which calls exit process", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{"supportsProgressReporting" => true})) + Server.receive_packet( + server, + initialize_req_(1, %{initialize_req_args() | supports_progress_reporting: true}) + ) + assert_receive(response(_, 1, "initialize", _)) Server.receive_packet( @@ -3532,7 +3600,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do event(_, "progressStart", %{ "cancellable" => true, "message" => "exit(:normal)", - "progressId" => 1, + "progressId" => "1", "requestId" => 1, "title" => "Evaluating expression" }) @@ -3554,7 +3622,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do ) ) - assert_receive(event(_, "progressEnd", %{"progressId" => 1})) + assert_receive(event(_, "progressEnd", %{"progressId" => "1"})) assert Process.alive?(server) end) @@ -3562,7 +3630,11 @@ defmodule ElixirLS.DebugAdapter.ServerTest do test "evaluate expression with attempt to exit debugger process", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{"supportsProgressReporting" => true})) + Server.receive_packet( + server, + initialize_req_(1, %{initialize_req_args() | supports_progress_reporting: true}) + ) + assert_receive(response(_, 1, "initialize", _)) Server.receive_packet( @@ -3574,7 +3646,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do event(_, "progressStart", %{ "cancellable" => true, "message" => "Process.exit(self(), :normal)", - "progressId" => 1, + "progressId" => "1", "requestId" => 1, "title" => "Evaluating expression" }) @@ -3596,7 +3668,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do ) ) - assert_receive(event(_, "progressEnd", %{"progressId" => 1})) + assert_receive(event(_, "progressEnd", %{"progressId" => "1"})) assert Process.alive?(server) end) @@ -3606,7 +3678,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do server: server } do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{})) + Server.receive_packet(server, initialize_req_(1)) assert_receive(response(_, 1, "initialize", _)) Server.receive_packet( @@ -3618,7 +3690,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do event(_, "progressStart", %{ "cancellable" => true, "message" => "Process.exit(self(), :normal)", - "progressId" => 1, + "progressId" => "1", "requestId" => 1, "title" => "Evaluating expression" }) @@ -3640,7 +3712,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do ) ) - refute_receive(event(_, "progressEnd", %{"progressId" => 1})) + refute_receive(event(_, "progressEnd", %{"progressId" => "1"})) assert Process.alive?(server) end) @@ -3648,7 +3720,11 @@ defmodule ElixirLS.DebugAdapter.ServerTest do test "evaluate expression with attempt to throw debugger process", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{"supportsProgressReporting" => true})) + Server.receive_packet( + server, + initialize_req_(1, %{initialize_req_args() | supports_progress_reporting: true}) + ) + assert_receive(response(_, 1, "initialize", _)) Server.receive_packet( @@ -3660,7 +3736,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do event(_, "progressStart", %{ "cancellable" => true, "message" => "throw(:goodmorning_bug)", - "progressId" => 1, + "progressId" => "1", "requestId" => 1, "title" => "Evaluating expression" }) @@ -3679,7 +3755,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do ) ) - assert_receive(event(_, "progressEnd", %{"progressId" => 1})) + assert_receive(event(_, "progressEnd", %{"progressId" => "1"})) assert Process.alive?(server) end) @@ -3687,7 +3763,11 @@ defmodule ElixirLS.DebugAdapter.ServerTest do test "evaluate expression which has long execution", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{"supportsProgressReporting" => true})) + Server.receive_packet( + server, + initialize_req_(1, %{initialize_req_args() | supports_progress_reporting: true}) + ) + assert_receive(response(_, 1, "initialize", _)) Server.receive_packet( @@ -3700,7 +3780,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", %{}), 5000) + assert_receive(response(_, 2, "launch"), 5000) Server.receive_packet( server, @@ -3711,7 +3791,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do event(_, "progressStart", %{ "cancellable" => true, "message" => ":timer.sleep(10_000)", - "progressId" => 1, + "progressId" => "1", "requestId" => 1, "title" => "Evaluating expression" }) @@ -3719,10 +3799,10 @@ defmodule ElixirLS.DebugAdapter.ServerTest do Server.receive_packet( server, - cancel_req(2, %{"progressId" => 1}) + cancel_req(2, %{"progressId" => "1"}) ) - assert_receive(response(_, 2, "cancel", _)) + assert_receive(response(_, 2, "cancel")) assert_receive( error_response( @@ -3737,7 +3817,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do ) ) - assert_receive(event(_, "progressEnd", %{"progressId" => 1})) + assert_receive(event(_, "progressEnd", %{"progressId" => "1"})) assert Process.alive?(server) end) @@ -3747,7 +3827,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do server: server } do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{})) + Server.receive_packet(server, initialize_req_(1)) assert_receive(response(_, 1, "initialize", _)) Server.receive_packet( @@ -3760,7 +3840,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do }) ) - assert_receive(response(_, 2, "launch", %{}), 5000) + assert_receive(response(_, 2, "launch"), 5000) Server.receive_packet( server, @@ -3771,7 +3851,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do event(_, "progressStart", %{ "cancellable" => true, "message" => ":timer.sleep(10_000)", - "progressId" => 1, + "progressId" => "1", "requestId" => 1, "title" => "Evaluating expression" }) @@ -3782,7 +3862,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do cancel_req(2, %{"requestId" => 1}) ) - assert_receive(response(_, 2, "cancel", _)) + assert_receive(response(_, 2, "cancel")) assert_receive( error_response( @@ -3797,7 +3877,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do ) ) - refute_receive(event(_, "progressEnd", %{"progressId" => 1})) + refute_receive(event(_, "progressEnd", %{"progressId" => "1"})) assert Process.alive?(server) end) @@ -3806,7 +3886,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do test "completions", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{})) + Server.receive_packet(server, initialize_req_(1)) assert_receive(response(_, 1, "initialize", _)) Server.receive_packet( @@ -3830,7 +3910,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do test "completions cancel", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{})) + Server.receive_packet(server, initialize_req_(1)) assert_receive(response(_, 1, "initialize", _)) Server.receive_packet( @@ -3851,7 +3931,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do cancel_req(2, %{"requestId" => 1}) ) - assert_receive(response(_, 2, "cancel", _)) + assert_receive(response(_, 2, "cancel")) assert_receive( error_response( @@ -3872,7 +3952,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do test "cancel not existing request", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{})) + Server.receive_packet(server, initialize_req_(1)) assert_receive(response(_, 1, "initialize", _)) Server.receive_packet( @@ -3899,7 +3979,7 @@ defmodule ElixirLS.DebugAdapter.ServerTest do test "source", %{server: server} do in_fixture(__DIR__, "mix_project", fn -> - Server.receive_packet(server, initialize_req(1, %{})) + Server.receive_packet(server, initialize_req_(1)) assert_receive(response(_, 1, "initialize", _)) Server.receive_packet( diff --git a/apps/debug_adapter/lib/debug_adapter/protocol.ex b/apps/debug_adapter/test/support/protocol.ex similarity index 100% rename from apps/debug_adapter/lib/debug_adapter/protocol.ex rename to apps/debug_adapter/test/support/protocol.ex diff --git a/apps/elixir_ls_utils/lib/completion_engine.ex b/apps/elixir_ls_utils/lib/completion_engine.ex index d910c4555..5a41f2519 100644 --- a/apps/elixir_ls_utils/lib/completion_engine.ex +++ b/apps/elixir_ls_utils/lib/completion_engine.ex @@ -1398,8 +1398,6 @@ defmodule ElixirLS.Utils.CompletionEngine do end end - defp get_struct_info(_, _metadata), do: {"", %{}} - defp match_map_fields(fields, hint, type, %State.Env{} = _env, %Metadata{} = metadata) do {subtype, origin, types, doc, meta} = case type do diff --git a/apps/language_server/lib/language_server/application.ex b/apps/language_server/lib/language_server/application.ex index 41d0b7e01..36c06e6d8 100644 --- a/apps/language_server/lib/language_server/application.ex +++ b/apps/language_server/lib/language_server/application.ex @@ -44,6 +44,7 @@ defmodule ElixirLS.LanguageServer.Application do :ok end + @spec restart() :: no_return() def restart() do Application.put_env(:language_server, :restart, true) System.halt(0) diff --git a/apps/language_server/lib/language_server/ast_utils.ex b/apps/language_server/lib/language_server/ast_utils.ex index cbcb3fb94..59c2f0564 100644 --- a/apps/language_server/lib/language_server/ast_utils.ex +++ b/apps/language_server/lib/language_server/ast_utils.ex @@ -1,7 +1,7 @@ # This code has originally been a part of https://github.com/elixir-lsp/elixir_sense defmodule ElixirLS.LanguageServer.AstUtils do - import ElixirLS.LanguageServer.Protocol + import ElixirLS.LanguageServer.RangeUtils alias ElixirLS.LanguageServer.SourceFile @binary_operators ~w[| . ** * / + - ++ -- +++ --- .. <> in |> <<< >>> <<~ ~>> <~ ~> <~> < > <= >= == != === !== =~ && &&& and || ||| or = => :: when <- -> \\]a diff --git a/apps/language_server/lib/language_server/build.ex b/apps/language_server/lib/language_server/build.ex index bd5f0b493..aa5d76948 100644 --- a/apps/language_server/lib/language_server/build.ex +++ b/apps/language_server/lib/language_server/build.ex @@ -138,7 +138,21 @@ defmodule ElixirLS.LanguageServer.Build do :ok catch kind, err -> - {payload, stacktrace} = Exception.blame(kind, err, __STACKTRACE__) + stacktrace = __STACKTRACE__ + + {payload, stacktrace} = + try do + Exception.blame(kind, err, stacktrace) + catch + kind_1, error_1 -> + # in case of error in Exception.blame we want to use the original error and stacktrace + Logger.error( + "Exception.blame failed: #{Exception.format(kind_1, error_1, __STACKTRACE__)}" + ) + + {err, stacktrace} + end + {:error, kind, payload, stacktrace} end end) @@ -300,7 +314,21 @@ defmodule ElixirLS.LanguageServer.Build do :ok catch kind, err -> - {payload, stacktrace} = Exception.blame(kind, err, __STACKTRACE__) + stacktrace = __STACKTRACE__ + + {payload, stacktrace} = + try do + Exception.blame(kind, err, stacktrace) + catch + kind_1, error_1 -> + # in case of error in Exception.blame we want to use the original error and stacktrace + Logger.error( + "Exception.blame failed: #{Exception.format(kind_1, error_1, __STACKTRACE__)}" + ) + + {err, stacktrace} + end + {:error, kind, payload, stacktrace} end end) @@ -360,7 +388,21 @@ defmodule ElixirLS.LanguageServer.Build do :ok catch kind, err -> - {payload, stacktrace} = Exception.blame(kind, err, __STACKTRACE__) + stacktrace = __STACKTRACE__ + + {payload, stacktrace} = + try do + Exception.blame(kind, err, stacktrace) + catch + kind_1, error_1 -> + # in case of error in Exception.blame we want to use the original error and stacktrace + Logger.error( + "Exception.blame failed: #{Exception.format(kind_1, error_1, __STACKTRACE__)}" + ) + + {err, stacktrace} + end + {:error, kind, payload, stacktrace} after # reset log config @@ -434,7 +476,21 @@ defmodule ElixirLS.LanguageServer.Build do Mix.Project.deps_paths() catch kind, payload -> - {payload, stacktrace} = Exception.blame(kind, payload, __STACKTRACE__) + stacktrace = __STACKTRACE__ + + {payload, stacktrace} = + try do + Exception.blame(kind, payload, stacktrace) + catch + kind_1, error_1 -> + # in case of error in Exception.blame we want to use the original error and stacktrace + Logger.error( + "Exception.blame failed: #{Exception.format(kind_1, error_1, __STACKTRACE__)}" + ) + + {payload, stacktrace} + end + message = Exception.format(kind, payload, stacktrace) Logger.warning("Unable to prune mix project: #{message}") [] @@ -448,7 +504,21 @@ defmodule ElixirLS.LanguageServer.Build do end) catch kind, payload -> - {payload, stacktrace} = Exception.blame(kind, payload, __STACKTRACE__) + stacktrace = __STACKTRACE__ + + {payload, stacktrace} = + try do + Exception.blame(kind, payload, stacktrace) + catch + kind_1, error_1 -> + # in case of error in Exception.blame we want to use the original error and stacktrace + Logger.error( + "Exception.blame failed: #{Exception.format(kind_1, error_1, __STACKTRACE__)}" + ) + + {payload, stacktrace} + end + message = Exception.format(kind, payload, stacktrace) Logger.warning("Unable to prune mix project module for #{app}: #{message}") nil diff --git a/apps/language_server/lib/language_server/client_capabilities.ex b/apps/language_server/lib/language_server/client_capabilities.ex new file mode 100644 index 000000000..713f704b7 --- /dev/null +++ b/apps/language_server/lib/language_server/client_capabilities.ex @@ -0,0 +1,193 @@ +defmodule ElixirLS.LanguageServer.ClientCapabilities do + @moduledoc """ + Utilities for checking client capabilities from LSP client capabilities. + + This module provides a centralized way to store and access client capabilities + using persistent_term for efficient access across the application. + """ + + @capabilities_key :language_server_client_capabilities + + @doc """ + Stores the client capabilities in persistent_term for global access. + """ + def store(client_capabilities) do + :persistent_term.put(@capabilities_key, client_capabilities) + end + + @doc """ + Retrieves the stored client capabilities from persistent_term. + Returns nil if no capabilities have been stored. + """ + def get do + :persistent_term.get(@capabilities_key, nil) + end + + @doc """ + Checks if the client supports hierarchical document symbols. + """ + def hierarchical_document_symbol_support? do + case get() do + %GenLSP.Structures.ClientCapabilities{ + text_document: %GenLSP.Structures.TextDocumentClientCapabilities{ + document_symbol: %GenLSP.Structures.DocumentSymbolClientCapabilities{ + hierarchical_document_symbol_support: hierarchical_document_symbol_support + } + } + } -> + hierarchical_document_symbol_support + + _ -> + false + end + end + + @doc """ + Checks if the client supports snippets in completion items. + """ + def snippets_supported? do + case get() do + %GenLSP.Structures.ClientCapabilities{ + text_document: %GenLSP.Structures.TextDocumentClientCapabilities{ + completion: %GenLSP.Structures.CompletionClientCapabilities{ + completion_item: %{snippet_support: snippet_support} + } + } + } -> + snippet_support + + _ -> + false + end + end + + @doc """ + Checks if the client supports deprecated completion items. + + Note: deprecated as of Language Server Protocol Specification - 3.15 + """ + def deprecated_supported? do + case get() do + %GenLSP.Structures.ClientCapabilities{ + text_document: %GenLSP.Structures.TextDocumentClientCapabilities{ + completion: %GenLSP.Structures.CompletionClientCapabilities{ + completion_item: %{deprecated_support: deprecated_support} + } + } + } -> + deprecated_support + + _ -> + false + end + end + + @doc """ + Returns the list of supported completion item tags, or empty list if not supported. + """ + def tags_supported do + case get() do + %GenLSP.Structures.ClientCapabilities{ + text_document: %GenLSP.Structures.TextDocumentClientCapabilities{ + completion: %GenLSP.Structures.CompletionClientCapabilities{ + completion_item: %{tag_support: %{value_set: value_set}} + } + } + } -> + value_set + + _ -> + [] + end + end + + @doc """ + Checks if the client supports signature help. + """ + def signature_help_supported? do + case get() do + %GenLSP.Structures.ClientCapabilities{ + text_document: %GenLSP.Structures.TextDocumentClientCapabilities{ + signature_help: %GenLSP.Structures.SignatureHelpClientCapabilities{} + } + } -> + true + + _ -> + false + end + end + + @doc """ + Checks if the client supports dynamic registration for workspace/didChangeConfiguration. + """ + def supports_dynamic_configuration_change_registration? do + case get() do + %GenLSP.Structures.ClientCapabilities{ + workspace: %GenLSP.Structures.WorkspaceClientCapabilities{ + did_change_configuration: %GenLSP.Structures.DidChangeConfigurationClientCapabilities{ + dynamic_registration: dynamic_registration + } + } + } -> + dynamic_registration + + _ -> + false + end + end + + @doc """ + Checks if the client supports dynamic registration for workspace/didChangeWatchedFiles. + """ + def supports_dynamic_file_watcher_registration? do + case get() do + %GenLSP.Structures.ClientCapabilities{ + workspace: %GenLSP.Structures.WorkspaceClientCapabilities{ + did_change_watched_files: %GenLSP.Structures.DidChangeWatchedFilesClientCapabilities{ + dynamic_registration: dynamic_registration + } + } + } -> + dynamic_registration + + _ -> + false + end + end + + @doc """ + Checks if the client supports workspace/configuration requests. + """ + def supports_configuration? do + case get() do + %GenLSP.Structures.ClientCapabilities{ + workspace: %GenLSP.Structures.WorkspaceClientCapabilities{ + configuration: configuration + } + } -> + configuration + + _ -> + false + end + end + + @doc """ + Checks if the client supports workspace symbol tags. + """ + def workspace_symbol_tag_support? do + case get() do + %GenLSP.Structures.ClientCapabilities{ + workspace: %GenLSP.Structures.WorkspaceClientCapabilities{ + symbol: %{tag_support: tag_support} + } + } + when tag_support != nil -> + true + + _ -> + false + end + end +end diff --git a/apps/language_server/lib/language_server/code_unit.ex b/apps/language_server/lib/language_server/code_unit.ex index f7a2190f7..edb9aac50 100644 --- a/apps/language_server/lib/language_server/code_unit.ex +++ b/apps/language_server/lib/language_server/code_unit.ex @@ -18,7 +18,8 @@ defmodule ElixirLS.LanguageServer.CodeUnit do @type utf8_offset :: non_neg_integer() @type utf16_offset :: non_neg_integer() - @type error :: {:error, :misaligned} | {:error, :out_of_bounds} + @type error :: + {:error, :misaligned} | {:error, :out_of_bounds} | {:error, :invalid_surrogate_position} # public @@ -130,51 +131,65 @@ defmodule ElixirLS.LanguageServer.CodeUnit do # UTF-8 - defp do_utf8_offset(_, 0, offset) do - offset - end + # Walk the UTF-8 bytes, consuming whole codepoints one-by-one. + # If the requested utf16 “remaining” lands in the middle of a + # 2-unit surrogate pair, we clamp back to the start of that codepoint. - defp do_utf8_offset(<<>>, _, offset) do - # this clause pegs the offset at the end of the string - # no matter the character index - offset - end + defp do_utf8_offset(_, 0, offset), do: offset + + defp do_utf8_offset(<<>>, _remaining, offset), do: offset - defp do_utf8_offset(<>, remaining, offset) when c < 128 do + defp do_utf8_offset(<>, remaining, offset) when c < 0x80 do do_utf8_offset(rest, remaining - 1, offset + 1) end defp do_utf8_offset(<>, remaining, offset) do s = <> - increment = utf8_size(s) - decrement = utf16_size(s) - do_utf8_offset(rest, remaining - decrement, offset + increment) - end + # 1 for BMP, 2 for supplementary + size16 = utf16_size(s) + size8 = byte_size(s) - defp do_to_utf8(_, 0, utf8_unit) do - {:ok, utf8_unit} - end + cond do + remaining < size16 and remaining > 0 -> + # landed inside a surrogate pair → clamp to before the pair + offset - defp do_to_utf8(_, utf_16_units, _) when utf_16_units < 0 do - {:error, :misaligned} + true -> + # either we have enough to consume the whole codepoint, or remaining <= 0 + do_utf8_offset(rest, remaining - size16, offset + size8) + end end - defp do_to_utf8(<<>>, _remaining, _utf8_unit) do - {:error, :out_of_bounds} - end + # at exactly zero we’re done + defp do_to_utf8(_, 0, utf8_unit), do: {:ok, utf8_unit} - defp do_to_utf8(<>, utf16_unit, utf8_unit) when c < 128 do - do_to_utf8(rest, utf16_unit - 1, utf8_unit + 1) + # before the start → misaligned + defp do_to_utf8(_, utf16_units, _) when utf16_units < 0 do + {:error, :misaligned} end - defp do_to_utf8(<>, utf16_unit, utf8_unit) do - utf8_code_units = byte_size(<>) - utf16_code_units = utf16_size(<>) + # ran off the end → out_of_bounds + defp do_to_utf8(<<>>, _remaining, _utf8_unit), do: {:error, :out_of_bounds} - do_to_utf8(rest, utf16_unit - utf16_code_units, utf8_unit + utf8_code_units) + # ASCII fast-path + defp do_to_utf8(<>, utf16_units, utf8_unit) when c < 0x80 do + do_to_utf8(rest, utf16_units - 1, utf8_unit + 1) end - defp utf8_size(binary) when is_binary(binary) do - byte_size(binary) + # Multi-byte path – detect mid-surrogate and error + defp do_to_utf8(<>, utf16_units, utf8_unit) do + s = <> + size8 = byte_size(s) + size16 = utf16_size(s) + + cond do + utf16_units < size16 and utf16_units > 0 -> + # asking for the 2nd code‐unit of a surrogate pair → invalid + {:error, :invalid_surrogate_position} + + true -> + # consume it and keep going + do_to_utf8(rest, utf16_units - size16, utf8_unit + size8) + end end end diff --git a/apps/language_server/lib/language_server/diagnostics.ex b/apps/language_server/lib/language_server/diagnostics.ex index f1e621c6d..4644437fc 100644 --- a/apps/language_server/lib/language_server/diagnostics.ex +++ b/apps/language_server/lib/language_server/diagnostics.ex @@ -4,6 +4,7 @@ defmodule ElixirLS.LanguageServer.Diagnostics do from various sources """ alias ElixirLS.LanguageServer.{SourceFile, JsonRpc} + import ElixirLS.LanguageServer.RangeUtils require Logger @enforce_keys [:file, :severity, :message, :position, :compiler_name] @@ -311,68 +312,75 @@ defmodule ElixirLS.LanguageServer.Diagnostics do end def publish_file_diagnostics(uri, uri_diagnostics, source_file, version) do - diagnostics_json = + diagnostics = for %__MODULE__{} = diagnostic <- uri_diagnostics do severity = case diagnostic.severity do :error -> - 1 + GenLSP.Enumerations.DiagnosticSeverity.error() :warning -> - 2 + GenLSP.Enumerations.DiagnosticSeverity.warning() :information -> - 3 + GenLSP.Enumerations.DiagnosticSeverity.information() :hint -> - 4 + GenLSP.Enumerations.DiagnosticSeverity.hint() other -> Logger.warning( "Invalid severity on diagnostic: #{inspect(other)}, using warning level" ) - 2 + GenLSP.Enumerations.DiagnosticSeverity.warning() end - %{ - "message" => diagnostic.message, - "severity" => severity, - "range" => range(normalize_position(diagnostic), source_file), - "source" => diagnostic.compiler_name, - "relatedInformation" => build_related_information(diagnostic, uri, source_file), - "tags" => get_tags(diagnostic) + related_information = + build_related_information(diagnostic, uri, source_file) + + %GenLSP.Structures.Diagnostic{ + message: diagnostic.message, + severity: severity, + range: range(normalize_position(diagnostic), source_file), + source: diagnostic.compiler_name, + related_information: related_information, + tags: get_tags(diagnostic) } end - |> Enum.sort_by(& &1["range"]["start"]) + |> Enum.sort_by(fn diag -> {diag.range.start.line, diag.range.start.character} end) |> Enum.dedup() - message = %{ - "uri" => uri, - "diagnostics" => diagnostics_json + params = %GenLSP.Structures.PublishDiagnosticsParams{ + uri: uri, + diagnostics: diagnostics } - message = + params = if is_integer(version) do - Map.put(message, "version", version) + %{params | version: version} else - message + params end - JsonRpc.notify("textDocument/publishDiagnostics", message) + notification = %GenLSP.Notifications.TextDocumentPublishDiagnostics{ + params: params + } + + JsonRpc.notify(notification) end defp get_tags(diagnostic) do unused = if Regex.match?(~r/unused|no effect/u, diagnostic.message) do - [1] + [GenLSP.Enumerations.DiagnosticTag.unnecessary()] else [] end deprecated = if Regex.match?(~r/deprecated/u, diagnostic.message) do - [2] + [GenLSP.Enumerations.DiagnosticTag.deprecated()] else [] end @@ -404,12 +412,12 @@ defmodule ElixirLS.LanguageServer.Diagnostics do if line do [ - %{ - "location" => %{ - "uri" => uri, - "range" => range(line, source_file) + %GenLSP.Structures.DiagnosticRelatedInformation{ + location: %GenLSP.Structures.Location{ + uri: uri, + range: range(line, source_file) }, - "message" => message + message: message } ] else @@ -438,12 +446,12 @@ defmodule ElixirLS.LanguageServer.Diagnostics do if line do [ - %{ - "location" => %{ - "uri" => uri, - "range" => range(line, source_file) + %GenLSP.Structures.DiagnosticRelatedInformation{ + location: %GenLSP.Structures.Location{ + uri: uri, + range: range(line, source_file) }, - "message" => "related" + message: "related" } ] else @@ -483,16 +491,12 @@ defmodule ElixirLS.LanguageServer.Diagnostics do message = "given type: #{trace.formatted_type}" - %{ - "location" => %{ - "uri" => uri, - "range" => - range( - {line || 1, column || 1}, - source_file - ) + %GenLSP.Structures.DiagnosticRelatedInformation{ + location: %GenLSP.Structures.Location{ + uri: uri, + range: range({line || 1, column || 1}, source_file) }, - "message" => message + message: message } end end @@ -500,53 +504,53 @@ defmodule ElixirLS.LanguageServer.Diagnostics do # for backwards compatibility with elixir < 1.16 {:error, %kind{} = payload} when kind == MismatchedDelimiterError -> [ - %{ - "location" => %{ - "uri" => uri, - "range" => + %GenLSP.Structures.DiagnosticRelatedInformation{ + location: %GenLSP.Structures.Location{ + uri: uri, + range: range( {payload.line, payload.column, payload.line, payload.column + String.length(to_string(payload.opening_delimiter))}, source_file ) }, - "message" => "opening delimiter: #{payload.opening_delimiter}" + message: "opening delimiter: #{payload.opening_delimiter}" }, - %{ - "location" => %{ - "uri" => uri, - "range" => + %GenLSP.Structures.DiagnosticRelatedInformation{ + location: %GenLSP.Structures.Location{ + uri: uri, + range: range( {payload.end_line, payload.end_column, payload.end_line, payload.end_column + String.length(to_string(payload.closing_delimiter))}, source_file ) }, - "message" => "closing delimiter: #{payload.closing_delimiter}" + message: "closing delimiter: #{payload.closing_delimiter}" } ] {:error, %kind{opening_delimiter: opening_delimiter} = payload} when kind == TokenMissingError and not is_nil(opening_delimiter) -> [ - %{ - "location" => %{ - "uri" => uri, - "range" => + %GenLSP.Structures.DiagnosticRelatedInformation{ + location: %GenLSP.Structures.Location{ + uri: uri, + range: range( {payload.line, payload.column, payload.line, payload.column + String.length(to_string(payload.opening_delimiter))}, source_file ) }, - "message" => "opening delimiter: #{payload.opening_delimiter}" + message: "opening delimiter: #{payload.opening_delimiter}" }, - %{ - "location" => %{ - "uri" => uri, - "range" => range({payload.end_line, payload.end_column}, source_file) + %GenLSP.Structures.DiagnosticRelatedInformation{ + location: %GenLSP.Structures.Location{ + uri: uri, + range: range({payload.end_line, payload.end_column}, source_file) }, - "message" => "expected delimiter: #{payload.expected_delimiter}" + message: "expected delimiter: #{payload.expected_delimiter}" } ] @@ -610,16 +614,7 @@ defmodule ElixirLS.LanguageServer.Diagnostics do {0, 0} end - %{ - "start" => %{ - "line" => line_start_lsp, - "character" => char_start_lsp - }, - "end" => %{ - "line" => line_start_lsp, - "character" => char_start_lsp - } - } + range(line_start_lsp, char_start_lsp, line_start_lsp, char_start_lsp) end # position is a 1 based line number and 1 based character cursor (UTF8) @@ -634,16 +629,7 @@ defmodule ElixirLS.LanguageServer.Diagnostics do {line_start_lsp, char_start_lsp} = SourceFile.elixir_position_to_lsp(lines, {line_start, char_start}) - %{ - "start" => %{ - "line" => line_start_lsp, - "character" => char_start_lsp - }, - "end" => %{ - "line" => line_start_lsp, - "character" => char_start_lsp - } - } + range(line_start_lsp, char_start_lsp, line_start_lsp, char_start_lsp) end # position is a range defined by 1 based line numbers and 1 based character cursors (UTF8) @@ -665,16 +651,7 @@ defmodule ElixirLS.LanguageServer.Diagnostics do {line_end_lsp, char_end_lsp} = SourceFile.elixir_position_to_lsp(lines, {line_end, char_end}) - %{ - "start" => %{ - "line" => line_start_lsp, - "character" => char_start_lsp - }, - "end" => %{ - "line" => line_end_lsp, - "character" => char_end_lsp - } - } + range(line_start_lsp, char_start_lsp, line_end_lsp, char_end_lsp) end # source file is unknown @@ -682,7 +659,7 @@ defmodule ElixirLS.LanguageServer.Diagnostics do # unfortunately LSP does not allow `null` range so we need to return something defp range(_, _) do # we don't care about utf16 positions here as we send 0 - %{"start" => %{"line" => 0, "character" => 0}, "end" => %{"line" => 0, "character" => 0}} + range(0, 0, 0, 0) end # this utility function is copied from elixir source diff --git a/apps/language_server/lib/language_server/dialyzer.ex b/apps/language_server/lib/language_server/dialyzer.ex index 1ebd0f0cf..71284ae17 100644 --- a/apps/language_server/lib/language_server/dialyzer.ex +++ b/apps/language_server/lib/language_server/dialyzer.ex @@ -85,7 +85,21 @@ defmodule ElixirLS.LanguageServer.Dialyzer do GenServer.call({:global, {parent, __MODULE__}}, {:suggest_contracts, files}, :infinity) catch kind, payload -> - {payload, stacktrace} = Exception.blame(kind, payload, __STACKTRACE__) + stacktrace = __STACKTRACE__ + + {payload, stacktrace} = + try do + Exception.blame(kind, payload, stacktrace) + catch + kind_1, error_1 -> + # in case of error in Exception.blame we want to use the original error and stacktrace + Logger.error( + "Exception.blame failed: #{Exception.format(kind_1, error_1, __STACKTRACE__)}" + ) + + {payload, stacktrace} + end + error_msg = Exception.format(kind, payload, stacktrace) Logger.error("Unable to suggest contracts: #{error_msg}") diff --git a/apps/language_server/lib/language_server/dialyzer_incremental.ex b/apps/language_server/lib/language_server/dialyzer_incremental.ex index 4b3271211..84437ae31 100644 --- a/apps/language_server/lib/language_server/dialyzer_incremental.ex +++ b/apps/language_server/lib/language_server/dialyzer_incremental.ex @@ -45,7 +45,21 @@ defmodule ElixirLS.LanguageServer.DialyzerIncremental do GenServer.call({:global, {parent, __MODULE__}}, {:suggest_contracts, files}, :infinity) catch kind, payload -> - {payload, stacktrace} = Exception.blame(kind, payload, __STACKTRACE__) + stacktrace = __STACKTRACE__ + + {payload, stacktrace} = + try do + Exception.blame(kind, payload, stacktrace) + catch + kind_1, error_1 -> + # in case of error in Exception.blame we want to use the original error and stacktrace + Logger.error( + "Exception.blame failed: #{Exception.format(kind_1, error_1, __STACKTRACE__)}" + ) + + {payload, stacktrace} + end + error_msg = Exception.format(kind, payload, stacktrace) Logger.error("Unable to suggest contracts: #{error_msg}") @@ -102,7 +116,20 @@ defmodule ElixirLS.LanguageServer.DialyzerIncremental do SuccessTypings.suggest_contracts(plt, files) catch :throw = kind, {:dialyzer_error, message} = payload -> - {_payload, stacktrace} = Exception.blame(kind, payload, __STACKTRACE__) + stacktrace = __STACKTRACE__ + + {_payload, stacktrace} = + try do + Exception.blame(kind, payload, stacktrace) + catch + kind_1, error_1 -> + # in case of error in Exception.blame we want to use the original error and stacktrace + Logger.error( + "Exception.blame failed: #{Exception.format(kind_1, error_1, __STACKTRACE__)}" + ) + + {payload, stacktrace} + end Logger.warning( "Unable to load incremental PLT: #{message}\n#{Exception.format_stacktrace(stacktrace)}" @@ -111,7 +138,20 @@ defmodule ElixirLS.LanguageServer.DialyzerIncremental do [] kind, payload -> - {payload, stacktrace} = Exception.blame(kind, payload, __STACKTRACE__) + stacktrace = __STACKTRACE__ + + {payload, stacktrace} = + try do + Exception.blame(kind, payload, stacktrace) + catch + kind_1, error_1 -> + # in case of error in Exception.blame we want to use the original error and stacktrace + Logger.error( + "Exception.blame failed: #{Exception.format(kind_1, error_1, __STACKTRACE__)}" + ) + + {payload, stacktrace} + end Logger.error( "Unexpected error during incremental PLT load: #{Exception.format(kind, payload, stacktrace)}" @@ -362,7 +402,20 @@ defmodule ElixirLS.LanguageServer.DialyzerIncremental do {warnings, dialyzer_plt} catch :throw = kind, {:dialyzer_error, message} = payload -> - {_payload, stacktrace} = Exception.blame(kind, payload, __STACKTRACE__) + stacktrace = __STACKTRACE__ + + {_payload, stacktrace} = + try do + Exception.blame(kind, payload, stacktrace) + catch + kind_1, error_1 -> + # in case of error in Exception.blame we want to use the original error and stacktrace + Logger.error( + "Exception.blame failed: #{Exception.format(kind_1, error_1, __STACKTRACE__)}" + ) + + {payload, stacktrace} + end Logger.error( "Dialyzer error during incremental PLT build: #{message}\n#{Exception.format_stacktrace(stacktrace)}" @@ -371,7 +424,20 @@ defmodule ElixirLS.LanguageServer.DialyzerIncremental do {[], nil} kind, payload -> - {payload, stacktrace} = Exception.blame(kind, payload, __STACKTRACE__) + stacktrace = __STACKTRACE__ + + {payload, stacktrace} = + try do + Exception.blame(kind, payload, stacktrace) + catch + kind_1, error_1 -> + # in case of error in Exception.blame we want to use the original error and stacktrace + Logger.error( + "Exception.blame failed: #{Exception.format(kind_1, error_1, __STACKTRACE__)}" + ) + + {payload, stacktrace} + end Logger.error( "Unexpected error during incremental PLT build: #{Exception.format(kind, payload, stacktrace)}" diff --git a/apps/language_server/lib/language_server/json_rpc.ex b/apps/language_server/lib/language_server/json_rpc.ex index 2de01cd4a..dccc89e17 100644 --- a/apps/language_server/lib/language_server/json_rpc.ex +++ b/apps/language_server/lib/language_server/json_rpc.ex @@ -13,7 +13,6 @@ defmodule ElixirLS.LanguageServer.JsonRpc do @default_server LanguageServer.Server defstruct language_server: @default_server, - next_id: 1, outgoing_requests: %{} ## Macros @@ -87,6 +86,16 @@ defmodule ElixirLS.LanguageServer.JsonRpc do WireProtocol.send(notification(method, params)) end + def notify(%module{} = notification_struct) do + case SchematicV.dump(module.schematic(), notification_struct) do + {:ok, dumped} -> + WireProtocol.send(dumped) + + {:error, error} -> + IO.puts(:stderr, "Error dumping notification: #{inspect(error)}") + end + end + def respond(id, result) do WireProtocol.send(response(id, result)) end @@ -95,18 +104,36 @@ defmodule ElixirLS.LanguageServer.JsonRpc do {code, default_message} = error_code_and_message(type) if data do - WireProtocol.send(error_response(id, code, message || default_message, data)) + {data_payload, data_module} = data + {:ok, dumped} = SchematicV.dump(data_module.schematic(), data_payload) + WireProtocol.send(error_response(id, code, message || default_message, dumped)) else WireProtocol.send(error_response(id, code, message || default_message)) end end def show_message(type, message) do - notify("window/showMessage", %{type: message_type_code(type), message: to_string(message)}) + notification = %GenLSP.Notifications.WindowShowMessage{ + params: %GenLSP.Structures.ShowMessageParams{ + type: message_type_to_genlsp(type), + message: to_string(message) + } + } + + notify(notification) end def log_message(type, message) do - notify("window/logMessage", %{type: message_type_code(type), message: to_string(message)}) + if not String.starts_with?(to_string(message), "Failed to lookup telemetry handlers") do + notification = %GenLSP.Notifications.WindowLogMessage{ + params: %GenLSP.Structures.LogMessageParams{ + type: message_type_to_genlsp(type), + message: to_string(message) + } + } + + notify(notification) + end end def telemetry(name, properties, measurements) do @@ -133,44 +160,75 @@ defmodule ElixirLS.LanguageServer.JsonRpc do "elixir_ls.mix_target" => mix_target } - notify("telemetry/event", %{ - name: name, - properties: Map.merge(common_properties, properties), - measurements: measurements - }) + notification = %GenLSP.Notifications.TelemetryEvent{ + params: %{ + name: name, + properties: Map.merge(common_properties, properties), + measurements: measurements + } + } + + notify(notification) end def register_capability_request(server \\ __MODULE__, server_instance_id, method, options) do - id = server_instance_id <> method <> JasonV.encode!(options) - - send_request(server, "client/registerCapability", %{ - "registrations" => [ - %{ - "id" => :crypto.hash(:sha, id) |> Base.encode16(), - "method" => method, - "registerOptions" => options - } - ] - }) + {options_payload, options_module} = options + {:ok, dumped} = SchematicV.dump(options_module.schematic(), options_payload) + id_string = server_instance_id <> method <> JasonV.encode!(dumped) + registration_id = :crypto.hash(:sha, id_string) |> Base.encode16() + + # Generate a unique request ID + request_id = System.unique_integer([:positive]) + + request = %GenLSP.Requests.ClientRegisterCapability{ + id: request_id, + params: %GenLSP.Structures.RegistrationParams{ + registrations: [ + %GenLSP.Structures.Registration{ + id: registration_id, + method: method, + register_options: options_payload + } + ] + } + } + + send_request(server, request) end def get_configuration_request(server \\ __MODULE__, scope_uri, section) do - send_request(server, "workspace/configuration", %{ - "items" => [ - %{ - "scopeUri" => scope_uri, - "section" => section - } - ] - }) + # Generate a unique request ID + request_id = System.unique_integer([:positive]) + + request = %GenLSP.Requests.WorkspaceConfiguration{ + id: request_id, + params: %GenLSP.Structures.ConfigurationParams{ + items: [ + %GenLSP.Structures.ConfigurationItem{ + scope_uri: scope_uri, + section: section + } + ] + } + } + + send_request(server, request) end def show_message_request(server \\ __MODULE__, type, message, actions) do - send_request(server, "window/showMessageRequest", %{ - "type" => message_type_code(type), - "message" => message, - "actions" => actions - }) + # Generate a unique request ID + request_id = System.unique_integer([:positive]) + + request = %GenLSP.Requests.WindowShowMessageRequest{ + id: request_id, + params: %GenLSP.Structures.ShowMessageRequestParams{ + type: message_type_to_genlsp(type), + message: message, + actions: actions + } + } + + send_request(server, request) end # Used to intercept :user/:standard_io output @@ -193,8 +251,9 @@ defmodule ElixirLS.LanguageServer.JsonRpc do GenServer.call(server, {:packet, packet}, :infinity) end - def send_request(server \\ __MODULE__, method, params) do - GenServer.call(server, {:request, method, params}, :infinity) + def send_request(server \\ __MODULE__, %module{id: id} = request_struct) do + {:ok, dumped} = SchematicV.dump(module.schematic(), request_struct) + GenServer.call(server, {:request, id, dumped, module}, :infinity) end ## Server callbacks @@ -219,37 +278,39 @@ defmodule ElixirLS.LanguageServer.JsonRpc do end @impl GenServer - def handle_call({:packet, response(id, result)}, _from, state) do - %{^id => from} = state.outgoing_requests - GenServer.reply(from, {:ok, result}) - state = update_in(state.outgoing_requests, &Map.delete(&1, id)) - {:reply, :ok, state} - end + def handle_call({:packet, %{"id" => id, "result" => result}}, _from, state) do + %{^id => {from, module}} = state.outgoing_requests + + case SchematicV.unify(module.result(), result) do + {:ok, error_response = %GenLSP.ErrorResponse{}} -> + GenServer.reply(from, {:error, error_response}) + + {:ok, loaded} -> + GenServer.reply(from, {:ok, loaded}) + + {:error, error} -> + GenServer.reply(from, {:error, error}) + end - @impl GenServer - def handle_call({:packet, error_response(id, code, message)}, _from, state) do - %{^id => from} = state.outgoing_requests - GenServer.reply(from, {:error, code, message}) state = update_in(state.outgoing_requests, &Map.delete(&1, id)) {:reply, :ok, state} end @impl GenServer - def handle_call({:request, method, params}, from, state) do - WireProtocol.send(request(state.next_id, method, params)) - state = update_in(state.outgoing_requests, &Map.put(&1, state.next_id, from)) - state = %__MODULE__{state | next_id: state.next_id + 1} + def handle_call({:request, id, dumped, module}, from, state) do + WireProtocol.send(dumped) + state = update_in(state.outgoing_requests, &Map.put(&1, id, {from, module})) {:noreply, state} end ## Helpers - defp message_type_code(type) do + defp message_type_to_genlsp(type) do case type do - :error -> 1 - :warning -> 2 - :info -> 3 - :log -> 4 + :error -> GenLSP.Enumerations.MessageType.error() + :warning -> GenLSP.Enumerations.MessageType.warning() + :info -> GenLSP.Enumerations.MessageType.info() + :log -> GenLSP.Enumerations.MessageType.log() end end diff --git a/apps/language_server/lib/language_server/lsp/protocol/base_types.ex b/apps/language_server/lib/language_server/lsp/protocol/base_types.ex new file mode 100644 index 000000000..4579d8eda --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/base_types.ex @@ -0,0 +1,7 @@ +# codegen: do not edit +defmodule GenLSP.BaseTypes do + @type uri :: String.t() + @type document_uri :: String.t() + @type uinteger :: integer() + @type null :: nil +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/code_action_kind.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/code_action_kind.ex new file mode 100644 index 000000000..9aba15367 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/code_action_kind.ex @@ -0,0 +1,112 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.CodeActionKind do + @moduledoc """ + A set of predefined code action kinds + """ + + @type t :: String.t() + + import SchematicV, warn: false + + @doc """ + Empty kind. + """ + @spec empty() :: String.t() + def empty, do: "" + + @doc """ + Base kind for quickfix actions: 'quickfix' + """ + @spec quick_fix() :: String.t() + def quick_fix, do: "quickfix" + + @doc """ + Base kind for refactoring actions: 'refactor' + """ + @spec refactor() :: String.t() + def refactor, do: "refactor" + + @doc """ + Base kind for refactoring extraction actions: 'refactor.extract' + + Example extract actions: + + - Extract method + - Extract function + - Extract variable + - Extract interface from class + - ... + """ + @spec refactor_extract() :: String.t() + def refactor_extract, do: "refactor.extract" + + @doc """ + Base kind for refactoring inline actions: 'refactor.inline' + + Example inline actions: + + - Inline function + - Inline variable + - Inline constant + - ... + """ + @spec refactor_inline() :: String.t() + def refactor_inline, do: "refactor.inline" + + @doc """ + Base kind for refactoring rewrite actions: 'refactor.rewrite' + + Example rewrite actions: + + - Convert JavaScript function to class + - Add or remove parameter + - Encapsulate field + - Make method static + - Move method to base class + - ... + """ + @spec refactor_rewrite() :: String.t() + def refactor_rewrite, do: "refactor.rewrite" + + @doc """ + Base kind for source actions: `source` + + Source code actions apply to the entire file. + """ + @spec source() :: String.t() + def source, do: "source" + + @doc """ + Base kind for an organize imports source action: `source.organizeImports` + """ + @spec source_organize_imports() :: String.t() + def source_organize_imports, do: "source.organizeImports" + + @doc """ + Base kind for auto-fix source actions: `source.fixAll`. + + Fix all actions automatically fix errors that have a clear fix that do not require user input. + They should not suppress errors or perform unsafe fixes such as generating new types or classes. + + @since 3.15.0 + """ + @spec source_fix_all() :: String.t() + def source_fix_all, do: "source.fixAll" + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + "", + "quickfix", + "refactor", + "refactor.extract", + "refactor.inline", + "refactor.rewrite", + "source", + "source.organizeImports", + "source.fixAll", + str() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/code_action_trigger_kind.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/code_action_trigger_kind.ex new file mode 100644 index 000000000..3dcb115c9 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/code_action_trigger_kind.ex @@ -0,0 +1,36 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.CodeActionTriggerKind do + @moduledoc """ + The reason why code actions were requested. + + @since 3.17.0 + """ + + @type t :: 1 | 2 + + import SchematicV, warn: false + + @doc """ + Code actions were explicitly requested by the user or by an extension. + """ + @spec invoked() :: 1 + def invoked, do: 1 + + @doc """ + Code actions were requested automatically. + + This typically happens when current selection in a file changes, but can + also be triggered when file content changes. + """ + @spec automatic() :: 2 + def automatic, do: 2 + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + 1, + 2 + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/completion_item_kind.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/completion_item_kind.ex new file mode 100644 index 000000000..dac293196 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/completion_item_kind.ex @@ -0,0 +1,142 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.CompletionItemKind do + @moduledoc """ + The kind of a completion entry. + """ + + @type t :: + 1 + | 2 + | 3 + | 4 + | 5 + | 6 + | 7 + | 8 + | 9 + | 10 + | 11 + | 12 + | 13 + | 14 + | 15 + | 16 + | 17 + | 18 + | 19 + | 20 + | 21 + | 22 + | 23 + | 24 + | 25 + + import SchematicV, warn: false + + @spec text() :: 1 + def text, do: 1 + + @spec method() :: 2 + def method, do: 2 + + @spec function() :: 3 + def function, do: 3 + + @spec constructor() :: 4 + def constructor, do: 4 + + @spec field() :: 5 + def field, do: 5 + + @spec variable() :: 6 + def variable, do: 6 + + @spec class() :: 7 + def class, do: 7 + + @spec interface() :: 8 + def interface, do: 8 + + @spec module() :: 9 + def module, do: 9 + + @spec property() :: 10 + def property, do: 10 + + @spec unit() :: 11 + def unit, do: 11 + + @spec value() :: 12 + def value, do: 12 + + @spec enum() :: 13 + def enum, do: 13 + + @spec keyword() :: 14 + def keyword, do: 14 + + @spec snippet() :: 15 + def snippet, do: 15 + + @spec color() :: 16 + def color, do: 16 + + @spec file() :: 17 + def file, do: 17 + + @spec reference() :: 18 + def reference, do: 18 + + @spec folder() :: 19 + def folder, do: 19 + + @spec enum_member() :: 20 + def enum_member, do: 20 + + @spec constant() :: 21 + def constant, do: 21 + + @spec struct() :: 22 + def struct, do: 22 + + @spec event() :: 23 + def event, do: 23 + + @spec operator() :: 24 + def operator, do: 24 + + @spec type_parameter() :: 25 + def type_parameter, do: 25 + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25 + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/completion_item_tag.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/completion_item_tag.ex new file mode 100644 index 000000000..bc42df813 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/completion_item_tag.ex @@ -0,0 +1,27 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.CompletionItemTag do + @moduledoc """ + Completion item tags are extra annotations that tweak the rendering of a completion + item. + + @since 3.15.0 + """ + + @type t :: 1 + + import SchematicV, warn: false + + @doc """ + Render a completion as obsolete, usually using a strike-out. + """ + @spec deprecated() :: 1 + def deprecated, do: 1 + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + 1 + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/completion_trigger_kind.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/completion_trigger_kind.ex new file mode 100644 index 000000000..f54c85646 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/completion_trigger_kind.ex @@ -0,0 +1,40 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.CompletionTriggerKind do + @moduledoc """ + How a completion was triggered + """ + + @type t :: 1 | 2 | 3 + + import SchematicV, warn: false + + @doc """ + Completion was triggered by typing an identifier (24x7 code + complete), manual invocation (e.g Ctrl+Space) or via API. + """ + @spec invoked() :: 1 + def invoked, do: 1 + + @doc """ + Completion was triggered by a trigger character specified by + the `triggerCharacters` properties of the `CompletionRegistrationOptions`. + """ + @spec trigger_character() :: 2 + def trigger_character, do: 2 + + @doc """ + Completion was re-triggered as current completion list is incomplete + """ + @spec trigger_for_incomplete_completions() :: 3 + def trigger_for_incomplete_completions, do: 3 + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + 1, + 2, + 3 + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/diagnostic_severity.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/diagnostic_severity.ex new file mode 100644 index 000000000..798ff73b2 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/diagnostic_severity.ex @@ -0,0 +1,45 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.DiagnosticSeverity do + @moduledoc """ + The diagnostic's severity. + """ + + @type t :: 1 | 2 | 3 | 4 + + import SchematicV, warn: false + + @doc """ + Reports an error. + """ + @spec error() :: 1 + def error, do: 1 + + @doc """ + Reports a warning. + """ + @spec warning() :: 2 + def warning, do: 2 + + @doc """ + Reports an information. + """ + @spec information() :: 3 + def information, do: 3 + + @doc """ + Reports a hint. + """ + @spec hint() :: 4 + def hint, do: 4 + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + 1, + 2, + 3, + 4 + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/diagnostic_tag.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/diagnostic_tag.ex new file mode 100644 index 000000000..c52c91c30 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/diagnostic_tag.ex @@ -0,0 +1,38 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.DiagnosticTag do + @moduledoc """ + The diagnostic tags. + + @since 3.15.0 + """ + + @type t :: 1 | 2 + + import SchematicV, warn: false + + @doc """ + Unused or unnecessary code. + + Clients are allowed to render diagnostics with this tag faded out instead of having + an error squiggle. + """ + @spec unnecessary() :: 1 + def unnecessary, do: 1 + + @doc """ + Deprecated or obsolete code. + + Clients are allowed to rendered diagnostics with this tag strike through. + """ + @spec deprecated() :: 2 + def deprecated, do: 2 + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + 1, + 2 + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/document_diagnostic_report_kind.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/document_diagnostic_report_kind.ex new file mode 100644 index 000000000..822a30379 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/document_diagnostic_report_kind.ex @@ -0,0 +1,35 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.DocumentDiagnosticReportKind do + @moduledoc """ + The document diagnostic report kinds. + + @since 3.17.0 + """ + + @type t :: String.t() + + import SchematicV, warn: false + + @doc """ + A diagnostic report with a full + set of problems. + """ + @spec full() :: String.t() + def full, do: "full" + + @doc """ + A report indicating that the last + returned report is still accurate. + """ + @spec unchanged() :: String.t() + def unchanged, do: "unchanged" + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + "full", + "unchanged" + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/document_highlight_kind.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/document_highlight_kind.ex new file mode 100644 index 000000000..894d51033 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/document_highlight_kind.ex @@ -0,0 +1,38 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.DocumentHighlightKind do + @moduledoc """ + A document highlight kind. + """ + + @type t :: 1 | 2 | 3 + + import SchematicV, warn: false + + @doc """ + A textual occurrence. + """ + @spec text() :: 1 + def text, do: 1 + + @doc """ + Read-access of a symbol, like reading a variable. + """ + @spec read() :: 2 + def read, do: 2 + + @doc """ + Write-access of a symbol, like writing to a variable. + """ + @spec write() :: 3 + def write, do: 3 + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + 1, + 2, + 3 + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/error_codes.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/error_codes.ex new file mode 100644 index 000000000..8f824dbdd --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/error_codes.ex @@ -0,0 +1,50 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.ErrorCodes do + @moduledoc """ + Predefined error codes. + """ + + @type t :: -32700 | -32600 | -32601 | -32602 | -32603 | -32002 | -32001 + + import SchematicV, warn: false + + @spec parse_error() :: -32700 + def parse_error, do: -32700 + + @spec invalid_request() :: -32600 + def invalid_request, do: -32600 + + @spec method_not_found() :: -32601 + def method_not_found, do: -32601 + + @spec invalid_params() :: -32602 + def invalid_params, do: -32602 + + @spec internal_error() :: -32603 + def internal_error, do: -32603 + + @doc """ + Error code indicating that a server received a notification or + request before the server has received the `initialize` request. + """ + @spec server_not_initialized() :: -32002 + def server_not_initialized, do: -32002 + + @spec unknown_error_code() :: -32001 + def unknown_error_code, do: -32001 + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + -32700, + -32600, + -32601, + -32602, + -32603, + -32002, + -32001, + int() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/failure_handling_kind.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/failure_handling_kind.ex new file mode 100644 index 000000000..cc9a09b62 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/failure_handling_kind.ex @@ -0,0 +1,46 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.FailureHandlingKind do + @type t :: String.t() + + import SchematicV, warn: false + + @doc """ + Applying the workspace change is simply aborted if one of the changes provided + fails. All operations executed before the failing operation stay executed. + """ + @spec abort() :: String.t() + def abort, do: "abort" + + @doc """ + All operations are executed transactional. That means they either all + succeed or no changes at all are applied to the workspace. + """ + @spec transactional() :: String.t() + def transactional, do: "transactional" + + @doc """ + If the workspace edit contains only textual file changes they are executed transactional. + If resource changes (create, rename or delete file) are part of the change the failure + handling strategy is abort. + """ + @spec text_only_transactional() :: String.t() + def text_only_transactional, do: "textOnlyTransactional" + + @doc """ + The client tries to undo the operations already executed. But there is no + guarantee that this is succeeding. + """ + @spec undo() :: String.t() + def undo, do: "undo" + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + "abort", + "transactional", + "textOnlyTransactional", + "undo" + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/file_change_type.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/file_change_type.ex new file mode 100644 index 000000000..5202dd008 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/file_change_type.ex @@ -0,0 +1,38 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.FileChangeType do + @moduledoc """ + The file event type + """ + + @type t :: 1 | 2 | 3 + + import SchematicV, warn: false + + @doc """ + The file got created. + """ + @spec created() :: 1 + def created, do: 1 + + @doc """ + The file got changed. + """ + @spec changed() :: 2 + def changed, do: 2 + + @doc """ + The file got deleted. + """ + @spec deleted() :: 3 + def deleted, do: 3 + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + 1, + 2, + 3 + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/file_operation_pattern_kind.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/file_operation_pattern_kind.ex new file mode 100644 index 000000000..b03726725 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/file_operation_pattern_kind.ex @@ -0,0 +1,34 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.FileOperationPatternKind do + @moduledoc """ + A pattern kind describing if a glob pattern matches a file a folder or + both. + + @since 3.16.0 + """ + + @type t :: String.t() + + import SchematicV, warn: false + + @doc """ + The pattern matches a file only. + """ + @spec file() :: String.t() + def file, do: "file" + + @doc """ + The pattern matches a folder only. + """ + @spec folder() :: String.t() + def folder, do: "folder" + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + "file", + "folder" + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/folding_range_kind.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/folding_range_kind.ex new file mode 100644 index 000000000..db7938667 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/folding_range_kind.ex @@ -0,0 +1,39 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.FoldingRangeKind do + @moduledoc """ + A set of predefined range kinds. + """ + + @type t :: String.t() + + import SchematicV, warn: false + + @doc """ + Folding range for a comment + """ + @spec comment() :: String.t() + def comment, do: "comment" + + @doc """ + Folding range for an import or include + """ + @spec imports() :: String.t() + def imports, do: "imports" + + @doc """ + Folding range for a region (e.g. `#region`) + """ + @spec region() :: String.t() + def region, do: "region" + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + "comment", + "imports", + "region", + str() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/inlay_hint_kind.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/inlay_hint_kind.ex new file mode 100644 index 000000000..ec84f2912 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/inlay_hint_kind.ex @@ -0,0 +1,33 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.InlayHintKind do + @moduledoc """ + Inlay hint kinds. + + @since 3.17.0 + """ + + @type t :: 1 | 2 + + import SchematicV, warn: false + + @doc """ + An inlay hint that for a type annotation. + """ + @spec type() :: 1 + def type, do: 1 + + @doc """ + An inlay hint that is for a parameter. + """ + @spec parameter() :: 2 + def parameter, do: 2 + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + 1, + 2 + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/insert_text_format.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/insert_text_format.ex new file mode 100644 index 000000000..987e16949 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/insert_text_format.ex @@ -0,0 +1,39 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.InsertTextFormat do + @moduledoc """ + Defines whether the insert text in a completion item should be interpreted as + plain text or a snippet. + """ + + @type t :: 1 | 2 + + import SchematicV, warn: false + + @doc """ + The primary text to be inserted is treated as a plain string. + """ + @spec plain_text() :: 1 + def plain_text, do: 1 + + @doc """ + The primary text to be inserted is treated as a snippet. + + A snippet can define tab stops and placeholders with `$1`, `$2` + and `${3:foo}`. `$0` defines the final tab stop, it defaults to + the end of the snippet. Placeholders with equal identifiers are linked, + that is typing in one will update others too. + + See also: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#snippet_syntax + """ + @spec snippet() :: 2 + def snippet, do: 2 + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + 1, + 2 + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/insert_text_mode.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/insert_text_mode.ex new file mode 100644 index 000000000..6addf0eb5 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/insert_text_mode.ex @@ -0,0 +1,44 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.InsertTextMode do + @moduledoc """ + How whitespace and indentation is handled during completion + item insertion. + + @since 3.16.0 + """ + + @type t :: 1 | 2 + + import SchematicV, warn: false + + @doc """ + The insertion or replace strings is taken as it is. If the + value is multi line the lines below the cursor will be + inserted using the indentation defined in the string value. + The client will not apply any kind of adjustments to the + string. + """ + @spec as_is() :: 1 + def as_is, do: 1 + + @doc """ + The editor adjusts leading whitespace of new lines so that + they match the indentation up to the cursor of the line for + which the item is accepted. + + Consider a line like this: <2tabs><3tabs>foo. Accepting a + multi line completion item is indented using 2 tabs and all + following lines inserted will be indented using 2 tabs as well. + """ + @spec adjust_indentation() :: 2 + def adjust_indentation, do: 2 + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + 1, + 2 + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/lsp_error_codes.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/lsp_error_codes.ex new file mode 100644 index 000000000..40710d6a9 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/lsp_error_codes.ex @@ -0,0 +1,59 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.LSPErrorCodes do + @type t :: -32803 | -32802 | -32801 | -32800 + + import SchematicV, warn: false + + @doc """ + A request failed but it was syntactically correct, e.g the + method name was known and the parameters were valid. The error + message should contain human readable information about why + the request failed. + + @since 3.17.0 + """ + @spec request_failed() :: -32803 + def request_failed, do: -32803 + + @doc """ + The server cancelled the request. This error code should + only be used for requests that explicitly support being + server cancellable. + + @since 3.17.0 + """ + @spec server_cancelled() :: -32802 + def server_cancelled, do: -32802 + + @doc """ + The server detected that the content of a document got + modified outside normal conditions. A server should + NOT send this error code if it detects a content change + in it unprocessed messages. The result even computed + on an older state might still be useful for the client. + + If a client decides that a result is not of any use anymore + the client should cancel the request. + """ + @spec content_modified() :: -32801 + def content_modified, do: -32801 + + @doc """ + The client has canceled a request and a server as detected + the cancel. + """ + @spec request_cancelled() :: -32800 + def request_cancelled, do: -32800 + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + -32803, + -32802, + -32801, + -32800, + int() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/markup_kind.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/markup_kind.ex new file mode 100644 index 000000000..93d4684cd --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/markup_kind.ex @@ -0,0 +1,35 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.MarkupKind do + @moduledoc """ + Describes the content type that a client supports in various + result literals like `Hover`, `ParameterInfo` or `CompletionItem`. + + Please note that `MarkupKinds` must not start with a `$`. This kinds + are reserved for internal usage. + """ + + @type t :: String.t() + + import SchematicV, warn: false + + @doc """ + Plain text is supported as a content format + """ + @spec plain_text() :: String.t() + def plain_text, do: "plaintext" + + @doc """ + Markdown is supported as a content format + """ + @spec markdown() :: String.t() + def markdown, do: "markdown" + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + "plaintext", + "markdown" + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/message_type.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/message_type.ex new file mode 100644 index 000000000..2313c482a --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/message_type.ex @@ -0,0 +1,45 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.MessageType do + @moduledoc """ + The message type + """ + + @type t :: 1 | 2 | 3 | 4 + + import SchematicV, warn: false + + @doc """ + An error message. + """ + @spec error() :: 1 + def error, do: 1 + + @doc """ + A warning message. + """ + @spec warning() :: 2 + def warning, do: 2 + + @doc """ + An information message. + """ + @spec info() :: 3 + def info, do: 3 + + @doc """ + A log message. + """ + @spec log() :: 4 + def log, do: 4 + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + 1, + 2, + 3, + 4 + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/moniker_kind.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/moniker_kind.ex new file mode 100644 index 000000000..dbd93e29d --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/moniker_kind.ex @@ -0,0 +1,41 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.MonikerKind do + @moduledoc """ + The moniker kind. + + @since 3.16.0 + """ + + @type t :: String.t() + + import SchematicV, warn: false + + @doc """ + The moniker represent a symbol that is imported into a project + """ + @spec import() :: String.t() + def import, do: "import" + + @doc """ + The moniker represents a symbol that is exported from a project + """ + @spec export() :: String.t() + def export, do: "export" + + @doc """ + The moniker represents a symbol that is local to a project (e.g. a local + variable of a function, a class not visible outside the project, ...) + """ + @spec local() :: String.t() + def local, do: "local" + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + "import", + "export", + "local" + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/notebook_cell_kind.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/notebook_cell_kind.ex new file mode 100644 index 000000000..250a54415 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/notebook_cell_kind.ex @@ -0,0 +1,33 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.NotebookCellKind do + @moduledoc """ + A notebook cell kind. + + @since 3.17.0 + """ + + @type t :: 1 | 2 + + import SchematicV, warn: false + + @doc """ + A markup-cell is formatted source that is used for display. + """ + @spec markup() :: 1 + def markup, do: 1 + + @doc """ + A code-cell is source code. + """ + @spec code() :: 2 + def code, do: 2 + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + 1, + 2 + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/position_encoding_kind.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/position_encoding_kind.ex new file mode 100644 index 000000000..dfdc1e940 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/position_encoding_kind.ex @@ -0,0 +1,48 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.PositionEncodingKind do + @moduledoc """ + A set of predefined position encoding kinds. + + @since 3.17.0 + """ + + @type t :: String.t() + + import SchematicV, warn: false + + @doc """ + Character offsets count UTF-8 code units. + """ + @spec utf8() :: String.t() + def utf8, do: "utf-8" + + @doc """ + Character offsets count UTF-16 code units. + + This is the default and must always be supported + by servers + """ + @spec utf16() :: String.t() + def utf16, do: "utf-16" + + @doc """ + Character offsets count UTF-32 code units. + + Implementation note: these are the same as Unicode code points, + so this `PositionEncodingKind` may also be used for an + encoding-agnostic representation of character offsets. + """ + @spec utf32() :: String.t() + def utf32, do: "utf-32" + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + "utf-8", + "utf-16", + "utf-32", + str() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/prepare_support_default_behavior.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/prepare_support_default_behavior.ex new file mode 100644 index 000000000..a0e43b129 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/prepare_support_default_behavior.ex @@ -0,0 +1,21 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.PrepareSupportDefaultBehavior do + @type t :: 1 + + import SchematicV, warn: false + + @doc """ + The client's default behavior is to select the identifier + according the to language's syntax rule. + """ + @spec identifier() :: 1 + def identifier, do: 1 + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + 1 + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/resource_operation_kind.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/resource_operation_kind.ex new file mode 100644 index 000000000..f6d6c87bd --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/resource_operation_kind.ex @@ -0,0 +1,34 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.ResourceOperationKind do + @type t :: String.t() + + import SchematicV, warn: false + + @doc """ + Supports creating new files and folders. + """ + @spec create() :: String.t() + def create, do: "create" + + @doc """ + Supports renaming existing files and folders. + """ + @spec rename() :: String.t() + def rename, do: "rename" + + @doc """ + Supports deleting existing files and folders. + """ + @spec delete() :: String.t() + def delete, do: "delete" + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + "create", + "rename", + "delete" + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/semantic_token_modifiers.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/semantic_token_modifiers.ex new file mode 100644 index 000000000..4b9e98f84 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/semantic_token_modifiers.ex @@ -0,0 +1,62 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.SemanticTokenModifiers do + @moduledoc """ + A set of predefined token modifiers. This set is not fixed + an clients can specify additional token types via the + corresponding client capabilities. + + @since 3.16.0 + """ + + @type t :: String.t() + + import SchematicV, warn: false + + @spec declaration() :: String.t() + def declaration, do: "declaration" + + @spec definition() :: String.t() + def definition, do: "definition" + + @spec readonly() :: String.t() + def readonly, do: "readonly" + + @spec static() :: String.t() + def static, do: "static" + + @spec deprecated() :: String.t() + def deprecated, do: "deprecated" + + @spec abstract() :: String.t() + def abstract, do: "abstract" + + @spec async() :: String.t() + def async, do: "async" + + @spec modification() :: String.t() + def modification, do: "modification" + + @spec documentation() :: String.t() + def documentation, do: "documentation" + + @spec default_library() :: String.t() + def default_library, do: "defaultLibrary" + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + "declaration", + "definition", + "readonly", + "static", + "deprecated", + "abstract", + "async", + "modification", + "documentation", + "defaultLibrary", + str() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/semantic_token_types.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/semantic_token_types.ex new file mode 100644 index 000000000..2e05ec6b0 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/semantic_token_types.ex @@ -0,0 +1,121 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.SemanticTokenTypes do + @moduledoc """ + A set of predefined token types. This set is not fixed + an clients can specify additional token types via the + corresponding client capabilities. + + @since 3.16.0 + """ + + @type t :: String.t() + + import SchematicV, warn: false + + @spec namespace() :: String.t() + def namespace, do: "namespace" + + @doc """ + Represents a generic type. Acts as a fallback for types which can't be mapped to + a specific type like class or enum. + """ + @spec type() :: String.t() + def type, do: "type" + + @spec class() :: String.t() + def class, do: "class" + + @spec enum() :: String.t() + def enum, do: "enum" + + @spec interface() :: String.t() + def interface, do: "interface" + + @spec struct() :: String.t() + def struct, do: "struct" + + @spec type_parameter() :: String.t() + def type_parameter, do: "typeParameter" + + @spec parameter() :: String.t() + def parameter, do: "parameter" + + @spec variable() :: String.t() + def variable, do: "variable" + + @spec property() :: String.t() + def property, do: "property" + + @spec enum_member() :: String.t() + def enum_member, do: "enumMember" + + @spec event() :: String.t() + def event, do: "event" + + @spec function() :: String.t() + def function, do: "function" + + @spec method() :: String.t() + def method, do: "method" + + @spec macro() :: String.t() + def macro, do: "macro" + + @spec keyword() :: String.t() + def keyword, do: "keyword" + + @spec modifier() :: String.t() + def modifier, do: "modifier" + + @spec comment() :: String.t() + def comment, do: "comment" + + @spec string() :: String.t() + def string, do: "string" + + @spec number() :: String.t() + def number, do: "number" + + @spec regexp() :: String.t() + def regexp, do: "regexp" + + @spec operator() :: String.t() + def operator, do: "operator" + + @doc """ + @since 3.17.0 + """ + @spec decorator() :: String.t() + def decorator, do: "decorator" + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + "namespace", + "type", + "class", + "enum", + "interface", + "struct", + "typeParameter", + "parameter", + "variable", + "property", + "enumMember", + "event", + "function", + "method", + "macro", + "keyword", + "modifier", + "comment", + "string", + "number", + "regexp", + "operator", + "decorator", + str() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/signature_help_trigger_kind.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/signature_help_trigger_kind.ex new file mode 100644 index 000000000..654bfcccf --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/signature_help_trigger_kind.ex @@ -0,0 +1,40 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.SignatureHelpTriggerKind do + @moduledoc """ + How a signature help was triggered. + + @since 3.15.0 + """ + + @type t :: 1 | 2 | 3 + + import SchematicV, warn: false + + @doc """ + Signature help was invoked manually by the user or by a command. + """ + @spec invoked() :: 1 + def invoked, do: 1 + + @doc """ + Signature help was triggered by a trigger character. + """ + @spec trigger_character() :: 2 + def trigger_character, do: 2 + + @doc """ + Signature help was triggered by the cursor moving or by the document content changing. + """ + @spec content_change() :: 3 + def content_change, do: 3 + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + 1, + 2, + 3 + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/symbol_kind.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/symbol_kind.ex new file mode 100644 index 000000000..1a7623417 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/symbol_kind.ex @@ -0,0 +1,147 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.SymbolKind do + @moduledoc """ + A symbol kind. + """ + + @type t :: + 1 + | 2 + | 3 + | 4 + | 5 + | 6 + | 7 + | 8 + | 9 + | 10 + | 11 + | 12 + | 13 + | 14 + | 15 + | 16 + | 17 + | 18 + | 19 + | 20 + | 21 + | 22 + | 23 + | 24 + | 25 + | 26 + + import SchematicV, warn: false + + @spec file() :: 1 + def file, do: 1 + + @spec module() :: 2 + def module, do: 2 + + @spec namespace() :: 3 + def namespace, do: 3 + + @spec package() :: 4 + def package, do: 4 + + @spec class() :: 5 + def class, do: 5 + + @spec method() :: 6 + def method, do: 6 + + @spec property() :: 7 + def property, do: 7 + + @spec field() :: 8 + def field, do: 8 + + @spec constructor() :: 9 + def constructor, do: 9 + + @spec enum() :: 10 + def enum, do: 10 + + @spec interface() :: 11 + def interface, do: 11 + + @spec function() :: 12 + def function, do: 12 + + @spec variable() :: 13 + def variable, do: 13 + + @spec constant() :: 14 + def constant, do: 14 + + @spec string() :: 15 + def string, do: 15 + + @spec number() :: 16 + def number, do: 16 + + @spec boolean() :: 17 + def boolean, do: 17 + + @spec array() :: 18 + def array, do: 18 + + @spec object() :: 19 + def object, do: 19 + + @spec key() :: 20 + def key, do: 20 + + @spec null() :: 21 + def null, do: 21 + + @spec enum_member() :: 22 + def enum_member, do: 22 + + @spec struct() :: 23 + def struct, do: 23 + + @spec event() :: 24 + def event, do: 24 + + @spec operator() :: 25 + def operator, do: 25 + + @spec type_parameter() :: 26 + def type_parameter, do: 26 + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26 + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/symbol_tag.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/symbol_tag.ex new file mode 100644 index 000000000..1645ed760 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/symbol_tag.ex @@ -0,0 +1,26 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.SymbolTag do + @moduledoc """ + Symbol tags are extra annotations that tweak the rendering of a symbol. + + @since 3.16 + """ + + @type t :: 1 + + import SchematicV, warn: false + + @doc """ + Render a symbol as obsolete, usually using a strike-out. + """ + @spec deprecated() :: 1 + def deprecated, do: 1 + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + 1 + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/text_document_save_reason.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/text_document_save_reason.ex new file mode 100644 index 000000000..aa4d47afc --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/text_document_save_reason.ex @@ -0,0 +1,39 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.TextDocumentSaveReason do + @moduledoc """ + Represents reasons why a text document is saved. + """ + + @type t :: 1 | 2 | 3 + + import SchematicV, warn: false + + @doc """ + Manually triggered, e.g. by the user pressing save, by starting debugging, + or by an API call. + """ + @spec manual() :: 1 + def manual, do: 1 + + @doc """ + Automatic after a delay. + """ + @spec after_delay() :: 2 + def after_delay, do: 2 + + @doc """ + When the editor lost focus. + """ + @spec focus_out() :: 3 + def focus_out, do: 3 + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + 1, + 2, + 3 + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/text_document_sync_kind.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/text_document_sync_kind.ex new file mode 100644 index 000000000..934846c18 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/text_document_sync_kind.ex @@ -0,0 +1,42 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.TextDocumentSyncKind do + @moduledoc """ + Defines how the host (editor) should sync + document changes to the language server. + """ + + @type t :: 0 | 1 | 2 + + import SchematicV, warn: false + + @doc """ + Documents should not be synced at all. + """ + @spec none() :: 0 + def none, do: 0 + + @doc """ + Documents are synced by always sending the full content + of the document. + """ + @spec full() :: 1 + def full, do: 1 + + @doc """ + Documents are synced by sending the full content on open. + After that only incremental updates to the document are + send. + """ + @spec incremental() :: 2 + def incremental, do: 2 + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + 0, + 1, + 2 + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/token_format.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/token_format.ex new file mode 100644 index 000000000..42d8a2201 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/token_format.ex @@ -0,0 +1,17 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.TokenFormat do + @type t :: String.t() + + import SchematicV, warn: false + + @spec relative() :: String.t() + def relative, do: "relative" + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + "relative" + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/trace_values.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/trace_values.ex new file mode 100644 index 000000000..8d0a0efbf --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/trace_values.ex @@ -0,0 +1,34 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.TraceValues do + @type t :: String.t() + + import SchematicV, warn: false + + @doc """ + Turn tracing off. + """ + @spec off() :: String.t() + def off, do: "off" + + @doc """ + Trace messages only. + """ + @spec messages() :: String.t() + def messages, do: "messages" + + @doc """ + Verbose message tracing. + """ + @spec verbose() :: String.t() + def verbose, do: "verbose" + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + "off", + "messages", + "verbose" + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/uniqueness_level.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/uniqueness_level.ex new file mode 100644 index 000000000..3c792520c --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/uniqueness_level.ex @@ -0,0 +1,54 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.UniquenessLevel do + @moduledoc """ + Moniker uniqueness level to define scope of the moniker. + + @since 3.16.0 + """ + + @type t :: String.t() + + import SchematicV, warn: false + + @doc """ + The moniker is only unique inside a document + """ + @spec document() :: String.t() + def document, do: "document" + + @doc """ + The moniker is unique inside a project for which a dump got created + """ + @spec project() :: String.t() + def project, do: "project" + + @doc """ + The moniker is unique inside the group to which a project belongs + """ + @spec group() :: String.t() + def group, do: "group" + + @doc """ + The moniker is unique inside the moniker scheme. + """ + @spec scheme() :: String.t() + def scheme, do: "scheme" + + @doc """ + The moniker is globally unique + """ + @spec global() :: String.t() + def global, do: "global" + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + "document", + "project", + "group", + "scheme", + "global" + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/enumerations/watch_kind.ex b/apps/language_server/lib/language_server/lsp/protocol/enumerations/watch_kind.ex new file mode 100644 index 000000000..ad17d590f --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/enumerations/watch_kind.ex @@ -0,0 +1,35 @@ +# codegen: do not edit +defmodule GenLSP.Enumerations.WatchKind do + @type t :: 1 | 2 | 4 + + import SchematicV, warn: false + + @doc """ + Interested in create events. + """ + @spec create() :: 1 + def create, do: 1 + + @doc """ + Interested in change events + """ + @spec change() :: 2 + def change, do: 2 + + @doc """ + Interested in delete events + """ + @spec delete() :: 4 + def delete, do: 4 + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + 1, + 2, + 4, + int() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/error_response.ex b/apps/language_server/lib/language_server/lsp/protocol/error_response.ex new file mode 100644 index 000000000..6b17d297c --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/error_response.ex @@ -0,0 +1,28 @@ +# codegen: do not edit +defmodule GenLSP.ErrorResponse do + @moduledoc """ + A Response Message sent as a result of a request. + + If a request doesn’t provide a result value the receiver of a request still needs to return a response message to conform to the JSON-RPC specification. + + The result property of the ResponseMessage should be set to null in this case to signal a successful request. + """ + import SchematicV + + use TypedStruct + + typedstruct do + field(:data, String.t() | number() | boolean() | list() | map() | nil) + field(:code, integer(), enforce: true) + field(:message, String.t(), enforce: true) + end + + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional(:data) => oneof([str(), int(), bool(), list(), map(), nil]), + code: int(), + message: str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/notifications.ex b/apps/language_server/lib/language_server/lsp/protocol/notifications.ex new file mode 100644 index 000000000..d99d1644d --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/notifications.ex @@ -0,0 +1,92 @@ +# codegen: do not edit +defmodule GenLSP.Notifications do + import SchematicV + + def new(notification) do + unify( + oneof(fn + %{"method" => "$/cancelRequest"} -> + GenLSP.Notifications.DollarCancelRequest.schematic() + + %{"method" => "$/logTrace"} -> + GenLSP.Notifications.DollarLogTrace.schematic() + + %{"method" => "$/progress"} -> + GenLSP.Notifications.DollarProgress.schematic() + + %{"method" => "$/setTrace"} -> + GenLSP.Notifications.DollarSetTrace.schematic() + + %{"method" => "exit"} -> + GenLSP.Notifications.Exit.schematic() + + %{"method" => "initialized"} -> + GenLSP.Notifications.Initialized.schematic() + + %{"method" => "notebookDocument/didChange"} -> + GenLSP.Notifications.NotebookDocumentDidChange.schematic() + + %{"method" => "notebookDocument/didClose"} -> + GenLSP.Notifications.NotebookDocumentDidClose.schematic() + + %{"method" => "notebookDocument/didOpen"} -> + GenLSP.Notifications.NotebookDocumentDidOpen.schematic() + + %{"method" => "notebookDocument/didSave"} -> + GenLSP.Notifications.NotebookDocumentDidSave.schematic() + + %{"method" => "telemetry/event"} -> + GenLSP.Notifications.TelemetryEvent.schematic() + + %{"method" => "textDocument/didChange"} -> + GenLSP.Notifications.TextDocumentDidChange.schematic() + + %{"method" => "textDocument/didClose"} -> + GenLSP.Notifications.TextDocumentDidClose.schematic() + + %{"method" => "textDocument/didOpen"} -> + GenLSP.Notifications.TextDocumentDidOpen.schematic() + + %{"method" => "textDocument/didSave"} -> + GenLSP.Notifications.TextDocumentDidSave.schematic() + + %{"method" => "textDocument/publishDiagnostics"} -> + GenLSP.Notifications.TextDocumentPublishDiagnostics.schematic() + + %{"method" => "textDocument/willSave"} -> + GenLSP.Notifications.TextDocumentWillSave.schematic() + + %{"method" => "window/logMessage"} -> + GenLSP.Notifications.WindowLogMessage.schematic() + + %{"method" => "window/showMessage"} -> + GenLSP.Notifications.WindowShowMessage.schematic() + + %{"method" => "window/workDoneProgress/cancel"} -> + GenLSP.Notifications.WindowWorkDoneProgressCancel.schematic() + + %{"method" => "workspace/didChangeConfiguration"} -> + GenLSP.Notifications.WorkspaceDidChangeConfiguration.schematic() + + %{"method" => "workspace/didChangeWatchedFiles"} -> + GenLSP.Notifications.WorkspaceDidChangeWatchedFiles.schematic() + + %{"method" => "workspace/didChangeWorkspaceFolders"} -> + GenLSP.Notifications.WorkspaceDidChangeWorkspaceFolders.schematic() + + %{"method" => "workspace/didCreateFiles"} -> + GenLSP.Notifications.WorkspaceDidCreateFiles.schematic() + + %{"method" => "workspace/didDeleteFiles"} -> + GenLSP.Notifications.WorkspaceDidDeleteFiles.schematic() + + %{"method" => "workspace/didRenameFiles"} -> + GenLSP.Notifications.WorkspaceDidRenameFiles.schematic() + + _ -> + {:error, "unexpected notification payload"} + end), + notification + ) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/notifications/dollar_cancel_request.ex b/apps/language_server/lib/language_server/lsp/protocol/notifications/dollar_cancel_request.ex new file mode 100644 index 000000000..42d82b099 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/notifications/dollar_cancel_request.ex @@ -0,0 +1,22 @@ +# codegen: do not edit +defmodule GenLSP.Notifications.DollarCancelRequest do + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "$/cancelRequest") + field(:jsonrpc, String.t(), default: "2.0") + field(:params, GenLSP.Structures.CancelParams.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "$/cancelRequest", + jsonrpc: "2.0", + params: GenLSP.Structures.CancelParams.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/notifications/dollar_log_trace.ex b/apps/language_server/lib/language_server/lsp/protocol/notifications/dollar_log_trace.ex new file mode 100644 index 000000000..63d8822d0 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/notifications/dollar_log_trace.ex @@ -0,0 +1,22 @@ +# codegen: do not edit +defmodule GenLSP.Notifications.DollarLogTrace do + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "$/logTrace") + field(:jsonrpc, String.t(), default: "2.0") + field(:params, GenLSP.Structures.LogTraceParams.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "$/logTrace", + jsonrpc: "2.0", + params: GenLSP.Structures.LogTraceParams.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/notifications/dollar_progress.ex b/apps/language_server/lib/language_server/lsp/protocol/notifications/dollar_progress.ex new file mode 100644 index 000000000..b8a7327a8 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/notifications/dollar_progress.ex @@ -0,0 +1,22 @@ +# codegen: do not edit +defmodule GenLSP.Notifications.DollarProgress do + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "$/progress") + field(:jsonrpc, String.t(), default: "2.0") + field(:params, GenLSP.Structures.ProgressParams.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "$/progress", + jsonrpc: "2.0", + params: GenLSP.Structures.ProgressParams.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/notifications/dollar_set_trace.ex b/apps/language_server/lib/language_server/lsp/protocol/notifications/dollar_set_trace.ex new file mode 100644 index 000000000..9cf6863b5 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/notifications/dollar_set_trace.ex @@ -0,0 +1,22 @@ +# codegen: do not edit +defmodule GenLSP.Notifications.DollarSetTrace do + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "$/setTrace") + field(:jsonrpc, String.t(), default: "2.0") + field(:params, GenLSP.Structures.SetTraceParams.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "$/setTrace", + jsonrpc: "2.0", + params: GenLSP.Structures.SetTraceParams.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/notifications/exit.ex b/apps/language_server/lib/language_server/lsp/protocol/notifications/exit.ex new file mode 100644 index 000000000..ec0331894 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/notifications/exit.ex @@ -0,0 +1,29 @@ +# codegen: do not edit +defmodule GenLSP.Notifications.Exit do + @moduledoc """ + The exit event is sent from the client to the server to + ask the server to exit its process. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "exit") + field(:jsonrpc, String.t(), default: "2.0") + field(:params, nil) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "exit", + jsonrpc: "2.0", + params: nil + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/notifications/initialized.ex b/apps/language_server/lib/language_server/lsp/protocol/notifications/initialized.ex new file mode 100644 index 000000000..056a379b3 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/notifications/initialized.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Notifications.Initialized do + @moduledoc """ + The initialized notification is sent from the client to the + server after the client is fully initialized and the server + is allowed to send requests from the server to the client. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "initialized") + field(:jsonrpc, String.t(), default: "2.0") + field(:params, GenLSP.Structures.InitializedParams.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "initialized", + jsonrpc: "2.0", + params: GenLSP.Structures.InitializedParams.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/notifications/notebook_document_did_change.ex b/apps/language_server/lib/language_server/lsp/protocol/notifications/notebook_document_did_change.ex new file mode 100644 index 000000000..9849e7f67 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/notifications/notebook_document_did_change.ex @@ -0,0 +1,22 @@ +# codegen: do not edit +defmodule GenLSP.Notifications.NotebookDocumentDidChange do + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "notebookDocument/didChange") + field(:jsonrpc, String.t(), default: "2.0") + field(:params, GenLSP.Structures.DidChangeNotebookDocumentParams.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "notebookDocument/didChange", + jsonrpc: "2.0", + params: GenLSP.Structures.DidChangeNotebookDocumentParams.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/notifications/notebook_document_did_close.ex b/apps/language_server/lib/language_server/lsp/protocol/notifications/notebook_document_did_close.ex new file mode 100644 index 000000000..a5bebdd8e --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/notifications/notebook_document_did_close.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Notifications.NotebookDocumentDidClose do + @moduledoc """ + A notification sent when a notebook closes. + + @since 3.17.0 + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "notebookDocument/didClose") + field(:jsonrpc, String.t(), default: "2.0") + field(:params, GenLSP.Structures.DidCloseNotebookDocumentParams.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "notebookDocument/didClose", + jsonrpc: "2.0", + params: GenLSP.Structures.DidCloseNotebookDocumentParams.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/notifications/notebook_document_did_open.ex b/apps/language_server/lib/language_server/lsp/protocol/notifications/notebook_document_did_open.ex new file mode 100644 index 000000000..e7bb69c65 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/notifications/notebook_document_did_open.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Notifications.NotebookDocumentDidOpen do + @moduledoc """ + A notification sent when a notebook opens. + + @since 3.17.0 + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "notebookDocument/didOpen") + field(:jsonrpc, String.t(), default: "2.0") + field(:params, GenLSP.Structures.DidOpenNotebookDocumentParams.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "notebookDocument/didOpen", + jsonrpc: "2.0", + params: GenLSP.Structures.DidOpenNotebookDocumentParams.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/notifications/notebook_document_did_save.ex b/apps/language_server/lib/language_server/lsp/protocol/notifications/notebook_document_did_save.ex new file mode 100644 index 000000000..b342af843 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/notifications/notebook_document_did_save.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Notifications.NotebookDocumentDidSave do + @moduledoc """ + A notification sent when a notebook document is saved. + + @since 3.17.0 + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "notebookDocument/didSave") + field(:jsonrpc, String.t(), default: "2.0") + field(:params, GenLSP.Structures.DidSaveNotebookDocumentParams.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "notebookDocument/didSave", + jsonrpc: "2.0", + params: GenLSP.Structures.DidSaveNotebookDocumentParams.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/notifications/telemetry_event.ex b/apps/language_server/lib/language_server/lsp/protocol/notifications/telemetry_event.ex new file mode 100644 index 000000000..b0057095e --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/notifications/telemetry_event.ex @@ -0,0 +1,29 @@ +# codegen: do not edit +defmodule GenLSP.Notifications.TelemetryEvent do + @moduledoc """ + The telemetry event notification is sent from the server to the client to ask + the client to log telemetry data. + + Message Direction: serverToClient + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "telemetry/event") + field(:jsonrpc, String.t(), default: "2.0") + field(:params, GenLSP.TypeAlias.LSPAny.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "telemetry/event", + jsonrpc: "2.0", + params: GenLSP.TypeAlias.LSPAny.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/notifications/text_document_did_change.ex b/apps/language_server/lib/language_server/lsp/protocol/notifications/text_document_did_change.ex new file mode 100644 index 000000000..caf7c7e99 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/notifications/text_document_did_change.ex @@ -0,0 +1,29 @@ +# codegen: do not edit +defmodule GenLSP.Notifications.TextDocumentDidChange do + @moduledoc """ + The document change notification is sent from the client to the server to signal + changes to a text document. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/didChange") + field(:jsonrpc, String.t(), default: "2.0") + field(:params, GenLSP.Structures.DidChangeTextDocumentParams.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/didChange", + jsonrpc: "2.0", + params: GenLSP.Structures.DidChangeTextDocumentParams.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/notifications/text_document_did_close.ex b/apps/language_server/lib/language_server/lsp/protocol/notifications/text_document_did_close.ex new file mode 100644 index 000000000..ad125c200 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/notifications/text_document_did_close.ex @@ -0,0 +1,34 @@ +# codegen: do not edit +defmodule GenLSP.Notifications.TextDocumentDidClose do + @moduledoc """ + The document close notification is sent from the client to the server when + the document got closed in the client. The document's truth now exists where + the document's uri points to (e.g. if the document's uri is a file uri the + truth now exists on disk). As with the open notification the close notification + is about managing the document's content. Receiving a close notification + doesn't mean that the document was open in an editor before. A close + notification requires a previous open notification to be sent. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/didClose") + field(:jsonrpc, String.t(), default: "2.0") + field(:params, GenLSP.Structures.DidCloseTextDocumentParams.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/didClose", + jsonrpc: "2.0", + params: GenLSP.Structures.DidCloseTextDocumentParams.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/notifications/text_document_did_open.ex b/apps/language_server/lib/language_server/lsp/protocol/notifications/text_document_did_open.ex new file mode 100644 index 000000000..a92be54ad --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/notifications/text_document_did_open.ex @@ -0,0 +1,35 @@ +# codegen: do not edit +defmodule GenLSP.Notifications.TextDocumentDidOpen do + @moduledoc """ + The document open notification is sent from the client to the server to signal + newly opened text documents. The document's truth is now managed by the client + and the server must not try to read the document's truth using the document's + uri. Open in this sense means it is managed by the client. It doesn't necessarily + mean that its content is presented in an editor. An open notification must not + be sent more than once without a corresponding close notification send before. + This means open and close notification must be balanced and the max open count + is one. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/didOpen") + field(:jsonrpc, String.t(), default: "2.0") + field(:params, GenLSP.Structures.DidOpenTextDocumentParams.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/didOpen", + jsonrpc: "2.0", + params: GenLSP.Structures.DidOpenTextDocumentParams.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/notifications/text_document_did_save.ex b/apps/language_server/lib/language_server/lsp/protocol/notifications/text_document_did_save.ex new file mode 100644 index 000000000..85ba8c3d4 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/notifications/text_document_did_save.ex @@ -0,0 +1,29 @@ +# codegen: do not edit +defmodule GenLSP.Notifications.TextDocumentDidSave do + @moduledoc """ + The document save notification is sent from the client to the server when + the document got saved in the client. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/didSave") + field(:jsonrpc, String.t(), default: "2.0") + field(:params, GenLSP.Structures.DidSaveTextDocumentParams.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/didSave", + jsonrpc: "2.0", + params: GenLSP.Structures.DidSaveTextDocumentParams.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/notifications/text_document_publish_diagnostics.ex b/apps/language_server/lib/language_server/lsp/protocol/notifications/text_document_publish_diagnostics.ex new file mode 100644 index 000000000..e0946b5a0 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/notifications/text_document_publish_diagnostics.ex @@ -0,0 +1,29 @@ +# codegen: do not edit +defmodule GenLSP.Notifications.TextDocumentPublishDiagnostics do + @moduledoc """ + Diagnostics notification are sent from the server to the client to signal + results of validation runs. + + Message Direction: serverToClient + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/publishDiagnostics") + field(:jsonrpc, String.t(), default: "2.0") + field(:params, GenLSP.Structures.PublishDiagnosticsParams.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/publishDiagnostics", + jsonrpc: "2.0", + params: GenLSP.Structures.PublishDiagnosticsParams.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/notifications/text_document_will_save.ex b/apps/language_server/lib/language_server/lsp/protocol/notifications/text_document_will_save.ex new file mode 100644 index 000000000..1480115df --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/notifications/text_document_will_save.ex @@ -0,0 +1,29 @@ +# codegen: do not edit +defmodule GenLSP.Notifications.TextDocumentWillSave do + @moduledoc """ + A document will save notification is sent from the client to the server before + the document is actually saved. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/willSave") + field(:jsonrpc, String.t(), default: "2.0") + field(:params, GenLSP.Structures.WillSaveTextDocumentParams.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/willSave", + jsonrpc: "2.0", + params: GenLSP.Structures.WillSaveTextDocumentParams.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/notifications/window_log_message.ex b/apps/language_server/lib/language_server/lsp/protocol/notifications/window_log_message.ex new file mode 100644 index 000000000..728cf6719 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/notifications/window_log_message.ex @@ -0,0 +1,29 @@ +# codegen: do not edit +defmodule GenLSP.Notifications.WindowLogMessage do + @moduledoc """ + The log message notification is sent from the server to the client to ask + the client to log a particular message. + + Message Direction: serverToClient + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "window/logMessage") + field(:jsonrpc, String.t(), default: "2.0") + field(:params, GenLSP.Structures.LogMessageParams.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "window/logMessage", + jsonrpc: "2.0", + params: GenLSP.Structures.LogMessageParams.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/notifications/window_show_message.ex b/apps/language_server/lib/language_server/lsp/protocol/notifications/window_show_message.ex new file mode 100644 index 000000000..23dfda43f --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/notifications/window_show_message.ex @@ -0,0 +1,29 @@ +# codegen: do not edit +defmodule GenLSP.Notifications.WindowShowMessage do + @moduledoc """ + The show message notification is sent from a server to a client to ask + the client to display a particular message in the user interface. + + Message Direction: serverToClient + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "window/showMessage") + field(:jsonrpc, String.t(), default: "2.0") + field(:params, GenLSP.Structures.ShowMessageParams.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "window/showMessage", + jsonrpc: "2.0", + params: GenLSP.Structures.ShowMessageParams.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/notifications/window_work_done_progress_cancel.ex b/apps/language_server/lib/language_server/lsp/protocol/notifications/window_work_done_progress_cancel.ex new file mode 100644 index 000000000..59c46fa7e --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/notifications/window_work_done_progress_cancel.ex @@ -0,0 +1,29 @@ +# codegen: do not edit +defmodule GenLSP.Notifications.WindowWorkDoneProgressCancel do + @moduledoc """ + The `window/workDoneProgress/cancel` notification is sent from the client to the server to cancel a progress + initiated on the server side. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "window/workDoneProgress/cancel") + field(:jsonrpc, String.t(), default: "2.0") + field(:params, GenLSP.Structures.WorkDoneProgressCancelParams.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "window/workDoneProgress/cancel", + jsonrpc: "2.0", + params: GenLSP.Structures.WorkDoneProgressCancelParams.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/notifications/workspace_did_change_configuration.ex b/apps/language_server/lib/language_server/lsp/protocol/notifications/workspace_did_change_configuration.ex new file mode 100644 index 000000000..f9bd85e38 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/notifications/workspace_did_change_configuration.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Notifications.WorkspaceDidChangeConfiguration do + @moduledoc """ + The configuration change notification is sent from the client to the server + when the client's configuration has changed. The notification contains + the changed configuration as defined by the language client. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "workspace/didChangeConfiguration") + field(:jsonrpc, String.t(), default: "2.0") + field(:params, GenLSP.Structures.DidChangeConfigurationParams.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "workspace/didChangeConfiguration", + jsonrpc: "2.0", + params: GenLSP.Structures.DidChangeConfigurationParams.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/notifications/workspace_did_change_watched_files.ex b/apps/language_server/lib/language_server/lsp/protocol/notifications/workspace_did_change_watched_files.ex new file mode 100644 index 000000000..471e20846 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/notifications/workspace_did_change_watched_files.ex @@ -0,0 +1,29 @@ +# codegen: do not edit +defmodule GenLSP.Notifications.WorkspaceDidChangeWatchedFiles do + @moduledoc """ + The watched files notification is sent from the client to the server when + the client detects changes to file watched by the language client. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "workspace/didChangeWatchedFiles") + field(:jsonrpc, String.t(), default: "2.0") + field(:params, GenLSP.Structures.DidChangeWatchedFilesParams.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "workspace/didChangeWatchedFiles", + jsonrpc: "2.0", + params: GenLSP.Structures.DidChangeWatchedFilesParams.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/notifications/workspace_did_change_workspace_folders.ex b/apps/language_server/lib/language_server/lsp/protocol/notifications/workspace_did_change_workspace_folders.ex new file mode 100644 index 000000000..177ab75f1 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/notifications/workspace_did_change_workspace_folders.ex @@ -0,0 +1,29 @@ +# codegen: do not edit +defmodule GenLSP.Notifications.WorkspaceDidChangeWorkspaceFolders do + @moduledoc """ + The `workspace/didChangeWorkspaceFolders` notification is sent from the client to the server when the workspace + folder configuration changes. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "workspace/didChangeWorkspaceFolders") + field(:jsonrpc, String.t(), default: "2.0") + field(:params, GenLSP.Structures.DidChangeWorkspaceFoldersParams.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "workspace/didChangeWorkspaceFolders", + jsonrpc: "2.0", + params: GenLSP.Structures.DidChangeWorkspaceFoldersParams.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/notifications/workspace_did_create_files.ex b/apps/language_server/lib/language_server/lsp/protocol/notifications/workspace_did_create_files.ex new file mode 100644 index 000000000..9dfd0627b --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/notifications/workspace_did_create_files.ex @@ -0,0 +1,31 @@ +# codegen: do not edit +defmodule GenLSP.Notifications.WorkspaceDidCreateFiles do + @moduledoc """ + The did create files notification is sent from the client to the server when + files were created from within the client. + + @since 3.16.0 + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "workspace/didCreateFiles") + field(:jsonrpc, String.t(), default: "2.0") + field(:params, GenLSP.Structures.CreateFilesParams.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "workspace/didCreateFiles", + jsonrpc: "2.0", + params: GenLSP.Structures.CreateFilesParams.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/notifications/workspace_did_delete_files.ex b/apps/language_server/lib/language_server/lsp/protocol/notifications/workspace_did_delete_files.ex new file mode 100644 index 000000000..55d58b571 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/notifications/workspace_did_delete_files.ex @@ -0,0 +1,31 @@ +# codegen: do not edit +defmodule GenLSP.Notifications.WorkspaceDidDeleteFiles do + @moduledoc """ + The will delete files request is sent from the client to the server before files are actually + deleted as long as the deletion is triggered from within the client. + + @since 3.16.0 + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "workspace/didDeleteFiles") + field(:jsonrpc, String.t(), default: "2.0") + field(:params, GenLSP.Structures.DeleteFilesParams.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "workspace/didDeleteFiles", + jsonrpc: "2.0", + params: GenLSP.Structures.DeleteFilesParams.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/notifications/workspace_did_rename_files.ex b/apps/language_server/lib/language_server/lsp/protocol/notifications/workspace_did_rename_files.ex new file mode 100644 index 000000000..32be857ee --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/notifications/workspace_did_rename_files.ex @@ -0,0 +1,31 @@ +# codegen: do not edit +defmodule GenLSP.Notifications.WorkspaceDidRenameFiles do + @moduledoc """ + The did rename files notification is sent from the client to the server when + files were renamed from within the client. + + @since 3.16.0 + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "workspace/didRenameFiles") + field(:jsonrpc, String.t(), default: "2.0") + field(:params, GenLSP.Structures.RenameFilesParams.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "workspace/didRenameFiles", + jsonrpc: "2.0", + params: GenLSP.Structures.RenameFilesParams.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests.ex b/apps/language_server/lib/language_server/lsp/protocol/requests.ex new file mode 100644 index 000000000..8e0c393ee --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests.ex @@ -0,0 +1,206 @@ +# codegen: do not edit +defmodule GenLSP.Requests do + import SchematicV + + def new(request) do + unify( + oneof(fn + %{"method" => "callHierarchy/incomingCalls"} -> + GenLSP.Requests.CallHierarchyIncomingCalls.schematic() + + %{"method" => "callHierarchy/outgoingCalls"} -> + GenLSP.Requests.CallHierarchyOutgoingCalls.schematic() + + %{"method" => "client/registerCapability"} -> + GenLSP.Requests.ClientRegisterCapability.schematic() + + %{"method" => "client/unregisterCapability"} -> + GenLSP.Requests.ClientUnregisterCapability.schematic() + + %{"method" => "codeAction/resolve"} -> + GenLSP.Requests.CodeActionResolve.schematic() + + %{"method" => "codeLens/resolve"} -> + GenLSP.Requests.CodeLensResolve.schematic() + + %{"method" => "completionItem/resolve"} -> + GenLSP.Requests.CompletionItemResolve.schematic() + + %{"method" => "documentLink/resolve"} -> + GenLSP.Requests.DocumentLinkResolve.schematic() + + %{"method" => "initialize"} -> + GenLSP.Requests.Initialize.schematic() + + %{"method" => "inlayHint/resolve"} -> + GenLSP.Requests.InlayHintResolve.schematic() + + %{"method" => "shutdown"} -> + GenLSP.Requests.Shutdown.schematic() + + %{"method" => "textDocument/codeAction"} -> + GenLSP.Requests.TextDocumentCodeAction.schematic() + + %{"method" => "textDocument/codeLens"} -> + GenLSP.Requests.TextDocumentCodeLens.schematic() + + %{"method" => "textDocument/colorPresentation"} -> + GenLSP.Requests.TextDocumentColorPresentation.schematic() + + %{"method" => "textDocument/completion"} -> + GenLSP.Requests.TextDocumentCompletion.schematic() + + %{"method" => "textDocument/declaration"} -> + GenLSP.Requests.TextDocumentDeclaration.schematic() + + %{"method" => "textDocument/definition"} -> + GenLSP.Requests.TextDocumentDefinition.schematic() + + %{"method" => "textDocument/diagnostic"} -> + GenLSP.Requests.TextDocumentDiagnostic.schematic() + + %{"method" => "textDocument/documentColor"} -> + GenLSP.Requests.TextDocumentDocumentColor.schematic() + + %{"method" => "textDocument/documentHighlight"} -> + GenLSP.Requests.TextDocumentDocumentHighlight.schematic() + + %{"method" => "textDocument/documentLink"} -> + GenLSP.Requests.TextDocumentDocumentLink.schematic() + + %{"method" => "textDocument/documentSymbol"} -> + GenLSP.Requests.TextDocumentDocumentSymbol.schematic() + + %{"method" => "textDocument/foldingRange"} -> + GenLSP.Requests.TextDocumentFoldingRange.schematic() + + %{"method" => "textDocument/formatting"} -> + GenLSP.Requests.TextDocumentFormatting.schematic() + + %{"method" => "textDocument/hover"} -> + GenLSP.Requests.TextDocumentHover.schematic() + + %{"method" => "textDocument/implementation"} -> + GenLSP.Requests.TextDocumentImplementation.schematic() + + %{"method" => "textDocument/inlayHint"} -> + GenLSP.Requests.TextDocumentInlayHint.schematic() + + %{"method" => "textDocument/inlineValue"} -> + GenLSP.Requests.TextDocumentInlineValue.schematic() + + %{"method" => "textDocument/linkedEditingRange"} -> + GenLSP.Requests.TextDocumentLinkedEditingRange.schematic() + + %{"method" => "textDocument/moniker"} -> + GenLSP.Requests.TextDocumentMoniker.schematic() + + %{"method" => "textDocument/onTypeFormatting"} -> + GenLSP.Requests.TextDocumentOnTypeFormatting.schematic() + + %{"method" => "textDocument/prepareCallHierarchy"} -> + GenLSP.Requests.TextDocumentPrepareCallHierarchy.schematic() + + %{"method" => "textDocument/prepareRename"} -> + GenLSP.Requests.TextDocumentPrepareRename.schematic() + + %{"method" => "textDocument/prepareTypeHierarchy"} -> + GenLSP.Requests.TextDocumentPrepareTypeHierarchy.schematic() + + %{"method" => "textDocument/rangeFormatting"} -> + GenLSP.Requests.TextDocumentRangeFormatting.schematic() + + %{"method" => "textDocument/references"} -> + GenLSP.Requests.TextDocumentReferences.schematic() + + %{"method" => "textDocument/rename"} -> + GenLSP.Requests.TextDocumentRename.schematic() + + %{"method" => "textDocument/selectionRange"} -> + GenLSP.Requests.TextDocumentSelectionRange.schematic() + + %{"method" => "textDocument/semanticTokens/full"} -> + GenLSP.Requests.TextDocumentSemanticTokensFull.schematic() + + %{"method" => "textDocument/semanticTokens/full/delta"} -> + GenLSP.Requests.TextDocumentSemanticTokensFullDelta.schematic() + + %{"method" => "textDocument/semanticTokens/range"} -> + GenLSP.Requests.TextDocumentSemanticTokensRange.schematic() + + %{"method" => "textDocument/signatureHelp"} -> + GenLSP.Requests.TextDocumentSignatureHelp.schematic() + + %{"method" => "textDocument/typeDefinition"} -> + GenLSP.Requests.TextDocumentTypeDefinition.schematic() + + %{"method" => "textDocument/willSaveWaitUntil"} -> + GenLSP.Requests.TextDocumentWillSaveWaitUntil.schematic() + + %{"method" => "typeHierarchy/subtypes"} -> + GenLSP.Requests.TypeHierarchySubtypes.schematic() + + %{"method" => "typeHierarchy/supertypes"} -> + GenLSP.Requests.TypeHierarchySupertypes.schematic() + + %{"method" => "window/showDocument"} -> + GenLSP.Requests.WindowShowDocument.schematic() + + %{"method" => "window/showMessageRequest"} -> + GenLSP.Requests.WindowShowMessageRequest.schematic() + + %{"method" => "window/workDoneProgress/create"} -> + GenLSP.Requests.WindowWorkDoneProgressCreate.schematic() + + %{"method" => "workspace/applyEdit"} -> + GenLSP.Requests.WorkspaceApplyEdit.schematic() + + %{"method" => "workspace/codeLens/refresh"} -> + GenLSP.Requests.WorkspaceCodeLensRefresh.schematic() + + %{"method" => "workspace/configuration"} -> + GenLSP.Requests.WorkspaceConfiguration.schematic() + + %{"method" => "workspace/diagnostic"} -> + GenLSP.Requests.WorkspaceDiagnostic.schematic() + + %{"method" => "workspace/diagnostic/refresh"} -> + GenLSP.Requests.WorkspaceDiagnosticRefresh.schematic() + + %{"method" => "workspace/executeCommand"} -> + GenLSP.Requests.WorkspaceExecuteCommand.schematic() + + %{"method" => "workspace/inlayHint/refresh"} -> + GenLSP.Requests.WorkspaceInlayHintRefresh.schematic() + + %{"method" => "workspace/inlineValue/refresh"} -> + GenLSP.Requests.WorkspaceInlineValueRefresh.schematic() + + %{"method" => "workspace/semanticTokens/refresh"} -> + GenLSP.Requests.WorkspaceSemanticTokensRefresh.schematic() + + %{"method" => "workspace/symbol"} -> + GenLSP.Requests.WorkspaceSymbol.schematic() + + %{"method" => "workspace/willCreateFiles"} -> + GenLSP.Requests.WorkspaceWillCreateFiles.schematic() + + %{"method" => "workspace/willDeleteFiles"} -> + GenLSP.Requests.WorkspaceWillDeleteFiles.schematic() + + %{"method" => "workspace/willRenameFiles"} -> + GenLSP.Requests.WorkspaceWillRenameFiles.schematic() + + %{"method" => "workspace/workspaceFolders"} -> + GenLSP.Requests.WorkspaceWorkspaceFolders.schematic() + + %{"method" => "workspaceSymbol/resolve"} -> + GenLSP.Requests.WorkspaceSymbolResolve.schematic() + + _ -> + {:error, "unexpected request payload"} + end), + request + ) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/call_hierarchy_incoming_calls.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/call_hierarchy_incoming_calls.ex new file mode 100644 index 000000000..3933a939d --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/call_hierarchy_incoming_calls.ex @@ -0,0 +1,43 @@ +# codegen: do not edit +defmodule GenLSP.Requests.CallHierarchyIncomingCalls do + @moduledoc """ + A request to resolve the incoming calls for a given `CallHierarchyItem`. + + @since 3.16.0 + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "callHierarchy/incomingCalls") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.CallHierarchyIncomingCallsParams.t()) + end + + @type result :: list(GenLSP.Structures.CallHierarchyIncomingCall.t()) | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "callHierarchy/incomingCalls", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.CallHierarchyIncomingCallsParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([list(GenLSP.Structures.CallHierarchyIncomingCall.schematic()), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/call_hierarchy_outgoing_calls.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/call_hierarchy_outgoing_calls.ex new file mode 100644 index 000000000..4dfe17edd --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/call_hierarchy_outgoing_calls.ex @@ -0,0 +1,43 @@ +# codegen: do not edit +defmodule GenLSP.Requests.CallHierarchyOutgoingCalls do + @moduledoc """ + A request to resolve the outgoing calls for a given `CallHierarchyItem`. + + @since 3.16.0 + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "callHierarchy/outgoingCalls") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.CallHierarchyOutgoingCallsParams.t()) + end + + @type result :: list(GenLSP.Structures.CallHierarchyOutgoingCall.t()) | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "callHierarchy/outgoingCalls", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.CallHierarchyOutgoingCallsParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([list(GenLSP.Structures.CallHierarchyOutgoingCall.schematic()), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/client_register_capability.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/client_register_capability.ex new file mode 100644 index 000000000..cba01f0e5 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/client_register_capability.ex @@ -0,0 +1,42 @@ +# codegen: do not edit +defmodule GenLSP.Requests.ClientRegisterCapability do + @moduledoc """ + The `client/registerCapability` request is sent from the server to the client to register a new capability + handler on the client side. + + Message Direction: serverToClient + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "client/registerCapability") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.RegistrationParams.t()) + end + + @type result :: nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "client/registerCapability", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.RegistrationParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + nil, + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/client_unregister_capability.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/client_unregister_capability.ex new file mode 100644 index 000000000..d7dd1f10a --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/client_unregister_capability.ex @@ -0,0 +1,42 @@ +# codegen: do not edit +defmodule GenLSP.Requests.ClientUnregisterCapability do + @moduledoc """ + The `client/unregisterCapability` request is sent from the server to the client to unregister a previously registered capability + handler on the client side. + + Message Direction: serverToClient + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "client/unregisterCapability") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.UnregistrationParams.t()) + end + + @type result :: nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "client/unregisterCapability", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.UnregistrationParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + nil, + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/code_action_resolve.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/code_action_resolve.ex new file mode 100644 index 000000000..2e6ee4aec --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/code_action_resolve.ex @@ -0,0 +1,43 @@ +# codegen: do not edit +defmodule GenLSP.Requests.CodeActionResolve do + @moduledoc """ + Request to resolve additional information for a given code action.The request's + parameter is of type {@link CodeAction} the response + is of type {@link CodeAction} or a Thenable that resolves to such. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "codeAction/resolve") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.CodeAction.t()) + end + + @type result :: GenLSP.Structures.CodeAction.t() + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "codeAction/resolve", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.CodeAction.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + GenLSP.Structures.CodeAction.schematic(), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/code_lens_resolve.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/code_lens_resolve.ex new file mode 100644 index 000000000..16b5339ca --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/code_lens_resolve.ex @@ -0,0 +1,41 @@ +# codegen: do not edit +defmodule GenLSP.Requests.CodeLensResolve do + @moduledoc """ + A request to resolve a command for a given code lens. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "codeLens/resolve") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.CodeLens.t()) + end + + @type result :: GenLSP.Structures.CodeLens.t() + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "codeLens/resolve", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.CodeLens.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + GenLSP.Structures.CodeLens.schematic(), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/completion_item_resolve.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/completion_item_resolve.ex new file mode 100644 index 000000000..2bc7eae0d --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/completion_item_resolve.ex @@ -0,0 +1,43 @@ +# codegen: do not edit +defmodule GenLSP.Requests.CompletionItemResolve do + @moduledoc """ + Request to resolve additional information for a given completion item.The request's + parameter is of type {@link CompletionItem} the response + is of type {@link CompletionItem} or a Thenable that resolves to such. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "completionItem/resolve") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.CompletionItem.t()) + end + + @type result :: GenLSP.Structures.CompletionItem.t() + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "completionItem/resolve", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.CompletionItem.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + GenLSP.Structures.CompletionItem.schematic(), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/document_link_resolve.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/document_link_resolve.ex new file mode 100644 index 000000000..decef6fd6 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/document_link_resolve.ex @@ -0,0 +1,43 @@ +# codegen: do not edit +defmodule GenLSP.Requests.DocumentLinkResolve do + @moduledoc """ + Request to resolve additional information for a given document link. The request's + parameter is of type {@link DocumentLink} the response + is of type {@link DocumentLink} or a Thenable that resolves to such. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "documentLink/resolve") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.DocumentLink.t()) + end + + @type result :: GenLSP.Structures.DocumentLink.t() + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "documentLink/resolve", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.DocumentLink.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + GenLSP.Structures.DocumentLink.schematic(), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/initialize.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/initialize.ex new file mode 100644 index 000000000..5334aaade --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/initialize.ex @@ -0,0 +1,45 @@ +# codegen: do not edit +defmodule GenLSP.Requests.Initialize do + @moduledoc """ + The initialize request is sent from the client to the server. + It is sent once as the request after starting up the server. + The requests parameter is of type {@link InitializeParams} + the response if of type {@link InitializeResult} of a Thenable that + resolves to such. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "initialize") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.InitializeParams.t()) + end + + @type result :: GenLSP.Structures.InitializeResult.t() + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "initialize", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.InitializeParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + GenLSP.Structures.InitializeResult.schematic(), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/inlay_hint_resolve.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/inlay_hint_resolve.ex new file mode 100644 index 000000000..1f91a676f --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/inlay_hint_resolve.ex @@ -0,0 +1,45 @@ +# codegen: do not edit +defmodule GenLSP.Requests.InlayHintResolve do + @moduledoc """ + A request to resolve additional properties for an inlay hint. + The request's parameter is of type {@link InlayHint}, the response is + of type {@link InlayHint} or a Thenable that resolves to such. + + @since 3.17.0 + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "inlayHint/resolve") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.InlayHint.t()) + end + + @type result :: GenLSP.Structures.InlayHint.t() + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "inlayHint/resolve", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.InlayHint.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + GenLSP.Structures.InlayHint.schematic(), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/shutdown.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/shutdown.ex new file mode 100644 index 000000000..177f22f3a --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/shutdown.ex @@ -0,0 +1,42 @@ +# codegen: do not edit +defmodule GenLSP.Requests.Shutdown do + @moduledoc """ + A shutdown request is sent from the client to the server. + It is sent once when the client decides to shutdown the + server. The only notification that is sent after a shutdown request + is the exit event. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "shutdown") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + end + + @type result :: nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "shutdown", + jsonrpc: "2.0", + id: int() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + nil, + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_code_action.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_code_action.ex new file mode 100644 index 000000000..2c82beb0f --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_code_action.ex @@ -0,0 +1,46 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentCodeAction do + @moduledoc """ + A request to provide commands for the given text document and range. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/codeAction") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.CodeActionParams.t()) + end + + @type result :: list(GenLSP.Structures.Command.t() | GenLSP.Structures.CodeAction.t()) | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/codeAction", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.CodeActionParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([ + list( + oneof([GenLSP.Structures.Command.schematic(), GenLSP.Structures.CodeAction.schematic()]) + ), + nil + ]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_code_lens.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_code_lens.ex new file mode 100644 index 000000000..c45b0ee2f --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_code_lens.ex @@ -0,0 +1,41 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentCodeLens do + @moduledoc """ + A request to provide code lens for the given text document. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/codeLens") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.CodeLensParams.t()) + end + + @type result :: list(GenLSP.Structures.CodeLens.t()) | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/codeLens", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.CodeLensParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([list(GenLSP.Structures.CodeLens.schematic()), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_color_presentation.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_color_presentation.ex new file mode 100644 index 000000000..02433569d --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_color_presentation.ex @@ -0,0 +1,44 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentColorPresentation do + @moduledoc """ + A request to list all presentation for a color. The request's + parameter is of type {@link ColorPresentationParams} the + response is of type {@link ColorInformation ColorInformation[]} or a Thenable + that resolves to such. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/colorPresentation") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.ColorPresentationParams.t()) + end + + @type result :: list(GenLSP.Structures.ColorPresentation.t()) + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/colorPresentation", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.ColorPresentationParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + list(GenLSP.Structures.ColorPresentation.schematic()), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_completion.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_completion.ex new file mode 100644 index 000000000..272061433 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_completion.ex @@ -0,0 +1,54 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentCompletion do + @moduledoc """ + Request to request completion at a given text document position. The request's + parameter is of type {@link TextDocumentPosition} the response + is of type {@link CompletionItem CompletionItem[]} or {@link CompletionList} + or a Thenable that resolves to such. + + The request can delay the computation of the {@link CompletionItem.detail `detail`} + and {@link CompletionItem.documentation `documentation`} properties to the `completionItem/resolve` + request. However, properties that are needed for the initial sorting and filtering, like `sortText`, + `filterText`, `insertText`, and `textEdit`, must not be changed during resolve. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/completion") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.CompletionParams.t()) + end + + @type result :: + list(GenLSP.Structures.CompletionItem.t()) | GenLSP.Structures.CompletionList.t() | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/completion", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.CompletionParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([ + list(GenLSP.Structures.CompletionItem.schematic()), + GenLSP.Structures.CompletionList.schematic(), + nil + ]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_declaration.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_declaration.ex new file mode 100644 index 000000000..90da8afc1 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_declaration.ex @@ -0,0 +1,50 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentDeclaration do + @moduledoc """ + A request to resolve the type definition locations of a symbol at a given text + document position. The request's parameter is of type [TextDocumentPositionParams] + (#TextDocumentPositionParams) the response is of type {@link Declaration} + or a typed array of {@link DeclarationLink} or a Thenable that resolves + to such. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/declaration") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.DeclarationParams.t()) + end + + @type result :: + GenLSP.TypeAlias.Declaration.t() | list(GenLSP.TypeAlias.DeclarationLink.t()) | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/declaration", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.DeclarationParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([ + GenLSP.TypeAlias.Declaration.schematic(), + list(GenLSP.TypeAlias.DeclarationLink.schematic()), + nil + ]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_definition.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_definition.ex new file mode 100644 index 000000000..b5e8957cd --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_definition.ex @@ -0,0 +1,50 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentDefinition do + @moduledoc """ + A request to resolve the definition location of a symbol at a given text + document position. The request's parameter is of type [TextDocumentPosition] + (#TextDocumentPosition) the response is of either type {@link Definition} + or a typed array of {@link DefinitionLink} or a Thenable that resolves + to such. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/definition") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.DefinitionParams.t()) + end + + @type result :: + GenLSP.TypeAlias.Definition.t() | list(GenLSP.TypeAlias.DefinitionLink.t()) | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/definition", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.DefinitionParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([ + GenLSP.TypeAlias.Definition.schematic(), + list(GenLSP.TypeAlias.DefinitionLink.schematic()), + nil + ]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_diagnostic.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_diagnostic.ex new file mode 100644 index 000000000..1d9e4315b --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_diagnostic.ex @@ -0,0 +1,43 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentDiagnostic do + @moduledoc """ + The document diagnostic request definition. + + @since 3.17.0 + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/diagnostic") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.DocumentDiagnosticParams.t()) + end + + @type result :: GenLSP.TypeAlias.DocumentDiagnosticReport.t() + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/diagnostic", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.DocumentDiagnosticParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + GenLSP.TypeAlias.DocumentDiagnosticReport.schematic(), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_document_color.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_document_color.ex new file mode 100644 index 000000000..ec7fad5dc --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_document_color.ex @@ -0,0 +1,44 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentDocumentColor do + @moduledoc """ + A request to list all color symbols found in a given text document. The request's + parameter is of type {@link DocumentColorParams} the + response is of type {@link ColorInformation ColorInformation[]} or a Thenable + that resolves to such. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/documentColor") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.DocumentColorParams.t()) + end + + @type result :: list(GenLSP.Structures.ColorInformation.t()) + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/documentColor", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.DocumentColorParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + list(GenLSP.Structures.ColorInformation.schematic()), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_document_highlight.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_document_highlight.ex new file mode 100644 index 000000000..cc2c5abfc --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_document_highlight.ex @@ -0,0 +1,44 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentDocumentHighlight do + @moduledoc """ + Request to resolve a {@link DocumentHighlight} for a given + text document position. The request's parameter is of type [TextDocumentPosition] + (#TextDocumentPosition) the request response is of type [DocumentHighlight[]] + (#DocumentHighlight) or a Thenable that resolves to such. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/documentHighlight") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.DocumentHighlightParams.t()) + end + + @type result :: list(GenLSP.Structures.DocumentHighlight.t()) | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/documentHighlight", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.DocumentHighlightParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([list(GenLSP.Structures.DocumentHighlight.schematic()), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_document_link.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_document_link.ex new file mode 100644 index 000000000..cf36c2c9b --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_document_link.ex @@ -0,0 +1,41 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentDocumentLink do + @moduledoc """ + A request to provide document links + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/documentLink") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.DocumentLinkParams.t()) + end + + @type result :: list(GenLSP.Structures.DocumentLink.t()) | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/documentLink", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.DocumentLinkParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([list(GenLSP.Structures.DocumentLink.schematic()), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_document_symbol.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_document_symbol.ex new file mode 100644 index 000000000..2ea7afe4c --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_document_symbol.ex @@ -0,0 +1,51 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentDocumentSymbol do + @moduledoc """ + A request to list all symbols found in a given text document. The request's + parameter is of type {@link TextDocumentIdentifier} the + response is of type {@link SymbolInformation SymbolInformation[]} or a Thenable + that resolves to such. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/documentSymbol") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.DocumentSymbolParams.t()) + end + + @type result :: + list(GenLSP.Structures.SymbolInformation.t()) + | list(GenLSP.Structures.DocumentSymbol.t()) + | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/documentSymbol", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.DocumentSymbolParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([ + list(GenLSP.Structures.SymbolInformation.schematic()), + list(GenLSP.Structures.DocumentSymbol.schematic()), + nil + ]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_folding_range.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_folding_range.ex new file mode 100644 index 000000000..1b303e1d1 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_folding_range.ex @@ -0,0 +1,44 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentFoldingRange do + @moduledoc """ + A request to provide folding ranges in a document. The request's + parameter is of type {@link FoldingRangeParams}, the + response is of type {@link FoldingRangeList} or a Thenable + that resolves to such. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/foldingRange") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.FoldingRangeParams.t()) + end + + @type result :: list(GenLSP.Structures.FoldingRange.t()) | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/foldingRange", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.FoldingRangeParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([list(GenLSP.Structures.FoldingRange.schematic()), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_formatting.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_formatting.ex new file mode 100644 index 000000000..793aa44e9 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_formatting.ex @@ -0,0 +1,41 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentFormatting do + @moduledoc """ + A request to format a whole document. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/formatting") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.DocumentFormattingParams.t()) + end + + @type result :: list(GenLSP.Structures.TextEdit.t()) | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/formatting", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.DocumentFormattingParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([list(GenLSP.Structures.TextEdit.schematic()), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_hover.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_hover.ex new file mode 100644 index 000000000..382745235 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_hover.ex @@ -0,0 +1,43 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentHover do + @moduledoc """ + Request to request hover information at a given text document position. The request's + parameter is of type {@link TextDocumentPosition} the response is of + type {@link Hover} or a Thenable that resolves to such. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/hover") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.HoverParams.t()) + end + + @type result :: GenLSP.Structures.Hover.t() | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/hover", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.HoverParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([GenLSP.Structures.Hover.schematic(), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_implementation.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_implementation.ex new file mode 100644 index 000000000..c73ae9b61 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_implementation.ex @@ -0,0 +1,49 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentImplementation do + @moduledoc """ + A request to resolve the implementation locations of a symbol at a given text + document position. The request's parameter is of type [TextDocumentPositionParams] + (#TextDocumentPositionParams) the response is of type {@link Definition} or a + Thenable that resolves to such. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/implementation") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.ImplementationParams.t()) + end + + @type result :: + GenLSP.TypeAlias.Definition.t() | list(GenLSP.TypeAlias.DefinitionLink.t()) | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/implementation", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.ImplementationParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([ + GenLSP.TypeAlias.Definition.schematic(), + list(GenLSP.TypeAlias.DefinitionLink.schematic()), + nil + ]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_inlay_hint.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_inlay_hint.ex new file mode 100644 index 000000000..c63d87eb0 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_inlay_hint.ex @@ -0,0 +1,45 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentInlayHint do + @moduledoc """ + A request to provide inlay hints in a document. The request's parameter is of + type {@link InlayHintsParams}, the response is of type + {@link InlayHint InlayHint[]} or a Thenable that resolves to such. + + @since 3.17.0 + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/inlayHint") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.InlayHintParams.t()) + end + + @type result :: list(GenLSP.Structures.InlayHint.t()) | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/inlayHint", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.InlayHintParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([list(GenLSP.Structures.InlayHint.schematic()), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_inline_value.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_inline_value.ex new file mode 100644 index 000000000..f7972df3f --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_inline_value.ex @@ -0,0 +1,45 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentInlineValue do + @moduledoc """ + A request to provide inline values in a document. The request's parameter is of + type {@link InlineValueParams}, the response is of type + {@link InlineValue InlineValue[]} or a Thenable that resolves to such. + + @since 3.17.0 + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/inlineValue") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.InlineValueParams.t()) + end + + @type result :: list(GenLSP.TypeAlias.InlineValue.t()) | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/inlineValue", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.InlineValueParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([list(GenLSP.TypeAlias.InlineValue.schematic()), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_linked_editing_range.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_linked_editing_range.ex new file mode 100644 index 000000000..46e05cac6 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_linked_editing_range.ex @@ -0,0 +1,43 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentLinkedEditingRange do + @moduledoc """ + A request to provide ranges that can be edited together. + + @since 3.16.0 + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/linkedEditingRange") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.LinkedEditingRangeParams.t()) + end + + @type result :: GenLSP.Structures.LinkedEditingRanges.t() | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/linkedEditingRange", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.LinkedEditingRangeParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([GenLSP.Structures.LinkedEditingRanges.schematic(), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_moniker.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_moniker.ex new file mode 100644 index 000000000..034a03e09 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_moniker.ex @@ -0,0 +1,43 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentMoniker do + @moduledoc """ + A request to get the moniker of a symbol at a given text document position. + The request parameter is of type {@link TextDocumentPositionParams}. + The response is of type {@link Moniker Moniker[]} or `null`. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/moniker") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.MonikerParams.t()) + end + + @type result :: list(GenLSP.Structures.Moniker.t()) | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/moniker", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.MonikerParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([list(GenLSP.Structures.Moniker.schematic()), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_on_type_formatting.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_on_type_formatting.ex new file mode 100644 index 000000000..b6eec3656 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_on_type_formatting.ex @@ -0,0 +1,41 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentOnTypeFormatting do + @moduledoc """ + A request to format a document on type. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/onTypeFormatting") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.DocumentOnTypeFormattingParams.t()) + end + + @type result :: list(GenLSP.Structures.TextEdit.t()) | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/onTypeFormatting", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.DocumentOnTypeFormattingParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([list(GenLSP.Structures.TextEdit.schematic()), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_prepare_call_hierarchy.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_prepare_call_hierarchy.ex new file mode 100644 index 000000000..bb2be652e --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_prepare_call_hierarchy.ex @@ -0,0 +1,44 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentPrepareCallHierarchy do + @moduledoc """ + A request to result a `CallHierarchyItem` in a document at a given position. + Can be used as an input to an incoming or outgoing call hierarchy. + + @since 3.16.0 + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/prepareCallHierarchy") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.CallHierarchyPrepareParams.t()) + end + + @type result :: list(GenLSP.Structures.CallHierarchyItem.t()) | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/prepareCallHierarchy", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.CallHierarchyPrepareParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([list(GenLSP.Structures.CallHierarchyItem.schematic()), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_prepare_rename.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_prepare_rename.ex new file mode 100644 index 000000000..402fd6993 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_prepare_rename.ex @@ -0,0 +1,43 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentPrepareRename do + @moduledoc """ + A request to test and perform the setup necessary for a rename. + + @since 3.16 - support for default behavior + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/prepareRename") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.PrepareRenameParams.t()) + end + + @type result :: GenLSP.TypeAlias.PrepareRenameResult.t() | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/prepareRename", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.PrepareRenameParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([GenLSP.TypeAlias.PrepareRenameResult.schematic(), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_prepare_type_hierarchy.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_prepare_type_hierarchy.ex new file mode 100644 index 000000000..030ad03ba --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_prepare_type_hierarchy.ex @@ -0,0 +1,44 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentPrepareTypeHierarchy do + @moduledoc """ + A request to result a `TypeHierarchyItem` in a document at a given position. + Can be used as an input to a subtypes or supertypes type hierarchy. + + @since 3.17.0 + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/prepareTypeHierarchy") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.TypeHierarchyPrepareParams.t()) + end + + @type result :: list(GenLSP.Structures.TypeHierarchyItem.t()) | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/prepareTypeHierarchy", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.TypeHierarchyPrepareParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([list(GenLSP.Structures.TypeHierarchyItem.schematic()), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_range_formatting.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_range_formatting.ex new file mode 100644 index 000000000..eb0e28048 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_range_formatting.ex @@ -0,0 +1,41 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentRangeFormatting do + @moduledoc """ + A request to format a range in a document. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/rangeFormatting") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.DocumentRangeFormattingParams.t()) + end + + @type result :: list(GenLSP.Structures.TextEdit.t()) | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/rangeFormatting", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.DocumentRangeFormattingParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([list(GenLSP.Structures.TextEdit.schematic()), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_references.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_references.ex new file mode 100644 index 000000000..2d8b6937b --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_references.ex @@ -0,0 +1,44 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentReferences do + @moduledoc """ + A request to resolve project-wide references for the symbol denoted + by the given text document position. The request's parameter is of + type {@link ReferenceParams} the response is of type + {@link Location Location[]} or a Thenable that resolves to such. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/references") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.ReferenceParams.t()) + end + + @type result :: list(GenLSP.Structures.Location.t()) | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/references", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.ReferenceParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([list(GenLSP.Structures.Location.schematic()), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_rename.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_rename.ex new file mode 100644 index 000000000..a059d3b87 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_rename.ex @@ -0,0 +1,41 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentRename do + @moduledoc """ + A request to rename a symbol. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/rename") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.RenameParams.t()) + end + + @type result :: GenLSP.Structures.WorkspaceEdit.t() | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/rename", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.RenameParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([GenLSP.Structures.WorkspaceEdit.schematic(), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_selection_range.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_selection_range.ex new file mode 100644 index 000000000..75e77fcca --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_selection_range.ex @@ -0,0 +1,44 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentSelectionRange do + @moduledoc """ + A request to provide selection ranges in a document. The request's + parameter is of type {@link SelectionRangeParams}, the + response is of type {@link SelectionRange SelectionRange[]} or a Thenable + that resolves to such. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/selectionRange") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.SelectionRangeParams.t()) + end + + @type result :: list(GenLSP.Structures.SelectionRange.t()) | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/selectionRange", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.SelectionRangeParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([list(GenLSP.Structures.SelectionRange.schematic()), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_semantic_tokens_full.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_semantic_tokens_full.ex new file mode 100644 index 000000000..33269e6c0 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_semantic_tokens_full.ex @@ -0,0 +1,41 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentSemanticTokensFull do + @moduledoc """ + @since 3.16.0 + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/semanticTokens/full") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.SemanticTokensParams.t()) + end + + @type result :: GenLSP.Structures.SemanticTokens.t() | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/semanticTokens/full", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.SemanticTokensParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([GenLSP.Structures.SemanticTokens.schematic(), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_semantic_tokens_full_delta.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_semantic_tokens_full_delta.ex new file mode 100644 index 000000000..89f10a54c --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_semantic_tokens_full_delta.ex @@ -0,0 +1,46 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentSemanticTokensFullDelta do + @moduledoc """ + @since 3.16.0 + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/semanticTokens/full/delta") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.SemanticTokensDeltaParams.t()) + end + + @type result :: + GenLSP.Structures.SemanticTokens.t() | GenLSP.Structures.SemanticTokensDelta.t() | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/semanticTokens/full/delta", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.SemanticTokensDeltaParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([ + GenLSP.Structures.SemanticTokens.schematic(), + GenLSP.Structures.SemanticTokensDelta.schematic(), + nil + ]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_semantic_tokens_range.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_semantic_tokens_range.ex new file mode 100644 index 000000000..7447e1d5c --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_semantic_tokens_range.ex @@ -0,0 +1,41 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentSemanticTokensRange do + @moduledoc """ + @since 3.16.0 + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/semanticTokens/range") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.SemanticTokensRangeParams.t()) + end + + @type result :: GenLSP.Structures.SemanticTokens.t() | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/semanticTokens/range", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.SemanticTokensRangeParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([GenLSP.Structures.SemanticTokens.schematic(), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_signature_help.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_signature_help.ex new file mode 100644 index 000000000..6108947fe --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_signature_help.ex @@ -0,0 +1,35 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentSignatureHelp do + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/signatureHelp") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.SignatureHelpParams.t()) + end + + @type result :: GenLSP.Structures.SignatureHelp.t() | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/signatureHelp", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.SignatureHelpParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([GenLSP.Structures.SignatureHelp.schematic(), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_type_definition.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_type_definition.ex new file mode 100644 index 000000000..3d1d22db1 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_type_definition.ex @@ -0,0 +1,49 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentTypeDefinition do + @moduledoc """ + A request to resolve the type definition locations of a symbol at a given text + document position. The request's parameter is of type [TextDocumentPositionParams] + (#TextDocumentPositionParams) the response is of type {@link Definition} or a + Thenable that resolves to such. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/typeDefinition") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.TypeDefinitionParams.t()) + end + + @type result :: + GenLSP.TypeAlias.Definition.t() | list(GenLSP.TypeAlias.DefinitionLink.t()) | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/typeDefinition", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.TypeDefinitionParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([ + GenLSP.TypeAlias.Definition.schematic(), + list(GenLSP.TypeAlias.DefinitionLink.schematic()), + nil + ]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_will_save_wait_until.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_will_save_wait_until.ex new file mode 100644 index 000000000..777586442 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/text_document_will_save_wait_until.ex @@ -0,0 +1,46 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TextDocumentWillSaveWaitUntil do + @moduledoc """ + A document will save request is sent from the client to the server before + the document is actually saved. The request can return an array of TextEdits + which will be applied to the text document before it is saved. Please note that + clients might drop results if computing the text edits took too long or if a + server constantly fails on this request. This is done to keep the save fast and + reliable. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "textDocument/willSaveWaitUntil") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.WillSaveTextDocumentParams.t()) + end + + @type result :: list(GenLSP.Structures.TextEdit.t()) | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "textDocument/willSaveWaitUntil", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.WillSaveTextDocumentParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([list(GenLSP.Structures.TextEdit.schematic()), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/type_hierarchy_subtypes.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/type_hierarchy_subtypes.ex new file mode 100644 index 000000000..a4f89d210 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/type_hierarchy_subtypes.ex @@ -0,0 +1,43 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TypeHierarchySubtypes do + @moduledoc """ + A request to resolve the subtypes for a given `TypeHierarchyItem`. + + @since 3.17.0 + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "typeHierarchy/subtypes") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.TypeHierarchySubtypesParams.t()) + end + + @type result :: list(GenLSP.Structures.TypeHierarchyItem.t()) | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "typeHierarchy/subtypes", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.TypeHierarchySubtypesParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([list(GenLSP.Structures.TypeHierarchyItem.schematic()), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/type_hierarchy_supertypes.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/type_hierarchy_supertypes.ex new file mode 100644 index 000000000..b71ffd1f2 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/type_hierarchy_supertypes.ex @@ -0,0 +1,43 @@ +# codegen: do not edit +defmodule GenLSP.Requests.TypeHierarchySupertypes do + @moduledoc """ + A request to resolve the supertypes for a given `TypeHierarchyItem`. + + @since 3.17.0 + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "typeHierarchy/supertypes") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.TypeHierarchySupertypesParams.t()) + end + + @type result :: list(GenLSP.Structures.TypeHierarchyItem.t()) | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "typeHierarchy/supertypes", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.TypeHierarchySupertypesParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([list(GenLSP.Structures.TypeHierarchyItem.schematic()), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/window_show_document.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/window_show_document.ex new file mode 100644 index 000000000..573b5caa8 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/window_show_document.ex @@ -0,0 +1,46 @@ +# codegen: do not edit +defmodule GenLSP.Requests.WindowShowDocument do + @moduledoc """ + A request to show a document. This request might open an + external program depending on the value of the URI to open. + For example a request to open `https://code.visualstudio.com/` + will very likely open the URI in a WEB browser. + + @since 3.16.0 + + Message Direction: serverToClient + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "window/showDocument") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.ShowDocumentParams.t()) + end + + @type result :: GenLSP.Structures.ShowDocumentResult.t() + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "window/showDocument", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.ShowDocumentParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + GenLSP.Structures.ShowDocumentResult.schematic(), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/window_show_message_request.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/window_show_message_request.ex new file mode 100644 index 000000000..2fd7bde65 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/window_show_message_request.ex @@ -0,0 +1,42 @@ +# codegen: do not edit +defmodule GenLSP.Requests.WindowShowMessageRequest do + @moduledoc """ + The show message request is sent from the server to the client to show a message + and a set of options actions to the user. + + Message Direction: serverToClient + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "window/showMessageRequest") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.ShowMessageRequestParams.t()) + end + + @type result :: GenLSP.Structures.MessageActionItem.t() | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "window/showMessageRequest", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.ShowMessageRequestParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([GenLSP.Structures.MessageActionItem.schematic(), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/window_work_done_progress_create.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/window_work_done_progress_create.ex new file mode 100644 index 000000000..c679de888 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/window_work_done_progress_create.ex @@ -0,0 +1,42 @@ +# codegen: do not edit +defmodule GenLSP.Requests.WindowWorkDoneProgressCreate do + @moduledoc """ + The `window/workDoneProgress/create` request is sent from the server to the client to initiate progress + reporting from the server. + + Message Direction: serverToClient + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "window/workDoneProgress/create") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.WorkDoneProgressCreateParams.t()) + end + + @type result :: nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "window/workDoneProgress/create", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.WorkDoneProgressCreateParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + nil, + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_apply_edit.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_apply_edit.ex new file mode 100644 index 000000000..56c5c83df --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_apply_edit.ex @@ -0,0 +1,41 @@ +# codegen: do not edit +defmodule GenLSP.Requests.WorkspaceApplyEdit do + @moduledoc """ + A request sent from the server to the client to modified certain resources. + + Message Direction: serverToClient + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "workspace/applyEdit") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.ApplyWorkspaceEditParams.t()) + end + + @type result :: GenLSP.Structures.ApplyWorkspaceEditResult.t() + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "workspace/applyEdit", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.ApplyWorkspaceEditParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + GenLSP.Structures.ApplyWorkspaceEditResult.schematic(), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_code_lens_refresh.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_code_lens_refresh.ex new file mode 100644 index 000000000..56178a47c --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_code_lens_refresh.ex @@ -0,0 +1,41 @@ +# codegen: do not edit +defmodule GenLSP.Requests.WorkspaceCodeLensRefresh do + @moduledoc """ + A request to refresh all code actions + + @since 3.16.0 + + Message Direction: serverToClient + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "workspace/codeLens/refresh") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + end + + @type result :: nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "workspace/codeLens/refresh", + jsonrpc: "2.0", + id: int() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + nil, + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_configuration.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_configuration.ex new file mode 100644 index 000000000..f930d4503 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_configuration.ex @@ -0,0 +1,47 @@ +# codegen: do not edit +defmodule GenLSP.Requests.WorkspaceConfiguration do + @moduledoc """ + The 'workspace/configuration' request is sent from the server to the client to fetch a certain + configuration setting. + + This pull model replaces the old push model were the client signaled configuration change via an + event. If the server still needs to react to configuration changes (since the server caches the + result of `workspace/configuration` requests) the server should register for an empty configuration + change event and empty the cache if such an event is received. + + Message Direction: serverToClient + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "workspace/configuration") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.ConfigurationParams.t()) + end + + @type result :: list(GenLSP.TypeAlias.LSPAny.t()) + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "workspace/configuration", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.ConfigurationParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + list(GenLSP.TypeAlias.LSPAny.schematic()), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_diagnostic.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_diagnostic.ex new file mode 100644 index 000000000..9c1685e41 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_diagnostic.ex @@ -0,0 +1,43 @@ +# codegen: do not edit +defmodule GenLSP.Requests.WorkspaceDiagnostic do + @moduledoc """ + The workspace diagnostic request definition. + + @since 3.17.0 + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "workspace/diagnostic") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.WorkspaceDiagnosticParams.t()) + end + + @type result :: GenLSP.Structures.WorkspaceDiagnosticReport.t() + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "workspace/diagnostic", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.WorkspaceDiagnosticParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + GenLSP.Structures.WorkspaceDiagnosticReport.schematic(), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_diagnostic_refresh.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_diagnostic_refresh.ex new file mode 100644 index 000000000..a3350b23a --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_diagnostic_refresh.ex @@ -0,0 +1,41 @@ +# codegen: do not edit +defmodule GenLSP.Requests.WorkspaceDiagnosticRefresh do + @moduledoc """ + The diagnostic refresh request definition. + + @since 3.17.0 + + Message Direction: serverToClient + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "workspace/diagnostic/refresh") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + end + + @type result :: nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "workspace/diagnostic/refresh", + jsonrpc: "2.0", + id: int() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + nil, + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_execute_command.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_execute_command.ex new file mode 100644 index 000000000..90076a1e1 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_execute_command.ex @@ -0,0 +1,42 @@ +# codegen: do not edit +defmodule GenLSP.Requests.WorkspaceExecuteCommand do + @moduledoc """ + A request send from the client to the server to execute a command. The request might return + a workspace edit which the client will apply to the workspace. + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "workspace/executeCommand") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.ExecuteCommandParams.t()) + end + + @type result :: GenLSP.TypeAlias.LSPAny.t() | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "workspace/executeCommand", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.ExecuteCommandParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([GenLSP.TypeAlias.LSPAny.schematic(), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_inlay_hint_refresh.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_inlay_hint_refresh.ex new file mode 100644 index 000000000..1b0eb3a8e --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_inlay_hint_refresh.ex @@ -0,0 +1,39 @@ +# codegen: do not edit +defmodule GenLSP.Requests.WorkspaceInlayHintRefresh do + @moduledoc """ + @since 3.17.0 + + Message Direction: serverToClient + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "workspace/inlayHint/refresh") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + end + + @type result :: nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "workspace/inlayHint/refresh", + jsonrpc: "2.0", + id: int() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + nil, + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_inline_value_refresh.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_inline_value_refresh.ex new file mode 100644 index 000000000..75860fcdc --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_inline_value_refresh.ex @@ -0,0 +1,39 @@ +# codegen: do not edit +defmodule GenLSP.Requests.WorkspaceInlineValueRefresh do + @moduledoc """ + @since 3.17.0 + + Message Direction: serverToClient + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "workspace/inlineValue/refresh") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + end + + @type result :: nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "workspace/inlineValue/refresh", + jsonrpc: "2.0", + id: int() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + nil, + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_semantic_tokens_refresh.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_semantic_tokens_refresh.ex new file mode 100644 index 000000000..d4c21ff50 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_semantic_tokens_refresh.ex @@ -0,0 +1,39 @@ +# codegen: do not edit +defmodule GenLSP.Requests.WorkspaceSemanticTokensRefresh do + @moduledoc """ + @since 3.16.0 + + Message Direction: serverToClient + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "workspace/semanticTokens/refresh") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + end + + @type result :: nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "workspace/semanticTokens/refresh", + jsonrpc: "2.0", + id: int() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + nil, + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_symbol.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_symbol.ex new file mode 100644 index 000000000..0db5d71b5 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_symbol.ex @@ -0,0 +1,56 @@ +# codegen: do not edit +defmodule GenLSP.Requests.WorkspaceSymbol do + @moduledoc """ + A request to list project-wide symbols matching the query string given + by the {@link WorkspaceSymbolParams}. The response is + of type {@link SymbolInformation SymbolInformation[]} or a Thenable that + resolves to such. + + @since 3.17.0 - support for WorkspaceSymbol in the returned data. Clients + need to advertise support for WorkspaceSymbols via the client capability + `workspace.symbol.resolveSupport`. + + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "workspace/symbol") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.WorkspaceSymbolParams.t()) + end + + @type result :: + list(GenLSP.Structures.SymbolInformation.t()) + | list(GenLSP.Structures.WorkspaceSymbol.t()) + | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "workspace/symbol", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.WorkspaceSymbolParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([ + list(GenLSP.Structures.SymbolInformation.schematic()), + list(GenLSP.Structures.WorkspaceSymbol.schematic()), + nil + ]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_symbol_resolve.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_symbol_resolve.ex new file mode 100644 index 000000000..cdd7a2e02 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_symbol_resolve.ex @@ -0,0 +1,44 @@ +# codegen: do not edit +defmodule GenLSP.Requests.WorkspaceSymbolResolve do + @moduledoc """ + A request to resolve the range inside the workspace + symbol's location. + + @since 3.17.0 + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "workspaceSymbol/resolve") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.WorkspaceSymbol.t()) + end + + @type result :: GenLSP.Structures.WorkspaceSymbol.t() + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "workspaceSymbol/resolve", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.WorkspaceSymbol.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + GenLSP.Structures.WorkspaceSymbol.schematic(), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_will_create_files.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_will_create_files.ex new file mode 100644 index 000000000..61d61f45c --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_will_create_files.ex @@ -0,0 +1,44 @@ +# codegen: do not edit +defmodule GenLSP.Requests.WorkspaceWillCreateFiles do + @moduledoc """ + The will create files request is sent from the client to the server before files are actually + created as long as the creation is triggered from within the client. + + @since 3.16.0 + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "workspace/willCreateFiles") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.CreateFilesParams.t()) + end + + @type result :: GenLSP.Structures.WorkspaceEdit.t() | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "workspace/willCreateFiles", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.CreateFilesParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([GenLSP.Structures.WorkspaceEdit.schematic(), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_will_delete_files.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_will_delete_files.ex new file mode 100644 index 000000000..9b5230aa6 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_will_delete_files.ex @@ -0,0 +1,44 @@ +# codegen: do not edit +defmodule GenLSP.Requests.WorkspaceWillDeleteFiles do + @moduledoc """ + The did delete files notification is sent from the client to the server when + files were deleted from within the client. + + @since 3.16.0 + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "workspace/willDeleteFiles") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.DeleteFilesParams.t()) + end + + @type result :: GenLSP.Structures.WorkspaceEdit.t() | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "workspace/willDeleteFiles", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.DeleteFilesParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([GenLSP.Structures.WorkspaceEdit.schematic(), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_will_rename_files.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_will_rename_files.ex new file mode 100644 index 000000000..501657b27 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_will_rename_files.ex @@ -0,0 +1,44 @@ +# codegen: do not edit +defmodule GenLSP.Requests.WorkspaceWillRenameFiles do + @moduledoc """ + The will rename files request is sent from the client to the server before files are actually + renamed as long as the rename is triggered from within the client. + + @since 3.16.0 + + Message Direction: clientToServer + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "workspace/willRenameFiles") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + field(:params, GenLSP.Structures.RenameFilesParams.t()) + end + + @type result :: GenLSP.Structures.WorkspaceEdit.t() | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "workspace/willRenameFiles", + jsonrpc: "2.0", + id: int(), + params: GenLSP.Structures.RenameFilesParams.schematic() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([GenLSP.Structures.WorkspaceEdit.schematic(), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_workspace_folders.ex b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_workspace_folders.ex new file mode 100644 index 000000000..a3e939de4 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/requests/workspace_workspace_folders.ex @@ -0,0 +1,39 @@ +# codegen: do not edit +defmodule GenLSP.Requests.WorkspaceWorkspaceFolders do + @moduledoc """ + The `workspace/workspaceFolders` is sent from the server to the client to fetch the open workspace folders. + + Message Direction: serverToClient + """ + + import SchematicV, warn: false + + use TypedStruct + + typedstruct do + field(:method, String.t(), default: "workspace/workspaceFolders") + field(:jsonrpc, String.t(), default: "2.0") + field(:id, integer(), enforce: true) + end + + @type result :: list(GenLSP.Structures.WorkspaceFolder.t()) | nil + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + method: "workspace/workspaceFolders", + jsonrpc: "2.0", + id: int() + }) + end + + @doc false + @spec result() :: SchematicV.t() + def result() do + oneof([ + oneof([list(GenLSP.Structures.WorkspaceFolder.schematic()), nil]), + GenLSP.ErrorResponse.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/annotated_text_edit.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/annotated_text_edit.ex new file mode 100644 index 000000000..5b1e75506 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/annotated_text_edit.ex @@ -0,0 +1,38 @@ +# codegen: do not edit +defmodule GenLSP.Structures.AnnotatedTextEdit do + @moduledoc """ + A special text edit with an additional change annotation. + + @since 3.16.0. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * annotation_id: The actual identifier of the change annotation + * range: The range of the text document to be manipulated. To insert + text into a document create a range where start === end. + * new_text: The string to be inserted. For delete operations use an + empty string. + """ + + typedstruct do + field(:annotation_id, GenLSP.TypeAlias.ChangeAnnotationIdentifier.t(), enforce: true) + field(:range, GenLSP.Structures.Range.t(), enforce: true) + field(:new_text, String.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"annotationId", :annotation_id} => GenLSP.TypeAlias.ChangeAnnotationIdentifier.schematic(), + {"range", :range} => GenLSP.Structures.Range.schematic(), + {"newText", :new_text} => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/apply_workspace_edit_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/apply_workspace_edit_params.ex new file mode 100644 index 000000000..9bd9cd06d --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/apply_workspace_edit_params.ex @@ -0,0 +1,33 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ApplyWorkspaceEditParams do + @moduledoc """ + The parameters passed via an apply workspace edit request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * label: An optional label of the workspace edit. This label is + presented in the user interface for example on an undo + stack to undo the workspace edit. + * edit: The edits to apply. + """ + + typedstruct do + field(:label, String.t()) + field(:edit, GenLSP.Structures.WorkspaceEdit.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"label", :label}) => str(), + {"edit", :edit} => GenLSP.Structures.WorkspaceEdit.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/apply_workspace_edit_result.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/apply_workspace_edit_result.ex new file mode 100644 index 000000000..bca27b0d3 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/apply_workspace_edit_result.ex @@ -0,0 +1,40 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ApplyWorkspaceEditResult do + @moduledoc """ + The result returned from the apply workspace edit request. + + @since 3.17 renamed from ApplyWorkspaceEditResponse + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * applied: Indicates whether the edit was applied or not. + * failure_reason: An optional textual description for why the edit was not applied. + This may be used by the server for diagnostic logging or to provide + a suitable error for a request that triggered the edit. + * failed_change: Depending on the client's failure handling strategy `failedChange` might + contain the index of the change that failed. This property is only available + if the client signals a `failureHandlingStrategy` in its client capabilities. + """ + + typedstruct do + field(:applied, boolean(), enforce: true) + field(:failure_reason, String.t()) + field(:failed_change, GenLSP.BaseTypes.uinteger()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"applied", :applied} => bool(), + optional({"failureReason", :failure_reason}) => str(), + optional({"failedChange", :failed_change}) => int() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/base_symbol_information.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/base_symbol_information.ex new file mode 100644 index 000000000..d54f4ebd3 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/base_symbol_information.ex @@ -0,0 +1,42 @@ +# codegen: do not edit +defmodule GenLSP.Structures.BaseSymbolInformation do + @moduledoc """ + A base for all symbol information. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * name: The name of this symbol. + * kind: The kind of this symbol. + * tags: Tags for this symbol. + + @since 3.16.0 + * container_name: The name of the symbol containing this symbol. This information is for + user interface purposes (e.g. to render a qualifier in the user interface + if necessary). It can't be used to re-infer a hierarchy for the document + symbols. + """ + + typedstruct do + field(:name, String.t(), enforce: true) + field(:kind, GenLSP.Enumerations.SymbolKind.t(), enforce: true) + field(:tags, list(GenLSP.Enumerations.SymbolTag.t())) + field(:container_name, String.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"name", :name} => str(), + {"kind", :kind} => GenLSP.Enumerations.SymbolKind.schematic(), + optional({"tags", :tags}) => list(GenLSP.Enumerations.SymbolTag.schematic()), + optional({"containerName", :container_name}) => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/call_hierarchy_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/call_hierarchy_client_capabilities.ex new file mode 100644 index 000000000..a0290407f --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/call_hierarchy_client_capabilities.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CallHierarchyClientCapabilities do + @moduledoc """ + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether implementation supports dynamic registration. If this is set to `true` + the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)` + return value for the corresponding server capability as well. + """ + + typedstruct do + field(:dynamic_registration, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/call_hierarchy_incoming_call.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/call_hierarchy_incoming_call.ex new file mode 100644 index 000000000..b31050afa --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/call_hierarchy_incoming_call.ex @@ -0,0 +1,34 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CallHierarchyIncomingCall do + @moduledoc """ + Represents an incoming call, e.g. a caller of a method or constructor. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * from: The item that makes the call. + * from_ranges: The ranges at which the calls appear. This is relative to the caller + denoted by {@link CallHierarchyIncomingCall.from `this.from`}. + """ + + typedstruct do + field(:from, GenLSP.Structures.CallHierarchyItem.t(), enforce: true) + field(:from_ranges, list(GenLSP.Structures.Range.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"from", :from} => GenLSP.Structures.CallHierarchyItem.schematic(), + {"fromRanges", :from_ranges} => list(GenLSP.Structures.Range.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/call_hierarchy_incoming_calls_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/call_hierarchy_incoming_calls_params.ex new file mode 100644 index 000000000..5e739d0a5 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/call_hierarchy_incoming_calls_params.ex @@ -0,0 +1,38 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CallHierarchyIncomingCallsParams do + @moduledoc """ + The parameter of a `callHierarchy/incomingCalls` request. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * item + * work_done_token: An optional token that a server can use to report work done progress. + * partial_result_token: An optional token that a server can use to report partial results (e.g. streaming) to + the client. + """ + + typedstruct do + field(:item, GenLSP.Structures.CallHierarchyItem.t(), enforce: true) + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:partial_result_token, GenLSP.TypeAlias.ProgressToken.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"item", :item} => GenLSP.Structures.CallHierarchyItem.schematic(), + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + optional({"partialResultToken", :partial_result_token}) => + GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/call_hierarchy_item.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/call_hierarchy_item.ex new file mode 100644 index 000000000..acc7cb0e9 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/call_hierarchy_item.ex @@ -0,0 +1,54 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CallHierarchyItem do + @moduledoc """ + Represents programming constructs like functions or constructors in the context + of call hierarchy. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * name: The name of this item. + * kind: The kind of this item. + * tags: Tags for this item. + * detail: More detail for this item, e.g. the signature of a function. + * uri: The resource identifier of this item. + * range: The range enclosing this symbol not including leading/trailing whitespace but everything else, e.g. comments and code. + * selection_range: The range that should be selected and revealed when this symbol is being picked, e.g. the name of a function. + Must be contained by the {@link CallHierarchyItem.range `range`}. + * data: A data entry field that is preserved between a call hierarchy prepare and + incoming calls or outgoing calls requests. + """ + + typedstruct do + field(:name, String.t(), enforce: true) + field(:kind, GenLSP.Enumerations.SymbolKind.t(), enforce: true) + field(:tags, list(GenLSP.Enumerations.SymbolTag.t())) + field(:detail, String.t()) + field(:uri, GenLSP.BaseTypes.document_uri(), enforce: true) + field(:range, GenLSP.Structures.Range.t(), enforce: true) + field(:selection_range, GenLSP.Structures.Range.t(), enforce: true) + field(:data, GenLSP.TypeAlias.LSPAny.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"name", :name} => str(), + {"kind", :kind} => GenLSP.Enumerations.SymbolKind.schematic(), + optional({"tags", :tags}) => list(GenLSP.Enumerations.SymbolTag.schematic()), + optional({"detail", :detail}) => str(), + {"uri", :uri} => str(), + {"range", :range} => GenLSP.Structures.Range.schematic(), + {"selectionRange", :selection_range} => GenLSP.Structures.Range.schematic(), + optional({"data", :data}) => GenLSP.TypeAlias.LSPAny.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/call_hierarchy_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/call_hierarchy_options.ex new file mode 100644 index 000000000..6d895434f --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/call_hierarchy_options.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CallHierarchyOptions do + @moduledoc """ + Call hierarchy options used during static registration. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_progress + """ + + typedstruct do + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/call_hierarchy_outgoing_call.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/call_hierarchy_outgoing_call.ex new file mode 100644 index 000000000..727e774cb --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/call_hierarchy_outgoing_call.ex @@ -0,0 +1,35 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CallHierarchyOutgoingCall do + @moduledoc """ + Represents an outgoing call, e.g. calling a getter from a method or a method from a constructor etc. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * to: The item that is called. + * from_ranges: The range at which this item is called. This is the range relative to the caller, e.g the item + passed to {@link CallHierarchyItemProvider.provideCallHierarchyOutgoingCalls `provideCallHierarchyOutgoingCalls`} + and not {@link CallHierarchyOutgoingCall.to `this.to`}. + """ + + typedstruct do + field(:to, GenLSP.Structures.CallHierarchyItem.t(), enforce: true) + field(:from_ranges, list(GenLSP.Structures.Range.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"to", :to} => GenLSP.Structures.CallHierarchyItem.schematic(), + {"fromRanges", :from_ranges} => list(GenLSP.Structures.Range.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/call_hierarchy_outgoing_calls_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/call_hierarchy_outgoing_calls_params.ex new file mode 100644 index 000000000..9b36f7eca --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/call_hierarchy_outgoing_calls_params.ex @@ -0,0 +1,38 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CallHierarchyOutgoingCallsParams do + @moduledoc """ + The parameter of a `callHierarchy/outgoingCalls` request. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * item + * work_done_token: An optional token that a server can use to report work done progress. + * partial_result_token: An optional token that a server can use to report partial results (e.g. streaming) to + the client. + """ + + typedstruct do + field(:item, GenLSP.Structures.CallHierarchyItem.t(), enforce: true) + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:partial_result_token, GenLSP.TypeAlias.ProgressToken.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"item", :item} => GenLSP.Structures.CallHierarchyItem.schematic(), + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + optional({"partialResultToken", :partial_result_token}) => + GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/call_hierarchy_prepare_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/call_hierarchy_prepare_params.ex new file mode 100644 index 000000000..8d10e519e --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/call_hierarchy_prepare_params.ex @@ -0,0 +1,36 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CallHierarchyPrepareParams do + @moduledoc """ + The parameter of a `textDocument/prepareCallHierarchy` request. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_token: An optional token that a server can use to report work done progress. + * text_document: The text document. + * position: The position inside the text document. + """ + + typedstruct do + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:position, GenLSP.Structures.Position.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + {"position", :position} => GenLSP.Structures.Position.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/call_hierarchy_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/call_hierarchy_registration_options.ex new file mode 100644 index 000000000..e997e71aa --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/call_hierarchy_registration_options.ex @@ -0,0 +1,36 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CallHierarchyRegistrationOptions do + @moduledoc """ + Call hierarchy options used during static or dynamic registration. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * id: The id used to register the request. The id can be used to deregister + the request again. See also Registration#id. + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + """ + + typedstruct do + field(:id, String.t()) + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"id", :id}) => str(), + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/cancel_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/cancel_params.ex new file mode 100644 index 000000000..77a5d9ebf --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/cancel_params.ex @@ -0,0 +1,24 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CancelParams do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * id: The request id to cancel. + """ + + typedstruct do + field(:id, integer() | String.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"id", :id} => oneof([int(), str()]) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/change_annotation.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/change_annotation.ex new file mode 100644 index 000000000..31f6426ad --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/change_annotation.ex @@ -0,0 +1,39 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ChangeAnnotation do + @moduledoc """ + Additional information that describes document changes. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * label: A human-readable string describing the actual change. The string + is rendered prominent in the user interface. + * needs_confirmation: A flag which indicates that user confirmation is needed + before applying the change. + * description: A human-readable string which is rendered less prominent in + the user interface. + """ + + typedstruct do + field(:label, String.t(), enforce: true) + field(:needs_confirmation, boolean()) + field(:description, String.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"label", :label} => str(), + optional({"needsConfirmation", :needs_confirmation}) => bool(), + optional({"description", :description}) => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/client_capabilities.ex new file mode 100644 index 000000000..be5257536 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/client_capabilities.ex @@ -0,0 +1,50 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ClientCapabilities do + @moduledoc """ + Defines the capabilities provided by the client. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * workspace: Workspace specific client capabilities. + * text_document: Text document specific client capabilities. + * notebook_document: Capabilities specific to the notebook document support. + + @since 3.17.0 + * window: Window specific client capabilities. + * general: General client capabilities. + + @since 3.16.0 + * experimental: Experimental client capabilities. + """ + + typedstruct do + field(:workspace, GenLSP.Structures.WorkspaceClientCapabilities.t()) + field(:text_document, GenLSP.Structures.TextDocumentClientCapabilities.t()) + field(:notebook_document, GenLSP.Structures.NotebookDocumentClientCapabilities.t()) + field(:window, GenLSP.Structures.WindowClientCapabilities.t()) + field(:general, GenLSP.Structures.GeneralClientCapabilities.t()) + field(:experimental, GenLSP.TypeAlias.LSPAny.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workspace", :workspace}) => + GenLSP.Structures.WorkspaceClientCapabilities.schematic(), + optional({"textDocument", :text_document}) => + GenLSP.Structures.TextDocumentClientCapabilities.schematic(), + optional({"notebookDocument", :notebook_document}) => + GenLSP.Structures.NotebookDocumentClientCapabilities.schematic(), + optional({"window", :window}) => GenLSP.Structures.WindowClientCapabilities.schematic(), + optional({"general", :general}) => GenLSP.Structures.GeneralClientCapabilities.schematic(), + optional({"experimental", :experimental}) => GenLSP.TypeAlias.LSPAny.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/code_action.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/code_action.ex new file mode 100644 index 000000000..912c5f973 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/code_action.ex @@ -0,0 +1,82 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CodeAction do + @moduledoc """ + A code action represents a change that can be performed in code, e.g. to fix a problem or + to refactor code. + + A CodeAction must set either `edit` and/or a `command`. If both are supplied, the `edit` is applied first, then the `command` is executed. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * title: A short, human-readable, title for this code action. + * kind: The kind of the code action. + + Used to filter code actions. + * diagnostics: The diagnostics that this code action resolves. + * is_preferred: Marks this as a preferred action. Preferred actions are used by the `auto fix` command and can be targeted + by keybindings. + + A quick fix should be marked preferred if it properly addresses the underlying error. + A refactoring should be marked preferred if it is the most reasonable choice of actions to take. + + @since 3.15.0 + * disabled: Marks that the code action cannot currently be applied. + + Clients should follow the following guidelines regarding disabled code actions: + + - Disabled code actions are not shown in automatic [lightbulbs](https://code.visualstudio.com/docs/editor/editingevolved#_code-action) + code action menus. + + - Disabled actions are shown as faded out in the code action menu when the user requests a more specific type + of code action, such as refactorings. + + - If the user has a [keybinding](https://code.visualstudio.com/docs/editor/refactoring#_keybindings-for-code-actions) + that auto applies a code action and only disabled code actions are returned, the client should show the user an + error message with `reason` in the editor. + + @since 3.16.0 + * edit: The workspace edit this code action performs. + * command: A command this code action executes. If a code action + provides an edit and a command, first the edit is + executed and then the command. + * data: A data entry field that is preserved on a code action between + a `textDocument/codeAction` and a `codeAction/resolve` request. + + @since 3.16.0 + """ + + typedstruct do + field(:title, String.t(), enforce: true) + field(:kind, GenLSP.Enumerations.CodeActionKind.t()) + field(:diagnostics, list(GenLSP.Structures.Diagnostic.t())) + field(:is_preferred, boolean()) + field(:disabled, map()) + field(:edit, GenLSP.Structures.WorkspaceEdit.t()) + field(:command, GenLSP.Structures.Command.t()) + field(:data, GenLSP.TypeAlias.LSPAny.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"title", :title} => str(), + optional({"kind", :kind}) => GenLSP.Enumerations.CodeActionKind.schematic(), + optional({"diagnostics", :diagnostics}) => list(GenLSP.Structures.Diagnostic.schematic()), + optional({"isPreferred", :is_preferred}) => bool(), + optional({"disabled", :disabled}) => + map(%{ + {"reason", :reason} => str() + }), + optional({"edit", :edit}) => GenLSP.Structures.WorkspaceEdit.schematic(), + optional({"command", :command}) => GenLSP.Structures.Command.schematic(), + optional({"data", :data}) => GenLSP.TypeAlias.LSPAny.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/code_action_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/code_action_client_capabilities.ex new file mode 100644 index 000000000..c499dedfd --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/code_action_client_capabilities.ex @@ -0,0 +1,76 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CodeActionClientCapabilities do + @moduledoc """ + The Client Capabilities of a {@link CodeActionRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether code action supports dynamic registration. + * code_action_literal_support: The client support code action literals of type `CodeAction` as a valid + response of the `textDocument/codeAction` request. If the property is not + set the request can only return `Command` literals. + + @since 3.8.0 + * is_preferred_support: Whether code action supports the `isPreferred` property. + + @since 3.15.0 + * disabled_support: Whether code action supports the `disabled` property. + + @since 3.16.0 + * data_support: Whether code action supports the `data` property which is + preserved between a `textDocument/codeAction` and a + `codeAction/resolve` request. + + @since 3.16.0 + * resolve_support: Whether the client supports resolving additional code action + properties via a separate `codeAction/resolve` request. + + @since 3.16.0 + * honors_change_annotations: Whether the client honors the change annotations in + text edits and resource operations returned via the + `CodeAction#edit` property by for example presenting + the workspace edit in the user interface and asking + for confirmation. + + @since 3.16.0 + """ + + typedstruct do + field(:dynamic_registration, boolean()) + field(:code_action_literal_support, map()) + field(:is_preferred_support, boolean()) + field(:disabled_support, boolean()) + field(:data_support, boolean()) + field(:resolve_support, map()) + field(:honors_change_annotations, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool(), + optional({"codeActionLiteralSupport", :code_action_literal_support}) => + map(%{ + {"codeActionKind", :code_action_kind} => + map(%{ + {"valueSet", :value_set} => list(GenLSP.Enumerations.CodeActionKind.schematic()) + }) + }), + optional({"isPreferredSupport", :is_preferred_support}) => bool(), + optional({"disabledSupport", :disabled_support}) => bool(), + optional({"dataSupport", :data_support}) => bool(), + optional({"resolveSupport", :resolve_support}) => + map(%{ + {"properties", :properties} => list(str()) + }), + optional({"honorsChangeAnnotations", :honors_change_annotations}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/code_action_context.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/code_action_context.ex new file mode 100644 index 000000000..18c3aac2d --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/code_action_context.ex @@ -0,0 +1,45 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CodeActionContext do + @moduledoc """ + Contains additional diagnostic information about the context in which + a {@link CodeActionProvider.provideCodeActions code action} is run. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * diagnostics: An array of diagnostics known on the client side overlapping the range provided to the + `textDocument/codeAction` request. They are provided so that the server knows which + errors are currently presented to the user for the given range. There is no guarantee + that these accurately reflect the error state of the resource. The primary parameter + to compute code actions is the provided range. + * only: Requested kind of actions to return. + + Actions not of this kind are filtered out by the client before being shown. So servers + can omit computing them. + * trigger_kind: The reason why code actions were requested. + + @since 3.17.0 + """ + + typedstruct do + field(:diagnostics, list(GenLSP.Structures.Diagnostic.t()), enforce: true) + field(:only, list(GenLSP.Enumerations.CodeActionKind.t())) + field(:trigger_kind, GenLSP.Enumerations.CodeActionTriggerKind.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"diagnostics", :diagnostics} => list(GenLSP.Structures.Diagnostic.schematic()), + optional({"only", :only}) => list(GenLSP.Enumerations.CodeActionKind.schematic()), + optional({"triggerKind", :trigger_kind}) => + GenLSP.Enumerations.CodeActionTriggerKind.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/code_action_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/code_action_options.ex new file mode 100644 index 000000000..a1dcb0d24 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/code_action_options.ex @@ -0,0 +1,41 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CodeActionOptions do + @moduledoc """ + Provider options for a {@link CodeActionRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * code_action_kinds: CodeActionKinds that this server may return. + + The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server + may list out every specific kind they provide. + * resolve_provider: The server provides support to resolve additional + information for a code action. + + @since 3.16.0 + * work_done_progress + """ + + typedstruct do + field(:code_action_kinds, list(GenLSP.Enumerations.CodeActionKind.t())) + field(:resolve_provider, boolean()) + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"codeActionKinds", :code_action_kinds}) => + list(GenLSP.Enumerations.CodeActionKind.schematic()), + optional({"resolveProvider", :resolve_provider}) => bool(), + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/code_action_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/code_action_params.ex new file mode 100644 index 000000000..c3f759a43 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/code_action_params.ex @@ -0,0 +1,42 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CodeActionParams do + @moduledoc """ + The parameters of a {@link CodeActionRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * text_document: The document in which the command was invoked. + * range: The range for which the command was invoked. + * context: Context carrying additional information. + * work_done_token: An optional token that a server can use to report work done progress. + * partial_result_token: An optional token that a server can use to report partial results (e.g. streaming) to + the client. + """ + + typedstruct do + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:range, GenLSP.Structures.Range.t(), enforce: true) + field(:context, GenLSP.Structures.CodeActionContext.t(), enforce: true) + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:partial_result_token, GenLSP.TypeAlias.ProgressToken.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + {"range", :range} => GenLSP.Structures.Range.schematic(), + {"context", :context} => GenLSP.Structures.CodeActionContext.schematic(), + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + optional({"partialResultToken", :partial_result_token}) => + GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/code_action_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/code_action_registration_options.ex new file mode 100644 index 000000000..d852d147c --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/code_action_registration_options.ex @@ -0,0 +1,43 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CodeActionRegistrationOptions do + @moduledoc """ + Registration options for a {@link CodeActionRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + * code_action_kinds: CodeActionKinds that this server may return. + + The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server + may list out every specific kind they provide. + * resolve_provider: The server provides support to resolve additional + information for a code action. + + @since 3.16.0 + """ + + typedstruct do + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + field(:code_action_kinds, list(GenLSP.Enumerations.CodeActionKind.t())) + field(:resolve_provider, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]), + optional({"codeActionKinds", :code_action_kinds}) => + list(GenLSP.Enumerations.CodeActionKind.schematic()), + optional({"resolveProvider", :resolve_provider}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/code_description.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/code_description.ex new file mode 100644 index 000000000..7d4060246 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/code_description.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CodeDescription do + @moduledoc """ + Structure to capture a description for an error code. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * href: An URI to open with more information about the diagnostic error. + """ + + typedstruct do + field(:href, GenLSP.BaseTypes.uri(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"href", :href} => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/code_lens.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/code_lens.ex new file mode 100644 index 000000000..a90707a11 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/code_lens.ex @@ -0,0 +1,40 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CodeLens do + @moduledoc """ + A code lens represents a {@link Command command} that should be shown along with + source text, like the number of references, a way to run tests, etc. + + A code lens is _unresolved_ when no command is associated to it. For performance + reasons the creation of a code lens and resolving should be done in two stages. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * range: The range in which this code lens is valid. Should only span a single line. + * command: The command this code lens represents. + * data: A data entry field that is preserved on a code lens item between + a {@link CodeLensRequest} and a [CodeLensResolveRequest] + (#CodeLensResolveRequest) + """ + + typedstruct do + field(:range, GenLSP.Structures.Range.t(), enforce: true) + field(:command, GenLSP.Structures.Command.t()) + field(:data, GenLSP.TypeAlias.LSPAny.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"range", :range} => GenLSP.Structures.Range.schematic(), + optional({"command", :command}) => GenLSP.Structures.Command.schematic(), + optional({"data", :data}) => GenLSP.TypeAlias.LSPAny.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/code_lens_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/code_lens_client_capabilities.ex new file mode 100644 index 000000000..50e785eeb --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/code_lens_client_capabilities.ex @@ -0,0 +1,28 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CodeLensClientCapabilities do + @moduledoc """ + The client capabilities of a {@link CodeLensRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether code lens supports dynamic registration. + """ + + typedstruct do + field(:dynamic_registration, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/code_lens_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/code_lens_options.ex new file mode 100644 index 000000000..d9b8b0418 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/code_lens_options.ex @@ -0,0 +1,31 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CodeLensOptions do + @moduledoc """ + Code Lens provider options of a {@link CodeLensRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * resolve_provider: Code lens has a resolve provider as well. + * work_done_progress + """ + + typedstruct do + field(:resolve_provider, boolean()) + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"resolveProvider", :resolve_provider}) => bool(), + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/code_lens_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/code_lens_params.ex new file mode 100644 index 000000000..1efc318be --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/code_lens_params.ex @@ -0,0 +1,36 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CodeLensParams do + @moduledoc """ + The parameters of a {@link CodeLensRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * text_document: The document to request code lens for. + * work_done_token: An optional token that a server can use to report work done progress. + * partial_result_token: An optional token that a server can use to report partial results (e.g. streaming) to + the client. + """ + + typedstruct do + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:partial_result_token, GenLSP.TypeAlias.ProgressToken.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + optional({"partialResultToken", :partial_result_token}) => + GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/code_lens_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/code_lens_registration_options.ex new file mode 100644 index 000000000..cc6ec8ca9 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/code_lens_registration_options.ex @@ -0,0 +1,33 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CodeLensRegistrationOptions do + @moduledoc """ + Registration options for a {@link CodeLensRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + * resolve_provider: Code lens has a resolve provider as well. + """ + + typedstruct do + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + field(:resolve_provider, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]), + optional({"resolveProvider", :resolve_provider}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/code_lens_workspace_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/code_lens_workspace_client_capabilities.ex new file mode 100644 index 000000000..1665c82a1 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/code_lens_workspace_client_capabilities.ex @@ -0,0 +1,34 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CodeLensWorkspaceClientCapabilities do + @moduledoc """ + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * refresh_support: Whether the client implementation supports a refresh request sent from the + server to the client. + + Note that this event is global and will force the client to refresh all + code lenses currently shown. It should be used with absolute care and is + useful for situation where a server for example detect a project wide + change that requires such a calculation. + """ + + typedstruct do + field(:refresh_support, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"refreshSupport", :refresh_support}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/color.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/color.ex new file mode 100644 index 000000000..cfcfca6ee --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/color.ex @@ -0,0 +1,37 @@ +# codegen: do not edit +defmodule GenLSP.Structures.Color do + @moduledoc """ + Represents a color in RGBA space. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * red: The red component of this color in the range [0-1]. + * green: The green component of this color in the range [0-1]. + * blue: The blue component of this color in the range [0-1]. + * alpha: The alpha component of this color in the range [0-1]. + """ + + typedstruct do + field(:red, float(), enforce: true) + field(:green, float(), enforce: true) + field(:blue, float(), enforce: true) + field(:alpha, float(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"red", :red} => str(), + {"green", :green} => str(), + {"blue", :blue} => str(), + {"alpha", :alpha} => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/color_information.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/color_information.ex new file mode 100644 index 000000000..ded18d660 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/color_information.ex @@ -0,0 +1,31 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ColorInformation do + @moduledoc """ + Represents a color range from a document. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * range: The range in the document where this color appears. + * color: The actual color value for this color range. + """ + + typedstruct do + field(:range, GenLSP.Structures.Range.t(), enforce: true) + field(:color, GenLSP.Structures.Color.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"range", :range} => GenLSP.Structures.Range.schematic(), + {"color", :color} => GenLSP.Structures.Color.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/color_presentation.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/color_presentation.ex new file mode 100644 index 000000000..3cc21b42c --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/color_presentation.ex @@ -0,0 +1,36 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ColorPresentation do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * label: The label of this color presentation. It will be shown on the color + picker header. By default this is also the text that is inserted when selecting + this color presentation. + * text_edit: An {@link TextEdit edit} which is applied to a document when selecting + this presentation for the color. When `falsy` the {@link ColorPresentation.label label} + is used. + * additional_text_edits: An optional array of additional {@link TextEdit text edits} that are applied when + selecting this color presentation. Edits must not overlap with the main {@link ColorPresentation.textEdit edit} nor with themselves. + """ + + typedstruct do + field(:label, String.t(), enforce: true) + field(:text_edit, GenLSP.Structures.TextEdit.t()) + field(:additional_text_edits, list(GenLSP.Structures.TextEdit.t())) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"label", :label} => str(), + optional({"textEdit", :text_edit}) => GenLSP.Structures.TextEdit.schematic(), + optional({"additionalTextEdits", :additional_text_edits}) => + list(GenLSP.Structures.TextEdit.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/color_presentation_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/color_presentation_params.ex new file mode 100644 index 000000000..082d1c855 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/color_presentation_params.ex @@ -0,0 +1,42 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ColorPresentationParams do + @moduledoc """ + Parameters for a {@link ColorPresentationRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * text_document: The text document. + * color: The color to request presentations for. + * range: The range where the color would be inserted. Serves as a context. + * work_done_token: An optional token that a server can use to report work done progress. + * partial_result_token: An optional token that a server can use to report partial results (e.g. streaming) to + the client. + """ + + typedstruct do + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:color, GenLSP.Structures.Color.t(), enforce: true) + field(:range, GenLSP.Structures.Range.t(), enforce: true) + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:partial_result_token, GenLSP.TypeAlias.ProgressToken.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + {"color", :color} => GenLSP.Structures.Color.schematic(), + {"range", :range} => GenLSP.Structures.Range.schematic(), + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + optional({"partialResultToken", :partial_result_token}) => + GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/command.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/command.ex new file mode 100644 index 000000000..e6ba05ed6 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/command.ex @@ -0,0 +1,38 @@ +# codegen: do not edit +defmodule GenLSP.Structures.Command do + @moduledoc """ + Represents a reference to a command. Provides a title which + will be used to represent a command in the UI and, optionally, + an array of arguments which will be passed to the command handler + function when invoked. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * title: Title of the command, like `save`. + * command: The identifier of the actual command handler. + * arguments: Arguments that the command handler should be + invoked with. + """ + + typedstruct do + field(:title, String.t(), enforce: true) + field(:command, String.t(), enforce: true) + field(:arguments, list(GenLSP.TypeAlias.LSPAny.t())) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"title", :title} => str(), + {"command", :command} => str(), + optional({"arguments", :arguments}) => list(GenLSP.TypeAlias.LSPAny.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/completion_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/completion_client_capabilities.ex new file mode 100644 index 000000000..2a26bd096 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/completion_client_capabilities.ex @@ -0,0 +1,82 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CompletionClientCapabilities do + @moduledoc """ + Completion client capabilities + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether completion supports dynamic registration. + * completion_item: The client supports the following `CompletionItem` specific + capabilities. + * completion_item_kind + * insert_text_mode: Defines how the client handles whitespace and indentation + when accepting a completion item that uses multi line + text in either `insertText` or `textEdit`. + + @since 3.17.0 + * context_support: The client supports to send additional context information for a + `textDocument/completion` request. + * completion_list: The client supports the following `CompletionList` specific + capabilities. + + @since 3.17.0 + """ + + typedstruct do + field(:dynamic_registration, boolean()) + field(:completion_item, map()) + field(:completion_item_kind, map()) + field(:insert_text_mode, GenLSP.Enumerations.InsertTextMode.t()) + field(:context_support, boolean()) + field(:completion_list, map()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool(), + optional({"completionItem", :completion_item}) => + map(%{ + optional({"snippetSupport", :snippet_support}) => bool(), + optional({"commitCharactersSupport", :commit_characters_support}) => bool(), + optional({"documentationFormat", :documentation_format}) => + list(GenLSP.Enumerations.MarkupKind.schematic()), + optional({"deprecatedSupport", :deprecated_support}) => bool(), + optional({"preselectSupport", :preselect_support}) => bool(), + optional({"tagSupport", :tag_support}) => + map(%{ + {"valueSet", :value_set} => list(GenLSP.Enumerations.CompletionItemTag.schematic()) + }), + optional({"insertReplaceSupport", :insert_replace_support}) => bool(), + optional({"resolveSupport", :resolve_support}) => + map(%{ + {"properties", :properties} => list(str()) + }), + optional({"insertTextModeSupport", :insert_text_mode_support}) => + map(%{ + {"valueSet", :value_set} => list(GenLSP.Enumerations.InsertTextMode.schematic()) + }), + optional({"labelDetailsSupport", :label_details_support}) => bool() + }), + optional({"completionItemKind", :completion_item_kind}) => + map(%{ + optional({"valueSet", :value_set}) => + list(GenLSP.Enumerations.CompletionItemKind.schematic()) + }), + optional({"insertTextMode", :insert_text_mode}) => + GenLSP.Enumerations.InsertTextMode.schematic(), + optional({"contextSupport", :context_support}) => bool(), + optional({"completionList", :completion_list}) => + map(%{ + optional({"itemDefaults", :item_defaults}) => list(str()) + }) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/completion_context.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/completion_context.ex new file mode 100644 index 000000000..62ce01b90 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/completion_context.ex @@ -0,0 +1,32 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CompletionContext do + @moduledoc """ + Contains additional information about the context in which a completion request is triggered. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * trigger_kind: How the completion was triggered. + * trigger_character: The trigger character (a single character) that has trigger code complete. + Is undefined if `triggerKind !== CompletionTriggerKind.TriggerCharacter` + """ + + typedstruct do + field(:trigger_kind, GenLSP.Enumerations.CompletionTriggerKind.t(), enforce: true) + field(:trigger_character, String.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"triggerKind", :trigger_kind} => GenLSP.Enumerations.CompletionTriggerKind.schematic(), + optional({"triggerCharacter", :trigger_character}) => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/completion_item.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/completion_item.ex new file mode 100644 index 000000000..e87b4f62e --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/completion_item.ex @@ -0,0 +1,171 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CompletionItem do + @moduledoc """ + A completion item represents a text snippet that is + proposed to complete text that is being typed. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * label: The label of this completion item. + + The label property is also by default the text that + is inserted when selecting this completion. + + If label details are provided the label itself should + be an unqualified name of the completion item. + * label_details: Additional details for the label + + @since 3.17.0 + * kind: The kind of this completion item. Based of the kind + an icon is chosen by the editor. + * tags: Tags for this completion item. + + @since 3.15.0 + * detail: A human-readable string with additional information + about this item, like type or symbol information. + * documentation: A human-readable string that represents a doc-comment. + * deprecated: Indicates if this item is deprecated. + @deprecated Use `tags` instead. + * preselect: Select this item when showing. + + *Note* that only one completion item can be selected and that the + tool / client decides which item that is. The rule is that the *first* + item of those that match best is selected. + * sort_text: A string that should be used when comparing this item + with other items. When `falsy` the {@link CompletionItem.label label} + is used. + * filter_text: A string that should be used when filtering a set of + completion items. When `falsy` the {@link CompletionItem.label label} + is used. + * insert_text: A string that should be inserted into a document when selecting + this completion. When `falsy` the {@link CompletionItem.label label} + is used. + + The `insertText` is subject to interpretation by the client side. + Some tools might not take the string literally. For example + VS Code when code complete is requested in this example + `con` and a completion item with an `insertText` of + `console` is provided it will only insert `sole`. Therefore it is + recommended to use `textEdit` instead since it avoids additional client + side interpretation. + * insert_text_format: The format of the insert text. The format applies to both the + `insertText` property and the `newText` property of a provided + `textEdit`. If omitted defaults to `InsertTextFormat.PlainText`. + + Please note that the insertTextFormat doesn't apply to + `additionalTextEdits`. + * insert_text_mode: How whitespace and indentation is handled during completion + item insertion. If not provided the clients default value depends on + the `textDocument.completion.insertTextMode` client capability. + + @since 3.16.0 + * text_edit: An {@link TextEdit edit} which is applied to a document when selecting + this completion. When an edit is provided the value of + {@link CompletionItem.insertText insertText} is ignored. + + Most editors support two different operations when accepting a completion + item. One is to insert a completion text and the other is to replace an + existing text with a completion text. Since this can usually not be + predetermined by a server it can report both ranges. Clients need to + signal support for `InsertReplaceEdits` via the + `textDocument.completion.insertReplaceSupport` client capability + property. + + *Note 1:* The text edit's range as well as both ranges from an insert + replace edit must be a [single line] and they must contain the position + at which completion has been requested. + *Note 2:* If an `InsertReplaceEdit` is returned the edit's insert range + must be a prefix of the edit's replace range, that means it must be + contained and starting at the same position. + + @since 3.16.0 additional type `InsertReplaceEdit` + * text_edit_text: The edit text used if the completion item is part of a CompletionList and + CompletionList defines an item default for the text edit range. + + Clients will only honor this property if they opt into completion list + item defaults using the capability `completionList.itemDefaults`. + + If not provided and a list's default range is provided the label + property is used as a text. + + @since 3.17.0 + * additional_text_edits: An optional array of additional {@link TextEdit text edits} that are applied when + selecting this completion. Edits must not overlap (including the same insert position) + with the main {@link CompletionItem.textEdit edit} nor with themselves. + + Additional text edits should be used to change text unrelated to the current cursor position + (for example adding an import statement at the top of the file if the completion item will + insert an unqualified type). + * commit_characters: An optional set of characters that when pressed while this completion is active will accept it first and + then type that character. *Note* that all commit characters should have `length=1` and that superfluous + characters will be ignored. + * command: An optional {@link Command command} that is executed *after* inserting this completion. *Note* that + additional modifications to the current document should be described with the + {@link CompletionItem.additionalTextEdits additionalTextEdits}-property. + * data: A data entry field that is preserved on a completion item between a + {@link CompletionRequest} and a {@link CompletionResolveRequest}. + """ + + typedstruct do + field(:label, String.t(), enforce: true) + field(:label_details, GenLSP.Structures.CompletionItemLabelDetails.t()) + field(:kind, GenLSP.Enumerations.CompletionItemKind.t()) + field(:tags, list(GenLSP.Enumerations.CompletionItemTag.t())) + field(:detail, String.t()) + field(:documentation, String.t() | GenLSP.Structures.MarkupContent.t()) + field(:deprecated, boolean()) + field(:preselect, boolean()) + field(:sort_text, String.t()) + field(:filter_text, String.t()) + field(:insert_text, String.t()) + field(:insert_text_format, GenLSP.Enumerations.InsertTextFormat.t()) + field(:insert_text_mode, GenLSP.Enumerations.InsertTextMode.t()) + field(:text_edit, GenLSP.Structures.TextEdit.t() | GenLSP.Structures.InsertReplaceEdit.t()) + field(:text_edit_text, String.t()) + field(:additional_text_edits, list(GenLSP.Structures.TextEdit.t())) + field(:commit_characters, list(String.t())) + field(:command, GenLSP.Structures.Command.t()) + field(:data, GenLSP.TypeAlias.LSPAny.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"label", :label} => str(), + optional({"labelDetails", :label_details}) => + GenLSP.Structures.CompletionItemLabelDetails.schematic(), + optional({"kind", :kind}) => GenLSP.Enumerations.CompletionItemKind.schematic(), + optional({"tags", :tags}) => list(GenLSP.Enumerations.CompletionItemTag.schematic()), + optional({"detail", :detail}) => str(), + optional({"documentation", :documentation}) => + oneof([str(), GenLSP.Structures.MarkupContent.schematic()]), + optional({"deprecated", :deprecated}) => bool(), + optional({"preselect", :preselect}) => bool(), + optional({"sortText", :sort_text}) => str(), + optional({"filterText", :filter_text}) => str(), + optional({"insertText", :insert_text}) => str(), + optional({"insertTextFormat", :insert_text_format}) => + GenLSP.Enumerations.InsertTextFormat.schematic(), + optional({"insertTextMode", :insert_text_mode}) => + GenLSP.Enumerations.InsertTextMode.schematic(), + optional({"textEdit", :text_edit}) => + oneof([ + GenLSP.Structures.TextEdit.schematic(), + GenLSP.Structures.InsertReplaceEdit.schematic() + ]), + optional({"textEditText", :text_edit_text}) => str(), + optional({"additionalTextEdits", :additional_text_edits}) => + list(GenLSP.Structures.TextEdit.schematic()), + optional({"commitCharacters", :commit_characters}) => list(str()), + optional({"command", :command}) => GenLSP.Structures.Command.schematic(), + optional({"data", :data}) => GenLSP.TypeAlias.LSPAny.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/completion_item_label_details.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/completion_item_label_details.ex new file mode 100644 index 000000000..7aece0372 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/completion_item_label_details.ex @@ -0,0 +1,35 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CompletionItemLabelDetails do + @moduledoc """ + Additional details for a completion item label. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * detail: An optional string which is rendered less prominently directly after {@link CompletionItem.label label}, + without any spacing. Should be used for function signatures and type annotations. + * description: An optional string which is rendered less prominently after {@link CompletionItem.detail}. Should be used + for fully qualified names and file paths. + """ + + typedstruct do + field(:detail, String.t()) + field(:description, String.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"detail", :detail}) => str(), + optional({"description", :description}) => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/completion_list.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/completion_list.ex new file mode 100644 index 000000000..3392f4527 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/completion_list.ex @@ -0,0 +1,66 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CompletionList do + @moduledoc """ + Represents a collection of {@link CompletionItem completion items} to be presented + in the editor. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * is_incomplete: This list it not complete. Further typing results in recomputing this list. + + Recomputed lists have all their items replaced (not appended) in the + incomplete completion sessions. + * item_defaults: In many cases the items of an actual completion result share the same + value for properties like `commitCharacters` or the range of a text + edit. A completion list can therefore define item defaults which will + be used if a completion item itself doesn't specify the value. + + If a completion list specifies a default value and a completion item + also specifies a corresponding value the one from the item is used. + + Servers are only allowed to return default values if the client + signals support for this via the `completionList.itemDefaults` + capability. + + @since 3.17.0 + * items: The completion items. + """ + + typedstruct do + field(:is_incomplete, boolean(), enforce: true) + field(:item_defaults, map()) + field(:items, list(GenLSP.Structures.CompletionItem.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"isIncomplete", :is_incomplete} => bool(), + optional({"itemDefaults", :item_defaults}) => + map(%{ + optional({"commitCharacters", :commit_characters}) => list(str()), + optional({"editRange", :edit_range}) => + oneof([ + GenLSP.Structures.Range.schematic(), + map(%{ + {"insert", :insert} => GenLSP.Structures.Range.schematic(), + {"replace", :replace} => GenLSP.Structures.Range.schematic() + }) + ]), + optional({"insertTextFormat", :insert_text_format}) => + GenLSP.Enumerations.InsertTextFormat.schematic(), + optional({"insertTextMode", :insert_text_mode}) => + GenLSP.Enumerations.InsertTextMode.schematic(), + optional({"data", :data}) => GenLSP.TypeAlias.LSPAny.schematic() + }), + {"items", :items} => list(GenLSP.Structures.CompletionItem.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/completion_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/completion_options.ex new file mode 100644 index 000000000..8047a27d5 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/completion_options.ex @@ -0,0 +1,61 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CompletionOptions do + @moduledoc """ + Completion options. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * trigger_characters: Most tools trigger completion request automatically without explicitly requesting + it using a keyboard shortcut (e.g. Ctrl+Space). Typically they do so when the user + starts to type an identifier. For example if the user types `c` in a JavaScript file + code complete will automatically pop up present `console` besides others as a + completion item. Characters that make up identifiers don't need to be listed here. + + If code complete should automatically be trigger on characters not being valid inside + an identifier (for example `.` in JavaScript) list them in `triggerCharacters`. + * all_commit_characters: The list of all possible characters that commit a completion. This field can be used + if clients don't support individual commit characters per completion item. See + `ClientCapabilities.textDocument.completion.completionItem.commitCharactersSupport` + + If a server provides both `allCommitCharacters` and commit characters on an individual + completion item the ones on the completion item win. + + @since 3.2.0 + * resolve_provider: The server provides support to resolve additional + information for a completion item. + * completion_item: The server supports the following `CompletionItem` specific + capabilities. + + @since 3.17.0 + * work_done_progress + """ + + typedstruct do + field(:trigger_characters, list(String.t())) + field(:all_commit_characters, list(String.t())) + field(:resolve_provider, boolean()) + field(:completion_item, map()) + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"triggerCharacters", :trigger_characters}) => list(str()), + optional({"allCommitCharacters", :all_commit_characters}) => list(str()), + optional({"resolveProvider", :resolve_provider}) => bool(), + optional({"completionItem", :completion_item}) => + map(%{ + optional({"labelDetailsSupport", :label_details_support}) => bool() + }), + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/completion_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/completion_params.ex new file mode 100644 index 000000000..3ff9a9fd2 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/completion_params.ex @@ -0,0 +1,43 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CompletionParams do + @moduledoc """ + Completion parameters + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * context: The completion context. This is only available it the client specifies + to send this using the client capability `textDocument.completion.contextSupport === true` + * work_done_token: An optional token that a server can use to report work done progress. + * partial_result_token: An optional token that a server can use to report partial results (e.g. streaming) to + the client. + * text_document: The text document. + * position: The position inside the text document. + """ + + typedstruct do + field(:context, GenLSP.Structures.CompletionContext.t()) + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:partial_result_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:position, GenLSP.Structures.Position.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"context", :context}) => GenLSP.Structures.CompletionContext.schematic(), + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + optional({"partialResultToken", :partial_result_token}) => + GenLSP.TypeAlias.ProgressToken.schematic(), + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + {"position", :position} => GenLSP.Structures.Position.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/completion_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/completion_registration_options.ex new file mode 100644 index 000000000..2a775f203 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/completion_registration_options.ex @@ -0,0 +1,63 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CompletionRegistrationOptions do + @moduledoc """ + Registration options for a {@link CompletionRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + * trigger_characters: Most tools trigger completion request automatically without explicitly requesting + it using a keyboard shortcut (e.g. Ctrl+Space). Typically they do so when the user + starts to type an identifier. For example if the user types `c` in a JavaScript file + code complete will automatically pop up present `console` besides others as a + completion item. Characters that make up identifiers don't need to be listed here. + + If code complete should automatically be trigger on characters not being valid inside + an identifier (for example `.` in JavaScript) list them in `triggerCharacters`. + * all_commit_characters: The list of all possible characters that commit a completion. This field can be used + if clients don't support individual commit characters per completion item. See + `ClientCapabilities.textDocument.completion.completionItem.commitCharactersSupport` + + If a server provides both `allCommitCharacters` and commit characters on an individual + completion item the ones on the completion item win. + + @since 3.2.0 + * resolve_provider: The server provides support to resolve additional + information for a completion item. + * completion_item: The server supports the following `CompletionItem` specific + capabilities. + + @since 3.17.0 + """ + + typedstruct do + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + field(:trigger_characters, list(String.t())) + field(:all_commit_characters, list(String.t())) + field(:resolve_provider, boolean()) + field(:completion_item, map()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]), + optional({"triggerCharacters", :trigger_characters}) => list(str()), + optional({"allCommitCharacters", :all_commit_characters}) => list(str()), + optional({"resolveProvider", :resolve_provider}) => bool(), + optional({"completionItem", :completion_item}) => + map(%{ + optional({"labelDetailsSupport", :label_details_support}) => bool() + }) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/configuration_item.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/configuration_item.ex new file mode 100644 index 000000000..578a8f6df --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/configuration_item.ex @@ -0,0 +1,27 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ConfigurationItem do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * scope_uri: The scope to get the configuration section for. + * section: The configuration section asked for. + """ + + typedstruct do + field(:scope_uri, String.t()) + field(:section, String.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"scopeUri", :scope_uri}) => str(), + optional({"section", :section}) => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/configuration_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/configuration_params.ex new file mode 100644 index 000000000..537a5c833 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/configuration_params.ex @@ -0,0 +1,28 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ConfigurationParams do + @moduledoc """ + The parameters of a configuration request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * items + """ + + typedstruct do + field(:items, list(GenLSP.Structures.ConfigurationItem.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"items", :items} => list(GenLSP.Structures.ConfigurationItem.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/create_file.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/create_file.ex new file mode 100644 index 000000000..284cf42e4 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/create_file.ex @@ -0,0 +1,40 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CreateFile do + @moduledoc """ + Create file operation. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * kind: A create + * uri: The resource to create. + * options: Additional options + * annotation_id: An optional annotation identifier describing the operation. + + @since 3.16.0 + """ + + typedstruct do + field(:kind, String.t(), enforce: true) + field(:uri, GenLSP.BaseTypes.document_uri(), enforce: true) + field(:options, GenLSP.Structures.CreateFileOptions.t()) + field(:annotation_id, GenLSP.TypeAlias.ChangeAnnotationIdentifier.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"kind", :kind} => "create", + {"uri", :uri} => str(), + optional({"options", :options}) => GenLSP.Structures.CreateFileOptions.schematic(), + optional({"annotationId", :annotation_id}) => + GenLSP.TypeAlias.ChangeAnnotationIdentifier.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/create_file_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/create_file_options.ex new file mode 100644 index 000000000..d2e3b1820 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/create_file_options.ex @@ -0,0 +1,31 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CreateFileOptions do + @moduledoc """ + Options to create a file. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * overwrite: Overwrite existing file. Overwrite wins over `ignoreIfExists` + * ignore_if_exists: Ignore if exists. + """ + + typedstruct do + field(:overwrite, boolean()) + field(:ignore_if_exists, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"overwrite", :overwrite}) => bool(), + optional({"ignoreIfExists", :ignore_if_exists}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/create_files_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/create_files_params.ex new file mode 100644 index 000000000..6fa283e6b --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/create_files_params.ex @@ -0,0 +1,31 @@ +# codegen: do not edit +defmodule GenLSP.Structures.CreateFilesParams do + @moduledoc """ + The parameters sent in notifications/requests for user-initiated creation of + files. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * files: An array of all files/folders created in this operation. + """ + + typedstruct do + field(:files, list(GenLSP.Structures.FileCreate.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"files", :files} => list(GenLSP.Structures.FileCreate.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/declaration_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/declaration_client_capabilities.ex new file mode 100644 index 000000000..d192705c5 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/declaration_client_capabilities.ex @@ -0,0 +1,33 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DeclarationClientCapabilities do + @moduledoc """ + @since 3.14.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether declaration supports dynamic registration. If this is set to `true` + the client supports the new `DeclarationRegistrationOptions` return value + for the corresponding server capability as well. + * link_support: The client supports additional metadata in the form of declaration links. + """ + + typedstruct do + field(:dynamic_registration, boolean()) + field(:link_support, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool(), + optional({"linkSupport", :link_support}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/declaration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/declaration_options.ex new file mode 100644 index 000000000..c078857d5 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/declaration_options.ex @@ -0,0 +1,24 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DeclarationOptions do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_progress + """ + + typedstruct do + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/declaration_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/declaration_params.ex new file mode 100644 index 000000000..2323362cb --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/declaration_params.ex @@ -0,0 +1,35 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DeclarationParams do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_token: An optional token that a server can use to report work done progress. + * partial_result_token: An optional token that a server can use to report partial results (e.g. streaming) to + the client. + * text_document: The text document. + * position: The position inside the text document. + """ + + typedstruct do + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:partial_result_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:position, GenLSP.Structures.Position.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + optional({"partialResultToken", :partial_result_token}) => + GenLSP.TypeAlias.ProgressToken.schematic(), + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + {"position", :position} => GenLSP.Structures.Position.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/declaration_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/declaration_registration_options.ex new file mode 100644 index 000000000..d097659f3 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/declaration_registration_options.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DeclarationRegistrationOptions do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * id: The id used to register the request. The id can be used to deregister + the request again. See also Registration#id. + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + """ + + typedstruct do + field(:id, String.t()) + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"id", :id}) => str(), + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/definition_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/definition_client_capabilities.ex new file mode 100644 index 000000000..0630a7a92 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/definition_client_capabilities.ex @@ -0,0 +1,33 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DefinitionClientCapabilities do + @moduledoc """ + Client Capabilities for a {@link DefinitionRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether definition supports dynamic registration. + * link_support: The client supports additional metadata in the form of definition links. + + @since 3.14.0 + """ + + typedstruct do + field(:dynamic_registration, boolean()) + field(:link_support, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool(), + optional({"linkSupport", :link_support}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/definition_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/definition_options.ex new file mode 100644 index 000000000..6a15d75b4 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/definition_options.ex @@ -0,0 +1,28 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DefinitionOptions do + @moduledoc """ + Server Capabilities for a {@link DefinitionRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_progress + """ + + typedstruct do + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/definition_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/definition_params.ex new file mode 100644 index 000000000..d789a2f87 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/definition_params.ex @@ -0,0 +1,39 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DefinitionParams do + @moduledoc """ + Parameters for a {@link DefinitionRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_token: An optional token that a server can use to report work done progress. + * partial_result_token: An optional token that a server can use to report partial results (e.g. streaming) to + the client. + * text_document: The text document. + * position: The position inside the text document. + """ + + typedstruct do + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:partial_result_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:position, GenLSP.Structures.Position.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + optional({"partialResultToken", :partial_result_token}) => + GenLSP.TypeAlias.ProgressToken.schematic(), + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + {"position", :position} => GenLSP.Structures.Position.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/definition_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/definition_registration_options.ex new file mode 100644 index 000000000..6a0c2eb06 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/definition_registration_options.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DefinitionRegistrationOptions do + @moduledoc """ + Registration options for a {@link DefinitionRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + """ + + typedstruct do + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/delete_file.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/delete_file.ex new file mode 100644 index 000000000..534c18757 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/delete_file.ex @@ -0,0 +1,40 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DeleteFile do + @moduledoc """ + Delete file operation + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * kind: A delete + * uri: The file to delete. + * options: Delete options. + * annotation_id: An optional annotation identifier describing the operation. + + @since 3.16.0 + """ + + typedstruct do + field(:kind, String.t(), enforce: true) + field(:uri, GenLSP.BaseTypes.document_uri(), enforce: true) + field(:options, GenLSP.Structures.DeleteFileOptions.t()) + field(:annotation_id, GenLSP.TypeAlias.ChangeAnnotationIdentifier.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"kind", :kind} => "delete", + {"uri", :uri} => str(), + optional({"options", :options}) => GenLSP.Structures.DeleteFileOptions.schematic(), + optional({"annotationId", :annotation_id}) => + GenLSP.TypeAlias.ChangeAnnotationIdentifier.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/delete_file_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/delete_file_options.ex new file mode 100644 index 000000000..ec6e7c8a0 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/delete_file_options.ex @@ -0,0 +1,31 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DeleteFileOptions do + @moduledoc """ + Delete file options + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * recursive: Delete the content recursively if a folder is denoted. + * ignore_if_not_exists: Ignore the operation if the file doesn't exist. + """ + + typedstruct do + field(:recursive, boolean()) + field(:ignore_if_not_exists, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"recursive", :recursive}) => bool(), + optional({"ignoreIfNotExists", :ignore_if_not_exists}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/delete_files_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/delete_files_params.ex new file mode 100644 index 000000000..9de35cd3f --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/delete_files_params.ex @@ -0,0 +1,31 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DeleteFilesParams do + @moduledoc """ + The parameters sent in notifications/requests for user-initiated deletes of + files. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * files: An array of all files/folders deleted in this operation. + """ + + typedstruct do + field(:files, list(GenLSP.Structures.FileDelete.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"files", :files} => list(GenLSP.Structures.FileDelete.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/diagnostic.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/diagnostic.ex new file mode 100644 index 000000000..6f9495e8a --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/diagnostic.ex @@ -0,0 +1,67 @@ +# codegen: do not edit +defmodule GenLSP.Structures.Diagnostic do + @moduledoc """ + Represents a diagnostic, such as a compiler error or warning. Diagnostic objects + are only valid in the scope of a resource. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * range: The range at which the message applies + * severity: The diagnostic's severity. Can be omitted. If omitted it is up to the + client to interpret diagnostics as error, warning, info or hint. + * code: The diagnostic's code, which usually appear in the user interface. + * code_description: An optional property to describe the error code. + Requires the code field (above) to be present/not null. + + @since 3.16.0 + * source: A human-readable string describing the source of this + diagnostic, e.g. 'typescript' or 'super lint'. It usually + appears in the user interface. + * message: The diagnostic's message. It usually appears in the user interface + * tags: Additional metadata about the diagnostic. + + @since 3.15.0 + * related_information: An array of related diagnostic information, e.g. when symbol-names within + a scope collide all definitions can be marked via this property. + * data: A data entry field that is preserved between a `textDocument/publishDiagnostics` + notification and `textDocument/codeAction` request. + + @since 3.16.0 + """ + + typedstruct do + field(:range, GenLSP.Structures.Range.t(), enforce: true) + field(:severity, GenLSP.Enumerations.DiagnosticSeverity.t()) + field(:code, integer() | String.t()) + field(:code_description, GenLSP.Structures.CodeDescription.t()) + field(:source, String.t()) + field(:message, String.t(), enforce: true) + field(:tags, list(GenLSP.Enumerations.DiagnosticTag.t())) + field(:related_information, list(GenLSP.Structures.DiagnosticRelatedInformation.t())) + field(:data, GenLSP.TypeAlias.LSPAny.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"range", :range} => GenLSP.Structures.Range.schematic(), + optional({"severity", :severity}) => GenLSP.Enumerations.DiagnosticSeverity.schematic(), + optional({"code", :code}) => oneof([int(), str()]), + optional({"codeDescription", :code_description}) => + GenLSP.Structures.CodeDescription.schematic(), + optional({"source", :source}) => str(), + {"message", :message} => str(), + optional({"tags", :tags}) => list(GenLSP.Enumerations.DiagnosticTag.schematic()), + optional({"relatedInformation", :related_information}) => + list(GenLSP.Structures.DiagnosticRelatedInformation.schematic()), + optional({"data", :data}) => GenLSP.TypeAlias.LSPAny.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/diagnostic_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/diagnostic_client_capabilities.ex new file mode 100644 index 000000000..f211b4601 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/diagnostic_client_capabilities.ex @@ -0,0 +1,35 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DiagnosticClientCapabilities do + @moduledoc """ + Client capabilities specific to diagnostic pull requests. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether implementation supports dynamic registration. If this is set to `true` + the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)` + return value for the corresponding server capability as well. + * related_document_support: Whether the clients supports related documents for document diagnostic pulls. + """ + + typedstruct do + field(:dynamic_registration, boolean()) + field(:related_document_support, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool(), + optional({"relatedDocumentSupport", :related_document_support}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/diagnostic_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/diagnostic_options.ex new file mode 100644 index 000000000..84130cefd --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/diagnostic_options.ex @@ -0,0 +1,43 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DiagnosticOptions do + @moduledoc """ + Diagnostic options. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * identifier: An optional identifier under which the diagnostics are + managed by the client. + * inter_file_dependencies: Whether the language has inter file dependencies meaning that + editing code in one file can result in a different diagnostic + set in another file. Inter file dependencies are common for + most programming languages and typically uncommon for linters. + * workspace_diagnostics: The server provides support for workspace diagnostics as well. + * work_done_progress + """ + + typedstruct do + field(:identifier, String.t()) + field(:inter_file_dependencies, boolean(), enforce: true) + field(:workspace_diagnostics, boolean(), enforce: true) + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"identifier", :identifier}) => str(), + {"interFileDependencies", :inter_file_dependencies} => bool(), + {"workspaceDiagnostics", :workspace_diagnostics} => bool(), + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/diagnostic_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/diagnostic_registration_options.ex new file mode 100644 index 000000000..478db738b --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/diagnostic_registration_options.ex @@ -0,0 +1,49 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DiagnosticRegistrationOptions do + @moduledoc """ + Diagnostic registration options. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * id: The id used to register the request. The id can be used to deregister + the request again. See also Registration#id. + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + * identifier: An optional identifier under which the diagnostics are + managed by the client. + * inter_file_dependencies: Whether the language has inter file dependencies meaning that + editing code in one file can result in a different diagnostic + set in another file. Inter file dependencies are common for + most programming languages and typically uncommon for linters. + * workspace_diagnostics: The server provides support for workspace diagnostics as well. + """ + + typedstruct do + field(:id, String.t()) + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + field(:identifier, String.t()) + field(:inter_file_dependencies, boolean(), enforce: true) + field(:workspace_diagnostics, boolean(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"id", :id}) => str(), + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]), + optional({"identifier", :identifier}) => str(), + {"interFileDependencies", :inter_file_dependencies} => bool(), + {"workspaceDiagnostics", :workspace_diagnostics} => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/diagnostic_related_information.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/diagnostic_related_information.ex new file mode 100644 index 000000000..dd2eb98cc --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/diagnostic_related_information.ex @@ -0,0 +1,33 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DiagnosticRelatedInformation do + @moduledoc """ + Represents a related message and source code location for a diagnostic. This should be + used to point to code locations that cause or related to a diagnostics, e.g when duplicating + a symbol in a scope. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * location: The location of this related diagnostic information. + * message: The message of this related diagnostic information. + """ + + typedstruct do + field(:location, GenLSP.Structures.Location.t(), enforce: true) + field(:message, String.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"location", :location} => GenLSP.Structures.Location.schematic(), + {"message", :message} => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/diagnostic_server_cancellation_data.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/diagnostic_server_cancellation_data.ex new file mode 100644 index 000000000..f4e6fe770 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/diagnostic_server_cancellation_data.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DiagnosticServerCancellationData do + @moduledoc """ + Cancellation data returned from a diagnostic request. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * retrigger_request + """ + + typedstruct do + field(:retrigger_request, boolean(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"retriggerRequest", :retrigger_request} => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/diagnostic_workspace_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/diagnostic_workspace_client_capabilities.ex new file mode 100644 index 000000000..55c91cab6 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/diagnostic_workspace_client_capabilities.ex @@ -0,0 +1,36 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DiagnosticWorkspaceClientCapabilities do + @moduledoc """ + Workspace client capabilities specific to diagnostic pull requests. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * refresh_support: Whether the client implementation supports a refresh request sent from + the server to the client. + + Note that this event is global and will force the client to refresh all + pulled diagnostics currently shown. It should be used with absolute care and + is useful for situation where a server for example detects a project wide + change that requires such a calculation. + """ + + typedstruct do + field(:refresh_support, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"refreshSupport", :refresh_support}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/did_change_configuration_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/did_change_configuration_client_capabilities.ex new file mode 100644 index 000000000..7cac83efa --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/did_change_configuration_client_capabilities.ex @@ -0,0 +1,24 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DidChangeConfigurationClientCapabilities do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Did change configuration notification supports dynamic registration. + """ + + typedstruct do + field(:dynamic_registration, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/did_change_configuration_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/did_change_configuration_params.ex new file mode 100644 index 000000000..2332c40ca --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/did_change_configuration_params.ex @@ -0,0 +1,28 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DidChangeConfigurationParams do + @moduledoc """ + The parameters of a change configuration notification. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * settings: The actual changed settings + """ + + typedstruct do + field(:settings, GenLSP.TypeAlias.LSPAny.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"settings", :settings} => GenLSP.TypeAlias.LSPAny.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/did_change_configuration_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/did_change_configuration_registration_options.ex new file mode 100644 index 000000000..d7b0e1b91 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/did_change_configuration_registration_options.ex @@ -0,0 +1,24 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DidChangeConfigurationRegistrationOptions do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * section + """ + + typedstruct do + field(:section, String.t() | list(String.t())) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"section", :section}) => oneof([str(), list(str())]) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/did_change_notebook_document_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/did_change_notebook_document_params.ex new file mode 100644 index 000000000..7e85da6c6 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/did_change_notebook_document_params.ex @@ -0,0 +1,52 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DidChangeNotebookDocumentParams do + @moduledoc """ + The params sent in a change notebook document notification. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * notebook_document: The notebook document that did change. The version number points + to the version after all provided changes have been applied. If + only the text document content of a cell changes the notebook version + doesn't necessarily have to change. + * change: The actual changes to the notebook document. + + The changes describe single state changes to the notebook document. + So if there are two changes c1 (at array index 0) and c2 (at array + index 1) for a notebook in state S then c1 moves the notebook from + S to S' and c2 from S' to S''. So c1 is computed on the state S and + c2 is computed on the state S'. + + To mirror the content of a notebook using change events use the following approach: + - start with the same initial content + - apply the 'notebookDocument/didChange' notifications in the order you receive them. + - apply the `NotebookChangeEvent`s in a single notification in the order + you receive them. + """ + + typedstruct do + field(:notebook_document, GenLSP.Structures.VersionedNotebookDocumentIdentifier.t(), + enforce: true + ) + + field(:change, GenLSP.Structures.NotebookDocumentChangeEvent.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"notebookDocument", :notebook_document} => + GenLSP.Structures.VersionedNotebookDocumentIdentifier.schematic(), + {"change", :change} => GenLSP.Structures.NotebookDocumentChangeEvent.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/did_change_text_document_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/did_change_text_document_params.ex new file mode 100644 index 000000000..e5364942c --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/did_change_text_document_params.ex @@ -0,0 +1,48 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DidChangeTextDocumentParams do + @moduledoc """ + The change text document notification's parameters. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * text_document: The document that did change. The version number points + to the version after all provided content changes have + been applied. + * content_changes: The actual content changes. The content changes describe single state changes + to the document. So if there are two content changes c1 (at array index 0) and + c2 (at array index 1) for a document in state S then c1 moves the document from + S to S' and c2 from S' to S''. So c1 is computed on the state S and c2 is computed + on the state S'. + + To mirror the content of a document using change events use the following approach: + - start with the same initial content + - apply the 'textDocument/didChange' notifications in the order you receive them. + - apply the `TextDocumentContentChangeEvent`s in a single notification in the order + you receive them. + """ + + typedstruct do + field(:text_document, GenLSP.Structures.VersionedTextDocumentIdentifier.t(), enforce: true) + + field(:content_changes, list(GenLSP.TypeAlias.TextDocumentContentChangeEvent.t()), + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"textDocument", :text_document} => + GenLSP.Structures.VersionedTextDocumentIdentifier.schematic(), + {"contentChanges", :content_changes} => + list(GenLSP.TypeAlias.TextDocumentContentChangeEvent.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/did_change_watched_files_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/did_change_watched_files_client_capabilities.ex new file mode 100644 index 000000000..47817bced --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/did_change_watched_files_client_capabilities.ex @@ -0,0 +1,32 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DidChangeWatchedFilesClientCapabilities do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Did change watched files notification supports dynamic registration. Please note + that the current protocol doesn't support static configuration for file changes + from the server side. + * relative_pattern_support: Whether the client has support for {@link RelativePattern relative pattern} + or not. + + @since 3.17.0 + """ + + typedstruct do + field(:dynamic_registration, boolean()) + field(:relative_pattern_support, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool(), + optional({"relativePatternSupport", :relative_pattern_support}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/did_change_watched_files_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/did_change_watched_files_params.ex new file mode 100644 index 000000000..46d2a8379 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/did_change_watched_files_params.ex @@ -0,0 +1,28 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DidChangeWatchedFilesParams do + @moduledoc """ + The watched files change notification's parameters. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * changes: The actual file events. + """ + + typedstruct do + field(:changes, list(GenLSP.Structures.FileEvent.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"changes", :changes} => list(GenLSP.Structures.FileEvent.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/did_change_watched_files_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/did_change_watched_files_registration_options.ex new file mode 100644 index 000000000..ddd9f68b4 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/did_change_watched_files_registration_options.ex @@ -0,0 +1,28 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DidChangeWatchedFilesRegistrationOptions do + @moduledoc """ + Describe options to be used when registered for text document change events. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * watchers: The watchers to register. + """ + + typedstruct do + field(:watchers, list(GenLSP.Structures.FileSystemWatcher.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"watchers", :watchers} => list(GenLSP.Structures.FileSystemWatcher.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/did_change_workspace_folders_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/did_change_workspace_folders_params.ex new file mode 100644 index 000000000..3dd3886a6 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/did_change_workspace_folders_params.ex @@ -0,0 +1,28 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DidChangeWorkspaceFoldersParams do + @moduledoc """ + The parameters of a `workspace/didChangeWorkspaceFolders` notification. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * event: The actual workspace folder change event. + """ + + typedstruct do + field(:event, GenLSP.Structures.WorkspaceFoldersChangeEvent.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"event", :event} => GenLSP.Structures.WorkspaceFoldersChangeEvent.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/did_close_notebook_document_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/did_close_notebook_document_params.ex new file mode 100644 index 000000000..b94cf8be1 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/did_close_notebook_document_params.ex @@ -0,0 +1,36 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DidCloseNotebookDocumentParams do + @moduledoc """ + The params sent in a close notebook document notification. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * notebook_document: The notebook document that got closed. + * cell_text_documents: The text documents that represent the content + of a notebook cell that got closed. + """ + + typedstruct do + field(:notebook_document, GenLSP.Structures.NotebookDocumentIdentifier.t(), enforce: true) + field(:cell_text_documents, list(GenLSP.Structures.TextDocumentIdentifier.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"notebookDocument", :notebook_document} => + GenLSP.Structures.NotebookDocumentIdentifier.schematic(), + {"cellTextDocuments", :cell_text_documents} => + list(GenLSP.Structures.TextDocumentIdentifier.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/did_close_text_document_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/did_close_text_document_params.ex new file mode 100644 index 000000000..036ca0a7c --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/did_close_text_document_params.ex @@ -0,0 +1,28 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DidCloseTextDocumentParams do + @moduledoc """ + The parameters sent in a close text document notification + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * text_document: The document that was closed. + """ + + typedstruct do + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/did_open_notebook_document_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/did_open_notebook_document_params.ex new file mode 100644 index 000000000..87155a4b1 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/did_open_notebook_document_params.ex @@ -0,0 +1,35 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DidOpenNotebookDocumentParams do + @moduledoc """ + The params sent in an open notebook document notification. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * notebook_document: The notebook document that got opened. + * cell_text_documents: The text documents that represent the content + of a notebook cell. + """ + + typedstruct do + field(:notebook_document, GenLSP.Structures.NotebookDocument.t(), enforce: true) + field(:cell_text_documents, list(GenLSP.Structures.TextDocumentItem.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"notebookDocument", :notebook_document} => GenLSP.Structures.NotebookDocument.schematic(), + {"cellTextDocuments", :cell_text_documents} => + list(GenLSP.Structures.TextDocumentItem.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/did_open_text_document_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/did_open_text_document_params.ex new file mode 100644 index 000000000..d88d1d8fd --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/did_open_text_document_params.ex @@ -0,0 +1,28 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DidOpenTextDocumentParams do + @moduledoc """ + The parameters sent in an open text document notification + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * text_document: The document that was opened. + """ + + typedstruct do + field(:text_document, GenLSP.Structures.TextDocumentItem.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentItem.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/did_save_notebook_document_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/did_save_notebook_document_params.ex new file mode 100644 index 000000000..2a4f3e002 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/did_save_notebook_document_params.ex @@ -0,0 +1,31 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DidSaveNotebookDocumentParams do + @moduledoc """ + The params sent in a save notebook document notification. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * notebook_document: The notebook document that got saved. + """ + + typedstruct do + field(:notebook_document, GenLSP.Structures.NotebookDocumentIdentifier.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"notebookDocument", :notebook_document} => + GenLSP.Structures.NotebookDocumentIdentifier.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/did_save_text_document_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/did_save_text_document_params.ex new file mode 100644 index 000000000..a0b0550c7 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/did_save_text_document_params.ex @@ -0,0 +1,32 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DidSaveTextDocumentParams do + @moduledoc """ + The parameters sent in a save text document notification + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * text_document: The document that was saved. + * text: Optional the content when saved. Depends on the includeText value + when the save notification was requested. + """ + + typedstruct do + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:text, String.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + optional({"text", :text}) => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_color_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_color_client_capabilities.ex new file mode 100644 index 000000000..dda9e1d0d --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_color_client_capabilities.ex @@ -0,0 +1,26 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentColorClientCapabilities do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether implementation supports dynamic registration. If this is set to `true` + the client supports the new `DocumentColorRegistrationOptions` return value + for the corresponding server capability as well. + """ + + typedstruct do + field(:dynamic_registration, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_color_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_color_options.ex new file mode 100644 index 000000000..07d5fdda6 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_color_options.ex @@ -0,0 +1,24 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentColorOptions do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_progress + """ + + typedstruct do + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_color_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_color_params.ex new file mode 100644 index 000000000..21c781dff --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_color_params.ex @@ -0,0 +1,36 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentColorParams do + @moduledoc """ + Parameters for a {@link DocumentColorRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * text_document: The text document. + * work_done_token: An optional token that a server can use to report work done progress. + * partial_result_token: An optional token that a server can use to report partial results (e.g. streaming) to + the client. + """ + + typedstruct do + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:partial_result_token, GenLSP.TypeAlias.ProgressToken.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + optional({"partialResultToken", :partial_result_token}) => + GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_color_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_color_registration_options.ex new file mode 100644 index 000000000..0d8395031 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_color_registration_options.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentColorRegistrationOptions do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * id: The id used to register the request. The id can be used to deregister + the request again. See also Registration#id. + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + """ + + typedstruct do + field(:id, String.t()) + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"id", :id}) => str(), + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_diagnostic_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_diagnostic_params.ex new file mode 100644 index 000000000..7788ca4df --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_diagnostic_params.ex @@ -0,0 +1,44 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentDiagnosticParams do + @moduledoc """ + Parameters of the document diagnostic request. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * text_document: The text document. + * identifier: The additional identifier provided during registration. + * previous_result_id: The result id of a previous response if provided. + * work_done_token: An optional token that a server can use to report work done progress. + * partial_result_token: An optional token that a server can use to report partial results (e.g. streaming) to + the client. + """ + + typedstruct do + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:identifier, String.t()) + field(:previous_result_id, String.t()) + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:partial_result_token, GenLSP.TypeAlias.ProgressToken.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + optional({"identifier", :identifier}) => str(), + optional({"previousResultId", :previous_result_id}) => str(), + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + optional({"partialResultToken", :partial_result_token}) => + GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_diagnostic_report_partial_result.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_diagnostic_report_partial_result.ex new file mode 100644 index 000000000..ec7908d97 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_diagnostic_report_partial_result.ex @@ -0,0 +1,46 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentDiagnosticReportPartialResult do + @moduledoc """ + A partial result for a document diagnostic report. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * related_documents + """ + + typedstruct do + field( + :related_documents, + %{ + GenLSP.BaseTypes.document_uri() => + GenLSP.Structures.FullDocumentDiagnosticReport.t() + | GenLSP.Structures.UnchangedDocumentDiagnosticReport.t() + }, + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"relatedDocuments", :related_documents} => + map( + keys: str(), + values: + oneof([ + GenLSP.Structures.FullDocumentDiagnosticReport.schematic(), + GenLSP.Structures.UnchangedDocumentDiagnosticReport.schematic() + ]) + ) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_formatting_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_formatting_client_capabilities.ex new file mode 100644 index 000000000..634b30d52 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_formatting_client_capabilities.ex @@ -0,0 +1,28 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentFormattingClientCapabilities do + @moduledoc """ + Client capabilities of a {@link DocumentFormattingRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether formatting supports dynamic registration. + """ + + typedstruct do + field(:dynamic_registration, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_formatting_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_formatting_options.ex new file mode 100644 index 000000000..2e1d48f5e --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_formatting_options.ex @@ -0,0 +1,28 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentFormattingOptions do + @moduledoc """ + Provider options for a {@link DocumentFormattingRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_progress + """ + + typedstruct do + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_formatting_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_formatting_params.ex new file mode 100644 index 000000000..344c747f4 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_formatting_params.ex @@ -0,0 +1,34 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentFormattingParams do + @moduledoc """ + The parameters of a {@link DocumentFormattingRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * text_document: The document to format. + * options: The format options. + * work_done_token: An optional token that a server can use to report work done progress. + """ + + typedstruct do + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:options, GenLSP.Structures.FormattingOptions.t(), enforce: true) + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + {"options", :options} => GenLSP.Structures.FormattingOptions.schematic(), + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_formatting_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_formatting_registration_options.ex new file mode 100644 index 000000000..4722ce93a --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_formatting_registration_options.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentFormattingRegistrationOptions do + @moduledoc """ + Registration options for a {@link DocumentFormattingRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + """ + + typedstruct do + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_highlight.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_highlight.ex new file mode 100644 index 000000000..d6e4be862 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_highlight.ex @@ -0,0 +1,33 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentHighlight do + @moduledoc """ + A document highlight is a range inside a text document which deserves + special attention. Usually a document highlight is visualized by changing + the background color of its range. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * range: The range this highlight applies to. + * kind: The highlight kind, default is {@link DocumentHighlightKind.Text text}. + """ + + typedstruct do + field(:range, GenLSP.Structures.Range.t(), enforce: true) + field(:kind, GenLSP.Enumerations.DocumentHighlightKind.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"range", :range} => GenLSP.Structures.Range.schematic(), + optional({"kind", :kind}) => GenLSP.Enumerations.DocumentHighlightKind.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_highlight_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_highlight_client_capabilities.ex new file mode 100644 index 000000000..f02fa86d0 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_highlight_client_capabilities.ex @@ -0,0 +1,28 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentHighlightClientCapabilities do + @moduledoc """ + Client Capabilities for a {@link DocumentHighlightRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether document highlight supports dynamic registration. + """ + + typedstruct do + field(:dynamic_registration, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_highlight_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_highlight_options.ex new file mode 100644 index 000000000..979d89b0f --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_highlight_options.ex @@ -0,0 +1,28 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentHighlightOptions do + @moduledoc """ + Provider options for a {@link DocumentHighlightRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_progress + """ + + typedstruct do + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_highlight_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_highlight_params.ex new file mode 100644 index 000000000..1f90cf15b --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_highlight_params.ex @@ -0,0 +1,39 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentHighlightParams do + @moduledoc """ + Parameters for a {@link DocumentHighlightRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_token: An optional token that a server can use to report work done progress. + * partial_result_token: An optional token that a server can use to report partial results (e.g. streaming) to + the client. + * text_document: The text document. + * position: The position inside the text document. + """ + + typedstruct do + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:partial_result_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:position, GenLSP.Structures.Position.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + optional({"partialResultToken", :partial_result_token}) => + GenLSP.TypeAlias.ProgressToken.schematic(), + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + {"position", :position} => GenLSP.Structures.Position.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_highlight_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_highlight_registration_options.ex new file mode 100644 index 000000000..47390c5eb --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_highlight_registration_options.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentHighlightRegistrationOptions do + @moduledoc """ + Registration options for a {@link DocumentHighlightRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + """ + + typedstruct do + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_link.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_link.ex new file mode 100644 index 000000000..bebbc701a --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_link.ex @@ -0,0 +1,45 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentLink do + @moduledoc """ + A document link is a range in a text document that links to an internal or external resource, like another + text document or a web site. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * range: The range this link applies to. + * target: The uri this link points to. If missing a resolve request is sent later. + * tooltip: The tooltip text when you hover over this link. + + If a tooltip is provided, is will be displayed in a string that includes instructions on how to + trigger the link, such as `{0} (ctrl + click)`. The specific instructions vary depending on OS, + user settings, and localization. + + @since 3.15.0 + * data: A data entry field that is preserved on a document link between a + DocumentLinkRequest and a DocumentLinkResolveRequest. + """ + + typedstruct do + field(:range, GenLSP.Structures.Range.t(), enforce: true) + field(:target, String.t()) + field(:tooltip, String.t()) + field(:data, GenLSP.TypeAlias.LSPAny.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"range", :range} => GenLSP.Structures.Range.schematic(), + optional({"target", :target}) => str(), + optional({"tooltip", :tooltip}) => str(), + optional({"data", :data}) => GenLSP.TypeAlias.LSPAny.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_link_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_link_client_capabilities.ex new file mode 100644 index 000000000..fa0f81613 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_link_client_capabilities.ex @@ -0,0 +1,33 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentLinkClientCapabilities do + @moduledoc """ + The client capabilities of a {@link DocumentLinkRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether document link supports dynamic registration. + * tooltip_support: Whether the client supports the `tooltip` property on `DocumentLink`. + + @since 3.15.0 + """ + + typedstruct do + field(:dynamic_registration, boolean()) + field(:tooltip_support, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool(), + optional({"tooltipSupport", :tooltip_support}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_link_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_link_options.ex new file mode 100644 index 000000000..49e99ec0f --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_link_options.ex @@ -0,0 +1,31 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentLinkOptions do + @moduledoc """ + Provider options for a {@link DocumentLinkRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * resolve_provider: Document links have a resolve provider as well. + * work_done_progress + """ + + typedstruct do + field(:resolve_provider, boolean()) + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"resolveProvider", :resolve_provider}) => bool(), + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_link_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_link_params.ex new file mode 100644 index 000000000..25f3eed10 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_link_params.ex @@ -0,0 +1,36 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentLinkParams do + @moduledoc """ + The parameters of a {@link DocumentLinkRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * text_document: The document to provide document links for. + * work_done_token: An optional token that a server can use to report work done progress. + * partial_result_token: An optional token that a server can use to report partial results (e.g. streaming) to + the client. + """ + + typedstruct do + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:partial_result_token, GenLSP.TypeAlias.ProgressToken.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + optional({"partialResultToken", :partial_result_token}) => + GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_link_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_link_registration_options.ex new file mode 100644 index 000000000..446458a43 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_link_registration_options.ex @@ -0,0 +1,33 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentLinkRegistrationOptions do + @moduledoc """ + Registration options for a {@link DocumentLinkRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + * resolve_provider: Document links have a resolve provider as well. + """ + + typedstruct do + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + field(:resolve_provider, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]), + optional({"resolveProvider", :resolve_provider}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_on_type_formatting_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_on_type_formatting_client_capabilities.ex new file mode 100644 index 000000000..48052f616 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_on_type_formatting_client_capabilities.ex @@ -0,0 +1,28 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentOnTypeFormattingClientCapabilities do + @moduledoc """ + Client capabilities of a {@link DocumentOnTypeFormattingRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether on type formatting supports dynamic registration. + """ + + typedstruct do + field(:dynamic_registration, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_on_type_formatting_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_on_type_formatting_options.ex new file mode 100644 index 000000000..e6475c199 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_on_type_formatting_options.ex @@ -0,0 +1,31 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentOnTypeFormattingOptions do + @moduledoc """ + Provider options for a {@link DocumentOnTypeFormattingRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * first_trigger_character: A character on which formatting should be triggered, like `{`. + * more_trigger_character: More trigger characters. + """ + + typedstruct do + field(:first_trigger_character, String.t(), enforce: true) + field(:more_trigger_character, list(String.t())) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"firstTriggerCharacter", :first_trigger_character} => str(), + optional({"moreTriggerCharacter", :more_trigger_character}) => list(str()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_on_type_formatting_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_on_type_formatting_params.ex new file mode 100644 index 000000000..d786d4ed0 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_on_type_formatting_params.ex @@ -0,0 +1,42 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentOnTypeFormattingParams do + @moduledoc """ + The parameters of a {@link DocumentOnTypeFormattingRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * text_document: The document to format. + * position: The position around which the on type formatting should happen. + This is not necessarily the exact position where the character denoted + by the property `ch` got typed. + * ch: The character that has been typed that triggered the formatting + on type request. That is not necessarily the last character that + got inserted into the document since the client could auto insert + characters as well (e.g. like automatic brace completion). + * options: The formatting options. + """ + + typedstruct do + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:position, GenLSP.Structures.Position.t(), enforce: true) + field(:ch, String.t(), enforce: true) + field(:options, GenLSP.Structures.FormattingOptions.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + {"position", :position} => GenLSP.Structures.Position.schematic(), + {"ch", :ch} => str(), + {"options", :options} => GenLSP.Structures.FormattingOptions.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_on_type_formatting_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_on_type_formatting_registration_options.ex new file mode 100644 index 000000000..c6b1d3869 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_on_type_formatting_registration_options.ex @@ -0,0 +1,36 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentOnTypeFormattingRegistrationOptions do + @moduledoc """ + Registration options for a {@link DocumentOnTypeFormattingRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + * first_trigger_character: A character on which formatting should be triggered, like `{`. + * more_trigger_character: More trigger characters. + """ + + typedstruct do + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + field(:first_trigger_character, String.t(), enforce: true) + field(:more_trigger_character, list(String.t())) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]), + {"firstTriggerCharacter", :first_trigger_character} => str(), + optional({"moreTriggerCharacter", :more_trigger_character}) => list(str()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_range_formatting_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_range_formatting_client_capabilities.ex new file mode 100644 index 000000000..da4e4761f --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_range_formatting_client_capabilities.ex @@ -0,0 +1,28 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentRangeFormattingClientCapabilities do + @moduledoc """ + Client capabilities of a {@link DocumentRangeFormattingRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether range formatting supports dynamic registration. + """ + + typedstruct do + field(:dynamic_registration, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_range_formatting_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_range_formatting_options.ex new file mode 100644 index 000000000..b060f70dc --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_range_formatting_options.ex @@ -0,0 +1,28 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentRangeFormattingOptions do + @moduledoc """ + Provider options for a {@link DocumentRangeFormattingRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_progress + """ + + typedstruct do + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_range_formatting_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_range_formatting_params.ex new file mode 100644 index 000000000..86a35962a --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_range_formatting_params.ex @@ -0,0 +1,37 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentRangeFormattingParams do + @moduledoc """ + The parameters of a {@link DocumentRangeFormattingRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * text_document: The document to format. + * range: The range to format + * options: The format options + * work_done_token: An optional token that a server can use to report work done progress. + """ + + typedstruct do + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:range, GenLSP.Structures.Range.t(), enforce: true) + field(:options, GenLSP.Structures.FormattingOptions.t(), enforce: true) + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + {"range", :range} => GenLSP.Structures.Range.schematic(), + {"options", :options} => GenLSP.Structures.FormattingOptions.schematic(), + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_range_formatting_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_range_formatting_registration_options.ex new file mode 100644 index 000000000..e263de5b6 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_range_formatting_registration_options.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentRangeFormattingRegistrationOptions do + @moduledoc """ + Registration options for a {@link DocumentRangeFormattingRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + """ + + typedstruct do + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_symbol.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_symbol.ex new file mode 100644 index 000000000..3d82ac003 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_symbol.ex @@ -0,0 +1,60 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentSymbol do + @moduledoc """ + Represents programming constructs like variables, classes, interfaces etc. + that appear in a document. Document symbols can be hierarchical and they + have two ranges: one that encloses its definition and one that points to + its most interesting range, e.g. the range of an identifier. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * name: The name of this symbol. Will be displayed in the user interface and therefore must not be + an empty string or a string only consisting of white spaces. + * detail: More detail for this symbol, e.g the signature of a function. + * kind: The kind of this symbol. + * tags: Tags for this document symbol. + + @since 3.16.0 + * deprecated: Indicates if this symbol is deprecated. + + @deprecated Use tags instead + * range: The range enclosing this symbol not including leading/trailing whitespace but everything else + like comments. This information is typically used to determine if the clients cursor is + inside the symbol to reveal in the symbol in the UI. + * selection_range: The range that should be selected and revealed when this symbol is being picked, e.g the name of a function. + Must be contained by the `range`. + * children: Children of this symbol, e.g. properties of a class. + """ + + typedstruct do + field(:name, String.t(), enforce: true) + field(:detail, String.t()) + field(:kind, GenLSP.Enumerations.SymbolKind.t(), enforce: true) + field(:tags, list(GenLSP.Enumerations.SymbolTag.t())) + field(:deprecated, boolean()) + field(:range, GenLSP.Structures.Range.t(), enforce: true) + field(:selection_range, GenLSP.Structures.Range.t(), enforce: true) + field(:children, list(GenLSP.Structures.DocumentSymbol.t())) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"name", :name} => str(), + optional({"detail", :detail}) => str(), + {"kind", :kind} => GenLSP.Enumerations.SymbolKind.schematic(), + optional({"tags", :tags}) => list(GenLSP.Enumerations.SymbolTag.schematic()), + optional({"deprecated", :deprecated}) => bool(), + {"range", :range} => GenLSP.Structures.Range.schematic(), + {"selectionRange", :selection_range} => GenLSP.Structures.Range.schematic(), + optional({"children", :children}) => list({__MODULE__, :schematic, []}) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_symbol_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_symbol_client_capabilities.ex new file mode 100644 index 000000000..720b12df9 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_symbol_client_capabilities.ex @@ -0,0 +1,55 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentSymbolClientCapabilities do + @moduledoc """ + Client Capabilities for a {@link DocumentSymbolRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether document symbol supports dynamic registration. + * symbol_kind: Specific capabilities for the `SymbolKind` in the + `textDocument/documentSymbol` request. + * hierarchical_document_symbol_support: The client supports hierarchical document symbols. + * tag_support: The client supports tags on `SymbolInformation`. Tags are supported on + `DocumentSymbol` if `hierarchicalDocumentSymbolSupport` is set to true. + Clients supporting tags have to handle unknown tags gracefully. + + @since 3.16.0 + * label_support: The client supports an additional label presented in the UI when + registering a document symbol provider. + + @since 3.16.0 + """ + + typedstruct do + field(:dynamic_registration, boolean()) + field(:symbol_kind, map()) + field(:hierarchical_document_symbol_support, boolean()) + field(:tag_support, map()) + field(:label_support, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool(), + optional({"symbolKind", :symbol_kind}) => + map(%{ + optional({"valueSet", :value_set}) => list(GenLSP.Enumerations.SymbolKind.schematic()) + }), + optional({"hierarchicalDocumentSymbolSupport", :hierarchical_document_symbol_support}) => + bool(), + optional({"tagSupport", :tag_support}) => + map(%{ + {"valueSet", :value_set} => list(GenLSP.Enumerations.SymbolTag.schematic()) + }), + optional({"labelSupport", :label_support}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_symbol_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_symbol_options.ex new file mode 100644 index 000000000..06b54bdc3 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_symbol_options.ex @@ -0,0 +1,34 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentSymbolOptions do + @moduledoc """ + Provider options for a {@link DocumentSymbolRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * label: A human-readable string that is shown when multiple outlines trees + are shown for the same document. + + @since 3.16.0 + * work_done_progress + """ + + typedstruct do + field(:label, String.t()) + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"label", :label}) => str(), + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_symbol_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_symbol_params.ex new file mode 100644 index 000000000..7558ec02b --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_symbol_params.ex @@ -0,0 +1,36 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentSymbolParams do + @moduledoc """ + Parameters for a {@link DocumentSymbolRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * text_document: The text document. + * work_done_token: An optional token that a server can use to report work done progress. + * partial_result_token: An optional token that a server can use to report partial results (e.g. streaming) to + the client. + """ + + typedstruct do + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:partial_result_token, GenLSP.TypeAlias.ProgressToken.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + optional({"partialResultToken", :partial_result_token}) => + GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/document_symbol_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/document_symbol_registration_options.ex new file mode 100644 index 000000000..8f89e56d9 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/document_symbol_registration_options.ex @@ -0,0 +1,36 @@ +# codegen: do not edit +defmodule GenLSP.Structures.DocumentSymbolRegistrationOptions do + @moduledoc """ + Registration options for a {@link DocumentSymbolRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + * label: A human-readable string that is shown when multiple outlines trees + are shown for the same document. + + @since 3.16.0 + """ + + typedstruct do + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + field(:label, String.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]), + optional({"label", :label}) => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/execute_command_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/execute_command_client_capabilities.ex new file mode 100644 index 000000000..03ad4143d --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/execute_command_client_capabilities.ex @@ -0,0 +1,28 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ExecuteCommandClientCapabilities do + @moduledoc """ + The client capabilities of a {@link ExecuteCommandRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Execute command supports dynamic registration. + """ + + typedstruct do + field(:dynamic_registration, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/execute_command_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/execute_command_options.ex new file mode 100644 index 000000000..38d1759c0 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/execute_command_options.ex @@ -0,0 +1,31 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ExecuteCommandOptions do + @moduledoc """ + The server capabilities of a {@link ExecuteCommandRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * commands: The commands to be executed on the server + * work_done_progress + """ + + typedstruct do + field(:commands, list(String.t()), enforce: true) + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"commands", :commands} => list(str()), + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/execute_command_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/execute_command_params.ex new file mode 100644 index 000000000..16fcf6491 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/execute_command_params.ex @@ -0,0 +1,34 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ExecuteCommandParams do + @moduledoc """ + The parameters of a {@link ExecuteCommandRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * command: The identifier of the actual command handler. + * arguments: Arguments that the command should be invoked with. + * work_done_token: An optional token that a server can use to report work done progress. + """ + + typedstruct do + field(:command, String.t(), enforce: true) + field(:arguments, list(GenLSP.TypeAlias.LSPAny.t())) + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"command", :command} => str(), + optional({"arguments", :arguments}) => list(GenLSP.TypeAlias.LSPAny.schematic()), + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/execute_command_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/execute_command_registration_options.ex new file mode 100644 index 000000000..f745d4947 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/execute_command_registration_options.ex @@ -0,0 +1,28 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ExecuteCommandRegistrationOptions do + @moduledoc """ + Registration options for a {@link ExecuteCommandRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * commands: The commands to be executed on the server + """ + + typedstruct do + field(:commands, list(String.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"commands", :commands} => list(str()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/execution_summary.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/execution_summary.ex new file mode 100644 index 000000000..2e0c57389 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/execution_summary.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ExecutionSummary do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * execution_order: A strict monotonically increasing value + indicating the execution order of a cell + inside a notebook. + * success: Whether the execution was successful or + not if known by the client. + """ + + typedstruct do + field(:execution_order, GenLSP.BaseTypes.uinteger(), enforce: true) + field(:success, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"executionOrder", :execution_order} => int(), + optional({"success", :success}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/file_create.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/file_create.ex new file mode 100644 index 000000000..218d4da1f --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/file_create.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.FileCreate do + @moduledoc """ + Represents information on a file/folder create. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * uri: A file:// URI for the location of the file/folder being created. + """ + + typedstruct do + field(:uri, String.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"uri", :uri} => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/file_delete.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/file_delete.ex new file mode 100644 index 000000000..d346369d9 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/file_delete.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.FileDelete do + @moduledoc """ + Represents information on a file/folder delete. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * uri: A file:// URI for the location of the file/folder being deleted. + """ + + typedstruct do + field(:uri, String.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"uri", :uri} => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/file_event.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/file_event.ex new file mode 100644 index 000000000..f56d0c677 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/file_event.ex @@ -0,0 +1,31 @@ +# codegen: do not edit +defmodule GenLSP.Structures.FileEvent do + @moduledoc """ + An event describing a file change. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * uri: The file's uri. + * type: The change type. + """ + + typedstruct do + field(:uri, GenLSP.BaseTypes.document_uri(), enforce: true) + field(:type, GenLSP.Enumerations.FileChangeType.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"uri", :uri} => str(), + {"type", :type} => GenLSP.Enumerations.FileChangeType.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/file_operation_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/file_operation_client_capabilities.ex new file mode 100644 index 000000000..b2d49ca91 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/file_operation_client_capabilities.ex @@ -0,0 +1,51 @@ +# codegen: do not edit +defmodule GenLSP.Structures.FileOperationClientCapabilities do + @moduledoc """ + Capabilities relating to events from file operations by the user in the client. + + These events do not come from the file system, they come from user operations + like renaming a file in the UI. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether the client supports dynamic registration for file requests/notifications. + * did_create: The client has support for sending didCreateFiles notifications. + * will_create: The client has support for sending willCreateFiles requests. + * did_rename: The client has support for sending didRenameFiles notifications. + * will_rename: The client has support for sending willRenameFiles requests. + * did_delete: The client has support for sending didDeleteFiles notifications. + * will_delete: The client has support for sending willDeleteFiles requests. + """ + + typedstruct do + field(:dynamic_registration, boolean()) + field(:did_create, boolean()) + field(:will_create, boolean()) + field(:did_rename, boolean()) + field(:will_rename, boolean()) + field(:did_delete, boolean()) + field(:will_delete, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool(), + optional({"didCreate", :did_create}) => bool(), + optional({"willCreate", :will_create}) => bool(), + optional({"didRename", :did_rename}) => bool(), + optional({"willRename", :will_rename}) => bool(), + optional({"didDelete", :did_delete}) => bool(), + optional({"willDelete", :will_delete}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/file_operation_filter.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/file_operation_filter.ex new file mode 100644 index 000000000..4d671d932 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/file_operation_filter.ex @@ -0,0 +1,34 @@ +# codegen: do not edit +defmodule GenLSP.Structures.FileOperationFilter do + @moduledoc """ + A filter to describe in which file operation requests or notifications + the server is interested in receiving. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * scheme: A Uri scheme like `file` or `untitled`. + * pattern: The actual file operation pattern. + """ + + typedstruct do + field(:scheme, String.t()) + field(:pattern, GenLSP.Structures.FileOperationPattern.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"scheme", :scheme}) => str(), + {"pattern", :pattern} => GenLSP.Structures.FileOperationPattern.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/file_operation_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/file_operation_options.ex new file mode 100644 index 000000000..e88c1fec8 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/file_operation_options.ex @@ -0,0 +1,51 @@ +# codegen: do not edit +defmodule GenLSP.Structures.FileOperationOptions do + @moduledoc """ + Options for notifications/requests for user operations on files. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * did_create: The server is interested in receiving didCreateFiles notifications. + * will_create: The server is interested in receiving willCreateFiles requests. + * did_rename: The server is interested in receiving didRenameFiles notifications. + * will_rename: The server is interested in receiving willRenameFiles requests. + * did_delete: The server is interested in receiving didDeleteFiles file notifications. + * will_delete: The server is interested in receiving willDeleteFiles file requests. + """ + + typedstruct do + field(:did_create, GenLSP.Structures.FileOperationRegistrationOptions.t()) + field(:will_create, GenLSP.Structures.FileOperationRegistrationOptions.t()) + field(:did_rename, GenLSP.Structures.FileOperationRegistrationOptions.t()) + field(:will_rename, GenLSP.Structures.FileOperationRegistrationOptions.t()) + field(:did_delete, GenLSP.Structures.FileOperationRegistrationOptions.t()) + field(:will_delete, GenLSP.Structures.FileOperationRegistrationOptions.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"didCreate", :did_create}) => + GenLSP.Structures.FileOperationRegistrationOptions.schematic(), + optional({"willCreate", :will_create}) => + GenLSP.Structures.FileOperationRegistrationOptions.schematic(), + optional({"didRename", :did_rename}) => + GenLSP.Structures.FileOperationRegistrationOptions.schematic(), + optional({"willRename", :will_rename}) => + GenLSP.Structures.FileOperationRegistrationOptions.schematic(), + optional({"didDelete", :did_delete}) => + GenLSP.Structures.FileOperationRegistrationOptions.schematic(), + optional({"willDelete", :will_delete}) => + GenLSP.Structures.FileOperationRegistrationOptions.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/file_operation_pattern.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/file_operation_pattern.ex new file mode 100644 index 000000000..f38b5e561 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/file_operation_pattern.ex @@ -0,0 +1,45 @@ +# codegen: do not edit +defmodule GenLSP.Structures.FileOperationPattern do + @moduledoc """ + A pattern to describe in which file operation requests or notifications + the server is interested in receiving. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * glob: The glob pattern to match. Glob patterns can have the following syntax: + - `*` to match one or more characters in a path segment + - `?` to match on one character in a path segment + - `**` to match any number of path segments, including none + - `{}` to group sub patterns into an OR expression. (e.g. `**​/*.{ts,js}` matches all TypeScript and JavaScript files) + - `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …) + - `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`) + * matches: Whether to match files or folders with this pattern. + + Matches both if undefined. + * options: Additional options used during matching. + """ + + typedstruct do + field(:glob, String.t(), enforce: true) + field(:matches, GenLSP.Enumerations.FileOperationPatternKind.t()) + field(:options, GenLSP.Structures.FileOperationPatternOptions.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"glob", :glob} => str(), + optional({"matches", :matches}) => GenLSP.Enumerations.FileOperationPatternKind.schematic(), + optional({"options", :options}) => GenLSP.Structures.FileOperationPatternOptions.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/file_operation_pattern_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/file_operation_pattern_options.ex new file mode 100644 index 000000000..11e00c990 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/file_operation_pattern_options.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.FileOperationPatternOptions do + @moduledoc """ + Matching options for the file operation pattern. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * ignore_case: The pattern should be matched ignoring casing. + """ + + typedstruct do + field(:ignore_case, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"ignoreCase", :ignore_case}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/file_operation_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/file_operation_registration_options.ex new file mode 100644 index 000000000..1ccc71ac6 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/file_operation_registration_options.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.FileOperationRegistrationOptions do + @moduledoc """ + The options to register for file operations. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * filters: The actual filters. + """ + + typedstruct do + field(:filters, list(GenLSP.Structures.FileOperationFilter.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"filters", :filters} => list(GenLSP.Structures.FileOperationFilter.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/file_rename.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/file_rename.ex new file mode 100644 index 000000000..39becfd90 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/file_rename.ex @@ -0,0 +1,33 @@ +# codegen: do not edit +defmodule GenLSP.Structures.FileRename do + @moduledoc """ + Represents information on a file/folder rename. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * old_uri: A file:// URI for the original location of the file/folder being renamed. + * new_uri: A file:// URI for the new location of the file/folder being renamed. + """ + + typedstruct do + field(:old_uri, String.t(), enforce: true) + field(:new_uri, String.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"oldUri", :old_uri} => str(), + {"newUri", :new_uri} => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/file_system_watcher.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/file_system_watcher.ex new file mode 100644 index 000000000..933b57d98 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/file_system_watcher.ex @@ -0,0 +1,31 @@ +# codegen: do not edit +defmodule GenLSP.Structures.FileSystemWatcher do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * glob_pattern: The glob pattern to watch. See {@link GlobPattern glob pattern} for more detail. + + @since 3.17.0 support for relative patterns. + * kind: The kind of events of interest. If omitted it defaults + to WatchKind.Create | WatchKind.Change | WatchKind.Delete + which is 7. + """ + + typedstruct do + field(:glob_pattern, GenLSP.TypeAlias.GlobPattern.t(), enforce: true) + field(:kind, GenLSP.Enumerations.WatchKind.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"globPattern", :glob_pattern} => GenLSP.TypeAlias.GlobPattern.schematic(), + optional({"kind", :kind}) => GenLSP.Enumerations.WatchKind.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/folding_range.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/folding_range.ex new file mode 100644 index 000000000..c7f4cd55b --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/folding_range.ex @@ -0,0 +1,52 @@ +# codegen: do not edit +defmodule GenLSP.Structures.FoldingRange do + @moduledoc """ + Represents a folding range. To be valid, start and end line must be bigger than zero and smaller + than the number of lines in the document. Clients are free to ignore invalid ranges. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * start_line: The zero-based start line of the range to fold. The folded area starts after the line's last character. + To be valid, the end must be zero or larger and smaller than the number of lines in the document. + * start_character: The zero-based character offset from where the folded range starts. If not defined, defaults to the length of the start line. + * end_line: The zero-based end line of the range to fold. The folded area ends with the line's last character. + To be valid, the end must be zero or larger and smaller than the number of lines in the document. + * end_character: The zero-based character offset before the folded range ends. If not defined, defaults to the length of the end line. + * kind: Describes the kind of the folding range such as 'comment' or 'region'. The kind + is used to categorize folding ranges and used by commands like 'Fold all comments'. + See {@link FoldingRangeKind} for an enumeration of standardized kinds. + * collapsed_text: The text that the client should show when the specified range is + collapsed. If not defined or not supported by the client, a default + will be chosen by the client. + + @since 3.17.0 + """ + + typedstruct do + field(:start_line, GenLSP.BaseTypes.uinteger(), enforce: true) + field(:start_character, GenLSP.BaseTypes.uinteger()) + field(:end_line, GenLSP.BaseTypes.uinteger(), enforce: true) + field(:end_character, GenLSP.BaseTypes.uinteger()) + field(:kind, GenLSP.Enumerations.FoldingRangeKind.t()) + field(:collapsed_text, String.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"startLine", :start_line} => int(), + optional({"startCharacter", :start_character}) => int(), + {"endLine", :end_line} => int(), + optional({"endCharacter", :end_character}) => int(), + optional({"kind", :kind}) => GenLSP.Enumerations.FoldingRangeKind.schematic(), + optional({"collapsedText", :collapsed_text}) => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/folding_range_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/folding_range_client_capabilities.ex new file mode 100644 index 000000000..1466b374f --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/folding_range_client_capabilities.ex @@ -0,0 +1,54 @@ +# codegen: do not edit +defmodule GenLSP.Structures.FoldingRangeClientCapabilities do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether implementation supports dynamic registration for folding range + providers. If this is set to `true` the client supports the new + `FoldingRangeRegistrationOptions` return value for the corresponding + server capability as well. + * range_limit: The maximum number of folding ranges that the client prefers to receive + per document. The value serves as a hint, servers are free to follow the + limit. + * line_folding_only: If set, the client signals that it only supports folding complete lines. + If set, client will ignore specified `startCharacter` and `endCharacter` + properties in a FoldingRange. + * folding_range_kind: Specific options for the folding range kind. + + @since 3.17.0 + * folding_range: Specific options for the folding range. + + @since 3.17.0 + """ + + typedstruct do + field(:dynamic_registration, boolean()) + field(:range_limit, GenLSP.BaseTypes.uinteger()) + field(:line_folding_only, boolean()) + field(:folding_range_kind, map()) + field(:folding_range, map()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool(), + optional({"rangeLimit", :range_limit}) => int(), + optional({"lineFoldingOnly", :line_folding_only}) => bool(), + optional({"foldingRangeKind", :folding_range_kind}) => + map(%{ + optional({"valueSet", :value_set}) => + list(GenLSP.Enumerations.FoldingRangeKind.schematic()) + }), + optional({"foldingRange", :folding_range}) => + map(%{ + optional({"collapsedText", :collapsed_text}) => bool() + }) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/folding_range_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/folding_range_options.ex new file mode 100644 index 000000000..5870ab026 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/folding_range_options.ex @@ -0,0 +1,24 @@ +# codegen: do not edit +defmodule GenLSP.Structures.FoldingRangeOptions do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_progress + """ + + typedstruct do + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/folding_range_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/folding_range_params.ex new file mode 100644 index 000000000..bf5539905 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/folding_range_params.ex @@ -0,0 +1,36 @@ +# codegen: do not edit +defmodule GenLSP.Structures.FoldingRangeParams do + @moduledoc """ + Parameters for a {@link FoldingRangeRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * text_document: The text document. + * work_done_token: An optional token that a server can use to report work done progress. + * partial_result_token: An optional token that a server can use to report partial results (e.g. streaming) to + the client. + """ + + typedstruct do + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:partial_result_token, GenLSP.TypeAlias.ProgressToken.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + optional({"partialResultToken", :partial_result_token}) => + GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/folding_range_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/folding_range_registration_options.ex new file mode 100644 index 000000000..454386217 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/folding_range_registration_options.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.FoldingRangeRegistrationOptions do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * id: The id used to register the request. The id can be used to deregister + the request again. See also Registration#id. + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + """ + + typedstruct do + field(:id, String.t()) + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"id", :id}) => str(), + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/formatting_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/formatting_options.ex new file mode 100644 index 000000000..797784f2f --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/formatting_options.ex @@ -0,0 +1,46 @@ +# codegen: do not edit +defmodule GenLSP.Structures.FormattingOptions do + @moduledoc """ + Value-object describing what options formatting should use. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * tab_size: Size of a tab in spaces. + * insert_spaces: Prefer spaces over tabs. + * trim_trailing_whitespace: Trim trailing whitespace on a line. + + @since 3.15.0 + * insert_final_newline: Insert a newline character at the end of the file if one does not exist. + + @since 3.15.0 + * trim_final_newlines: Trim all newlines after the final newline at the end of the file. + + @since 3.15.0 + """ + + typedstruct do + field(:tab_size, GenLSP.BaseTypes.uinteger(), enforce: true) + field(:insert_spaces, boolean(), enforce: true) + field(:trim_trailing_whitespace, boolean()) + field(:insert_final_newline, boolean()) + field(:trim_final_newlines, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"tabSize", :tab_size} => int(), + {"insertSpaces", :insert_spaces} => bool(), + optional({"trimTrailingWhitespace", :trim_trailing_whitespace}) => bool(), + optional({"insertFinalNewline", :insert_final_newline}) => bool(), + optional({"trimFinalNewlines", :trim_final_newlines}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/full_document_diagnostic_report.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/full_document_diagnostic_report.ex new file mode 100644 index 000000000..af1a24b09 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/full_document_diagnostic_report.ex @@ -0,0 +1,38 @@ +# codegen: do not edit +defmodule GenLSP.Structures.FullDocumentDiagnosticReport do + @moduledoc """ + A diagnostic report with a full set of problems. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * kind: A full document diagnostic report. + * result_id: An optional result id. If provided it will + be sent on the next diagnostic request for the + same document. + * items: The actual items. + """ + + typedstruct do + field(:kind, String.t(), enforce: true) + field(:result_id, String.t()) + field(:items, list(GenLSP.Structures.Diagnostic.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"kind", :kind} => "full", + optional({"resultId", :result_id}) => str(), + {"items", :items} => list(GenLSP.Structures.Diagnostic.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/general_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/general_client_capabilities.ex new file mode 100644 index 000000000..552e1366e --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/general_client_capabilities.ex @@ -0,0 +1,72 @@ +# codegen: do not edit +defmodule GenLSP.Structures.GeneralClientCapabilities do + @moduledoc """ + General client capabilities. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * stale_request_support: Client capability that signals how the client + handles stale requests (e.g. a request + for which the client will not process the response + anymore since the information is outdated). + + @since 3.17.0 + * regular_expressions: Client capabilities specific to regular expressions. + + @since 3.16.0 + * markdown: Client capabilities specific to the client's markdown parser. + + @since 3.16.0 + * position_encodings: The position encodings supported by the client. Client and server + have to agree on the same position encoding to ensure that offsets + (e.g. character position in a line) are interpreted the same on both + sides. + + To keep the protocol backwards compatible the following applies: if + the value 'utf-16' is missing from the array of position encodings + servers can assume that the client supports UTF-16. UTF-16 is + therefore a mandatory encoding. + + If omitted it defaults to ['utf-16']. + + Implementation considerations: since the conversion from one encoding + into another requires the content of the file / line the conversion + is best done where the file is read which is usually on the server + side. + + @since 3.17.0 + """ + + typedstruct do + field(:stale_request_support, map()) + field(:regular_expressions, GenLSP.Structures.RegularExpressionsClientCapabilities.t()) + field(:markdown, GenLSP.Structures.MarkdownClientCapabilities.t()) + field(:position_encodings, list(GenLSP.Enumerations.PositionEncodingKind.t())) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"staleRequestSupport", :stale_request_support}) => + map(%{ + {"cancel", :cancel} => bool(), + {"retryOnContentModified", :retry_on_content_modified} => list(str()) + }), + optional({"regularExpressions", :regular_expressions}) => + GenLSP.Structures.RegularExpressionsClientCapabilities.schematic(), + optional({"markdown", :markdown}) => + GenLSP.Structures.MarkdownClientCapabilities.schematic(), + optional({"positionEncodings", :position_encodings}) => + list(GenLSP.Enumerations.PositionEncodingKind.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/hover.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/hover.ex new file mode 100644 index 000000000..2d965932b --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/hover.ex @@ -0,0 +1,44 @@ +# codegen: do not edit +defmodule GenLSP.Structures.Hover do + @moduledoc """ + The result of a hover request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * contents: The hover's content + * range: An optional range inside the text document that is used to + visualize the hover, e.g. by changing the background color. + """ + + typedstruct do + field( + :contents, + GenLSP.Structures.MarkupContent.t() + | GenLSP.TypeAlias.MarkedString.t() + | list(GenLSP.TypeAlias.MarkedString.t()), + enforce: true + ) + + field(:range, GenLSP.Structures.Range.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"contents", :contents} => + oneof([ + GenLSP.Structures.MarkupContent.schematic(), + GenLSP.TypeAlias.MarkedString.schematic(), + list(GenLSP.TypeAlias.MarkedString.schematic()) + ]), + optional({"range", :range}) => GenLSP.Structures.Range.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/hover_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/hover_client_capabilities.ex new file mode 100644 index 000000000..bb1b0dfe1 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/hover_client_capabilities.ex @@ -0,0 +1,29 @@ +# codegen: do not edit +defmodule GenLSP.Structures.HoverClientCapabilities do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether hover supports dynamic registration. + * content_format: Client supports the following content formats for the content + property. The order describes the preferred format of the client. + """ + + typedstruct do + field(:dynamic_registration, boolean()) + field(:content_format, list(GenLSP.Enumerations.MarkupKind.t())) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool(), + optional({"contentFormat", :content_format}) => + list(GenLSP.Enumerations.MarkupKind.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/hover_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/hover_options.ex new file mode 100644 index 000000000..ea99b6e76 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/hover_options.ex @@ -0,0 +1,28 @@ +# codegen: do not edit +defmodule GenLSP.Structures.HoverOptions do + @moduledoc """ + Hover options. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_progress + """ + + typedstruct do + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/hover_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/hover_params.ex new file mode 100644 index 000000000..2b0924f8d --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/hover_params.ex @@ -0,0 +1,34 @@ +# codegen: do not edit +defmodule GenLSP.Structures.HoverParams do + @moduledoc """ + Parameters for a {@link HoverRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_token: An optional token that a server can use to report work done progress. + * text_document: The text document. + * position: The position inside the text document. + """ + + typedstruct do + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:position, GenLSP.Structures.Position.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + {"position", :position} => GenLSP.Structures.Position.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/hover_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/hover_registration_options.ex new file mode 100644 index 000000000..e3d908f1e --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/hover_registration_options.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.HoverRegistrationOptions do + @moduledoc """ + Registration options for a {@link HoverRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + """ + + typedstruct do + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/implementation_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/implementation_client_capabilities.ex new file mode 100644 index 000000000..5b1f759e9 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/implementation_client_capabilities.ex @@ -0,0 +1,35 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ImplementationClientCapabilities do + @moduledoc """ + @since 3.6.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether implementation supports dynamic registration. If this is set to `true` + the client supports the new `ImplementationRegistrationOptions` return value + for the corresponding server capability as well. + * link_support: The client supports additional metadata in the form of definition links. + + @since 3.14.0 + """ + + typedstruct do + field(:dynamic_registration, boolean()) + field(:link_support, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool(), + optional({"linkSupport", :link_support}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/implementation_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/implementation_options.ex new file mode 100644 index 000000000..518d7b866 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/implementation_options.ex @@ -0,0 +1,24 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ImplementationOptions do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_progress + """ + + typedstruct do + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/implementation_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/implementation_params.ex new file mode 100644 index 000000000..21ce4b586 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/implementation_params.ex @@ -0,0 +1,35 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ImplementationParams do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_token: An optional token that a server can use to report work done progress. + * partial_result_token: An optional token that a server can use to report partial results (e.g. streaming) to + the client. + * text_document: The text document. + * position: The position inside the text document. + """ + + typedstruct do + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:partial_result_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:position, GenLSP.Structures.Position.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + optional({"partialResultToken", :partial_result_token}) => + GenLSP.TypeAlias.ProgressToken.schematic(), + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + {"position", :position} => GenLSP.Structures.Position.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/implementation_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/implementation_registration_options.ex new file mode 100644 index 000000000..311ffc7eb --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/implementation_registration_options.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ImplementationRegistrationOptions do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * id: The id used to register the request. The id can be used to deregister + the request again. See also Registration#id. + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + """ + + typedstruct do + field(:id, String.t()) + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"id", :id}) => str(), + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/initialize_error.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/initialize_error.ex new file mode 100644 index 000000000..213e32ba6 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/initialize_error.ex @@ -0,0 +1,32 @@ +# codegen: do not edit +defmodule GenLSP.Structures.InitializeError do + @moduledoc """ + The data type of the ResponseError if the + initialize request fails. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * retry: Indicates whether the client execute the following retry logic: + (1) show the message provided by the ResponseError to the user + (2) user selects retry or cancel + (3) if user selected retry the initialize method is sent again. + """ + + typedstruct do + field(:retry, boolean(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"retry", :retry} => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/initialize_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/initialize_params.ex new file mode 100644 index 000000000..f1d6905d2 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/initialize_params.ex @@ -0,0 +1,80 @@ +# codegen: do not edit +defmodule GenLSP.Structures.InitializeParams do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * process_id: The process Id of the parent process that started + the server. + + Is `null` if the process has not been started by another process. + If the parent process is not alive then the server should exit. + * client_info: Information about the client + + @since 3.15.0 + * locale: The locale the client is currently showing the user interface + in. This must not necessarily be the locale of the operating + system. + + Uses IETF language tags as the value's syntax + (See https://en.wikipedia.org/wiki/IETF_language_tag) + + @since 3.16.0 + * root_path: The rootPath of the workspace. Is null + if no folder is open. + + @deprecated in favour of rootUri. + * root_uri: The rootUri of the workspace. Is null if no + folder is open. If both `rootPath` and `rootUri` are set + `rootUri` wins. + + @deprecated in favour of workspaceFolders. + * capabilities: The capabilities provided by the client (editor or tool) + * initialization_options: User provided initialization options. + * trace: The initial trace setting. If omitted trace is disabled ('off'). + * workspace_folders: The workspace folders configured in the client when the server starts. + + This property is only available if the client supports workspace folders. + It can be `null` if the client supports workspace folders but none are + configured. + + @since 3.6.0 + """ + + typedstruct do + field(:process_id, integer() | nil, enforce: true) + field(:client_info, map()) + field(:locale, String.t()) + field(:root_path, String.t() | nil) + field(:root_uri, GenLSP.BaseTypes.document_uri() | nil, enforce: true) + field(:capabilities, GenLSP.Structures.ClientCapabilities.t(), enforce: true) + field(:initialization_options, GenLSP.TypeAlias.LSPAny.t()) + field(:trace, GenLSP.Enumerations.TraceValues.t()) + field(:workspace_folders, list(GenLSP.Structures.WorkspaceFolder.t()) | nil) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"processId", :process_id} => oneof([int(), nil]), + optional({"clientInfo", :client_info}) => + map(%{ + {"name", :name} => str(), + optional({"version", :version}) => str() + }), + optional({"locale", :locale}) => str(), + optional({"rootPath", :root_path}) => oneof([str(), nil]), + {"rootUri", :root_uri} => oneof([str(), nil]), + {"capabilities", :capabilities} => GenLSP.Structures.ClientCapabilities.schematic(), + optional({"initializationOptions", :initialization_options}) => + GenLSP.TypeAlias.LSPAny.schematic(), + optional({"trace", :trace}) => GenLSP.Enumerations.TraceValues.schematic(), + optional({"workspaceFolders", :workspace_folders}) => + oneof([list(GenLSP.Structures.WorkspaceFolder.schematic()), nil]) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/initialize_result.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/initialize_result.ex new file mode 100644 index 000000000..4a12770f8 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/initialize_result.ex @@ -0,0 +1,37 @@ +# codegen: do not edit +defmodule GenLSP.Structures.InitializeResult do + @moduledoc """ + The result returned from an initialize request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * capabilities: The capabilities the language server provides. + * server_info: Information about the server. + + @since 3.15.0 + """ + + typedstruct do + field(:capabilities, GenLSP.Structures.ServerCapabilities.t(), enforce: true) + field(:server_info, map()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"capabilities", :capabilities} => GenLSP.Structures.ServerCapabilities.schematic(), + optional({"serverInfo", :server_info}) => + map(%{ + {"name", :name} => str(), + optional({"version", :version}) => str() + }) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/initialized_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/initialized_params.ex new file mode 100644 index 000000000..cb126d61c --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/initialized_params.ex @@ -0,0 +1,20 @@ +# codegen: do not edit +defmodule GenLSP.Structures.InitializedParams do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + """ + + typedstruct do + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{}) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/inlay_hint.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/inlay_hint.ex new file mode 100644 index 000000000..857e1a42c --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/inlay_hint.ex @@ -0,0 +1,69 @@ +# codegen: do not edit +defmodule GenLSP.Structures.InlayHint do + @moduledoc """ + Inlay hint information. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * position: The position of this hint. + * label: The label of this hint. A human readable string or an array of + InlayHintLabelPart label parts. + + *Note* that neither the string nor the label part can be empty. + * kind: The kind of this hint. Can be omitted in which case the client + should fall back to a reasonable default. + * text_edits: Optional text edits that are performed when accepting this inlay hint. + + *Note* that edits are expected to change the document so that the inlay + hint (or its nearest variant) is now part of the document and the inlay + hint itself is now obsolete. + * tooltip: The tooltip text when you hover over this item. + * padding_left: Render padding before the hint. + + Note: Padding should use the editor's background color, not the + background color of the hint itself. That means padding can be used + to visually align/separate an inlay hint. + * padding_right: Render padding after the hint. + + Note: Padding should use the editor's background color, not the + background color of the hint itself. That means padding can be used + to visually align/separate an inlay hint. + * data: A data entry field that is preserved on an inlay hint between + a `textDocument/inlayHint` and a `inlayHint/resolve` request. + """ + + typedstruct do + field(:position, GenLSP.Structures.Position.t(), enforce: true) + field(:label, String.t() | list(GenLSP.Structures.InlayHintLabelPart.t()), enforce: true) + field(:kind, GenLSP.Enumerations.InlayHintKind.t()) + field(:text_edits, list(GenLSP.Structures.TextEdit.t())) + field(:tooltip, String.t() | GenLSP.Structures.MarkupContent.t()) + field(:padding_left, boolean()) + field(:padding_right, boolean()) + field(:data, GenLSP.TypeAlias.LSPAny.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"position", :position} => GenLSP.Structures.Position.schematic(), + {"label", :label} => oneof([str(), list(GenLSP.Structures.InlayHintLabelPart.schematic())]), + optional({"kind", :kind}) => GenLSP.Enumerations.InlayHintKind.schematic(), + optional({"textEdits", :text_edits}) => list(GenLSP.Structures.TextEdit.schematic()), + optional({"tooltip", :tooltip}) => + oneof([str(), GenLSP.Structures.MarkupContent.schematic()]), + optional({"paddingLeft", :padding_left}) => bool(), + optional({"paddingRight", :padding_right}) => bool(), + optional({"data", :data}) => GenLSP.TypeAlias.LSPAny.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/inlay_hint_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/inlay_hint_client_capabilities.ex new file mode 100644 index 000000000..ac6c6759b --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/inlay_hint_client_capabilities.ex @@ -0,0 +1,37 @@ +# codegen: do not edit +defmodule GenLSP.Structures.InlayHintClientCapabilities do + @moduledoc """ + Inlay hint client capabilities. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether inlay hints support dynamic registration. + * resolve_support: Indicates which properties a client can resolve lazily on an inlay + hint. + """ + + typedstruct do + field(:dynamic_registration, boolean()) + field(:resolve_support, map()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool(), + optional({"resolveSupport", :resolve_support}) => + map(%{ + {"properties", :properties} => list(str()) + }) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/inlay_hint_label_part.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/inlay_hint_label_part.ex new file mode 100644 index 000000000..c515daf0d --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/inlay_hint_label_part.ex @@ -0,0 +1,56 @@ +# codegen: do not edit +defmodule GenLSP.Structures.InlayHintLabelPart do + @moduledoc """ + An inlay hint label part allows for interactive and composite labels + of inlay hints. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * value: The value of this label part. + * tooltip: The tooltip text when you hover over this label part. Depending on + the client capability `inlayHint.resolveSupport` clients might resolve + this property late using the resolve request. + * location: An optional source code location that represents this + label part. + + The editor will use this location for the hover and for code navigation + features: This part will become a clickable link that resolves to the + definition of the symbol at the given location (not necessarily the + location itself), it shows the hover that shows at the given location, + and it shows a context menu with further code navigation commands. + + Depending on the client capability `inlayHint.resolveSupport` clients + might resolve this property late using the resolve request. + * command: An optional command for this label part. + + Depending on the client capability `inlayHint.resolveSupport` clients + might resolve this property late using the resolve request. + """ + + typedstruct do + field(:value, String.t(), enforce: true) + field(:tooltip, String.t() | GenLSP.Structures.MarkupContent.t()) + field(:location, GenLSP.Structures.Location.t()) + field(:command, GenLSP.Structures.Command.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"value", :value} => str(), + optional({"tooltip", :tooltip}) => + oneof([str(), GenLSP.Structures.MarkupContent.schematic()]), + optional({"location", :location}) => GenLSP.Structures.Location.schematic(), + optional({"command", :command}) => GenLSP.Structures.Command.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/inlay_hint_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/inlay_hint_options.ex new file mode 100644 index 000000000..984f75c71 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/inlay_hint_options.ex @@ -0,0 +1,34 @@ +# codegen: do not edit +defmodule GenLSP.Structures.InlayHintOptions do + @moduledoc """ + Inlay hint options used during static registration. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * resolve_provider: The server provides support to resolve additional + information for an inlay hint item. + * work_done_progress + """ + + typedstruct do + field(:resolve_provider, boolean()) + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"resolveProvider", :resolve_provider}) => bool(), + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/inlay_hint_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/inlay_hint_params.ex new file mode 100644 index 000000000..277d67f8a --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/inlay_hint_params.ex @@ -0,0 +1,36 @@ +# codegen: do not edit +defmodule GenLSP.Structures.InlayHintParams do + @moduledoc """ + A parameter literal used in inlay hint requests. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * text_document: The text document. + * range: The document range for which inlay hints should be computed. + * work_done_token: An optional token that a server can use to report work done progress. + """ + + typedstruct do + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:range, GenLSP.Structures.Range.t(), enforce: true) + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + {"range", :range} => GenLSP.Structures.Range.schematic(), + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/inlay_hint_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/inlay_hint_registration_options.ex new file mode 100644 index 000000000..db4c1ac71 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/inlay_hint_registration_options.ex @@ -0,0 +1,40 @@ +# codegen: do not edit +defmodule GenLSP.Structures.InlayHintRegistrationOptions do + @moduledoc """ + Inlay hint options used during static or dynamic registration. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * id: The id used to register the request. The id can be used to deregister + the request again. See also Registration#id. + * resolve_provider: The server provides support to resolve additional + information for an inlay hint item. + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + """ + + typedstruct do + field(:id, String.t()) + field(:resolve_provider, boolean()) + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"id", :id}) => str(), + optional({"resolveProvider", :resolve_provider}) => bool(), + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/inlay_hint_workspace_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/inlay_hint_workspace_client_capabilities.ex new file mode 100644 index 000000000..c96836b2f --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/inlay_hint_workspace_client_capabilities.ex @@ -0,0 +1,36 @@ +# codegen: do not edit +defmodule GenLSP.Structures.InlayHintWorkspaceClientCapabilities do + @moduledoc """ + Client workspace capabilities specific to inlay hints. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * refresh_support: Whether the client implementation supports a refresh request sent from + the server to the client. + + Note that this event is global and will force the client to refresh all + inlay hints currently shown. It should be used with absolute care and + is useful for situation where a server for example detects a project wide + change that requires such a calculation. + """ + + typedstruct do + field(:refresh_support, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"refreshSupport", :refresh_support}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/inline_value_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/inline_value_client_capabilities.ex new file mode 100644 index 000000000..f430fb4ac --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/inline_value_client_capabilities.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.InlineValueClientCapabilities do + @moduledoc """ + Client capabilities specific to inline values. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether implementation supports dynamic registration for inline value providers. + """ + + typedstruct do + field(:dynamic_registration, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/inline_value_context.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/inline_value_context.ex new file mode 100644 index 000000000..29eb3e47d --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/inline_value_context.ex @@ -0,0 +1,32 @@ +# codegen: do not edit +defmodule GenLSP.Structures.InlineValueContext do + @moduledoc """ + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * frame_id: The stack frame (as a DAP Id) where the execution has stopped. + * stopped_location: The document range where execution has stopped. + Typically the end position of the range denotes the line where the inline values are shown. + """ + + typedstruct do + field(:frame_id, integer(), enforce: true) + field(:stopped_location, GenLSP.Structures.Range.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"frameId", :frame_id} => int(), + {"stoppedLocation", :stopped_location} => GenLSP.Structures.Range.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/inline_value_evaluatable_expression.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/inline_value_evaluatable_expression.ex new file mode 100644 index 000000000..3be494210 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/inline_value_evaluatable_expression.ex @@ -0,0 +1,36 @@ +# codegen: do not edit +defmodule GenLSP.Structures.InlineValueEvaluatableExpression do + @moduledoc """ + Provide an inline value through an expression evaluation. + If only a range is specified, the expression will be extracted from the underlying document. + An optional expression can be used to override the extracted expression. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * range: The document range for which the inline value applies. + The range is used to extract the evaluatable expression from the underlying document. + * expression: If specified the expression overrides the extracted expression. + """ + + typedstruct do + field(:range, GenLSP.Structures.Range.t(), enforce: true) + field(:expression, String.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"range", :range} => GenLSP.Structures.Range.schematic(), + optional({"expression", :expression}) => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/inline_value_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/inline_value_options.ex new file mode 100644 index 000000000..12c2bd4a1 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/inline_value_options.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.InlineValueOptions do + @moduledoc """ + Inline value options used during static registration. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_progress + """ + + typedstruct do + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/inline_value_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/inline_value_params.ex new file mode 100644 index 000000000..90cbf03a5 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/inline_value_params.ex @@ -0,0 +1,40 @@ +# codegen: do not edit +defmodule GenLSP.Structures.InlineValueParams do + @moduledoc """ + A parameter literal used in inline value requests. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * text_document: The text document. + * range: The document range for which inline values should be computed. + * context: Additional information about the context in which inline values were + requested. + * work_done_token: An optional token that a server can use to report work done progress. + """ + + typedstruct do + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:range, GenLSP.Structures.Range.t(), enforce: true) + field(:context, GenLSP.Structures.InlineValueContext.t(), enforce: true) + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + {"range", :range} => GenLSP.Structures.Range.schematic(), + {"context", :context} => GenLSP.Structures.InlineValueContext.schematic(), + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/inline_value_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/inline_value_registration_options.ex new file mode 100644 index 000000000..a3c65f1ce --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/inline_value_registration_options.ex @@ -0,0 +1,36 @@ +# codegen: do not edit +defmodule GenLSP.Structures.InlineValueRegistrationOptions do + @moduledoc """ + Inline value options used during static or dynamic registration. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * id: The id used to register the request. The id can be used to deregister + the request again. See also Registration#id. + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + """ + + typedstruct do + field(:id, String.t()) + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"id", :id}) => str(), + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/inline_value_text.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/inline_value_text.ex new file mode 100644 index 000000000..96a6931d7 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/inline_value_text.ex @@ -0,0 +1,33 @@ +# codegen: do not edit +defmodule GenLSP.Structures.InlineValueText do + @moduledoc """ + Provide inline value as text. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * range: The document range for which the inline value applies. + * text: The text of the inline value. + """ + + typedstruct do + field(:range, GenLSP.Structures.Range.t(), enforce: true) + field(:text, String.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"range", :range} => GenLSP.Structures.Range.schematic(), + {"text", :text} => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/inline_value_variable_lookup.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/inline_value_variable_lookup.ex new file mode 100644 index 000000000..1459d16d7 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/inline_value_variable_lookup.ex @@ -0,0 +1,39 @@ +# codegen: do not edit +defmodule GenLSP.Structures.InlineValueVariableLookup do + @moduledoc """ + Provide inline value through a variable lookup. + If only a range is specified, the variable name will be extracted from the underlying document. + An optional variable name can be used to override the extracted name. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * range: The document range for which the inline value applies. + The range is used to extract the variable name from the underlying document. + * variable_name: If specified the name of the variable to look up. + * case_sensitive_lookup: How to perform the lookup. + """ + + typedstruct do + field(:range, GenLSP.Structures.Range.t(), enforce: true) + field(:variable_name, String.t()) + field(:case_sensitive_lookup, boolean(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"range", :range} => GenLSP.Structures.Range.schematic(), + optional({"variableName", :variable_name}) => str(), + {"caseSensitiveLookup", :case_sensitive_lookup} => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/inline_value_workspace_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/inline_value_workspace_client_capabilities.ex new file mode 100644 index 000000000..e1d878c16 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/inline_value_workspace_client_capabilities.ex @@ -0,0 +1,36 @@ +# codegen: do not edit +defmodule GenLSP.Structures.InlineValueWorkspaceClientCapabilities do + @moduledoc """ + Client workspace capabilities specific to inline values. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * refresh_support: Whether the client implementation supports a refresh request sent from the + server to the client. + + Note that this event is global and will force the client to refresh all + inline values currently shown. It should be used with absolute care and is + useful for situation where a server for example detects a project wide + change that requires such a calculation. + """ + + typedstruct do + field(:refresh_support, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"refreshSupport", :refresh_support}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/insert_replace_edit.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/insert_replace_edit.ex new file mode 100644 index 000000000..90c93c32b --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/insert_replace_edit.ex @@ -0,0 +1,36 @@ +# codegen: do not edit +defmodule GenLSP.Structures.InsertReplaceEdit do + @moduledoc """ + A special text edit to provide an insert and a replace operation. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * new_text: The string to be inserted. + * insert: The range if the insert is requested + * replace: The range if the replace is requested. + """ + + typedstruct do + field(:new_text, String.t(), enforce: true) + field(:insert, GenLSP.Structures.Range.t(), enforce: true) + field(:replace, GenLSP.Structures.Range.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"newText", :new_text} => str(), + {"insert", :insert} => GenLSP.Structures.Range.schematic(), + {"replace", :replace} => GenLSP.Structures.Range.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/linked_editing_range_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/linked_editing_range_client_capabilities.ex new file mode 100644 index 000000000..3c3ebced9 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/linked_editing_range_client_capabilities.ex @@ -0,0 +1,32 @@ +# codegen: do not edit +defmodule GenLSP.Structures.LinkedEditingRangeClientCapabilities do + @moduledoc """ + Client capabilities for the linked editing range request. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether implementation supports dynamic registration. If this is set to `true` + the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)` + return value for the corresponding server capability as well. + """ + + typedstruct do + field(:dynamic_registration, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/linked_editing_range_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/linked_editing_range_options.ex new file mode 100644 index 000000000..6909061c7 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/linked_editing_range_options.ex @@ -0,0 +1,24 @@ +# codegen: do not edit +defmodule GenLSP.Structures.LinkedEditingRangeOptions do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_progress + """ + + typedstruct do + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/linked_editing_range_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/linked_editing_range_params.ex new file mode 100644 index 000000000..9baff20d4 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/linked_editing_range_params.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.LinkedEditingRangeParams do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_token: An optional token that a server can use to report work done progress. + * text_document: The text document. + * position: The position inside the text document. + """ + + typedstruct do + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:position, GenLSP.Structures.Position.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + {"position", :position} => GenLSP.Structures.Position.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/linked_editing_range_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/linked_editing_range_registration_options.ex new file mode 100644 index 000000000..99c72efae --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/linked_editing_range_registration_options.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.LinkedEditingRangeRegistrationOptions do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * id: The id used to register the request. The id can be used to deregister + the request again. See also Registration#id. + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + """ + + typedstruct do + field(:id, String.t()) + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"id", :id}) => str(), + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/linked_editing_ranges.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/linked_editing_ranges.ex new file mode 100644 index 000000000..94e60ab02 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/linked_editing_ranges.ex @@ -0,0 +1,36 @@ +# codegen: do not edit +defmodule GenLSP.Structures.LinkedEditingRanges do + @moduledoc """ + The result of a linked editing range request. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * ranges: A list of ranges that can be edited together. The ranges must have + identical length and contain identical text content. The ranges cannot overlap. + * word_pattern: An optional word pattern (regular expression) that describes valid contents for + the given ranges. If no pattern is provided, the client configuration's word + pattern will be used. + """ + + typedstruct do + field(:ranges, list(GenLSP.Structures.Range.t()), enforce: true) + field(:word_pattern, String.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"ranges", :ranges} => list(GenLSP.Structures.Range.schematic()), + optional({"wordPattern", :word_pattern}) => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/location.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/location.ex new file mode 100644 index 000000000..db5a2ac04 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/location.ex @@ -0,0 +1,32 @@ +# codegen: do not edit +defmodule GenLSP.Structures.Location do + @moduledoc """ + Represents a location inside a resource, such as a line + inside a text file. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * uri + * range + """ + + typedstruct do + field(:uri, GenLSP.BaseTypes.document_uri(), enforce: true) + field(:range, GenLSP.Structures.Range.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"uri", :uri} => str(), + {"range", :range} => GenLSP.Structures.Range.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/location_link.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/location_link.ex new file mode 100644 index 000000000..1409ee8fd --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/location_link.ex @@ -0,0 +1,45 @@ +# codegen: do not edit +defmodule GenLSP.Structures.LocationLink do + @moduledoc """ + Represents the connection of two locations. Provides additional metadata over normal {@link Location locations}, + including an origin range. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * origin_selection_range: Span of the origin of this link. + + Used as the underlined span for mouse interaction. Defaults to the word range at + the definition position. + * target_uri: The target resource identifier of this link. + * target_range: The full target range of this link. If the target for example is a symbol then target range is the + range enclosing this symbol not including leading/trailing whitespace but everything else + like comments. This information is typically used to highlight the range in the editor. + * target_selection_range: The range that should be selected and revealed when this link is being followed, e.g the name of a function. + Must be contained by the `targetRange`. See also `DocumentSymbol#range` + """ + + typedstruct do + field(:origin_selection_range, GenLSP.Structures.Range.t()) + field(:target_uri, GenLSP.BaseTypes.document_uri(), enforce: true) + field(:target_range, GenLSP.Structures.Range.t(), enforce: true) + field(:target_selection_range, GenLSP.Structures.Range.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"originSelectionRange", :origin_selection_range}) => + GenLSP.Structures.Range.schematic(), + {"targetUri", :target_uri} => str(), + {"targetRange", :target_range} => GenLSP.Structures.Range.schematic(), + {"targetSelectionRange", :target_selection_range} => GenLSP.Structures.Range.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/log_message_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/log_message_params.ex new file mode 100644 index 000000000..84faff96f --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/log_message_params.ex @@ -0,0 +1,31 @@ +# codegen: do not edit +defmodule GenLSP.Structures.LogMessageParams do + @moduledoc """ + The log message parameters. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * type: The message type. See {@link MessageType} + * message: The actual message. + """ + + typedstruct do + field(:type, GenLSP.Enumerations.MessageType.t(), enforce: true) + field(:message, String.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"type", :type} => GenLSP.Enumerations.MessageType.schematic(), + {"message", :message} => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/log_trace_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/log_trace_params.ex new file mode 100644 index 000000000..0c2102dcb --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/log_trace_params.ex @@ -0,0 +1,27 @@ +# codegen: do not edit +defmodule GenLSP.Structures.LogTraceParams do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * message + * verbose + """ + + typedstruct do + field(:message, String.t(), enforce: true) + field(:verbose, String.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"message", :message} => str(), + optional({"verbose", :verbose}) => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/markdown_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/markdown_client_capabilities.ex new file mode 100644 index 000000000..52e8f0353 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/markdown_client_capabilities.ex @@ -0,0 +1,39 @@ +# codegen: do not edit +defmodule GenLSP.Structures.MarkdownClientCapabilities do + @moduledoc """ + Client capabilities specific to the used markdown parser. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * parser: The name of the parser. + * version: The version of the parser. + * allowed_tags: A list of HTML tags that the client allows / supports in + Markdown. + + @since 3.17.0 + """ + + typedstruct do + field(:parser, String.t(), enforce: true) + field(:version, String.t()) + field(:allowed_tags, list(String.t())) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"parser", :parser} => str(), + optional({"version", :version}) => str(), + optional({"allowedTags", :allowed_tags}) => list(str()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/markup_content.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/markup_content.ex new file mode 100644 index 000000000..1ad2e65fe --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/markup_content.ex @@ -0,0 +1,52 @@ +# codegen: do not edit +defmodule GenLSP.Structures.MarkupContent do + @moduledoc """ + A `MarkupContent` literal represents a string value which content is interpreted base on its + kind flag. Currently the protocol supports `plaintext` and `markdown` as markup kinds. + + If the kind is `markdown` then the value can contain fenced code blocks like in GitHub issues. + See https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting + + Here is an example how such a string can be constructed using JavaScript / TypeScript: + ```ts + let markdown: MarkdownContent = { + kind: MarkupKind.Markdown, + value: [ + '# Header', + 'Some text', + '```typescript', + 'someCode();', + '```' + ].join('\n') + }; + ``` + + *Please Note* that clients might sanitize the return markdown. A client could decide to + remove HTML from the markdown to avoid script execution. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * kind: The type of the Markup + * value: The content itself + """ + + typedstruct do + field(:kind, GenLSP.Enumerations.MarkupKind.t(), enforce: true) + field(:value, String.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"kind", :kind} => GenLSP.Enumerations.MarkupKind.schematic(), + {"value", :value} => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/message_action_item.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/message_action_item.ex new file mode 100644 index 000000000..9efe898c0 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/message_action_item.ex @@ -0,0 +1,24 @@ +# codegen: do not edit +defmodule GenLSP.Structures.MessageActionItem do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * title: A short title like 'Retry', 'Open Log' etc. + """ + + typedstruct do + field(:title, String.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"title", :title} => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/moniker.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/moniker.ex new file mode 100644 index 000000000..7ba2352d4 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/moniker.ex @@ -0,0 +1,40 @@ +# codegen: do not edit +defmodule GenLSP.Structures.Moniker do + @moduledoc """ + Moniker definition to match LSIF 0.5 moniker definition. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * scheme: The scheme of the moniker. For example tsc or .Net + * identifier: The identifier of the moniker. The value is opaque in LSIF however + schema owners are allowed to define the structure if they want. + * unique: The scope in which the moniker is unique + * kind: The moniker kind if known. + """ + + typedstruct do + field(:scheme, String.t(), enforce: true) + field(:identifier, String.t(), enforce: true) + field(:unique, GenLSP.Enumerations.UniquenessLevel.t(), enforce: true) + field(:kind, GenLSP.Enumerations.MonikerKind.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"scheme", :scheme} => str(), + {"identifier", :identifier} => str(), + {"unique", :unique} => GenLSP.Enumerations.UniquenessLevel.schematic(), + optional({"kind", :kind}) => GenLSP.Enumerations.MonikerKind.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/moniker_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/moniker_client_capabilities.ex new file mode 100644 index 000000000..b0e2145c0 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/moniker_client_capabilities.ex @@ -0,0 +1,32 @@ +# codegen: do not edit +defmodule GenLSP.Structures.MonikerClientCapabilities do + @moduledoc """ + Client capabilities specific to the moniker request. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether moniker supports dynamic registration. If this is set to `true` + the client supports the new `MonikerRegistrationOptions` return value + for the corresponding server capability as well. + """ + + typedstruct do + field(:dynamic_registration, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/moniker_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/moniker_options.ex new file mode 100644 index 000000000..269bbf553 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/moniker_options.ex @@ -0,0 +1,24 @@ +# codegen: do not edit +defmodule GenLSP.Structures.MonikerOptions do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_progress + """ + + typedstruct do + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/moniker_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/moniker_params.ex new file mode 100644 index 000000000..103226c23 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/moniker_params.ex @@ -0,0 +1,35 @@ +# codegen: do not edit +defmodule GenLSP.Structures.MonikerParams do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_token: An optional token that a server can use to report work done progress. + * partial_result_token: An optional token that a server can use to report partial results (e.g. streaming) to + the client. + * text_document: The text document. + * position: The position inside the text document. + """ + + typedstruct do + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:partial_result_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:position, GenLSP.Structures.Position.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + optional({"partialResultToken", :partial_result_token}) => + GenLSP.TypeAlias.ProgressToken.schematic(), + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + {"position", :position} => GenLSP.Structures.Position.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/moniker_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/moniker_registration_options.ex new file mode 100644 index 000000000..2c0b4f5a9 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/moniker_registration_options.ex @@ -0,0 +1,26 @@ +# codegen: do not edit +defmodule GenLSP.Structures.MonikerRegistrationOptions do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + """ + + typedstruct do + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_cell.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_cell.ex new file mode 100644 index 000000000..6a3aae97b --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_cell.ex @@ -0,0 +1,48 @@ +# codegen: do not edit +defmodule GenLSP.Structures.NotebookCell do + @moduledoc """ + A notebook cell. + + A cell's document URI must be unique across ALL notebook + cells and can therefore be used to uniquely identify a + notebook cell or the cell's text document. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * kind: The cell's kind + * document: The URI of the cell's text document + content. + * metadata: Additional metadata stored with the cell. + + Note: should always be an object literal (e.g. LSPObject) + * execution_summary: Additional execution summary information + if supported by the client. + """ + + typedstruct do + field(:kind, GenLSP.Enumerations.NotebookCellKind.t(), enforce: true) + field(:document, GenLSP.BaseTypes.document_uri(), enforce: true) + field(:metadata, GenLSP.TypeAlias.LSPObject.t()) + field(:execution_summary, GenLSP.Structures.ExecutionSummary.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"kind", :kind} => GenLSP.Enumerations.NotebookCellKind.schematic(), + {"document", :document} => str(), + optional({"metadata", :metadata}) => GenLSP.TypeAlias.LSPObject.schematic(), + optional({"executionSummary", :execution_summary}) => + GenLSP.Structures.ExecutionSummary.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_cell_array_change.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_cell_array_change.ex new file mode 100644 index 000000000..6ca2b6db7 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_cell_array_change.ex @@ -0,0 +1,37 @@ +# codegen: do not edit +defmodule GenLSP.Structures.NotebookCellArrayChange do + @moduledoc """ + A change describing how to move a `NotebookCell` + array from state S to S'. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * start: The start oftest of the cell that changed. + * delete_count: The deleted cells + * cells: The new cells, if any + """ + + typedstruct do + field(:start, GenLSP.BaseTypes.uinteger(), enforce: true) + field(:delete_count, GenLSP.BaseTypes.uinteger(), enforce: true) + field(:cells, list(GenLSP.Structures.NotebookCell.t())) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"start", :start} => int(), + {"deleteCount", :delete_count} => int(), + optional({"cells", :cells}) => list(GenLSP.Structures.NotebookCell.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_cell_text_document_filter.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_cell_text_document_filter.ex new file mode 100644 index 000000000..2501ad434 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_cell_text_document_filter.ex @@ -0,0 +1,41 @@ +# codegen: do not edit +defmodule GenLSP.Structures.NotebookCellTextDocumentFilter do + @moduledoc """ + A notebook cell text document filter denotes a cell text + document by different properties. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * notebook: A filter that matches against the notebook + containing the notebook cell. If a string + value is provided it matches against the + notebook type. '*' matches every notebook. + * language: A language id like `python`. + + Will be matched against the language id of the + notebook cell document. '*' matches every language. + """ + + typedstruct do + field(:notebook, String.t() | GenLSP.TypeAlias.NotebookDocumentFilter.t(), enforce: true) + field(:language, String.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"notebook", :notebook} => + oneof([str(), GenLSP.TypeAlias.NotebookDocumentFilter.schematic()]), + optional({"language", :language}) => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_document.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_document.ex new file mode 100644 index 000000000..2b8d589cc --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_document.ex @@ -0,0 +1,46 @@ +# codegen: do not edit +defmodule GenLSP.Structures.NotebookDocument do + @moduledoc """ + A notebook document. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * uri: The notebook document's uri. + * notebook_type: The type of the notebook. + * version: The version number of this document (it will increase after each + change, including undo/redo). + * metadata: Additional metadata stored with the notebook + document. + + Note: should always be an object literal (e.g. LSPObject) + * cells: The cells of a notebook. + """ + + typedstruct do + field(:uri, GenLSP.BaseTypes.uri(), enforce: true) + field(:notebook_type, String.t(), enforce: true) + field(:version, integer(), enforce: true) + field(:metadata, GenLSP.TypeAlias.LSPObject.t()) + field(:cells, list(GenLSP.Structures.NotebookCell.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"uri", :uri} => str(), + {"notebookType", :notebook_type} => str(), + {"version", :version} => int(), + optional({"metadata", :metadata}) => GenLSP.TypeAlias.LSPObject.schematic(), + {"cells", :cells} => list(GenLSP.Structures.NotebookCell.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_document_change_event.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_document_change_event.ex new file mode 100644 index 000000000..f61a3e517 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_document_change_event.ex @@ -0,0 +1,55 @@ +# codegen: do not edit +defmodule GenLSP.Structures.NotebookDocumentChangeEvent do + @moduledoc """ + A change event for a notebook document. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * metadata: The changed meta data if any. + + Note: should always be an object literal (e.g. LSPObject) + * cells: Changes to cells + """ + + typedstruct do + field(:metadata, GenLSP.TypeAlias.LSPObject.t()) + field(:cells, map()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"metadata", :metadata}) => GenLSP.TypeAlias.LSPObject.schematic(), + optional({"cells", :cells}) => + map(%{ + optional({"structure", :structure}) => + map(%{ + {"array", :array} => GenLSP.Structures.NotebookCellArrayChange.schematic(), + optional({"didOpen", :did_open}) => + list(GenLSP.Structures.TextDocumentItem.schematic()), + optional({"didClose", :did_close}) => + list(GenLSP.Structures.TextDocumentIdentifier.schematic()) + }), + optional({"data", :data}) => list(GenLSP.Structures.NotebookCell.schematic()), + optional({"textContent", :text_content}) => + list( + map(%{ + {"document", :document} => + GenLSP.Structures.VersionedTextDocumentIdentifier.schematic(), + {"changes", :changes} => + list(GenLSP.TypeAlias.TextDocumentContentChangeEvent.schematic()) + }) + ) + }) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_document_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_document_client_capabilities.ex new file mode 100644 index 000000000..5955b7dd6 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_document_client_capabilities.ex @@ -0,0 +1,35 @@ +# codegen: do not edit +defmodule GenLSP.Structures.NotebookDocumentClientCapabilities do + @moduledoc """ + Capabilities specific to the notebook document support. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * synchronization: Capabilities specific to notebook document synchronization + + @since 3.17.0 + """ + + typedstruct do + field(:synchronization, GenLSP.Structures.NotebookDocumentSyncClientCapabilities.t(), + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"synchronization", :synchronization} => + GenLSP.Structures.NotebookDocumentSyncClientCapabilities.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_document_identifier.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_document_identifier.ex new file mode 100644 index 000000000..432968791 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_document_identifier.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.NotebookDocumentIdentifier do + @moduledoc """ + A literal to identify a notebook document in the client. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * uri: The notebook document's uri. + """ + + typedstruct do + field(:uri, GenLSP.BaseTypes.uri(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"uri", :uri} => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_document_sync_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_document_sync_client_capabilities.ex new file mode 100644 index 000000000..3ba647b26 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_document_sync_client_capabilities.ex @@ -0,0 +1,36 @@ +# codegen: do not edit +defmodule GenLSP.Structures.NotebookDocumentSyncClientCapabilities do + @moduledoc """ + Notebook specific client capabilities. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether implementation supports dynamic registration. If this is + set to `true` the client supports the new + `(TextDocumentRegistrationOptions & StaticRegistrationOptions)` + return value for the corresponding server capability as well. + * execution_summary_support: The client supports sending execution summary data per cell. + """ + + typedstruct do + field(:dynamic_registration, boolean()) + field(:execution_summary_support, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool(), + optional({"executionSummarySupport", :execution_summary_support}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_document_sync_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_document_sync_options.ex new file mode 100644 index 000000000..8126da849 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_document_sync_options.ex @@ -0,0 +1,68 @@ +# codegen: do not edit +defmodule GenLSP.Structures.NotebookDocumentSyncOptions do + @moduledoc """ + Options specific to a notebook plus its cells + to be synced to the server. + + If a selector provides a notebook document + filter but no cell selector all cells of a + matching notebook document will be synced. + + If a selector provides no notebook document + filter but only a cell selector all notebook + document that contain at least one matching + cell will be synced. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * notebook_selector: The notebooks to be synced + * save: Whether save notification should be forwarded to + the server. Will only be honored if mode === `notebook`. + """ + + typedstruct do + field(:notebook_selector, list(map() | map()), enforce: true) + field(:save, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"notebookSelector", :notebook_selector} => + list( + oneof([ + map(%{ + {"notebook", :notebook} => + oneof([str(), GenLSP.TypeAlias.NotebookDocumentFilter.schematic()]), + optional({"cells", :cells}) => + list( + map(%{ + {"language", :language} => str() + }) + ) + }), + map(%{ + optional({"notebook", :notebook}) => + oneof([str(), GenLSP.TypeAlias.NotebookDocumentFilter.schematic()]), + {"cells", :cells} => + list( + map(%{ + {"language", :language} => str() + }) + ) + }) + ]) + ), + optional({"save", :save}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_document_sync_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_document_sync_registration_options.ex new file mode 100644 index 000000000..92bbd033e --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/notebook_document_sync_registration_options.ex @@ -0,0 +1,62 @@ +# codegen: do not edit +defmodule GenLSP.Structures.NotebookDocumentSyncRegistrationOptions do + @moduledoc """ + Registration options specific to a notebook. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * id: The id used to register the request. The id can be used to deregister + the request again. See also Registration#id. + * notebook_selector: The notebooks to be synced + * save: Whether save notification should be forwarded to + the server. Will only be honored if mode === `notebook`. + """ + + typedstruct do + field(:id, String.t()) + field(:notebook_selector, list(map() | map()), enforce: true) + field(:save, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"id", :id}) => str(), + {"notebookSelector", :notebook_selector} => + list( + oneof([ + map(%{ + {"notebook", :notebook} => + oneof([str(), GenLSP.TypeAlias.NotebookDocumentFilter.schematic()]), + optional({"cells", :cells}) => + list( + map(%{ + {"language", :language} => str() + }) + ) + }), + map(%{ + optional({"notebook", :notebook}) => + oneof([str(), GenLSP.TypeAlias.NotebookDocumentFilter.schematic()]), + {"cells", :cells} => + list( + map(%{ + {"language", :language} => str() + }) + ) + }) + ]) + ), + optional({"save", :save}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/optional_versioned_text_document_identifier.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/optional_versioned_text_document_identifier.ex new file mode 100644 index 000000000..856c56fa9 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/optional_versioned_text_document_identifier.ex @@ -0,0 +1,35 @@ +# codegen: do not edit +defmodule GenLSP.Structures.OptionalVersionedTextDocumentIdentifier do + @moduledoc """ + A text document identifier to optionally denote a specific version of a text document. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * version: The version number of this document. If a versioned text document identifier + is sent from the server to the client and the file is not open in the editor + (the server has not received an open notification before) the server can send + `null` to indicate that the version is unknown and the content on disk is the + truth (as specified with document content ownership). + * uri: The text document's uri. + """ + + typedstruct do + field(:version, integer() | nil, enforce: true) + field(:uri, GenLSP.BaseTypes.document_uri(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"version", :version} => oneof([int(), nil]), + {"uri", :uri} => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/parameter_information.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/parameter_information.ex new file mode 100644 index 000000000..17fecc3e2 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/parameter_information.ex @@ -0,0 +1,44 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ParameterInformation do + @moduledoc """ + Represents a parameter of a callable-signature. A parameter can + have a label and a doc-comment. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * label: The label of this parameter information. + + Either a string or an inclusive start and exclusive end offsets within its containing + signature label. (see SignatureInformation.label). The offsets are based on a UTF-16 + string representation as `Position` and `Range` does. + + *Note*: a label of type string should be a substring of its containing signature label. + Its intended use case is to highlight the parameter label part in the `SignatureInformation.label`. + * documentation: The human-readable doc-comment of this parameter. Will be shown + in the UI but can be omitted. + """ + + typedstruct do + field(:label, String.t() | {GenLSP.BaseTypes.uinteger(), GenLSP.BaseTypes.uinteger()}, + enforce: true + ) + + field(:documentation, String.t() | GenLSP.Structures.MarkupContent.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"label", :label} => oneof([str(), tuple([int(), int()], from: :list)]), + optional({"documentation", :documentation}) => + oneof([str(), GenLSP.Structures.MarkupContent.schematic()]) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/partial_result_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/partial_result_params.ex new file mode 100644 index 000000000..610b505f5 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/partial_result_params.ex @@ -0,0 +1,26 @@ +# codegen: do not edit +defmodule GenLSP.Structures.PartialResultParams do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * partial_result_token: An optional token that a server can use to report partial results (e.g. streaming) to + the client. + """ + + typedstruct do + field(:partial_result_token, GenLSP.TypeAlias.ProgressToken.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"partialResultToken", :partial_result_token}) => + GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/position.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/position.ex new file mode 100644 index 000000000..d97dbc7af --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/position.ex @@ -0,0 +1,66 @@ +# codegen: do not edit +defmodule GenLSP.Structures.Position do + @moduledoc """ + Position in a text document expressed as zero-based line and character + offset. Prior to 3.17 the offsets were always based on a UTF-16 string + representation. So a string of the form `a𐐀b` the character offset of the + character `a` is 0, the character offset of `𐐀` is 1 and the character + offset of b is 3 since `𐐀` is represented using two code units in UTF-16. + Since 3.17 clients and servers can agree on a different string encoding + representation (e.g. UTF-8). The client announces it's supported encoding + via the client capability [`general.positionEncodings`](#clientCapabilities). + The value is an array of position encodings the client supports, with + decreasing preference (e.g. the encoding at index `0` is the most preferred + one). To stay backwards compatible the only mandatory encoding is UTF-16 + represented via the string `utf-16`. The server can pick one of the + encodings offered by the client and signals that encoding back to the + client via the initialize result's property + [`capabilities.positionEncoding`](#serverCapabilities). If the string value + `utf-16` is missing from the client's capability `general.positionEncodings` + servers can safely assume that the client supports UTF-16. If the server + omits the position encoding in its initialize result the encoding defaults + to the string value `utf-16`. Implementation considerations: since the + conversion from one encoding into another requires the content of the + file / line the conversion is best done where the file is read which is + usually on the server side. + + Positions are line end character agnostic. So you can not specify a position + that denotes `\r|\n` or `\n|` where `|` represents the character offset. + + @since 3.17.0 - support for negotiated position encoding. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * line: Line position in a document (zero-based). + + If a line number is greater than the number of lines in a document, it defaults back to the number of lines in the document. + If a line number is negative, it defaults to 0. + * character: Character offset on a line in a document (zero-based). + + The meaning of this offset is determined by the negotiated + `PositionEncodingKind`. + + If the character value is greater than the line length it defaults back to the + line length. + """ + + typedstruct do + field(:line, GenLSP.BaseTypes.uinteger(), enforce: true) + field(:character, GenLSP.BaseTypes.uinteger(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"line", :line} => int(), + {"character", :character} => int() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/prepare_rename_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/prepare_rename_params.ex new file mode 100644 index 000000000..fc840b921 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/prepare_rename_params.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.PrepareRenameParams do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_token: An optional token that a server can use to report work done progress. + * text_document: The text document. + * position: The position inside the text document. + """ + + typedstruct do + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:position, GenLSP.Structures.Position.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + {"position", :position} => GenLSP.Structures.Position.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/previous_result_id.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/previous_result_id.ex new file mode 100644 index 000000000..d4945b453 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/previous_result_id.ex @@ -0,0 +1,34 @@ +# codegen: do not edit +defmodule GenLSP.Structures.PreviousResultId do + @moduledoc """ + A previous result id in a workspace pull request. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * uri: The URI for which the client knowns a + result id. + * value: The value of the previous result id. + """ + + typedstruct do + field(:uri, GenLSP.BaseTypes.document_uri(), enforce: true) + field(:value, String.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"uri", :uri} => str(), + {"value", :value} => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/private_initialize_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/private_initialize_params.ex new file mode 100644 index 000000000..8ae33ca0a --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/private_initialize_params.ex @@ -0,0 +1,77 @@ +# codegen: do not edit +defmodule GenLSP.Structures.PrivateInitializeParams do + @moduledoc """ + The initialize parameters + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * process_id: The process Id of the parent process that started + the server. + + Is `null` if the process has not been started by another process. + If the parent process is not alive then the server should exit. + * client_info: Information about the client + + @since 3.15.0 + * locale: The locale the client is currently showing the user interface + in. This must not necessarily be the locale of the operating + system. + + Uses IETF language tags as the value's syntax + (See https://en.wikipedia.org/wiki/IETF_language_tag) + + @since 3.16.0 + * root_path: The rootPath of the workspace. Is null + if no folder is open. + + @deprecated in favour of rootUri. + * root_uri: The rootUri of the workspace. Is null if no + folder is open. If both `rootPath` and `rootUri` are set + `rootUri` wins. + + @deprecated in favour of workspaceFolders. + * capabilities: The capabilities provided by the client (editor or tool) + * initialization_options: User provided initialization options. + * trace: The initial trace setting. If omitted trace is disabled ('off'). + * work_done_token: An optional token that a server can use to report work done progress. + """ + + typedstruct do + field(:process_id, integer() | nil, enforce: true) + field(:client_info, map()) + field(:locale, String.t()) + field(:root_path, String.t() | nil) + field(:root_uri, GenLSP.BaseTypes.document_uri() | nil, enforce: true) + field(:capabilities, GenLSP.Structures.ClientCapabilities.t(), enforce: true) + field(:initialization_options, GenLSP.TypeAlias.LSPAny.t()) + field(:trace, GenLSP.Enumerations.TraceValues.t()) + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"processId", :process_id} => oneof([int(), nil]), + optional({"clientInfo", :client_info}) => + map(%{ + {"name", :name} => str(), + optional({"version", :version}) => str() + }), + optional({"locale", :locale}) => str(), + optional({"rootPath", :root_path}) => oneof([str(), nil]), + {"rootUri", :root_uri} => oneof([str(), nil]), + {"capabilities", :capabilities} => GenLSP.Structures.ClientCapabilities.schematic(), + optional({"initializationOptions", :initialization_options}) => + GenLSP.TypeAlias.LSPAny.schematic(), + optional({"trace", :trace}) => GenLSP.Enumerations.TraceValues.schematic(), + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/progress_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/progress_params.ex new file mode 100644 index 000000000..f13b0780d --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/progress_params.ex @@ -0,0 +1,27 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ProgressParams do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * token: The progress token provided by the client or server. + * value: The progress data. + """ + + typedstruct do + field(:token, GenLSP.TypeAlias.ProgressToken.t(), enforce: true) + field(:value, GenLSP.TypeAlias.LSPAny.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"token", :token} => GenLSP.TypeAlias.ProgressToken.schematic(), + {"value", :value} => GenLSP.TypeAlias.LSPAny.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/publish_diagnostics_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/publish_diagnostics_client_capabilities.ex new file mode 100644 index 000000000..0dab68e0a --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/publish_diagnostics_client_capabilities.ex @@ -0,0 +1,55 @@ +# codegen: do not edit +defmodule GenLSP.Structures.PublishDiagnosticsClientCapabilities do + @moduledoc """ + The publish diagnostic client capabilities. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * related_information: Whether the clients accepts diagnostics with related information. + * tag_support: Client supports the tag property to provide meta data about a diagnostic. + Clients supporting tags have to handle unknown tags gracefully. + + @since 3.15.0 + * version_support: Whether the client interprets the version property of the + `textDocument/publishDiagnostics` notification's parameter. + + @since 3.15.0 + * code_description_support: Client supports a codeDescription property + + @since 3.16.0 + * data_support: Whether code action supports the `data` property which is + preserved between a `textDocument/publishDiagnostics` and + `textDocument/codeAction` request. + + @since 3.16.0 + """ + + typedstruct do + field(:related_information, boolean()) + field(:tag_support, map()) + field(:version_support, boolean()) + field(:code_description_support, boolean()) + field(:data_support, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"relatedInformation", :related_information}) => bool(), + optional({"tagSupport", :tag_support}) => + map(%{ + {"valueSet", :value_set} => list(GenLSP.Enumerations.DiagnosticTag.schematic()) + }), + optional({"versionSupport", :version_support}) => bool(), + optional({"codeDescriptionSupport", :code_description_support}) => bool(), + optional({"dataSupport", :data_support}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/publish_diagnostics_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/publish_diagnostics_params.ex new file mode 100644 index 000000000..5c297e439 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/publish_diagnostics_params.ex @@ -0,0 +1,36 @@ +# codegen: do not edit +defmodule GenLSP.Structures.PublishDiagnosticsParams do + @moduledoc """ + The publish diagnostic notification's parameters. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * uri: The URI for which diagnostic information is reported. + * version: Optional the version number of the document the diagnostics are published for. + + @since 3.15.0 + * diagnostics: An array of diagnostic information items. + """ + + typedstruct do + field(:uri, GenLSP.BaseTypes.document_uri(), enforce: true) + field(:version, integer()) + field(:diagnostics, list(GenLSP.Structures.Diagnostic.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"uri", :uri} => str(), + optional({"version", :version}) => int(), + {"diagnostics", :diagnostics} => list(GenLSP.Structures.Diagnostic.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/range.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/range.ex new file mode 100644 index 000000000..30d145ef4 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/range.ex @@ -0,0 +1,41 @@ +# codegen: do not edit +defmodule GenLSP.Structures.Range do + @moduledoc """ + A range in a text document expressed as (zero-based) start and end positions. + + If you want to specify a range that contains a line including the line ending + character(s) then use an end position denoting the start of the next line. + For example: + ```ts + { + start: { line: 5, character: 23 } + end : { line 6, character : 0 } + } + ``` + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * start: The range's start position. + * end: The range's end position. + """ + + typedstruct do + field(:start, GenLSP.Structures.Position.t(), enforce: true) + field(:end, GenLSP.Structures.Position.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"start", :start} => GenLSP.Structures.Position.schematic(), + {"end", :end} => GenLSP.Structures.Position.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/reference_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/reference_client_capabilities.ex new file mode 100644 index 000000000..7dc7ae881 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/reference_client_capabilities.ex @@ -0,0 +1,28 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ReferenceClientCapabilities do + @moduledoc """ + Client Capabilities for a {@link ReferencesRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether references supports dynamic registration. + """ + + typedstruct do + field(:dynamic_registration, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/reference_context.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/reference_context.ex new file mode 100644 index 000000000..8e5040154 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/reference_context.ex @@ -0,0 +1,29 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ReferenceContext do + @moduledoc """ + Value-object that contains additional information when + requesting references. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * include_declaration: Include the declaration of the current symbol. + """ + + typedstruct do + field(:include_declaration, boolean(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"includeDeclaration", :include_declaration} => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/reference_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/reference_options.ex new file mode 100644 index 000000000..ebba5b27d --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/reference_options.ex @@ -0,0 +1,28 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ReferenceOptions do + @moduledoc """ + Reference options. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_progress + """ + + typedstruct do + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/reference_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/reference_params.ex new file mode 100644 index 000000000..b7c6a1c5f --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/reference_params.ex @@ -0,0 +1,42 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ReferenceParams do + @moduledoc """ + Parameters for a {@link ReferencesRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * context + * work_done_token: An optional token that a server can use to report work done progress. + * partial_result_token: An optional token that a server can use to report partial results (e.g. streaming) to + the client. + * text_document: The text document. + * position: The position inside the text document. + """ + + typedstruct do + field(:context, GenLSP.Structures.ReferenceContext.t(), enforce: true) + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:partial_result_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:position, GenLSP.Structures.Position.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"context", :context} => GenLSP.Structures.ReferenceContext.schematic(), + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + optional({"partialResultToken", :partial_result_token}) => + GenLSP.TypeAlias.ProgressToken.schematic(), + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + {"position", :position} => GenLSP.Structures.Position.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/reference_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/reference_registration_options.ex new file mode 100644 index 000000000..f3a2b062b --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/reference_registration_options.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ReferenceRegistrationOptions do + @moduledoc """ + Registration options for a {@link ReferencesRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + """ + + typedstruct do + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/registration.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/registration.ex new file mode 100644 index 000000000..0d6357110 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/registration.ex @@ -0,0 +1,35 @@ +# codegen: do not edit +defmodule GenLSP.Structures.Registration do + @moduledoc """ + General parameters to register for a notification or to register a provider. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * id: The id used to register the request. The id can be used to deregister + the request again. + * method: The method / capability to register for. + * register_options: Options necessary for the registration. + """ + + typedstruct do + field(:id, String.t(), enforce: true) + field(:method, String.t(), enforce: true) + field(:register_options, GenLSP.TypeAlias.LSPAny.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"id", :id} => str(), + {"method", :method} => str(), + optional({"registerOptions", :register_options}) => GenLSP.TypeAlias.LSPAny.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/registration_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/registration_params.ex new file mode 100644 index 000000000..efe8173e2 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/registration_params.ex @@ -0,0 +1,24 @@ +# codegen: do not edit +defmodule GenLSP.Structures.RegistrationParams do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * registrations + """ + + typedstruct do + field(:registrations, list(GenLSP.Structures.Registration.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"registrations", :registrations} => list(GenLSP.Structures.Registration.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/regular_expressions_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/regular_expressions_client_capabilities.ex new file mode 100644 index 000000000..f968d509c --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/regular_expressions_client_capabilities.ex @@ -0,0 +1,33 @@ +# codegen: do not edit +defmodule GenLSP.Structures.RegularExpressionsClientCapabilities do + @moduledoc """ + Client capabilities specific to regular expressions. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * engine: The engine's name. + * version: The engine's version. + """ + + typedstruct do + field(:engine, String.t(), enforce: true) + field(:version, String.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"engine", :engine} => str(), + optional({"version", :version}) => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/related_full_document_diagnostic_report.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/related_full_document_diagnostic_report.ex new file mode 100644 index 000000000..66bb97e21 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/related_full_document_diagnostic_report.ex @@ -0,0 +1,60 @@ +# codegen: do not edit +defmodule GenLSP.Structures.RelatedFullDocumentDiagnosticReport do + @moduledoc """ + A full diagnostic report with a set of related documents. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * related_documents: Diagnostics of related documents. This information is useful + in programming languages where code in a file A can generate + diagnostics in a file B which A depends on. An example of + such a language is C/C++ where marco definitions in a file + a.cpp and result in errors in a header file b.hpp. + + @since 3.17.0 + * kind: A full document diagnostic report. + * result_id: An optional result id. If provided it will + be sent on the next diagnostic request for the + same document. + * items: The actual items. + """ + + typedstruct do + field(:related_documents, %{ + GenLSP.BaseTypes.document_uri() => + GenLSP.Structures.FullDocumentDiagnosticReport.t() + | GenLSP.Structures.UnchangedDocumentDiagnosticReport.t() + }) + + field(:kind, String.t(), enforce: true) + field(:result_id, String.t()) + field(:items, list(GenLSP.Structures.Diagnostic.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"relatedDocuments", :related_documents}) => + map( + keys: str(), + values: + oneof([ + GenLSP.Structures.FullDocumentDiagnosticReport.schematic(), + GenLSP.Structures.UnchangedDocumentDiagnosticReport.schematic() + ]) + ), + {"kind", :kind} => "full", + optional({"resultId", :result_id}) => str(), + {"items", :items} => list(GenLSP.Structures.Diagnostic.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/related_unchanged_document_diagnostic_report.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/related_unchanged_document_diagnostic_report.ex new file mode 100644 index 000000000..ae663ed16 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/related_unchanged_document_diagnostic_report.ex @@ -0,0 +1,59 @@ +# codegen: do not edit +defmodule GenLSP.Structures.RelatedUnchangedDocumentDiagnosticReport do + @moduledoc """ + An unchanged diagnostic report with a set of related documents. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * related_documents: Diagnostics of related documents. This information is useful + in programming languages where code in a file A can generate + diagnostics in a file B which A depends on. An example of + such a language is C/C++ where marco definitions in a file + a.cpp and result in errors in a header file b.hpp. + + @since 3.17.0 + * kind: A document diagnostic report indicating + no changes to the last result. A server can + only return `unchanged` if result ids are + provided. + * result_id: A result id which will be sent on the next + diagnostic request for the same document. + """ + + typedstruct do + field(:related_documents, %{ + GenLSP.BaseTypes.document_uri() => + GenLSP.Structures.FullDocumentDiagnosticReport.t() + | GenLSP.Structures.UnchangedDocumentDiagnosticReport.t() + }) + + field(:kind, String.t(), enforce: true) + field(:result_id, String.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"relatedDocuments", :related_documents}) => + map( + keys: str(), + values: + oneof([ + GenLSP.Structures.FullDocumentDiagnosticReport.schematic(), + GenLSP.Structures.UnchangedDocumentDiagnosticReport.schematic() + ]) + ), + {"kind", :kind} => "unchanged", + {"resultId", :result_id} => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/relative_pattern.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/relative_pattern.ex new file mode 100644 index 000000000..6a8f596da --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/relative_pattern.ex @@ -0,0 +1,39 @@ +# codegen: do not edit +defmodule GenLSP.Structures.RelativePattern do + @moduledoc """ + A relative pattern is a helper to construct glob patterns that are matched + relatively to a base URI. The common value for a `baseUri` is a workspace + folder root, but it can be another absolute URI as well. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * base_uri: A workspace folder or a base URI to which this pattern will be matched + against relatively. + * pattern: The actual glob pattern; + """ + + typedstruct do + field(:base_uri, GenLSP.Structures.WorkspaceFolder.t() | GenLSP.BaseTypes.uri(), + enforce: true + ) + + field(:pattern, GenLSP.TypeAlias.Pattern.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"baseUri", :base_uri} => oneof([GenLSP.Structures.WorkspaceFolder.schematic(), str()]), + {"pattern", :pattern} => GenLSP.TypeAlias.Pattern.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/rename_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/rename_client_capabilities.ex new file mode 100644 index 000000000..7e2021274 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/rename_client_capabilities.ex @@ -0,0 +1,53 @@ +# codegen: do not edit +defmodule GenLSP.Structures.RenameClientCapabilities do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether rename supports dynamic registration. + * prepare_support: Client supports testing for validity of rename operations + before execution. + + @since 3.12.0 + * prepare_support_default_behavior: Client supports the default behavior result. + + The value indicates the default behavior used by the + client. + + @since 3.16.0 + * honors_change_annotations: Whether the client honors the change annotations in + text edits and resource operations returned via the + rename request's workspace edit by for example presenting + the workspace edit in the user interface and asking + for confirmation. + + @since 3.16.0 + """ + + typedstruct do + field(:dynamic_registration, boolean()) + field(:prepare_support, boolean()) + + field( + :prepare_support_default_behavior, + GenLSP.Enumerations.PrepareSupportDefaultBehavior.t() + ) + + field(:honors_change_annotations, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool(), + optional({"prepareSupport", :prepare_support}) => bool(), + optional({"prepareSupportDefaultBehavior", :prepare_support_default_behavior}) => + GenLSP.Enumerations.PrepareSupportDefaultBehavior.schematic(), + optional({"honorsChangeAnnotations", :honors_change_annotations}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/rename_file.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/rename_file.ex new file mode 100644 index 000000000..6ec30bfcc --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/rename_file.ex @@ -0,0 +1,43 @@ +# codegen: do not edit +defmodule GenLSP.Structures.RenameFile do + @moduledoc """ + Rename file operation + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * kind: A rename + * old_uri: The old (existing) location. + * new_uri: The new location. + * options: Rename options. + * annotation_id: An optional annotation identifier describing the operation. + + @since 3.16.0 + """ + + typedstruct do + field(:kind, String.t(), enforce: true) + field(:old_uri, GenLSP.BaseTypes.document_uri(), enforce: true) + field(:new_uri, GenLSP.BaseTypes.document_uri(), enforce: true) + field(:options, GenLSP.Structures.RenameFileOptions.t()) + field(:annotation_id, GenLSP.TypeAlias.ChangeAnnotationIdentifier.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"kind", :kind} => "rename", + {"oldUri", :old_uri} => str(), + {"newUri", :new_uri} => str(), + optional({"options", :options}) => GenLSP.Structures.RenameFileOptions.schematic(), + optional({"annotationId", :annotation_id}) => + GenLSP.TypeAlias.ChangeAnnotationIdentifier.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/rename_file_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/rename_file_options.ex new file mode 100644 index 000000000..d811c85d9 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/rename_file_options.ex @@ -0,0 +1,31 @@ +# codegen: do not edit +defmodule GenLSP.Structures.RenameFileOptions do + @moduledoc """ + Rename file options + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * overwrite: Overwrite target if existing. Overwrite wins over `ignoreIfExists` + * ignore_if_exists: Ignores if target exists. + """ + + typedstruct do + field(:overwrite, boolean()) + field(:ignore_if_exists, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"overwrite", :overwrite}) => bool(), + optional({"ignoreIfExists", :ignore_if_exists}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/rename_files_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/rename_files_params.ex new file mode 100644 index 000000000..7468f6b50 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/rename_files_params.ex @@ -0,0 +1,32 @@ +# codegen: do not edit +defmodule GenLSP.Structures.RenameFilesParams do + @moduledoc """ + The parameters sent in notifications/requests for user-initiated renames of + files. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * files: An array of all files/folders renamed in this operation. When a folder is renamed, only + the folder will be included, and not its children. + """ + + typedstruct do + field(:files, list(GenLSP.Structures.FileRename.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"files", :files} => list(GenLSP.Structures.FileRename.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/rename_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/rename_options.ex new file mode 100644 index 000000000..ac0f91813 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/rename_options.ex @@ -0,0 +1,33 @@ +# codegen: do not edit +defmodule GenLSP.Structures.RenameOptions do + @moduledoc """ + Provider options for a {@link RenameRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * prepare_provider: Renames should be checked and tested before being executed. + + @since version 3.12.0 + * work_done_progress + """ + + typedstruct do + field(:prepare_provider, boolean()) + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"prepareProvider", :prepare_provider}) => bool(), + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/rename_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/rename_params.ex new file mode 100644 index 000000000..ebc174b9c --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/rename_params.ex @@ -0,0 +1,39 @@ +# codegen: do not edit +defmodule GenLSP.Structures.RenameParams do + @moduledoc """ + The parameters of a {@link RenameRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * text_document: The document to rename. + * position: The position at which this request was sent. + * new_name: The new name of the symbol. If the given name is not valid the + request must return a {@link ResponseError} with an + appropriate message set. + * work_done_token: An optional token that a server can use to report work done progress. + """ + + typedstruct do + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:position, GenLSP.Structures.Position.t(), enforce: true) + field(:new_name, String.t(), enforce: true) + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + {"position", :position} => GenLSP.Structures.Position.schematic(), + {"newName", :new_name} => str(), + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/rename_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/rename_registration_options.ex new file mode 100644 index 000000000..347a176c3 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/rename_registration_options.ex @@ -0,0 +1,35 @@ +# codegen: do not edit +defmodule GenLSP.Structures.RenameRegistrationOptions do + @moduledoc """ + Registration options for a {@link RenameRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + * prepare_provider: Renames should be checked and tested before being executed. + + @since version 3.12.0 + """ + + typedstruct do + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + field(:prepare_provider, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]), + optional({"prepareProvider", :prepare_provider}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/resource_operation.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/resource_operation.ex new file mode 100644 index 000000000..b9f00f593 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/resource_operation.ex @@ -0,0 +1,34 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ResourceOperation do + @moduledoc """ + A generic resource operation. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * kind: The resource operation kind. + * annotation_id: An optional annotation identifier describing the operation. + + @since 3.16.0 + """ + + typedstruct do + field(:kind, String.t(), enforce: true) + field(:annotation_id, GenLSP.TypeAlias.ChangeAnnotationIdentifier.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"kind", :kind} => str(), + optional({"annotationId", :annotation_id}) => + GenLSP.TypeAlias.ChangeAnnotationIdentifier.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/save_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/save_options.ex new file mode 100644 index 000000000..edbf3dd2a --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/save_options.ex @@ -0,0 +1,28 @@ +# codegen: do not edit +defmodule GenLSP.Structures.SaveOptions do + @moduledoc """ + Save options. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * include_text: The client is supposed to include the content on save. + """ + + typedstruct do + field(:include_text, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"includeText", :include_text}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/selection_range.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/selection_range.ex new file mode 100644 index 000000000..d76102c92 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/selection_range.ex @@ -0,0 +1,32 @@ +# codegen: do not edit +defmodule GenLSP.Structures.SelectionRange do + @moduledoc """ + A selection range represents a part of a selection hierarchy. A selection range + may have a parent selection range that contains it. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * range: The {@link Range range} of this selection range. + * parent: The parent selection range containing this range. Therefore `parent.range` must contain `this.range`. + """ + + typedstruct do + field(:range, GenLSP.Structures.Range.t(), enforce: true) + field(:parent, GenLSP.Structures.SelectionRange.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"range", :range} => GenLSP.Structures.Range.schematic(), + optional({"parent", :parent}) => {__MODULE__, :schematic, []} + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/selection_range_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/selection_range_client_capabilities.ex new file mode 100644 index 000000000..53ec3c781 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/selection_range_client_capabilities.ex @@ -0,0 +1,26 @@ +# codegen: do not edit +defmodule GenLSP.Structures.SelectionRangeClientCapabilities do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether implementation supports dynamic registration for selection range providers. If this is set to `true` + the client supports the new `SelectionRangeRegistrationOptions` return value for the corresponding server + capability as well. + """ + + typedstruct do + field(:dynamic_registration, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/selection_range_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/selection_range_options.ex new file mode 100644 index 000000000..6c6698f07 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/selection_range_options.ex @@ -0,0 +1,24 @@ +# codegen: do not edit +defmodule GenLSP.Structures.SelectionRangeOptions do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_progress + """ + + typedstruct do + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/selection_range_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/selection_range_params.ex new file mode 100644 index 000000000..6897bdf4e --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/selection_range_params.ex @@ -0,0 +1,39 @@ +# codegen: do not edit +defmodule GenLSP.Structures.SelectionRangeParams do + @moduledoc """ + A parameter literal used in selection range requests. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * text_document: The text document. + * positions: The positions inside the text document. + * work_done_token: An optional token that a server can use to report work done progress. + * partial_result_token: An optional token that a server can use to report partial results (e.g. streaming) to + the client. + """ + + typedstruct do + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:positions, list(GenLSP.Structures.Position.t()), enforce: true) + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:partial_result_token, GenLSP.TypeAlias.ProgressToken.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + {"positions", :positions} => list(GenLSP.Structures.Position.schematic()), + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + optional({"partialResultToken", :partial_result_token}) => + GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/selection_range_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/selection_range_registration_options.ex new file mode 100644 index 000000000..e25e87ed3 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/selection_range_registration_options.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.SelectionRangeRegistrationOptions do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * id: The id used to register the request. The id can be used to deregister + the request again. See also Registration#id. + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + """ + + typedstruct do + field(:id, String.t()) + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"id", :id}) => str(), + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens.ex new file mode 100644 index 000000000..aa58af4d0 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens.ex @@ -0,0 +1,34 @@ +# codegen: do not edit +defmodule GenLSP.Structures.SemanticTokens do + @moduledoc """ + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * result_id: An optional result id. If provided and clients support delta updating + the client will include the result id in the next semantic token request. + A server can then instead of computing all semantic tokens again simply + send a delta. + * data: The actual tokens. + """ + + typedstruct do + field(:result_id, String.t()) + field(:data, list(GenLSP.BaseTypes.uinteger()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"resultId", :result_id}) => str(), + {"data", :data} => list(int()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_client_capabilities.ex new file mode 100644 index 000000000..837148d99 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_client_capabilities.ex @@ -0,0 +1,85 @@ +# codegen: do not edit +defmodule GenLSP.Structures.SemanticTokensClientCapabilities do + @moduledoc """ + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether implementation supports dynamic registration. If this is set to `true` + the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)` + return value for the corresponding server capability as well. + * requests: Which requests the client supports and might send to the server + depending on the server's capability. Please note that clients might not + show semantic tokens or degrade some of the user experience if a range + or full request is advertised by the client but not provided by the + server. If for example the client capability `requests.full` and + `request.range` are both set to true but the server only provides a + range provider the client might not render a minimap correctly or might + even decide to not show any semantic tokens at all. + * token_types: The token types that the client supports. + * token_modifiers: The token modifiers that the client supports. + * formats: The token formats the clients supports. + * overlapping_token_support: Whether the client supports tokens that can overlap each other. + * multiline_token_support: Whether the client supports tokens that can span multiple lines. + * server_cancel_support: Whether the client allows the server to actively cancel a + semantic token request, e.g. supports returning + LSPErrorCodes.ServerCancelled. If a server does the client + needs to retrigger the request. + + @since 3.17.0 + * augments_syntax_tokens: Whether the client uses semantic tokens to augment existing + syntax tokens. If set to `true` client side created syntax + tokens and semantic tokens are both used for colorization. If + set to `false` the client only uses the returned semantic tokens + for colorization. + + If the value is `undefined` then the client behavior is not + specified. + + @since 3.17.0 + """ + + typedstruct do + field(:dynamic_registration, boolean()) + field(:requests, map(), enforce: true) + field(:token_types, list(String.t()), enforce: true) + field(:token_modifiers, list(String.t()), enforce: true) + field(:formats, list(GenLSP.Enumerations.TokenFormat.t()), enforce: true) + field(:overlapping_token_support, boolean()) + field(:multiline_token_support, boolean()) + field(:server_cancel_support, boolean()) + field(:augments_syntax_tokens, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool(), + {"requests", :requests} => + map(%{ + optional({"range", :range}) => oneof([bool(), map(%{})]), + optional({"full", :full}) => + oneof([ + bool(), + map(%{ + optional({"delta", :delta}) => bool() + }) + ]) + }), + {"tokenTypes", :token_types} => list(str()), + {"tokenModifiers", :token_modifiers} => list(str()), + {"formats", :formats} => list(GenLSP.Enumerations.TokenFormat.schematic()), + optional({"overlappingTokenSupport", :overlapping_token_support}) => bool(), + optional({"multilineTokenSupport", :multiline_token_support}) => bool(), + optional({"serverCancelSupport", :server_cancel_support}) => bool(), + optional({"augmentsSyntaxTokens", :augments_syntax_tokens}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_delta.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_delta.ex new file mode 100644 index 000000000..b3c670c5d --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_delta.ex @@ -0,0 +1,31 @@ +# codegen: do not edit +defmodule GenLSP.Structures.SemanticTokensDelta do + @moduledoc """ + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * result_id + * edits: The semantic token edits to transform a previous result into a new result. + """ + + typedstruct do + field(:result_id, String.t()) + field(:edits, list(GenLSP.Structures.SemanticTokensEdit.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"resultId", :result_id}) => str(), + {"edits", :edits} => list(GenLSP.Structures.SemanticTokensEdit.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_delta_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_delta_params.ex new file mode 100644 index 000000000..dfff5dde8 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_delta_params.ex @@ -0,0 +1,40 @@ +# codegen: do not edit +defmodule GenLSP.Structures.SemanticTokensDeltaParams do + @moduledoc """ + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * text_document: The text document. + * previous_result_id: The result id of a previous response. The result Id can either point to a full response + or a delta response depending on what was received last. + * work_done_token: An optional token that a server can use to report work done progress. + * partial_result_token: An optional token that a server can use to report partial results (e.g. streaming) to + the client. + """ + + typedstruct do + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:previous_result_id, String.t(), enforce: true) + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:partial_result_token, GenLSP.TypeAlias.ProgressToken.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + {"previousResultId", :previous_result_id} => str(), + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + optional({"partialResultToken", :partial_result_token}) => + GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_delta_partial_result.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_delta_partial_result.ex new file mode 100644 index 000000000..28e28c403 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_delta_partial_result.ex @@ -0,0 +1,28 @@ +# codegen: do not edit +defmodule GenLSP.Structures.SemanticTokensDeltaPartialResult do + @moduledoc """ + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * edits + """ + + typedstruct do + field(:edits, list(GenLSP.Structures.SemanticTokensEdit.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"edits", :edits} => list(GenLSP.Structures.SemanticTokensEdit.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_edit.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_edit.ex new file mode 100644 index 000000000..d943c46b7 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_edit.ex @@ -0,0 +1,34 @@ +# codegen: do not edit +defmodule GenLSP.Structures.SemanticTokensEdit do + @moduledoc """ + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * start: The start offset of the edit. + * delete_count: The count of elements to remove. + * data: The elements to insert. + """ + + typedstruct do + field(:start, GenLSP.BaseTypes.uinteger(), enforce: true) + field(:delete_count, GenLSP.BaseTypes.uinteger(), enforce: true) + field(:data, list(GenLSP.BaseTypes.uinteger())) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"start", :start} => int(), + {"deleteCount", :delete_count} => int(), + optional({"data", :data}) => list(int()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_legend.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_legend.ex new file mode 100644 index 000000000..bc6ad8fb4 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_legend.ex @@ -0,0 +1,31 @@ +# codegen: do not edit +defmodule GenLSP.Structures.SemanticTokensLegend do + @moduledoc """ + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * token_types: The token types a server uses. + * token_modifiers: The token modifiers a server uses. + """ + + typedstruct do + field(:token_types, list(String.t()), enforce: true) + field(:token_modifiers, list(String.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"tokenTypes", :token_types} => list(str()), + {"tokenModifiers", :token_modifiers} => list(str()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_options.ex new file mode 100644 index 000000000..af07d0698 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_options.ex @@ -0,0 +1,44 @@ +# codegen: do not edit +defmodule GenLSP.Structures.SemanticTokensOptions do + @moduledoc """ + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * legend: The legend used by the server + * range: Server supports providing semantic tokens for a specific range + of a document. + * full: Server supports providing semantic tokens for a full document. + * work_done_progress + """ + + typedstruct do + field(:legend, GenLSP.Structures.SemanticTokensLegend.t(), enforce: true) + field(:range, boolean() | map()) + field(:full, boolean() | map()) + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"legend", :legend} => GenLSP.Structures.SemanticTokensLegend.schematic(), + optional({"range", :range}) => oneof([bool(), map(%{})]), + optional({"full", :full}) => + oneof([ + bool(), + map(%{ + optional({"delta", :delta}) => bool() + }) + ]), + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_params.ex new file mode 100644 index 000000000..2e22e7196 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_params.ex @@ -0,0 +1,36 @@ +# codegen: do not edit +defmodule GenLSP.Structures.SemanticTokensParams do + @moduledoc """ + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * text_document: The text document. + * work_done_token: An optional token that a server can use to report work done progress. + * partial_result_token: An optional token that a server can use to report partial results (e.g. streaming) to + the client. + """ + + typedstruct do + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:partial_result_token, GenLSP.TypeAlias.ProgressToken.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + optional({"partialResultToken", :partial_result_token}) => + GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_partial_result.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_partial_result.ex new file mode 100644 index 000000000..2876596f2 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_partial_result.ex @@ -0,0 +1,28 @@ +# codegen: do not edit +defmodule GenLSP.Structures.SemanticTokensPartialResult do + @moduledoc """ + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * data + """ + + typedstruct do + field(:data, list(GenLSP.BaseTypes.uinteger()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"data", :data} => list(int()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_range_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_range_params.ex new file mode 100644 index 000000000..373fcb557 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_range_params.ex @@ -0,0 +1,39 @@ +# codegen: do not edit +defmodule GenLSP.Structures.SemanticTokensRangeParams do + @moduledoc """ + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * text_document: The text document. + * range: The range the semantic tokens are requested for. + * work_done_token: An optional token that a server can use to report work done progress. + * partial_result_token: An optional token that a server can use to report partial results (e.g. streaming) to + the client. + """ + + typedstruct do + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:range, GenLSP.Structures.Range.t(), enforce: true) + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:partial_result_token, GenLSP.TypeAlias.ProgressToken.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + {"range", :range} => GenLSP.Structures.Range.schematic(), + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + optional({"partialResultToken", :partial_result_token}) => + GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_registration_options.ex new file mode 100644 index 000000000..b0d740e4e --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_registration_options.ex @@ -0,0 +1,50 @@ +# codegen: do not edit +defmodule GenLSP.Structures.SemanticTokensRegistrationOptions do + @moduledoc """ + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * id: The id used to register the request. The id can be used to deregister + the request again. See also Registration#id. + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + * legend: The legend used by the server + * range: Server supports providing semantic tokens for a specific range + of a document. + * full: Server supports providing semantic tokens for a full document. + """ + + typedstruct do + field(:id, String.t()) + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + field(:legend, GenLSP.Structures.SemanticTokensLegend.t(), enforce: true) + field(:range, boolean() | map()) + field(:full, boolean() | map()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"id", :id}) => str(), + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]), + {"legend", :legend} => GenLSP.Structures.SemanticTokensLegend.schematic(), + optional({"range", :range}) => oneof([bool(), map(%{})]), + optional({"full", :full}) => + oneof([ + bool(), + map(%{ + optional({"delta", :delta}) => bool() + }) + ]) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_workspace_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_workspace_client_capabilities.ex new file mode 100644 index 000000000..e18ffe69a --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/semantic_tokens_workspace_client_capabilities.ex @@ -0,0 +1,34 @@ +# codegen: do not edit +defmodule GenLSP.Structures.SemanticTokensWorkspaceClientCapabilities do + @moduledoc """ + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * refresh_support: Whether the client implementation supports a refresh request sent from + the server to the client. + + Note that this event is global and will force the client to refresh all + semantic tokens currently shown. It should be used with absolute care + and is useful for situation where a server for example detects a project + wide change that requires such a calculation. + """ + + typedstruct do + field(:refresh_support, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"refreshSupport", :refresh_support}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/server_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/server_capabilities.ex new file mode 100644 index 000000000..599760532 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/server_capabilities.ex @@ -0,0 +1,378 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ServerCapabilities do + @moduledoc """ + Defines the capabilities provided by a language + server. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * position_encoding: The position encoding the server picked from the encodings offered + by the client via the client capability `general.positionEncodings`. + + If the client didn't provide any position encodings the only valid + value that a server can return is 'utf-16'. + + If omitted it defaults to 'utf-16'. + + @since 3.17.0 + * text_document_sync: Defines how text documents are synced. Is either a detailed structure + defining each notification or for backwards compatibility the + TextDocumentSyncKind number. + * notebook_document_sync: Defines how notebook documents are synced. + + @since 3.17.0 + * completion_provider: The server provides completion support. + * hover_provider: The server provides hover support. + * signature_help_provider: The server provides signature help support. + * declaration_provider: The server provides Goto Declaration support. + * definition_provider: The server provides goto definition support. + * type_definition_provider: The server provides Goto Type Definition support. + * implementation_provider: The server provides Goto Implementation support. + * references_provider: The server provides find references support. + * document_highlight_provider: The server provides document highlight support. + * document_symbol_provider: The server provides document symbol support. + * code_action_provider: The server provides code actions. CodeActionOptions may only be + specified if the client states that it supports + `codeActionLiteralSupport` in its initial `initialize` request. + * code_lens_provider: The server provides code lens. + * document_link_provider: The server provides document link support. + * color_provider: The server provides color provider support. + * workspace_symbol_provider: The server provides workspace symbol support. + * document_formatting_provider: The server provides document formatting. + * document_range_formatting_provider: The server provides document range formatting. + * document_on_type_formatting_provider: The server provides document formatting on typing. + * rename_provider: The server provides rename support. RenameOptions may only be + specified if the client states that it supports + `prepareSupport` in its initial `initialize` request. + * folding_range_provider: The server provides folding provider support. + * selection_range_provider: The server provides selection range support. + * execute_command_provider: The server provides execute command support. + * call_hierarchy_provider: The server provides call hierarchy support. + + @since 3.16.0 + * linked_editing_range_provider: The server provides linked editing range support. + + @since 3.16.0 + * semantic_tokens_provider: The server provides semantic tokens support. + + @since 3.16.0 + * moniker_provider: The server provides moniker support. + + @since 3.16.0 + * type_hierarchy_provider: The server provides type hierarchy support. + + @since 3.17.0 + * inline_value_provider: The server provides inline values. + + @since 3.17.0 + * inlay_hint_provider: The server provides inlay hints. + + @since 3.17.0 + * diagnostic_provider: The server has support for pull model diagnostics. + + @since 3.17.0 + * workspace: Workspace specific server capabilities. + * experimental: Experimental server capabilities. + """ + + typedstruct do + field(:position_encoding, GenLSP.Enumerations.PositionEncodingKind.t()) + + field( + :text_document_sync, + GenLSP.Structures.TextDocumentSyncOptions.t() + | GenLSP.Enumerations.TextDocumentSyncKind.t() + ) + + field( + :notebook_document_sync, + GenLSP.Structures.NotebookDocumentSyncOptions.t() + | GenLSP.Structures.NotebookDocumentSyncRegistrationOptions.t() + ) + + field(:completion_provider, GenLSP.Structures.CompletionOptions.t()) + field(:hover_provider, boolean() | GenLSP.Structures.HoverOptions.t()) + field(:signature_help_provider, GenLSP.Structures.SignatureHelpOptions.t()) + + field( + :declaration_provider, + boolean() + | GenLSP.Structures.DeclarationOptions.t() + | GenLSP.Structures.DeclarationRegistrationOptions.t() + ) + + field(:definition_provider, boolean() | GenLSP.Structures.DefinitionOptions.t()) + + field( + :type_definition_provider, + boolean() + | GenLSP.Structures.TypeDefinitionOptions.t() + | GenLSP.Structures.TypeDefinitionRegistrationOptions.t() + ) + + field( + :implementation_provider, + boolean() + | GenLSP.Structures.ImplementationOptions.t() + | GenLSP.Structures.ImplementationRegistrationOptions.t() + ) + + field(:references_provider, boolean() | GenLSP.Structures.ReferenceOptions.t()) + + field( + :document_highlight_provider, + boolean() | GenLSP.Structures.DocumentHighlightOptions.t() + ) + + field(:document_symbol_provider, boolean() | GenLSP.Structures.DocumentSymbolOptions.t()) + field(:code_action_provider, boolean() | GenLSP.Structures.CodeActionOptions.t()) + field(:code_lens_provider, GenLSP.Structures.CodeLensOptions.t()) + field(:document_link_provider, GenLSP.Structures.DocumentLinkOptions.t()) + + field( + :color_provider, + boolean() + | GenLSP.Structures.DocumentColorOptions.t() + | GenLSP.Structures.DocumentColorRegistrationOptions.t() + ) + + field(:workspace_symbol_provider, boolean() | GenLSP.Structures.WorkspaceSymbolOptions.t()) + + field( + :document_formatting_provider, + boolean() | GenLSP.Structures.DocumentFormattingOptions.t() + ) + + field( + :document_range_formatting_provider, + boolean() | GenLSP.Structures.DocumentRangeFormattingOptions.t() + ) + + field( + :document_on_type_formatting_provider, + GenLSP.Structures.DocumentOnTypeFormattingOptions.t() + ) + + field(:rename_provider, boolean() | GenLSP.Structures.RenameOptions.t()) + + field( + :folding_range_provider, + boolean() + | GenLSP.Structures.FoldingRangeOptions.t() + | GenLSP.Structures.FoldingRangeRegistrationOptions.t() + ) + + field( + :selection_range_provider, + boolean() + | GenLSP.Structures.SelectionRangeOptions.t() + | GenLSP.Structures.SelectionRangeRegistrationOptions.t() + ) + + field(:execute_command_provider, GenLSP.Structures.ExecuteCommandOptions.t()) + + field( + :call_hierarchy_provider, + boolean() + | GenLSP.Structures.CallHierarchyOptions.t() + | GenLSP.Structures.CallHierarchyRegistrationOptions.t() + ) + + field( + :linked_editing_range_provider, + boolean() + | GenLSP.Structures.LinkedEditingRangeOptions.t() + | GenLSP.Structures.LinkedEditingRangeRegistrationOptions.t() + ) + + field( + :semantic_tokens_provider, + GenLSP.Structures.SemanticTokensOptions.t() + | GenLSP.Structures.SemanticTokensRegistrationOptions.t() + ) + + field( + :moniker_provider, + boolean() + | GenLSP.Structures.MonikerOptions.t() + | GenLSP.Structures.MonikerRegistrationOptions.t() + ) + + field( + :type_hierarchy_provider, + boolean() + | GenLSP.Structures.TypeHierarchyOptions.t() + | GenLSP.Structures.TypeHierarchyRegistrationOptions.t() + ) + + field( + :inline_value_provider, + boolean() + | GenLSP.Structures.InlineValueOptions.t() + | GenLSP.Structures.InlineValueRegistrationOptions.t() + ) + + field( + :inlay_hint_provider, + boolean() + | GenLSP.Structures.InlayHintOptions.t() + | GenLSP.Structures.InlayHintRegistrationOptions.t() + ) + + field( + :diagnostic_provider, + GenLSP.Structures.DiagnosticOptions.t() + | GenLSP.Structures.DiagnosticRegistrationOptions.t() + ) + + field(:workspace, map()) + field(:experimental, GenLSP.TypeAlias.LSPAny.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"positionEncoding", :position_encoding}) => + GenLSP.Enumerations.PositionEncodingKind.schematic(), + optional({"textDocumentSync", :text_document_sync}) => + oneof([ + GenLSP.Structures.TextDocumentSyncOptions.schematic(), + GenLSP.Enumerations.TextDocumentSyncKind.schematic() + ]), + optional({"notebookDocumentSync", :notebook_document_sync}) => + oneof([ + GenLSP.Structures.NotebookDocumentSyncOptions.schematic(), + GenLSP.Structures.NotebookDocumentSyncRegistrationOptions.schematic() + ]), + optional({"completionProvider", :completion_provider}) => + GenLSP.Structures.CompletionOptions.schematic(), + optional({"hoverProvider", :hover_provider}) => + oneof([bool(), GenLSP.Structures.HoverOptions.schematic()]), + optional({"signatureHelpProvider", :signature_help_provider}) => + GenLSP.Structures.SignatureHelpOptions.schematic(), + optional({"declarationProvider", :declaration_provider}) => + oneof([ + bool(), + GenLSP.Structures.DeclarationOptions.schematic(), + GenLSP.Structures.DeclarationRegistrationOptions.schematic() + ]), + optional({"definitionProvider", :definition_provider}) => + oneof([bool(), GenLSP.Structures.DefinitionOptions.schematic()]), + optional({"typeDefinitionProvider", :type_definition_provider}) => + oneof([ + bool(), + GenLSP.Structures.TypeDefinitionOptions.schematic(), + GenLSP.Structures.TypeDefinitionRegistrationOptions.schematic() + ]), + optional({"implementationProvider", :implementation_provider}) => + oneof([ + bool(), + GenLSP.Structures.ImplementationOptions.schematic(), + GenLSP.Structures.ImplementationRegistrationOptions.schematic() + ]), + optional({"referencesProvider", :references_provider}) => + oneof([bool(), GenLSP.Structures.ReferenceOptions.schematic()]), + optional({"documentHighlightProvider", :document_highlight_provider}) => + oneof([bool(), GenLSP.Structures.DocumentHighlightOptions.schematic()]), + optional({"documentSymbolProvider", :document_symbol_provider}) => + oneof([bool(), GenLSP.Structures.DocumentSymbolOptions.schematic()]), + optional({"codeActionProvider", :code_action_provider}) => + oneof([bool(), GenLSP.Structures.CodeActionOptions.schematic()]), + optional({"codeLensProvider", :code_lens_provider}) => + GenLSP.Structures.CodeLensOptions.schematic(), + optional({"documentLinkProvider", :document_link_provider}) => + GenLSP.Structures.DocumentLinkOptions.schematic(), + optional({"colorProvider", :color_provider}) => + oneof([ + bool(), + GenLSP.Structures.DocumentColorOptions.schematic(), + GenLSP.Structures.DocumentColorRegistrationOptions.schematic() + ]), + optional({"workspaceSymbolProvider", :workspace_symbol_provider}) => + oneof([bool(), GenLSP.Structures.WorkspaceSymbolOptions.schematic()]), + optional({"documentFormattingProvider", :document_formatting_provider}) => + oneof([bool(), GenLSP.Structures.DocumentFormattingOptions.schematic()]), + optional({"documentRangeFormattingProvider", :document_range_formatting_provider}) => + oneof([bool(), GenLSP.Structures.DocumentRangeFormattingOptions.schematic()]), + optional({"documentOnTypeFormattingProvider", :document_on_type_formatting_provider}) => + GenLSP.Structures.DocumentOnTypeFormattingOptions.schematic(), + optional({"renameProvider", :rename_provider}) => + oneof([bool(), GenLSP.Structures.RenameOptions.schematic()]), + optional({"foldingRangeProvider", :folding_range_provider}) => + oneof([ + bool(), + GenLSP.Structures.FoldingRangeOptions.schematic(), + GenLSP.Structures.FoldingRangeRegistrationOptions.schematic() + ]), + optional({"selectionRangeProvider", :selection_range_provider}) => + oneof([ + bool(), + GenLSP.Structures.SelectionRangeOptions.schematic(), + GenLSP.Structures.SelectionRangeRegistrationOptions.schematic() + ]), + optional({"executeCommandProvider", :execute_command_provider}) => + GenLSP.Structures.ExecuteCommandOptions.schematic(), + optional({"callHierarchyProvider", :call_hierarchy_provider}) => + oneof([ + bool(), + GenLSP.Structures.CallHierarchyOptions.schematic(), + GenLSP.Structures.CallHierarchyRegistrationOptions.schematic() + ]), + optional({"linkedEditingRangeProvider", :linked_editing_range_provider}) => + oneof([ + bool(), + GenLSP.Structures.LinkedEditingRangeOptions.schematic(), + GenLSP.Structures.LinkedEditingRangeRegistrationOptions.schematic() + ]), + optional({"semanticTokensProvider", :semantic_tokens_provider}) => + oneof([ + GenLSP.Structures.SemanticTokensOptions.schematic(), + GenLSP.Structures.SemanticTokensRegistrationOptions.schematic() + ]), + optional({"monikerProvider", :moniker_provider}) => + oneof([ + bool(), + GenLSP.Structures.MonikerOptions.schematic(), + GenLSP.Structures.MonikerRegistrationOptions.schematic() + ]), + optional({"typeHierarchyProvider", :type_hierarchy_provider}) => + oneof([ + bool(), + GenLSP.Structures.TypeHierarchyOptions.schematic(), + GenLSP.Structures.TypeHierarchyRegistrationOptions.schematic() + ]), + optional({"inlineValueProvider", :inline_value_provider}) => + oneof([ + bool(), + GenLSP.Structures.InlineValueOptions.schematic(), + GenLSP.Structures.InlineValueRegistrationOptions.schematic() + ]), + optional({"inlayHintProvider", :inlay_hint_provider}) => + oneof([ + bool(), + GenLSP.Structures.InlayHintOptions.schematic(), + GenLSP.Structures.InlayHintRegistrationOptions.schematic() + ]), + optional({"diagnosticProvider", :diagnostic_provider}) => + oneof([ + GenLSP.Structures.DiagnosticOptions.schematic(), + GenLSP.Structures.DiagnosticRegistrationOptions.schematic() + ]), + optional({"workspace", :workspace}) => + map(%{ + optional({"workspaceFolders", :workspace_folders}) => + GenLSP.Structures.WorkspaceFoldersServerCapabilities.schematic(), + optional({"fileOperations", :file_operations}) => + GenLSP.Structures.FileOperationOptions.schematic() + }), + optional({"experimental", :experimental}) => GenLSP.TypeAlias.LSPAny.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/set_trace_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/set_trace_params.ex new file mode 100644 index 000000000..48fbc41cc --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/set_trace_params.ex @@ -0,0 +1,24 @@ +# codegen: do not edit +defmodule GenLSP.Structures.SetTraceParams do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * value + """ + + typedstruct do + field(:value, GenLSP.Enumerations.TraceValues.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"value", :value} => GenLSP.Enumerations.TraceValues.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/show_document_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/show_document_client_capabilities.ex new file mode 100644 index 000000000..34bcf767b --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/show_document_client_capabilities.ex @@ -0,0 +1,31 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ShowDocumentClientCapabilities do + @moduledoc """ + Client capabilities for the showDocument request. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * support: The client has support for the showDocument + request. + """ + + typedstruct do + field(:support, boolean(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"support", :support} => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/show_document_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/show_document_params.ex new file mode 100644 index 000000000..02f13578e --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/show_document_params.ex @@ -0,0 +1,47 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ShowDocumentParams do + @moduledoc """ + Params to show a document. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * uri: The document uri to show. + * external: Indicates to show the resource in an external program. + To show for example `https://code.visualstudio.com/` + in the default WEB browser set `external` to `true`. + * take_focus: An optional property to indicate whether the editor + showing the document should take focus or not. + Clients might ignore this property if an external + program is started. + * selection: An optional selection range if the document is a text + document. Clients might ignore the property if an + external program is started or the file is not a text + file. + """ + + typedstruct do + field(:uri, GenLSP.BaseTypes.uri(), enforce: true) + field(:external, boolean()) + field(:take_focus, boolean()) + field(:selection, GenLSP.Structures.Range.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"uri", :uri} => str(), + optional({"external", :external}) => bool(), + optional({"takeFocus", :take_focus}) => bool(), + optional({"selection", :selection}) => GenLSP.Structures.Range.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/show_document_result.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/show_document_result.ex new file mode 100644 index 000000000..1912e9c50 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/show_document_result.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ShowDocumentResult do + @moduledoc """ + The result of a showDocument request. + + @since 3.16.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * success: A boolean indicating if the show was successful. + """ + + typedstruct do + field(:success, boolean(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"success", :success} => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/show_message_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/show_message_params.ex new file mode 100644 index 000000000..690ab7d92 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/show_message_params.ex @@ -0,0 +1,31 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ShowMessageParams do + @moduledoc """ + The parameters of a notification message. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * type: The message type. See {@link MessageType} + * message: The actual message. + """ + + typedstruct do + field(:type, GenLSP.Enumerations.MessageType.t(), enforce: true) + field(:message, String.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"type", :type} => GenLSP.Enumerations.MessageType.schematic(), + {"message", :message} => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/show_message_request_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/show_message_request_client_capabilities.ex new file mode 100644 index 000000000..21509e2b1 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/show_message_request_client_capabilities.ex @@ -0,0 +1,31 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ShowMessageRequestClientCapabilities do + @moduledoc """ + Show message request client capabilities + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * message_action_item: Capabilities specific to the `MessageActionItem` type. + """ + + typedstruct do + field(:message_action_item, map()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"messageActionItem", :message_action_item}) => + map(%{ + optional({"additionalPropertiesSupport", :additional_properties_support}) => bool() + }) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/show_message_request_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/show_message_request_params.ex new file mode 100644 index 000000000..121d38c54 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/show_message_request_params.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.ShowMessageRequestParams do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * type: The message type. See {@link MessageType} + * message: The actual message. + * actions: The message action items to present. + """ + + typedstruct do + field(:type, GenLSP.Enumerations.MessageType.t(), enforce: true) + field(:message, String.t(), enforce: true) + field(:actions, list(GenLSP.Structures.MessageActionItem.t())) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"type", :type} => GenLSP.Enumerations.MessageType.schematic(), + {"message", :message} => str(), + optional({"actions", :actions}) => list(GenLSP.Structures.MessageActionItem.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/signature_help.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/signature_help.ex new file mode 100644 index 000000000..8bb17169c --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/signature_help.ex @@ -0,0 +1,50 @@ +# codegen: do not edit +defmodule GenLSP.Structures.SignatureHelp do + @moduledoc """ + Signature help represents the signature of something + callable. There can be multiple signature but only one + active and only one active parameter. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * signatures: One or more signatures. + * active_signature: The active signature. If omitted or the value lies outside the + range of `signatures` the value defaults to zero or is ignored if + the `SignatureHelp` has no signatures. + + Whenever possible implementors should make an active decision about + the active signature and shouldn't rely on a default value. + + In future version of the protocol this property might become + mandatory to better express this. + * active_parameter: The active parameter of the active signature. If omitted or the value + lies outside the range of `signatures[activeSignature].parameters` + defaults to 0 if the active signature has parameters. If + the active signature has no parameters it is ignored. + In future version of the protocol this property might become + mandatory to better express the active parameter if the + active signature does have any. + """ + + typedstruct do + field(:signatures, list(GenLSP.Structures.SignatureInformation.t()), enforce: true) + field(:active_signature, GenLSP.BaseTypes.uinteger()) + field(:active_parameter, GenLSP.BaseTypes.uinteger()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"signatures", :signatures} => list(GenLSP.Structures.SignatureInformation.schematic()), + optional({"activeSignature", :active_signature}) => int(), + optional({"activeParameter", :active_parameter}) => int() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/signature_help_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/signature_help_client_capabilities.ex new file mode 100644 index 000000000..6801c6253 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/signature_help_client_capabilities.ex @@ -0,0 +1,49 @@ +# codegen: do not edit +defmodule GenLSP.Structures.SignatureHelpClientCapabilities do + @moduledoc """ + Client Capabilities for a {@link SignatureHelpRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether signature help supports dynamic registration. + * signature_information: The client supports the following `SignatureInformation` + specific properties. + * context_support: The client supports to send additional context information for a + `textDocument/signatureHelp` request. A client that opts into + contextSupport will also support the `retriggerCharacters` on + `SignatureHelpOptions`. + + @since 3.15.0 + """ + + typedstruct do + field(:dynamic_registration, boolean()) + field(:signature_information, map()) + field(:context_support, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool(), + optional({"signatureInformation", :signature_information}) => + map(%{ + optional({"documentationFormat", :documentation_format}) => + list(GenLSP.Enumerations.MarkupKind.schematic()), + optional({"parameterInformation", :parameter_information}) => + map(%{ + optional({"labelOffsetSupport", :label_offset_support}) => bool() + }), + optional({"activeParameterSupport", :active_parameter_support}) => bool() + }), + optional({"contextSupport", :context_support}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/signature_help_context.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/signature_help_context.ex new file mode 100644 index 000000000..ada4ca1d7 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/signature_help_context.ex @@ -0,0 +1,48 @@ +# codegen: do not edit +defmodule GenLSP.Structures.SignatureHelpContext do + @moduledoc """ + Additional information about the context in which a signature help request was triggered. + + @since 3.15.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * trigger_kind: Action that caused signature help to be triggered. + * trigger_character: Character that caused signature help to be triggered. + + This is undefined when `triggerKind !== SignatureHelpTriggerKind.TriggerCharacter` + * is_retrigger: `true` if signature help was already showing when it was triggered. + + Retriggers occurs when the signature help is already active and can be caused by actions such as + typing a trigger character, a cursor move, or document content changes. + * active_signature_help: The currently active `SignatureHelp`. + + The `activeSignatureHelp` has its `SignatureHelp.activeSignature` field updated based on + the user navigating through available signatures. + """ + + typedstruct do + field(:trigger_kind, GenLSP.Enumerations.SignatureHelpTriggerKind.t(), enforce: true) + field(:trigger_character, String.t()) + field(:is_retrigger, boolean(), enforce: true) + field(:active_signature_help, GenLSP.Structures.SignatureHelp.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"triggerKind", :trigger_kind} => GenLSP.Enumerations.SignatureHelpTriggerKind.schematic(), + optional({"triggerCharacter", :trigger_character}) => str(), + {"isRetrigger", :is_retrigger} => bool(), + optional({"activeSignatureHelp", :active_signature_help}) => + GenLSP.Structures.SignatureHelp.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/signature_help_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/signature_help_options.ex new file mode 100644 index 000000000..c6edf1382 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/signature_help_options.ex @@ -0,0 +1,39 @@ +# codegen: do not edit +defmodule GenLSP.Structures.SignatureHelpOptions do + @moduledoc """ + Server Capabilities for a {@link SignatureHelpRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * trigger_characters: List of characters that trigger signature help automatically. + * retrigger_characters: List of characters that re-trigger signature help. + + These trigger characters are only active when signature help is already showing. All trigger characters + are also counted as re-trigger characters. + + @since 3.15.0 + * work_done_progress + """ + + typedstruct do + field(:trigger_characters, list(String.t())) + field(:retrigger_characters, list(String.t())) + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"triggerCharacters", :trigger_characters}) => list(str()), + optional({"retriggerCharacters", :retrigger_characters}) => list(str()), + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/signature_help_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/signature_help_params.ex new file mode 100644 index 000000000..3cfb25049 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/signature_help_params.ex @@ -0,0 +1,40 @@ +# codegen: do not edit +defmodule GenLSP.Structures.SignatureHelpParams do + @moduledoc """ + Parameters for a {@link SignatureHelpRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * context: The signature help context. This is only available if the client specifies + to send this using the client capability `textDocument.signatureHelp.contextSupport === true` + + @since 3.15.0 + * work_done_token: An optional token that a server can use to report work done progress. + * text_document: The text document. + * position: The position inside the text document. + """ + + typedstruct do + field(:context, GenLSP.Structures.SignatureHelpContext.t()) + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:position, GenLSP.Structures.Position.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"context", :context}) => GenLSP.Structures.SignatureHelpContext.schematic(), + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + {"position", :position} => GenLSP.Structures.Position.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/signature_help_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/signature_help_registration_options.ex new file mode 100644 index 000000000..4f53e29d6 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/signature_help_registration_options.ex @@ -0,0 +1,41 @@ +# codegen: do not edit +defmodule GenLSP.Structures.SignatureHelpRegistrationOptions do + @moduledoc """ + Registration options for a {@link SignatureHelpRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + * trigger_characters: List of characters that trigger signature help automatically. + * retrigger_characters: List of characters that re-trigger signature help. + + These trigger characters are only active when signature help is already showing. All trigger characters + are also counted as re-trigger characters. + + @since 3.15.0 + """ + + typedstruct do + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + field(:trigger_characters, list(String.t())) + field(:retrigger_characters, list(String.t())) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]), + optional({"triggerCharacters", :trigger_characters}) => list(str()), + optional({"retriggerCharacters", :retrigger_characters}) => list(str()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/signature_information.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/signature_information.ex new file mode 100644 index 000000000..eb70be1c7 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/signature_information.ex @@ -0,0 +1,47 @@ +# codegen: do not edit +defmodule GenLSP.Structures.SignatureInformation do + @moduledoc """ + Represents the signature of something callable. A signature + can have a label, like a function-name, a doc-comment, and + a set of parameters. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * label: The label of this signature. Will be shown in + the UI. + * documentation: The human-readable doc-comment of this signature. Will be shown + in the UI but can be omitted. + * parameters: The parameters of this signature. + * active_parameter: The index of the active parameter. + + If provided, this is used in place of `SignatureHelp.activeParameter`. + + @since 3.16.0 + """ + + typedstruct do + field(:label, String.t(), enforce: true) + field(:documentation, String.t() | GenLSP.Structures.MarkupContent.t()) + field(:parameters, list(GenLSP.Structures.ParameterInformation.t())) + field(:active_parameter, GenLSP.BaseTypes.uinteger()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"label", :label} => str(), + optional({"documentation", :documentation}) => + oneof([str(), GenLSP.Structures.MarkupContent.schematic()]), + optional({"parameters", :parameters}) => + list(GenLSP.Structures.ParameterInformation.schematic()), + optional({"activeParameter", :active_parameter}) => int() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/static_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/static_registration_options.ex new file mode 100644 index 000000000..e91b972fe --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/static_registration_options.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.StaticRegistrationOptions do + @moduledoc """ + Static registration options to be returned in the initialize + request. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * id: The id used to register the request. The id can be used to deregister + the request again. See also Registration#id. + """ + + typedstruct do + field(:id, String.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"id", :id}) => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/symbol_information.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/symbol_information.ex new file mode 100644 index 000000000..dd020666c --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/symbol_information.ex @@ -0,0 +1,59 @@ +# codegen: do not edit +defmodule GenLSP.Structures.SymbolInformation do + @moduledoc """ + Represents information about programming constructs like variables, classes, + interfaces etc. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * deprecated: Indicates if this symbol is deprecated. + + @deprecated Use tags instead + * location: The location of this symbol. The location's range is used by a tool + to reveal the location in the editor. If the symbol is selected in the + tool the range's start information is used to position the cursor. So + the range usually spans more than the actual symbol's name and does + normally include things like visibility modifiers. + + The range doesn't have to denote a node range in the sense of an abstract + syntax tree. It can therefore not be used to re-construct a hierarchy of + the symbols. + * name: The name of this symbol. + * kind: The kind of this symbol. + * tags: Tags for this symbol. + + @since 3.16.0 + * container_name: The name of the symbol containing this symbol. This information is for + user interface purposes (e.g. to render a qualifier in the user interface + if necessary). It can't be used to re-infer a hierarchy for the document + symbols. + """ + + typedstruct do + field(:deprecated, boolean()) + field(:location, GenLSP.Structures.Location.t(), enforce: true) + field(:name, String.t(), enforce: true) + field(:kind, GenLSP.Enumerations.SymbolKind.t(), enforce: true) + field(:tags, list(GenLSP.Enumerations.SymbolTag.t())) + field(:container_name, String.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"deprecated", :deprecated}) => bool(), + {"location", :location} => GenLSP.Structures.Location.schematic(), + {"name", :name} => str(), + {"kind", :kind} => GenLSP.Enumerations.SymbolKind.schematic(), + optional({"tags", :tags}) => list(GenLSP.Enumerations.SymbolTag.schematic()), + optional({"containerName", :container_name}) => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_change_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_change_registration_options.ex new file mode 100644 index 000000000..f3442351b --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_change_registration_options.ex @@ -0,0 +1,33 @@ +# codegen: do not edit +defmodule GenLSP.Structures.TextDocumentChangeRegistrationOptions do + @moduledoc """ + Describe options to be used when registered for text document change events. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * sync_kind: How documents are synced to the server. + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + """ + + typedstruct do + field(:sync_kind, GenLSP.Enumerations.TextDocumentSyncKind.t(), enforce: true) + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"syncKind", :sync_kind} => GenLSP.Enumerations.TextDocumentSyncKind.schematic(), + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_client_capabilities.ex new file mode 100644 index 000000000..d4fb5016f --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_client_capabilities.ex @@ -0,0 +1,171 @@ +# codegen: do not edit +defmodule GenLSP.Structures.TextDocumentClientCapabilities do + @moduledoc """ + Text document specific client capabilities. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * synchronization: Defines which synchronization capabilities the client supports. + * completion: Capabilities specific to the `textDocument/completion` request. + * hover: Capabilities specific to the `textDocument/hover` request. + * signature_help: Capabilities specific to the `textDocument/signatureHelp` request. + * declaration: Capabilities specific to the `textDocument/declaration` request. + + @since 3.14.0 + * definition: Capabilities specific to the `textDocument/definition` request. + * type_definition: Capabilities specific to the `textDocument/typeDefinition` request. + + @since 3.6.0 + * implementation: Capabilities specific to the `textDocument/implementation` request. + + @since 3.6.0 + * references: Capabilities specific to the `textDocument/references` request. + * document_highlight: Capabilities specific to the `textDocument/documentHighlight` request. + * document_symbol: Capabilities specific to the `textDocument/documentSymbol` request. + * code_action: Capabilities specific to the `textDocument/codeAction` request. + * code_lens: Capabilities specific to the `textDocument/codeLens` request. + * document_link: Capabilities specific to the `textDocument/documentLink` request. + * color_provider: Capabilities specific to the `textDocument/documentColor` and the + `textDocument/colorPresentation` request. + + @since 3.6.0 + * formatting: Capabilities specific to the `textDocument/formatting` request. + * range_formatting: Capabilities specific to the `textDocument/rangeFormatting` request. + * on_type_formatting: Capabilities specific to the `textDocument/onTypeFormatting` request. + * rename: Capabilities specific to the `textDocument/rename` request. + * folding_range: Capabilities specific to the `textDocument/foldingRange` request. + + @since 3.10.0 + * selection_range: Capabilities specific to the `textDocument/selectionRange` request. + + @since 3.15.0 + * publish_diagnostics: Capabilities specific to the `textDocument/publishDiagnostics` notification. + * call_hierarchy: Capabilities specific to the various call hierarchy requests. + + @since 3.16.0 + * semantic_tokens: Capabilities specific to the various semantic token request. + + @since 3.16.0 + * linked_editing_range: Capabilities specific to the `textDocument/linkedEditingRange` request. + + @since 3.16.0 + * moniker: Client capabilities specific to the `textDocument/moniker` request. + + @since 3.16.0 + * type_hierarchy: Capabilities specific to the various type hierarchy requests. + + @since 3.17.0 + * inline_value: Capabilities specific to the `textDocument/inlineValue` request. + + @since 3.17.0 + * inlay_hint: Capabilities specific to the `textDocument/inlayHint` request. + + @since 3.17.0 + * diagnostic: Capabilities specific to the diagnostic pull model. + + @since 3.17.0 + """ + + typedstruct do + field(:synchronization, GenLSP.Structures.TextDocumentSyncClientCapabilities.t()) + field(:completion, GenLSP.Structures.CompletionClientCapabilities.t()) + field(:hover, GenLSP.Structures.HoverClientCapabilities.t()) + field(:signature_help, GenLSP.Structures.SignatureHelpClientCapabilities.t()) + field(:declaration, GenLSP.Structures.DeclarationClientCapabilities.t()) + field(:definition, GenLSP.Structures.DefinitionClientCapabilities.t()) + field(:type_definition, GenLSP.Structures.TypeDefinitionClientCapabilities.t()) + field(:implementation, GenLSP.Structures.ImplementationClientCapabilities.t()) + field(:references, GenLSP.Structures.ReferenceClientCapabilities.t()) + field(:document_highlight, GenLSP.Structures.DocumentHighlightClientCapabilities.t()) + field(:document_symbol, GenLSP.Structures.DocumentSymbolClientCapabilities.t()) + field(:code_action, GenLSP.Structures.CodeActionClientCapabilities.t()) + field(:code_lens, GenLSP.Structures.CodeLensClientCapabilities.t()) + field(:document_link, GenLSP.Structures.DocumentLinkClientCapabilities.t()) + field(:color_provider, GenLSP.Structures.DocumentColorClientCapabilities.t()) + field(:formatting, GenLSP.Structures.DocumentFormattingClientCapabilities.t()) + field(:range_formatting, GenLSP.Structures.DocumentRangeFormattingClientCapabilities.t()) + field(:on_type_formatting, GenLSP.Structures.DocumentOnTypeFormattingClientCapabilities.t()) + field(:rename, GenLSP.Structures.RenameClientCapabilities.t()) + field(:folding_range, GenLSP.Structures.FoldingRangeClientCapabilities.t()) + field(:selection_range, GenLSP.Structures.SelectionRangeClientCapabilities.t()) + field(:publish_diagnostics, GenLSP.Structures.PublishDiagnosticsClientCapabilities.t()) + field(:call_hierarchy, GenLSP.Structures.CallHierarchyClientCapabilities.t()) + field(:semantic_tokens, GenLSP.Structures.SemanticTokensClientCapabilities.t()) + field(:linked_editing_range, GenLSP.Structures.LinkedEditingRangeClientCapabilities.t()) + field(:moniker, GenLSP.Structures.MonikerClientCapabilities.t()) + field(:type_hierarchy, GenLSP.Structures.TypeHierarchyClientCapabilities.t()) + field(:inline_value, GenLSP.Structures.InlineValueClientCapabilities.t()) + field(:inlay_hint, GenLSP.Structures.InlayHintClientCapabilities.t()) + field(:diagnostic, GenLSP.Structures.DiagnosticClientCapabilities.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"synchronization", :synchronization}) => + GenLSP.Structures.TextDocumentSyncClientCapabilities.schematic(), + optional({"completion", :completion}) => + GenLSP.Structures.CompletionClientCapabilities.schematic(), + optional({"hover", :hover}) => GenLSP.Structures.HoverClientCapabilities.schematic(), + optional({"signatureHelp", :signature_help}) => + GenLSP.Structures.SignatureHelpClientCapabilities.schematic(), + optional({"declaration", :declaration}) => + GenLSP.Structures.DeclarationClientCapabilities.schematic(), + optional({"definition", :definition}) => + GenLSP.Structures.DefinitionClientCapabilities.schematic(), + optional({"typeDefinition", :type_definition}) => + GenLSP.Structures.TypeDefinitionClientCapabilities.schematic(), + optional({"implementation", :implementation}) => + GenLSP.Structures.ImplementationClientCapabilities.schematic(), + optional({"references", :references}) => + GenLSP.Structures.ReferenceClientCapabilities.schematic(), + optional({"documentHighlight", :document_highlight}) => + GenLSP.Structures.DocumentHighlightClientCapabilities.schematic(), + optional({"documentSymbol", :document_symbol}) => + GenLSP.Structures.DocumentSymbolClientCapabilities.schematic(), + optional({"codeAction", :code_action}) => + GenLSP.Structures.CodeActionClientCapabilities.schematic(), + optional({"codeLens", :code_lens}) => + GenLSP.Structures.CodeLensClientCapabilities.schematic(), + optional({"documentLink", :document_link}) => + GenLSP.Structures.DocumentLinkClientCapabilities.schematic(), + optional({"colorProvider", :color_provider}) => + GenLSP.Structures.DocumentColorClientCapabilities.schematic(), + optional({"formatting", :formatting}) => + GenLSP.Structures.DocumentFormattingClientCapabilities.schematic(), + optional({"rangeFormatting", :range_formatting}) => + GenLSP.Structures.DocumentRangeFormattingClientCapabilities.schematic(), + optional({"onTypeFormatting", :on_type_formatting}) => + GenLSP.Structures.DocumentOnTypeFormattingClientCapabilities.schematic(), + optional({"rename", :rename}) => GenLSP.Structures.RenameClientCapabilities.schematic(), + optional({"foldingRange", :folding_range}) => + GenLSP.Structures.FoldingRangeClientCapabilities.schematic(), + optional({"selectionRange", :selection_range}) => + GenLSP.Structures.SelectionRangeClientCapabilities.schematic(), + optional({"publishDiagnostics", :publish_diagnostics}) => + GenLSP.Structures.PublishDiagnosticsClientCapabilities.schematic(), + optional({"callHierarchy", :call_hierarchy}) => + GenLSP.Structures.CallHierarchyClientCapabilities.schematic(), + optional({"semanticTokens", :semantic_tokens}) => + GenLSP.Structures.SemanticTokensClientCapabilities.schematic(), + optional({"linkedEditingRange", :linked_editing_range}) => + GenLSP.Structures.LinkedEditingRangeClientCapabilities.schematic(), + optional({"moniker", :moniker}) => GenLSP.Structures.MonikerClientCapabilities.schematic(), + optional({"typeHierarchy", :type_hierarchy}) => + GenLSP.Structures.TypeHierarchyClientCapabilities.schematic(), + optional({"inlineValue", :inline_value}) => + GenLSP.Structures.InlineValueClientCapabilities.schematic(), + optional({"inlayHint", :inlay_hint}) => + GenLSP.Structures.InlayHintClientCapabilities.schematic(), + optional({"diagnostic", :diagnostic}) => + GenLSP.Structures.DiagnosticClientCapabilities.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_edit.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_edit.ex new file mode 100644 index 000000000..a2e13cf82 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_edit.ex @@ -0,0 +1,49 @@ +# codegen: do not edit +defmodule GenLSP.Structures.TextDocumentEdit do + @moduledoc """ + Describes textual changes on a text document. A TextDocumentEdit describes all changes + on a document version Si and after they are applied move the document to version Si+1. + So the creator of a TextDocumentEdit doesn't need to sort the array of edits or do any + kind of ordering. However the edits must be non overlapping. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * text_document: The text document to change. + * edits: The edits to be applied. + + @since 3.16.0 - support for AnnotatedTextEdit. This is guarded using a + client capability. + """ + + typedstruct do + field(:text_document, GenLSP.Structures.OptionalVersionedTextDocumentIdentifier.t(), + enforce: true + ) + + field(:edits, list(GenLSP.Structures.TextEdit.t() | GenLSP.Structures.AnnotatedTextEdit.t()), + enforce: true + ) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"textDocument", :text_document} => + GenLSP.Structures.OptionalVersionedTextDocumentIdentifier.schematic(), + {"edits", :edits} => + list( + oneof([ + GenLSP.Structures.TextEdit.schematic(), + GenLSP.Structures.AnnotatedTextEdit.schematic() + ]) + ) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_identifier.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_identifier.ex new file mode 100644 index 000000000..a8cce928c --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_identifier.ex @@ -0,0 +1,28 @@ +# codegen: do not edit +defmodule GenLSP.Structures.TextDocumentIdentifier do + @moduledoc """ + A literal to identify a text document in the client. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * uri: The text document's uri. + """ + + typedstruct do + field(:uri, GenLSP.BaseTypes.document_uri(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"uri", :uri} => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_item.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_item.ex new file mode 100644 index 000000000..8a1a6adf9 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_item.ex @@ -0,0 +1,39 @@ +# codegen: do not edit +defmodule GenLSP.Structures.TextDocumentItem do + @moduledoc """ + An item to transfer a text document from the client to the + server. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * uri: The text document's uri. + * language_id: The text document's language identifier. + * version: The version number of this document (it will increase after each + change, including undo/redo). + * text: The content of the opened text document. + """ + + typedstruct do + field(:uri, GenLSP.BaseTypes.document_uri(), enforce: true) + field(:language_id, String.t(), enforce: true) + field(:version, integer(), enforce: true) + field(:text, String.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"uri", :uri} => str(), + {"languageId", :language_id} => str(), + {"version", :version} => int(), + {"text", :text} => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_position_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_position_params.ex new file mode 100644 index 000000000..4d30ddfb3 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_position_params.ex @@ -0,0 +1,32 @@ +# codegen: do not edit +defmodule GenLSP.Structures.TextDocumentPositionParams do + @moduledoc """ + A parameter literal used in requests to pass a text document and a position inside that + document. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * text_document: The text document. + * position: The position inside the text document. + """ + + typedstruct do + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:position, GenLSP.Structures.Position.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + {"position", :position} => GenLSP.Structures.Position.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_registration_options.ex new file mode 100644 index 000000000..8bb455469 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_registration_options.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.TextDocumentRegistrationOptions do + @moduledoc """ + General text document registration options. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + """ + + typedstruct do + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_save_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_save_registration_options.ex new file mode 100644 index 000000000..095ac64d0 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_save_registration_options.ex @@ -0,0 +1,33 @@ +# codegen: do not edit +defmodule GenLSP.Structures.TextDocumentSaveRegistrationOptions do + @moduledoc """ + Save registration options. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + * include_text: The client is supposed to include the content on save. + """ + + typedstruct do + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + field(:include_text, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]), + optional({"includeText", :include_text}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_sync_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_sync_client_capabilities.ex new file mode 100644 index 000000000..5159d8c3c --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_sync_client_capabilities.ex @@ -0,0 +1,35 @@ +# codegen: do not edit +defmodule GenLSP.Structures.TextDocumentSyncClientCapabilities do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether text document synchronization supports dynamic registration. + * will_save: The client supports sending will save notifications. + * will_save_wait_until: The client supports sending a will save request and + waits for a response providing text edits which will + be applied to the document before it is saved. + * did_save: The client supports did save notifications. + """ + + typedstruct do + field(:dynamic_registration, boolean()) + field(:will_save, boolean()) + field(:will_save_wait_until, boolean()) + field(:did_save, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool(), + optional({"willSave", :will_save}) => bool(), + optional({"willSaveWaitUntil", :will_save_wait_until}) => bool(), + optional({"didSave", :did_save}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_sync_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_sync_options.ex new file mode 100644 index 000000000..3bfc2e20f --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/text_document_sync_options.ex @@ -0,0 +1,41 @@ +# codegen: do not edit +defmodule GenLSP.Structures.TextDocumentSyncOptions do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * open_close: Open and close notifications are sent to the server. If omitted open close notification should not + be sent. + * change: Change notifications are sent to the server. See TextDocumentSyncKind.None, TextDocumentSyncKind.Full + and TextDocumentSyncKind.Incremental. If omitted it defaults to TextDocumentSyncKind.None. + * will_save: If present will save notifications are sent to the server. If omitted the notification should not be + sent. + * will_save_wait_until: If present will save wait until requests are sent to the server. If omitted the request should not be + sent. + * save: If present save notifications are sent to the server. If omitted the notification should not be + sent. + """ + + typedstruct do + field(:open_close, boolean()) + field(:change, GenLSP.Enumerations.TextDocumentSyncKind.t()) + field(:will_save, boolean()) + field(:will_save_wait_until, boolean()) + field(:save, boolean() | GenLSP.Structures.SaveOptions.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"openClose", :open_close}) => bool(), + optional({"change", :change}) => GenLSP.Enumerations.TextDocumentSyncKind.schematic(), + optional({"willSave", :will_save}) => bool(), + optional({"willSaveWaitUntil", :will_save_wait_until}) => bool(), + optional({"save", :save}) => oneof([bool(), GenLSP.Structures.SaveOptions.schematic()]) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/text_edit.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/text_edit.ex new file mode 100644 index 000000000..077c8ec54 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/text_edit.ex @@ -0,0 +1,33 @@ +# codegen: do not edit +defmodule GenLSP.Structures.TextEdit do + @moduledoc """ + A text edit applicable to a text document. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * range: The range of the text document to be manipulated. To insert + text into a document create a range where start === end. + * new_text: The string to be inserted. For delete operations use an + empty string. + """ + + typedstruct do + field(:range, GenLSP.Structures.Range.t(), enforce: true) + field(:new_text, String.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"range", :range} => GenLSP.Structures.Range.schematic(), + {"newText", :new_text} => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/type_definition_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/type_definition_client_capabilities.ex new file mode 100644 index 000000000..a048045b9 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/type_definition_client_capabilities.ex @@ -0,0 +1,35 @@ +# codegen: do not edit +defmodule GenLSP.Structures.TypeDefinitionClientCapabilities do + @moduledoc """ + Since 3.6.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether implementation supports dynamic registration. If this is set to `true` + the client supports the new `TypeDefinitionRegistrationOptions` return value + for the corresponding server capability as well. + * link_support: The client supports additional metadata in the form of definition links. + + Since 3.14.0 + """ + + typedstruct do + field(:dynamic_registration, boolean()) + field(:link_support, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool(), + optional({"linkSupport", :link_support}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/type_definition_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/type_definition_options.ex new file mode 100644 index 000000000..2158aae5d --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/type_definition_options.ex @@ -0,0 +1,24 @@ +# codegen: do not edit +defmodule GenLSP.Structures.TypeDefinitionOptions do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_progress + """ + + typedstruct do + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/type_definition_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/type_definition_params.ex new file mode 100644 index 000000000..d8d787007 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/type_definition_params.ex @@ -0,0 +1,35 @@ +# codegen: do not edit +defmodule GenLSP.Structures.TypeDefinitionParams do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_token: An optional token that a server can use to report work done progress. + * partial_result_token: An optional token that a server can use to report partial results (e.g. streaming) to + the client. + * text_document: The text document. + * position: The position inside the text document. + """ + + typedstruct do + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:partial_result_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:position, GenLSP.Structures.Position.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + optional({"partialResultToken", :partial_result_token}) => + GenLSP.TypeAlias.ProgressToken.schematic(), + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + {"position", :position} => GenLSP.Structures.Position.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/type_definition_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/type_definition_registration_options.ex new file mode 100644 index 000000000..251f2299f --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/type_definition_registration_options.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.TypeDefinitionRegistrationOptions do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * id: The id used to register the request. The id can be used to deregister + the request again. See also Registration#id. + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + """ + + typedstruct do + field(:id, String.t()) + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"id", :id}) => str(), + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/type_hierarchy_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/type_hierarchy_client_capabilities.ex new file mode 100644 index 000000000..15227d0c0 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/type_hierarchy_client_capabilities.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.TypeHierarchyClientCapabilities do + @moduledoc """ + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Whether implementation supports dynamic registration. If this is set to `true` + the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)` + return value for the corresponding server capability as well. + """ + + typedstruct do + field(:dynamic_registration, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/type_hierarchy_item.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/type_hierarchy_item.ex new file mode 100644 index 000000000..45d30a143 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/type_hierarchy_item.ex @@ -0,0 +1,55 @@ +# codegen: do not edit +defmodule GenLSP.Structures.TypeHierarchyItem do + @moduledoc """ + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * name: The name of this item. + * kind: The kind of this item. + * tags: Tags for this item. + * detail: More detail for this item, e.g. the signature of a function. + * uri: The resource identifier of this item. + * range: The range enclosing this symbol not including leading/trailing whitespace + but everything else, e.g. comments and code. + * selection_range: The range that should be selected and revealed when this symbol is being + picked, e.g. the name of a function. Must be contained by the + {@link TypeHierarchyItem.range `range`}. + * data: A data entry field that is preserved between a type hierarchy prepare and + supertypes or subtypes requests. It could also be used to identify the + type hierarchy in the server, helping improve the performance on + resolving supertypes and subtypes. + """ + + typedstruct do + field(:name, String.t(), enforce: true) + field(:kind, GenLSP.Enumerations.SymbolKind.t(), enforce: true) + field(:tags, list(GenLSP.Enumerations.SymbolTag.t())) + field(:detail, String.t()) + field(:uri, GenLSP.BaseTypes.document_uri(), enforce: true) + field(:range, GenLSP.Structures.Range.t(), enforce: true) + field(:selection_range, GenLSP.Structures.Range.t(), enforce: true) + field(:data, GenLSP.TypeAlias.LSPAny.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"name", :name} => str(), + {"kind", :kind} => GenLSP.Enumerations.SymbolKind.schematic(), + optional({"tags", :tags}) => list(GenLSP.Enumerations.SymbolTag.schematic()), + optional({"detail", :detail}) => str(), + {"uri", :uri} => str(), + {"range", :range} => GenLSP.Structures.Range.schematic(), + {"selectionRange", :selection_range} => GenLSP.Structures.Range.schematic(), + optional({"data", :data}) => GenLSP.TypeAlias.LSPAny.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/type_hierarchy_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/type_hierarchy_options.ex new file mode 100644 index 000000000..ef407012f --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/type_hierarchy_options.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.TypeHierarchyOptions do + @moduledoc """ + Type hierarchy options used during static registration. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_progress + """ + + typedstruct do + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/type_hierarchy_prepare_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/type_hierarchy_prepare_params.ex new file mode 100644 index 000000000..a96ddbdd6 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/type_hierarchy_prepare_params.ex @@ -0,0 +1,36 @@ +# codegen: do not edit +defmodule GenLSP.Structures.TypeHierarchyPrepareParams do + @moduledoc """ + The parameter of a `textDocument/prepareTypeHierarchy` request. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_token: An optional token that a server can use to report work done progress. + * text_document: The text document. + * position: The position inside the text document. + """ + + typedstruct do + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:position, GenLSP.Structures.Position.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + {"position", :position} => GenLSP.Structures.Position.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/type_hierarchy_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/type_hierarchy_registration_options.ex new file mode 100644 index 000000000..3ab016fc2 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/type_hierarchy_registration_options.ex @@ -0,0 +1,36 @@ +# codegen: do not edit +defmodule GenLSP.Structures.TypeHierarchyRegistrationOptions do + @moduledoc """ + Type hierarchy options used during static or dynamic registration. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * id: The id used to register the request. The id can be used to deregister + the request again. See also Registration#id. + * document_selector: A document selector to identify the scope of the registration. If set to null + the document selector provided on the client side will be used. + """ + + typedstruct do + field(:id, String.t()) + field(:document_selector, GenLSP.TypeAlias.DocumentSelector.t() | nil, enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"id", :id}) => str(), + {"documentSelector", :document_selector} => + oneof([GenLSP.TypeAlias.DocumentSelector.schematic(), nil]) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/type_hierarchy_subtypes_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/type_hierarchy_subtypes_params.ex new file mode 100644 index 000000000..21f976cb9 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/type_hierarchy_subtypes_params.ex @@ -0,0 +1,38 @@ +# codegen: do not edit +defmodule GenLSP.Structures.TypeHierarchySubtypesParams do + @moduledoc """ + The parameter of a `typeHierarchy/subtypes` request. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * item + * work_done_token: An optional token that a server can use to report work done progress. + * partial_result_token: An optional token that a server can use to report partial results (e.g. streaming) to + the client. + """ + + typedstruct do + field(:item, GenLSP.Structures.TypeHierarchyItem.t(), enforce: true) + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:partial_result_token, GenLSP.TypeAlias.ProgressToken.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"item", :item} => GenLSP.Structures.TypeHierarchyItem.schematic(), + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + optional({"partialResultToken", :partial_result_token}) => + GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/type_hierarchy_supertypes_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/type_hierarchy_supertypes_params.ex new file mode 100644 index 000000000..bb3a4f8b2 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/type_hierarchy_supertypes_params.ex @@ -0,0 +1,38 @@ +# codegen: do not edit +defmodule GenLSP.Structures.TypeHierarchySupertypesParams do + @moduledoc """ + The parameter of a `typeHierarchy/supertypes` request. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * item + * work_done_token: An optional token that a server can use to report work done progress. + * partial_result_token: An optional token that a server can use to report partial results (e.g. streaming) to + the client. + """ + + typedstruct do + field(:item, GenLSP.Structures.TypeHierarchyItem.t(), enforce: true) + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:partial_result_token, GenLSP.TypeAlias.ProgressToken.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"item", :item} => GenLSP.Structures.TypeHierarchyItem.schematic(), + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + optional({"partialResultToken", :partial_result_token}) => + GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/unchanged_document_diagnostic_report.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/unchanged_document_diagnostic_report.ex new file mode 100644 index 000000000..67cd94833 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/unchanged_document_diagnostic_report.ex @@ -0,0 +1,38 @@ +# codegen: do not edit +defmodule GenLSP.Structures.UnchangedDocumentDiagnosticReport do + @moduledoc """ + A diagnostic report indicating that the last returned + report is still accurate. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * kind: A document diagnostic report indicating + no changes to the last result. A server can + only return `unchanged` if result ids are + provided. + * result_id: A result id which will be sent on the next + diagnostic request for the same document. + """ + + typedstruct do + field(:kind, String.t(), enforce: true) + field(:result_id, String.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"kind", :kind} => "unchanged", + {"resultId", :result_id} => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/unregistration.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/unregistration.ex new file mode 100644 index 000000000..76c7fa202 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/unregistration.ex @@ -0,0 +1,32 @@ +# codegen: do not edit +defmodule GenLSP.Structures.Unregistration do + @moduledoc """ + General parameters to unregister a request or notification. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * id: The id used to unregister the request or notification. Usually an id + provided during the register request. + * method: The method to unregister for. + """ + + typedstruct do + field(:id, String.t(), enforce: true) + field(:method, String.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"id", :id} => str(), + {"method", :method} => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/unregistration_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/unregistration_params.ex new file mode 100644 index 000000000..7e2b5d9a4 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/unregistration_params.ex @@ -0,0 +1,25 @@ +# codegen: do not edit +defmodule GenLSP.Structures.UnregistrationParams do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * unregisterations + """ + + typedstruct do + field(:unregisterations, list(GenLSP.Structures.Unregistration.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"unregisterations", :unregisterations} => + list(GenLSP.Structures.Unregistration.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/versioned_notebook_document_identifier.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/versioned_notebook_document_identifier.ex new file mode 100644 index 000000000..90bace710 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/versioned_notebook_document_identifier.ex @@ -0,0 +1,33 @@ +# codegen: do not edit +defmodule GenLSP.Structures.VersionedNotebookDocumentIdentifier do + @moduledoc """ + A versioned notebook document identifier. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * version: The version number of this notebook document. + * uri: The notebook document's uri. + """ + + typedstruct do + field(:version, integer(), enforce: true) + field(:uri, GenLSP.BaseTypes.uri(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"version", :version} => int(), + {"uri", :uri} => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/versioned_text_document_identifier.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/versioned_text_document_identifier.ex new file mode 100644 index 000000000..1c71db03d --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/versioned_text_document_identifier.ex @@ -0,0 +1,31 @@ +# codegen: do not edit +defmodule GenLSP.Structures.VersionedTextDocumentIdentifier do + @moduledoc """ + A text document identifier to denote a specific version of a text document. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * version: The version number of this document. + * uri: The text document's uri. + """ + + typedstruct do + field(:version, integer(), enforce: true) + field(:uri, GenLSP.BaseTypes.document_uri(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"version", :version} => int(), + {"uri", :uri} => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/will_save_text_document_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/will_save_text_document_params.ex new file mode 100644 index 000000000..dd75ae1ac --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/will_save_text_document_params.ex @@ -0,0 +1,31 @@ +# codegen: do not edit +defmodule GenLSP.Structures.WillSaveTextDocumentParams do + @moduledoc """ + The parameters sent in a will save text document notification. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * text_document: The document that will be saved. + * reason: The 'TextDocumentSaveReason'. + """ + + typedstruct do + field(:text_document, GenLSP.Structures.TextDocumentIdentifier.t(), enforce: true) + field(:reason, GenLSP.Enumerations.TextDocumentSaveReason.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"textDocument", :text_document} => GenLSP.Structures.TextDocumentIdentifier.schematic(), + {"reason", :reason} => GenLSP.Enumerations.TextDocumentSaveReason.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/window_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/window_client_capabilities.ex new file mode 100644 index 000000000..4fc4ef90a --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/window_client_capabilities.ex @@ -0,0 +1,44 @@ +# codegen: do not edit +defmodule GenLSP.Structures.WindowClientCapabilities do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_progress: It indicates whether the client supports server initiated + progress using the `window/workDoneProgress/create` request. + + The capability also controls Whether client supports handling + of progress notifications. If set servers are allowed to report a + `workDoneProgress` property in the request specific server + capabilities. + + @since 3.15.0 + * show_message: Capabilities specific to the showMessage request. + + @since 3.16.0 + * show_document: Capabilities specific to the showDocument request. + + @since 3.16.0 + """ + + typedstruct do + field(:work_done_progress, boolean()) + field(:show_message, GenLSP.Structures.ShowMessageRequestClientCapabilities.t()) + field(:show_document, GenLSP.Structures.ShowDocumentClientCapabilities.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneProgress", :work_done_progress}) => bool(), + optional({"showMessage", :show_message}) => + GenLSP.Structures.ShowMessageRequestClientCapabilities.schematic(), + optional({"showDocument", :show_document}) => + GenLSP.Structures.ShowDocumentClientCapabilities.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/work_done_progress_begin.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/work_done_progress_begin.ex new file mode 100644 index 000000000..9bc4f220c --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/work_done_progress_begin.ex @@ -0,0 +1,50 @@ +# codegen: do not edit +defmodule GenLSP.Structures.WorkDoneProgressBegin do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * kind + * title: Mandatory title of the progress operation. Used to briefly inform about + the kind of operation being performed. + + Examples: "Indexing" or "Linking dependencies". + * cancellable: Controls if a cancel button should show to allow the user to cancel the + long running operation. Clients that don't support cancellation are allowed + to ignore the setting. + * message: Optional, more detailed associated progress message. Contains + complementary information to the `title`. + + Examples: "3/25 files", "project/src/module2", "node_modules/some_dep". + If unset, the previous progress message (if any) is still valid. + * percentage: Optional progress percentage to display (value 100 is considered 100%). + If not provided infinite progress is assumed and clients are allowed + to ignore the `percentage` value in subsequent in report notifications. + + The value should be steadily rising. Clients are free to ignore values + that are not following this rule. The value range is [0, 100]. + """ + + typedstruct do + field(:kind, String.t(), enforce: true) + field(:title, String.t(), enforce: true) + field(:cancellable, boolean()) + field(:message, String.t()) + field(:percentage, GenLSP.BaseTypes.uinteger()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"kind", :kind} => "begin", + {"title", :title} => str(), + optional({"cancellable", :cancellable}) => bool(), + optional({"message", :message}) => str(), + optional({"percentage", :percentage}) => int() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/work_done_progress_cancel_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/work_done_progress_cancel_params.ex new file mode 100644 index 000000000..bd8134d2f --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/work_done_progress_cancel_params.ex @@ -0,0 +1,24 @@ +# codegen: do not edit +defmodule GenLSP.Structures.WorkDoneProgressCancelParams do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * token: The token to be used to report progress. + """ + + typedstruct do + field(:token, GenLSP.TypeAlias.ProgressToken.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"token", :token} => GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/work_done_progress_create_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/work_done_progress_create_params.ex new file mode 100644 index 000000000..80942d853 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/work_done_progress_create_params.ex @@ -0,0 +1,24 @@ +# codegen: do not edit +defmodule GenLSP.Structures.WorkDoneProgressCreateParams do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * token: The token to be used to report progress. + """ + + typedstruct do + field(:token, GenLSP.TypeAlias.ProgressToken.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"token", :token} => GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/work_done_progress_end.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/work_done_progress_end.ex new file mode 100644 index 000000000..2a1c6f5bc --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/work_done_progress_end.ex @@ -0,0 +1,28 @@ +# codegen: do not edit +defmodule GenLSP.Structures.WorkDoneProgressEnd do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * kind + * message: Optional, a final message indicating to for example indicate the outcome + of the operation. + """ + + typedstruct do + field(:kind, String.t(), enforce: true) + field(:message, String.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"kind", :kind} => "end", + optional({"message", :message}) => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/work_done_progress_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/work_done_progress_options.ex new file mode 100644 index 000000000..f475b01c9 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/work_done_progress_options.ex @@ -0,0 +1,24 @@ +# codegen: do not edit +defmodule GenLSP.Structures.WorkDoneProgressOptions do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_progress + """ + + typedstruct do + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/work_done_progress_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/work_done_progress_params.ex new file mode 100644 index 000000000..4d17c7a65 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/work_done_progress_params.ex @@ -0,0 +1,24 @@ +# codegen: do not edit +defmodule GenLSP.Structures.WorkDoneProgressParams do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * work_done_token: An optional token that a server can use to report work done progress. + """ + + typedstruct do + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/work_done_progress_report.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/work_done_progress_report.ex new file mode 100644 index 000000000..0971c899b --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/work_done_progress_report.ex @@ -0,0 +1,45 @@ +# codegen: do not edit +defmodule GenLSP.Structures.WorkDoneProgressReport do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * kind + * cancellable: Controls enablement state of a cancel button. + + Clients that don't support cancellation or don't support controlling the button's + enablement state are allowed to ignore the property. + * message: Optional, more detailed associated progress message. Contains + complementary information to the `title`. + + Examples: "3/25 files", "project/src/module2", "node_modules/some_dep". + If unset, the previous progress message (if any) is still valid. + * percentage: Optional progress percentage to display (value 100 is considered 100%). + If not provided infinite progress is assumed and clients are allowed + to ignore the `percentage` value in subsequent in report notifications. + + The value should be steadily rising. Clients are free to ignore values + that are not following this rule. The value range is [0, 100] + """ + + typedstruct do + field(:kind, String.t(), enforce: true) + field(:cancellable, boolean()) + field(:message, String.t()) + field(:percentage, GenLSP.BaseTypes.uinteger()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"kind", :kind} => "report", + optional({"cancellable", :cancellable}) => bool(), + optional({"message", :message}) => str(), + optional({"percentage", :percentage}) => int() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_client_capabilities.ex new file mode 100644 index 000000000..2f5a24adf --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_client_capabilities.ex @@ -0,0 +1,110 @@ +# codegen: do not edit +defmodule GenLSP.Structures.WorkspaceClientCapabilities do + @moduledoc """ + Workspace specific client capabilities. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * apply_edit: The client supports applying batch edits + to the workspace by supporting the request + 'workspace/applyEdit' + * workspace_edit: Capabilities specific to `WorkspaceEdit`s. + * did_change_configuration: Capabilities specific to the `workspace/didChangeConfiguration` notification. + * did_change_watched_files: Capabilities specific to the `workspace/didChangeWatchedFiles` notification. + * symbol: Capabilities specific to the `workspace/symbol` request. + * execute_command: Capabilities specific to the `workspace/executeCommand` request. + * workspace_folders: The client has support for workspace folders. + + @since 3.6.0 + * configuration: The client supports `workspace/configuration` requests. + + @since 3.6.0 + * semantic_tokens: Capabilities specific to the semantic token requests scoped to the + workspace. + + @since 3.16.0. + * code_lens: Capabilities specific to the code lens requests scoped to the + workspace. + + @since 3.16.0. + * file_operations: The client has support for file notifications/requests for user operations on files. + + Since 3.16.0 + * inline_value: Capabilities specific to the inline values requests scoped to the + workspace. + + @since 3.17.0. + * inlay_hint: Capabilities specific to the inlay hint requests scoped to the + workspace. + + @since 3.17.0. + * diagnostics: Capabilities specific to the diagnostic requests scoped to the + workspace. + + @since 3.17.0. + """ + + typedstruct do + field(:apply_edit, boolean()) + field(:workspace_edit, GenLSP.Structures.WorkspaceEditClientCapabilities.t()) + + field( + :did_change_configuration, + GenLSP.Structures.DidChangeConfigurationClientCapabilities.t() + ) + + field( + :did_change_watched_files, + GenLSP.Structures.DidChangeWatchedFilesClientCapabilities.t() + ) + + field(:symbol, GenLSP.Structures.WorkspaceSymbolClientCapabilities.t()) + field(:execute_command, GenLSP.Structures.ExecuteCommandClientCapabilities.t()) + field(:workspace_folders, boolean()) + field(:configuration, boolean()) + field(:semantic_tokens, GenLSP.Structures.SemanticTokensWorkspaceClientCapabilities.t()) + field(:code_lens, GenLSP.Structures.CodeLensWorkspaceClientCapabilities.t()) + field(:file_operations, GenLSP.Structures.FileOperationClientCapabilities.t()) + field(:inline_value, GenLSP.Structures.InlineValueWorkspaceClientCapabilities.t()) + field(:inlay_hint, GenLSP.Structures.InlayHintWorkspaceClientCapabilities.t()) + field(:diagnostics, GenLSP.Structures.DiagnosticWorkspaceClientCapabilities.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"applyEdit", :apply_edit}) => bool(), + optional({"workspaceEdit", :workspace_edit}) => + GenLSP.Structures.WorkspaceEditClientCapabilities.schematic(), + optional({"didChangeConfiguration", :did_change_configuration}) => + GenLSP.Structures.DidChangeConfigurationClientCapabilities.schematic(), + optional({"didChangeWatchedFiles", :did_change_watched_files}) => + GenLSP.Structures.DidChangeWatchedFilesClientCapabilities.schematic(), + optional({"symbol", :symbol}) => + GenLSP.Structures.WorkspaceSymbolClientCapabilities.schematic(), + optional({"executeCommand", :execute_command}) => + GenLSP.Structures.ExecuteCommandClientCapabilities.schematic(), + optional({"workspaceFolders", :workspace_folders}) => bool(), + optional({"configuration", :configuration}) => bool(), + optional({"semanticTokens", :semantic_tokens}) => + GenLSP.Structures.SemanticTokensWorkspaceClientCapabilities.schematic(), + optional({"codeLens", :code_lens}) => + GenLSP.Structures.CodeLensWorkspaceClientCapabilities.schematic(), + optional({"fileOperations", :file_operations}) => + GenLSP.Structures.FileOperationClientCapabilities.schematic(), + optional({"inlineValue", :inline_value}) => + GenLSP.Structures.InlineValueWorkspaceClientCapabilities.schematic(), + optional({"inlayHint", :inlay_hint}) => + GenLSP.Structures.InlayHintWorkspaceClientCapabilities.schematic(), + optional({"diagnostics", :diagnostics}) => + GenLSP.Structures.DiagnosticWorkspaceClientCapabilities.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_diagnostic_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_diagnostic_params.ex new file mode 100644 index 000000000..ca4b5612b --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_diagnostic_params.ex @@ -0,0 +1,43 @@ +# codegen: do not edit +defmodule GenLSP.Structures.WorkspaceDiagnosticParams do + @moduledoc """ + Parameters of the workspace diagnostic request. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * identifier: The additional identifier provided during registration. + * previous_result_ids: The currently known diagnostic reports with their + previous result ids. + * work_done_token: An optional token that a server can use to report work done progress. + * partial_result_token: An optional token that a server can use to report partial results (e.g. streaming) to + the client. + """ + + typedstruct do + field(:identifier, String.t()) + field(:previous_result_ids, list(GenLSP.Structures.PreviousResultId.t()), enforce: true) + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:partial_result_token, GenLSP.TypeAlias.ProgressToken.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"identifier", :identifier}) => str(), + {"previousResultIds", :previous_result_ids} => + list(GenLSP.Structures.PreviousResultId.schematic()), + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + optional({"partialResultToken", :partial_result_token}) => + GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_diagnostic_report.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_diagnostic_report.ex new file mode 100644 index 000000000..7af61c455 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_diagnostic_report.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.WorkspaceDiagnosticReport do + @moduledoc """ + A workspace diagnostic report. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * items + """ + + typedstruct do + field(:items, list(GenLSP.TypeAlias.WorkspaceDocumentDiagnosticReport.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"items", :items} => list(GenLSP.TypeAlias.WorkspaceDocumentDiagnosticReport.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_diagnostic_report_partial_result.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_diagnostic_report_partial_result.ex new file mode 100644 index 000000000..dce96de96 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_diagnostic_report_partial_result.ex @@ -0,0 +1,30 @@ +# codegen: do not edit +defmodule GenLSP.Structures.WorkspaceDiagnosticReportPartialResult do + @moduledoc """ + A partial result for a workspace diagnostic report. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * items + """ + + typedstruct do + field(:items, list(GenLSP.TypeAlias.WorkspaceDocumentDiagnosticReport.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"items", :items} => list(GenLSP.TypeAlias.WorkspaceDocumentDiagnosticReport.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_edit.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_edit.ex new file mode 100644 index 000000000..bbf9fc855 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_edit.ex @@ -0,0 +1,84 @@ +# codegen: do not edit +defmodule GenLSP.Structures.WorkspaceEdit do + @moduledoc """ + A workspace edit represents changes to many resources managed in the workspace. The edit + should either provide `changes` or `documentChanges`. If documentChanges are present + they are preferred over `changes` if the client can handle versioned document edits. + + Since version 3.13.0 a workspace edit can contain resource operations as well. If resource + operations are present clients need to execute the operations in the order in which they + are provided. So a workspace edit for example can consist of the following two changes: + (1) a create file a.txt and (2) a text document edit which insert text into file a.txt. + + An invalid sequence (e.g. (1) delete file a.txt and (2) insert text into file a.txt) will + cause failure of the operation. How the client recovers from the failure is described by + the client capability: `workspace.workspaceEdit.failureHandling` + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * changes: Holds changes to existing resources. + * document_changes: Depending on the client capability `workspace.workspaceEdit.resourceOperations` document changes + are either an array of `TextDocumentEdit`s to express changes to n different text documents + where each text document edit addresses a specific version of a text document. Or it can contain + above `TextDocumentEdit`s mixed with create, rename and delete file / folder operations. + + Whether a client supports versioned document edits is expressed via + `workspace.workspaceEdit.documentChanges` client capability. + + If a client neither supports `documentChanges` nor `workspace.workspaceEdit.resourceOperations` then + only plain `TextEdit`s using the `changes` property are supported. + * change_annotations: A map of change annotations that can be referenced in `AnnotatedTextEdit`s or create, rename and + delete file / folder operations. + + Whether clients honor this property depends on the client capability `workspace.changeAnnotationSupport`. + + @since 3.16.0 + """ + + typedstruct do + field(:changes, %{GenLSP.BaseTypes.document_uri() => list(GenLSP.Structures.TextEdit.t())}) + + field( + :document_changes, + list( + GenLSP.Structures.TextDocumentEdit.t() + | GenLSP.Structures.CreateFile.t() + | GenLSP.Structures.RenameFile.t() + | GenLSP.Structures.DeleteFile.t() + ) + ) + + field(:change_annotations, %{ + GenLSP.TypeAlias.ChangeAnnotationIdentifier.t() => GenLSP.Structures.ChangeAnnotation.t() + }) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"changes", :changes}) => + map(keys: str(), values: list(GenLSP.Structures.TextEdit.schematic())), + optional({"documentChanges", :document_changes}) => + list( + oneof([ + GenLSP.Structures.TextDocumentEdit.schematic(), + GenLSP.Structures.CreateFile.schematic(), + GenLSP.Structures.RenameFile.schematic(), + GenLSP.Structures.DeleteFile.schematic() + ]) + ), + optional({"changeAnnotations", :change_annotations}) => + map( + keys: GenLSP.TypeAlias.ChangeAnnotationIdentifier.schematic(), + values: GenLSP.Structures.ChangeAnnotation.schematic() + ) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_edit_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_edit_client_capabilities.ex new file mode 100644 index 000000000..9d12de1c3 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_edit_client_capabilities.ex @@ -0,0 +1,56 @@ +# codegen: do not edit +defmodule GenLSP.Structures.WorkspaceEditClientCapabilities do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * document_changes: The client supports versioned document changes in `WorkspaceEdit`s + * resource_operations: The resource operations the client supports. Clients should at least + support 'create', 'rename' and 'delete' files and folders. + + @since 3.13.0 + * failure_handling: The failure handling strategy of a client if applying the workspace edit + fails. + + @since 3.13.0 + * normalizes_line_endings: Whether the client normalizes line endings to the client specific + setting. + If set to `true` the client will normalize line ending characters + in a workspace edit to the client-specified new line + character. + + @since 3.16.0 + * change_annotation_support: Whether the client in general supports change annotations on text edits, + create file, rename file and delete file changes. + + @since 3.16.0 + """ + + typedstruct do + field(:document_changes, boolean()) + field(:resource_operations, list(GenLSP.Enumerations.ResourceOperationKind.t())) + field(:failure_handling, GenLSP.Enumerations.FailureHandlingKind.t()) + field(:normalizes_line_endings, boolean()) + field(:change_annotation_support, map()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"documentChanges", :document_changes}) => bool(), + optional({"resourceOperations", :resource_operations}) => + list(GenLSP.Enumerations.ResourceOperationKind.schematic()), + optional({"failureHandling", :failure_handling}) => + GenLSP.Enumerations.FailureHandlingKind.schematic(), + optional({"normalizesLineEndings", :normalizes_line_endings}) => bool(), + optional({"changeAnnotationSupport", :change_annotation_support}) => + map(%{ + optional({"groupsOnLabel", :groups_on_label}) => bool() + }) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_folder.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_folder.ex new file mode 100644 index 000000000..4435160ce --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_folder.ex @@ -0,0 +1,32 @@ +# codegen: do not edit +defmodule GenLSP.Structures.WorkspaceFolder do + @moduledoc """ + A workspace folder inside a client. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * uri: The associated URI for this workspace folder. + * name: The name of the workspace folder. Used to refer to this + workspace folder in the user interface. + """ + + typedstruct do + field(:uri, GenLSP.BaseTypes.uri(), enforce: true) + field(:name, String.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"uri", :uri} => str(), + {"name", :name} => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_folders_change_event.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_folders_change_event.ex new file mode 100644 index 000000000..f8bd36023 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_folders_change_event.ex @@ -0,0 +1,31 @@ +# codegen: do not edit +defmodule GenLSP.Structures.WorkspaceFoldersChangeEvent do + @moduledoc """ + The workspace folder change event. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * added: The array of added workspace folders + * removed: The array of the removed workspace folders + """ + + typedstruct do + field(:added, list(GenLSP.Structures.WorkspaceFolder.t()), enforce: true) + field(:removed, list(GenLSP.Structures.WorkspaceFolder.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"added", :added} => list(GenLSP.Structures.WorkspaceFolder.schematic()), + {"removed", :removed} => list(GenLSP.Structures.WorkspaceFolder.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_folders_initialize_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_folders_initialize_params.ex new file mode 100644 index 000000000..e2e2ab435 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_folders_initialize_params.ex @@ -0,0 +1,31 @@ +# codegen: do not edit +defmodule GenLSP.Structures.WorkspaceFoldersInitializeParams do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * workspace_folders: The workspace folders configured in the client when the server starts. + + This property is only available if the client supports workspace folders. + It can be `null` if the client supports workspace folders but none are + configured. + + @since 3.6.0 + """ + + typedstruct do + field(:workspace_folders, list(GenLSP.Structures.WorkspaceFolder.t()) | nil) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"workspaceFolders", :workspace_folders}) => + oneof([list(GenLSP.Structures.WorkspaceFolder.schematic()), nil]) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_folders_server_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_folders_server_capabilities.ex new file mode 100644 index 000000000..77b45d36d --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_folders_server_capabilities.ex @@ -0,0 +1,33 @@ +# codegen: do not edit +defmodule GenLSP.Structures.WorkspaceFoldersServerCapabilities do + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * supported: The server has support for workspace folders + * change_notifications: Whether the server wants to receive workspace folder + change notifications. + + If a string is provided the string is treated as an ID + under which the notification is registered on the client + side. The ID can be used to unregister for these events + using the `client/unregisterCapability` request. + """ + + typedstruct do + field(:supported, boolean()) + field(:change_notifications, String.t() | boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"supported", :supported}) => bool(), + optional({"changeNotifications", :change_notifications}) => oneof([str(), bool()]) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_full_document_diagnostic_report.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_full_document_diagnostic_report.ex new file mode 100644 index 000000000..c2e7d86b2 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_full_document_diagnostic_report.ex @@ -0,0 +1,45 @@ +# codegen: do not edit +defmodule GenLSP.Structures.WorkspaceFullDocumentDiagnosticReport do + @moduledoc """ + A full document diagnostic report for a workspace diagnostic result. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * uri: The URI for which diagnostic information is reported. + * version: The version number for which the diagnostics are reported. + If the document is not marked as open `null` can be provided. + * kind: A full document diagnostic report. + * result_id: An optional result id. If provided it will + be sent on the next diagnostic request for the + same document. + * items: The actual items. + """ + + typedstruct do + field(:uri, GenLSP.BaseTypes.document_uri(), enforce: true) + field(:version, integer() | nil, enforce: true) + field(:kind, String.t(), enforce: true) + field(:result_id, String.t()) + field(:items, list(GenLSP.Structures.Diagnostic.t()), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"uri", :uri} => str(), + {"version", :version} => oneof([int(), nil]), + {"kind", :kind} => "full", + optional({"resultId", :result_id}) => str(), + {"items", :items} => list(GenLSP.Structures.Diagnostic.schematic()) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_symbol.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_symbol.ex new file mode 100644 index 000000000..006eabb28 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_symbol.ex @@ -0,0 +1,63 @@ +# codegen: do not edit +defmodule GenLSP.Structures.WorkspaceSymbol do + @moduledoc """ + A special workspace symbol that supports locations without a range. + + See also SymbolInformation. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * location: The location of the symbol. Whether a server is allowed to + return a location without a range depends on the client + capability `workspace.symbol.resolveSupport`. + + See SymbolInformation#location for more details. + * data: A data entry field that is preserved on a workspace symbol between a + workspace symbol request and a workspace symbol resolve request. + * name: The name of this symbol. + * kind: The kind of this symbol. + * tags: Tags for this symbol. + + @since 3.16.0 + * container_name: The name of the symbol containing this symbol. This information is for + user interface purposes (e.g. to render a qualifier in the user interface + if necessary). It can't be used to re-infer a hierarchy for the document + symbols. + """ + + typedstruct do + field(:location, GenLSP.Structures.Location.t() | map(), enforce: true) + field(:data, GenLSP.TypeAlias.LSPAny.t()) + field(:name, String.t(), enforce: true) + field(:kind, GenLSP.Enumerations.SymbolKind.t(), enforce: true) + field(:tags, list(GenLSP.Enumerations.SymbolTag.t())) + field(:container_name, String.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"location", :location} => + oneof([ + GenLSP.Structures.Location.schematic(), + map(%{ + {"uri", :uri} => str() + }) + ]), + optional({"data", :data}) => GenLSP.TypeAlias.LSPAny.schematic(), + {"name", :name} => str(), + {"kind", :kind} => GenLSP.Enumerations.SymbolKind.schematic(), + optional({"tags", :tags}) => list(GenLSP.Enumerations.SymbolTag.schematic()), + optional({"containerName", :container_name}) => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_symbol_client_capabilities.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_symbol_client_capabilities.ex new file mode 100644 index 000000000..a3ea70178 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_symbol_client_capabilities.ex @@ -0,0 +1,53 @@ +# codegen: do not edit +defmodule GenLSP.Structures.WorkspaceSymbolClientCapabilities do + @moduledoc """ + Client capabilities for a {@link WorkspaceSymbolRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * dynamic_registration: Symbol request supports dynamic registration. + * symbol_kind: Specific capabilities for the `SymbolKind` in the `workspace/symbol` request. + * tag_support: The client supports tags on `SymbolInformation`. + Clients supporting tags have to handle unknown tags gracefully. + + @since 3.16.0 + * resolve_support: The client support partial workspace symbols. The client will send the + request `workspaceSymbol/resolve` to the server to resolve additional + properties. + + @since 3.17.0 + """ + + typedstruct do + field(:dynamic_registration, boolean()) + field(:symbol_kind, map()) + field(:tag_support, map()) + field(:resolve_support, map()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"dynamicRegistration", :dynamic_registration}) => bool(), + optional({"symbolKind", :symbol_kind}) => + map(%{ + optional({"valueSet", :value_set}) => list(GenLSP.Enumerations.SymbolKind.schematic()) + }), + optional({"tagSupport", :tag_support}) => + map(%{ + {"valueSet", :value_set} => list(GenLSP.Enumerations.SymbolTag.schematic()) + }), + optional({"resolveSupport", :resolve_support}) => + map(%{ + {"properties", :properties} => list(str()) + }) + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_symbol_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_symbol_options.ex new file mode 100644 index 000000000..9dfa17604 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_symbol_options.ex @@ -0,0 +1,34 @@ +# codegen: do not edit +defmodule GenLSP.Structures.WorkspaceSymbolOptions do + @moduledoc """ + Server capabilities for a {@link WorkspaceSymbolRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * resolve_provider: The server provides support to resolve additional + information for a workspace symbol. + + @since 3.17.0 + * work_done_progress + """ + + typedstruct do + field(:resolve_provider, boolean()) + field(:work_done_progress, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"resolveProvider", :resolve_provider}) => bool(), + optional({"workDoneProgress", :work_done_progress}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_symbol_params.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_symbol_params.ex new file mode 100644 index 000000000..d53a56bb8 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_symbol_params.ex @@ -0,0 +1,37 @@ +# codegen: do not edit +defmodule GenLSP.Structures.WorkspaceSymbolParams do + @moduledoc """ + The parameters of a {@link WorkspaceSymbolRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * query: A query string to filter symbols by. Clients may send an empty + string here to request all symbols. + * work_done_token: An optional token that a server can use to report work done progress. + * partial_result_token: An optional token that a server can use to report partial results (e.g. streaming) to + the client. + """ + + typedstruct do + field(:query, String.t(), enforce: true) + field(:work_done_token, GenLSP.TypeAlias.ProgressToken.t()) + field(:partial_result_token, GenLSP.TypeAlias.ProgressToken.t()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"query", :query} => str(), + optional({"workDoneToken", :work_done_token}) => GenLSP.TypeAlias.ProgressToken.schematic(), + optional({"partialResultToken", :partial_result_token}) => + GenLSP.TypeAlias.ProgressToken.schematic() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_symbol_registration_options.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_symbol_registration_options.ex new file mode 100644 index 000000000..6e40a8533 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_symbol_registration_options.ex @@ -0,0 +1,31 @@ +# codegen: do not edit +defmodule GenLSP.Structures.WorkspaceSymbolRegistrationOptions do + @moduledoc """ + Registration options for a {@link WorkspaceSymbolRequest}. + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * resolve_provider: The server provides support to resolve additional + information for a workspace symbol. + + @since 3.17.0 + """ + + typedstruct do + field(:resolve_provider, boolean()) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + optional({"resolveProvider", :resolve_provider}) => bool() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_unchanged_document_diagnostic_report.ex b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_unchanged_document_diagnostic_report.ex new file mode 100644 index 000000000..d0537ead7 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/structures/workspace_unchanged_document_diagnostic_report.ex @@ -0,0 +1,44 @@ +# codegen: do not edit +defmodule GenLSP.Structures.WorkspaceUnchangedDocumentDiagnosticReport do + @moduledoc """ + An unchanged document diagnostic report for a workspace diagnostic result. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + use TypedStruct + + @doc """ + ## Fields + + * uri: The URI for which diagnostic information is reported. + * version: The version number for which the diagnostics are reported. + If the document is not marked as open `null` can be provided. + * kind: A document diagnostic report indicating + no changes to the last result. A server can + only return `unchanged` if result ids are + provided. + * result_id: A result id which will be sent on the next + diagnostic request for the same document. + """ + + typedstruct do + field(:uri, GenLSP.BaseTypes.document_uri(), enforce: true) + field(:version, integer() | nil, enforce: true) + field(:kind, String.t(), enforce: true) + field(:result_id, String.t(), enforce: true) + end + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + schema(__MODULE__, %{ + {"uri", :uri} => str(), + {"version", :version} => oneof([int(), nil]), + {"kind", :kind} => "unchanged", + {"resultId", :result_id} => str() + }) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/type_aliases/change_annotation_identifier.ex b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/change_annotation_identifier.ex new file mode 100644 index 000000000..943992ed6 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/change_annotation_identifier.ex @@ -0,0 +1,16 @@ +# codegen: do not edit +defmodule GenLSP.TypeAlias.ChangeAnnotationIdentifier do + @moduledoc """ + An identifier to refer to a change annotation stored with a workspace edit. + """ + + import SchematicV, warn: false + + @type t :: String.t() + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + str() + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/type_aliases/declaration.ex b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/declaration.ex new file mode 100644 index 000000000..ed1cf0820 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/declaration.ex @@ -0,0 +1,16 @@ +# codegen: do not edit +defmodule GenLSP.TypeAlias.Declaration do + @moduledoc """ + The declaration of a symbol representation as one or many {@link Location locations}. + """ + + import SchematicV, warn: false + + @type t :: GenLSP.Structures.Location.t() | list(GenLSP.Structures.Location.t()) + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([GenLSP.Structures.Location.schematic(), list(GenLSP.Structures.Location.schematic())]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/type_aliases/declaration_link.ex b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/declaration_link.ex new file mode 100644 index 000000000..cf49ac1c3 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/declaration_link.ex @@ -0,0 +1,22 @@ +# codegen: do not edit +defmodule GenLSP.TypeAlias.DeclarationLink do + @moduledoc """ + Information about where a symbol is declared. + + Provides additional metadata over normal {@link Location location} declarations, including the range of + the declaring symbol. + + Servers should prefer returning `DeclarationLink` over `Declaration` if supported + by the client. + """ + + import SchematicV, warn: false + + @type t :: GenLSP.Structures.LocationLink.t() + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + GenLSP.Structures.LocationLink.schematic() + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/type_aliases/definition.ex b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/definition.ex new file mode 100644 index 000000000..a8456510f --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/definition.ex @@ -0,0 +1,21 @@ +# codegen: do not edit +defmodule GenLSP.TypeAlias.Definition do + @moduledoc """ + The definition of a symbol represented as one or many {@link Location locations}. + For most programming languages there is only one location at which a symbol is + defined. + + Servers should prefer returning `DefinitionLink` over `Definition` if supported + by the client. + """ + + import SchematicV, warn: false + + @type t :: GenLSP.Structures.Location.t() | list(GenLSP.Structures.Location.t()) + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([GenLSP.Structures.Location.schematic(), list(GenLSP.Structures.Location.schematic())]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/type_aliases/definition_link.ex b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/definition_link.ex new file mode 100644 index 000000000..bd1e23407 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/definition_link.ex @@ -0,0 +1,19 @@ +# codegen: do not edit +defmodule GenLSP.TypeAlias.DefinitionLink do + @moduledoc """ + Information about where a symbol is defined. + + Provides additional metadata over normal {@link Location location} definitions, including the range of + the defining symbol + """ + + import SchematicV, warn: false + + @type t :: GenLSP.Structures.LocationLink.t() + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + GenLSP.Structures.LocationLink.schematic() + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/type_aliases/document_diagnostic_report.ex b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/document_diagnostic_report.ex new file mode 100644 index 000000000..f00e8f057 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/document_diagnostic_report.ex @@ -0,0 +1,27 @@ +# codegen: do not edit +defmodule GenLSP.TypeAlias.DocumentDiagnosticReport do + @moduledoc """ + The result of a document diagnostic pull request. A report can + either be a full report containing all diagnostics for the + requested document or an unchanged report indicating that nothing + has changed in terms of diagnostics in comparison to the last + pull request. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + @type t :: + GenLSP.Structures.RelatedFullDocumentDiagnosticReport.t() + | GenLSP.Structures.RelatedUnchangedDocumentDiagnosticReport.t() + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + GenLSP.Structures.RelatedFullDocumentDiagnosticReport.schematic(), + GenLSP.Structures.RelatedUnchangedDocumentDiagnosticReport.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/type_aliases/document_filter.ex b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/document_filter.ex new file mode 100644 index 000000000..241d9aefa --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/document_filter.ex @@ -0,0 +1,24 @@ +# codegen: do not edit +defmodule GenLSP.TypeAlias.DocumentFilter do + @moduledoc """ + A document filter describes a top level text document or + a notebook cell document. + + @since 3.17.0 - proposed support for NotebookCellTextDocumentFilter. + """ + + import SchematicV, warn: false + + @type t :: + GenLSP.TypeAlias.TextDocumentFilter.t() + | GenLSP.Structures.NotebookCellTextDocumentFilter.t() + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + GenLSP.TypeAlias.TextDocumentFilter.schematic(), + GenLSP.Structures.NotebookCellTextDocumentFilter.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/type_aliases/document_selector.ex b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/document_selector.ex new file mode 100644 index 000000000..a9a061a91 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/document_selector.ex @@ -0,0 +1,20 @@ +# codegen: do not edit +defmodule GenLSP.TypeAlias.DocumentSelector do + @moduledoc """ + A document selector is the combination of one or many document filters. + + @sample `let sel:DocumentSelector = [{ language: 'typescript' }, { language: 'json', pattern: '**∕tsconfig.json' }]`; + + The use of a string as a document filter is deprecated @since 3.16.0. + """ + + import SchematicV, warn: false + + @type t :: list(GenLSP.TypeAlias.DocumentFilter.t()) + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + list(GenLSP.TypeAlias.DocumentFilter.schematic()) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/type_aliases/glob_pattern.ex b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/glob_pattern.ex new file mode 100644 index 000000000..2a34855c1 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/glob_pattern.ex @@ -0,0 +1,18 @@ +# codegen: do not edit +defmodule GenLSP.TypeAlias.GlobPattern do + @moduledoc """ + The glob pattern. Either a string pattern or a relative pattern. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + @type t :: GenLSP.TypeAlias.Pattern.t() | GenLSP.Structures.RelativePattern.t() + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([GenLSP.TypeAlias.Pattern.schematic(), GenLSP.Structures.RelativePattern.schematic()]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/type_aliases/inline_value.ex b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/inline_value.ex new file mode 100644 index 000000000..d724af8d4 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/inline_value.ex @@ -0,0 +1,29 @@ +# codegen: do not edit +defmodule GenLSP.TypeAlias.InlineValue do + @moduledoc """ + Inline value information can be provided by different means: + - directly as a text value (class InlineValueText). + - as a name to use for a variable lookup (class InlineValueVariableLookup) + - as an evaluatable expression (class InlineValueEvaluatableExpression) + The InlineValue types combines all inline value types into one type. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + @type t :: + GenLSP.Structures.InlineValueText.t() + | GenLSP.Structures.InlineValueVariableLookup.t() + | GenLSP.Structures.InlineValueEvaluatableExpression.t() + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + GenLSP.Structures.InlineValueText.schematic(), + GenLSP.Structures.InlineValueVariableLookup.schematic(), + GenLSP.Structures.InlineValueEvaluatableExpression.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/type_aliases/lsp_any.ex b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/lsp_any.ex new file mode 100644 index 000000000..47133e3fe --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/lsp_any.ex @@ -0,0 +1,38 @@ +# codegen: do not edit +defmodule GenLSP.TypeAlias.LSPAny do + @moduledoc """ + The LSP any type. + Please note that strictly speaking a property with the value `undefined` + can't be converted into JSON preserving the property name. However for + convenience it is allowed and assumed that all these properties are + optional as well. + @since 3.17.0 + """ + + import SchematicV, warn: false + + @type t :: any() + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + %SchematicV{ + kind: "lspany", + unify: fn x, dir -> + case x do + %mod{} -> + Code.ensure_loaded(mod) + + if function_exported?(mod, :schematic, 0) do + mod.schematic().unify.(x, dir) + else + {:ok, x} + end + + _ -> + {:ok, x} + end + end + } + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/type_aliases/lsp_array.ex b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/lsp_array.ex new file mode 100644 index 000000000..8e1e01c95 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/lsp_array.ex @@ -0,0 +1,17 @@ +# codegen: do not edit +defmodule GenLSP.TypeAlias.LSPArray do + @moduledoc """ + LSP arrays. + @since 3.17.0 + """ + + import SchematicV, warn: false + + @type t :: list(any()) + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + list(any()) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/type_aliases/lsp_object.ex b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/lsp_object.ex new file mode 100644 index 000000000..19bee6b9a --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/lsp_object.ex @@ -0,0 +1,17 @@ +# codegen: do not edit +defmodule GenLSP.TypeAlias.LSPObject do + @moduledoc """ + LSP object definition. + @since 3.17.0 + """ + + import SchematicV, warn: false + + @type t :: %{String.t() => any()} + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + map(keys: str(), values: any()) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/type_aliases/marked_string.ex b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/marked_string.ex new file mode 100644 index 000000000..d072c95fb --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/marked_string.ex @@ -0,0 +1,33 @@ +# codegen: do not edit +defmodule GenLSP.TypeAlias.MarkedString do + @moduledoc """ + MarkedString can be used to render human readable text. It is either a markdown string + or a code-block that provides a language and a code snippet. The language identifier + is semantically equal to the optional language identifier in fenced code blocks in GitHub + issues. See https://help.github.com/articles/creating-and-highlighting-code-blocks/#syntax-highlighting + + The pair of a language and a value is an equivalent to markdown: + ```${language} + ${value} + ``` + + Note that markdown strings will be sanitized - that means html will be escaped. + @deprecated use MarkupContent instead. + """ + + import SchematicV, warn: false + + @type t :: String.t() | map() + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + str(), + map(%{ + {"language", :language} => str(), + {"value", :value} => str() + }) + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/type_aliases/notebook_document_filter.ex b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/notebook_document_filter.ex new file mode 100644 index 000000000..88cc7f6d3 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/notebook_document_filter.ex @@ -0,0 +1,36 @@ +# codegen: do not edit +defmodule GenLSP.TypeAlias.NotebookDocumentFilter do + @moduledoc """ + A notebook document filter denotes a notebook document by + different properties. The properties will be match + against the notebook's URI (same as with documents) + + @since 3.17.0 + """ + + import SchematicV, warn: false + + @type t :: map() | map() | map() + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + map(%{ + {"notebookType", :notebook_type} => str(), + optional({"scheme", :scheme}) => str(), + optional({"pattern", :pattern}) => str() + }), + map(%{ + optional({"notebookType", :notebook_type}) => str(), + {"scheme", :scheme} => str(), + optional({"pattern", :pattern}) => str() + }), + map(%{ + optional({"notebookType", :notebook_type}) => str(), + optional({"scheme", :scheme}) => str(), + {"pattern", :pattern} => str() + }) + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/type_aliases/pattern.ex b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/pattern.ex new file mode 100644 index 000000000..694bbfd6c --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/pattern.ex @@ -0,0 +1,24 @@ +# codegen: do not edit +defmodule GenLSP.TypeAlias.Pattern do + @moduledoc """ + The glob pattern to watch relative to the base path. Glob patterns can have the following syntax: + - `*` to match one or more characters in a path segment + - `?` to match on one character in a path segment + - `**` to match any number of path segments, including none + - `{}` to group conditions (e.g. `**​/*.{ts,js}` matches all TypeScript and JavaScript files) + - `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …) + - `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`) + + @since 3.17.0 + """ + + import SchematicV, warn: false + + @type t :: String.t() + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + str() + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/type_aliases/prepare_rename_result.ex b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/prepare_rename_result.ex new file mode 100644 index 000000000..30a72466b --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/prepare_rename_result.ex @@ -0,0 +1,21 @@ +# codegen: do not edit +defmodule GenLSP.TypeAlias.PrepareRenameResult do + import SchematicV, warn: false + + @type t :: GenLSP.Structures.Range.t() | map() | map() + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + GenLSP.Structures.Range.schematic(), + map(%{ + {"range", :range} => GenLSP.Structures.Range.schematic(), + {"placeholder", :placeholder} => str() + }), + map(%{ + {"defaultBehavior", :default_behavior} => bool() + }) + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/type_aliases/progress_token.ex b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/progress_token.ex new file mode 100644 index 000000000..5c355c730 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/progress_token.ex @@ -0,0 +1,12 @@ +# codegen: do not edit +defmodule GenLSP.TypeAlias.ProgressToken do + import SchematicV, warn: false + + @type t :: integer() | String.t() + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([int(), str()]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/type_aliases/text_document_content_change_event.ex b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/text_document_content_change_event.ex new file mode 100644 index 000000000..5e89eff6b --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/text_document_content_change_event.ex @@ -0,0 +1,26 @@ +# codegen: do not edit +defmodule GenLSP.TypeAlias.TextDocumentContentChangeEvent do + @moduledoc """ + An event describing a change to a text document. If only a text is provided + it is considered to be the full content of the document. + """ + + import SchematicV, warn: false + + @type t :: map() | map() + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + map(%{ + {"range", :range} => GenLSP.Structures.Range.schematic(), + optional({"rangeLength", :range_length}) => int(), + {"text", :text} => str() + }), + map(%{ + {"text", :text} => str() + }) + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/type_aliases/text_document_filter.ex b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/text_document_filter.ex new file mode 100644 index 000000000..81e333bfa --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/text_document_filter.ex @@ -0,0 +1,47 @@ +# codegen: do not edit +defmodule GenLSP.TypeAlias.TextDocumentFilter do + @moduledoc """ + A document filter denotes a document by different properties like + the {@link TextDocument.languageId language}, the {@link Uri.scheme scheme} of + its resource, or a glob-pattern that is applied to the {@link TextDocument.fileName path}. + + Glob patterns can have the following syntax: + - `*` to match one or more characters in a path segment + - `?` to match on one character in a path segment + - `**` to match any number of path segments, including none + - `{}` to group sub patterns into an OR expression. (e.g. `**​/*.{ts,js}` matches all TypeScript and JavaScript files) + - `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …) + - `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`) + + @sample A language filter that applies to typescript files on disk: `{ language: 'typescript', scheme: 'file' }` + @sample A language filter that applies to all package.json paths: `{ language: 'json', pattern: '**package.json' }` + + @since 3.17.0 + """ + + import SchematicV, warn: false + + @type t :: map() | map() | map() + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + map(%{ + {"language", :language} => str(), + optional({"scheme", :scheme}) => str(), + optional({"pattern", :pattern}) => str() + }), + map(%{ + optional({"language", :language}) => str(), + {"scheme", :scheme} => str(), + optional({"pattern", :pattern}) => str() + }), + map(%{ + optional({"language", :language}) => str(), + optional({"scheme", :scheme}) => str(), + {"pattern", :pattern} => str() + }) + ]) + end +end diff --git a/apps/language_server/lib/language_server/lsp/protocol/type_aliases/workspace_document_diagnostic_report.ex b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/workspace_document_diagnostic_report.ex new file mode 100644 index 000000000..34965ec73 --- /dev/null +++ b/apps/language_server/lib/language_server/lsp/protocol/type_aliases/workspace_document_diagnostic_report.ex @@ -0,0 +1,23 @@ +# codegen: do not edit +defmodule GenLSP.TypeAlias.WorkspaceDocumentDiagnosticReport do + @moduledoc """ + A workspace diagnostic document report. + + @since 3.17.0 + """ + + import SchematicV, warn: false + + @type t :: + GenLSP.Structures.WorkspaceFullDocumentDiagnosticReport.t() + | GenLSP.Structures.WorkspaceUnchangedDocumentDiagnosticReport.t() + + @doc false + @spec schematic() :: SchematicV.t() + def schematic() do + oneof([ + GenLSP.Structures.WorkspaceFullDocumentDiagnosticReport.schematic(), + GenLSP.Structures.WorkspaceUnchangedDocumentDiagnosticReport.schematic() + ]) + end +end diff --git a/apps/language_server/lib/language_server/mix_shell.ex b/apps/language_server/lib/language_server/mix_shell.ex index 22ff07a72..ad657cfa4 100644 --- a/apps/language_server/lib/language_server/mix_shell.ex +++ b/apps/language_server/lib/language_server/mix_shell.ex @@ -42,13 +42,16 @@ defmodule ElixirLS.LanguageServer.MixShell do if WireProtocol.io_intercepted?() do response = JsonRpc.show_message_request(:info, message, [ - %{"title" => "No", "result" => false}, - %{"title" => "Yes", "result" => true} + %GenLSP.Structures.MessageActionItem{title: "No"}, + %GenLSP.Structures.MessageActionItem{title: "Yes"} ]) case response do - {:ok, %{"result" => result}} -> - result + {:ok, %GenLSP.Structures.MessageActionItem{title: "No"}} -> + false + + {:ok, %GenLSP.Structures.MessageActionItem{title: "Yes"}} -> + true other -> error("[ElixirLS] unexpected client response #{inspect(other)}, assuming yes") diff --git a/apps/language_server/lib/language_server/parser.ex b/apps/language_server/lib/language_server/parser.ex index 3ee8fdfcf..3691b5466 100644 --- a/apps/language_server/lib/language_server/parser.ex +++ b/apps/language_server/lib/language_server/parser.ex @@ -381,7 +381,20 @@ defmodule ElixirLS.LanguageServer.Parser do end catch kind, err -> - {payload, stacktrace} = Exception.blame(kind, err, __STACKTRACE__) + stacktrace = __STACKTRACE__ + + {payload, stacktrace} = + try do + Exception.blame(kind, err, stacktrace) + catch + kind_1, error_1 -> + # in case of error in Exception.blame we want to use the original error and stacktrace + Logger.error( + "Exception.blame failed: #{Exception.format(kind_1, error_1, __STACKTRACE__)}" + ) + + {err, stacktrace} + end message = Exception.format(kind, payload, stacktrace) diff --git a/apps/language_server/lib/language_server/protocol/document_symbol.ex b/apps/language_server/lib/language_server/protocol/document_symbol.ex deleted file mode 100644 index 36728b435..000000000 --- a/apps/language_server/lib/language_server/protocol/document_symbol.ex +++ /dev/null @@ -1,9 +0,0 @@ -defmodule ElixirLS.LanguageServer.Protocol.DocumentSymbol do - @moduledoc """ - Corresponds to the LSP interface of the same name. - - For details see https://microsoft.github.io/language-server-protocol/specification#textDocument_documentSymbol - """ - @derive JasonV.Encoder - defstruct [:name, :detail, :kind, :range, :selectionRange, :children] -end diff --git a/apps/language_server/lib/language_server/protocol/location.ex b/apps/language_server/lib/language_server/protocol/location.ex index 61a078ef5..ef1d0e33b 100644 --- a/apps/language_server/lib/language_server/protocol/location.ex +++ b/apps/language_server/lib/language_server/protocol/location.ex @@ -8,9 +8,12 @@ defmodule ElixirLS.LanguageServer.Protocol.Location do defstruct [:uri, :range] alias ElixirLS.LanguageServer.SourceFile - require ElixirLS.LanguageServer.Protocol, as: Protocol + import ElixirLS.LanguageServer.RangeUtils - def new( + @doc """ + Converts an ElixirLS.LanguageServer.Location to a GenLSP.Structures.Location + """ + def to_gen_lsp( %ElixirLS.LanguageServer.Location{ file: file, line: line, @@ -37,9 +40,9 @@ defmodule ElixirLS.LanguageServer.Protocol.Location do {line, column} = SourceFile.elixir_position_to_lsp(text, {line, column}) {end_line, end_column} = SourceFile.elixir_position_to_lsp(text, {end_line, end_column}) - %Protocol.Location{ + %GenLSP.Structures.Location{ uri: uri, - range: Protocol.range(line, column, end_line, end_column) + range: range(line, column, end_line, end_column) } end end diff --git a/apps/language_server/lib/language_server/protocol/symbol_information.ex b/apps/language_server/lib/language_server/protocol/symbol_information.ex deleted file mode 100644 index 02349e140..000000000 --- a/apps/language_server/lib/language_server/protocol/symbol_information.ex +++ /dev/null @@ -1,9 +0,0 @@ -defmodule ElixirLS.LanguageServer.Protocol.SymbolInformation do - @moduledoc """ - Corresponds to the LSP interface of the same name. - - For details see https://microsoft.github.io/language-server-protocol/specification#textDocument_documentSymbol - """ - @derive JasonV.Encoder - defstruct [:name, :kind, :location, :containerName] -end diff --git a/apps/language_server/lib/language_server/protocol/text_edit.ex b/apps/language_server/lib/language_server/protocol/text_edit.ex deleted file mode 100644 index f2fcc8314..000000000 --- a/apps/language_server/lib/language_server/protocol/text_edit.ex +++ /dev/null @@ -1,12 +0,0 @@ -defmodule ElixirLS.LanguageServer.Protocol.TextEdit do - @moduledoc """ - Corresponds to the LSP interface of the same name. - - For details see https://microsoft.github.io/language-server-protocol/specification#textEdit - """ - - @type t :: %__MODULE__{} - - @derive JasonV.Encoder - defstruct [:range, :newText] -end diff --git a/apps/language_server/lib/language_server/providers/code_action/code_action_result.ex b/apps/language_server/lib/language_server/providers/code_action/code_action_result.ex deleted file mode 100644 index dd9482df5..000000000 --- a/apps/language_server/lib/language_server/providers/code_action/code_action_result.ex +++ /dev/null @@ -1,24 +0,0 @@ -defmodule ElixirLS.LanguageServer.Providers.CodeAction.CodeActionResult do - alias ElixirLS.LanguageServer.Protocol.TextEdit - - @type t :: %{ - title: String.t(), - kind: String.t(), - edit: %{ - changes: %{String.t() => TextEdit.t()} - } - } - - @spec new(String.t(), String.t(), [TextEdit.t()], String.t()) :: t() - def new(title, kind, text_edits, uri) do - %{ - :title => title, - :kind => kind, - :edit => %{ - :changes => %{ - uri => text_edits - } - } - } - end -end diff --git a/apps/language_server/lib/language_server/providers/code_action/helpers.ex b/apps/language_server/lib/language_server/providers/code_action/helpers.ex index 07b86476d..f4599a86c 100644 --- a/apps/language_server/lib/language_server/providers/code_action/helpers.ex +++ b/apps/language_server/lib/language_server/providers/code_action/helpers.ex @@ -1,18 +1,19 @@ defmodule ElixirLS.LanguageServer.Providers.CodeAction.Helpers do - alias ElixirLS.LanguageServer.Protocol.TextEdit alias ElixirLS.LanguageServer.Providers.CodeMod.Ast alias ElixirLS.LanguageServer.Providers.CodeMod.Text - @spec update_line(TextEdit.t(), non_neg_integer()) :: TextEdit.t() + @spec update_line(GenLSP.Structures.TextEdit.t(), non_neg_integer()) :: + GenLSP.Structures.TextEdit.t() def update_line( - %TextEdit{range: %{"start" => start_line, "end" => end_line}} = text_edit, + %GenLSP.Structures.TextEdit{range: range} = text_edit, line_number ) do - %TextEdit{ + %GenLSP.Structures.TextEdit{ text_edit - | range: %{ - "start" => %{start_line | "line" => line_number}, - "end" => %{end_line | "line" => line_number} + | range: %GenLSP.Structures.Range{ + range + | start: %GenLSP.Structures.Position{range.start | line: line_number}, + end: %GenLSP.Structures.Position{range.end | line: line_number} } } end @@ -53,10 +54,14 @@ defmodule ElixirLS.LanguageServer.Providers.CodeAction.Helpers do # https://microsoft.github.io/language-server-protocol/specifications/lsp/3.18/specification/#diagnostic # message can be string or MarkupContent # string - def diagnostic_to_message(%{"message" => message}) when is_binary(message), do: message + def diagnostic_to_message(%GenLSP.Structures.Diagnostic{message: message}) + when is_binary(message), + do: message # MarkupContent - def diagnostic_to_message(%{"message" => %{"kind" => kind, "value" => value}}) + def diagnostic_to_message(%GenLSP.Structures.Diagnostic{ + message: %GenLSP.Structures.MarkupContent{kind: kind, value: value} + }) when kind in ["plaintext", "markdown"], do: value end diff --git a/apps/language_server/lib/language_server/providers/code_action/replace_remote_function.ex b/apps/language_server/lib/language_server/providers/code_action/replace_remote_function.ex index beeb43fa2..416c5f32c 100644 --- a/apps/language_server/lib/language_server/providers/code_action/replace_remote_function.ex +++ b/apps/language_server/lib/language_server/providers/code_action/replace_remote_function.ex @@ -4,9 +4,6 @@ defmodule ElixirLS.LanguageServer.Providers.CodeAction.ReplaceRemoteFunction do similar names """ - use ElixirLS.LanguageServer.Protocol - - alias ElixirLS.LanguageServer.Providers.CodeAction.CodeActionResult alias ElixirLS.LanguageServer.Providers.CodeMod.Ast alias ElixirLS.LanguageServer.Providers.CodeMod.Diff alias ElixirLS.LanguageServer.Providers.CodeMod.Text @@ -17,7 +14,9 @@ defmodule ElixirLS.LanguageServer.Providers.CodeAction.ReplaceRemoteFunction do import ElixirLS.LanguageServer.Providers.CodeAction.Helpers - @spec apply(SourceFile.t(), String.t(), [map()]) :: [CodeActionResult.t()] + @spec apply(SourceFile.t(), String.t(), [GenLSP.Structures.Diagnostic.t()]) :: [ + GenLSP.Structures.CodeAction.t() + ] def apply(%SourceFile{} = source_file, uri, diagnostics) do Enum.flat_map(diagnostics, fn diagnostic -> with {:ok, module, function, arity, line_number} <- extract_function_and_line(diagnostic), @@ -29,11 +28,11 @@ defmodule ElixirLS.LanguageServer.Providers.CodeAction.ReplaceRemoteFunction do end) end - defp extract_function_and_line(diagnostic) do + defp extract_function_and_line(diagnostic = %GenLSP.Structures.Diagnostic{}) do message = diagnostic_to_message(diagnostic) with {:ok, module, function, arity} <- extract_function(message) do - {:ok, module, function, arity, diagnostic["range"]["start"]["line"]} + {:ok, module, function, arity, diagnostic.range.start.line} end end @@ -97,8 +96,13 @@ defmodule ElixirLS.LanguageServer.Providers.CodeAction.ReplaceRemoteFunction do {:ok, [_ | _] = text_edits} -> text_edits = Enum.map(text_edits, &update_line(&1, line_number)) - code_action = - CodeActionResult.new("Rename to #{suggestion}", "quickfix", text_edits, uri) + code_action = %GenLSP.Structures.CodeAction{ + title: "Rename to #{suggestion}", + kind: "quickfix", + edit: %GenLSP.Structures.WorkspaceEdit{ + changes: %{uri => text_edits} + } + } [code_action | acc] diff --git a/apps/language_server/lib/language_server/providers/code_action/replace_with_underscore.ex b/apps/language_server/lib/language_server/providers/code_action/replace_with_underscore.ex index 98833004e..14503843c 100644 --- a/apps/language_server/lib/language_server/providers/code_action/replace_with_underscore.ex +++ b/apps/language_server/lib/language_server/providers/code_action/replace_with_underscore.ex @@ -3,10 +3,6 @@ defmodule ElixirLS.LanguageServer.Providers.CodeAction.ReplaceWithUnderscore do A code action that prefixes unused variables with an underscore """ - use ElixirLS.LanguageServer.Protocol - - alias ElixirLS.LanguageServer.Protocol.TextEdit - alias ElixirLS.LanguageServer.Providers.CodeAction.CodeActionResult alias ElixirLS.LanguageServer.Providers.CodeMod.Ast alias ElixirLS.LanguageServer.Providers.CodeMod.Diff alias ElixirLS.LanguageServer.Providers.CodeMod.Text @@ -14,7 +10,9 @@ defmodule ElixirLS.LanguageServer.Providers.CodeAction.ReplaceWithUnderscore do import ElixirLS.LanguageServer.Providers.CodeAction.Helpers - @spec apply(SourceFile.t(), String.t(), [map()]) :: [CodeActionResult.t()] + @spec apply(SourceFile.t(), String.t(), [GenLSP.Structures.Diagnostic.t()]) :: [ + GenLSP.Structures.CodeAction.t() + ] def apply(%SourceFile{} = source_file, uri, diagnostics) do Enum.flat_map(diagnostics, fn diagnostic -> with {:ok, variable_name, line_number} <- extract_variable_and_line(diagnostic), @@ -27,11 +25,11 @@ defmodule ElixirLS.LanguageServer.Providers.CodeAction.ReplaceWithUnderscore do end) end - defp extract_variable_and_line(diagnostic) do + defp extract_variable_and_line(diagnostic = %GenLSP.Structures.Diagnostic{}) do message = diagnostic_to_message(diagnostic) with {:ok, variable_name} <- extract_variable_name(message) do - {:ok, variable_name, diagnostic["range"]["start"]["line"]} + {:ok, variable_name, diagnostic.range.start.line} end end @@ -56,13 +54,13 @@ defmodule ElixirLS.LanguageServer.Providers.CodeAction.ReplaceWithUnderscore do [_ | _] -> text_edits = Enum.map(text_edits, &update_line(&1, line_number)) - reply = - CodeActionResult.new( - "Rename to _#{variable_name}", - "quickfix", - text_edits, - uri - ) + reply = %GenLSP.Structures.CodeAction{ + title: "Rename to _#{variable_name}", + kind: "quickfix", + edit: %GenLSP.Structures.WorkspaceEdit{ + changes: %{uri => text_edits} + } + } {:ok, reply} end @@ -79,7 +77,8 @@ defmodule ElixirLS.LanguageServer.Providers.CodeAction.ReplaceWithUnderscore do end end - @spec text_edits(String.t(), Ast.t(), atom()) :: {:ok, [TextEdit.t()]} | :error + @spec text_edits(String.t(), Ast.t(), atom()) :: + {:ok, [GenLSP.Structures.TextEdit.t()]} | :error defp text_edits(original_text, ast, variable_name) do with {:ok, transformed} <- apply_transform(original_text, ast, variable_name) do {:ok, to_text_edits(original_text, transformed)} @@ -110,6 +109,6 @@ defmodule ElixirLS.LanguageServer.Providers.CodeAction.ReplaceWithUnderscore do defp to_text_edits(original_text, fixed_text) do original_text |> Diff.diff(fixed_text) - |> Enum.filter(&(&1.newText == "_")) + |> Enum.filter(&(&1.new_text == "_")) end end diff --git a/apps/language_server/lib/language_server/providers/code_lens.ex b/apps/language_server/lib/language_server/providers/code_lens.ex index 37dc88a5f..e3b801e35 100644 --- a/apps/language_server/lib/language_server/providers/code_lens.ex +++ b/apps/language_server/lib/language_server/providers/code_lens.ex @@ -8,7 +8,7 @@ defmodule ElixirLS.LanguageServer.Providers.CodeLens do """ alias ElixirLS.LanguageServer.Providers.CodeLens - import ElixirLS.LanguageServer.Protocol + import ElixirLS.LanguageServer.RangeUtils def spec_code_lens(server_instance_id, uri, text), do: CodeLens.TypeSpec.code_lens(server_instance_id, uri, text) @@ -17,13 +17,13 @@ defmodule ElixirLS.LanguageServer.Providers.CodeLens do do: CodeLens.Test.code_lens(parser_context, project_dir) def build_code_lens(line, title, command, argument) do - %{ + %GenLSP.Structures.CodeLens{ # we don't care about utf16 positions here as we send 0 - "range" => range(line - 1, 0, line - 1, 0), - "command" => %{ - "title" => title, - "command" => command, - "arguments" => [argument] + range: range(line - 1, 0, line - 1, 0), + command: %GenLSP.Structures.Command{ + title: title, + command: command, + arguments: [argument] } } end diff --git a/apps/language_server/lib/language_server/providers/code_mod/diff.ex b/apps/language_server/lib/language_server/providers/code_mod/diff.ex index 24599de48..5b077a0ea 100644 --- a/apps/language_server/lib/language_server/providers/code_mod/diff.ex +++ b/apps/language_server/lib/language_server/providers/code_mod/diff.ex @@ -1,8 +1,8 @@ defmodule ElixirLS.LanguageServer.Providers.CodeMod.Diff do alias ElixirLS.LanguageServer.CodeUnit - alias ElixirLS.LanguageServer.Protocol.TextEdit + alias GenLSP.Structures.TextEdit - import ElixirLS.LanguageServer.Protocol + import ElixirLS.LanguageServer.RangeUtils @spec diff(String.t(), String.t()) :: [TextEdit.t()] def diff(source, dest) do @@ -31,24 +31,19 @@ defmodule ElixirLS.LanguageServer.Providers.CodeMod.Diff do # insert rather than "" defp collapse( %TextEdit{ - newText: "", - range: %{ - "end" => %{"character" => same_character, "line" => same_line} - } + new_text: "", + range: range(_, _, same_line, same_character) } = delete_edit, [ %TextEdit{ - newText: insert_text, - range: - %{ - "start" => %{"character" => same_character, "line" => same_line} - } = _insert_edit + new_text: insert_text, + range: range(same_line, same_character, _, _) = _insert_edit } | rest ] ) when byte_size(insert_text) > 0 do - collapsed_edit = %TextEdit{delete_edit | newText: insert_text} + collapsed_edit = %TextEdit{delete_edit | new_text: insert_text} [collapsed_edit | rest] end @@ -95,7 +90,7 @@ defmodule ElixirLS.LanguageServer.Providers.CodeMod.Diff do defp edit(text, start_line, start_unit, end_line, end_unit) do %TextEdit{ - newText: text, + new_text: text, range: range(start_line, start_unit, end_line, end_unit) } end diff --git a/apps/language_server/lib/language_server/providers/completion.ex b/apps/language_server/lib/language_server/providers/completion.ex index 237a59f63..50fac2bdb 100644 --- a/apps/language_server/lib/language_server/providers/completion.ex +++ b/apps/language_server/lib/language_server/providers/completion.ex @@ -7,32 +7,37 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do with the Language Server Protocol. We also attempt to determine the context based on the line text before the cursor so we can filter out suggestions that are not relevant. """ - alias ElixirLS.LanguageServer.Protocol.TextEdit alias ElixirLS.LanguageServer.{SourceFile, Parser} - import ElixirLS.LanguageServer.Protocol, only: [range: 4] alias ElixirLS.Utils.Matcher alias ElixirSense.Core.State alias ElixirSense.Core.Normalized.Code, as: NormalizedCode alias ElixirLS.LanguageServer.MarkdownUtils require Logger - @enforce_keys [:label, :kind, :insert_text, :priority, :tags] + defmodule CompletionItem do + @enforce_keys [:label, :kind, :insert_text, :tags] + defstruct [ + :label, + :kind, + :detail, + :documentation, + :insert_text, + :insert_text_mode, + :filter_text, + :label_details, + :tags, + :command, + {:preselect, false}, + :additional_text_edit, + :text_edit + ] + end + + @enforce_keys [:priority, :completion_item] defstruct [ - :label, - :kind, - :detail, - :documentation, - :insert_text, - :insert_text_mode, - :filter_text, # Lower priority is shown higher in the result list :priority, - :label_details, - :tags, - :command, - {:preselect, false}, - :additional_text_edit, - :text_edit + :completion_item ] @func_snippets %{ @@ -280,6 +285,7 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do |> maybe_add_keywords(context) |> Enum.reject(&is_nil/1) |> sort_items() + |> Enum.map(& &1.completion_item) # add trigger signatures to arity 0 if there are higher arity completions that would trigger commands = @@ -294,24 +300,26 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do items = items |> Enum.map(fn - %{command: nil, kind: kind} = item when kind in [:function, :constant, :class] -> - command = commands[{kind, item.label}] + %CompletionItem{command: nil, kind: kind} = completion_item + when kind in [:function, :constant, :class] -> + command = commands[{kind, completion_item.label}] if command do - %{item | command: command, insert_text: "#{item.label}($1)$0"} + %{completion_item | command: command, insert_text: "#{completion_item.label}($1)$0"} else - item + completion_item end - item -> - item + completion_item -> + completion_item end) - items_json = - items - |> items_to_json(options) + completion_list = %GenLSP.Structures.CompletionList{ + is_incomplete: is_incomplete(items), + items: items_to_gen_lsp(items, options) + } - {:ok, %{"isIncomplete" => is_incomplete(items_json), "items" => items_json}} + {:ok, completion_list} end defp maybe_add_do(completion_items, context, options) do @@ -323,23 +331,25 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do if hint in ["d", "do"] do item = %__MODULE__{ - label: "do", - kind: :keyword, - detail: "reserved word", - insert_text: - if String.trim(context.text_after_cursor) == "" do - if Keyword.get(options, :snippets_supported, false) do - "do\n $0\nend" - else - "do" - end - else - "do: " - end, - tags: [], priority: 0, - # force selection over other longer not exact completions - preselect: hint == "do" + completion_item: %CompletionItem{ + label: "do", + kind: :keyword, + detail: "reserved word", + insert_text: + if String.trim(context.text_after_cursor) == "" do + if Keyword.get(options, :snippets_supported, false) do + "do\n $0\nend" + else + "do" + end + else + "do: " + end, + tags: [], + # force selection over other longer not exact completions + preselect: hint == "do" + } } [item | completion_items] @@ -364,20 +374,20 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do keyword in ~w(rescue catch else after) -> if String.trim(context.text_after_cursor) == "" do {nil, - %{ - "range" => %{ - "start" => %{ - "line" => context.line - 1, - "character" => + %GenLSP.Structures.TextEdit{ + range: %GenLSP.Structures.Range{ + start: %GenLSP.Structures.Position{ + line: context.line - 1, + character: context.character - String.length(hint) - 1 - max(context.line_indent - context.do_block_indent, 0) }, - "end" => %{ - "line" => context.line - 1, - "character" => context.character - 1 + end: %GenLSP.Structures.Position{ + line: context.line - 1, + character: context.character - 1 } }, - "newText" => "#{keyword}\n " + new_text: "#{keyword}\n " }} else {"#{keyword}: ", nil} @@ -388,17 +398,20 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do keyword == "end" -> {nil, - %{ - "range" => %{ - "start" => %{ - "line" => context.line - 1, - "character" => + %GenLSP.Structures.TextEdit{ + range: %GenLSP.Structures.Range{ + start: %GenLSP.Structures.Position{ + line: context.line - 1, + character: context.character - String.length(hint) - 1 - max(context.line_indent - context.do_block_indent, 0) }, - "end" => %{"line" => context.line - 1, "character" => context.character - 1} + end: %GenLSP.Structures.Position{ + line: context.line - 1, + character: context.character - 1 + } }, - "newText" => "end\n" + new_text: "end\n" }} true -> @@ -406,15 +419,17 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do end %__MODULE__{ - label: keyword, - kind: :keyword, - detail: "reserved word", - insert_text: insert_text, - text_edit: text_edit, - tags: [], priority: 0, - insert_text_mode: 2, - preselect: hint == keyword + completion_item: %CompletionItem{ + label: keyword, + kind: :keyword, + detail: "reserved word", + insert_text: insert_text, + text_edit: text_edit, + tags: [], + insert_text_mode: GenLSP.Enumerations.InsertTextMode.adjust_indentation(), + preselect: hint == keyword + } } end @@ -478,14 +493,16 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do end %__MODULE__{ - label: name, - kind: :enum_member, - detail: "module attribute", - documentation: name <> "\n" <> if(summary, do: summary, else: ""), - insert_text: insert_text, - filter_text: name_only, priority: 14, - tags: [] + completion_item: %CompletionItem{ + label: name, + kind: :enum_member, + detail: "module attribute", + documentation: name <> "\n" <> if(summary, do: summary, else: ""), + insert_text: insert_text, + filter_text: name_only, + tags: [] + } } end @@ -499,12 +516,14 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do _options ) do %__MODULE__{ - label: to_string(name), - kind: :variable, - detail: "variable", - insert_text: name, priority: 13, - tags: [] + completion_item: %CompletionItem{ + label: to_string(name), + kind: :variable, + detail: "variable", + insert_text: name, + tags: [] + } } end @@ -516,13 +535,15 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do snippet = Regex.replace(~r/"\$\{(.*)\}\$"/U, snippet, "${\\1}") %__MODULE__{ - label: description, - kind: :value, - detail: "return value", - documentation: spec, - insert_text: snippet, priority: 15, - tags: [] + completion_item: %CompletionItem{ + label: description, + kind: :value, + detail: "return value", + documentation: spec, + insert_text: snippet, + tags: [] + } } end @@ -566,20 +587,25 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do label_details = Map.update!( - completion_without_additional_text_edit.label_details, + completion_without_additional_text_edit.completion_item.label_details, "description", &("alias " <> &1) ) %__MODULE__{ - completion_without_additional_text_edit - | additional_text_edit: %TextEdit{ - range: range(line_to_insert_alias, 0, line_to_insert_alias, 0), - newText: alias_edit - }, - documentation: name <> "\n" <> summary, - label_details: label_details, - priority: 24 + priority: 24, + completion_item: %CompletionItem{ + completion_without_additional_text_edit.completion_item + | additional_text_edit: %GenLSP.Structures.TextEdit{ + range: %GenLSP.Structures.Range{ + start: %GenLSP.Structures.Position{line: line_to_insert_alias, character: 0}, + end: %GenLSP.Structures.Position{line: line_to_insert_alias, character: 0} + }, + new_text: alias_edit + }, + documentation: name <> "\n" <> summary, + label_details: label_details + } } end @@ -635,15 +661,17 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do end %__MODULE__{ - label: name, - kind: kind, - detail: detail, - documentation: summary <> "\n\n" <> MarkdownUtils.get_metadata_md(metadata), - insert_text: insert_text, - filter_text: name, - label_details: label_details, priority: priority, - tags: metadata_to_tags(metadata) + completion_item: %CompletionItem{ + label: name, + kind: kind, + detail: detail, + documentation: summary <> "\n\n" <> MarkdownUtils.get_metadata_md(metadata), + insert_text: insert_text, + filter_text: name, + label_details: label_details, + tags: metadata_to_tags(metadata) + } } end @@ -686,14 +714,16 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do end %__MODULE__{ - label: label, - kind: :interface, - detail: "#{origin} #{subtype}", - documentation: summary <> "\n\n" <> MarkdownUtils.get_metadata_md(metadata), - insert_text: insert_text, priority: 12, - filter_text: filter_text, - tags: metadata_to_tags(metadata) + completion_item: %CompletionItem{ + label: label, + kind: :interface, + detail: "#{origin} #{subtype}", + documentation: summary <> "\n\n" <> MarkdownUtils.get_metadata_md(metadata), + insert_text: insert_text, + filter_text: filter_text, + tags: metadata_to_tags(metadata) + } } end end @@ -720,14 +750,16 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do label = "#{def_str}#{name}/#{arity}" %__MODULE__{ - label: label, - kind: :interface, - detail: "#{origin} protocol function", - documentation: summary <> "\n\n" <> MarkdownUtils.get_metadata_md(metadata), - insert_text: insert_text, priority: 12, - filter_text: name, - tags: metadata_to_tags(metadata) + completion_item: %CompletionItem{ + label: label, + kind: :interface, + detail: "#{origin} protocol function", + documentation: summary <> "\n\n" <> MarkdownUtils.get_metadata_md(metadata), + insert_text: insert_text, + filter_text: name, + tags: metadata_to_tags(metadata) + } } end end @@ -769,13 +801,15 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do end %__MODULE__{ - label: to_string(name), - detail: detail, - insert_text: if(call?, do: name, else: "#{name}: "), - documentation: summary <> formatted_spec, priority: 10, - kind: :field, - tags: [] + completion_item: %CompletionItem{ + label: to_string(name), + detail: detail, + insert_text: if(call?, do: name, else: "#{name}: "), + documentation: summary <> formatted_spec, + kind: :field, + tags: [] + } } end @@ -802,15 +836,18 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do subtype == :keyword -> {"", - %{ - "range" => %{ - "start" => %{ - "line" => context.line, - "character" => context.character - String.length(context.prefix) + %GenLSP.Structures.TextEdit{ + range: %GenLSP.Structures.Range{ + start: %GenLSP.Structures.Position{ + line: context.line, + character: context.character - String.length(context.prefix) }, - "end" => %{"line" => context.line, "character" => context.character} + end: %GenLSP.Structures.Position{ + line: context.line, + character: context.character + } }, - "newText" => "#{name}: " + new_text: "#{name}: " }} match?(":" <> _, context.prefix) -> @@ -821,14 +858,16 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do end %__MODULE__{ - label: to_string(name), - detail: "#{origin} option", - documentation: formatted_spec, - insert_text: insert_text, - text_edit: text_edit, priority: 10, - kind: :field, - tags: [] + completion_item: %CompletionItem{ + label: to_string(name), + detail: "#{origin} option", + documentation: formatted_spec, + insert_text: insert_text, + text_edit: text_edit, + kind: :field, + tags: [] + } } end @@ -853,12 +892,14 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do end %__MODULE__{ - label: name, - detail: "bitstring option", - insert_text: insert_text, priority: 10, - kind: :type_parameter, - tags: [] + completion_item: %CompletionItem{ + label: name, + detail: "bitstring option", + insert_text: insert_text, + kind: :type_parameter, + tags: [] + } } end @@ -905,18 +946,21 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do end %__MODULE__{ - label: name, - detail: "typespec #{signature}", - label_details: %{ - "detail" => "(#{Enum.join(args_list, ", ")})", - "description" => if(origin, do: "#{origin}.#{name}/#{arity}", else: "#{name}/#{arity}") - }, - documentation: "#{doc}\n\n#{MarkdownUtils.get_metadata_md(metadata)}\n\n#{formatted_spec}", - insert_text: snippet, priority: 10, - kind: :class, - tags: metadata_to_tags(metadata), - command: command + completion_item: %CompletionItem{ + label: name, + detail: "typespec #{signature}", + label_details: %{ + "detail" => "(#{Enum.join(args_list, ", ")})", + "description" => if(origin, do: "#{origin}.#{name}/#{arity}", else: "#{name}/#{arity}") + }, + documentation: + "#{doc}\n\n#{MarkdownUtils.get_metadata_md(metadata)}\n\n#{formatted_spec}", + insert_text: snippet, + kind: :class, + tags: metadata_to_tags(metadata), + command: command + } } end @@ -934,15 +978,17 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do end %__MODULE__{ - label: label, - detail: suggestion[:detail] || "", - documentation: suggestion[:documentation] || "", - insert_text: insert_text, - filter_text: suggestion[:filter_text], priority: suggestion[:priority] || 0, - kind: kind, - command: suggestion[:command], - tags: [] + completion_item: %CompletionItem{ + label: label, + detail: suggestion[:detail] || "", + documentation: suggestion[:documentation] || "", + insert_text: insert_text, + filter_text: suggestion[:filter_text], + kind: kind, + command: suggestion[:command], + tags: [] + } } end @@ -977,7 +1023,10 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do if completion do completion = if name in @operators do - %__MODULE__{completion | kind: :operator} + %__MODULE__{ + completion + | completion_item: %CompletionItem{completion.completion_item | kind: :operator} + } else completion end @@ -995,18 +1044,27 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do label_details = Map.update!( - completion.label_details, + completion.completion_item.label_details, "description", &("require " <> &1) ) %__MODULE__{ completion - | additional_text_edit: %TextEdit{ - range: range(line_to_insert_require, 0, line_to_insert_require, 0), - newText: require_edit - }, - label_details: label_details + | completion_item: %CompletionItem{ + completion.completion_item + | additional_text_edit: %GenLSP.Structures.TextEdit{ + range: %GenLSP.Structures.Range{ + start: %GenLSP.Structures.Position{ + line: line_to_insert_require, + character: 0 + }, + end: %GenLSP.Structures.Position{line: line_to_insert_require, character: 0} + }, + new_text: require_edit + }, + label_details: label_details + } } else completion @@ -1015,7 +1073,14 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do file_path = Keyword.get(options, :file_path) if snippet = snippet_for({origin, name}, Map.put(context, :file_path, file_path)) do - %__MODULE__{completion | insert_text: snippet, label: name} + %__MODULE__{ + completion + | completion_item: %CompletionItem{ + completion.completion_item + | insert_text: snippet, + label: name + } + } else completion end @@ -1227,44 +1292,6 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do text != "" end - # LSP CompletionItemKind enumeration - defp completion_kind(kind) do - case kind do - :text -> 1 - :method -> 2 - :function -> 3 - :constructor -> 4 - :field -> 5 - :variable -> 6 - :class -> 7 - :interface -> 8 - :module -> 9 - :property -> 10 - :unit -> 11 - :value -> 12 - :enum -> 13 - :keyword -> 14 - :snippet -> 15 - :color -> 16 - :file -> 17 - :reference -> 18 - :folder -> 19 - :enum_member -> 20 - :constant -> 21 - :struct -> 22 - :event -> 23 - :operator -> 24 - :type_parameter -> 25 - end - end - - defp insert_text_format(type) do - case type do - :plain_text -> 1 - :snippet -> 2 - end - end - defp get_prefix(text_before_cursor) do regex = ~r/[\w0-9\._!\?\:@\->]+$/u @@ -1369,19 +1396,21 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do if label == name or remote_calls? do %__MODULE__{ - label: label, - kind: if(type == :function, do: :function, else: :constant), - detail: to_string(type), - label_details: %{ - "detail" => "(#{Enum.join(args_list, ", ")})", - "description" => "#{origin}.#{label}/#{arity}" - }, - documentation: - summary <> "\n\n" <> MarkdownUtils.get_metadata_md(metadata) <> "\n\n" <> footer, - insert_text: insert_text, priority: 17, - tags: metadata_to_tags(metadata), - command: command + completion_item: %CompletionItem{ + label: label, + kind: if(type == :function, do: :function, else: :constant), + detail: to_string(type), + label_details: %{ + "detail" => "(#{Enum.join(args_list, ", ")})", + "description" => "#{origin}.#{label}/#{arity}" + }, + documentation: + summary <> "\n\n" <> MarkdownUtils.get_metadata_md(metadata) <> "\n\n" <> footer, + insert_text: insert_text, + tags: metadata_to_tags(metadata), + command: command + } } end end @@ -1393,10 +1422,10 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do end defp sort_items(items) do - Enum.sort_by(items, fn %__MODULE__{priority: priority, label: label} = item -> + Enum.sort_by(items, fn %__MODULE__{priority: priority, completion_item: completion_item} -> # deprioritize deprecated priority = - if item.tags |> Enum.any?(&(&1 == :deprecated)) do + if completion_item.tags |> Enum.any?(&(&1 == :deprecated)) do priority + 30 else priority @@ -1409,113 +1438,172 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do # _underscored_function # __MODULE__ # operators - {priority, label =~ ~r/^[^\p{L}]/u, label} + {priority, completion_item.label =~ ~r/^[^\p{L}]/u, completion_item.label} end) end - defp items_to_json(items, options) do + defp items_to_gen_lsp(items, options) do snippets_supported = Keyword.get(options, :snippets_supported, false) items = - Enum.reject(items, fn item -> - not snippets_supported and snippet?(item) + Enum.reject(items, fn completion_item -> + not snippets_supported and snippet?(completion_item) end) for {item, idx} <- Enum.with_index(items) do - item_to_json(item, idx, options) + item_to_gen_lsp(item, idx, options) end end - defp item_to_json(item, idx, options) do - kind = - try do - completion_kind(item.kind) - rescue - _ -> - raise "unexpected kind #{inspect(item.kind)} in completion #{inspect(item)}" - end + defp item_to_gen_lsp(%CompletionItem{} = completion_item, idx, options) do + kind = completion_kind_gen_lsp(completion_item.kind) - json = %{ - "label" => item.label, - "kind" => kind, - "detail" => item.detail, - "documentation" => %{"value" => item.documentation || "", kind: "markdown"}, - "labelDetails" => item.label_details, - "filterText" => item.filter_text, - "sortText" => String.pad_leading(to_string(idx), 8, "0"), - "insertText" => item.insert_text, - "additionalTextEdits" => - if item.additional_text_edit do - [item.additional_text_edit] - else - nil - end, - "command" => item.command, - "insertTextFormat" => - if Keyword.get(options, :snippets_supported, false) do - insert_text_format(:snippet) - else - insert_text_format(:plain_text) - end, - # adjustIndentation - "insertTextMode" => 2 + base_item = %GenLSP.Structures.CompletionItem{ + label: completion_item.label, + kind: kind, + detail: completion_item.detail, + sort_text: String.pad_leading(to_string(idx), 8, "0"), + filter_text: completion_item.filter_text, + insert_text: completion_item.insert_text, + preselect: if(completion_item.preselect, do: true, else: nil), + command: + if(completion_item.command, do: command_to_gen_lsp(completion_item.command), else: nil) } - json = - if item.preselect do - Map.put(json, "preselect", true) + base_item = + if completion_item.documentation do + %{ + base_item + | documentation: %GenLSP.Structures.MarkupContent{ + kind: GenLSP.Enumerations.MarkupKind.markdown(), + value: completion_item.documentation + } + } + else + base_item + end + + base_item = + if completion_item.label_details do + %{ + base_item + | label_details: %GenLSP.Structures.CompletionItemLabelDetails{ + detail: completion_item.label_details["detail"], + description: completion_item.label_details["description"] + } + } else - json + base_item end - json = - if item.insert_text_mode do - Map.put(json, "insertTextMode", item.insert_text_mode) + base_item = + if completion_item.additional_text_edit do + %{base_item | additional_text_edits: [completion_item.additional_text_edit]} else - json + base_item end - json = - if item.text_edit do - Map.put(json, "textEdit", item.text_edit) + base_item = + if completion_item.text_edit do + %{base_item | text_edit: completion_item.text_edit} else - json + base_item end - # deprecated as of Language Server Protocol Specification - 3.15 - json = - if Keyword.get(options, :deprecated_supported, false) do - Map.merge(json, %{ - "deprecated" => item.tags |> Enum.any?(&(&1 == :deprecated)) - }) + base_item = + if completion_item.insert_text_mode do + %{base_item | insert_text_mode: completion_item.insert_text_mode} + else + base_item + end + + base_item = + if Keyword.get(options, :snippets_supported, false) do + %{base_item | insert_text_format: GenLSP.Enumerations.InsertTextFormat.snippet()} else - json + %{base_item | insert_text_format: GenLSP.Enumerations.InsertTextFormat.plain_text()} end tags_supported = options |> Keyword.get(:tags_supported, []) - json = + base_item = if tags_supported != [] do - Map.merge(json, %{ - "tags" => item.tags |> Enum.map(&tag_to_code/1) |> Enum.filter(&(&1 in tags_supported)) - }) + completion_tags = + completion_item.tags + |> Enum.map(&tag_to_gen_lsp/1) + |> Enum.filter(&(&1 != nil)) + |> Enum.filter(&(&1 in tags_supported)) + + %{base_item | tags: if(completion_tags != [], do: completion_tags, else: nil)} else - json + base_item end - for {k, v} <- json, not is_nil(v), into: %{}, do: {k, v} + # deprecated as of Language Server Protocol Specification - 3.15 + base_item = + if Keyword.get(options, :deprecated_supported, false) do + %{ + base_item + | deprecated: + if(completion_item.tags |> Enum.any?(&(&1 == :deprecated)), do: true, else: nil) + } + else + base_item + end + + base_item end - defp snippet?(item) do - item.kind == :snippet || - (item.insert_text != nil and String.match?(item.insert_text, ~r/\${?\d/u)) + defp snippet?(completion_item = %CompletionItem{}) do + completion_item.kind == :snippet || + (completion_item.insert_text != nil and + String.match?(completion_item.insert_text, ~r/\${?\d/u)) end - # As defined by CompletionItemTag in https://microsoft.github.io/language-server-protocol/specifications/specification-current/ - defp tag_to_code(:deprecated), do: 1 + # GenLSP helper functions + defp completion_kind_gen_lsp(kind) do + case kind do + :text -> GenLSP.Enumerations.CompletionItemKind.text() + :method -> GenLSP.Enumerations.CompletionItemKind.method() + :function -> GenLSP.Enumerations.CompletionItemKind.function() + :constructor -> GenLSP.Enumerations.CompletionItemKind.constructor() + :field -> GenLSP.Enumerations.CompletionItemKind.field() + :variable -> GenLSP.Enumerations.CompletionItemKind.variable() + :class -> GenLSP.Enumerations.CompletionItemKind.class() + :interface -> GenLSP.Enumerations.CompletionItemKind.interface() + :module -> GenLSP.Enumerations.CompletionItemKind.module() + :property -> GenLSP.Enumerations.CompletionItemKind.property() + :unit -> GenLSP.Enumerations.CompletionItemKind.unit() + :value -> GenLSP.Enumerations.CompletionItemKind.value() + :enum -> GenLSP.Enumerations.CompletionItemKind.enum() + :keyword -> GenLSP.Enumerations.CompletionItemKind.keyword() + :snippet -> GenLSP.Enumerations.CompletionItemKind.snippet() + :color -> GenLSP.Enumerations.CompletionItemKind.color() + :file -> GenLSP.Enumerations.CompletionItemKind.file() + :reference -> GenLSP.Enumerations.CompletionItemKind.reference() + :folder -> GenLSP.Enumerations.CompletionItemKind.folder() + :enum_member -> GenLSP.Enumerations.CompletionItemKind.enum_member() + :constant -> GenLSP.Enumerations.CompletionItemKind.constant() + :struct -> GenLSP.Enumerations.CompletionItemKind.struct() + :event -> GenLSP.Enumerations.CompletionItemKind.event() + :operator -> GenLSP.Enumerations.CompletionItemKind.operator() + :type_parameter -> GenLSP.Enumerations.CompletionItemKind.type_parameter() + end + end + + defp tag_to_gen_lsp(:deprecated), do: GenLSP.Enumerations.CompletionItemTag.deprecated() + defp tag_to_gen_lsp(_), do: nil + + defp command_to_gen_lsp(command) when is_map(command) do + %GenLSP.Structures.Command{ + title: command["title"], + command: command["command"], + arguments: command["arguments"] + } + end defp metadata_to_tags(metadata) do - # As of Language Server Protocol Specification - 3.15 only one tag is supported + # As of Language Server Protocol Specification - 3.18 only one tag is supported case metadata[:deprecated] do nil -> [] _ -> [:deprecated] @@ -1523,9 +1611,11 @@ defmodule ElixirLS.LanguageServer.Providers.Completion do end defp function_name_with_parens?(name, arity, locals_without_parens) do - (locals_without_parens || MapSet.new()) - |> MapSet.member?({String.to_atom(name), arity}) - |> Kernel.not() + locals_without_parens = locals_without_parens || MapSet.new() + name = String.to_atom(name) + + not (MapSet.member?(locals_without_parens, {name, arity}) or + MapSet.member?(locals_without_parens, {name, :*})) end defp sanitize_function_name(name, origin) when origin in ["Kernel", "Kernel.SpecialForms"], diff --git a/apps/language_server/lib/language_server/providers/completion/generic_reducer.ex b/apps/language_server/lib/language_server/providers/completion/generic_reducer.ex index 0be75d990..6aacff765 100644 --- a/apps/language_server/lib/language_server/providers/completion/generic_reducer.ex +++ b/apps/language_server/lib/language_server/providers/completion/generic_reducer.ex @@ -49,7 +49,21 @@ defmodule ElixirLS.LanguageServer.Providers.Completion.GenericReducer do reducer.suggestions(hint, func_call, chain, opts) |> handle_suggestions(acc) catch kind, payload -> - {payload, stacktrace} = Exception.blame(kind, payload, __STACKTRACE__) + stacktrace = __STACKTRACE__ + + {payload, stacktrace} = + try do + Exception.blame(kind, payload, stacktrace) + catch + kind_1, error_1 -> + # in case of error in Exception.blame we want to use the original error and stacktrace + Logger.error( + "Exception.blame failed: #{Exception.format(kind_1, error_1, __STACKTRACE__)}" + ) + + {payload, stacktrace} + end + message = Exception.format(kind, payload, stacktrace) Logger.error("Error in suggestions reducer: #{message}") {:cont, acc} @@ -64,7 +78,21 @@ defmodule ElixirLS.LanguageServer.Providers.Completion.GenericReducer do reducer.suggestions(hint, opts) |> handle_suggestions(acc) catch kind, payload -> - {payload, stacktrace} = Exception.blame(kind, payload, __STACKTRACE__) + stacktrace = __STACKTRACE__ + + {payload, stacktrace} = + try do + Exception.blame(kind, payload, stacktrace) + catch + kind_1, error_1 -> + # in case of error in Exception.blame we want to use the original error and stacktrace + Logger.error( + "Exception.blame failed: #{Exception.format(kind_1, error_1, __STACKTRACE__)}" + ) + + {payload, stacktrace} + end + message = Exception.format(kind, payload, stacktrace) Logger.error("Error in suggestions reducer: #{message}") {:cont, acc} diff --git a/apps/language_server/lib/language_server/providers/declaration.ex b/apps/language_server/lib/language_server/providers/declaration.ex index ac3c8a72e..8f7d20419 100644 --- a/apps/language_server/lib/language_server/providers/declaration.ex +++ b/apps/language_server/lib/language_server/providers/declaration.ex @@ -19,10 +19,10 @@ defmodule ElixirLS.LanguageServer.Providers.Declaration do nil %ElixirLS.LanguageServer.Location{} = location -> - Protocol.Location.new(location, uri, source_file.text, project_dir) + Protocol.Location.to_gen_lsp(location, uri, source_file.text, project_dir) list when is_list(list) -> - Enum.map(list, &Protocol.Location.new(&1, uri, source_file.text, project_dir)) + Enum.map(list, &Protocol.Location.to_gen_lsp(&1, uri, source_file.text, project_dir)) end {:ok, result} diff --git a/apps/language_server/lib/language_server/providers/definition.ex b/apps/language_server/lib/language_server/providers/definition.ex index 25ea03bf1..a68e93d40 100644 --- a/apps/language_server/lib/language_server/providers/definition.ex +++ b/apps/language_server/lib/language_server/providers/definition.ex @@ -19,7 +19,7 @@ defmodule ElixirLS.LanguageServer.Providers.Definition do nil %ElixirLS.LanguageServer.Location{} = location -> - Protocol.Location.new(location, uri, source_file.text, project_dir) + Protocol.Location.to_gen_lsp(location, uri, source_file.text, project_dir) end {:ok, result} diff --git a/apps/language_server/lib/language_server/providers/document_symbols.ex b/apps/language_server/lib/language_server/providers/document_symbols.ex index c6a9fc36b..15fea0059 100644 --- a/apps/language_server/lib/language_server/providers/document_symbols.ex +++ b/apps/language_server/lib/language_server/providers/document_symbols.ex @@ -7,7 +7,6 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do alias ElixirLS.LanguageServer.Providers.SymbolUtils alias ElixirLS.LanguageServer.{SourceFile, Parser} - require ElixirLS.LanguageServer.Protocol, as: Protocol defmodule Info do defstruct [:type, :name, :detail, :location, :children, :selection_location, :symbol] @@ -121,7 +120,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do %Info{ type: type, name: symbol || module_name, - detail: if(defname == :defimpl_transformed, do: :defimpl, else: defname), + detail: if(defname == :defimpl_transformed, do: :defimpl, else: defname) |> to_string, location: location, selection_location: module_name_location, children: module_symbols, @@ -157,7 +156,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do %Info{ type: :struct, name: "#{defname} #{module_name}", - detail: defname, + detail: defname |> to_string, location: location, children: children } @@ -238,7 +237,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do type: if(defname in @macro_defs, do: :constant, else: :function), symbol: name_str, name: "#{name_str}/#{if(is_list(args), do: length(args), else: 0)}", - detail: defname, + detail: defname |> to_string, location: location, selection_location: head_location, children: [] @@ -262,7 +261,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do type: if(defname in @macro_defs, do: :constant, else: :function), symbol: name_str, name: "#{name_str}/#{if(is_list(args), do: length(args), else: 0)}", - detail: defname, + detail: defname |> to_string, location: location, selection_location: head_location, children: [] @@ -288,7 +287,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do %Info{ type: :class, name: "#{name}", - detail: :defrecord, + detail: :defrecord |> to_string, location: location |> Keyword.merge(Keyword.take(alias_location, [:line, :column])), children: children } @@ -299,7 +298,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do %Info{ type: :function, name: Macro.to_string(name), - detail: :test, + detail: :test |> to_string, location: location, children: [] } @@ -332,7 +331,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do %Info{ type: :function, name: Macro.to_string(name), - detail: :describe, + detail: :describe |> to_string, location: location, children: module_symbols } @@ -384,24 +383,31 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do location_to_range(info.location, text, nil) |> maybe_extend_range(selection_range) - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ name: info.name, detail: info.detail, kind: SymbolUtils.symbol_kind_to_code(info.type), range: range, - selectionRange: selection_range, + selection_range: selection_range, children: build_symbol_information_hierarchical(uri, text, info.children) } end defp maybe_extend_range( - Protocol.range(start_line, start_character, end_line, end_character), - Protocol.range( - selection_start_line, - selection_start_character, - selection_end_line, - selection_end_character - ) + %GenLSP.Structures.Range{ + start: %GenLSP.Structures.Position{line: start_line, character: start_character}, + end: %GenLSP.Structures.Position{line: end_line, character: end_character} + }, + %GenLSP.Structures.Range{ + start: %GenLSP.Structures.Position{ + line: selection_start_line, + character: selection_start_character + }, + end: %GenLSP.Structures.Position{ + line: selection_end_line, + character: selection_end_character + } + } ) do {extended_start_line, extended_start_character} = cond do @@ -427,12 +433,13 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do {end_line, end_character} end - Protocol.range( - extended_start_line, - extended_start_character, - extended_end_line, - extended_end_character - ) + %GenLSP.Structures.Range{ + start: %GenLSP.Structures.Position{ + line: extended_start_line, + character: extended_start_character + }, + end: %GenLSP.Structures.Position{line: extended_end_line, character: extended_end_character} + } end defp build_symbol_information_flat(uri, text, info, parent_name \\ nil) @@ -444,27 +451,27 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do case info.children do [_ | _] -> [ - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: info.name, kind: SymbolUtils.symbol_kind_to_code(info.type), - location: %{ + location: %GenLSP.Structures.Location{ uri: uri, range: location_to_range(info.location, text, nil) }, - containerName: parent_name + container_name: parent_name } | Enum.map(info.children, &build_symbol_information_flat(uri, text, &1, info.name)) ] _ -> - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: info.name, kind: SymbolUtils.symbol_kind_to_code(info.type), - location: %{ + location: %GenLSP.Structures.Location{ uri: uri, range: location_to_range(info.location, text, nil) }, - containerName: parent_name + container_name: parent_name } end end @@ -537,7 +544,10 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbols do {start_line, start_character} end - Protocol.range(start_line, start_character, end_line, end_character) + %GenLSP.Structures.Range{ + start: %GenLSP.Structures.Position{line: start_line, character: start_character}, + end: %GenLSP.Structures.Position{line: end_line, character: end_character} + } end defp extract_module_name(protocol: protocol, implementations: implementations) do diff --git a/apps/language_server/lib/language_server/providers/execute_command/apply_spec.ex b/apps/language_server/lib/language_server/providers/execute_command/apply_spec.ex index 4d9b41f8f..38d94e3c4 100644 --- a/apps/language_server/lib/language_server/providers/execute_command/apply_spec.ex +++ b/apps/language_server/lib/language_server/providers/execute_command/apply_spec.ex @@ -5,7 +5,7 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ApplySpec do """ alias ElixirLS.LanguageServer.{JsonRpc, SourceFile} - import ElixirLS.LanguageServer.Protocol + import ElixirLS.LanguageServer.RangeUtils alias ElixirLS.LanguageServer.Server require Logger @@ -81,18 +81,26 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ApplySpec do end edit_result = - JsonRpc.send_request("workspace/applyEdit", %{ - "label" => "Add @spec to #{mod}.#{fun}/#{arity}", - "edit" => %{ - "changes" => %{ - # we don't care about utf16 positions here as we send 0 - uri => [%{"range" => range(line - 1, 0, line - 1, 0), "newText" => formatted}] + JsonRpc.send_request(%GenLSP.Requests.WorkspaceApplyEdit{ + id: System.unique_integer([:positive]), + params: %GenLSP.Structures.ApplyWorkspaceEditParams{ + label: "Add @spec to #{mod}.#{fun}/#{arity}", + edit: %GenLSP.Structures.WorkspaceEdit{ + changes: %{ + # we don't care about utf16 positions here as we send 0 + uri => [ + %GenLSP.Structures.TextEdit{ + range: range(line - 1, 0, line - 1, 0), + new_text: formatted + } + ] + } } } }) case edit_result do - {:ok, %{"applied" => true}} -> + {:ok, %GenLSP.Structures.ApplyWorkspaceEditResult{applied: true}} -> {:ok, nil} other -> diff --git a/apps/language_server/lib/language_server/providers/execute_command/manipulate_pipes.ex b/apps/language_server/lib/language_server/providers/execute_command/manipulate_pipes.ex index 7d072cbcd..fec8609ae 100644 --- a/apps/language_server/lib/language_server/providers/execute_command/manipulate_pipes.ex +++ b/apps/language_server/lib/language_server/providers/execute_command/manipulate_pipes.ex @@ -5,11 +5,10 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipes do Returns a formatted source fragment. """ - import ElixirLS.LanguageServer.Protocol alias ElixirLS.LanguageServer.{JsonRpc, Server} alias ElixirLS.LanguageServer.SourceFile - alias ElixirLS.LanguageServer.Protocol.TextEdit + import ElixirLS.LanguageServer.RangeUtils alias __MODULE__.AST @@ -39,13 +38,16 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipes do from_pipe_at_cursor(source_file.text, line, col) end - with {:ok, %TextEdit{} = text_edit} <- processing_result, - {:ok, %{"applied" => true}} <- - JsonRpc.send_request("workspace/applyEdit", %{ - "label" => label, - "edit" => %{ - "changes" => %{ - uri => [text_edit] + with {:ok, %GenLSP.Structures.TextEdit{} = text_edit} <- processing_result, + {:ok, %GenLSP.Structures.ApplyWorkspaceEditResult{applied: true}} <- + JsonRpc.send_request(%GenLSP.Requests.WorkspaceApplyEdit{ + id: System.unique_integer([:positive]), + params: %GenLSP.Structures.ApplyWorkspaceEditParams{ + label: label, + edit: %GenLSP.Structures.WorkspaceEdit{ + changes: %{ + uri => [text_edit] + } } } }) do @@ -103,7 +105,7 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipes do with {:result, %{function_call: function_call, range: range}} when not is_nil(function_call) and not is_nil(range) <- {:result, result}, {:ok, piped_text} <- AST.to_pipe(function_call) do - text_edit = %TextEdit{newText: piped_text, range: range} + text_edit = %GenLSP.Structures.TextEdit{new_text: piped_text, range: range} {:ok, text_edit} else {:result, %{function_call: nil}} -> @@ -147,7 +149,7 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipes do with {:result, %{pipe_call: pipe_call, range: range}} when not is_nil(pipe_call) and not is_nil(range) <- {:result, result}, {:ok, unpiped_text} <- AST.from_pipe(pipe_call) do - text_edit = %TextEdit{newText: unpiped_text, range: range} + text_edit = %GenLSP.Structures.TextEdit{new_text: unpiped_text, range: range} {:ok, text_edit} else {:result, %{pipe_call: nil}} -> diff --git a/apps/language_server/lib/language_server/providers/folding_range.ex b/apps/language_server/lib/language_server/providers/folding_range.ex index 6409a609d..74999a9cc 100644 --- a/apps/language_server/lib/language_server/providers/folding_range.ex +++ b/apps/language_server/lib/language_server/providers/folding_range.ex @@ -46,7 +46,7 @@ defmodule ElixirLS.LanguageServer.Providers.FoldingRange do ## Notes Each pass may return ranges in any order. - But all ranges are valid, i.e. endLine > startLine. + But all ranges are valid, i.e. end_line > start_line. """ alias __MODULE__ @@ -56,13 +56,7 @@ defmodule ElixirLS.LanguageServer.Providers.FoldingRange do lines: [FoldingRange.Line.t()] } - @type t :: %{ - required(:startLine) => non_neg_integer(), - required(:endLine) => non_neg_integer(), - optional(:startCharacter?) => non_neg_integer(), - optional(:endCharacter?) => non_neg_integer(), - optional(:kind?) => :comment | :imports | :region - } + @type t :: GenLSP.Structures.FoldingRange.t() @doc """ Provides folding ranges for a source file @@ -79,8 +73,8 @@ defmodule ElixirLS.LanguageServer.Providers.FoldingRange do ...> \""" iex> FoldingRange.provide(%{text: text}) {:ok, [ - %{startLine: 0, endLine: 3, kind?: :region}, - %{startLine: 1, endLine: 2, kind?: :region} + %GenLSP.Structures.FoldingRange{start_line: 0, end_line: 3, kind: "region"}, + %GenLSP.Structures.FoldingRange{start_line: 1, end_line: 2, kind: "region"} ]} """ @@ -128,14 +122,14 @@ defmodule ElixirLS.LanguageServer.Providers.FoldingRange do defp merge_ranges_with_priorities(range_lists_with_priorities) do range_lists_with_priorities |> Enum.flat_map(fn {priority, ranges} -> Enum.zip(Stream.cycle([priority]), ranges) end) - |> Enum.group_by(fn {_priority, range} -> range.startLine end) + |> Enum.group_by(fn {_priority, range} -> range.start_line end) |> Enum.map(fn {_start, ranges_with_priority} -> {_priority, range} = ranges_with_priority - |> Enum.max_by(fn {priority, range} -> {priority, range.endLine} end) + |> Enum.max_by(fn {priority, range} -> {priority, range.end_line} end) range end) - |> Enum.sort_by(& &1.startLine) + |> Enum.sort_by(& &1.start_line) end end diff --git a/apps/language_server/lib/language_server/providers/folding_range/comment_block.ex b/apps/language_server/lib/language_server/providers/folding_range/comment_block.ex index ec1265e55..6a9812fe2 100644 --- a/apps/language_server/lib/language_server/providers/folding_range/comment_block.ex +++ b/apps/language_server/lib/language_server/providers/folding_range/comment_block.ex @@ -30,7 +30,7 @@ defmodule ElixirLS.LanguageServer.Providers.FoldingRange.CommentBlock do iex> FoldingRange.convert_text_to_input(text) iex> |> CommentBlock.provide_ranges() {:ok, [ - %{startLine: 2, endLine: 4, kind?: :comment} + %GenLSP.Structures.FoldingRange{start_line: 2, end_line: 4, kind: "comment"} ]} """ @spec provide_ranges(FoldingRange.input()) :: {:ok, [FoldingRange.t()]} @@ -67,12 +67,12 @@ defmodule ElixirLS.LanguageServer.Providers.FoldingRange.CommentBlock do {{{end_line, _}, _}, {{start_line, _}, _}} = group |> FoldingRange.Helpers.first_and_last_of_list() - %{ - startLine: start_line, + %GenLSP.Structures.FoldingRange{ + start_line: start_line, # We're not doing end_line - 1 on purpose. # It seems weird to show the first _and_ last line of a comment block. - endLine: end_line, - kind?: :comment + end_line: end_line, + kind: GenLSP.Enumerations.FoldingRangeKind.comment() } end end diff --git a/apps/language_server/lib/language_server/providers/folding_range/indentation.ex b/apps/language_server/lib/language_server/providers/folding_range/indentation.ex index b5697447a..aae082646 100644 --- a/apps/language_server/lib/language_server/providers/folding_range/indentation.ex +++ b/apps/language_server/lib/language_server/providers/folding_range/indentation.ex @@ -34,10 +34,10 @@ defmodule ElixirLS.LanguageServer.Providers.FoldingRange.Indentation do iex> FoldingRange.convert_text_to_input(text) ...> |> FoldingRange.Indentation.provide_ranges() {:ok, [ - %{startLine: 0, endLine: 12, kind?: :region}, - %{startLine: 1, endLine: 11, kind?: :region}, - %{startLine: 7, endLine: 9, kind?: :region}, - %{startLine: 2, endLine: 5, kind?: :region}, + %GenLSP.Structures.FoldingRange{start_line: 0, end_line: 12, kind: "region"}, + %GenLSP.Structures.FoldingRange{start_line: 1, end_line: 11, kind: "region"}, + %GenLSP.Structures.FoldingRange{start_line: 7, end_line: 9, kind: "region"}, + %GenLSP.Structures.FoldingRange{start_line: 2, end_line: 5, kind: "region"}, ]} Note that the empty lines 6 and 10 do not appear in the inner most ranges. @@ -103,10 +103,10 @@ defmodule ElixirLS.LanguageServer.Providers.FoldingRange.Indentation do defp pairs_to_ranges(pairs) do pairs |> Enum.map(fn {{r1, _}, {r2, _}} -> - %{ - startLine: r1, - endLine: r2 - 1, - kind?: :region + %GenLSP.Structures.FoldingRange{ + start_line: r1, + end_line: r2 - 1, + kind: GenLSP.Enumerations.FoldingRangeKind.region() } end) end diff --git a/apps/language_server/lib/language_server/providers/folding_range/special_token.ex b/apps/language_server/lib/language_server/providers/folding_range/special_token.ex index 7d89da5ae..70621d901 100644 --- a/apps/language_server/lib/language_server/providers/folding_range/special_token.ex +++ b/apps/language_server/lib/language_server/providers/folding_range/special_token.ex @@ -4,7 +4,7 @@ defmodule ElixirLS.LanguageServer.Providers.FoldingRange.SpecialToken do Several tokens, like `"..."`s, define ranges all on their own. This module converts these tokens to ranges. - These ranges can be either `kind?: :comment` or `kind?: :region`. + These ranges can be either `kind: "comment"` or `kind: "region"`. """ alias ElixirLS.LanguageServer.Providers.FoldingRange @@ -41,8 +41,8 @@ defmodule ElixirLS.LanguageServer.Providers.FoldingRange.SpecialToken do iex> FoldingRange.convert_text_to_input(text) ...> |> FoldingRange.SpecialToken.provide_ranges() {:ok, [ - %{startLine: 5, endLine: 6, kind?: :region}, - %{startLine: 2, endLine: 3, kind?: :region}, + %GenLSP.Structures.FoldingRange{start_line: 5, end_line: 6, kind: "region"}, + %GenLSP.Structures.FoldingRange{start_line: 2, end_line: 3, kind: "region"}, ]} """ @spec provide_ranges(FoldingRange.input()) :: {:ok, [FoldingRange.t()]} @@ -114,17 +114,21 @@ defmodule ElixirLS.LanguageServer.Providers.FoldingRange.SpecialToken do classify_group(first, last) end) |> Enum.map(fn {start_line, end_line, kind} -> - %{ - startLine: start_line, - endLine: end_line - 1, - kind?: kind + %GenLSP.Structures.FoldingRange{ + start_line: start_line, + end_line: end_line - 1, + kind: kind } end) - |> Enum.filter(fn range -> range.endLine > range.startLine end) + |> Enum.filter(fn range -> range.end_line > range.start_line end) end defp classify_group({kind, {start_line, _, _}, _}, {_, {end_line, _, _}, _}) do - kind = if kind == :at_op, do: :comment, else: :region + kind = + if kind == :at_op, + do: GenLSP.Enumerations.FoldingRangeKind.comment(), + else: GenLSP.Enumerations.FoldingRangeKind.region() + {start_line, end_line, kind} end end diff --git a/apps/language_server/lib/language_server/providers/folding_range/token_pairs.ex b/apps/language_server/lib/language_server/providers/folding_range/token_pairs.ex index 572237740..f9d507004 100644 --- a/apps/language_server/lib/language_server/providers/folding_range/token_pairs.ex +++ b/apps/language_server/lib/language_server/providers/folding_range/token_pairs.ex @@ -3,7 +3,7 @@ defmodule ElixirLS.LanguageServer.Providers.FoldingRange.TokenPair do Code folding based on pairs of tokens Certain pairs of tokens, like `do` and `end`, natrually define ranges. - These ranges all have `kind?: :region`. + These ranges all have `kind: "region"`. Note that we exclude the line that the 2nd of the pair, e.g. `end`, is on. This is so that when collapsed, both tokens are visible. @@ -43,8 +43,8 @@ defmodule ElixirLS.LanguageServer.Providers.FoldingRange.TokenPair do iex> FoldingRange.convert_text_to_input(text) ...> |> TokenPair.provide_ranges() {:ok, [ - %{startLine: 0, endLine: 3, kind?: :region}, - %{startLine: 1, endLine: 2, kind?: :region} + %GenLSP.Structures.FoldingRange{start_line: 0, end_line: 3, kind: "region"}, + %GenLSP.Structures.FoldingRange{start_line: 1, end_line: 2, kind: "region"} ]} """ @spec provide_ranges(FoldingRange.input()) :: {:ok, [FoldingRange.t()]} @@ -106,7 +106,11 @@ defmodule ElixirLS.LanguageServer.Providers.FoldingRange.TokenPair do end) |> Enum.filter(fn {start_line, end_line} -> end_line > start_line end) |> Enum.map(fn {start_line, end_line} -> - %{startLine: start_line, endLine: end_line, kind?: :region} + %GenLSP.Structures.FoldingRange{ + start_line: start_line, + end_line: end_line, + kind: GenLSP.Enumerations.FoldingRangeKind.region() + } end) end end diff --git a/apps/language_server/lib/language_server/providers/formatting.ex b/apps/language_server/lib/language_server/providers/formatting.ex index 7f9ade78e..b8de0e477 100644 --- a/apps/language_server/lib/language_server/providers/formatting.ex +++ b/apps/language_server/lib/language_server/providers/formatting.ex @@ -1,8 +1,7 @@ defmodule ElixirLS.LanguageServer.Providers.Formatting do - import ElixirLS.LanguageServer.Protocol, only: [range: 4] - alias ElixirLS.LanguageServer.Protocol.TextEdit alias ElixirLS.LanguageServer.SourceFile alias ElixirLS.LanguageServer.JsonRpc + import ElixirLS.LanguageServer.RangeUtils require Logger def format(%SourceFile{} = source_file, uri = "file:" <> _, project_dir, mix_project?) @@ -113,17 +112,31 @@ defmodule ElixirLS.LanguageServer.Providers.Formatting do myers_diff_to_text_edits(rest, advance_pos({line, col}, str), edits) {{:ins, str}, _} -> - edit = %TextEdit{range: range(line, col, line, col), newText: str} + edit = %GenLSP.Structures.TextEdit{ + range: range(line, col, line, col), + new_text: str + } + myers_diff_to_text_edits(rest, {line, col}, [edit | edits]) {{:del, del_str}, [{:ins, ins_str} | rest]} -> {end_line, end_col} = advance_pos({line, col}, del_str) - edit = %TextEdit{range: range(line, col, end_line, end_col), newText: ins_str} + + edit = %GenLSP.Structures.TextEdit{ + range: range(line, col, end_line, end_col), + new_text: ins_str + } + myers_diff_to_text_edits(rest, {end_line, end_col}, [edit | edits]) {{:del, str}, _} -> {end_line, end_col} = advance_pos({line, col}, str) - edit = %TextEdit{range: range(line, col, end_line, end_col), newText: ""} + + edit = %GenLSP.Structures.TextEdit{ + range: range(line, col, end_line, end_col), + new_text: "" + } + myers_diff_to_text_edits(rest, {end_line, end_col}, [edit | edits]) end end diff --git a/apps/language_server/lib/language_server/providers/hover.ex b/apps/language_server/lib/language_server/providers/hover.ex index d6b5430e5..1976622d1 100644 --- a/apps/language_server/lib/language_server/providers/hover.ex +++ b/apps/language_server/lib/language_server/providers/hover.ex @@ -1,6 +1,5 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do alias ElixirLS.LanguageServer.{SourceFile, DocLinks, Parser} - import ElixirLS.LanguageServer.Protocol alias ElixirLS.LanguageServer.MarkdownUtils alias ElixirLS.LanguageServer.Providers.Hover.Docs require Logger @@ -18,9 +17,9 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do %{docs: docs, range: es_range} -> lines = SourceFile.lines(source_file.text) - %{ - "contents" => contents(docs), - "range" => build_range(lines, es_range) + %GenLSP.Structures.Hover{ + contents: contents(docs), + range: build_range(lines, es_range) } end @@ -30,12 +29,18 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do ## Helpers def build_range(lines, %{begin: {begin_line, begin_char}, end: {end_line, end_char}}) do - range( - begin_line - 1, - SourceFile.elixir_character_to_lsp(lines |> Enum.at(begin_line - 1, ""), begin_char), - end_line - 1, - SourceFile.elixir_character_to_lsp(lines |> Enum.at(end_line - 1, ""), end_char) - ) + %GenLSP.Structures.Range{ + start: %GenLSP.Structures.Position{ + line: begin_line - 1, + character: + SourceFile.elixir_character_to_lsp(lines |> Enum.at(begin_line - 1, ""), begin_char) + }, + end: %GenLSP.Structures.Position{ + line: end_line - 1, + character: + SourceFile.elixir_character_to_lsp(lines |> Enum.at(end_line - 1, ""), end_char) + } + } end defp contents(docs) do @@ -44,8 +49,8 @@ defmodule ElixirLS.LanguageServer.Providers.Hover do |> Enum.map(&format_doc/1) |> MarkdownUtils.join_with_horizontal_rule() - %{ - kind: "markdown", + %GenLSP.Structures.MarkupContent{ + kind: GenLSP.Enumerations.MarkupKind.markdown(), value: markdown_value } end diff --git a/apps/language_server/lib/language_server/providers/hover/docs.ex b/apps/language_server/lib/language_server/providers/hover/docs.ex index dd161ad4d..3873cd9d2 100644 --- a/apps/language_server/lib/language_server/providers/hover/docs.ex +++ b/apps/language_server/lib/language_server/providers/hover/docs.ex @@ -251,9 +251,6 @@ defmodule ElixirLS.LanguageServer.Providers.Hover.Docs do {line, column} = context.end call_arity = Metadata.get_call_arity(metadata, mod, fun, line, column) || :any get_all_docs({mod, fun, call_arity}, metadata, env, kind) - - _ -> - nil end end diff --git a/apps/language_server/lib/language_server/providers/implementation.ex b/apps/language_server/lib/language_server/providers/implementation.ex index f570a68a5..54300d8e6 100644 --- a/apps/language_server/lib/language_server/providers/implementation.ex +++ b/apps/language_server/lib/language_server/providers/implementation.ex @@ -17,7 +17,7 @@ defmodule ElixirLS.LanguageServer.Providers.Implementation do results = for location <- locations, - do: Protocol.Location.new(location, uri, source_file.text, project_dir) + do: Protocol.Location.to_gen_lsp(location, uri, source_file.text, project_dir) {:ok, results} end diff --git a/apps/language_server/lib/language_server/providers/on_type_formatting.ex b/apps/language_server/lib/language_server/providers/on_type_formatting.ex index a14205a84..a339211d0 100644 --- a/apps/language_server/lib/language_server/providers/on_type_formatting.ex +++ b/apps/language_server/lib/language_server/providers/on_type_formatting.ex @@ -8,7 +8,7 @@ defmodule ElixirLS.LanguageServer.Providers.OnTypeFormatting do """ alias ElixirLS.LanguageServer.SourceFile - import ElixirLS.LanguageServer.Protocol + import ElixirLS.LanguageServer.RangeUtils def format(%SourceFile{} = source_file, line, character, "\n", _options) when line >= 1 do # we don't care about utf16 positions here as we only pass character back to client @@ -41,7 +41,7 @@ defmodule ElixirLS.LanguageServer.Providers.OnTypeFormatting do edited_text = SourceFile.apply_edit(source_file.text, range, new_text) if indentation_suggests_edit? or terminators_correct?(edited_text) do - {:ok, [%{"range" => range, "newText" => new_text}]} + {:ok, [%GenLSP.Structures.TextEdit{range: range, new_text: new_text}]} else {:ok, nil} end @@ -76,9 +76,15 @@ defmodule ElixirLS.LanguageServer.Providers.OnTypeFormatting do defp insert_end_edit(indentation, line, character, insert_on_next_line?) do # we don't care about utf16 positions here as we either use 0 or what the client sent if insert_on_next_line? do - {range(line + 1, 0, line + 1, 0), "#{indentation}end\n"} + { + range(line + 1, 0, line + 1, 0), + "#{indentation}end\n" + } else - {range(line, character, line, character), "\n#{indentation}end"} + { + range(line, character, line, character), + "\n#{indentation}end" + } end end end diff --git a/apps/language_server/lib/language_server/providers/plugins/plugin.ex b/apps/language_server/lib/language_server/providers/plugins/plugin.ex index 8ee3ae065..fafc45689 100644 --- a/apps/language_server/lib/language_server/providers/plugins/plugin.ex +++ b/apps/language_server/lib/language_server/providers/plugins/plugin.ex @@ -1,7 +1,7 @@ defmodule ElixirLS.LanguageServer.Plugin do alias ElixirSense.Core.Metadata alias ElixirSense.Core.State - @type suggestion :: ElixirLS.LanguageServer.Providers.Suggestion.generic() + @type suggestion :: ElixirLS.LanguageServer.Providers.Completion.Suggestion.generic() @type context :: term @type acc :: %{context: context(), result: list(suggestion())} diff --git a/apps/language_server/lib/language_server/providers/references.ex b/apps/language_server/lib/language_server/providers/references.ex index e03302128..f180761bb 100644 --- a/apps/language_server/lib/language_server/providers/references.ex +++ b/apps/language_server/lib/language_server/providers/references.ex @@ -10,7 +10,6 @@ defmodule ElixirLS.LanguageServer.Providers.References do """ alias ElixirLS.LanguageServer.{SourceFile, Build, Parser} - import ElixirLS.LanguageServer.Protocol alias ElixirLS.LanguageServer.Providers.References.Locator require Logger @@ -46,11 +45,14 @@ defmodule ElixirLS.LanguageServer.Providers.References do {end_line, end_column} = SourceFile.elixir_position_to_lsp(text, {ref.range.end.line, ref.range.end.column}) - range = range(start_line, start_column, end_line, end_column) + uri = build_uri(ref, current_file_uri, project_dir) - %{ - "range" => range, - "uri" => build_uri(ref, current_file_uri, project_dir) + %GenLSP.Structures.Location{ + uri: uri, + range: %GenLSP.Structures.Range{ + start: %GenLSP.Structures.Position{line: start_line, character: start_column}, + end: %GenLSP.Structures.Position{line: end_line, character: end_column} + } } {:error, :nofile} -> diff --git a/apps/language_server/lib/language_server/providers/selection_ranges.ex b/apps/language_server/lib/language_server/providers/selection_ranges.ex index e3f1d6d65..35ac08c45 100644 --- a/apps/language_server/lib/language_server/providers/selection_ranges.ex +++ b/apps/language_server/lib/language_server/providers/selection_ranges.ex @@ -19,7 +19,6 @@ defmodule ElixirLS.LanguageServer.Providers.SelectionRanges do alias ElixirLS.LanguageServer.SourceFile alias ElixirLS.LanguageServer.Providers.FoldingRange - import ElixirLS.LanguageServer.Protocol import ElixirLS.LanguageServer.RangeUtils alias ElixirLS.LanguageServer.AstUtils alias ElixirSense.Core.Normalized.Code, as: NormalizedCode @@ -67,7 +66,7 @@ defmodule ElixirLS.LanguageServer.Providers.SelectionRanges do |> Enum.map(&FoldingRange.Indentation.extract_cell/1) |> FoldingRange.Indentation.pair_cells() - for %{"line" => line, "character" => character} <- positions do + for %GenLSP.Structures.Position{line: line, character: character} <- positions do {line, character} = SourceFile.lsp_position_to_elixir(lines, {line, character}) # for convenance the code in this module uses 0 based indexing {line, character} = {line - 1, character - 1} @@ -122,9 +121,12 @@ defmodule ElixirLS.LanguageServer.Providers.SelectionRanges do {end_line_elixir + 1, end_character_elixir + 1} ) - %{ - "range" => range(start_line_lsp, start_character_lsp, end_line_lsp, end_character_lsp), - "parent" => parent + %GenLSP.Structures.SelectionRange{ + range: %GenLSP.Structures.Range{ + start: %GenLSP.Structures.Position{line: start_line_lsp, character: start_character_lsp}, + end: %GenLSP.Structures.Position{line: end_line_lsp, character: end_character_lsp} + }, + parent: parent } end) end diff --git a/apps/language_server/lib/language_server/providers/signature_help.ex b/apps/language_server/lib/language_server/providers/signature_help.ex index a66a77428..bea453911 100644 --- a/apps/language_server/lib/language_server/providers/signature_help.ex +++ b/apps/language_server/lib/language_server/providers/signature_help.ex @@ -16,10 +16,10 @@ defmodule ElixirLS.LanguageServer.Providers.SignatureHelp do response = case Signature.signature(source_file.text, line, character, metadata: metadata) do %{active_param: active_param, signatures: signatures} -> - %{ - "activeSignature" => 0, - "activeParameter" => active_param, - "signatures" => Enum.map(signatures, &signature_response/1) + %GenLSP.Structures.SignatureHelp{ + active_signature: 0, + active_parameter: active_param, + signatures: Enum.map(signatures, &signature_response/1) } :none -> @@ -38,52 +38,67 @@ defmodule ElixirLS.LanguageServer.Providers.SignatureHelp do metadata: metadata } = signature ) do - params_info = for param <- params, do: %{"label" => param} + params_info = for param <- params, do: %GenLSP.Structures.ParameterInformation{label: param} label = "#{name}(#{Enum.join(params, ", ")})" - response = %{"label" => label, "parameters" => params_info} - response = + base_signature = %GenLSP.Structures.SignatureInformation{ + label: label, + parameters: params_info + } + + base_signature = case signature do %{active_param: active_param} -> - Map.put(response, "activeParameter", active_param) + %{base_signature | active_parameter: active_param} _ -> - response + base_signature end case {spec, documentation} do {"", ""} -> - put_metadata(response, metadata) + put_metadata(base_signature, metadata) {"", _} -> - put_documentation(response, documentation) + put_documentation(base_signature, documentation) |> put_metadata(metadata) {_, _} -> spec_str = SourceFile.format_spec(spec, line_length: 42) - put_documentation(response, "#{documentation}\n#{spec_str}") + put_documentation(base_signature, "#{documentation}\n#{spec_str}") |> put_metadata(metadata) end end - defp put_documentation(response, documentation) do - Map.put(response, "documentation", %{"kind" => "markdown", "value" => documentation}) + defp put_documentation(signature = %GenLSP.Structures.SignatureInformation{}, documentation) do + %{ + signature + | documentation: %GenLSP.Structures.MarkupContent{ + kind: GenLSP.Enumerations.MarkupKind.markdown(), + value: documentation + } + } end - defp put_metadata(response, metadata) do + defp put_metadata(signature = %GenLSP.Structures.SignatureInformation{}, metadata) do if metadata do metadata_md = MarkdownUtils.get_metadata_md(metadata) if metadata_md != "" do - current_docs = get_in(response, ["documentation", "value"]) || "" - put_documentation(response, metadata_md <> "\n\n" <> current_docs) + current_docs = + case signature.documentation do + %GenLSP.Structures.MarkupContent{value: value} -> value + _ -> "" + end + + put_documentation(signature, metadata_md <> "\n\n" <> current_docs) else - response + signature end else - response + signature end end end diff --git a/apps/language_server/lib/language_server/providers/symbol_utils.ex b/apps/language_server/lib/language_server/providers/symbol_utils.ex index dec12df2a..fb675f7eb 100644 --- a/apps/language_server/lib/language_server/providers/symbol_utils.ex +++ b/apps/language_server/lib/language_server/providers/symbol_utils.ex @@ -1,31 +1,31 @@ defmodule ElixirLS.LanguageServer.Providers.SymbolUtils do @symbol_enum %{ - file: 1, - module: 2, - namespace: 3, - package: 4, - class: 5, - method: 6, - property: 7, - field: 8, - constructor: 9, - enum: 10, - interface: 11, - function: 12, - variable: 13, - constant: 14, - string: 15, - number: 16, - boolean: 17, - array: 18, - object: 19, - key: 20, - null: 21, - enum_member: 22, - struct: 23, - event: 24, - operator: 25, - type_parameter: 26 + file: GenLSP.Enumerations.SymbolKind.file(), + module: GenLSP.Enumerations.SymbolKind.module(), + namespace: GenLSP.Enumerations.SymbolKind.namespace(), + package: GenLSP.Enumerations.SymbolKind.package(), + class: GenLSP.Enumerations.SymbolKind.class(), + method: GenLSP.Enumerations.SymbolKind.method(), + property: GenLSP.Enumerations.SymbolKind.property(), + field: GenLSP.Enumerations.SymbolKind.field(), + constructor: GenLSP.Enumerations.SymbolKind.constructor(), + enum: GenLSP.Enumerations.SymbolKind.enum(), + interface: GenLSP.Enumerations.SymbolKind.interface(), + function: GenLSP.Enumerations.SymbolKind.function(), + variable: GenLSP.Enumerations.SymbolKind.variable(), + constant: GenLSP.Enumerations.SymbolKind.constant(), + string: GenLSP.Enumerations.SymbolKind.string(), + number: GenLSP.Enumerations.SymbolKind.number(), + boolean: GenLSP.Enumerations.SymbolKind.boolean(), + array: GenLSP.Enumerations.SymbolKind.array(), + object: GenLSP.Enumerations.SymbolKind.object(), + key: GenLSP.Enumerations.SymbolKind.key(), + null: GenLSP.Enumerations.SymbolKind.null(), + enum_member: GenLSP.Enumerations.SymbolKind.enum_member(), + struct: GenLSP.Enumerations.SymbolKind.struct(), + event: GenLSP.Enumerations.SymbolKind.event(), + operator: GenLSP.Enumerations.SymbolKind.operator(), + type_parameter: GenLSP.Enumerations.SymbolKind.type_parameter() } for {kind, code} <- @symbol_enum do diff --git a/apps/language_server/lib/language_server/providers/workspace_symbols.ex b/apps/language_server/lib/language_server/providers/workspace_symbols.ex index cecafa102..ec554662f 100644 --- a/apps/language_server/lib/language_server/providers/workspace_symbols.ex +++ b/apps/language_server/lib/language_server/providers/workspace_symbols.ex @@ -6,6 +6,7 @@ defmodule ElixirLS.LanguageServer.Providers.WorkspaceSymbols do """ use GenServer + alias ElixirLS.LanguageServer.ClientCapabilities alias ElixirLS.LanguageServer.ErlangSourceFile alias ElixirLS.LanguageServer.SourceFile alias ElixirLS.LanguageServer.Providers.SymbolUtils @@ -14,26 +15,7 @@ defmodule ElixirLS.LanguageServer.Providers.WorkspaceSymbols do require ElixirSense.Core.Introspection, as: Introspection require Logger - @type position_t :: %{ - line: non_neg_integer, - character: non_neg_integer - } - - @type range_t :: %{ - start: position_t, - end: position_t - } - - @type location_t :: %{ - uri: String.t(), - range: range_t - } - - @type symbol_information_t :: %{ - kind: integer, - name: String.t(), - location: location_t - } + @type symbol_information_t :: GenLSP.Structures.WorkspaceSymbol.t() @typep key_t :: :modules @typep symbol_t :: module | {module, atom, non_neg_integer} @@ -151,12 +133,9 @@ defmodule ElixirLS.LanguageServer.Providers.WorkspaceSymbols do @impl GenServer def handle_cast({:notify_settings_stored, project_dir}, state) do - # as of LSP 3.17 only one tag is defined and clients are required to silently ignore unknown tags + # as of LSP 3.18 only one tag is defined and clients are required to silently ignore unknown tags # so there's no need to pass the list - tag_support = - :persistent_term.get(:language_server_client_capabilities)["workspace"]["symbol"][ - "tagSupport" - ] != nil + tag_support = ClientCapabilities.workspace_symbol_tag_support?() {:noreply, %{state | project_dir: project_dir, tag_support: tag_support}} end @@ -640,30 +619,25 @@ defmodule ElixirLS.LanguageServer.Providers.WorkspaceSymbols do @spec build_result(atom, symbol_t, String.t(), :erl_anno.anno(), map(), String.t(), boolean) :: symbol_information_t defp build_result(key, symbol, path, annotation, metadata, project_dir, tag_support) do - res = %{ - kind: @symbol_codes |> Map.fetch!(key), - name: symbol_name(key, symbol), - location: %{ - uri: SourceFile.Path.to_uri(path, project_dir), - range: build_range(annotation) - } + range = build_range(annotation) + + location = %GenLSP.Structures.Location{ + uri: SourceFile.Path.to_uri(path, project_dir), + range: range } container_name = container_name(key, symbol) + symbol_kind_code = @symbol_codes |> Map.fetch!(key) - res = - if container_name do - Map.put(res, :containerName, container_name) - else - res - end + tags = if tag_support, do: metadata_to_tags(metadata), else: nil - if tag_support do - tags = metadata_to_tags(metadata) - Map.put(res, :tags, tags) - else - res - end + %GenLSP.Structures.WorkspaceSymbol{ + kind: symbol_kind_code, + name: symbol_name(key, symbol), + location: location, + container_name: container_name, + tags: tags + } end @module_kinds [:module, :interface, :struct] @@ -696,14 +670,14 @@ defmodule ElixirLS.LanguageServer.Providers.WorkspaceSymbols do inspect(module) end - @spec build_range(:erl_anno.anno()) :: range_t + @spec build_range(:erl_anno.anno()) :: GenLSP.Structures.Range.t() defp build_range(annotation) do line = max(:erl_anno.line(annotation), 1) - 1 # we don't care about utf16 positions here as we send 0 # it's not worth to present column info here - %{ - start: %{line: line, character: 0}, - end: %{line: line + 1, character: 0} + %GenLSP.Structures.Range{ + start: %GenLSP.Structures.Position{line: line, character: 0}, + end: %GenLSP.Structures.Position{line: line + 1, character: 0} } end diff --git a/apps/language_server/lib/language_server/range_utils.ex b/apps/language_server/lib/language_server/range_utils.ex index f10764fa5..f8905af41 100644 --- a/apps/language_server/lib/language_server/range_utils.ex +++ b/apps/language_server/lib/language_server/range_utils.ex @@ -3,7 +3,20 @@ defmodule ElixirLS.LanguageServer.RangeUtils do Utilities for working with ranges. """ - import ElixirLS.LanguageServer.Protocol + defmacro range(start_line, start_character, end_line, end_character) do + quote do + %GenLSP.Structures.Range{ + start: %GenLSP.Structures.Position{ + line: unquote(start_line), + character: unquote(start_character) + }, + end: %GenLSP.Structures.Position{ + line: unquote(end_line), + character: unquote(end_character) + } + } + end + end # this function differs from the one in SourceFile - it returns utf8 ranges def full_range(lines = [_ | _]) do diff --git a/apps/language_server/lib/language_server/server.ex b/apps/language_server/lib/language_server/server.ex index 8236347b2..def4713b8 100644 --- a/apps/language_server/lib/language_server/server.ex +++ b/apps/language_server/lib/language_server/server.ex @@ -21,7 +21,7 @@ defmodule ElixirLS.LanguageServer.Server do alias ElixirLS.LanguageServer.{ SourceFile, Build, - Protocol, + ClientCapabilities, JsonRpc, Dialyzer, DialyzerIncremental, @@ -52,14 +52,12 @@ defmodule ElixirLS.LanguageServer.Server do alias ElixirLS.Utils.Launch alias ElixirLS.LanguageServer.Tracer alias ElixirLS.Utils.MixfileHelpers - - use Protocol + import ElixirLS.LanguageServer.JsonRpc, only: [notification: 1, request: 2, request: 3] defstruct [ :server_instance_id, :build_ref, :dialyzer_sup, - :client_capabilities, :root_uri, :project_dir, :settings, @@ -204,7 +202,7 @@ defmodule ElixirLS.LanguageServer.Server do requests_ids_by_pid = if popped_request do - {pid, ref, command, start_time} = popped_request + {pid, ref, command, start_time, request_module} = popped_request # we are no longer interested in :DOWN message Process.demonitor(ref, [:flush]) @@ -228,7 +226,30 @@ defmodule ElixirLS.LanguageServer.Server do {:ok, result} -> elapsed = System.monotonic_time(:millisecond) - start_time - JsonRpc.respond(id, result) + + # Use request module's result schematic if available (GenLSP requests) + response_body = + if function_exported?(request_module, :result, 0) do + dumped_body = + case SchematicV.dump(request_module.result(), result) do + {:ok, dumped_body} -> + dumped_body + + {:error, error} -> + IO.puts( + :stderr, + "Error dumping result: #{inspect(error)} for #{inspect(result)}" + ) + + nil + end + + dumped_body + else + result + end + + JsonRpc.respond(id, response_body) JsonRpc.telemetry( "lsp_request", @@ -318,7 +339,16 @@ defmodule ElixirLS.LanguageServer.Server do state = %__MODULE__{received_shutdown?: false, server_instance_id: server_instance_id} ) when is_initialized(server_instance_id) do - new_state = handle_notification(packet, state) + struct = + case GenLSP.Notifications.new(packet) do + {:ok, struct} -> + struct + + {:error, "unexpected notification payload"} -> + packet + end + + new_state = handle_notification(struct, state) {:noreply, new_state} end @@ -327,7 +357,16 @@ defmodule ElixirLS.LanguageServer.Server do def handle_cast({:receive_packet, notification(_) = packet}, state = %__MODULE__{}) do case packet do notification("exit") -> - new_state = handle_notification(packet, state) + struct = + case GenLSP.Notifications.new(packet) do + {:ok, struct} -> + struct + + {:error, "unexpected notification payload"} -> + packet + end + + new_state = handle_notification(struct, state) {:noreply, new_state} @@ -427,7 +466,12 @@ defmodule ElixirLS.LanguageServer.Server do updated_requests = if id do - {{^pid, ^ref, command, _start_time}, updated_requests} = Map.pop!(requests, id) + {command, updated_requests} = + case Map.pop!(requests, id) do + {{^pid, ^ref, command, _start_time, _request_module}, updated_requests} -> + {command, updated_requests} + end + error_msg = Exception.format_exit(reason) JsonRpc.respond_with_error(id, :internal_error, error_msg) @@ -454,7 +498,7 @@ defmodule ElixirLS.LanguageServer.Server do ## Helpers - defp handle_notification(notification("initialized"), state = %__MODULE__{}) do + defp handle_notification(%GenLSP.Notifications.Initialized{}, state = %__MODULE__{}) do # according to https://github.com/microsoft/language-server-protocol/issues/567#issuecomment-1060605611 # this is the best point to pull configuration @@ -466,11 +510,7 @@ defmodule ElixirLS.LanguageServer.Server do end supports_dynamic_configuration_change_registration = - get_in(state.client_capabilities, [ - "workspace", - "didChangeConfiguration", - "dynamicRegistration" - ]) + ClientCapabilities.supports_dynamic_configuration_change_registration?() if supports_dynamic_configuration_change_registration do Logger.info("Registering for workspace/didChangeConfiguration notifications") @@ -480,11 +520,7 @@ defmodule ElixirLS.LanguageServer.Server do end supports_dynamic_file_watcher_registration = - get_in(state.client_capabilities, [ - "workspace", - "didChangeWatchedFiles", - "dynamicRegistration" - ]) + ClientCapabilities.supports_dynamic_file_watcher_registration?() if supports_dynamic_file_watcher_registration do Logger.info("Registering for workspace/didChangeWatchedFiles notifications") @@ -497,14 +533,23 @@ defmodule ElixirLS.LanguageServer.Server do end defp handle_notification( - cancel_request(id), + %GenLSP.Notifications.DollarCancelRequest{ + params: %GenLSP.Structures.CancelParams{ + id: id + } + }, %__MODULE__{requests: requests, requests_ids_by_pid: requests_ids_by_pid} = state ) do {request, updated_requests} = Map.pop(requests, id) updated_requests_ids_by_pid = if request do - {pid, ref, _command, _start_time} = request + {pid, ref} = + case request do + {pid, ref, _command, _start_time} -> {pid, ref} + {pid, ref, _command, _start_time, _request_module} -> {pid, ref} + end + # we are no longer interested in :DOWN message Process.demonitor(ref, [:flush]) Process.exit(pid, :cancelled) @@ -521,7 +566,14 @@ defmodule ElixirLS.LanguageServer.Server do # We don't start performing builds until we receive settings from the client in case they've set # the `projectDir` or `mixEnv` settings. # note that clients supporting `workspace/configuration` will send nil and we need to pull - defp handle_notification(did_change_configuration(changed_settings), state = %__MODULE__{}) do + defp handle_notification( + %GenLSP.Notifications.WorkspaceDidChangeConfiguration{ + params: %GenLSP.Structures.DidChangeConfigurationParams{ + settings: changed_settings + } + }, + state = %__MODULE__{} + ) do Logger.info("Received workspace/didChangeConfiguration") prev_settings = state.settings || %{} @@ -547,7 +599,7 @@ defmodule ElixirLS.LanguageServer.Server do end end - defp handle_notification(notification("exit"), state = %__MODULE__{}) do + defp handle_notification(%GenLSP.Notifications.Exit{}, state = %__MODULE__{}) do code = if state.received_shutdown?, do: 0, else: 1 unless :persistent_term.get(:language_server_test_mode, false) do @@ -559,7 +611,19 @@ defmodule ElixirLS.LanguageServer.Server do state end - defp handle_notification(did_open(uri, language_id, version, text), state = %__MODULE__{}) do + defp handle_notification( + %GenLSP.Notifications.TextDocumentDidOpen{ + params: %GenLSP.Structures.DidOpenTextDocumentParams{ + text_document: %GenLSP.Structures.TextDocumentItem{ + uri: uri, + language_id: language_id, + version: version, + text: text + } + } + }, + state = %__MODULE__{} + ) do if Map.has_key?(state.source_files, uri) do # An open notification must not be sent more than once without a corresponding # close notification send before @@ -590,7 +654,16 @@ defmodule ElixirLS.LanguageServer.Server do end end - defp handle_notification(did_close(uri), state = %__MODULE__{}) do + defp handle_notification( + %GenLSP.Notifications.TextDocumentDidClose{ + params: %GenLSP.Structures.DidCloseTextDocumentParams{ + text_document: %GenLSP.Structures.TextDocumentIdentifier{ + uri: uri + } + } + }, + state = %__MODULE__{} + ) do if not Map.has_key?(state.source_files, uri) do # A close notification requires a previous open notification to be sent Logger.warning( @@ -611,7 +684,18 @@ defmodule ElixirLS.LanguageServer.Server do end end - defp handle_notification(did_change(uri, version, content_changes), state = %__MODULE__{}) do + defp handle_notification( + %GenLSP.Notifications.TextDocumentDidChange{ + params: %GenLSP.Structures.DidChangeTextDocumentParams{ + text_document: %GenLSP.Structures.VersionedTextDocumentIdentifier{ + uri: uri, + version: version + }, + content_changes: content_changes + } + }, + state = %__MODULE__{} + ) do if not Map.has_key?(state.source_files, uri) do # The source file was not marked as open either due to a bug in the # client or a restart of the server. So just ignore the message and do @@ -655,7 +739,16 @@ defmodule ElixirLS.LanguageServer.Server do end end - defp handle_notification(did_save(uri), state = %__MODULE__{}) do + defp handle_notification( + %GenLSP.Notifications.TextDocumentDidSave{ + params: %GenLSP.Structures.DidSaveTextDocumentParams{ + text_document: %GenLSP.Structures.TextDocumentIdentifier{ + uri: uri + } + } + }, + state = %__MODULE__{} + ) do if not Map.has_key?(state.source_files, uri) do Logger.warning( "Received textDocument/didSave for file that is not open. Received uri: #{inspect(uri)}" @@ -670,18 +763,22 @@ defmodule ElixirLS.LanguageServer.Server do end defp handle_notification( - did_change_watched_files(changes), + %GenLSP.Notifications.WorkspaceDidChangeWatchedFiles{ + params: %GenLSP.Structures.DidChangeWatchedFilesParams{ + changes: changes + } + }, state = %__MODULE__{project_dir: project_dir} ) when is_binary(project_dir) do - changes = Enum.filter(changes, &match?(%{"uri" => "file:" <> _}, &1)) + changes = Enum.filter(changes, &String.starts_with?(&1.uri, "file:")) # `settings` may not always be available here, like during testing additional_watched_extensions = Map.get(state.settings || %{}, "additionalWatchedExtensions", []) needs_build = - Enum.any?(changes, fn %{"uri" => uri = "file:" <> _, "type" => type} -> + Enum.any?(changes, fn %GenLSP.Structures.FileEvent{uri: uri, type: type} -> path = SourceFile.Path.from_uri(uri) relative_path = Path.relative_to(path, state.project_dir) @@ -689,27 +786,32 @@ defmodule ElixirLS.LanguageServer.Server do first_path_segment not in [".elixir_ls", "_build"] and Path.extname(path) in (additional_watched_extensions ++ @default_watched_extensions) and - (type in [1, 3] or not Map.has_key?(state.source_files, uri) or + (type in [ + GenLSP.Enumerations.FileChangeType.created(), + GenLSP.Enumerations.FileChangeType.deleted() + ] or not Map.has_key?(state.source_files, uri) or state.source_files[uri].dirty?) end) deleted_paths = - for change <- changes, - change["type"] == 3, - do: SourceFile.Path.from_uri(change["uri"]) + for change = %GenLSP.Structures.FileEvent{} <- changes, + change.type == GenLSP.Enumerations.FileChangeType.deleted(), + do: SourceFile.Path.from_uri(change.uri) for path <- deleted_paths do Tracer.notify_file_deleted(path) end + deleted_change_type = GenLSP.Enumerations.FileChangeType.deleted() + source_files = changes |> Enum.reduce(state.source_files, fn - %{"type" => 3}, acc -> + %GenLSP.Structures.FileEvent{type: ^deleted_change_type}, acc -> # deleted file still open in editor, keep dirty flag acc - %{"uri" => uri = "file:" <> _}, acc -> + %GenLSP.Structures.FileEvent{uri: uri = "file:" <> _}, acc -> # file created/updated - set dirty flag to false if file contents are equal case acc[uri] do %SourceFile{text: source_file_text, dirty?: true} = source_file -> @@ -735,7 +837,7 @@ defmodule ElixirLS.LanguageServer.Server do state = %{state | source_files: source_files} changes - |> Enum.map(& &1["uri"]) + |> Enum.map(& &1.uri) |> WorkspaceSymbols.notify_uris_modified() if needs_build do @@ -745,7 +847,10 @@ defmodule ElixirLS.LanguageServer.Server do end end - defp handle_notification(did_change_watched_files(_changes), state = %__MODULE__{}) do + defp handle_notification( + %GenLSP.Notifications.WorkspaceDidChangeWatchedFiles{}, + state = %__MODULE__{project_dir: nil} + ) do # swallow notification if we are not in mix_project state end @@ -768,12 +873,32 @@ defmodule ElixirLS.LanguageServer.Server do when not is_initialized(server_instance_id) do start_time = System.monotonic_time(:millisecond) + struct = + case GenLSP.Requests.new(packet) do + {:ok, struct} -> + struct + + {:error, "unexpected request payload"} -> + packet + end + case packet do - initialize_req(_id, _root_uri, _client_capabilities) -> + request(id, "initialize") -> try do - {:ok, result, state} = handle_request(packet, state) + # Store the request module for proper result encoding + request_module = struct.__struct__ + {:ok, result, state} = handle_request(struct, state) elapsed = System.monotonic_time(:millisecond) - start_time - JsonRpc.respond(id, result) + # Use request module's result schematic if available (GenLSP requests) + response_body = + if function_exported?(request_module, :result, 0) do + {:ok, dumped_body} = SchematicV.dump(request_module.result(), result) + dumped_body + else + result + end + + JsonRpc.respond(id, response_body) JsonRpc.telemetry("lsp_request", %{"elixir_ls.lsp_command" => "initialize"}, %{ "elixir_ls.lsp_request_time" => elapsed @@ -782,14 +907,31 @@ defmodule ElixirLS.LanguageServer.Server do state catch kind, payload -> - {payload, stacktrace} = Exception.blame(kind, payload, __STACKTRACE__) + stacktrace = __STACKTRACE__ + + {payload, stacktrace} = + try do + Exception.blame(kind, payload, stacktrace) + catch + kind_1, error_1 -> + # in case of error in Exception.blame we want to use the original error and stacktrace + Logger.error( + "Exception.blame failed: #{Exception.format(kind_1, error_1, __STACKTRACE__)}" + ) + + {payload, stacktrace} + end + error_msg = Exception.format(kind, payload, stacktrace) # on error in initialize the protocol requires to respond with # https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#initializeError # the initialize request can fail on broken OTP installs, no point in retrying - JsonRpc.respond_with_error(id, :internal_error, error_msg, %{ - "retry" => false + JsonRpc.respond_with_error(id, :internal_error, error_msg, { + %GenLSP.Structures.InitializeError{ + retry: false + }, + GenLSP.Structures.InitializeError }) do_sanity_check(error_msg) @@ -826,12 +968,21 @@ defmodule ElixirLS.LanguageServer.Server do defp handle_request_packet( id, - packet = %{"method" => command}, + packet = %{"method" => command, "id" => id}, state = %__MODULE__{received_shutdown?: false} ) do + struct = + case GenLSP.Requests.new(packet) do + {:ok, struct} -> + struct + + {:error, "unexpected request payload"} -> + packet + end + command = case packet do - execute_command_req(_id, custom_command_with_server_id, _args) -> + request(_id, "workspace/executeCommand", %{"command" => custom_command_with_server_id}) -> command <> ":" <> (ExecuteCommand.get_command(custom_command_with_server_id) || "") _ -> @@ -841,10 +992,21 @@ defmodule ElixirLS.LanguageServer.Server do start_time = System.monotonic_time(:millisecond) try do - case handle_request(packet, state) do + case handle_request(struct, state) do {:ok, result, state} -> + # Store the request module for proper result encoding + request_module = struct.__struct__ elapsed = System.monotonic_time(:millisecond) - start_time - JsonRpc.respond(id, result) + # Use request module's result schematic if available (GenLSP requests) + response_body = + if function_exported?(request_module, :result, 0) do + {:ok, dumped_body} = SchematicV.dump(request_module.result(), result) + dumped_body + else + result + end + + JsonRpc.respond(id, response_body) JsonRpc.telemetry( "lsp_request", @@ -878,9 +1040,13 @@ defmodule ElixirLS.LanguageServer.Server do {:async, fun, state} -> {pid, ref} = handle_request_async(id, fun) + # Store the request module for proper result encoding + request_module = struct.__struct__ + %{ state - | requests: Map.put(state.requests, id, {pid, ref, command, start_time}), + | requests: + Map.put(state.requests, id, {pid, ref, command, start_time, request_module}), requests_ids_by_pid: Map.put(state.requests_ids_by_pid, pid, id) } end @@ -891,7 +1057,21 @@ defmodule ElixirLS.LanguageServer.Server do state catch kind, payload -> - {payload, stacktrace} = Exception.blame(kind, payload, __STACKTRACE__) + stacktrace = __STACKTRACE__ + + {payload, stacktrace} = + try do + Exception.blame(kind, payload, stacktrace) + catch + kind_1, error_1 -> + # in case of error in Exception.blame we want to use the original error and stacktrace + Logger.error( + "Exception.blame failed: #{Exception.format(kind_1, error_1, __STACKTRACE__)}" + ) + + {payload, stacktrace} + end + error_msg = Exception.format(kind, payload, stacktrace) JsonRpc.respond_with_error(id, :internal_error, error_msg) @@ -928,7 +1108,12 @@ defmodule ElixirLS.LanguageServer.Server do end defp handle_request( - initialize_req(_id, root_uri, client_capabilities), + %GenLSP.Requests.Initialize{ + params: %GenLSP.Structures.InitializeParams{ + root_uri: root_uri, + capabilities: client_capabilities = %GenLSP.Structures.ClientCapabilities{} + } + }, state = %__MODULE__{server_instance_id: server_instance_id} ) when not is_initialized(server_instance_id) do @@ -946,29 +1131,41 @@ defmodule ElixirLS.LanguageServer.Server do state end + ClientCapabilities.store(client_capabilities) + state = %{ state - | client_capabilities: client_capabilities, - server_instance_id: server_instance_id + | server_instance_id: server_instance_id } - :persistent_term.put(:language_server_client_capabilities, client_capabilities) - {:ok, - %{ - "capabilities" => server_capabilities(server_instance_id), - "serverInfo" => %{ - "name" => "ElixirLS", - "version" => "#{Launch.language_server_version()}" + %GenLSP.Structures.InitializeResult{ + capabilities: server_capabilities(server_instance_id), + server_info: %{ + name: "ElixirLS", + version: "#{Launch.language_server_version()}" } }, state} end - defp handle_request(request(_id, "shutdown", _params), state = %__MODULE__{}) do + defp handle_request(%GenLSP.Requests.Shutdown{}, state = %__MODULE__{}) do {:ok, nil, %{state | received_shutdown?: true}} end - defp handle_request(definition_req(_id, uri, line, character), state = %__MODULE__{}) do + defp handle_request( + %GenLSP.Requests.TextDocumentDefinition{ + params: %GenLSP.Structures.DefinitionParams{ + text_document: %GenLSP.Structures.TextDocumentIdentifier{ + uri: uri + }, + position: %GenLSP.Structures.Position{ + line: line, + character: character + } + } + }, + state = %__MODULE__{} + ) do source_file = get_source_file(state, uri) fun = fn -> @@ -980,7 +1177,20 @@ defmodule ElixirLS.LanguageServer.Server do {:async, fun, state} end - defp handle_request(declaration_req(_id, uri, line, character), state = %__MODULE__{}) do + defp handle_request( + %GenLSP.Requests.TextDocumentDeclaration{ + params: %GenLSP.Structures.DeclarationParams{ + text_document: %GenLSP.Structures.TextDocumentIdentifier{ + uri: uri + }, + position: %GenLSP.Structures.Position{ + line: line, + character: character + } + } + }, + state = %__MODULE__{} + ) do source_file = get_source_file(state, uri) fun = fn -> @@ -992,7 +1202,20 @@ defmodule ElixirLS.LanguageServer.Server do {:async, fun, state} end - defp handle_request(implementation_req(_id, uri, line, character), state = %__MODULE__{}) do + defp handle_request( + %GenLSP.Requests.TextDocumentImplementation{ + params: %GenLSP.Structures.ImplementationParams{ + text_document: %GenLSP.Structures.TextDocumentIdentifier{ + uri: uri + }, + position: %GenLSP.Structures.Position{ + line: line, + character: character + } + } + }, + state = %__MODULE__{} + ) do source_file = get_source_file(state, uri) fun = fn -> @@ -1005,7 +1228,20 @@ defmodule ElixirLS.LanguageServer.Server do end defp handle_request( - references_req(_id, uri, line, character, include_declaration), + %GenLSP.Requests.TextDocumentReferences{ + params: %GenLSP.Structures.ReferenceParams{ + text_document: %GenLSP.Structures.TextDocumentIdentifier{ + uri: uri + }, + position: %GenLSP.Structures.Position{ + line: line, + character: character + }, + context: %GenLSP.Structures.ReferenceContext{ + include_declaration: include_declaration + } + } + }, state = %__MODULE__{} ) do source_file = get_source_file(state, uri) @@ -1028,7 +1264,20 @@ defmodule ElixirLS.LanguageServer.Server do {:async, fun, state} end - defp handle_request(hover_req(_id, uri, line, character), state = %__MODULE__{}) do + defp handle_request( + %GenLSP.Requests.TextDocumentHover{ + params: %GenLSP.Structures.HoverParams{ + text_document: %GenLSP.Structures.TextDocumentIdentifier{ + uri: uri + }, + position: %GenLSP.Structures.Position{ + line: line, + character: character + } + } + }, + state = %__MODULE__{} + ) do source_file = get_source_file(state, uri) fun = fn -> @@ -1040,16 +1289,20 @@ defmodule ElixirLS.LanguageServer.Server do {:async, fun, state} end - defp handle_request(document_symbol_req(_id, uri), state = %__MODULE__{}) do + defp handle_request( + %GenLSP.Requests.TextDocumentDocumentSymbol{ + params: %GenLSP.Structures.DocumentSymbolParams{ + text_document: %GenLSP.Structures.TextDocumentIdentifier{ + uri: uri + } + } + }, + state = %__MODULE__{} + ) do source_file = get_source_file(state, uri) fun = fn -> - hierarchical? = - get_in(state.client_capabilities, [ - "textDocument", - "documentSymbol", - "hierarchicalDocumentSymbolSupport" - ]) || false + hierarchical? = ClientCapabilities.hierarchical_document_symbol_support?() if String.ends_with?(uri, [".ex", ".exs", ".eex"]) or source_file.language_id in ["elixir", "eex", "html-eex"] do @@ -1063,7 +1316,14 @@ defmodule ElixirLS.LanguageServer.Server do {:async, fun, state} end - defp handle_request(workspace_symbol_req(_id, query), state = %__MODULE__{}) do + defp handle_request( + %GenLSP.Requests.WorkspaceSymbol{ + params: %GenLSP.Structures.WorkspaceSymbolParams{ + query: query + } + }, + state = %__MODULE__{} + ) do fun = fn -> WorkspaceSymbols.symbols(query) end @@ -1071,48 +1331,39 @@ defmodule ElixirLS.LanguageServer.Server do {:async, fun, state} end - defp handle_request(completion_req(_id, uri, line, character), state = %__MODULE__{}) do + defp handle_request( + %GenLSP.Requests.TextDocumentCompletion{ + params: %GenLSP.Structures.CompletionParams{ + text_document: %GenLSP.Structures.TextDocumentIdentifier{ + uri: uri + }, + position: %GenLSP.Structures.Position{ + line: line, + character: character + } + } + }, + state = %__MODULE__{} + ) do settings = state.settings || %{} source_file = get_source_file(state, uri) - snippets_supported = - !!get_in(state.client_capabilities, [ - "textDocument", - "completion", - "completionItem", - "snippetSupport" - ]) + snippets_supported = ClientCapabilities.snippets_supported?() # deprecated as of Language Server Protocol Specification - 3.15 - deprecated_supported = - !!get_in(state.client_capabilities, [ - "textDocument", - "completion", - "completionItem", - "deprecatedSupport" - ]) - - tags_supported = - case get_in(state.client_capabilities, [ - "textDocument", - "completion", - "completionItem", - "tagSupport" - ]) do - nil -> [] - %{"valueSet" => value_set} -> value_set - end + deprecated_supported = ClientCapabilities.deprecated_supported?() + + tags_supported = ClientCapabilities.tags_supported() - signature_help_supported = - !!get_in(state.client_capabilities, ["textDocument", "signatureHelp"]) + signature_help_supported = ClientCapabilities.signature_help_supported?() locals_without_parens = case SourceFile.formatter_for(uri, state.project_dir, state.mix_project?) do {:ok, {_, opts}} -> locals_without_parens = Keyword.get(opts, :locals_without_parens, []) - if List.improper?(locals_without_parens) do + if not is_list(locals_without_parens) or List.improper?(locals_without_parens) do [] else locals_without_parens @@ -1151,13 +1402,35 @@ defmodule ElixirLS.LanguageServer.Server do {:async, fun, state} end - defp handle_request(formatting_req(_id, uri, _options), state = %__MODULE__{}) do + defp handle_request( + %GenLSP.Requests.TextDocumentFormatting{ + params: %GenLSP.Structures.DocumentFormattingParams{ + text_document: %GenLSP.Structures.TextDocumentIdentifier{ + uri: uri + } + } + }, + state = %__MODULE__{} + ) do source_file = get_source_file(state, uri) fun = fn -> Formatting.format(source_file, uri, state.project_dir, state.mix_project?) end {:async, fun, state} end - defp handle_request(signature_help_req(_id, uri, line, character), state = %__MODULE__{}) do + defp handle_request( + %GenLSP.Requests.TextDocumentSignatureHelp{ + params: %GenLSP.Structures.SignatureHelpParams{ + text_document: %GenLSP.Structures.TextDocumentIdentifier{ + uri: uri + }, + position: %GenLSP.Structures.Position{ + line: line, + character: character + } + } + }, + state = %__MODULE__{} + ) do source_file = get_source_file(state, uri) fun = fn -> @@ -1171,7 +1444,19 @@ defmodule ElixirLS.LanguageServer.Server do end defp handle_request( - on_type_formatting_req(_id, uri, line, character, ch, options), + %GenLSP.Requests.TextDocumentOnTypeFormatting{ + params: %GenLSP.Structures.DocumentOnTypeFormattingParams{ + text_document: %GenLSP.Structures.TextDocumentIdentifier{ + uri: uri + }, + position: %GenLSP.Structures.Position{ + line: line, + character: character + }, + ch: ch, + options: options + } + }, state = %__MODULE__{} ) do source_file = get_source_file(state, uri) @@ -1188,7 +1473,16 @@ defmodule ElixirLS.LanguageServer.Server do {:async, fun, state} end - defp handle_request(code_lens_req(_id, uri), state = %__MODULE__{}) do + defp handle_request( + %GenLSP.Requests.TextDocumentCodeLens{ + params: %GenLSP.Structures.CodeLensParams{ + text_document: %GenLSP.Structures.TextDocumentIdentifier{ + uri: uri + } + } + }, + state = %__MODULE__{} + ) do source_file = get_source_file(state, uri) fun = fn -> @@ -1203,7 +1497,17 @@ defmodule ElixirLS.LanguageServer.Server do {:async, fun, state} end - defp handle_request(execute_command_req(_id, command, args) = req, state = %__MODULE__{}) do + defp handle_request( + %GenLSP.Requests.WorkspaceExecuteCommand{ + params: %GenLSP.Structures.ExecuteCommandParams{ + command: command, + arguments: arguments + } + } = req, + state = %__MODULE__{} + ) do + args = arguments || [] + {:async, fn -> case ExecuteCommand.execute(command, args, state) do @@ -1217,7 +1521,16 @@ defmodule ElixirLS.LanguageServer.Server do end, state} end - defp handle_request(folding_range_req(_id, uri), state = %__MODULE__{}) do + defp handle_request( + %GenLSP.Requests.TextDocumentFoldingRange{ + params: %GenLSP.Structures.FoldingRangeParams{ + text_document: %GenLSP.Structures.TextDocumentIdentifier{ + uri: uri + } + } + }, + state = %__MODULE__{} + ) do source_file = get_source_file(state, uri) fun = fn -> @@ -1232,7 +1545,17 @@ defmodule ElixirLS.LanguageServer.Server do {:async, fun, state} end - defp handle_request(selection_range_req(_id, uri, positions), state = %__MODULE__{}) do + defp handle_request( + %GenLSP.Requests.TextDocumentSelectionRange{ + params: %GenLSP.Structures.SelectionRangeParams{ + text_document: %GenLSP.Structures.TextDocumentIdentifier{ + uri: uri + }, + positions: positions + } + }, + state = %__MODULE__{} + ) do source_file = get_source_file(state, uri) fun = fn -> @@ -1258,7 +1581,19 @@ defmodule ElixirLS.LanguageServer.Server do {:async, fun, state} end - defp handle_request(code_action_req(_id, uri, diagnostics), state = %__MODULE__{}) do + defp handle_request( + %GenLSP.Requests.TextDocumentCodeAction{ + params: %GenLSP.Structures.CodeActionParams{ + text_document: %GenLSP.Structures.TextDocumentIdentifier{ + uri: uri + }, + context: %GenLSP.Structures.CodeActionContext{ + diagnostics: diagnostics + } + } + }, + state = %__MODULE__{} + ) do source_file = get_source_file(state, uri) {:async, fn -> CodeAction.code_actions(source_file, uri, diagnostics) end, state} @@ -1294,34 +1629,47 @@ defmodule ElixirLS.LanguageServer.Server do end defp server_capabilities(server_instance_id) do - %{ - "macroExpansion" => true, - "textDocumentSync" => %{ - "change" => 2, - "openClose" => true, - "save" => %{"includeText" => true} + %GenLSP.Structures.ServerCapabilities{ + experimental: %{"macroExpansion" => true}, + text_document_sync: %GenLSP.Structures.TextDocumentSyncOptions{ + change: GenLSP.Enumerations.TextDocumentSyncKind.incremental(), + open_close: true, + save: %GenLSP.Structures.SaveOptions{include_text: true} + }, + hover_provider: true, + completion_provider: %GenLSP.Structures.CompletionOptions{ + trigger_characters: Completion.trigger_characters() + }, + definition_provider: true, + declaration_provider: true, + implementation_provider: true, + references_provider: true, + document_formatting_provider: true, + signature_help_provider: %GenLSP.Structures.SignatureHelpOptions{ + trigger_characters: SignatureHelp.trigger_characters() + }, + document_symbol_provider: %GenLSP.Structures.DocumentSymbolOptions{ + label: "Elixir outline" }, - "hoverProvider" => true, - "completionProvider" => %{"triggerCharacters" => Completion.trigger_characters()}, - "definitionProvider" => true, - "declarationProvider" => true, - "implementationProvider" => true, - "referencesProvider" => true, - "documentFormattingProvider" => true, - "signatureHelpProvider" => %{"triggerCharacters" => SignatureHelp.trigger_characters()}, - "documentSymbolProvider" => %{"label" => "Elixir outline"}, - "workspaceSymbolProvider" => true, - "documentOnTypeFormattingProvider" => %{"firstTriggerCharacter" => "\n"}, - "codeLensProvider" => %{"resolveProvider" => false}, - "selectionRangeProvider" => true, - "executeCommandProvider" => %{ - "commands" => ExecuteCommand.get_commands(server_instance_id) + workspace_symbol_provider: true, + document_on_type_formatting_provider: %GenLSP.Structures.DocumentOnTypeFormattingOptions{ + first_trigger_character: "\n" }, - "workspace" => %{ - "workspaceFolders" => %{"supported" => false, "changeNotifications" => false} + code_lens_provider: %GenLSP.Structures.CodeLensOptions{ + resolve_provider: false }, - "foldingRangeProvider" => true, - "codeActionProvider" => true + selection_range_provider: true, + execute_command_provider: %GenLSP.Structures.ExecuteCommandOptions{ + commands: ExecuteCommand.get_commands(server_instance_id) + }, + workspace: %{ + workspace_folders: %GenLSP.Structures.WorkspaceFoldersServerCapabilities{ + supported: false, + change_notifications: false + } + }, + folding_range_provider: true, + code_action_provider: true } end @@ -1790,8 +2138,8 @@ defmodule ElixirLS.LanguageServer.Server do defp set_settings(state = %__MODULE__{settings: prev_settings}, settings) when settings != prev_settings do enable_dialyzer = - Dialyzer.check_support() == :ok and Map.get(settings, "autoBuild", true) and - Map.get(settings, "dialyzerEnabled", true) + Dialyzer.check_support() == :ok and Map.get(settings, "autoBuild", true) == true and + Map.get(settings, "dialyzerEnabled", true) == true if enable_dialyzer do dialyzer_warn_opts = Map.get(settings, "dialyzerWarnOpts", []) @@ -1952,9 +2300,10 @@ defmodule ElixirLS.LanguageServer.Server do case JsonRpc.register_capability_request( server_instance_id, "workspace/didChangeWatchedFiles", - %{ - "watchers" => Enum.map(exts, &%{"globPattern" => "**/*" <> &1}) - } + {%GenLSP.Structures.DidChangeWatchedFilesRegistrationOptions{ + watchers: + Enum.map(exts, &%GenLSP.Structures.FileSystemWatcher{glob_pattern: "**/*" <> &1}) + }, GenLSP.Structures.DidChangeWatchedFilesRegistrationOptions} ) do {:ok, nil} -> Logger.info("client/registerCapability succeeded") @@ -1981,7 +2330,8 @@ defmodule ElixirLS.LanguageServer.Server do case JsonRpc.register_capability_request( server_instance_id, "workspace/didChangeConfiguration", - %{} + {%GenLSP.Structures.DidChangeConfigurationRegistrationOptions{}, + GenLSP.Structures.DidChangeConfigurationRegistrationOptions} ) do {:ok, nil} -> Logger.info("client/registerCapability succeeded") @@ -2310,10 +2660,7 @@ defmodule ElixirLS.LanguageServer.Server do defp pull_configuration(state) do supports_get_configuration = - get_in(state.client_capabilities, [ - "workspace", - "configuration" - ]) + ClientCapabilities.supports_configuration?() if supports_get_configuration do response = JsonRpc.get_configuration_request(state.root_uri, "elixirLS") diff --git a/apps/language_server/lib/language_server/source_file.ex b/apps/language_server/lib/language_server/source_file.ex index cfc9fdd25..c1e9bfdf7 100644 --- a/apps/language_server/lib/language_server/source_file.ex +++ b/apps/language_server/lib/language_server/source_file.ex @@ -1,7 +1,7 @@ defmodule ElixirLS.LanguageServer.SourceFile do - alias ElixirLS.LanguageServer.Protocol.TextEdit + alias GenLSP.Structures.TextEdit - import ElixirLS.LanguageServer.Protocol + import ElixirLS.LanguageServer.RangeUtils alias ElixirLS.LanguageServer.JsonRpc require ElixirSense.Core.Introspection, as: Introspection require Logger @@ -50,24 +50,27 @@ defmodule ElixirLS.LanguageServer.SourceFile do def apply_content_changes(%__MODULE__{} = source_file, [edit | rest]) do source_file = - case maybe_convert_text_edit(edit) do - %{"range" => edited_range, "text" => new_text} when not is_nil(edited_range) -> + case normalize_text_edit(edit) do + # GenLSP.TypeAlias.TextDocumentContentChangeEvent with range + %{range: edited_range, text: new_text} when not is_nil(edited_range) -> update_in(source_file.text, fn text -> apply_edit(text, edited_range, new_text) end) - %{"text" => new_text} -> + # GenLSP.TypeAlias.TextDocumentContentChangeEvent without range + %{text: new_text} -> put_in(source_file.text, new_text) end apply_content_changes(source_file, rest) end - defp maybe_convert_text_edit(%TextEdit{range: range, newText: new_text}) do - %{"range" => range, "text" => new_text} + defp normalize_text_edit(%TextEdit{range: range, new_text: new_text}) do + # return a map with the same fields as GenLSP.TypeAlias.TextDocumentContentChangeEvent + %{range: range, text: new_text} end - defp maybe_convert_text_edit(edit) do + defp normalize_text_edit(edit) do edit end @@ -292,7 +295,21 @@ defmodule ElixirLS.LanguageServer.SourceFile do end catch kind, payload -> - {payload, stacktrace} = Exception.blame(kind, payload, __STACKTRACE__) + stacktrace = __STACKTRACE__ + + {payload, stacktrace} = + try do + Exception.blame(kind, payload, stacktrace) + catch + kind_1, error_1 -> + # in case of error in Exception.blame we want to use the original error and stacktrace + Logger.error( + "Exception.blame failed: #{Exception.format(kind_1, error_1, __STACKTRACE__)}" + ) + + {payload, stacktrace} + end + message = Exception.format(kind, payload, stacktrace) Logger.warning("Unable to get formatter options for #{path}: #{message}") @@ -327,7 +344,7 @@ defmodule ElixirLS.LanguageServer.SourceFile do String.length(partial_utf8) + 1 end - # “Clamp” helper. + # "Clamp" helper. # - If offset is out of bounds, keep it within [0, max_bytes]. # - Then check if we landed *immediately* after a high surrogate (0xD800..0xDBFF); # if so, subtract 2 to avoid slicing in the middle. diff --git a/apps/language_server/mix.exs b/apps/language_server/mix.exs index f463e2752..ae1a88199 100644 --- a/apps/language_server/mix.exs +++ b/apps/language_server/mix.exs @@ -46,7 +46,10 @@ defmodule ElixirLS.LanguageServer.MixProject do {:path_glob_vendored, github: "elixir-lsp/path_glob", ref: @dep_versions[:path_glob_vendored]}, {:patch, "~> 0.12.0", only: [:dev, :test], runtime: false}, - {:benchee, "~> 1.0", only: :dev, runtime: false} + {:benchee, "~> 1.0", only: :dev, runtime: false}, + {:schematic_v, + github: "elixir-lsp/schematic_vendored", ref: @dep_versions[:schematic_vendored]}, + {:typed_struct, "~> 0.3"} ] end diff --git a/apps/language_server/test/ast_utils_test.exs b/apps/language_server/test/ast_utils_test.exs index 9137a4a87..77f96f5dc 100644 --- a/apps/language_server/test/ast_utils_test.exs +++ b/apps/language_server/test/ast_utils_test.exs @@ -1,7 +1,7 @@ defmodule ElixirLS.LanguageServer.AstUtilsTest do use ExUnit.Case - import ElixirLS.LanguageServer.Protocol + import ElixirLS.LanguageServer.RangeUtils import ElixirLS.LanguageServer.AstUtils defp get_range(code) do diff --git a/apps/language_server/test/code_unit_test.exs b/apps/language_server/test/code_unit_test.exs new file mode 100644 index 000000000..c260f7cd3 --- /dev/null +++ b/apps/language_server/test/code_unit_test.exs @@ -0,0 +1,392 @@ +defmodule ElixirLS.LanguageServer.CodeUnitTest do + use ExUnit.Case, async: true + + alias ElixirLS.LanguageServer.CodeUnit + + describe "basic UTF-8 to UTF-16 conversions" do + test "converts simple ASCII text" do + text = "hello" + assert CodeUnit.utf16_offset(text, 0) == 0 + assert CodeUnit.utf16_offset(text, 1) == 1 + assert CodeUnit.utf16_offset(text, 5) == 5 + end + + test "converts text with multi-byte UTF-8 characters" do + # é is 2 bytes in UTF-8, 1 code unit in UTF-16 + text = "héllo" + assert CodeUnit.utf16_offset(text, 0) == 0 + # h + assert CodeUnit.utf16_offset(text, 1) == 1 + # é (2 UTF-8 bytes, 1 UTF-16 code unit) + assert CodeUnit.utf16_offset(text, 2) == 2 + # l + assert CodeUnit.utf16_offset(text, 3) == 3 + end + end + + describe "UTF-16 to UTF-8 conversions" do + test "converts simple ASCII text" do + text = "hello" + assert CodeUnit.utf8_offset(text, 0) == 0 + assert CodeUnit.utf8_offset(text, 1) == 1 + assert CodeUnit.utf8_offset(text, 5) == 5 + end + + test "converts text with multi-byte UTF-8 characters" do + # é is 2 bytes in UTF-8, 1 code unit in UTF-16 + text = "héllo" + assert CodeUnit.utf8_offset(text, 0) == 0 + # h + assert CodeUnit.utf8_offset(text, 1) == 1 + # after é (2 UTF-8 bytes) + assert CodeUnit.utf8_offset(text, 2) == 3 + # l + assert CodeUnit.utf8_offset(text, 3) == 4 + end + end + + describe "surrogate pair handling" do + test "handles text with surrogate pairs correctly" do + # U+1F600 (😀) requires a surrogate pair in UTF-16 + text = "a😀b" + + # In UTF-8: "a" (1 byte) + "😀" (4 bytes) + "b" (1 byte) = 6 bytes total + # In UTF-16: "a" (1 code unit) + "😀" (2 code units) + "b" (1 code unit) = 4 code units total + + # start + assert CodeUnit.utf16_offset(text, 0) == 0 + # after 'a' + assert CodeUnit.utf16_offset(text, 1) == 1 + # after '😀' (2 UTF-16 code units) + assert CodeUnit.utf16_offset(text, 2) == 3 + # after 'b' + assert CodeUnit.utf16_offset(text, 3) == 4 + end + + test "validates UTF-16 positions don't point to low surrogates" do + text = "a😀b" + + # Position 0, 1, 3, 4 are valid (not pointing to low surrogate) + assert CodeUnit.utf8_offset(text, 0) == 0 + assert CodeUnit.utf8_offset(text, 1) == 1 + # after 😀 + assert CodeUnit.utf8_offset(text, 3) == 5 + # after b + assert CodeUnit.utf8_offset(text, 4) == 6 + + # Position 2 points to the low surrogate of 😀, should be clamped to position 1 + # clamped to previous valid position + assert CodeUnit.utf8_offset(text, 2) == 1 + end + + test "to_utf8 validates surrogate positions" do + text = "a😀b" + + # Valid positions + assert {:ok, 0} == CodeUnit.to_utf8(text, 0) + assert {:ok, 1} == CodeUnit.to_utf8(text, 1) + # after 😀 + assert {:ok, 5} == CodeUnit.to_utf8(text, 3) + # after b + assert {:ok, 6} == CodeUnit.to_utf8(text, 4) + + # Invalid position (points to low surrogate of 😀) + assert {:error, :invalid_surrogate_position} == CodeUnit.to_utf8(text, 2) + end + + test "handles multiple surrogate pairs" do + # Two emoji characters + text = "😀😃" + + # Each emoji is 2 UTF-16 code units + # start + assert CodeUnit.utf16_offset(text, 0) == 0 + # after first emoji + assert CodeUnit.utf16_offset(text, 1) == 2 + # after second emoji + assert CodeUnit.utf16_offset(text, 2) == 4 + + # UTF-8 positions + # start + assert CodeUnit.utf8_offset(text, 0) == 0 + # after first emoji (4 UTF-8 bytes) + assert CodeUnit.utf8_offset(text, 2) == 4 + # after second emoji (8 UTF-8 bytes total) + assert CodeUnit.utf8_offset(text, 4) == 8 + + # Invalid positions (pointing to low surrogates) + # clamped to previous valid + assert CodeUnit.utf8_offset(text, 1) == 0 + # clamped to previous valid + assert CodeUnit.utf8_offset(text, 3) == 4 + end + end + + describe "UTF-16 counting" do + test "counts UTF-16 code units correctly" do + assert CodeUnit.count(:utf16, "hello") == 5 + # é is 1 UTF-16 code unit + assert CodeUnit.count(:utf16, "héllo") == 5 + # emoji is 2 UTF-16 code units + assert CodeUnit.count(:utf16, "😀") == 2 + # a + 😀 + b = 1 + 2 + 1 + assert CodeUnit.count(:utf16, "a😀b") == 4 + end + end + + describe "BMP (Basic Multilingual Plane) characters" do + test "handles BMP characters correctly" do + # Basic Latin (ASCII) + text = "Hello" + assert CodeUnit.count(:utf16, text) == 5 + assert CodeUnit.utf16_offset(text, 0) == 0 + assert CodeUnit.utf16_offset(text, 5) == 5 + + # Extended Latin + # é is U+00E9 (BMP) + text = "café" + assert CodeUnit.count(:utf16, text) == 4 + assert CodeUnit.utf16_offset(text, 0) == 0 + assert CodeUnit.utf16_offset(text, 4) == 4 + + # Greek letters (BMP) + # Greek letters in BMP + text = "αβγ" + assert CodeUnit.count(:utf16, text) == 3 + assert CodeUnit.utf16_offset(text, 0) == 0 + assert CodeUnit.utf16_offset(text, 3) == 3 + end + + test "handles BMP symbols and punctuation" do + # Various BMP symbols + # Copyright, registered, trademark symbols + text = "©®™" + assert CodeUnit.count(:utf16, text) == 3 + + # Currency symbols + # Euro, Pound, Yen + text = "€£¥" + assert CodeUnit.count(:utf16, text) == 3 + + # Mathematical symbols in BMP + # For all, exists, empty set + text = "∀∃∅" + assert CodeUnit.count(:utf16, text) == 3 + end + + test "BMP variation selectors" do + # BMP variation selector (U+FE00-U+FE0F range) + # Base character + BMP variation selector = 2 code units, but may form 1 grapheme + # A + variation selector-16 + text = "A\uFE0F" + assert CodeUnit.count(:utf16, text) == 2 + + # Conversions should work without errors + assert CodeUnit.utf16_offset(text, 0) == 0 + assert CodeUnit.utf16_offset(text, 1) == 1 + assert CodeUnit.utf16_offset(text, 2) == 2 + + assert CodeUnit.utf8_offset(text, 0) == 0 + assert CodeUnit.utf8_offset(text, 1) == 1 + # A (1 byte) + variation selector (3 bytes) + assert CodeUnit.utf8_offset(text, 2) == 4 + end + end + + describe "supplementary range characters" do + test "handles supplementary characters (surrogate pairs)" do + # Mathematical script capitals (U+1D400-U+1D7FF) + # Mathematical script A and B (U+1D49C, U+1D49D) + text = "𝒜𝒝" + # Each char needs 2 UTF-16 code units + assert CodeUnit.count(:utf16, text) == 4 + + # UTF-16 offsets + # start + assert CodeUnit.utf16_offset(text, 0) == 0 + # after first char (2 code units) + assert CodeUnit.utf16_offset(text, 1) == 2 + # after second char (4 code units total) + assert CodeUnit.utf16_offset(text, 2) == 4 + + # UTF-8 conversions + # start + assert CodeUnit.utf8_offset(text, 0) == 0 + # after first char (4 UTF-8 bytes) + assert CodeUnit.utf8_offset(text, 2) == 4 + # after second char (8 UTF-8 bytes total) + assert CodeUnit.utf8_offset(text, 4) == 8 + end + + test "handles emoji in supplementary range" do + # Common emoji requiring surrogate pairs + # Rocket, glowing star, star + text = "🚀🌟⭐" + + # Count UTF-16 code units (emojis need 2 each, star might be BMP) + utf16_count = CodeUnit.count(:utf16, text) + # At least 3, possibly more if all need surrogate pairs + assert utf16_count >= 3 + + # Basic conversion tests + assert CodeUnit.utf16_offset(text, 0) == 0 + assert CodeUnit.utf8_offset(text, 0) == 0 + + # Should handle all positions without crashing + for i <- 0..utf16_count do + utf8_pos = CodeUnit.utf8_offset(text, i) + assert utf8_pos >= 0 + assert utf8_pos <= byte_size(text) + end + end + + test "handles supplementary variation selectors" do + # Supplementary variation selectors (U+E0100-U+E01EF) + # These require surrogate pairs in UTF-16 + # A + supplementary variation selector + B + text = "A\u{E0100}B" + + utf16_count = CodeUnit.count(:utf16, text) + # A (1) + variation selector (2) + B (1) = 4 code units + assert utf16_count == 4 + + # Test conversions handle surrogate pairs correctly + # A + assert CodeUnit.utf16_offset(text, 0) == 0 + # start of variation selector + assert CodeUnit.utf16_offset(text, 1) == 1 + # after variation selector (2 code units) + assert CodeUnit.utf16_offset(text, 2) == 3 + # B + assert CodeUnit.utf16_offset(text, 3) == 4 + + # UTF-8 conversions + # start + assert CodeUnit.utf8_offset(text, 0) == 0 + # after A + assert CodeUnit.utf8_offset(text, 1) == 1 + # after variation selector (4 UTF-8 bytes) + assert CodeUnit.utf8_offset(text, 3) == 5 + # after B + assert CodeUnit.utf8_offset(text, 4) == 6 + + # Test that positions pointing to low surrogates are handled safely + # Position 2 would point to low surrogate of variation selector + result = CodeUnit.utf8_offset(text, 2) + # Should clamp to before the surrogate pair + assert result == 1 + end + + test "handles mixed BMP and supplementary characters" do + # Mix of BMP and supplementary characters + # BMP + supplementary + BMP + text = "A🎨B" + + utf16_count = CodeUnit.count(:utf16, text) + # A (1) + 🎨 (2) + B (1) = 4 code units + assert utf16_count == 4 + + # Test specific positions + # A + assert CodeUnit.utf16_offset(text, 0) == 0 + # start of 🎨 + assert CodeUnit.utf16_offset(text, 1) == 1 + # after 🎨 + assert CodeUnit.utf16_offset(text, 2) == 3 + # B + assert CodeUnit.utf16_offset(text, 3) == 4 + + # Test UTF-8 conversions + # start + assert CodeUnit.utf8_offset(text, 0) == 0 + # after A + assert CodeUnit.utf8_offset(text, 1) == 1 + # after 🎨 (4 UTF-8 bytes) + assert CodeUnit.utf8_offset(text, 3) == 5 + # after B + assert CodeUnit.utf8_offset(text, 4) == 6 + + # Position 2 points to low surrogate, should clamp + # clamps to before emoji + assert CodeUnit.utf8_offset(text, 2) == 1 + end + + test "boundary cases between BMP and supplementary" do + # Test characters near the BMP boundary (U+FFFF) + # Last BMP char + first supplementary + replacement char + text = "\uFFFE\u{10000}\uFFFF" + + utf16_count = CodeUnit.count(:utf16, text) + # 1 + 2 + 1 = 4 code units + assert utf16_count == 4 + + # Should handle conversions without errors + for i <- 0..utf16_count do + utf8_pos = CodeUnit.utf8_offset(text, i) + assert utf8_pos >= 0 + assert utf8_pos <= byte_size(text) + + # Test round-trip safety + utf16_pos = CodeUnit.utf16_offset(text, utf8_pos) + assert utf16_pos >= 0 + assert utf16_pos <= utf16_count + end + end + end + + describe "edge cases" do + test "handles empty strings" do + assert CodeUnit.utf16_offset("", 0) == 0 + assert CodeUnit.utf8_offset("", 0) == 0 + assert {:ok, 0} == CodeUnit.to_utf8("", 0) + assert {:ok, 0} == CodeUnit.to_utf16("", 0) + end + + test "handles out of bounds positions gracefully" do + text = "hello" + + # Should clamp to end of string + assert CodeUnit.utf16_offset(text, 100) == 5 + assert CodeUnit.utf8_offset(text, 100) == 5 + end + + test "handles mixed content with surrogate pairs and regular characters" do + text = "Hello 😀 World 🌍!" + + # This should work without errors and handle surrogate pairs correctly + utf16_count = CodeUnit.count(:utf16, text) + # More UTF-16 code units than characters due to emojis + assert utf16_count > String.length(text) + + # Test that all positions can be converted without crashing + # and produce reasonable results + for i <- 0..utf16_count do + utf8_pos = CodeUnit.utf8_offset(text, i) + + # UTF-8 position should be valid + assert utf8_pos >= 0 + assert utf8_pos <= byte_size(text) + + # Should be able to convert back to UTF-16 + utf16_pos = CodeUnit.utf16_offset(text, utf8_pos) + assert utf16_pos >= 0 + assert utf16_pos <= utf16_count + + # Converting back to UTF-8 should not crash + utf8_pos2 = CodeUnit.utf8_offset(text, utf16_pos) + assert utf8_pos2 >= 0 + assert utf8_pos2 <= byte_size(text) + end + + # Test specific safe positions that we know should work + # start + assert CodeUnit.utf8_offset(text, 0) == 0 + # start + assert CodeUnit.utf16_offset(text, 0) == 0 + + # Test that basic conversions work without crashing + assert CodeUnit.utf8_offset(text, 6) >= 0 + assert CodeUnit.utf16_offset(text, 6) >= 0 + end + end +end diff --git a/apps/language_server/test/providers/code_action/replace_remote_function_test.exs b/apps/language_server/test/providers/code_action/replace_remote_function_test.exs index 9372c1a6c..9f5ce14c1 100644 --- a/apps/language_server/test/providers/code_action/replace_remote_function_test.exs +++ b/apps/language_server/test/providers/code_action/replace_remote_function_test.exs @@ -4,7 +4,7 @@ defmodule ElixirLS.LanguageServer.Providers.CodeAction.ReplaceRemoteFunctionTest alias ElixirLS.LanguageServer.Providers.CodeAction.ReplaceRemoteFunction alias ElixirLS.LanguageServer.SourceFile - import ElixirLS.LanguageServer.Protocol + import ElixirLS.LanguageServer.RangeUtils @default_message """ Enum.counts/1 is undefined or private. Did you mean: @@ -25,9 +25,9 @@ defmodule ElixirLS.LanguageServer.Providers.CodeAction.ReplaceRemoteFunctionTest range = range(line_number, 0, line_number + 1, 0) diagnostics = [ - %{ - "message" => message, - "range" => range + %GenLSP.Structures.Diagnostic{ + message: message, + range: range } ] diff --git a/apps/language_server/test/providers/code_action/replace_with_underscore_test.exs b/apps/language_server/test/providers/code_action/replace_with_underscore_test.exs index 13dcb4b43..3274a8fdc 100644 --- a/apps/language_server/test/providers/code_action/replace_with_underscore_test.exs +++ b/apps/language_server/test/providers/code_action/replace_with_underscore_test.exs @@ -4,7 +4,7 @@ defmodule ElixirLS.LanguageServer.Providers.CodeAction.ReplaceWithUnderscoreTest alias ElixirLS.LanguageServer.Providers.CodeAction.ReplaceWithUnderscore alias ElixirLS.LanguageServer.SourceFile - import ElixirLS.LanguageServer.Protocol + import ElixirLS.LanguageServer.RangeUtils def apply_code_mod(original_text, options) do variable = Keyword.get(options, :variable, :unused) @@ -22,9 +22,9 @@ defmodule ElixirLS.LanguageServer.Providers.CodeAction.ReplaceWithUnderscoreTest range = range(line_number, 0, line_number + 1, 0) diagnostics = [ - %{ - "message" => message, - "range" => range + %GenLSP.Structures.Diagnostic{ + message: message, + range: range } ] diff --git a/apps/language_server/test/providers/code_lens/test_test.exs b/apps/language_server/test/providers/code_lens/test_test.exs index cee987615..051925221 100644 --- a/apps/language_server/test/providers/code_lens/test_test.exs +++ b/apps/language_server/test/providers/code_lens/test_test.exs @@ -4,6 +4,7 @@ defmodule ElixirLS.LanguageServer.Providers.CodeLens.TestTest do import ElixirLS.LanguageServer.Test.PlatformTestHelpers alias ElixirLS.LanguageServer.Providers.CodeLens alias ElixirLS.LanguageServer.Test.ParserContextBuilder + import ElixirLS.LanguageServer.RangeUtils @project_dir "/project" @@ -577,21 +578,12 @@ defmodule ElixirLS.LanguageServer.Providers.CodeLens.TestTest do } |> Map.merge(args) - %{ - "range" => %{ - "start" => %{ - "line" => line, - "character" => 0 - }, - "end" => %{ - "line" => line, - "character" => 0 - } - }, - "command" => %{ - "title" => get_lens_title(target), - "command" => "elixir.lens.test.run", - "arguments" => [arguments] + %GenLSP.Structures.CodeLens{ + range: range(line, 0, line, 0), + command: %GenLSP.Structures.Command{ + title: get_lens_title(target), + command: "elixir.lens.test.run", + arguments: [arguments] } } end diff --git a/apps/language_server/test/providers/code_mod/diff_test.exs b/apps/language_server/test/providers/code_mod/diff_test.exs index 1c6dd19de..742ddf483 100644 --- a/apps/language_server/test/providers/code_mod/diff_test.exs +++ b/apps/language_server/test/providers/code_mod/diff_test.exs @@ -1,14 +1,12 @@ defmodule ElixirLS.LanguageServer.Providers.CodeMod.DiffTest do use ElixirLS.LanguageServer.Test.CodeMod.Case - alias ElixirLS.LanguageServer.Protocol.TextEdit - import ElixirLS.LanguageServer.Providers.CodeMod.Diff - import ElixirLS.LanguageServer.Protocol + import ElixirLS.LanguageServer.RangeUtils def edit(start_line, start_code_unit, end_line, end_code_unit, replacement) do - %TextEdit{ - newText: replacement, + %GenLSP.Structures.TextEdit{ + new_text: replacement, range: range(start_line, start_code_unit, end_line, end_code_unit) } end diff --git a/apps/language_server/test/providers/completion_test.exs b/apps/language_server/test/providers/completion_test.exs index c99df434d..5b619bc6e 100644 --- a/apps/language_server/test/providers/completion_test.exs +++ b/apps/language_server/test/providers/completion_test.exs @@ -16,9 +16,9 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do locals_without_parens: MapSet.new() ] - @signature_command %{ - "title" => "Trigger Parameter Hint", - "command" => "editor.action.triggerParameterHints" + @signature_command %GenLSP.Structures.Command{ + title: "Trigger Parameter Hint", + command: "editor.action.triggerParameterHints" } test "do is returned" do @@ -38,11 +38,11 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => [first_item | _items]}} = + {:ok, %GenLSP.Structures.CompletionList{items: [first_item | _items]}} = Completion.completion(parser_context, line, char, @supports) - assert first_item["label"] == "do" - assert first_item["preselect"] == true + assert first_item.label == "do" + assert first_item.preselect == true end test "end is returned" do @@ -65,15 +65,15 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => [first_item | items]}} = + {:ok, %GenLSP.Structures.CompletionList{items: [first_item | items]}} = Completion.completion(parser_context, line, char, @supports) - assert first_item["label"] == "end" + assert first_item.label == "end" completions = items - |> Enum.filter(&(&1["label"] =~ "engineering_department")) - |> Enum.map(& &1["insertText"]) + |> Enum.filter(&(&1.label =~ "engineering_department")) + |> Enum.map(& &1.insert_text) assert completions == ["engineering_department()"] end @@ -96,12 +96,13 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => items}} = Completion.completion(parser_context, line, char, @supports) + {:ok, %GenLSP.Structures.CompletionList{items: items}} = + Completion.completion(parser_context, line, char, @supports) logger_labels = ["warn", "debug", "error", "info"] for lfn <- logger_labels do - assert(Enum.any?(items, fn %{"label" => label} -> label == lfn end)) + assert(Enum.any?(items, fn item -> item.label == lfn end)) end end @@ -123,12 +124,13 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => items}} = Completion.completion(parser_context, line, char, @supports) + {:ok, %GenLSP.Structures.CompletionList{items: items}} = + Completion.completion(parser_context, line, char, @supports) logger_labels = ["warn", "debug", "error", "info"] for lfn <- logger_labels do - assert(Enum.any?(items, fn %{"label" => label} -> label == lfn end)) + assert(Enum.any?(items, fn item -> item.label == lfn end)) end end @@ -149,10 +151,10 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => [first_suggestion | _tail]}} = + {:ok, %GenLSP.Structures.CompletionList{items: [first_suggestion | _tail]}} = Completion.completion(parser_context, line, char, @supports) - assert first_suggestion["label"] === "fn" + assert first_suggestion.label === "fn" end test "unless with snippets not supported does not return a completion" do @@ -173,10 +175,12 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => items}} = Completion.completion(parser_context, line, char, @supports) + {:ok, %GenLSP.Structures.CompletionList{items: items}} = + Completion.completion(parser_context, line, char, @supports) + assert length(items) == 1 - {:ok, %{"items" => items}} = + {:ok, %GenLSP.Structures.CompletionList{items: items}} = Completion.completion( parser_context, line, @@ -203,14 +207,15 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => [item]}} = Completion.completion(parser_context, line, char, @supports) + {:ok, %GenLSP.Structures.CompletionList{items: [item]}} = + Completion.completion(parser_context, line, char, @supports) # 8 is interface - assert item["kind"] == 8 - assert item["label"] == "ExampleProtocol" - assert item["labelDetails"]["detail"] == "protocol" + assert item.kind == 8 + assert item.label == "ExampleProtocol" + assert item.label_details.detail == "protocol" - assert item["labelDetails"]["description"] == + assert item.label_details.description == "ElixirLS.LanguageServer.Fixtures.ExampleProtocol" end @@ -228,12 +233,13 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => items}} = Completion.completion(parser_context, line, char, @supports) + {:ok, %GenLSP.Structures.CompletionList{items: items}} = + Completion.completion(parser_context, line, char, @supports) completions = items - |> Enum.filter(&(&1["detail"] =~ "protocol function")) - |> Enum.map(& &1["label"]) + |> Enum.filter(&(&1.detail =~ "protocol function")) + |> Enum.map(& &1.label) assert completions == [ "def my_fun/2" @@ -256,16 +262,17 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => items}} = Completion.completion(parser_context, line, char, @supports) + {:ok, %GenLSP.Structures.CompletionList{items: items}} = + Completion.completion(parser_context, line, char, @supports) assert [item, _] = items # 8 is interface - assert item["kind"] == 8 - assert item["label"] == "ExampleBehaviour" - assert item["labelDetails"]["detail"] == "behaviour" + assert item.kind == 8 + assert item.label == "ExampleBehaviour" + assert item.label_details.detail == "behaviour" - assert item["labelDetails"]["description"] == + assert item.label_details.description == "ElixirLS.LanguageServer.Fixtures.ExampleBehaviour" end @@ -285,16 +292,17 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => items}} = Completion.completion(parser_context, line, char, @supports) + {:ok, %GenLSP.Structures.CompletionList{items: items}} = + Completion.completion(parser_context, line, char, @supports) assert [item] = items # 22 is struct - assert item["kind"] == 22 - assert item["label"] == "ExampleException" - assert item["labelDetails"]["detail"] == "exception" + assert item.kind == 22 + assert item.label == "ExampleException" + assert item.label_details.detail == "exception" - assert item["labelDetails"]["description"] == + assert item.label_details.description == "ElixirLS.LanguageServer.Fixtures.ExampleException" end @@ -313,16 +321,17 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => items}} = Completion.completion(parser_context, line, char, @supports) + {:ok, %GenLSP.Structures.CompletionList{items: items}} = + Completion.completion(parser_context, line, char, @supports) first_completion = items - |> Enum.filter(&(&1["detail"] =~ "callback")) + |> Enum.filter(&(&1.detail =~ "callback")) |> Enum.at(0) - assert first_completion["label"] =~ "def build_greeting" + assert first_completion.label =~ "def build_greeting" - assert first_completion["insertText"] == "def build_greeting(${1:name}) do\n\t$0\nend" + assert first_completion.insert_text == "def build_greeting(${1:name}) do\n\t$0\nend" end test "provides completions for callbacks with `def` before" do @@ -341,14 +350,15 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => items}} = Completion.completion(parser_context, line, char, @supports) + {:ok, %GenLSP.Structures.CompletionList{items: items}} = + Completion.completion(parser_context, line, char, @supports) first_completion = items - |> Enum.filter(&(&1["detail"] =~ "callback")) + |> Enum.filter(&(&1.detail =~ "callback")) |> Enum.at(0) - assert first_completion["label"] =~ "def build_greeting" + assert first_completion.label =~ "def build_greeting" end test "returns module completions after pipe" do @@ -370,12 +380,13 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => items}} = Completion.completion(parser_context, line, char, @supports) + {:ok, %GenLSP.Structures.CompletionList{items: items}} = + Completion.completion(parser_context, line, char, @supports) completions = items - |> Enum.filter(&(&1["detail"] =~ "struct")) - |> Enum.map(& &1["label"]) + |> Enum.filter(&(&1.detail =~ "struct")) + |> Enum.map(& &1.label) assert "NaiveDateTime" in completions @@ -385,12 +396,13 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => items}} = Completion.completion(parser_context, line, char, @supports) + {:ok, %GenLSP.Structures.CompletionList{items: items}} = + Completion.completion(parser_context, line, char, @supports) completions = items - |> Enum.filter(&(&1["detail"] =~ "module")) - |> Enum.map(& &1["label"]) + |> Enum.filter(&(&1.detail =~ "module")) + |> Enum.map(& &1.label) assert "Integer" in completions @@ -400,12 +412,13 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => items}} = Completion.completion(parser_context, line, char, @supports) + {:ok, %GenLSP.Structures.CompletionList{items: items}} = + Completion.completion(parser_context, line, char, @supports) completions = items - |> Enum.filter(&(&1["detail"] =~ "struct")) - |> Enum.map(& &1["label"]) + |> Enum.filter(&(&1.detail =~ "struct")) + |> Enum.map(& &1.label) assert "NaiveDateTime" in completions end @@ -423,26 +436,31 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => [item]}} = Completion.completion(parser_context, line, char, options) + {:ok, %GenLSP.Structures.CompletionList{items: [item]}} = + Completion.completion(parser_context, line, char, options) + item end test "returns deprecated flag when supported" do - assert %{"deprecated" => true} = get_deprecated_completion_item(deprecated_supported: true) + assert %GenLSP.Structures.CompletionItem{deprecated: true} = + get_deprecated_completion_item(deprecated_supported: true) end test "returns deprecated completion tag when supported" do - assert %{"tags" => [1]} = get_deprecated_completion_item(tags_supported: [1]) + assert %GenLSP.Structures.CompletionItem{tags: [1]} = + get_deprecated_completion_item(tags_supported: [1]) end test "returns no deprecated indicator when not supported" do # deprecated and tags not supported item = get_deprecated_completion_item([]) - refute Map.has_key?(item, "deprecated") - refute Map.has_key?(item, "tags") + assert item.deprecated == nil + assert item.tags == nil - # tags supported but not deprecated tag - assert %{"tags" => []} = get_deprecated_completion_item(tags_supported: [2]) + # tags supported but not deprecated tag - the item still has deprecated tag but it's filtered out + item = get_deprecated_completion_item(tags_supported: [2]) + assert item.tags == nil || item.tags == [] end end @@ -471,28 +489,33 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => items}} = Completion.completion(parser_context, line, char, @supports) + {:ok, %GenLSP.Structures.CompletionList{items: items}} = + Completion.completion(parser_context, line, char, @supports) - assert [item] = items |> Enum.filter(&(&1["label"] == "ExampleStruct")) + assert [item] = items |> Enum.filter(&(&1.label == "ExampleStruct")) # 22 is struct - assert item["kind"] == 22 - assert item["labelDetails"]["detail"] == "struct" + assert item.kind == 22 + assert item.label_details.detail == "struct" - assert item["labelDetails"]["description"] == + assert item.label_details.description == "alias ElixirLS.LanguageServer.Fixtures.ExampleStruct" - assert [%{newText: "alias ElixirLS.LanguageServer.Fixtures.ExampleStruct\n"}] = - item["additionalTextEdits"] + assert [ + %GenLSP.Structures.TextEdit{ + new_text: "alias ElixirLS.LanguageServer.Fixtures.ExampleStruct\n" + } + ] = + item.additional_text_edits assert [ - %{ - range: %{ - "end" => %{"character" => 0, "line" => 8}, - "start" => %{"character" => 0, "line" => 8} + %GenLSP.Structures.TextEdit{ + range: %GenLSP.Structures.Range{ + end: %GenLSP.Structures.Position{character: 0, line: 8}, + start: %GenLSP.Structures.Position{character: 0, line: 8} } } - ] = item["additionalTextEdits"] + ] = item.additional_text_edits end test "suggests nothing when auto_insert_required_alias is false" do @@ -521,7 +544,8 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => items}} = Completion.completion(parser_context, line, char, supports) + {:ok, %GenLSP.Structures.CompletionList{items: items}} = + Completion.completion(parser_context, line, char, supports) # nothing is suggested assert [] = items @@ -535,11 +559,12 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => items}} = Completion.completion(parser_context, line, char, @supports) + {:ok, %GenLSP.Structures.CompletionList{items: items}} = + Completion.completion(parser_context, line, char, @supports) assert [item | _] = items - assert item["label"] == "do" + assert item.label == "do" end end @@ -560,29 +585,31 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => items}} = Completion.completion(parser_context, line, char, @supports) + {:ok, %GenLSP.Structures.CompletionList{items: items}} = + Completion.completion(parser_context, line, char, @supports) assert [item] = items # 21 is constant which we use for macro - assert item["kind"] == 21 - assert item["label"] == "error" - assert item["detail"] == "macro" - assert item["labelDetails"]["detail"] == "(message_or_fun, metadata \\\\ [])" + assert item.kind == 21 + assert item.label == "error" + assert item.detail == "macro" + assert item.label_details.detail == "(message_or_fun, metadata \\\\ [])" - assert item["labelDetails"]["description"] == + assert item.label_details.description == "require Logger.error/2" - assert [%{newText: " require Logger\n"}] = item["additionalTextEdits"] + assert [%GenLSP.Structures.TextEdit{new_text: " require Logger\n"}] = + item.additional_text_edits assert [ - %{ - range: %{ - "end" => %{"character" => 0, "line" => 1}, - "start" => %{"character" => 0, "line" => 1} + %GenLSP.Structures.TextEdit{ + range: %GenLSP.Structures.Range{ + end: %GenLSP.Structures.Position{character: 0, line: 1}, + start: %GenLSP.Structures.Position{character: 0, line: 1} } } - ] = item["additionalTextEdits"] + ] = item.additional_text_edits end end @@ -604,7 +631,8 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => items}} = Completion.completion(parser_context, line, char, @supports) + {:ok, %GenLSP.Structures.CompletionList{items: items}} = + Completion.completion(parser_context, line, char, @supports) assert [] == items end @@ -627,16 +655,17 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => items}} = Completion.completion(parser_context, line, char, @supports) + {:ok, %GenLSP.Structures.CompletionList{items: items}} = + Completion.completion(parser_context, line, char, @supports) assert [item] = items # 22 is struct - assert item["kind"] == 22 - assert item["label"] == "ExampleStruct" - assert item["labelDetails"]["detail"] == "struct" + assert item.kind == 22 + assert item.label == "ExampleStruct" + assert item.label_details.detail == "struct" - assert item["labelDetails"]["description"] == + assert item.label_details.description == "ElixirLS.LanguageServer.Fixtures.ExampleStruct" end @@ -658,10 +687,11 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => items}} = Completion.completion(parser_context, line, char, @supports) + {:ok, %GenLSP.Structures.CompletionList{items: items}} = + Completion.completion(parser_context, line, char, @supports) - assert ["__struct__", "other", "some"] == items |> Enum.map(& &1["label"]) |> Enum.sort() - assert (items |> hd)["detail"] == "MyModule struct field" + assert ["__struct__", "other", "some"] == items |> Enum.map(& &1.label) |> Enum.sort() + assert (items |> hd).detail == "MyModule struct field" end test "returns map keys in call syntax" do @@ -680,10 +710,11 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => items}} = Completion.completion(parser_context, line, char, @supports) + {:ok, %GenLSP.Structures.CompletionList{items: items}} = + Completion.completion(parser_context, line, char, @supports) - assert ["other", "some"] == items |> Enum.map(& &1["label"]) |> Enum.sort() - assert (items |> hd)["detail"] == "map key" + assert ["other", "some"] == items |> Enum.map(& &1.label) |> Enum.sort() + assert (items |> hd).detail == "map key" end test "returns struct fields in update syntax" do @@ -704,12 +735,13 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => items}} = Completion.completion(parser_context, line, char, @supports) + {:ok, %GenLSP.Structures.CompletionList{items: items}} = + Completion.completion(parser_context, line, char, @supports) assert ["__struct__", "other", "some"] == - items |> Enum.filter(&(&1["kind"] == 5)) |> Enum.map(& &1["label"]) |> Enum.sort() + items |> Enum.filter(&(&1.kind == 5)) |> Enum.map(& &1.label) |> Enum.sort() - assert (items |> hd)["detail"] == "MyModule struct field" + assert (items |> hd).detail == "MyModule struct field" end test "returns map keys in update syntax" do @@ -728,12 +760,13 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => items}} = Completion.completion(parser_context, line, char, @supports) + {:ok, %GenLSP.Structures.CompletionList{items: items}} = + Completion.completion(parser_context, line, char, @supports) assert ["other", "some"] == - items |> Enum.filter(&(&1["kind"] == 5)) |> Enum.map(& &1["label"]) |> Enum.sort() + items |> Enum.filter(&(&1.kind == 5)) |> Enum.map(& &1.label) |> Enum.sort() - assert (items |> hd)["detail"] == "map key" + assert (items |> hd).detail == "map key" end test "returns struct fields in definition syntax" do @@ -756,13 +789,13 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {:ok, result} = Completion.completion(parser_context, line, char, @supports) - assert result["isIncomplete"] == true - items = result["items"] + assert result.is_incomplete == true + items = result.items assert ["__struct__", "other", "some"] == - items |> Enum.filter(&(&1["kind"] == 5)) |> Enum.map(& &1["label"]) |> Enum.sort() + items |> Enum.filter(&(&1.kind == 5)) |> Enum.map(& &1.label) |> Enum.sort() - assert (items |> hd)["detail"] == "MyModule struct field" + assert (items |> hd).detail == "MyModule struct field" end test "isIncomplete is false when there are no results" do @@ -782,8 +815,8 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do parser_context = ParserContextBuilder.from_string(text, {line, char}) {:ok, result} = Completion.completion(parser_context, line, char, @supports) - assert result["isIncomplete"] == false - assert result["items"] == [] + assert result.is_incomplete == false + assert result.items == [] end end @@ -811,19 +844,18 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => items}} = Completion.completion(parser_context, line, char, opts) + {:ok, %GenLSP.Structures.CompletionList{items: items}} = + Completion.completion(parser_context, line, char, opts) - [item] = items |> Enum.filter(&(&1["insertText"] == "true")) + [item] = items |> Enum.filter(&(&1.insert_text == "true")) - assert %{ - "detail" => "reserved word", - "documentation" => %{:kind => "markdown", "value" => ""}, - "insertText" => "true", - "insertTextFormat" => 2, - "kind" => 14, - "label" => "true", - "sortText" => "00000000" - } = item + assert item.detail == "reserved word" + assert item.documentation == nil + assert item.insert_text == "true" + assert item.insert_text_format == 2 + assert item.kind == 14 + assert item.label == "true" + assert item.sort_text == "00000000" end end @@ -853,12 +885,17 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => [item]}} = Completion.completion(parser_context, line, char, opts) - assert item["command"] == @signature_command + {:ok, %GenLSP.Structures.CompletionList{items: [item]}} = + Completion.completion(parser_context, line, char, opts) + + assert item.command == @signature_command opts = Keyword.merge(@supports, signature_after_complete: false) - {:ok, %{"items" => [item]}} = Completion.completion(parser_context, line, char, opts) - assert item["command"] == nil + + {:ok, %GenLSP.Structures.CompletionList{items: [item]}} = + Completion.completion(parser_context, line, char, opts) + + assert item.command == nil end test "without snippets nor signature support, complete with just the name", context do @@ -869,10 +906,12 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do opts = Keyword.merge(@supports, snippets_supported: false, signature_help_supported: false) {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => [item]}} = Completion.completion(parser_context, line, char, opts) - assert item["insertText"] == "add_2_numbers" - assert item["command"] == nil + {:ok, %GenLSP.Structures.CompletionList{items: [item]}} = + Completion.completion(parser_context, line, char, opts) + + assert item.insert_text == "add_2_numbers" + assert item.command == nil opts = Keyword.merge(@supports, @@ -880,10 +919,11 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do locals_without_parens: MapSet.new(add_2_numbers: 2) ) - {:ok, %{"items" => [item]}} = Completion.completion(parser_context, line, char, opts) + {:ok, %GenLSP.Structures.CompletionList{items: [item]}} = + Completion.completion(parser_context, line, char, opts) - assert item["insertText"] == "add_2_numbers " - assert item["command"] == @signature_command + assert item.insert_text == "add_2_numbers " + assert item.command == @signature_command end test "with signature support and no snippets support, complete with the name and trigger signature", @@ -895,10 +935,12 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do opts = Keyword.merge(@supports, snippets_supported: false) {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => [item]}} = Completion.completion(parser_context, line, char, opts) - assert item["insertText"] == "add_2_numbers(" - assert item["command"] == @signature_command + {:ok, %GenLSP.Structures.CompletionList{items: [item]}} = + Completion.completion(parser_context, line, char, opts) + + assert item.insert_text == "add_2_numbers(" + assert item.command == @signature_command end test "with snippets support and no signature support, complete with name and args", @@ -910,10 +952,12 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do opts = Keyword.merge(@supports, signature_help_supported: false) {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => [item]}} = Completion.completion(parser_context, line, char, opts) - assert item["insertText"] == "add_2_numbers(${1:a}, ${2:b})" - assert item["command"] == nil + {:ok, %GenLSP.Structures.CompletionList{items: [item]}} = + Completion.completion(parser_context, line, char, opts) + + assert item.insert_text == "add_2_numbers(${1:a}, ${2:b})" + assert item.command == nil end test "with snippets/signature support, add placeholder between parens and trigger signature", @@ -923,10 +967,12 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do TestUtils.assert_has_cursor_char(text, line, char) {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => [item]}} = Completion.completion(parser_context, line, char, @supports) - assert item["insertText"] == "add_2_numbers($1)$0" - assert item["command"] == @signature_command + {:ok, %GenLSP.Structures.CompletionList{items: [item]}} = + Completion.completion(parser_context, line, char, @supports) + + assert item.insert_text == "add_2_numbers($1)$0" + assert item.command == @signature_command end test "with snippets/signature support, before valid arg, do not close parens" do @@ -945,10 +991,12 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do TestUtils.assert_has_cursor_char(text, line, char) {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => [item]}} = Completion.completion(parser_context, line, char, @supports) - assert item["insertText"] == "add_2_numbers(" - assert item["command"] == @signature_command + {:ok, %GenLSP.Structures.CompletionList{items: [item]}} = + Completion.completion(parser_context, line, char, @supports) + + assert item.insert_text == "add_2_numbers(" + assert item.command == @signature_command end test "function in :locals_without_parens doesn't complete with args if there's text after cursor" do @@ -969,10 +1017,12 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do opts = Keyword.merge(@supports, locals_without_parens: MapSet.new(add_2_numbers: 2)) {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => [item]}} = Completion.completion(parser_context, line, char, opts) - assert item["insertText"] == "add_2_numbers" - assert item["command"] == @signature_command + {:ok, %GenLSP.Structures.CompletionList{items: [item]}} = + Completion.completion(parser_context, line, char, opts) + + assert item.insert_text == "add_2_numbers" + assert item.command == @signature_command end test "complete with parens if there are remote calls" do @@ -991,9 +1041,11 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do opts = Keyword.merge(@supports, locals_without_parens: MapSet.new(drop: 2)) {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => [item]}} = Completion.completion(parser_context, line, char, opts) - assert item["insertText"] == "drop($1)$0" + {:ok, %GenLSP.Structures.CompletionList{items: [item]}} = + Completion.completion(parser_context, line, char, opts) + + assert item.insert_text == "drop($1)$0" end test "function with arity 0 does not triggers signature" do @@ -1012,10 +1064,12 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do TestUtils.assert_has_cursor_char(text, line, char) {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => [item]}} = Completion.completion(parser_context, line, char, @supports) - assert item["insertText"] == "my_func()" - assert item["command"] == nil + {:ok, %GenLSP.Structures.CompletionList{items: [item]}} = + Completion.completion(parser_context, line, char, @supports) + + assert item.insert_text == "my_func()" + assert item.command == nil end test "without signature support, unused default arguments are removed from the snippet" do @@ -1037,17 +1091,17 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => [item1, item2, item3]}} = + {:ok, %GenLSP.Structures.CompletionList{items: [item1, item2, item3]}} = Completion.completion(parser_context, line, char, opts) - assert item1["label"] == "my_func" - assert item1["insertText"] == "my_func(${1:text})" + assert item1.label == "my_func" + assert item1.insert_text == "my_func(${1:text})" - assert item2["label"] == "my_func" - assert item2["insertText"] == "my_func(${1:text}, ${2:opts1})" + assert item2.label == "my_func" + assert item2.insert_text == "my_func(${1:text}, ${2:opts1})" - assert item3["label"] == "my_func" - assert item3["insertText"] == "my_func(${1:text}, ${2:opts1}, ${3:opts2})" + assert item3.label == "my_func" + assert item3.insert_text == "my_func(${1:text}, ${2:opts1}, ${3:opts2})" end test "when after a capture, derived functions from default arguments are listed and no signature is triggered" do @@ -1067,37 +1121,37 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => [item1, item2, item3]}} = + {:ok, %GenLSP.Structures.CompletionList{items: [item1, item2, item3]}} = Completion.completion(parser_context, line, char, @supports) - assert item1["label"] == "my_func" - assert item1["insertText"] == "my_func${1:/1}$0" - assert item1["command"] == nil + assert item1.label == "my_func" + assert item1.insert_text == "my_func${1:/1}$0" + assert item1.command == nil - assert item2["label"] == "my_func" - assert item2["insertText"] == "my_func${1:/2}$0" - assert item2["command"] == nil + assert item2.label == "my_func" + assert item2.insert_text == "my_func${1:/2}$0" + assert item2.command == nil - assert item3["label"] == "my_func" - assert item3["insertText"] == "my_func${1:/3}$0" - assert item3["command"] == nil + assert item3.label == "my_func" + assert item3.insert_text == "my_func${1:/3}$0" + assert item3.command == nil opts = Keyword.merge(@supports, snippets_supported: false) - {:ok, %{"items" => [item1, item2, item3]}} = + {:ok, %GenLSP.Structures.CompletionList{items: [item1, item2, item3]}} = Completion.completion(parser_context, line, char, opts) - assert item1["label"] == "my_func" - assert item1["insertText"] == "my_func/1" - assert item1["command"] == nil + assert item1.label == "my_func" + assert item1.insert_text == "my_func/1" + assert item1.command == nil - assert item2["label"] == "my_func" - assert item2["insertText"] == "my_func/2" - assert item2["command"] == nil + assert item2.label == "my_func" + assert item2.insert_text == "my_func/2" + assert item2.command == nil - assert item3["label"] == "my_func" - assert item3["insertText"] == "my_func/3" - assert item3["command"] == nil + assert item3.label == "my_func" + assert item3.insert_text == "my_func/3" + assert item3.command == nil end test "with signature support, a function with default arguments generate just one suggestion" do @@ -1116,10 +1170,13 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do TestUtils.assert_has_cursor_char(text, line, char) {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => [item]}} = Completion.completion(parser_context, line, char, @supports) - assert item["label"] == "my_func" - assert item["insertText"] == "my_func($1)$0" - assert item["command"] == @signature_command + + {:ok, %GenLSP.Structures.CompletionList{items: [item]}} = + Completion.completion(parser_context, line, char, @supports) + + assert item.label == "my_func" + assert item.insert_text == "my_func($1)$0" + assert item.command == @signature_command end test "with signature support, a function with a derived in locals_without_parens generate more than one suggestion" do @@ -1141,15 +1198,15 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do parser_context = ParserContextBuilder.from_string(text, {line, char}) opts = Keyword.merge(@supports, locals_without_parens: MapSet.new(timestamps: 0)) - {:ok, %{"items" => [item_1, item_2]}} = + {:ok, %GenLSP.Structures.CompletionList{items: [item_1, item_2]}} = Completion.completion(parser_context, line, char, opts) - assert item_1["label"] == "timestamps" - assert item_1["labelDetails"]["detail"] == "()" - assert item_1["labelDetails"]["description"] == "MyModule.timestamps/0" - assert item_2["label"] == "timestamps" - assert item_2["labelDetails"]["detail"] == "(a)" - assert item_2["labelDetails"]["description"] == "MyModule.timestamps/1" + assert item_1.label == "timestamps" + assert item_1.label_details.detail == "()" + assert item_1.label_details.description == "MyModule.timestamps/0" + assert item_2.label == "timestamps" + assert item_2.label_details.detail == "(a)" + assert item_2.label_details.description == "MyModule.timestamps/1" end test "with signature support, a function with 1 default argument triggers signature" do @@ -1168,10 +1225,13 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do TestUtils.assert_has_cursor_char(text, line, char) {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => [item]}} = Completion.completion(parser_context, line, char, @supports) - assert item["label"] == "func_with_1_arg" - assert item["insertText"] == "func_with_1_arg($1)$0" - assert item["command"] == @signature_command + + {:ok, %GenLSP.Structures.CompletionList{items: [item]}} = + Completion.completion(parser_context, line, char, @supports) + + assert item.label == "func_with_1_arg" + assert item.insert_text == "func_with_1_arg($1)$0" + assert item.command == @signature_command end test "a function with 1 default argument after a pipe does not trigger signature" do @@ -1190,10 +1250,13 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do TestUtils.assert_has_cursor_char(text, line, char) {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => [item]}} = Completion.completion(parser_context, line, char, @supports) - assert item["label"] == "func_with_1_arg" - assert item["insertText"] == "func_with_1_arg()" - assert item["command"] == nil + + {:ok, %GenLSP.Structures.CompletionList{items: [item]}} = + Completion.completion(parser_context, line, char, @supports) + + assert item.label == "func_with_1_arg" + assert item.insert_text == "func_with_1_arg()" + assert item.command == nil end test "the detail of a local function is visibility + type + signature" do @@ -1215,17 +1278,17 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => [pub, priv]}} = + {:ok, %GenLSP.Structures.CompletionList{items: [pub, priv]}} = Completion.completion(parser_context, line, char, @supports) - assert pub["label"] == "my_func" - assert pub["detail"] == "function" - assert pub["labelDetails"]["detail"] == "(text)" - assert pub["labelDetails"]["description"] == "MyModule.my_func/1" - assert priv["label"] == "my_func_priv" - assert priv["detail"] == "function" - assert priv["labelDetails"]["detail"] == "(text)" - assert priv["labelDetails"]["description"] == "MyModule.my_func_priv/1" + assert pub.label == "my_func" + assert pub.detail == "function" + assert pub.label_details.detail == "(text)" + assert pub.label_details.description == "MyModule.my_func/1" + assert priv.label == "my_func_priv" + assert priv.detail == "function" + assert priv.label_details.detail == "(text)" + assert priv.label_details.description == "MyModule.my_func_priv/1" end test "the detail of a remote function is origin + type + signature" do @@ -1248,13 +1311,13 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => [item | _]}} = + {:ok, %GenLSP.Structures.CompletionList{items: [item | _]}} = Completion.completion(parser_context, line, char, @supports) - assert item["label"] == "func" - assert item["detail"] == "function" - assert item["labelDetails"]["detail"] == "()" - assert item["labelDetails"]["description"] == "RemoteMod.func/0" + assert item.label == "func" + assert item.detail == "function" + assert item.label_details.detail == "()" + assert item.label_details.description == "RemoteMod.func/0" end test "documentation is the markdown of summary + formatted spec" do @@ -1273,12 +1336,12 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - {:ok, %{"items" => [item | _]}} = + {:ok, %GenLSP.Structures.CompletionList{items: [item | _]}} = Completion.completion(parser_context, line, char, @supports) - assert item["documentation"] == %{ - :kind => "markdown", - "value" => """ + assert item.documentation == %GenLSP.Structures.MarkupContent{ + kind: "markdown", + value: """ The summary **Application** language_server @@ -1310,7 +1373,7 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - assert {:ok, %{"items" => [first | _] = _items}} = + assert {:ok, %GenLSP.Structures.CompletionList{items: [first | _] = _items}} = Completion.completion( parser_context, line, @@ -1322,10 +1385,8 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do ) ) - assert %{ - "label" => "defmodule", - "insertText" => "defmodule MyProject.SubFolder.MyFile$1 do\n\t$0\nend" - } = first + assert first.label == "defmodule" + assert first.insert_text == "defmodule MyProject.SubFolder.MyFile$1 do\n\t$0\nend" end test "will suggest defmodule without module_name snippet when file path does not match expected patterns" do @@ -1340,7 +1401,7 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - assert {:ok, %{"items" => [first | _] = _items}} = + assert {:ok, %GenLSP.Structures.CompletionList{items: [first | _] = _items}} = Completion.completion( parser_context, line, @@ -1352,10 +1413,8 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do ) ) - assert %{ - "label" => "defmodule", - "insertText" => "defmodule $1 do\n\t$0\nend" - } = first + assert first.label == "defmodule" + assert first.insert_text == "defmodule $1 do\n\t$0\nend" end test "will suggest defmodule without module_name snippet when file path is nil" do @@ -1370,7 +1429,7 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - assert {:ok, %{"items" => [first | _] = _items}} = + assert {:ok, %GenLSP.Structures.CompletionList{items: [first | _] = _items}} = Completion.completion( parser_context, line, @@ -1382,10 +1441,8 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do ) ) - assert %{ - "label" => "defmodule", - "insertText" => "defmodule $1 do\n\t$0\nend" - } = first + assert first.label == "defmodule" + assert first.insert_text == "defmodule $1 do\n\t$0\nend" end test "will suggest defprotocol with protocol_name snippet when file path matches **/lib/**/*.ex" do @@ -1400,7 +1457,7 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - assert {:ok, %{"items" => [first | _] = _items}} = + assert {:ok, %GenLSP.Structures.CompletionList{items: [first | _] = _items}} = Completion.completion( parser_context, line, @@ -1412,10 +1469,8 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do ) ) - assert %{ - "label" => "defprotocol", - "insertText" => "defprotocol MyProject.SubFolder.MyFile$1 do\n\t$0\nend" - } = first + assert first.label == "defprotocol" + assert first.insert_text == "defprotocol MyProject.SubFolder.MyFile$1 do\n\t$0\nend" end test "will suggest defprotocol without protocol_name snippet when file path does not match expected patterns" do @@ -1430,7 +1485,7 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - assert {:ok, %{"items" => [first | _] = _items}} = + assert {:ok, %GenLSP.Structures.CompletionList{items: [first | _] = _items}} = Completion.completion( parser_context, line, @@ -1442,10 +1497,8 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do ) ) - assert %{ - "label" => "defprotocol", - "insertText" => "defprotocol $1 do\n\t$0\nend" - } = first + assert first.label == "defprotocol" + assert first.insert_text == "defprotocol $1 do\n\t$0\nend" end if Version.match?(System.version(), ">= 1.15.0") do @@ -1462,7 +1515,7 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - assert {:ok, %{"items" => items}} = + assert {:ok, %GenLSP.Structures.CompletionList{items: items}} = Completion.completion( parser_context, line, @@ -1470,10 +1523,10 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do @supports ) - assert item = Enum.find(items, fn item -> item["label"] == "\"0abc\\\"asd\"" end) - assert item["insertText"] == "\"0abc\\\"asd\"($1)$0" + assert item = Enum.find(items, fn item -> item.label == "\"0abc\\\"asd\"" end) + assert item.insert_text == "\"0abc\\\"asd\"($1)$0" - assert item["labelDetails"]["description"] == + assert item.label_details.description == "ElixirLS.LanguageServer.Fixtures.ExampleQuotedDefs.\"0abc\\\"asd\"/2" end end @@ -1494,10 +1547,10 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - assert {:ok, %{"items" => [first | _] = items}} = + assert {:ok, %GenLSP.Structures.CompletionList{items: [first | _] = items}} = Completion.completion(parser_context, line, char, @supports) - labels = Enum.map(items, & &1["label"]) + labels = Enum.map(items, & &1.label) assert labels == [ ~s(@moduledoc """"""), @@ -1505,17 +1558,19 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do "@moduledoc false" ] - assert first == %{ - "detail" => "module attribute snippet", - "documentation" => %{:kind => "markdown", "value" => "Documents a module"}, - "filterText" => "moduledoc", - "insertText" => ~s(moduledoc """\n$0\n"""), - "insertTextFormat" => 2, - "kind" => 15, - "label" => ~s(@moduledoc """"""), - "sortText" => "00000000", - "insertTextMode" => 2 + assert first.detail == "module attribute snippet" + + assert first.documentation == %GenLSP.Structures.MarkupContent{ + kind: "markdown", + value: "Documents a module" } + + assert first.filter_text == "moduledoc" + assert first.insert_text == ~s(moduledoc """\n$0\n""") + assert first.insert_text_format == 2 + assert first.kind == 15 + assert first.label == ~s(@moduledoc """""") + assert first.sort_text == "00000000" end end @@ -1564,10 +1619,10 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - assert {:ok, %{"items" => items}} = + assert {:ok, %GenLSP.Structures.CompletionList{items: items}} = Completion.completion(parser_context, line, char, @supports) - refute Enum.any?(items, fn i -> i["label"] == "make_ref/0" end) + refute Enum.any?(items, fn i -> i.label == "make_ref/0" end) end end @@ -1589,10 +1644,11 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - assert {:ok, %{"items" => items}} = + assert {:ok, %GenLSP.Structures.CompletionList{items: items}} = Completion.completion(parser_context, line, char, @supports) - assert %{"insertText" => insert_text} = Enum.find(items, &match?(%{"label" => "case"}, &1)) + assert item = Enum.find(items, fn item -> item.label == "case" end) + insert_text = item.insert_text assert insert_text =~ "case do\n\t" end @@ -1613,11 +1669,11 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - assert {:ok, %{"items" => items}} = + assert {:ok, %GenLSP.Structures.CompletionList{items: items}} = Completion.completion(parser_context, line, char, @supports) - assert %{"insertText" => insert_text} = - Enum.find(items, &match?(%{"label" => "unless"}, &1)) + assert item = Enum.find(items, fn item -> item.label == "unless" end) + insert_text = item.insert_text assert insert_text =~ "unless do\n\t" end @@ -1639,10 +1695,11 @@ defmodule ElixirLS.LanguageServer.Providers.CompletionTest do {line, char} = SourceFile.lsp_position_to_elixir(text, {line, char}) parser_context = ParserContextBuilder.from_string(text, {line, char}) - assert {:ok, %{"items" => items}} = + assert {:ok, %GenLSP.Structures.CompletionList{items: items}} = Completion.completion(parser_context, line, char, @supports) - assert %{"insertText" => insert_text} = Enum.find(items, &match?(%{"label" => "if"}, &1)) + assert item = Enum.find(items, fn item -> item.label == "if" end) + insert_text = item.insert_text assert insert_text =~ "if do\n\t" end diff --git a/apps/language_server/test/providers/definition_test.exs b/apps/language_server/test/providers/definition_test.exs index 1403e3711..f82ba6a1b 100644 --- a/apps/language_server/test/providers/definition_test.exs +++ b/apps/language_server/test/providers/definition_test.exs @@ -2,11 +2,11 @@ defmodule ElixirLS.LanguageServer.Providers.DefinitionTest do use ExUnit.Case, async: true alias ElixirLS.LanguageServer.Providers.Definition - alias ElixirLS.LanguageServer.Protocol.Location alias ElixirLS.LanguageServer.SourceFile alias ElixirLS.LanguageServer.Test.FixtureHelpers alias ElixirLS.LanguageServer.Test.ParserContextBuilder require ElixirLS.Test.TextLoc + import ElixirLS.LanguageServer.RangeUtils test "find definition remote function call" do file_path = FixtureHelpers.get_path("references_remote.ex") @@ -27,13 +27,10 @@ defmodule ElixirLS.LanguageServer.Providers.DefinitionTest do {line, char} = SourceFile.lsp_position_to_elixir(parser_context.source_file.text, {line, char}) - assert {:ok, %Location{uri: ^b_uri, range: range}} = + assert {:ok, %GenLSP.Structures.Location{uri: ^b_uri, range: range}} = Definition.definition(uri, parser_context, line, char, File.cwd!()) - assert range == %{ - "start" => %{"line" => 1, "character" => 2}, - "end" => %{"line" => 6, "character" => 5} - } + assert range == range(1, 2, 6, 5) end test "find definition remote macro call" do @@ -54,13 +51,10 @@ defmodule ElixirLS.LanguageServer.Providers.DefinitionTest do {line, char} = SourceFile.lsp_position_to_elixir(parser_context.source_file.text, {line, char}) - assert {:ok, %Location{uri: ^b_uri, range: range}} = + assert {:ok, %GenLSP.Structures.Location{uri: ^b_uri, range: range}} = Definition.definition(uri, parser_context, line, char, File.cwd!()) - assert range == %{ - "start" => %{"line" => 8, "character" => 2}, - "end" => %{"line" => 12, "character" => 5} - } + assert range == range(8, 2, 12, 5) end test "find definition imported function call" do @@ -81,13 +75,10 @@ defmodule ElixirLS.LanguageServer.Providers.DefinitionTest do {line, char} = SourceFile.lsp_position_to_elixir(parser_context.source_file.text, {line, char}) - assert {:ok, %Location{uri: ^b_uri, range: range}} = + assert {:ok, %GenLSP.Structures.Location{uri: ^b_uri, range: range}} = Definition.definition(uri, parser_context, line, char, File.cwd!()) - assert range == %{ - "start" => %{"line" => 1, "character" => 2}, - "end" => %{"line" => 6, "character" => 5} - } + assert range == range(1, 2, 6, 5) end test "find definition imported macro call" do @@ -108,13 +99,10 @@ defmodule ElixirLS.LanguageServer.Providers.DefinitionTest do {line, char} = SourceFile.lsp_position_to_elixir(parser_context.source_file.text, {line, char}) - assert {:ok, %Location{uri: ^b_uri, range: range}} = + assert {:ok, %GenLSP.Structures.Location{uri: ^b_uri, range: range}} = Definition.definition(uri, parser_context, line, char, File.cwd!()) - assert range == %{ - "start" => %{"line" => 8, "character" => 2}, - "end" => %{"line" => 12, "character" => 5} - } + assert range == range(8, 2, 12, 5) end test "find definition local function call" do @@ -135,13 +123,10 @@ defmodule ElixirLS.LanguageServer.Providers.DefinitionTest do {line, char} = SourceFile.lsp_position_to_elixir(parser_context.source_file.text, {line, char}) - assert {:ok, %Location{uri: ^b_uri, range: range}} = + assert {:ok, %GenLSP.Structures.Location{uri: ^b_uri, range: range}} = Definition.definition(uri, parser_context, line, char, File.cwd!()) - assert range == %{ - "start" => %{"line" => 1, "character" => 2}, - "end" => %{"line" => 6, "character" => 5} - } + assert range == range(1, 2, 6, 5) end test "find definition local macro call" do @@ -162,13 +147,10 @@ defmodule ElixirLS.LanguageServer.Providers.DefinitionTest do {line, char} = SourceFile.lsp_position_to_elixir(parser_context.source_file.text, {line, char}) - assert {:ok, %Location{uri: ^b_uri, range: range}} = + assert {:ok, %GenLSP.Structures.Location{uri: ^b_uri, range: range}} = Definition.definition(uri, parser_context, line, char, File.cwd!()) - assert range == %{ - "start" => %{"line" => 8, "character" => 2}, - "end" => %{"line" => 12, "character" => 5} - } + assert range == range(8, 2, 12, 5) end test "find definition variable" do @@ -189,13 +171,10 @@ defmodule ElixirLS.LanguageServer.Providers.DefinitionTest do {line, char} = SourceFile.lsp_position_to_elixir(parser_context.source_file.text, {line, char}) - assert {:ok, %Location{uri: ^b_uri, range: range}} = + assert {:ok, %GenLSP.Structures.Location{uri: ^b_uri, range: range}} = Definition.definition(uri, parser_context, line, char, File.cwd!()) - assert range == %{ - "start" => %{"line" => 2, "character" => 4}, - "end" => %{"line" => 2, "character" => 23} - } + assert range == range(2, 4, 2, 23) end test "find definition attribute" do @@ -216,12 +195,9 @@ defmodule ElixirLS.LanguageServer.Providers.DefinitionTest do {line, char} = SourceFile.lsp_position_to_elixir(parser_context.source_file.text, {line, char}) - assert {:ok, %Location{uri: ^b_uri, range: range}} = + assert {:ok, %GenLSP.Structures.Location{uri: ^b_uri, range: range}} = Definition.definition(uri, parser_context, line, char, File.cwd!()) - assert range == %{ - "start" => %{"line" => 24, "character" => 2}, - "end" => %{"line" => 24, "character" => 23} - } + assert range == range(24, 2, 24, 23) end end diff --git a/apps/language_server/test/providers/document_symbols_test.exs b/apps/language_server/test/providers/document_symbols_test.exs index 5a42fe2e9..bf4220fc2 100644 --- a/apps/language_server/test/providers/document_symbols_test.exs +++ b/apps/language_server/test/providers/document_symbols_test.exs @@ -4,6 +4,25 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do alias ElixirLS.LanguageServer.Providers.DocumentSymbols alias ElixirLS.LanguageServer.Protocol alias ElixirLS.LanguageServer.Test.ParserContextBuilder + import ElixirLS.LanguageServer.RangeUtils + + defp get_document_symbols(uri, text, flat) do + results = DocumentSymbols.symbols(uri, text, flat) + + case results do + {:ok, results} -> + assert match?( + {:ok, _dumped}, + SchematicV.dump(GenLSP.Requests.TextDocumentDocumentSymbol.result(), results) + ), + inspect(results) + + _ -> + :ok + end + + results + end test "returns hierarchical symbol information" do uri = "file:///project/file.ex" @@ -59,169 +78,115 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 22, name: "@my_mod_var", - range: %{ - "end" => %{"character" => 37, "line" => 2}, - "start" => %{"character" => 8, "line" => 2} - }, - selectionRange: %{ - "end" => %{"character" => 37, "line" => 2}, - "start" => %{"character" => 8, "line" => 2} - } + range: range(2, 8, 2, 37), + selection_range: range(2, 8, 2, 37) }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "my_fn/1", - detail: :def, - range: %{ - "end" => %{"character" => 31, "line" => 3}, - "start" => %{"character" => 8, "line" => 3} - }, - selectionRange: %{ - "end" => %{"character" => 22, "line" => 3}, - "start" => %{"character" => 12, "line" => 3} - } + detail: "def", + range: range(3, 8, 3, 31), + selection_range: range(3, 12, 3, 22) }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "my_private_fn/1", - detail: :defp + detail: "defp" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 14, name: "my_macro/0", - detail: :defmacro + detail: "defmacro" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 14, name: "my_private_macro/0", - detail: :defmacrop + detail: "defmacrop" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 14, name: "my_guard/1", - detail: :defguard, - range: %{ - "end" => %{"character" => 47, "line" => 7}, - "start" => %{"character" => 8, "line" => 7} - }, - selectionRange: %{ - "end" => %{"character" => 28, "line" => 7}, - "start" => %{"character" => 17, "line" => 7} - } + detail: "defguard", + range: range(7, 8, 7, 47), + selection_range: range(7, 17, 7, 28) }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 14, name: "my_private_guard/1", - detail: :defguardp + detail: "defguardp" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "my_delegate/1", - detail: :defdelegate, - range: %{ - "end" => %{"character" => 61, "line" => 9}, - "start" => %{"character" => 8, "line" => 9} - }, - selectionRange: %{ - "end" => %{"character" => 37, "line" => 9}, - "start" => %{"character" => 20, "line" => 9} - } + detail: "defdelegate", + range: range(9, 8, 9, 61), + selection_range: range(9, 20, 9, 37) }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 14, name: "my_guard/0", - detail: :defguard + detail: "defguard" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "my_fn_no_arg/0", - range: %{ - "end" => %{"character" => 33, "line" => 11}, - "start" => %{"character" => 8, "line" => 11} - }, - selectionRange: %{ - "end" => %{"character" => 24, "line" => 11}, - "start" => %{"character" => 12, "line" => 11} - } + range: range(11, 8, 11, 33), + selection_range: range(11, 12, 11, 24) }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "my_fn_with_guard/1" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "my_fn_with_more_blocks/1", - range: %{ - "end" => %{"character" => 11, "line" => 23}, - "start" => %{"character" => 8, "line" => 13} - }, - selectionRange: %{ - "end" => %{"character" => 39, "line" => 13}, - "start" => %{"character" => 12, "line" => 13} - } + range: range(13, 8, 23, 11), + selection_range: range(13, 12, 13, 39) }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "fun_multiple_when/1", - range: %{ - "end" => %{"character" => 42, "line" => 24}, - "start" => %{"character" => 8, "line" => 24} - }, - selectionRange: %{ - "end" => %{"character" => 42, "line" => 24}, - "start" => %{"character" => 12, "line" => 24} - } + range: range(24, 8, 24, 42), + selection_range: range(24, 12, 24, 42) }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "fun_multiple_when/1", - range: %{ - "end" => %{"character" => 11, "line" => 30}, - "start" => %{"character" => 8, "line" => 25} - }, - selectionRange: %{ - "end" => %{"character" => 35, "line" => 25}, - "start" => %{"character" => 12, "line" => 25} - } + range: range(25, 8, 30, 11), + selection_range: range(25, 12, 25, 35) }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "fun_multiple_when/1", - range: %{ - "end" => %{"character" => 11, "line" => 33}, - "start" => %{"character" => 8, "line" => 31} - }, - selectionRange: %{ - "end" => %{"character" => 37, "line" => 31}, - "start" => %{"character" => 12, "line" => 31} - } + range: range(31, 8, 33, 11), + selection_range: range(31, 12, 31, 37) }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "fun_multiline_args/2" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "fun_multiline_args/2" @@ -229,17 +194,11 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do ], kind: 2, name: "MyModule", - detail: :defmodule, - range: %{ - "end" => %{"character" => 9, "line" => 45}, - "start" => %{"character" => 6, "line" => 1} - }, - selectionRange: %{ - "end" => %{"character" => 24, "line" => 1}, - "start" => %{"character" => 16, "line" => 1} - } + detail: "defmodule", + range: range(1, 6, 45, 9), + selection_range: range(1, 16, 1, 24) } - ]} = DocumentSymbols.symbols(uri, parser_context, true) + ]} = get_document_symbols(uri, parser_context, true) end test "returns flat symbol information" do @@ -286,117 +245,99 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "MyModule", kind: 2, - location: %{ - range: %{ - "end" => %{"character" => 9, "line" => 35}, - "start" => %{"character" => 6, "line" => 1} - } + location: %GenLSP.Structures.Location{ + range: range(1, 6, 35, 9) } }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "@my_mod_var", kind: 22, - location: %{ - range: %{ - "end" => %{"character" => 37, "line" => 2}, - "start" => %{"character" => 8, "line" => 2} - } + location: %GenLSP.Structures.Location{ + range: range(2, 8, 2, 37) }, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "my_fn/1", kind: 12, - location: %{ - range: %{ - "end" => %{"character" => 31, "line" => 3}, - "start" => %{"character" => 8, "line" => 3} - } + location: %GenLSP.Structures.Location{ + range: range(3, 8, 3, 31) }, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "my_private_fn/1", kind: 12, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "my_macro/0", kind: 14, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "my_private_macro/0", kind: 14, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "my_guard/1", kind: 14, - location: %{ - range: %{ - "end" => %{"character" => 47, "line" => 7}, - "start" => %{"character" => 8, "line" => 7} - } + location: %GenLSP.Structures.Location{ + range: range(7, 8, 7, 47) }, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "my_private_guard/1", kind: 14, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "my_delegate/1", kind: 12, - location: %{ - range: %{ - "end" => %{"character" => 61, "line" => 9}, - "start" => %{"character" => 8, "line" => 9} - } + location: %GenLSP.Structures.Location{ + range: range(9, 8, 9, 61) }, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "my_guard/0", kind: 14, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "my_fn_no_arg/0", kind: 12, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "my_fn_with_guard/1", kind: 12, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "my_fn_with_more_blocks/1", kind: 12, - location: %{ - range: %{ - "end" => %{"character" => 11, "line" => 23}, - "start" => %{"character" => 8, "line" => 13} - } + location: %GenLSP.Structures.Location{ + range: range(13, 8, 23, 11) }, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ kind: 12, name: "fun_multiline_args/2", - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ kind: 12, name: "fun_multiline_args/2", - containerName: "MyModule" + container_name: "MyModule" } - ]} = DocumentSymbols.symbols(uri, parser_context, false) + ]} = get_document_symbols(uri, parser_context, false) end test "[nested] handles nested module definitions" do @@ -413,11 +354,11 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "my_fn/0" @@ -425,28 +366,16 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do ], kind: 2, name: "Sub.Module", - range: %{ - "end" => %{"character" => 11, "line" => 4}, - "start" => %{"character" => 8, "line" => 2} - }, - selectionRange: %{ - "end" => %{"character" => 28, "line" => 2}, - "start" => %{"character" => 18, "line" => 2} - } + range: range(2, 8, 4, 11), + selection_range: range(2, 18, 2, 28) } ], kind: 2, name: "MyModule", - range: %{ - "end" => %{"character" => 9, "line" => 5}, - "start" => %{"character" => 6, "line" => 1} - }, - selectionRange: %{ - "end" => %{"character" => 24, "line" => 1}, - "start" => %{"character" => 16, "line" => 1} - } + range: range(1, 6, 5, 9), + selection_range: range(1, 16, 1, 24) } - ]} = DocumentSymbols.symbols(uri, parser_context, true) + ]} = get_document_symbols(uri, parser_context, true) end test "[flat] handles nested module definitions" do @@ -463,33 +392,27 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "MyModule", kind: 2, - location: %{ - range: %{ - "end" => %{"character" => 9, "line" => 5}, - "start" => %{"character" => 6, "line" => 1} - } + location: %GenLSP.Structures.Location{ + range: range(1, 6, 5, 9) } }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "SubModule", kind: 2, - location: %{ - range: %{ - "end" => %{"character" => 11, "line" => 4}, - "start" => %{"character" => 8, "line" => 2} - } + location: %GenLSP.Structures.Location{ + range: range(2, 8, 4, 11) }, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ kind: 12, name: "my_fn/0", - containerName: "SubModule" + container_name: "SubModule" } - ]} = DocumentSymbols.symbols(uri, parser_context, false) + ]} = get_document_symbols(uri, parser_context, false) end test "[nested] handles multiple module definitions" do @@ -507,9 +430,9 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "some_function/0" @@ -517,18 +440,12 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do ], kind: 2, name: "MyModule", - range: %{ - "end" => %{"character" => 9, "line" => 3}, - "start" => %{"character" => 6, "line" => 1} - }, - selectionRange: %{ - "end" => %{"character" => 24, "line" => 1}, - "start" => %{"character" => 16, "line" => 1} - } + range: range(1, 6, 3, 9), + selection_range: range(1, 16, 1, 24) }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "some_other_function/0" @@ -536,16 +453,10 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do ], kind: 2, name: "MyOtherModule", - range: %{ - "end" => %{"character" => 9, "line" => 6}, - "start" => %{"character" => 6, "line" => 4} - }, - selectionRange: %{ - "end" => %{"character" => 29, "line" => 4}, - "start" => %{"character" => 16, "line" => 4} - } + range: range(4, 6, 6, 9), + selection_range: range(4, 16, 4, 29) } - ]} = DocumentSymbols.symbols(uri, parser_context, true) + ]} = get_document_symbols(uri, parser_context, true) end test "[flat] handles multiple module definitions" do @@ -563,37 +474,31 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "MyModule", kind: 2, - location: %{ - range: %{ - "end" => %{"character" => 9, "line" => 3}, - "start" => %{"character" => 6, "line" => 1} - } + location: %GenLSP.Structures.Location{ + range: range(1, 6, 3, 9) } }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "some_function/0", kind: 12, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "MyOtherModule", kind: 2, - location: %{ - range: %{ - "end" => %{"character" => 9, "line" => 6}, - "start" => %{"character" => 6, "line" => 4} - } + location: %GenLSP.Structures.Location{ + range: range(4, 6, 6, 9) } }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ kind: 12, name: "some_other_function/0", - containerName: "MyOtherModule" + container_name: "MyOtherModule" } - ]} = DocumentSymbols.symbols(uri, parser_context, false) + ]} = get_document_symbols(uri, parser_context, false) end test "[nested] handles elixir atom module definitions" do @@ -608,9 +513,9 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "my_fn/0" @@ -618,16 +523,10 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do ], kind: 2, name: "MyModule", - range: %{ - "end" => %{"character" => 9, "line" => 3}, - "start" => %{"character" => 6, "line" => 1} - }, - selectionRange: %{ - "end" => %{"character" => 9, "line" => 3}, - "start" => %{"character" => 6, "line" => 1} - } + range: range(1, 6, 3, 9), + selection_range: range(1, 6, 3, 9) } - ]} = DocumentSymbols.symbols(uri, parser_context, true) + ]} = get_document_symbols(uri, parser_context, true) end test "[flat] handles elixir atom module definitions" do @@ -642,22 +541,19 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "MyModule", kind: 2, - location: %{ - range: %{ - "end" => %{"character" => 9, "line" => 3}, - "start" => %{"character" => 6, "line" => 1} - } + location: %GenLSP.Structures.Location{ + range: range(1, 6, 3, 9) } }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "my_fn/0", kind: 12, - containerName: "MyModule" + container_name: "MyModule" } - ]} = DocumentSymbols.symbols(uri, parser_context, false) + ]} = get_document_symbols(uri, parser_context, false) end test "[nested] handles unquoted module definitions" do @@ -672,9 +568,9 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "my_fn/0" @@ -682,16 +578,10 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do ], kind: 2, name: "unquote(var)", - range: %{ - "end" => %{"character" => 9, "line" => 3}, - "start" => %{"character" => 6, "line" => 1} - }, - selectionRange: %{ - "end" => %{"character" => 28, "line" => 1}, - "start" => %{"character" => 16, "line" => 1} - } + range: range(1, 6, 3, 9), + selection_range: range(1, 16, 1, 28) } - ]} = DocumentSymbols.symbols(uri, parser_context, true) + ]} = get_document_symbols(uri, parser_context, true) end test "[flat] handles unquoted module definitions" do @@ -706,22 +596,19 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "unquote(var)", kind: 2, - location: %{ - range: %{ - "end" => %{"character" => 9, "line" => 3}, - "start" => %{"character" => 6, "line" => 1} - } + location: %GenLSP.Structures.Location{ + range: range(1, 6, 3, 9) } }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ kind: 12, name: "my_fn/0", - containerName: "unquote(var)" + container_name: "unquote(var)" } - ]} = DocumentSymbols.symbols(uri, parser_context, false) + ]} = get_document_symbols(uri, parser_context, false) end test "[nested] handles erlang atom module definitions" do @@ -736,9 +623,9 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "my_fn/0" @@ -746,16 +633,10 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do ], kind: 2, name: "my_module", - range: %{ - "end" => %{"character" => 9, "line" => 3}, - "start" => %{"character" => 6, "line" => 1} - }, - selectionRange: %{ - "end" => %{"character" => 9, "line" => 3}, - "start" => %{"character" => 6, "line" => 1} - } + range: range(1, 6, 3, 9), + selection_range: range(1, 6, 3, 9) } - ]} = DocumentSymbols.symbols(uri, parser_context, true) + ]} = get_document_symbols(uri, parser_context, true) end test "[flat] handles erlang atom module definitions" do @@ -770,22 +651,19 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "my_module", kind: 2, - location: %{ - range: %{ - "end" => %{"character" => 9, "line" => 3}, - "start" => %{"character" => 6, "line" => 1} - } + location: %GenLSP.Structures.Location{ + range: range(1, 6, 3, 9) } }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "my_fn/0", kind: 12, - containerName: "my_module" + container_name: "my_module" } - ]} = DocumentSymbols.symbols(uri, parser_context, false) + ]} = get_document_symbols(uri, parser_context, false) end test "[nested] handles nested module definitions with __MODULE__" do @@ -802,11 +680,11 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "my_fn/0" @@ -819,7 +697,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do kind: 2, name: "__MODULE__" } - ]} = DocumentSymbols.symbols(uri, parser_context, true) + ]} = get_document_symbols(uri, parser_context, true) end test "[flat] handles nested module definitions with __MODULE__" do @@ -836,21 +714,21 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "__MODULE__", kind: 2 }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "__MODULE__.SubModule", kind: 2, - containerName: "__MODULE__" + container_name: "__MODULE__" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "my_fn/0", kind: 12, - containerName: "__MODULE__.SubModule" + container_name: "__MODULE__.SubModule" } - ]} = DocumentSymbols.symbols(uri, parser_context, false) + ]} = get_document_symbols(uri, parser_context, false) end test "[nested] handles protocols and implementations" do @@ -875,90 +753,54 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "size/1", - range: %{ - "end" => %{"character" => 16, "line" => 2}, - "start" => %{"character" => 2, "line" => 2} - }, - selectionRange: %{ - "end" => %{"character" => 16, "line" => 2}, - "start" => %{"character" => 6, "line" => 2} - } + range: range(2, 2, 2, 16), + selection_range: range(2, 6, 2, 16) } ], kind: 11, name: "MyProtocol", - detail: :defprotocol, - range: %{ - "end" => %{"character" => 3, "line" => 3}, - "start" => %{"character" => 0, "line" => 0} - }, - selectionRange: %{ - "end" => %{"character" => 22, "line" => 0}, - "start" => %{"character" => 12, "line" => 0} - } + detail: "defprotocol", + range: range(0, 0, 3, 3), + selection_range: range(0, 12, 0, 22) }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "size/1", - range: %{ - "end" => %{"character" => 41, "line" => 6}, - "start" => %{"character" => 2, "line" => 6} - }, - selectionRange: %{ - "end" => %{"character" => 18, "line" => 6}, - "start" => %{"character" => 6, "line" => 6} - } + range: range(6, 2, 6, 41), + selection_range: range(6, 6, 6, 18) } ], kind: 2, name: "MyProtocol, for: BitString", - detail: :defimpl, - range: %{ - "end" => %{"character" => 3, "line" => 7}, - "start" => %{"character" => 0, "line" => 5} - }, - selectionRange: %{ - "end" => %{"character" => 3, "line" => 7}, - "start" => %{"character" => 0, "line" => 5} - } + detail: "defimpl", + range: range(5, 0, 7, 3), + selection_range: range(5, 0, 7, 3) }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "size/1", - range: %{ - "end" => %{"character" => 36, "line" => 10}, - "start" => %{"character" => 2, "line" => 10} - }, - selectionRange: %{ - "end" => %{"character" => 17, "line" => 10}, - "start" => %{"character" => 6, "line" => 10} - } + range: range(10, 2, 10, 36), + selection_range: range(10, 6, 10, 17) } ], kind: 2, name: "MyProtocol, for: [List, MyList]", - range: %{ - "end" => %{"character" => 3, "line" => 11}, - "start" => %{"character" => 0, "line" => 9} - }, - selectionRange: %{ - "end" => %{"character" => 3, "line" => 11}, - "start" => %{"character" => 0, "line" => 9} - } + range: range(9, 0, 11, 3), + selection_range: range(9, 0, 11, 3) } - ]} = DocumentSymbols.symbols(uri, parser_context, true) + ]} = get_document_symbols(uri, parser_context, true) end test "[flat] handles protocols and implementations" do @@ -983,70 +825,52 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "MyProtocol", kind: 11, - location: %{ - range: %{ - "end" => %{"character" => 3, "line" => 3}, - "start" => %{"character" => 0, "line" => 0} - } + location: %GenLSP.Structures.Location{ + range: range(0, 0, 3, 3) } }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ kind: 12, name: "size/1", - location: %{ - range: %{ - "end" => %{"character" => 16, "line" => 2}, - "start" => %{"character" => 2, "line" => 2} - } + location: %GenLSP.Structures.Location{ + range: range(2, 2, 2, 16) }, - containerName: "MyProtocol" + container_name: "MyProtocol" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ kind: 2, name: "MyProtocol, for: BitString", - location: %{ - range: %{ - "end" => %{"character" => 3, "line" => 7}, - "start" => %{"character" => 0, "line" => 5} - } + location: %GenLSP.Structures.Location{ + range: range(5, 0, 7, 3) } }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ kind: 12, name: "size/1", - location: %{ - range: %{ - "end" => %{"character" => 41, "line" => 6}, - "start" => %{"character" => 2, "line" => 6} - } + location: %GenLSP.Structures.Location{ + range: range(6, 2, 6, 41) }, - containerName: "MyProtocol, for: BitString" + container_name: "MyProtocol, for: BitString" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ kind: 2, name: "MyProtocol, for: [List, MyList]", - location: %{ - range: %{ - "end" => %{"character" => 3, "line" => 11}, - "start" => %{"character" => 0, "line" => 9} - } + location: %GenLSP.Structures.Location{ + range: range(9, 0, 11, 3) } }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ kind: 12, name: "size/1", - location: %{ - range: %{ - "end" => %{"character" => 36, "line" => 10}, - "start" => %{"character" => 2, "line" => 10} - } + location: %GenLSP.Structures.Location{ + range: range(10, 2, 10, 36) }, - containerName: "MyProtocol, for: [List, MyList]" + container_name: "MyProtocol, for: [List, MyList]" } - ]} = DocumentSymbols.symbols(uri, parser_context, false) + ]} = get_document_symbols(uri, parser_context, false) end test "[nested] handles module definitions with struct" do @@ -1062,53 +886,35 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 7, name: "prop", - range: %{ - "end" => %{"character" => _, "line" => 1}, - "start" => %{"character" => 2, "line" => 1} - }, - selectionRange: %{ - "end" => %{"character" => _, "line" => 1}, - "start" => %{"character" => 2, "line" => 1} - } + range: range(1, 2, 1, _), + selection_range: range(1, 2, 1, _) }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 7, name: "prop_with_def", - range: %{ - "end" => %{"character" => _, "line" => 1}, - "start" => %{"character" => 2, "line" => 1} - }, - selectionRange: %{ - "end" => %{"character" => _, "line" => 1}, - "start" => %{"character" => 2, "line" => 1} - } + range: range(1, 2, 1, _), + selection_range: range(1, 2, 1, _) } ], kind: 23, name: "defstruct MyModule", - range: %{ - "end" => %{"character" => 39, "line" => 1}, - "start" => %{"character" => 2, "line" => 1} - }, - selectionRange: %{ - "end" => %{"character" => 39, "line" => 1}, - "start" => %{"character" => 2, "line" => 1} - } + range: range(1, 2, 1, 39), + selection_range: range(1, 2, 1, 39) } ], kind: 2, name: "MyModule" } - ]} = DocumentSymbols.symbols(uri, parser_context, true) + ]} = get_document_symbols(uri, parser_context, true) end test "[flat] handles module definitions with struct" do @@ -1124,44 +930,35 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "MyModule", kind: 2 }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "defstruct MyModule", kind: 23, - location: %{ - range: %{ - "end" => %{"character" => 39, "line" => 1}, - "start" => %{"character" => 2, "line" => 1} - } + location: %GenLSP.Structures.Location{ + range: range(1, 2, 1, 39) }, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "prop", kind: 7, - location: %{ - range: %{ - "end" => %{"character" => _, "line" => 1}, - "start" => %{"character" => 2, "line" => 1} - } + location: %GenLSP.Structures.Location{ + range: range(1, 2, 1, _) }, - containerName: "defstruct MyModule" + container_name: "defstruct MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ kind: 7, name: "prop_with_def", - location: %{ - range: %{ - "end" => %{"character" => _, "line" => 1}, - "start" => %{"character" => 2, "line" => 1} - } + location: %GenLSP.Structures.Location{ + range: range(1, 2, 1, _) }, - containerName: "defstruct MyModule" + container_name: "defstruct MyModule" } - ]} = DocumentSymbols.symbols(uri, parser_context, false) + ]} = get_document_symbols(uri, parser_context, false) end test "[nested] handles module definitions with exception" do @@ -1177,40 +974,28 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 7, name: "message", - range: %{ - "end" => %{"character" => _, "line" => 1}, - "start" => %{"character" => 2, "line" => 1} - }, - selectionRange: %{ - "end" => %{"character" => _, "line" => 1}, - "start" => %{"character" => 2, "line" => 1} - } + range: range(1, 2, 1, _), + selection_range: range(1, 2, 1, _) } ], kind: 23, name: "defexception MyError", - range: %{ - "end" => %{"character" => 25, "line" => 1}, - "start" => %{"character" => 2, "line" => 1} - }, - selectionRange: %{ - "end" => %{"character" => 25, "line" => 1}, - "start" => %{"character" => 2, "line" => 1} - } + range: range(1, 2, 1, 25), + selection_range: range(1, 2, 1, 25) } ], kind: 2, name: "MyError" } - ]} = DocumentSymbols.symbols(uri, parser_context, true) + ]} = get_document_symbols(uri, parser_context, true) end test "[flat] handles module definitions with exception" do @@ -1226,33 +1011,27 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "MyError", kind: 2 }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ kind: 23, name: "defexception MyError", - location: %{ - range: %{ - "end" => %{"character" => 25, "line" => 1}, - "start" => %{"character" => 2, "line" => 1} - } + location: %GenLSP.Structures.Location{ + range: range(1, 2, 1, 25) }, - containerName: "MyError" + container_name: "MyError" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ kind: 7, name: "message", - location: %{ - range: %{ - "end" => %{"character" => _, "line" => 1}, - "start" => %{"character" => 2, "line" => 1} - } + location: %GenLSP.Structures.Location{ + range: range(1, 2, 1, _) }, - containerName: "defexception MyError" + container_name: "defexception MyError" } - ]} = DocumentSymbols.symbols(uri, parser_context, false) + ]} = get_document_symbols(uri, parser_context, false) end test "[nested] handles module definitions with typespecs" do @@ -1279,60 +1058,54 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ %{ children: [], kind: 5, name: "my_simple/0", detail: "@type", - range: %{ - "end" => %{"character" => 28, "line" => 1}, - "start" => %{"character" => 2, "line" => 1} - }, - selectionRange: %{ - "end" => %{"character" => 17, "line" => 1}, - "start" => %{"character" => 8, "line" => 1} - } + range: range(1, 2, 1, 28), + selection_range: range(1, 8, 1, 17) }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 5, name: "my_union/0" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 5, name: "my_simple_private/0", detail: "@typep" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 5, name: "my_simple_opaque/0", detail: "@opaque" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 5, name: "my_with_args/2" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 5, name: "my_with_args_when/2" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 5, name: "abc/0" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 22, name: "@type" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 5, name: "my_with_multiline_args/2" @@ -1341,7 +1114,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do kind: 2, name: "MyModule" } - ]} = DocumentSymbols.symbols(uri, parser_context, true) + ]} = get_document_symbols(uri, parser_context, true) end test "[flat] handles module definitions with typespecs" do @@ -1368,62 +1141,59 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "MyModule", kind: 2 }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ kind: 5, name: "my_simple/0", - location: %{ - range: %{ - "end" => %{"character" => 28, "line" => 1}, - "start" => %{"character" => 2, "line" => 1} - } + location: %GenLSP.Structures.Location{ + range: range(1, 2, 1, 28) }, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ kind: 5, name: "my_union/0", - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ kind: 5, name: "my_simple_private/0", - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ kind: 5, name: "my_simple_opaque/0", - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ kind: 5, name: "my_with_args/2", - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ kind: 5, name: "my_with_args_when/2", - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ kind: 5, name: "abc/0", - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ kind: 22, name: "@type", - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ kind: 5, name: "my_with_multiline_args/2", - containerName: "MyModule" + container_name: "MyModule" } - ]} = DocumentSymbols.symbols(uri, parser_context, false) + ]} = get_document_symbols(uri, parser_context, false) end test "[nested] handles module definitions with callbacks" do @@ -1446,47 +1216,41 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 24, name: "my_callback/2", detail: "@callback", - range: %{ - "end" => %{"character" => 52, "line" => 1}, - "start" => %{"character" => 2, "line" => 1} - }, - selectionRange: %{ - "end" => %{"character" => 37, "line" => 1}, - "start" => %{"character" => 12, "line" => 1} - } + range: range(1, 2, 1, 52), + selection_range: range(1, 12, 1, 37) }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 24, name: "my_macrocallback/2", detail: "@macrocallback" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 24, name: "my_callback_when/2", detail: "@callback" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 24, name: "my_macrocallback_when/2", detail: "@macrocallback" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 24, name: "my_callback_no_arg/0", detail: "@callback" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 24, name: "my_macrocallback_no_arg/0", @@ -1496,7 +1260,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do kind: 2, name: "MyModule" } - ]} = DocumentSymbols.symbols(uri, parser_context, true) + ]} = get_document_symbols(uri, parser_context, true) end test "[flat] handles module definitions with callbacks" do @@ -1519,47 +1283,44 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "MyModule", kind: 2 }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "my_callback/2", kind: 24, - location: %{ - range: %{ - "end" => %{"character" => 52, "line" => 1}, - "start" => %{"character" => 2, "line" => 1} - } + location: %GenLSP.Structures.Location{ + range: range(1, 2, 1, 52) }, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "my_macrocallback/2", kind: 24, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "my_callback_when/2", kind: 24, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "my_macrocallback_when/2", kind: 24, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "my_callback_no_arg/0", kind: 24, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "my_macrocallback_no_arg/0", kind: 24, - containerName: "MyModule" + container_name: "MyModule" } - ]} = DocumentSymbols.symbols(uri, parser_context, false) + ]} = get_document_symbols(uri, parser_context, false) end test "[nested] handles funs with specs" do @@ -1575,9 +1336,9 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "my_fn/1" @@ -1586,7 +1347,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do kind: 2, name: "MyModule" } - ]} = DocumentSymbols.symbols(uri, parser_context, true) + ]} = get_document_symbols(uri, parser_context, true) end test "[flat] handles funs with specs" do @@ -1602,16 +1363,16 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "MyModule", kind: 2 }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "my_fn/1", kind: 12, - containerName: "MyModule" + container_name: "MyModule" } - ]} = DocumentSymbols.symbols(uri, parser_context, false) + ]} = get_document_symbols(uri, parser_context, false) end test "[nested] handles records" do @@ -1625,52 +1386,34 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do parser_context = ParserContextBuilder.from_string(text) - result = DocumentSymbols.symbols(uri, parser_context, true) + result = get_document_symbols(uri, parser_context, true) assert {:ok, [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 7, name: "name", - range: %{ - "end" => %{"character" => 55, "line" => 3}, - "start" => %{"character" => 15, "line" => 3} - }, - selectionRange: %{ - "end" => %{"character" => 55, "line" => 3}, - "start" => %{"character" => 15, "line" => 3} - } + range: range(3, 15, 3, 55), + selection_range: range(3, 15, 3, 55) }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 7, name: "age", - range: %{ - "end" => %{"character" => 55, "line" => 3}, - "start" => %{"character" => 15, "line" => 3} - }, - selectionRange: %{ - "end" => %{"character" => 55, "line" => 3}, - "start" => %{"character" => 15, "line" => 3} - } + range: range(3, 15, 3, 55), + selection_range: range(3, 15, 3, 55) } ], kind: 5, name: ":user", - detail: :defrecord, - range: %{ - "end" => %{"character" => 55, "line" => 3}, - "start" => %{"character" => 8, "line" => 3} - }, - selectionRange: %{ - "end" => %{"character" => 55, "line" => 3}, - "start" => %{"character" => 8, "line" => 3} - } + detail: "defrecord", + range: range(3, 8, 3, 55), + selection_range: range(3, 8, 3, 55) } ], kind: 2, @@ -1690,45 +1433,36 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do parser_context = ParserContextBuilder.from_string(text) - result = DocumentSymbols.symbols(uri, parser_context, false) + result = get_document_symbols(uri, parser_context, false) assert {:ok, [ - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "MyModule", kind: 2, - location: %{ - range: %{ - "end" => %{"character" => 9, "line" => 4}, - "start" => %{"character" => 6, "line" => 1} - } + location: %GenLSP.Structures.Location{ + range: range(1, 6, 4, 9) } }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: ":user", kind: 5, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ - containerName: ":user", + %GenLSP.Structures.SymbolInformation{ + container_name: ":user", kind: 7, - location: %{ - range: %{ - "end" => %{"character" => 55, "line" => 3}, - "start" => %{"character" => 15, "line" => 3} - }, + location: %GenLSP.Structures.Location{ + range: range(3, 15, 3, 55), uri: "file:///project/file.ex" }, name: "name" }, - %Protocol.SymbolInformation{ - containerName: ":user", + %GenLSP.Structures.SymbolInformation{ + container_name: ":user", kind: 7, - location: %{ - range: %{ - "end" => %{"character" => 55, "line" => 3}, - "start" => %{"character" => 15, "line" => 3} - }, + location: %GenLSP.Structures.Location{ + range: range(3, 15, 3, 55), uri: "file:///project/file.ex" }, name: "age" @@ -1751,12 +1485,12 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 2, name: "MyModule" } - ]} = DocumentSymbols.symbols(uri, parser_context, true) + ]} = get_document_symbols(uri, parser_context, true) end test "[flat] skips docs attributes" do @@ -1774,11 +1508,11 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "MyModule", kind: 2 } - ]} = DocumentSymbols.symbols(uri, parser_context, false) + ]} = get_document_symbols(uri, parser_context, false) end test "[nested] handles various builtin attributes" do @@ -1810,82 +1544,76 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 22, name: "@optional_callbacks", - range: %{ - "end" => %{"character" => 58, "line" => 1}, - "start" => %{"character" => 2, "line" => 1} - }, - selectionRange: %{ - "end" => %{"character" => 58, "line" => 1}, - "start" => %{"character" => 2, "line" => 1} - } + range: range(1, 2, 1, 58), + selection_range: range(1, 2, 1, 58) }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 11, name: "@behaviour MyBehaviour" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 22, name: "@derive" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 22, name: "@enforce_keys" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 22, name: "@compile" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 22, name: "@dialyzer" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 22, name: "@file" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 22, name: "@external_resource" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 22, name: "@on_load" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 22, name: "@on_definition" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 22, name: "@vsn" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 22, name: "@after_compile" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 22, name: "@before_compile" }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 22, name: "@fallback_to_any" @@ -1894,7 +1622,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do kind: 2, name: "MyModule" } - ]} = DocumentSymbols.symbols(uri, parser_context, true) + ]} = get_document_symbols(uri, parser_context, true) end test "[flat] handles various builtin attributes" do @@ -1926,93 +1654,87 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "MyModule", kind: 2, - location: %{ - range: %{ - "end" => %{"character" => 3, "line" => 18}, - "start" => %{"character" => 0, "line" => 0} - } + location: %GenLSP.Structures.Location{ + range: range(0, 0, 18, 3) } }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "@optional_callbacks", kind: 22, - location: %{ - range: %{ - "end" => %{"character" => 58, "line" => 1}, - "start" => %{"character" => 2, "line" => 1} - } + location: %GenLSP.Structures.Location{ + range: range(1, 2, 1, 58) }, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "@behaviour MyBehaviour", kind: 11, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "@derive", kind: 22, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "@enforce_keys", kind: 22, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "@compile", kind: 22, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "@dialyzer", kind: 22, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "@file", kind: 22, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "@external_resource", kind: 22, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "@on_load", kind: 22, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "@on_definition", kind: 22, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "@vsn", kind: 22, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "@after_compile", kind: 22, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "@before_compile", kind: 22, - containerName: "MyModule" + container_name: "MyModule" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "@fallback_to_any", kind: 22, - containerName: "MyModule" + container_name: "MyModule" } - ]} = DocumentSymbols.symbols(uri, parser_context, false) + ]} = get_document_symbols(uri, parser_context, false) end test "[nested] handles exunit tests" do @@ -2029,41 +1751,29 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "\"does something\"", - detail: :test, - range: %{ - "end" => %{"character" => 38, "line" => 3}, - "start" => %{"character" => 8, "line" => 3} - }, - selectionRange: %{ - "end" => %{"character" => 38, "line" => 3}, - "start" => %{"character" => 8, "line" => 3} - } + detail: "test", + range: range(3, 8, 3, 38), + selection_range: range(3, 8, 3, 38) }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "\"not implemented\"", - detail: :test, - range: %{ - "end" => %{"character" => 30, "line" => 4}, - "start" => %{"character" => 8, "line" => 4} - }, - selectionRange: %{ - "end" => %{"character" => 30, "line" => 4}, - "start" => %{"character" => 8, "line" => 4} - } + detail: "test", + range: range(4, 8, 4, 30), + selection_range: range(4, 8, 4, 30) } ], kind: 2, name: "MyModuleTest" } - ]} = DocumentSymbols.symbols(uri, parser_context, true) + ]} = get_document_symbols(uri, parser_context, true) end test "[flat] handles exunit tests" do @@ -2079,28 +1789,22 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "MyModuleTest", kind: 2, - location: %{ - range: %{ - "end" => %{"character" => 9, "line" => 4}, - "start" => %{"character" => 6, "line" => 1} - } + location: %GenLSP.Structures.Location{ + range: range(1, 6, 4, 9) } }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "\"does something\"", kind: 12, - location: %{ - range: %{ - "end" => %{"character" => 38, "line" => 3}, - "start" => %{"character" => 8, "line" => 3} - } + location: %GenLSP.Structures.Location{ + range: range(3, 8, 3, 38) }, - containerName: "MyModuleTest" + container_name: "MyModuleTest" } - ]} = DocumentSymbols.symbols(uri, parser_context, false) + ]} = get_document_symbols(uri, parser_context, false) end test "[nested] handles exunit describe tests" do @@ -2118,41 +1822,29 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "\"does something\"", - range: %{ - "end" => %{"character" => _, "line" => 4}, - "start" => %{"character" => 10, "line" => 4} - }, - selectionRange: %{ - "end" => %{"character" => _, "line" => 4}, - "start" => %{"character" => 10, "line" => 4} - } + range: range(4, 10, 4, _), + selection_range: range(4, 10, 4, _) } ], kind: 12, name: "\"some description\"", - detail: :describe, - range: %{ - "end" => %{"character" => 11, "line" => 5}, - "start" => %{"character" => 8, "line" => 3} - }, - selectionRange: %{ - "end" => %{"character" => 11, "line" => 5}, - "start" => %{"character" => 8, "line" => 3} - } + detail: "describe", + range: range(3, 8, 5, _), + selection_range: range(3, 8, 5, _) } ], kind: 2, name: "MyModuleTest" } - ]} = DocumentSymbols.symbols(uri, parser_context, true) + ]} = get_document_symbols(uri, parser_context, true) end test "[nested] handles exunit describes and tests with unevaluated names" do @@ -2170,40 +1862,28 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "\"does\" <> \"something\"", - range: %{ - "end" => %{"character" => _, "line" => 4}, - "start" => %{"character" => 10, "line" => 4} - }, - selectionRange: %{ - "end" => %{"character" => _, "line" => 4}, - "start" => %{"character" => 10, "line" => 4} - } + range: range(4, 10, 4, _), + selection_range: range(4, 10, 4, _) } ], kind: 12, name: describe_sigil, - range: %{ - "end" => %{"character" => 11, "line" => 5}, - "start" => %{"character" => 8, "line" => 3} - }, - selectionRange: %{ - "end" => %{"character" => 11, "line" => 5}, - "start" => %{"character" => 8, "line" => 3} - } + range: range(3, 8, 5, 11), + selection_range: range(3, 8, 5, 11) } ], kind: 2, name: "MyModuleTest" } - ]} = DocumentSymbols.symbols(uri, parser_context, true) + ]} = get_document_symbols(uri, parser_context, true) assert describe_sigil == "~S(some \"description\")" end @@ -2223,39 +1903,30 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "MyModuleTest", kind: 2, - location: %{ - range: %{ - "end" => %{"character" => 9, "line" => 6}, - "start" => %{"character" => 6, "line" => 1} - } + location: %GenLSP.Structures.Location{ + range: range(1, 6, 6, 9) } }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "\"some description\"", kind: 12, - location: %{ - range: %{ - "end" => %{"character" => 11, "line" => 5}, - "start" => %{"character" => 8, "line" => 3} - } + location: %GenLSP.Structures.Location{ + range: range(3, 8, 5, 11) }, - containerName: "MyModuleTest" + container_name: "MyModuleTest" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "\"does something\"", kind: 12, - location: %{ - range: %{ - "end" => %{"character" => _, "line" => 4}, - "start" => %{"character" => 10, "line" => 4} - } + location: %GenLSP.Structures.Location{ + range: range(4, 10, 4, _) }, - containerName: "\"some description\"" + container_name: "\"some description\"" } - ]} = DocumentSymbols.symbols(uri, parser_context, false) + ]} = get_document_symbols(uri, parser_context, false) end test "[flat] handles exunit describes and tests with unevaluated names" do @@ -2273,39 +1944,30 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "MyModuleTest", kind: 2, - location: %{ - range: %{ - "end" => %{"character" => 9, "line" => 6}, - "start" => %{"character" => 6, "line" => 1} - } + location: %GenLSP.Structures.Location{ + range: range(1, 6, 6, 9) } }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: describe_sigil, kind: 12, - location: %{ - range: %{ - "end" => %{"character" => 11, "line" => 5}, - "start" => %{"character" => 8, "line" => 3} - } + location: %GenLSP.Structures.Location{ + range: range(3, 8, 5, 11) }, - containerName: "MyModuleTest" + container_name: "MyModuleTest" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "\"does\" <> \"something\"", kind: 12, - location: %{ - range: %{ - "end" => %{"character" => _, "line" => 4}, - "start" => %{"character" => 10, "line" => 4} - } + location: %GenLSP.Structures.Location{ + range: range(4, 10, 4, _) }, - containerName: describe_sigil + container_name: describe_sigil } - ]} = DocumentSymbols.symbols(uri, parser_context, false) + ]} = get_document_symbols(uri, parser_context, false) assert describe_sigil == "~S(some \"description\")" end @@ -2330,52 +1992,34 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "setup", - range: %{ - "end" => %{"character" => 5, "line" => 4}, - "start" => %{"character" => 2, "line" => 2} - }, - selectionRange: %{ - "end" => %{"character" => 5, "line" => 4}, - "start" => %{"character" => 2, "line" => 2} - } + range: range(2, 2, 4, 5), + selection_range: range(2, 2, 4, 5) }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "setup", - range: %{ - "end" => %{"character" => 31, "line" => 5}, - "start" => %{"character" => 2, "line" => 5} - }, - selectionRange: %{ - "end" => %{"character" => 31, "line" => 5}, - "start" => %{"character" => 2, "line" => 5} - } + range: range(5, 2, 5, 31), + selection_range: range(5, 2, 5, 31) }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "setup_all", - range: %{ - "end" => %{"character" => 5, "line" => 8}, - "start" => %{"character" => 2, "line" => 6} - }, - selectionRange: %{ - "end" => %{"character" => 5, "line" => 8}, - "start" => %{"character" => 2, "line" => 6} - } + range: range(6, 2, 8, 5), + selection_range: range(6, 2, 8, 5) } ], kind: 2, name: "MyModuleTest" } - ]} = DocumentSymbols.symbols(uri, parser_context, true) + ]} = get_document_symbols(uri, parser_context, true) end test "[flat] handles exunit callbacks" do @@ -2398,50 +2042,38 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "MyModuleTest", kind: 2, - location: %{ - range: %{ - "end" => %{"character" => 3, "line" => 9}, - "start" => %{"character" => 0, "line" => 0} - } + location: %GenLSP.Structures.Location{ + range: range(0, 0, 9, 3) } }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "setup", kind: 12, - location: %{ - range: %{ - "end" => %{"character" => 5, "line" => 4}, - "start" => %{"character" => 2, "line" => 2} - } + location: %GenLSP.Structures.Location{ + range: range(2, 2, 4, 5) }, - containerName: "MyModuleTest" + container_name: "MyModuleTest" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "setup", kind: 12, - location: %{ - range: %{ - "end" => %{"character" => 31, "line" => 5}, - "start" => %{"character" => 2, "line" => 5} - } + location: %GenLSP.Structures.Location{ + range: range(5, 2, 5, 31) }, - containerName: "MyModuleTest" + container_name: "MyModuleTest" }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "setup_all", kind: 12, - location: %{ - range: %{ - "end" => %{"character" => 5, "line" => 8}, - "start" => %{"character" => 2, "line" => 6} - } + location: %GenLSP.Structures.Location{ + range: range(6, 2, 8, 5) }, - containerName: "MyModuleTest" + container_name: "MyModuleTest" } - ]} = DocumentSymbols.symbols(uri, parser_context, false) + ]} = get_document_symbols(uri, parser_context, false) end test "[nested] handles config" do @@ -2465,59 +2097,35 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 20, name: "config :logger :console", - range: %{ - "end" => %{"character" => 23, "line" => 5}, - "start" => %{"character" => 0, "line" => 1} - }, - selectionRange: %{ - "end" => %{"character" => 23, "line" => 5}, - "start" => %{"character" => 0, "line" => 1} - } + range: range(1, 0, 5, 23), + selection_range: range(1, 0, 5, 23) }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 20, name: "config :app :key", - range: %{ - "end" => %{"character" => 25, "line" => 6}, - "start" => %{"character" => 0, "line" => 6} - }, - selectionRange: %{ - "end" => %{"character" => 25, "line" => 6}, - "start" => %{"character" => 0, "line" => 6} - } + range: range(6, 0, 6, 25), + selection_range: range(6, 0, 6, 25) }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 20, name: "config :my_app [:ecto_repos]", - range: %{ - "end" => %{"character" => 26, "line" => 8}, - "start" => %{"character" => 0, "line" => 7} - }, - selectionRange: %{ - "end" => %{"character" => 26, "line" => 8}, - "start" => %{"character" => 0, "line" => 7} - } + range: range(7, 0, 8, 26), + selection_range: range(7, 0, 8, 26) }, - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 20, name: "config :my_app MyApp.Repo", - range: %{ - "end" => %{"character" => _, "line" => _}, - "start" => %{"character" => 0, "line" => 9} - }, - selectionRange: %{ - "end" => %{"character" => _, "line" => _}, - "start" => %{"character" => 0, "line" => 9} - } + range: range(9, 0, _, _), + selection_range: range(9, 0, _, _) } - ]} = DocumentSymbols.symbols(uri, parser_context, true) + ]} = get_document_symbols(uri, parser_context, true) end test "[flat] handles config" do @@ -2541,47 +2149,35 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do assert {:ok, [ - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "config :logger :console", kind: 20, - location: %{ - range: %{ - "end" => %{"character" => 23, "line" => 5}, - "start" => %{"character" => 0, "line" => 1} - } + location: %GenLSP.Structures.Location{ + range: range(1, 0, 5, 23) } }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "config :app :key", kind: 20, - location: %{ - range: %{ - "end" => %{"character" => 25, "line" => 6}, - "start" => %{"character" => 0, "line" => 6} - } + location: %GenLSP.Structures.Location{ + range: range(6, 0, 6, 25) } }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "config :my_app [:ecto_repos]", kind: 20, - location: %{ - range: %{ - "end" => %{"character" => 26, "line" => 8}, - "start" => %{"character" => 0, "line" => 7} - } + location: %GenLSP.Structures.Location{ + range: range(7, 0, 8, 26) } }, - %Protocol.SymbolInformation{ + %GenLSP.Structures.SymbolInformation{ name: "config :my_app MyApp.Repo", kind: 20, - location: %{ - range: %{ - "end" => %{"character" => _, "line" => _}, - "start" => %{"character" => 0, "line" => 9} - } + location: %GenLSP.Structures.Location{ + range: range(9, 0, _, _) } } - ]} = DocumentSymbols.symbols(uri, parser_context, false) + ]} = get_document_symbols(uri, parser_context, false) end test "[nested] handles a file with a top-level module without a name" do @@ -2595,10 +2191,10 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do parser_context = ParserContextBuilder.from_string(text) - assert {:ok, document_symbols} = DocumentSymbols.symbols(uri, parser_context, true) + assert {:ok, document_symbols} = get_document_symbols(uri, parser_context, true) assert [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: children, kind: 2, name: "MISSING_MODULE_NAME" @@ -2606,7 +2202,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do ] = document_symbols assert [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 12, name: "foo/0" @@ -2624,10 +2220,10 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do parser_context = ParserContextBuilder.from_string(text) - assert {:ok, document_symbols} = DocumentSymbols.symbols(uri, parser_context, true) + assert {:ok, document_symbols} = get_document_symbols(uri, parser_context, true) assert [ - %Protocol.DocumentSymbol{ + %GenLSP.Structures.DocumentSymbol{ children: [], kind: 11, name: "MISSING_PROTOCOL_NAME" @@ -2648,7 +2244,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do parser_context = ParserContextBuilder.from_string(text) - assert {:ok, []} = DocumentSymbols.symbols(uri, parser_context, true) + assert {:ok, []} = get_document_symbols(uri, parser_context, true) end describe "invalid documents" do @@ -2658,7 +2254,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do parser_context = ParserContextBuilder.from_string(text) - assert {:ok, []} = DocumentSymbols.symbols(uri, parser_context, true) + assert {:ok, []} = get_document_symbols(uri, parser_context, true) end test "handles a protocol being defined" do @@ -2667,7 +2263,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do parser_context = ParserContextBuilder.from_string(text) - assert {:ok, []} = DocumentSymbols.symbols(uri, parser_context, true) + assert {:ok, []} = get_document_symbols(uri, parser_context, true) end test "handles a protocol being impolemented" do @@ -2676,7 +2272,7 @@ defmodule ElixirLS.LanguageServer.Providers.DocumentSymbolsTest do parser_context = ParserContextBuilder.from_string(text) - assert {:ok, []} = DocumentSymbols.symbols(uri, parser_context, true) + assert {:ok, []} = get_document_symbols(uri, parser_context, true) end end end diff --git a/apps/language_server/test/providers/execute_command/manipulate_pipes_test.exs b/apps/language_server/test/providers/execute_command/manipulate_pipes_test.exs index 213ed5ce9..b194dd125 100644 --- a/apps/language_server/test/providers/execute_command/manipulate_pipes_test.exs +++ b/apps/language_server/test/providers/execute_command/manipulate_pipes_test.exs @@ -3,7 +3,7 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d alias ElixirLS.LanguageServer.{Server, SourceFile} alias ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipes - alias ElixirLS.LanguageServer.Protocol.TextEdit + alias GenLSP.Structures.TextEdit defmodule JsonRpcMock do use GenServer @@ -35,12 +35,22 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d id: JsonRpcMock, start: {JsonRpcMock, :start_link, - [[success_reply: {:ok, %{"applied" => true}}, test_pid: self()]]} + [ + [ + success_reply: {:ok, %GenLSP.Structures.ApplyWorkspaceEditResult{applied: true}}, + test_pid: self() + ] + ]} }) :ok end + defp range_to_lsp(range) do + {:ok, range} = SchematicV.unify(GenLSP.Structures.Range.schematic(), range) + range + end + describe "execute/2 toPipe" do test "can pipe remote calls in single lines" do uri = "file:///some_file.ex" @@ -71,7 +81,8 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d } ) - assert_receive {:request, "workspace/applyEdit", params} + assert_receive {:request, _id, %{"method" => "workspace/applyEdit", "params" => params}, + GenLSP.Requests.WorkspaceApplyEdit} expected_range = %{ "end" => %{"character" => 18, "line" => 2}, @@ -84,9 +95,9 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d "edit" => %{ "changes" => %{ uri => [ - %TextEdit{ - newText: expected_substitution, - range: expected_range + %{ + "newText" => expected_substitution, + "range" => expected_range } ] } @@ -108,7 +119,7 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d assert ElixirLS.LanguageServer.SourceFile.apply_edit( text, - expected_range, + range_to_lsp(expected_range), expected_substitution ) == edited_text end @@ -145,7 +156,8 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d } ) - assert_receive {:request, "workspace/applyEdit", params} + assert_receive {:request, _id, %{"method" => "workspace/applyEdit", "params" => params}, + GenLSP.Requests.WorkspaceApplyEdit} expected_range = %{ "end" => %{"character" => 5, "line" => 5}, @@ -158,9 +170,9 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d "edit" => %{ "changes" => %{ uri => [ - %TextEdit{ - newText: expected_substitution, - range: expected_range + %{ + "newText" => expected_substitution, + "range" => expected_range } ] } @@ -182,7 +194,7 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d assert ElixirLS.LanguageServer.SourceFile.apply_edit( text, - expected_range, + range_to_lsp(expected_range), expected_substitution ) == edited_text end @@ -219,7 +231,8 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d } ) - assert_receive {:request, "workspace/applyEdit", params} + assert_receive {:request, _id, %{"method" => "workspace/applyEdit", "params" => params}, + GenLSP.Requests.WorkspaceApplyEdit} expected_range = %{ "end" => %{"character" => 5, "line" => 5}, @@ -232,9 +245,9 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d "edit" => %{ "changes" => %{ uri => [ - %TextEdit{ - newText: expected_substitution, - range: expected_range + %{ + "newText" => expected_substitution, + "range" => expected_range } ] } @@ -256,7 +269,7 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d assert ElixirLS.LanguageServer.SourceFile.apply_edit( text, - expected_range, + range_to_lsp(expected_range), expected_substitution ) == edited_text end @@ -518,7 +531,8 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d } ) - assert_receive {:request, "workspace/applyEdit", params} + assert_receive {:request, _id, %{"method" => "workspace/applyEdit", "params" => params}, + GenLSP.Requests.WorkspaceApplyEdit} expected_range = %{ "start" => %{"line" => 2, "character" => 4}, @@ -531,9 +545,9 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d "edit" => %{ "changes" => %{ uri => [ - %TextEdit{ - newText: expected_substitution, - range: expected_range + %{ + "newText" => expected_substitution, + "range" => expected_range } ] } @@ -556,7 +570,7 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d assert ElixirLS.LanguageServer.SourceFile.apply_edit( text, - expected_range, + range_to_lsp(expected_range), expected_substitution ) == edited_text end @@ -622,7 +636,8 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d } ) - assert_receive {:request, "workspace/applyEdit", params} + assert_receive {:request, _id, %{"method" => "workspace/applyEdit", "params" => params}, + GenLSP.Requests.WorkspaceApplyEdit} expected_range = %{ "end" => %{"character" => 5, "line" => 5}, @@ -635,9 +650,9 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d "edit" => %{ "changes" => %{ uri => [ - %TextEdit{ - newText: expected_substitution, - range: expected_range + %{ + "newText" => expected_substitution, + "range" => expected_range } ] } @@ -659,7 +674,7 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d assert edited_text == ElixirLS.LanguageServer.SourceFile.apply_edit( text, - expected_range, + range_to_lsp(expected_range), expected_substitution ) end @@ -692,7 +707,8 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d } ) - assert_receive {:request, "workspace/applyEdit", params} + assert_receive {:request, _id, %{"method" => "workspace/applyEdit", "params" => params}, + GenLSP.Requests.WorkspaceApplyEdit} expected_range = %{ "end" => %{"character" => 18, "line" => 2}, @@ -705,9 +721,9 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d "edit" => %{ "changes" => %{ uri => [ - %TextEdit{ - newText: expected_substitution, - range: expected_range + %{ + "newText" => expected_substitution, + "range" => expected_range } ] } @@ -727,7 +743,7 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d assert ElixirLS.LanguageServer.SourceFile.apply_edit( text, - expected_range, + range_to_lsp(expected_range), expected_substitution ) == edited_text end @@ -792,7 +808,8 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d } ) - assert_receive {:request, "workspace/applyEdit", params} + assert_receive {:request, _id, %{"method" => "workspace/applyEdit", "params" => params}, + GenLSP.Requests.WorkspaceApplyEdit} expected_range = %{ "end" => %{"character" => 41, "line" => 4}, @@ -805,9 +822,9 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d "edit" => %{ "changes" => %{ uri => [ - %TextEdit{ - newText: expected_substitution, - range: expected_range + %{ + "newText" => expected_substitution, + "range" => expected_range } ] } @@ -829,7 +846,7 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d assert ElixirLS.LanguageServer.SourceFile.apply_edit( text, - expected_range, + range_to_lsp(expected_range), expected_substitution ) == edited_text end @@ -865,7 +882,8 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d } ) - assert_receive {:request, "workspace/applyEdit", params} + assert_receive {:request, _id, %{"method" => "workspace/applyEdit", "params" => params}, + GenLSP.Requests.WorkspaceApplyEdit} expected_range = %{ "end" => %{"character" => 23, "line" => 2}, @@ -878,9 +896,9 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d "edit" => %{ "changes" => %{ uri => [ - %TextEdit{ - newText: expected_substitution, - range: expected_range + %{ + "newText" => expected_substitution, + "range" => expected_range } ] } @@ -902,7 +920,7 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d assert ElixirLS.LanguageServer.SourceFile.apply_edit( text, - expected_range, + range_to_lsp(expected_range), expected_substitution ) == edited_text end @@ -939,7 +957,8 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d } ) - assert_receive {:request, "workspace/applyEdit", params} + assert_receive {:request, _id, %{"method" => "workspace/applyEdit", "params" => params}, + GenLSP.Requests.WorkspaceApplyEdit} expected_range = %{ "end" => %{"character" => 5, "line" => 5}, @@ -952,9 +971,9 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d "edit" => %{ "changes" => %{ uri => [ - %TextEdit{ - newText: expected_substitution, - range: expected_range + %{ + "newText" => expected_substitution, + "range" => expected_range } ] } @@ -976,7 +995,7 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d assert ElixirLS.LanguageServer.SourceFile.apply_edit( text, - expected_range, + range_to_lsp(expected_range), expected_substitution ) == edited_text end @@ -1011,7 +1030,8 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d } ) - assert_receive {:request, "workspace/applyEdit", params} + assert_receive {:request, _id, %{"method" => "workspace/applyEdit", "params" => params}, + GenLSP.Requests.WorkspaceApplyEdit} expected_range = %{ "end" => %{"character" => 25, "line" => 2}, @@ -1024,9 +1044,9 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d "edit" => %{ "changes" => %{ uri => [ - %TextEdit{ - newText: expected_substitution, - range: expected_range + %{ + "newText" => expected_substitution, + "range" => expected_range } ] } @@ -1049,7 +1069,7 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d assert ElixirLS.LanguageServer.SourceFile.apply_edit( text, - expected_range, + range_to_lsp(expected_range), expected_substitution ) == edited_text end @@ -1084,7 +1104,8 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d } ) - assert_receive {:request, "workspace/applyEdit", params} + assert_receive {:request, _id, %{"method" => "workspace/applyEdit", "params" => params}, + GenLSP.Requests.WorkspaceApplyEdit} expected_range = %{ "end" => %{"character" => 18, "line" => 3}, @@ -1097,9 +1118,9 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d "edit" => %{ "changes" => %{ uri => [ - %TextEdit{ - newText: expected_substitution, - range: expected_range + %{ + "newText" => expected_substitution, + "range" => expected_range } ] } @@ -1121,7 +1142,7 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d assert edited_text == ElixirLS.LanguageServer.SourceFile.apply_edit( text, - expected_range, + range_to_lsp(expected_range), expected_substitution ) end @@ -1187,7 +1208,8 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d } ) - assert_receive {:request, "workspace/applyEdit", params} + assert_receive {:request, _id, %{"method" => "workspace/applyEdit", "params" => params}, + GenLSP.Requests.WorkspaceApplyEdit} expected_range = %{ "end" => %{"character" => 18, "line" => 3}, @@ -1200,9 +1222,9 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d "edit" => %{ "changes" => %{ uri => [ - %TextEdit{ - newText: expected_substitution, - range: expected_range + %{ + "newText" => expected_substitution, + "range" => expected_range } ] } @@ -1222,7 +1244,7 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d assert ElixirLS.LanguageServer.SourceFile.apply_edit( text, - expected_range, + range_to_lsp(expected_range), expected_substitution ) == edited_text end @@ -1248,7 +1270,7 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ManipulatePipesTest d case result do {:ok, _} -> - assert_receive {:request, _, _} + assert_receive {:request, _, _, _} _ -> nil diff --git a/apps/language_server/test/providers/folding_range_test.exs b/apps/language_server/test/providers/folding_range_test.exs index 47a5226aa..c9e468a14 100644 --- a/apps/language_server/test/providers/folding_range_test.exs +++ b/apps/language_server/test/providers/folding_range_test.exs @@ -290,7 +290,7 @@ defmodule ElixirLS.LanguageServer.Providers.FoldingRangeTest do """ test "@moduledoc, @doc, and stand-alone heredocs", %{ranges_result: ranges_result, text: text} do assert {:ok, ranges} = ranges_result - expected = [{1, 2, :comment}, {5, 6, :comment}, {9, 10, :region}] + expected = [{1, 2, "comment"}, {5, 6, "comment"}, {9, 10, "region"}] assert compare_condensed_ranges(ranges, expected, text) end @@ -369,7 +369,7 @@ defmodule ElixirLS.LanguageServer.Providers.FoldingRangeTest do """ test "@doc with ~S sigil", %{ranges_result: ranges_result, text: text} do assert {:ok, ranges} = ranges_result - assert compare_condensed_ranges(ranges, [{1, 2, :comment}, {5, 6, :comment}], text) + assert compare_condensed_ranges(ranges, [{1, 2, "comment"}, {5, 6, "comment"}], text) end defp fold_via_special_tokens(%{text: text} = context) do @@ -486,7 +486,7 @@ defmodule ElixirLS.LanguageServer.Providers.FoldingRangeTest do """ test "@doc false does not create a folding range", %{ranges_result: ranges_result, text: text} do assert {:ok, ranges} = ranges_result - expected = [{0, 5, :region}, {2, 4, :region}] + expected = [{0, 5, "region"}, {2, 4, "region"}] assert compare_condensed_ranges(ranges, expected, text) end @@ -503,7 +503,7 @@ defmodule ElixirLS.LanguageServer.Providers.FoldingRangeTest do """ test "@typedoc example", %{ranges_result: ranges_result, text: text} do assert {:ok, ranges} = ranges_result - expected = [{0, 7, :region}, {4, 6, :region}] + expected = [{0, 7, "region"}, {4, 6, "region"}] assert compare_condensed_ranges(ranges, expected, text) end @@ -522,7 +522,7 @@ defmodule ElixirLS.LanguageServer.Providers.FoldingRangeTest do text: text } do assert {:ok, ranges} = ranges_result - expected = [{0, 6, :region}, {3, 5, :region}] + expected = [{0, 6, "region"}, {3, 5, "region"}] assert compare_condensed_ranges(ranges, expected, text) end @@ -536,10 +536,10 @@ defmodule ElixirLS.LanguageServer.Providers.FoldingRangeTest do result_condensed = result |> Enum.map(fn - %{startLine: start_line, endLine: end_line, kind?: kind} -> + %GenLSP.Structures.FoldingRange{start_line: start_line, end_line: end_line, kind: kind} -> {start_line, end_line, kind} - %{startLine: start_line, endLine: end_line} -> + %GenLSP.Structures.FoldingRange{start_line: start_line, end_line: end_line} -> {start_line, end_line, :any} end) |> Enum.sort() diff --git a/apps/language_server/test/providers/formatting_test.exs b/apps/language_server/test/providers/formatting_test.exs index f4689f8b5..d56dc7b22 100644 --- a/apps/language_server/test/providers/formatting_test.exs +++ b/apps/language_server/test/providers/formatting_test.exs @@ -2,10 +2,11 @@ defmodule ElixirLS.LanguageServer.Providers.FormattingTest do use ElixirLS.Utils.MixTest.Case, async: false import ElixirLS.LanguageServer.Test.PlatformTestHelpers alias ElixirLS.LanguageServer.Providers.Formatting - alias ElixirLS.LanguageServer.Protocol.TextEdit + alias GenLSP.Structures.TextEdit alias ElixirLS.LanguageServer.SourceFile alias ElixirLS.LanguageServer.MixProjectCache alias ElixirLS.LanguageServer.Test.FixtureHelpers + import ElixirLS.LanguageServer.RangeUtils setup do {:ok, _} = start_supervised(MixProjectCache) @@ -40,24 +41,18 @@ defmodule ElixirLS.LanguageServer.Providers.FormattingTest do assert changes == [ %TextEdit{ - newText: ")", - range: %{ - "end" => %{"character" => 23, "line" => 4}, - "start" => %{"character" => 23, "line" => 4} - } + new_text: ")", + range: range(4, 23, 4, 23) }, %TextEdit{ - newText: "(", - range: %{ - "end" => %{"character" => 16, "line" => 4}, - "start" => %{"character" => 15, "line" => 4} - } + new_text: "(", + range: range(4, 15, 4, 16) } ] assert Enum.all?(changes, fn change -> - assert_position_type(change.range["end"]) and - assert_position_type(change.range["start"]) + assert_position_type(change.range.end) and + assert_position_type(change.range.start) end) end) end @@ -90,24 +85,18 @@ defmodule ElixirLS.LanguageServer.Providers.FormattingTest do assert changes == [ %TextEdit{ - newText: ")", - range: %{ - "end" => %{"character" => 23, "line" => 4}, - "start" => %{"character" => 23, "line" => 4} - } + new_text: ")", + range: range(4, 23, 4, 23) }, %TextEdit{ - newText: "(", - range: %{ - "end" => %{"character" => 16, "line" => 4}, - "start" => %{"character" => 15, "line" => 4} - } + new_text: "(", + range: range(4, 15, 4, 16) } ] assert Enum.all?(changes, fn change -> - assert_position_type(change.range["end"]) and - assert_position_type(change.range["start"]) + assert_position_type(change.range.end) and + assert_position_type(change.range.start) end) end) end @@ -141,24 +130,18 @@ defmodule ElixirLS.LanguageServer.Providers.FormattingTest do assert changes == [ %TextEdit{ - newText: ")", - range: %{ - "end" => %{"character" => 23, "line" => 4}, - "start" => %{"character" => 23, "line" => 4} - } + new_text: ")", + range: range(4, 23, 4, 23) }, %TextEdit{ - newText: "(", - range: %{ - "end" => %{"character" => 16, "line" => 4}, - "start" => %{"character" => 15, "line" => 4} - } + new_text: "(", + range: range(4, 15, 4, 16) } ] assert Enum.all?(changes, fn change -> - assert_position_type(change.range["end"]) and - assert_position_type(change.range["start"]) + assert_position_type(change.range.end) and + assert_position_type(change.range.start) end) end) end @@ -194,59 +177,38 @@ defmodule ElixirLS.LanguageServer.Providers.FormattingTest do assert changes == [ %TextEdit{ - newText: "\n", - range: %{ - "end" => %{"character" => 0, "line" => 7}, - "start" => %{"character" => 3, "line" => 6} - } + new_text: "\n", + range: range(6, 3, 7, 0) }, %TextEdit{ - newText: "\n", - range: %{ - "end" => %{"character" => 0, "line" => 6}, - "start" => %{"character" => 5, "line" => 5} - } + new_text: "\n", + range: range(5, 5, 6, 0) }, %TextEdit{ - newText: ")\n", - range: %{ - "end" => %{"character" => 0, "line" => 5}, - "start" => %{"character" => 23, "line" => 4} - } + new_text: ")\n", + range: range(4, 23, 5, 0) }, %TextEdit{ - newText: "(", - range: %{ - "end" => %{"character" => 16, "line" => 4}, - "start" => %{"character" => 15, "line" => 4} - } + new_text: "(", + range: range(4, 15, 4, 16) }, %TextEdit{ - newText: "\n", - range: %{ - "end" => %{"character" => 0, "line" => 4}, - "start" => %{"character" => 25, "line" => 3} - } + new_text: "\n", + range: range(3, 25, 4, 0) }, %TextEdit{ - newText: "\n\n", - range: %{ - "end" => %{"character" => 0, "line" => 3}, - "start" => %{"character" => 16, "line" => 1} - } + new_text: "\n\n", + range: range(1, 16, 3, 0) }, %TextEdit{ - newText: "\n", - range: %{ - "end" => %{"character" => 0, "line" => 1}, - "start" => %{"character" => 21, "line" => 0} - } + new_text: "\n", + range: range(0, 21, 1, 0) } ] assert Enum.all?(changes, fn change -> - assert_position_type(change.range["end"]) and - assert_position_type(change.range["start"]) + assert_position_type(change.range.end) and + assert_position_type(change.range.start) end) end) end @@ -314,29 +276,23 @@ defmodule ElixirLS.LanguageServer.Providers.FormattingTest do assert changes == [ %TextEdit{ - newText: ")", - range: %{ - "end" => %{"character" => 2, "line" => 7}, - "start" => %{"character" => 2, "line" => 7} - } + new_text: ")", + range: range(7, 2, 7, 2) }, %TextEdit{ - newText: "(", - range: %{ - "end" => %{"character" => 20, "line" => 4}, - "start" => %{"character" => 15, "line" => 4} - } + new_text: "(", + range: range(4, 15, 4, 20) } ] assert Enum.all?(changes, fn change -> - assert_position_type(change.range["end"]) and - assert_position_type(change.range["start"]) + assert_position_type(change.range.end) and + assert_position_type(change.range.start) end) end) end - defp assert_position_type(%{"character" => ch, "line" => line}), + defp assert_position_type(%GenLSP.Structures.Position{character: ch, line: line}), do: is_integer(ch) and is_integer(line) @tag :fixture @@ -392,18 +348,12 @@ defmodule ElixirLS.LanguageServer.Providers.FormattingTest do assert changes == [ %TextEdit{ - newText: ")", - range: %{ - "end" => %{"character" => 12, "line" => 0}, - "start" => %{"character" => 12, "line" => 0} - } + new_text: ")", + range: range(0, 12, 0, 12) }, %TextEdit{ - newText: "(", - range: %{ - "end" => %{"character" => 8, "line" => 0}, - "start" => %{"character" => 7, "line" => 0} - } + new_text: "(", + range: range(0, 7, 0, 8) } ] end) @@ -432,18 +382,12 @@ defmodule ElixirLS.LanguageServer.Providers.FormattingTest do assert changes == [ %TextEdit{ - newText: ")", - range: %{ - "end" => %{"character" => 16, "line" => 0}, - "start" => %{"character" => 16, "line" => 0} - } + new_text: ")", + range: range(0, 16, 0, 16) }, %TextEdit{ - newText: "(", - range: %{ - "end" => %{"character" => 8, "line" => 0}, - "start" => %{"character" => 7, "line" => 0} - } + new_text: "(", + range: range(0, 7, 0, 8) } ] end) @@ -472,18 +416,12 @@ defmodule ElixirLS.LanguageServer.Providers.FormattingTest do assert changes == [ %TextEdit{ - newText: ")", - range: %{ - "end" => %{"character" => 213, "line" => 0}, - "start" => %{"character" => 213, "line" => 0} - } + new_text: ")", + range: range(0, 213, 0, 213) }, %TextEdit{ - newText: "(", - range: %{ - "end" => %{"character" => 8, "line" => 0}, - "start" => %{"character" => 7, "line" => 0} - } + new_text: "(", + range: range(0, 7, 0, 8) } ] end) @@ -518,7 +456,7 @@ defmodule ElixirLS.LanguageServer.Providers.FormattingTest do def assert_formatted(path, project_dir, mix_file?) do assert match?( - {:ok, [%ElixirLS.LanguageServer.Protocol.TextEdit{} | _]}, + {:ok, [%GenLSP.Structures.TextEdit{} | _]}, format(path, project_dir, mix_file?) ), "expected '#{path}' to be formatted" diff --git a/apps/language_server/test/providers/hover_test.exs b/apps/language_server/test/providers/hover_test.exs index 6e692a9c6..0f3d9d72c 100644 --- a/apps/language_server/test/providers/hover_test.exs +++ b/apps/language_server/test/providers/hover_test.exs @@ -44,7 +44,10 @@ defmodule ElixirLS.LanguageServer.Providers.HoverTest do {line, char} = SourceFile.lsp_position_to_elixir(parser_context.source_file.text, {line, char}) - assert {:ok, %{"contents" => %{kind: "markdown", value: v}}} = + assert {:ok, + %GenLSP.Structures.Hover{ + contents: %GenLSP.Structures.MarkupContent{kind: "markdown", value: v} + }} = Hover.hover(parser_context, line, char) assert String.starts_with?( @@ -68,7 +71,10 @@ defmodule ElixirLS.LanguageServer.Providers.HoverTest do {line, char} = SourceFile.lsp_position_to_elixir(parser_context.source_file.text, {line, char}) - assert {:ok, %{"contents" => %{kind: "markdown", value: v}}} = + assert {:ok, + %GenLSP.Structures.Hover{ + contents: %GenLSP.Structures.MarkupContent{kind: "markdown", value: v} + }} = Hover.hover(parser_context, line, char) assert String.starts_with?( @@ -90,7 +96,10 @@ defmodule ElixirLS.LanguageServer.Providers.HoverTest do {line, char} = SourceFile.lsp_position_to_elixir(parser_context.source_file.text, {line, char}) - assert {:ok, %{"contents" => %{kind: "markdown", value: v}}} = + assert {:ok, + %GenLSP.Structures.Hover{ + contents: %GenLSP.Structures.MarkupContent{kind: "markdown", value: v} + }} = Hover.hover(parser_context, line, char) assert String.starts_with?( @@ -112,7 +121,10 @@ defmodule ElixirLS.LanguageServer.Providers.HoverTest do {line, char} = SourceFile.lsp_position_to_elixir(parser_context.source_file.text, {line, char}) - assert {:ok, %{"contents" => %{kind: "markdown", value: v}}} = + assert {:ok, + %GenLSP.Structures.Hover{ + contents: %GenLSP.Structures.MarkupContent{kind: "markdown", value: v} + }} = Hover.hover(parser_context, line, char) assert String.starts_with?( @@ -134,7 +146,10 @@ defmodule ElixirLS.LanguageServer.Providers.HoverTest do {line, char} = SourceFile.lsp_position_to_elixir(parser_context.source_file.text, {line, char}) - assert {:ok, %{"contents" => %{kind: "markdown", value: v}}} = + assert {:ok, + %GenLSP.Structures.Hover{ + contents: %GenLSP.Structures.MarkupContent{kind: "markdown", value: v} + }} = Hover.hover(parser_context, line, char) assert String.starts_with?( @@ -158,7 +173,10 @@ defmodule ElixirLS.LanguageServer.Providers.HoverTest do {line, char} = SourceFile.lsp_position_to_elixir(parser_context.source_file.text, {line, char}) - assert {:ok, %{"contents" => %{kind: "markdown", value: v}}} = + assert {:ok, + %GenLSP.Structures.Hover{ + contents: %GenLSP.Structures.MarkupContent{kind: "markdown", value: v} + }} = Hover.hover(parser_context, line, char) assert String.starts_with?(v, "```elixir\n:timer.sleep(") @@ -182,7 +200,10 @@ defmodule ElixirLS.LanguageServer.Providers.HoverTest do {line, char} = SourceFile.lsp_position_to_elixir(parser_context.source_file.text, {line, char}) - assert {:ok, %{"contents" => %{kind: "markdown", value: v}}} = + assert {:ok, + %GenLSP.Structures.Hover{ + contents: %GenLSP.Structures.MarkupContent{kind: "markdown", value: v} + }} = Hover.hover(parser_context, line, char) assert String.starts_with?( @@ -204,7 +225,10 @@ defmodule ElixirLS.LanguageServer.Providers.HoverTest do {line, char} = SourceFile.lsp_position_to_elixir(parser_context.source_file.text, {line, char}) - assert {:ok, %{"contents" => %{kind: "markdown", value: v}}} = + assert {:ok, + %GenLSP.Structures.Hover{ + contents: %GenLSP.Structures.MarkupContent{kind: "markdown", value: v} + }} = Hover.hover(parser_context, line, char) assert String.starts_with?( @@ -226,7 +250,10 @@ defmodule ElixirLS.LanguageServer.Providers.HoverTest do {line, char} = SourceFile.lsp_position_to_elixir(parser_context.source_file.text, {line, char}) - assert {:ok, %{"contents" => %{kind: "markdown", value: v}}} = + assert {:ok, + %GenLSP.Structures.Hover{ + contents: %GenLSP.Structures.MarkupContent{kind: "markdown", value: v} + }} = Hover.hover(parser_context, line, char) assert String.starts_with?( diff --git a/apps/language_server/test/providers/implementation_test.exs b/apps/language_server/test/providers/implementation_test.exs index a6e343cd8..df879f38e 100644 --- a/apps/language_server/test/providers/implementation_test.exs +++ b/apps/language_server/test/providers/implementation_test.exs @@ -2,11 +2,11 @@ defmodule ElixirLS.LanguageServer.Providers.ImplementationTest do use ExUnit.Case, async: true alias ElixirLS.LanguageServer.Providers.Implementation - alias ElixirLS.LanguageServer.Protocol.Location alias ElixirLS.LanguageServer.SourceFile alias ElixirLS.LanguageServer.Test.FixtureHelpers alias ElixirLS.LanguageServer.Test.ParserContextBuilder require ElixirLS.Test.TextLoc + import ElixirLS.LanguageServer.RangeUtils test "find implementations" do # force load as currently only loaded or loadable modules that are a part @@ -27,13 +27,9 @@ defmodule ElixirLS.LanguageServer.Providers.ImplementationTest do {line, char} = SourceFile.lsp_position_to_elixir(parser_context.source_file.text, {line, char}) - assert {:ok, [%Location{uri: ^uri, range: range}]} = + assert {:ok, [%GenLSP.Structures.Location{uri: ^uri, range: range}]} = Implementation.implementation(uri, parser_context, line, char, File.cwd!()) - assert range == - %{ - "start" => %{"line" => 5, "character" => 0}, - "end" => %{"line" => 13, "character" => 3} - } + assert range == range(5, 0, 13, 3) end end diff --git a/apps/language_server/test/providers/on_type_formatting_test.exs b/apps/language_server/test/providers/on_type_formatting_test.exs index 539f13770..e8b405366 100644 --- a/apps/language_server/test/providers/on_type_formatting_test.exs +++ b/apps/language_server/test/providers/on_type_formatting_test.exs @@ -3,6 +3,7 @@ defmodule ElixirLS.LanguageServer.Providers.OnTypeFormattingTest do alias ElixirLS.LanguageServer.Providers.OnTypeFormatting alias ElixirLS.LanguageServer.SourceFile + import ElixirLS.LanguageServer.RangeUtils test "insert `end` after `do`" do text = """ @@ -11,12 +12,9 @@ defmodule ElixirLS.LanguageServer.Providers.OnTypeFormattingTest do assert {:ok, [ - %{ - "newText" => "\nend", - "range" => %{ - "start" => %{"character" => 0, "line" => 1}, - "end" => %{"character" => 0, "line" => 1} - } + %GenLSP.Structures.TextEdit{ + new_text: "\nend", + range: range(1, 0, 1, 0) } ]} = OnTypeFormatting.format(%SourceFile{text: text}, 1, 0, "\n", []) end @@ -30,12 +28,9 @@ defmodule ElixirLS.LanguageServer.Providers.OnTypeFormattingTest do assert {:ok, [ - %{ - "newText" => "\n end", - "range" => %{ - "start" => %{"character" => 0, "line" => 2}, - "end" => %{"character" => 0, "line" => 2} - } + %GenLSP.Structures.TextEdit{ + new_text: "\n end", + range: range(2, 0, 2, 0) } ]} = OnTypeFormatting.format(%SourceFile{text: text}, 2, 0, "\n", []) end diff --git a/apps/language_server/test/providers/references_test.exs b/apps/language_server/test/providers/references_test.exs index a72f251c4..8170e5065 100644 --- a/apps/language_server/test/providers/references_test.exs +++ b/apps/language_server/test/providers/references_test.exs @@ -8,6 +8,7 @@ defmodule ElixirLS.LanguageServer.Providers.ReferencesTest do alias ElixirLS.LanguageServer.Build alias ElixirLS.LanguageServer.Test.ParserContextBuilder require ElixirLS.Test.TextLoc + import ElixirLS.LanguageServer.RangeUtils setup_all context do {:ok, pid} = Tracer.start_link([]) @@ -57,9 +58,9 @@ defmodule ElixirLS.LanguageServer.Providers.ReferencesTest do list = References.references(parser_context, uri, line, char, true, File.cwd!()) assert length(list) == 3 - assert Enum.any?(list, &(&1["uri"] |> String.ends_with?("references_remote.ex"))) - assert Enum.any?(list, &(&1["uri"] |> String.ends_with?("references_imported.ex"))) - assert Enum.any?(list, &(&1["uri"] |> String.ends_with?("references_referenced.ex"))) + assert Enum.any?(list, &(&1.uri |> String.ends_with?("references_remote.ex"))) + assert Enum.any?(list, &(&1.uri |> String.ends_with?("references_imported.ex"))) + assert Enum.any?(list, &(&1.uri |> String.ends_with?("references_referenced.ex"))) end test "finds local, remote and imported references to a macro" do @@ -80,9 +81,9 @@ defmodule ElixirLS.LanguageServer.Providers.ReferencesTest do list = References.references(parser_context, uri, line, char, true, File.cwd!()) assert length(list) == 3 - assert Enum.any?(list, &(&1["uri"] |> String.ends_with?("references_remote.ex"))) - assert Enum.any?(list, &(&1["uri"] |> String.ends_with?("references_imported.ex"))) - assert Enum.any?(list, &(&1["uri"] |> String.ends_with?("references_referenced.ex"))) + assert Enum.any?(list, &(&1.uri |> String.ends_with?("references_remote.ex"))) + assert Enum.any?(list, &(&1.uri |> String.ends_with?("references_imported.ex"))) + assert Enum.any?(list, &(&1.uri |> String.ends_with?("references_referenced.ex"))) end test "find a references to a macro generated function call" do @@ -100,12 +101,9 @@ defmodule ElixirLS.LanguageServer.Providers.ReferencesTest do SourceFile.lsp_position_to_elixir(parser_context.source_file.text, {line, char}) assert References.references(parser_context, uri, line, char, true, File.cwd!()) == [ - %{ - "range" => %{ - "end" => %{"character" => 16, "line" => 6}, - "start" => %{"character" => 4, "line" => 6} - }, - "uri" => uri + %GenLSP.Structures.Location{ + range: range(6, 4, 6, 16), + uri: uri } ] end @@ -125,12 +123,9 @@ defmodule ElixirLS.LanguageServer.Providers.ReferencesTest do SourceFile.lsp_position_to_elixir(parser_context.source_file.text, {line, char}) assert References.references(parser_context, uri, line, char, true, File.cwd!()) == [ - %{ - "range" => %{ - "start" => %{"line" => 10, "character" => 4}, - "end" => %{"line" => 10, "character" => 22} - }, - "uri" => uri + %GenLSP.Structures.Location{ + range: range(10, 4, 10, 22), + uri: uri } ] end @@ -150,19 +145,13 @@ defmodule ElixirLS.LanguageServer.Providers.ReferencesTest do SourceFile.lsp_position_to_elixir(parser_context.source_file.text, {line, char}) assert References.references(parser_context, uri, line, char, true, File.cwd!()) == [ - %{ - "range" => %{ - "end" => %{"character" => 23, "line" => 2}, - "start" => %{"character" => 4, "line" => 2} - }, - "uri" => uri + %GenLSP.Structures.Location{ + range: range(2, 4, 2, 23), + uri: uri }, - %{ - "range" => %{ - "end" => %{"character" => 31, "line" => 4}, - "start" => %{"character" => 12, "line" => 4} - }, - "uri" => uri + %GenLSP.Structures.Location{ + range: range(4, 12, 4, 31), + uri: uri } ] end @@ -182,19 +171,13 @@ defmodule ElixirLS.LanguageServer.Providers.ReferencesTest do SourceFile.lsp_position_to_elixir(parser_context.source_file.text, {line, char}) assert References.references(parser_context, uri, line, char, true, File.cwd!()) == [ - %{ - "range" => %{ - "end" => %{"character" => 23, "line" => 24}, - "start" => %{"character" => 2, "line" => 24} - }, - "uri" => uri + %GenLSP.Structures.Location{ + range: range(24, 2, 24, 23), + uri: uri }, - %{ - "range" => %{ - "end" => %{"character" => 25, "line" => 27}, - "start" => %{"character" => 4, "line" => 27} - }, - "uri" => uri + %GenLSP.Structures.Location{ + range: range(27, 4, 27, 25), + uri: uri } ] end @@ -217,8 +200,8 @@ defmodule ElixirLS.LanguageServer.Providers.ReferencesTest do list = References.references(parser_context, uri, line, char, true, File.cwd!()) assert length(list) == 2 - assert Enum.any?(list, &(&1["uri"] |> String.ends_with?("references_erlang.ex"))) - assert Enum.any?(list, &(&1["uri"] |> String.ends_with?("references_referenced.ex"))) + assert Enum.any?(list, &(&1.uri |> String.ends_with?("references_erlang.ex"))) + assert Enum.any?(list, &(&1.uri |> String.ends_with?("references_referenced.ex"))) end test "finds remote references to erlang module" do @@ -239,8 +222,8 @@ defmodule ElixirLS.LanguageServer.Providers.ReferencesTest do list = References.references(parser_context, uri, line, char, true, File.cwd!()) assert length(list) == 2 - assert Enum.any?(list, &(&1["uri"] |> String.ends_with?("references_erlang.ex"))) - assert Enum.any?(list, &(&1["uri"] |> String.ends_with?("references_referenced.ex"))) + assert Enum.any?(list, &(&1.uri |> String.ends_with?("references_erlang.ex"))) + assert Enum.any?(list, &(&1.uri |> String.ends_with?("references_referenced.ex"))) end test "finds alias references" do @@ -260,9 +243,9 @@ defmodule ElixirLS.LanguageServer.Providers.ReferencesTest do list = References.references(parser_context, uri, line, char, true, File.cwd!()) - |> Enum.filter(&String.ends_with?(&1["uri"], "references_alias.ex")) + |> Enum.filter(&String.ends_with?(&1.uri, "references_alias.ex")) - references_lines = Enum.map(list, & &1["range"]["start"]["line"]) + references_lines = Enum.map(list, & &1.range.start.line) assert references_lines == [1, 2, 3, 3, 4, 4, 7, 11, 15, 19, 20] end diff --git a/apps/language_server/test/providers/selection_ranges_test.exs b/apps/language_server/test/providers/selection_ranges_test.exs index aeba827e2..90bd08eef 100644 --- a/apps/language_server/test/providers/selection_ranges_test.exs +++ b/apps/language_server/test/providers/selection_ranges_test.exs @@ -3,10 +3,12 @@ defmodule ElixirLS.LanguageServer.Providers.SelectionRangesTest do alias ElixirLS.LanguageServer.Providers.SelectionRanges alias ElixirLS.LanguageServer.{SourceFile} - import ElixirLS.LanguageServer.Protocol + import ElixirLS.LanguageServer.RangeUtils defp get_ranges(text, line, character) do - SelectionRanges.selection_ranges(text, [%{"line" => line, "character" => character}]) + SelectionRanges.selection_ranges(text, [ + %GenLSP.Structures.Position{line: line, character: character} + ]) |> hd |> flatten end @@ -17,7 +19,7 @@ defmodule ElixirLS.LanguageServer.Providers.SelectionRangesTest do defp flatten(nil, acc), do: acc - defp flatten(%{"range" => range, "parent" => parent}, acc) do + defp flatten(%GenLSP.Structures.SelectionRange{range: range, parent: parent}, acc) do flatten(parent, [range | acc]) end diff --git a/apps/language_server/test/providers/workspace_symbols_test.exs b/apps/language_server/test/providers/workspace_symbols_test.exs index 179acdd03..3f7e8efcc 100644 --- a/apps/language_server/test/providers/workspace_symbols_test.exs +++ b/apps/language_server/test/providers/workspace_symbols_test.exs @@ -64,9 +64,9 @@ defmodule ElixirLS.LanguageServer.Providers.WorkspaceSymbolsTest do assert module.kind == 11 assert module.location.uri |> String.ends_with?("lib/workspace_symbols.ex") - assert module.location.range == %{ - end: %{character: 0, line: 1}, - start: %{character: 0, line: 0} + assert module.location.range == %GenLSP.Structures.Range{ + end: %GenLSP.Structures.Position{character: 0, line: 1}, + start: %GenLSP.Structures.Position{character: 0, line: 0} } assert WorkspaceSymbols.symbols("work") @@ -95,14 +95,14 @@ defmodule ElixirLS.LanguageServer.Providers.WorkspaceSymbolsTest do assert some_function.kind == 12 - assert some_function.containerName == "ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols" + assert some_function.container_name == "ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols" assert some_function.location.uri |> String.ends_with?("lib/workspace_symbols.ex") - assert some_function.location.range == %{ - end: %{character: 0, line: 2}, - start: %{character: 0, line: 1} + assert some_function.location.range == %GenLSP.Structures.Range{ + end: %GenLSP.Structures.Position{character: 0, line: 2}, + start: %GenLSP.Structures.Position{character: 0, line: 1} } assert WorkspaceSymbols.symbols("fun") @@ -133,14 +133,14 @@ defmodule ElixirLS.LanguageServer.Providers.WorkspaceSymbolsTest do assert some_type.kind == 5 - assert some_type.containerName == "ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols" + assert some_type.container_name == "ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols" assert some_type.location.uri |> String.ends_with?("lib/workspace_symbols.ex") - assert some_type.location.range == %{ - end: %{character: 0, line: 8}, - start: %{character: 0, line: 7} + assert some_type.location.range == %GenLSP.Structures.Range{ + end: %GenLSP.Structures.Position{character: 0, line: 8}, + start: %GenLSP.Structures.Position{character: 0, line: 7} } assert Enum.any?( @@ -176,14 +176,14 @@ defmodule ElixirLS.LanguageServer.Providers.WorkspaceSymbolsTest do assert some_callback.kind == 24 - assert some_callback.containerName == "ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols" + assert some_callback.container_name == "ElixirLS.LanguageServer.Fixtures.WorkspaceSymbols" assert some_callback.location.uri |> String.ends_with?("lib/workspace_symbols.ex") - assert some_callback.location.range == %{ - end: %{character: 0, line: 5}, - start: %{character: 0, line: 4} + assert some_callback.location.range == %GenLSP.Structures.Range{ + end: %GenLSP.Structures.Position{character: 0, line: 5}, + start: %GenLSP.Structures.Position{character: 0, line: 4} } assert Enum.any?( diff --git a/apps/language_server/test/range_utils_test.exs b/apps/language_server/test/range_utils_test.exs index 23f1160fc..6080c025c 100644 --- a/apps/language_server/test/range_utils_test.exs +++ b/apps/language_server/test/range_utils_test.exs @@ -1,7 +1,6 @@ defmodule ElixirLS.LanguageServer.RangeUtilsTest do use ExUnit.Case - import ElixirLS.LanguageServer.Protocol import ElixirLS.LanguageServer.RangeUtils describe "valid?/1" do diff --git a/apps/language_server/test/server_test.exs b/apps/language_server/test/server_test.exs index 67b02b46c..090f4f828 100644 --- a/apps/language_server/test/server_test.exs +++ b/apps/language_server/test/server_test.exs @@ -94,12 +94,12 @@ defmodule ElixirLS.LanguageServer.ServerTest do ) assert_receive(%{"id" => 1, "result" => %{"capabilities" => %{}}}, 1000) - Server.receive_packet(server, notification("initialized")) + Server.receive_packet(server, notification("initialized", %{})) uri = root_uri() assert_receive( %{ - "id" => 1, + "id" => id, "method" => "workspace/configuration", "params" => %{"items" => [%{"scopeUri" => ^uri, "section" => "elixirLS"}]} }, @@ -107,7 +107,7 @@ defmodule ElixirLS.LanguageServer.ServerTest do ) JsonRpc.receive_packet( - response(1, [ + response(id, [ %{ "mixEnv" => "dev", "autoBuild" => false, @@ -136,7 +136,7 @@ defmodule ElixirLS.LanguageServer.ServerTest do ) assert_receive(%{"id" => 1, "result" => %{"capabilities" => %{}}}, 1000) - Server.receive_packet(server, notification("initialized")) + Server.receive_packet(server, notification("initialized", %{})) uri = root_uri() assert_receive( @@ -198,7 +198,7 @@ defmodule ElixirLS.LanguageServer.ServerTest do ) assert_receive(%{"id" => 1, "result" => %{"capabilities" => %{}}}, 1000) - Server.receive_packet(server, notification("initialized")) + Server.receive_packet(server, notification("initialized", %{})) uri = root_uri() refute_receive( @@ -249,7 +249,7 @@ defmodule ElixirLS.LanguageServer.ServerTest do ) assert_receive(%{"id" => 1, "result" => %{"capabilities" => %{}}}, 1000) - Server.receive_packet(server, notification("initialized")) + Server.receive_packet(server, notification("initialized", %{})) assert_receive( %{ @@ -909,7 +909,7 @@ defmodule ElixirLS.LanguageServer.ServerTest do "type" => 2 } }, - 1000 + 3000 state = :sys.get_state(server) refute Map.has_key?(state.source_files, uri) @@ -1308,14 +1308,16 @@ defmodule ElixirLS.LanguageServer.ServerTest do test "auto complete", %{server: server} do in_fixture(__DIR__, "clean", fn -> uri = "file:///file.ex" - code = ~S( - defmodule MyModule do - def my_fn, do: GenSer - end - ) + + code = """ + defmodule MyModule do + def my_fn, do: GenServe + end + """ + fake_initialize(server) Server.receive_packet(server, did_open(uri, "elixir", 1, code)) - Server.receive_packet(server, completion_req(1, uri, 2, 25)) + Server.receive_packet(server, completion_req(1, uri, 1, 22)) resp = assert_receive(%{"id" => 1}, 10000) @@ -1568,7 +1570,14 @@ defmodule ElixirLS.LanguageServer.ServerTest do initialize(server) Server.receive_packet(server, did_open(uri, "elixir", 1, code)) wait_until_compiled(server) - Server.receive_packet(server, formatting_req(2, uri, %{})) + + Server.receive_packet( + server, + formatting_req(2, uri, %{ + "tabSize" => 2, + "insertSpaces" => true + }) + ) resp = assert_receive(%{"id" => 2}, 1000) @@ -1592,7 +1601,14 @@ defmodule ElixirLS.LanguageServer.ServerTest do # Now try it in a subdirectory with its own .formatter.exs file that does not define a max line length. subdir_uri = Path.join([root_uri(), "lib/file.ex"]) Server.receive_packet(server, did_open(subdir_uri, "elixir", 1, code)) - Server.receive_packet(server, formatting_req(3, subdir_uri, %{})) + + Server.receive_packet( + server, + formatting_req(3, subdir_uri, %{ + "tabSize" => 2, + "insertSpaces" => true + }) + ) resp = assert_receive(%{"id" => 3}, 1000) @@ -2204,7 +2220,7 @@ defmodule ElixirLS.LanguageServer.ServerTest do test "single file", %{server: server} do in_fixture(__DIR__, "no_mixfile", fn -> Server.receive_packet(server, initialize_req(1, nil, %{})) - Server.receive_packet(server, notification("initialized")) + Server.receive_packet(server, notification("initialized", %{})) Server.receive_packet( server, diff --git a/apps/language_server/test/source_file_test.exs b/apps/language_server/test/source_file_test.exs index 7581ad0cd..2b6ddd237 100644 --- a/apps/language_server/test/source_file_test.exs +++ b/apps/language_server/test/source_file_test.exs @@ -3,6 +3,7 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do use ExUnitProperties alias ElixirLS.LanguageServer.SourceFile + import ElixirLS.LanguageServer.RangeUtils test "format_spec/2 with nil" do assert SourceFile.format_spec(nil, []) == "" @@ -105,19 +106,19 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do high = map_size(line_offsets) if high == 0 do - %{"line" => 0, "character" => offset} + %GenLSP.Structures.Position{line: 0, character: offset} else low = find_low_high(low, high, offset, line_offsets) # low is the least x for which the line offset is larger than the current offset # or array.length if no line offset is larger than the current offset line = low - 1 - %{"line" => line, "character" => offset - line_offsets[line]} + %GenLSP.Structures.Position{line: line, character: offset - line_offsets[line]} end end def position_create(l, c) do - %{"line" => l, "character" => c} + %GenLSP.Structures.Position{line: l, character: c} end def position_after_substring(text, sub_text) do @@ -128,19 +129,15 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do def range_for_substring(source_file, sub_text) do index = index_of(source_file.text, sub_text) - %{ - "start" => position_at(source_file.text, index), - "end" => position_at(source_file.text, index + (String.to_charlist(sub_text) |> length)) + %GenLSP.Structures.Range{ + start: position_at(source_file.text, index), + end: position_at(source_file.text, index + (String.to_charlist(sub_text) |> length)) } end def range_after_substring(source_file, sub_text) do pos = position_after_substring(source_file.text, sub_text) - %{"start" => pos, "end" => pos} - end - - def range_create(sl, sc, el, ec) do - %{"start" => position_create(sl, sc), "end" => position_create(el, ec)} + %GenLSP.Structures.Range{start: pos, end: pos} end test "empty update" do @@ -150,12 +147,12 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do test "full update" do assert %SourceFile{text: "efg456"} = - SourceFile.apply_content_changes(new("abc123"), [%{"text" => "efg456"}]) + SourceFile.apply_content_changes(new("abc123"), [%{text: "efg456"}]) assert %SourceFile{text: "world"} = SourceFile.apply_content_changes(new("abc123"), [ - %{"text" => "hello"}, - %{"text" => "world"} + %{text: "hello"}, + %{text: "world"} ]) end @@ -165,8 +162,8 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do assert %SourceFile{text: "function abc() {\n console.log(\"\");\n}"} = SourceFile.apply_content_changes(sf, [ %{ - "text" => "", - "range" => range_for_substring(sf, "hello, world!") + text: "", + range: range_for_substring(sf, "hello, world!") } ]) end @@ -177,8 +174,8 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do assert %SourceFile{text: "function abc() {\n \n}"} = SourceFile.apply_content_changes(sf, [ %{ - "text" => "", - "range" => range_for_substring(sf, " foo();\n bar();\n") + text: "", + range: range_for_substring(sf, " foo();\n bar();\n") } ]) end @@ -189,8 +186,8 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do assert %SourceFile{text: "function abc() {\n \n \n}"} = SourceFile.apply_content_changes(sf, [ %{ - "text" => "", - "range" => range_for_substring(sf, "foo();\n bar();") + text: "", + range: range_for_substring(sf, "foo();\n bar();") } ]) end @@ -203,8 +200,8 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do } = SourceFile.apply_content_changes(sf, [ %{ - "text" => ", world!", - "range" => range_after_substring(sf, "hello") + text: ", world!", + range: range_after_substring(sf, "hello") } ]) end @@ -217,8 +214,8 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do } = SourceFile.apply_content_changes(sf, [ %{ - "text" => "\n bar();", - "range" => range_after_substring(sf, "foo();") + text: "\n bar();", + range: range_after_substring(sf, "foo();") } ]) end @@ -231,8 +228,8 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do } = SourceFile.apply_content_changes(sf, [ %{ - "text" => "hello, test case!!!", - "range" => range_for_substring(sf, "hello, world!") + text: "hello, test case!!!", + range: range_for_substring(sf, "hello, world!") } ]) end @@ -243,8 +240,8 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do assert %SourceFile{text: "function abc() {\n console.log(\"hey\");\n}"} = SourceFile.apply_content_changes(sf, [ %{ - "text" => "hey", - "range" => range_for_substring(sf, "hello, world!") + text: "hey", + range: range_for_substring(sf, "hello, world!") } ]) end @@ -257,8 +254,8 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do } = SourceFile.apply_content_changes(sf, [ %{ - "text" => "world, hello!", - "range" => range_for_substring(sf, "hello, world!") + text: "world, hello!", + range: range_for_substring(sf, "hello, world!") } ]) end @@ -271,8 +268,8 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do } = SourceFile.apply_content_changes(sf, [ %{ - "text" => "\n//hello\nfunction d(){", - "range" => range_for_substring(sf, "function abc() {") + text: "\n//hello\nfunction d(){", + range: range_for_substring(sf, "function abc() {") } ]) end @@ -283,8 +280,8 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do assert %SourceFile{text: "a1\nb1\na2\nb2xx\nyy"} = SourceFile.apply_content_changes(sf, [ %{ - "text" => "xx\nyy", - "range" => range_for_substring(sf, "\na3\nb3\na4\nb4\n") + text: "xx\nyy", + range: range_for_substring(sf, "\na3\nb3\na4\nb4\n") } ]) end @@ -295,8 +292,8 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do assert %SourceFile{text: "a1\nb1\n\nxx1\nxx2\nb3\na4\nb4\n"} = SourceFile.apply_content_changes(sf, [ %{ - "text" => "\nxx1\nxx2", - "range" => range_for_substring(sf, "a2\nb2\na3") + text: "\nxx1\nxx2", + range: range_for_substring(sf, "a2\nb2\na3") } ]) end @@ -307,8 +304,8 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do assert %SourceFile{text: "a1\nb1\n\ny\n\nb3\na4\nb4\n"} = SourceFile.apply_content_changes(sf, [ %{ - "text" => "\ny\n", - "range" => range_for_substring(sf, "a2\nb2\na3") + text: "\ny\n", + range: range_for_substring(sf, "a2\nb2\na3") } ]) end @@ -320,8 +317,8 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do assert %SourceFile{text: res} = SourceFile.apply_content_changes(sf, [ %{ - "text" => text, - "range" => range_for_substring(sf, "\ncc") + text: text, + range: range_for_substring(sf, "\ncc") } ]) @@ -336,16 +333,16 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do } = SourceFile.apply_content_changes(sf, [ %{ - "text" => "defg", - "range" => range_create(0, 12, 0, 12) + text: "defg", + range: range(0, 12, 0, 12) }, %{ - "text" => "hello, test case!!!", - "range" => range_create(1, 15, 1, 28) + text: "hello, test case!!!", + range: range(1, 15, 1, 28) }, %{ - "text" => "hij", - "range" => range_create(0, 16, 0, 16) + text: "hij", + range: range(0, 16, 0, 16) } ]) end @@ -356,8 +353,8 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do assert %SourceFile{text: "foooo\nbar some extra content\nbaz"} = SourceFile.apply_content_changes(sf, [ %{ - "text" => " some extra content", - "range" => range_create(1, 3, 1, 3) + text: " some extra content", + range: range(1, 3, 1, 3) } ]) end @@ -368,8 +365,8 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do assert %SourceFile{text: "foooo\nbar some extra\ncontent\nbaz"} = SourceFile.apply_content_changes(sf, [ %{ - "text" => " some extra\ncontent", - "range" => range_create(1, 3, 1, 3) + text: " some extra\ncontent", + range: range(1, 3, 1, 3) } ]) end @@ -380,8 +377,8 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do assert %SourceFile{text: "foooo\n\nbaz"} = SourceFile.apply_content_changes(sf, [ %{ - "text" => "", - "range" => range_create(1, 0, 1, 3) + text: "", + range: range(1, 0, 1, 3) } ]) end @@ -392,8 +389,8 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do assert %SourceFile{text: "foooo\nbaz"} = SourceFile.apply_content_changes(sf, [ %{ - "text" => "", - "range" => range_create(0, 5, 1, 3) + text: "", + range: range(0, 5, 1, 3) } ]) end @@ -404,8 +401,8 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do assert %SourceFile{text: "foooo\nbaz\nbaz"} = SourceFile.apply_content_changes(sf, [ %{ - "text" => "z", - "range" => range_create(1, 2, 1, 3) + text: "z", + range: range(1, 2, 1, 3) } ]) end @@ -416,8 +413,8 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do assert %SourceFile{text: "foo\nfoobar"} = SourceFile.apply_content_changes(sf, [ %{ - "text" => "foobar", - "range" => range_create(1, 0, 1, 3) + text: "foobar", + range: range(1, 0, 1, 3) } ]) end @@ -428,8 +425,8 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do assert %SourceFile{text: "foooo\r\nbaz\rbaz"} = SourceFile.apply_content_changes(sf, [ %{ - "text" => "z", - "range" => range_create(1, 2, 1, 3) + text: "z", + range: range(1, 2, 1, 3) } ]) end @@ -440,8 +437,8 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do assert %SourceFile{text: "foooo\nbaz\r\nz\rz\nbaz"} = SourceFile.apply_content_changes(sf, [ %{ - "text" => "z\r\nz\rz", - "range" => range_create(1, 2, 1, 3) + text: "z\r\nz\rz", + range: range(1, 2, 1, 3) } ]) end @@ -452,8 +449,8 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do assert %SourceFile{text: "foooo\nb🏳️‍🌈z\nbaz"} = SourceFile.apply_content_changes(sf, [ %{ - "text" => "z", - "range" => range_create(1, 7, 1, 8) + text: "z", + range: range(1, 7, 1, 8) } ]) end @@ -464,8 +461,8 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do assert %SourceFile{text: "foooo\nbaz🏳️‍🌈z\nbaz"} = SourceFile.apply_content_changes(sf, [ %{ - "text" => "z🏳️‍🌈z", - "range" => range_create(1, 2, 1, 3) + text: "z🏳️‍🌈z", + range: range(1, 2, 1, 3) } ]) end @@ -476,8 +473,8 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do assert %SourceFile{text: "abc123foo\nbar"} = SourceFile.apply_content_changes(sf, [ %{ - "text" => "abc123", - "range" => range_create(-2, 0, -1, 3) + text: "abc123", + range: range(-2, 0, -1, 3) } ]) end @@ -488,8 +485,8 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do assert %SourceFile{text: "foobar\nbar"} = SourceFile.apply_content_changes(sf, [ %{ - "text" => "foobar", - "range" => range_create(-1, 0, 0, 3) + text: "foobar", + range: range(-1, 0, 0, 3) } ]) end @@ -500,8 +497,8 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do assert %SourceFile{text: "foo\nfoobar"} = SourceFile.apply_content_changes(sf, [ %{ - "text" => "foobar", - "range" => range_create(1, 0, 1, 10) + text: "foobar", + range: range(1, 0, 1, 10) } ]) end @@ -512,8 +509,8 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do assert %SourceFile{text: "foo\nbarabc123"} = SourceFile.apply_content_changes(sf, [ %{ - "text" => "abc123", - "range" => range_create(3, 0, 6, 10) + text: "abc123", + range: range(3, 0, 6, 10) } ]) end @@ -524,8 +521,8 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do assert %SourceFile{text: "entirely new content"} = SourceFile.apply_content_changes(sf, [ %{ - "text" => "entirely new content", - "range" => range_create(-1, 1, 2, 10000) + text: "entirely new content", + range: range(-1, 1, 2, 10000) } ]) end @@ -545,16 +542,30 @@ defmodule ElixirLS.LanguageServer.SourceFileTest do end test "full_range" do - assert %{ - "end" => %{"character" => 0, "line" => 0}, - "start" => %{"character" => 0, "line" => 0} + assert %GenLSP.Structures.Range{ + end: %GenLSP.Structures.Position{character: 0, line: 0}, + start: %GenLSP.Structures.Position{character: 0, line: 0} } = SourceFile.full_range(new("")) - assert %{"end" => %{"character" => 1, "line" => 0}} = SourceFile.full_range(new("a")) - assert %{"end" => %{"character" => 0, "line" => 1}} = SourceFile.full_range(new("\n")) - assert %{"end" => %{"character" => 2, "line" => 1}} = SourceFile.full_range(new("a\naa")) - assert %{"end" => %{"character" => 2, "line" => 1}} = SourceFile.full_range(new("a\r\naa")) - assert %{"end" => %{"character" => 8, "line" => 1}} = SourceFile.full_range(new("a\naa🏳️‍🌈")) + assert %GenLSP.Structures.Range{ + end: %GenLSP.Structures.Position{character: 1, line: 0} + } = SourceFile.full_range(new("a")) + + assert %GenLSP.Structures.Range{ + end: %GenLSP.Structures.Position{character: 0, line: 1} + } = SourceFile.full_range(new("\n")) + + assert %GenLSP.Structures.Range{ + end: %GenLSP.Structures.Position{character: 2, line: 1} + } = SourceFile.full_range(new("a\naa")) + + assert %GenLSP.Structures.Range{ + end: %GenLSP.Structures.Position{character: 2, line: 1} + } = SourceFile.full_range(new("a\r\naa")) + + assert %GenLSP.Structures.Range{ + end: %GenLSP.Structures.Position{character: 8, line: 1} + } = SourceFile.full_range(new("a\naa🏳️‍🌈")) end describe "lines_with_endings/1" do diff --git a/apps/language_server/lib/language_server/protocol.ex b/apps/language_server/test/support/protocol.ex similarity index 100% rename from apps/language_server/lib/language_server/protocol.ex rename to apps/language_server/test/support/protocol.ex diff --git a/apps/language_server/test/support/server_test_helpers.ex b/apps/language_server/test/support/server_test_helpers.ex index 745aa7785..b39da0c02 100644 --- a/apps/language_server/test/support/server_test_helpers.ex +++ b/apps/language_server/test/support/server_test_helpers.ex @@ -5,6 +5,7 @@ defmodule ElixirLS.LanguageServer.Test.ServerTestHelpers do alias ElixirLS.LanguageServer.JsonRpc alias ElixirLS.LanguageServer.SourceFile alias ElixirLS.LanguageServer.Providers.WorkspaceSymbols + alias ElixirLS.LanguageServer.ClientCapabilities alias ElixirLS.Utils.PacketCapture use ElixirLS.LanguageServer.Protocol @@ -85,7 +86,7 @@ defmodule ElixirLS.LanguageServer.Test.ServerTestHelpers do }) ) - Server.receive_packet(server, notification("initialized")) + Server.receive_packet(server, notification("initialized", %{})) config = config || %{"dialyzerEnabled" => false} @@ -106,6 +107,38 @@ defmodule ElixirLS.LanguageServer.Test.ServerTestHelpers do end def fake_initialize(server, mix_project? \\ true) do + # Store default client capabilities for tests + default_client_capabilities = %GenLSP.Structures.ClientCapabilities{ + text_document: %GenLSP.Structures.TextDocumentClientCapabilities{ + completion: %GenLSP.Structures.CompletionClientCapabilities{ + completion_item: %{ + snippet_support: true, + deprecated_support: true, + tag_support: %{value_set: [1]} + } + }, + hover: %GenLSP.Structures.HoverClientCapabilities{}, + signature_help: %GenLSP.Structures.SignatureHelpClientCapabilities{}, + document_symbol: %GenLSP.Structures.DocumentSymbolClientCapabilities{ + hierarchical_document_symbol_support: true + } + }, + workspace: %GenLSP.Structures.WorkspaceClientCapabilities{ + configuration: true, + did_change_configuration: %GenLSP.Structures.DidChangeConfigurationClientCapabilities{ + dynamic_registration: true + }, + did_change_watched_files: %GenLSP.Structures.DidChangeWatchedFilesClientCapabilities{ + dynamic_registration: true + }, + symbol: %GenLSP.Structures.WorkspaceSymbolClientCapabilities{ + tag_support: %{value_set: [1]} + } + } + } + + ClientCapabilities.store(default_client_capabilities) + :sys.replace_state(server, fn state -> %{state | server_instance_id: "123", project_dir: File.cwd!(), mix_project?: mix_project?} end) diff --git a/apps/language_server/test/support/test_utils.ex b/apps/language_server/test/support/test_utils.ex index 5f8b85223..62aebd360 100644 --- a/apps/language_server/test/support/test_utils.ex +++ b/apps/language_server/test/support/test_utils.ex @@ -1,10 +1,9 @@ defmodule ElixirLS.LanguageServer.Test.TestUtils do - alias ElixirLS.LanguageServer.Protocol.TextEdit + alias GenLSP.Structures.TextEdit alias ElixirLS.LanguageServer.SourceFile def apply_text_edit(text, %TextEdit{} = text_edit) do - %TextEdit{range: range, newText: new_text} = text_edit - + %GenLSP.Structures.TextEdit{range: range, new_text: new_text} = text_edit SourceFile.apply_edit(text, range, new_text) end end diff --git a/dep_versions.exs b/dep_versions.exs index c56bf625c..9a7c97126 100644 --- a/dep_versions.exs +++ b/dep_versions.exs @@ -3,5 +3,6 @@ dialyxir_vendored: "f8f64cfb6797c518294687e7c03ae817bacbc6ee", jason_v: "f1c10fa9c445cb9f300266122ef18671054b2330", erl2ex_vendored: "073ac6b9a44282e718b6050c7b27cedf9217a12a", - path_glob_vendored: "965350dc41def7be4a70a23904195c733a2ecc84" + path_glob_vendored: "965350dc41def7be4a70a23904195c733a2ecc84", + schematic_vendored: "7ecf3cd4b3ee319abf7d0914d325657a1f56cffd" ] diff --git a/mix.lock b/mix.lock index 0d32b58d0..baea6974a 100644 --- a/mix.lock +++ b/mix.lock @@ -9,6 +9,8 @@ "nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"}, "patch": {:hex, :patch, "0.12.0", "2da8967d382bade20344a3e89d618bfba563b12d4ac93955468e830777f816b0", [:mix], [], "hexpm", "ffd0e9a7f2ad5054f37af84067ee88b1ad337308a1cb227e181e3967127b0235"}, "path_glob_vendored": {:git, "https://github.com/elixir-lsp/path_glob.git", "965350dc41def7be4a70a23904195c733a2ecc84", [ref: "965350dc41def7be4a70a23904195c733a2ecc84"]}, + "schematic_v": {:git, "https://github.com/elixir-lsp/schematic_vendored.git", "7ecf3cd4b3ee319abf7d0914d325657a1f56cffd", [ref: "7ecf3cd4b3ee319abf7d0914d325657a1f56cffd"]}, "statistex": {:hex, :statistex, "1.0.0", "f3dc93f3c0c6c92e5f291704cf62b99b553253d7969e9a5fa713e5481cd858a5", [:mix], [], "hexpm", "ff9d8bee7035028ab4742ff52fc80a2aa35cece833cf5319009b52f1b5a86c27"}, "stream_data": {:hex, :stream_data, "0.5.0", "b27641e58941685c75b353577dc602c9d2c12292dd84babf506c2033cd97893e", [:mix], [], "hexpm", "012bd2eec069ada4db3411f9115ccafa38540a3c78c4c0349f151fc761b9e271"}, + "typed_struct": {:hex, :typed_struct, "0.3.0", "939789e3c1dca39d7170c87f729127469d1315dcf99fee8e152bb774b17e7ff7", [:mix], [], "hexpm", "c50bd5c3a61fe4e198a8504f939be3d3c85903b382bde4865579bc23111d1b6d"}, } diff --git a/scripts/elixir_check.bat b/scripts/elixir_check.bat new file mode 100644 index 000000000..41481cd99 --- /dev/null +++ b/scripts/elixir_check.bat @@ -0,0 +1,16 @@ +@echo off & setlocal enabledelayedexpansion + +SET ELS_MODE=elixir_check + +IF EXIST "%APPDATA%\elixir_ls\setup.bat" ( + ECHO "" | CALL "%APPDATA%\elixir_ls\setup.bat" > nul + IF %ERRORLEVEL% NEQ 0 EXIT 1 +) + +SET MIX_ENV=prod +@REM pipe echo to avoid passing protocol messages to quiet install command +@REM intercept stdout and stderr +@REM elixir is a batch script and needs to be called +ECHO "" | CALL elixir "%~dp0quiet_install.exs" >nul +IF %ERRORLEVEL% NEQ 0 EXIT 1 +elixir %ELS_ELIXIR_OPTS% --erl "-kernel standard_io_encoding latin1 +sbwt none +sbwtdcpu none +sbwtdio none %ELS_ERL_OPTS%" "%~dp0launch.exs" diff --git a/scripts/elixir_check.sh b/scripts/elixir_check.sh new file mode 100755 index 000000000..c9ce283cd --- /dev/null +++ b/scripts/elixir_check.sh @@ -0,0 +1,23 @@ +#!/bin/sh +# Checks if elixir is available. This script must be in the same directory as mix install launch script. + +readlink_f () { + cd "$(dirname "$1")" > /dev/null || exit 1 + filename="$(basename "$1")" + if [ -h "$filename" ]; then + readlink_f "$(readlink "$filename")" + else + echo "$(pwd -P)/$filename" + fi +} + +if [ -z "${ELS_INSTALL_PREFIX}" ]; then + dir="$(dirname "$(readlink_f "$0")")" + >&2 echo "Running ${dir}/launch.sh" +else + dir=${ELS_INSTALL_PREFIX} + >&2 echo "ELS_INSTALL_PREFIX is set, running ${ELS_INSTALL_PREFIX}/launch.sh" +fi + +export ELS_MODE=elixir_check +exec "${dir}/launch.sh" diff --git a/scripts/launch.exs b/scripts/launch.exs index 810b09236..9633d2c4f 100644 --- a/scripts/launch.exs +++ b/scripts/launch.exs @@ -1,3 +1,11 @@ +# Handle elixir_check early to avoid Mix and installer interference +if System.get_env("ELS_MODE") == "elixir_check" do + # Simply exit successfully if we reach this point, + # meaning elixir is working and available + System.halt(0) +end + +# Continue with normal startup for language_server and debug_adapter Application.put_env(:elixir, :ansi_enabled, false) Code.eval_file("#{__DIR__}/installer.exs")