Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor request handling #777

Merged
merged 7 commits into from
Jul 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 55 additions & 16 deletions apps/server/lib/lexical/server.ex
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
defmodule Lexical.Server do
alias Lexical.Proto.Convert
alias Lexical.Protocol.Notifications
alias Lexical.Protocol.Requests
alias Lexical.Protocol.Responses
alias Lexical.Server.Provider
alias Lexical.Server.Provider.Handlers
alias Lexical.Server.State
alias Lexical.Server.TaskQueue

require Logger

Expand All @@ -23,11 +24,6 @@ defmodule Lexical.Server do

@dialyzer {:nowarn_function, apply_to_state: 2}

@spec response_complete(Requests.request(), Responses.response()) :: :ok
def response_complete(request, response) do
GenServer.call(__MODULE__, {:response_complete, request, response})
end

@spec server_request(
Requests.request(),
(Requests.request(), {:ok, any()} | {:error, term()} -> term())
Expand All @@ -53,10 +49,6 @@ defmodule Lexical.Server do
{:ok, State.new()}
end

def handle_call({:response_complete, _request, _response}, _from, %State{} = state) do
{:reply, :ok, state}
end

def handle_call({:server_request, request, on_response}, _from, %State{} = state) do
new_state = State.add_request(state, request, on_response)
{:reply, :okk, new_state}
Expand Down Expand Up @@ -111,12 +103,12 @@ defmodule Lexical.Server do
end

def handle_message(%Requests.Cancel{} = cancel_request, %State{} = state) do
Provider.Queue.cancel(cancel_request)
TaskQueue.cancel(cancel_request)
{:ok, state}
end

def handle_message(%Notifications.Cancel{} = cancel_notification, %State{} = state) do
Provider.Queue.cancel(cancel_notification)
TaskQueue.cancel(cancel_notification)
{:ok, state}
end

Expand All @@ -138,13 +130,22 @@ defmodule Lexical.Server do
end

def handle_message(%_{} = request, %State{} = state) do
Provider.Queue.add(request, state.configuration)
with {:ok, handler} <- fetch_handler(request),
{:ok, req} <- Convert.to_native(request) do
TaskQueue.add(request.id, {handler, :handle, [req, state.configuration.project]})
else
{:error, {:unhandled, _}} ->
Logger.info("Unhandled request: #{request.method}")

_ ->
:ok
end

{:ok, state}
end

def handle_message(%{} = request, %State{} = state) do
new_state = State.finish_request(state, request)
def handle_message(%{} = response, %State{} = state) do
new_state = State.finish_request(state, response)

{:ok, new_state}
end
Expand All @@ -156,4 +157,42 @@ defmodule Lexical.Server do
error -> {error, state}
end
end

# credo:disable-for-next-line Credo.Check.Refactor.CyclomaticComplexity
defp fetch_handler(%_{} = request) do
case request do
%Requests.FindReferences{} ->
{:ok, Handlers.FindReferences}

%Requests.Formatting{} ->
{:ok, Handlers.Formatting}

%Requests.CodeAction{} ->
{:ok, Handlers.CodeAction}

%Requests.CodeLens{} ->
{:ok, Handlers.CodeLens}

%Requests.Completion{} ->
{:ok, Handlers.Completion}

%Requests.GoToDefinition{} ->
{:ok, Handlers.GoToDefinition}

%Requests.Hover{} ->
{:ok, Handlers.Hover}

%Requests.ExecuteCommand{} ->
{:ok, Handlers.Commands}

%Requests.DocumentSymbols{} ->
{:ok, Handlers.DocumentSymbols}

%Requests.WorkspaceSymbol{} ->
{:ok, Handlers.WorkspaceSymbol}

%request_module{} ->
{:error, {:unhandled, request_module}}
end
end
end
6 changes: 3 additions & 3 deletions apps/server/lib/lexical/server/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ defmodule Lexical.Server.Application do

alias Lexical.Document
alias Lexical.Server
alias Lexical.Server.Provider
alias Lexical.Server.TaskQueue
alias Lexical.Server.Transport

use Application
Expand All @@ -16,8 +16,8 @@ defmodule Lexical.Server.Application do
document_store_child_spec(),
Server,
{DynamicSupervisor, Server.Project.Supervisor.options()},
Provider.Queue.Supervisor.child_spec(),
Provider.Queue.child_spec(),
{Task.Supervisor, name: TaskQueue.task_supervisor_name()},
TaskQueue,
{Transport.StdIO, [:standard_io, &Server.protocol_message/1]}
]

Expand Down
6 changes: 3 additions & 3 deletions apps/server/lib/lexical/server/configuration.ex
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ defmodule Lexical.Server.Configuration do
|> tap(&set/1)
end

@spec new() :: t
def new do
%__MODULE__{support: Support.new()}
@spec new(keyword()) :: t
def new(attrs \\ []) do
struct!(__MODULE__, [support: Support.new()] ++ attrs)
end

defp set(%__MODULE__{} = config) do
Expand Down
28 changes: 0 additions & 28 deletions apps/server/lib/lexical/server/provider/env.ex

This file was deleted.

42 changes: 0 additions & 42 deletions apps/server/lib/lexical/server/provider/handlers.ex

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ defmodule Lexical.Server.Provider.Handlers.CodeAction do
alias Lexical.Protocol.Types.Workspace
alias Lexical.RemoteControl
alias Lexical.RemoteControl.CodeAction
alias Lexical.Server.Provider.Env
alias Lexical.Server.Configuration

require Logger

def handle(%Requests.CodeAction{} = request, %Env{} = env) do
def handle(%Requests.CodeAction{} = request, %Configuration{} = config) do
diagnostics = Enum.map(request.context.diagnostics, &to_code_action_diagnostic/1)

code_actions =
RemoteControl.Api.code_actions(
env.project,
config.project,
request.document,
request.range,
diagnostics,
Expand Down
6 changes: 3 additions & 3 deletions apps/server/lib/lexical/server/provider/handlers/code_lens.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ defmodule Lexical.Server.Provider.Handlers.CodeLens do
alias Lexical.Protocol.Responses
alias Lexical.Protocol.Types.CodeLens
alias Lexical.RemoteControl
alias Lexical.Server.Provider.Env
alias Lexical.Server.Configuration
alias Lexical.Server.Provider.Handlers

import Document.Line
require Logger

def handle(%Requests.CodeLens{} = request, %Env{} = env) do
def handle(%Requests.CodeLens{} = request, %Configuration{} = config) do
lenses =
case reindex_lens(env.project, request.document) do
case reindex_lens(config.project, request.document) do
nil -> []
lens -> List.wrap(lens)
end
Expand Down
8 changes: 4 additions & 4 deletions apps/server/lib/lexical/server/provider/handlers/commands.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ defmodule Lexical.Server.Provider.Handlers.Commands do
alias Lexical.Protocol.Types
alias Lexical.Protocol.Types.ErrorCodes
alias Lexical.RemoteControl
alias Lexical.Server.Provider.Env
alias Lexical.Server.Configuration
alias Lexical.Server.Window

require ErrorCodes
Expand All @@ -26,12 +26,12 @@ defmodule Lexical.Server.Provider.Handlers.Commands do
)
end

def handle(%Requests.ExecuteCommand{} = request, %Env{} = env) do
def handle(%Requests.ExecuteCommand{} = request, %Configuration{} = config) do
response =
case request.command do
@reindex_name ->
Logger.info("Reindex #{Project.name(env.project)}")
reindex(env.project, request.id)
Logger.info("Reindex #{Project.name(config.project)}")
reindex(config.project, request.id)

invalid ->
message = "#{invalid} is not a valid command"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ defmodule Lexical.Server.Provider.Handlers.Completion do
alias Lexical.Protocol.Responses
alias Lexical.Protocol.Types.Completion
alias Lexical.Server.CodeIntelligence
alias Lexical.Server.Provider.Env
alias Lexical.Server.Configuration

require Logger

def handle(%Requests.Completion{} = request, %Env{} = env) do
def handle(%Requests.Completion{} = request, %Configuration{} = config) do
completions =
CodeIntelligence.Completion.complete(
env.project,
config.project,
document_analysis(request.document, request.position),
request.position,
request.context || Completion.Context.new(trigger_kind: :invoked)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ defmodule Lexical.Server.Provider.Handlers.DocumentSymbols do
alias Lexical.Protocol.Types.Symbol.Kind, as: SymbolKind
alias Lexical.RemoteControl.Api
alias Lexical.RemoteControl.CodeIntelligence.Symbols
alias Lexical.Server.Provider.Env
alias Lexical.Server.Configuration

require SymbolKind

def handle(%DocumentSymbols{} = request, %Env{} = env) do
def handle(%DocumentSymbols{} = request, %Configuration{} = config) do
symbols =
env.project
config.project
|> Api.document_symbols(request.document)
|> Enum.map(&to_response(&1, request.document))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ defmodule Lexical.Server.Provider.Handlers.FindReferences do
alias Lexical.Protocol.Requests.FindReferences
alias Lexical.Protocol.Responses
alias Lexical.RemoteControl.Api
alias Lexical.Server.Provider.Env
alias Lexical.Server.Configuration

require Logger

def handle(%FindReferences{} = request, %Env{} = env) do
def handle(%FindReferences{} = request, %Configuration{} = config) do
include_declaration? = !!request.context.include_declaration

locations =
case Document.Store.fetch(request.document.uri, :analysis) do
{:ok, _document, %Ast.Analysis{} = analysis} ->
Api.references(env.project, analysis, request.position, include_declaration?)
Api.references(config.project, analysis, request.position, include_declaration?)

_ ->
nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ defmodule Lexical.Server.Provider.Handlers.Formatting do
alias Lexical.Protocol.Requests
alias Lexical.Protocol.Responses
alias Lexical.RemoteControl
alias Lexical.Server.Provider.Env
alias Lexical.Server.Configuration

require Logger

def handle(%Requests.Formatting{} = request, %Env{} = env) do
def handle(%Requests.Formatting{} = request, %Configuration{} = config) do
document = request.document

case RemoteControl.Api.format(env.project, document) do
case RemoteControl.Api.format(config.project, document) do
{:ok, %Changes{} = document_edits} ->
response = Responses.Formatting.new(request.id, document_edits)
Logger.info("Response #{inspect(response)}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ defmodule Lexical.Server.Provider.Handlers.GoToDefinition do
alias Lexical.Protocol.Requests.GoToDefinition
alias Lexical.Protocol.Responses
alias Lexical.RemoteControl
alias Lexical.Server.Configuration

require Logger

def handle(%GoToDefinition{} = request, env) do
case RemoteControl.Api.definition(env.project, request.document, request.position) do
def handle(%GoToDefinition{} = request, %Configuration{} = config) do
case RemoteControl.Api.definition(config.project, request.document, request.position) do
{:ok, native_location} ->
{:reply, Responses.GoToDefinition.new(request.id, native_location)}

Expand Down
Loading
Loading