Skip to content

Commit fe14474

Browse files
committed
Address review concerns
- Also show errors in the client via window/showMessage - Improve logging cases - Only register with nodemapper when node started ok - For now do not introduce full expert test
1 parent dc9c8f1 commit fe14474

File tree

4 files changed

+69
-83
lines changed

4 files changed

+69
-83
lines changed

apps/expert/lib/expert.ex

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ defmodule Expert do
44
alias Expert.Protocol.Id
55
alias Expert.Provider.Handlers
66
alias Expert.State
7+
alias GenLSP.Enumerations
78
alias GenLSP.Requests
89
alias GenLSP.Structures
910

@@ -55,10 +56,12 @@ defmodule Expert do
5556

5657
with {:ok, response, state} <- State.initialize(state, request),
5758
{:ok, response} <- Expert.Protocol.Convert.to_lsp(response) do
58-
config = state.configuration
59-
6059
Task.Supervisor.start_child(:expert_task_queue, fn ->
61-
Logger.info("Starting project at uri #{config.project.root_uri}")
60+
config = state.configuration
61+
62+
start_message = "Starting project at uri #{config.project.root_uri}"
63+
GenLSP.info(lsp, start_message)
64+
Logger.info(start_message)
6265

6366
start_result = Project.Supervisor.start(config.project)
6467

@@ -201,11 +204,42 @@ defmodule Expert do
201204
end
202205

203206
def handle_info({:engine_initialized, {:error, reason}}, lsp) do
204-
GenLSP.error(get_lsp(), initialization_error_message(reason))
207+
error_message = initialization_error_message(reason)
208+
error(error_message)
205209

206210
{:noreply, lsp}
207211
end
208212

213+
def info(message) do
214+
Logger.info(message)
215+
216+
log_show(message, Enumerations.MessageType.info())
217+
end
218+
219+
def error(message) do
220+
Logger.error(message)
221+
222+
log_show(message, Enumerations.MessageType.error())
223+
end
224+
225+
defp log_show(message, log_level) do
226+
lsp = get_lsp()
227+
228+
GenLSP.notify(lsp, %GenLSP.Notifications.WindowShowMessage{
229+
params: %GenLSP.Structures.ShowMessageParams{
230+
type: log_level,
231+
message: message
232+
}
233+
})
234+
235+
GenLSP.notify(lsp, %GenLSP.Notifications.WindowLogMessage{
236+
params: %GenLSP.Structures.LogMessageParams{
237+
type: log_level,
238+
message: message
239+
}
240+
})
241+
end
242+
209243
defp apply_to_state(%State{} = state, %{} = request_or_notification) do
210244
case State.apply(state, request_or_notification) do
211245
{:ok, response, new_state} -> {:ok, response, new_state}
@@ -298,13 +332,13 @@ defmodule Expert do
298332
# NOTE:
299333
# ** (Mix.Error) httpc request failed with: ... Could not install Hex because Mix could not download metadata ...
300334
{:shutdown, {:error, :normal, message}} ->
301-
"Node #{name} shutdown with error:\n\n#{message}"
335+
"Engine #{name} shutdown with error:\n\n#{message}"
302336

303337
{:shutdown, {:node_exit, node_exit}} ->
304-
"Node #{name} exit with status #{node_exit.status}, last message:\n\n#{node_exit.last_message}"
338+
"Engine #{name} exit with status #{node_exit.status}, last message:\n\n#{node_exit.last_message}"
305339

306340
reason ->
307-
"Failed to start node #{name}: #{inspect(reason)}"
341+
"Failed to start engine #{name}: #{inspect(reason)}"
308342
end
309343
end
310344
end

apps/expert/lib/expert/application.ex

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,18 @@ defmodule Expert.Application do
6666

6767
ensure_epmd_module!()
6868

69-
children = [
69+
LogFilter.hook_into_logger()
70+
71+
children_spec = children(buffer: buffer_opts)
72+
opts = [strategy: :one_for_one, name: Expert.Supervisor]
73+
74+
Supervisor.start_link(children_spec, opts)
75+
end
76+
77+
def children(opts) do
78+
buffer_opts = Keyword.fetch!(opts, :buffer)
79+
80+
[
7081
{Forge.NodePortMapper, []},
7182
document_store_child_spec(),
7283
{DynamicSupervisor, Expert.Project.DynamicSupervisor.options()},
@@ -81,11 +92,6 @@ defmodule Expert.Application do
8192
dynamic_supervisor: Expert.DynamicSupervisor,
8293
assigns: Expert.Assigns}
8394
]
84-
85-
LogFilter.hook_into_logger()
86-
87-
opts = [strategy: :one_for_one, name: Expert.Supervisor]
88-
Supervisor.start_link(children, opts)
8995
end
9096

9197
@doc false

apps/expert/lib/expert/engine_node.ex

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ defmodule Expert.EngineNode do
5151
# everything works fine.
5252
"""
5353
node_start = Node.start(:"#{Project.node_name(state.project)}", :longnames)
54-
#{Forge.NodePortMapper}.register()
5554
case node_start do
5655
{:ok, _} ->
56+
#{Forge.NodePortMapper}.register()
5757
IO.puts(\"ok\")
5858
{:error, reason} ->
5959
IO.puts(\"error starting node:\n \#{inspect(reason)}\")
@@ -112,16 +112,18 @@ defmodule Expert.EngineNode do
112112
end
113113

114114
def on_exit_status(%__MODULE__{} = state, exit_status) do
115-
Logger.debug(
116-
"Node exited with status #{exit_status}, last message: #{to_string(state.last_message)}"
117-
)
118-
119115
stop_reason =
120116
case exit_status do
121117
0 ->
118+
Logger.info("Engine shutdown")
119+
122120
:shutdown
123121

124122
_error_status ->
123+
Logger.error(
124+
"Engine shut down unexpectedly, node exited with status #{exit_status}). Last message: #{state.last_message}"
125+
)
126+
125127
{:shutdown, {:node_exit, %{status: exit_status, last_message: state.last_message}}}
126128
end
127129

apps/expert/test/expert_test.exs

Lines changed: 9 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,11 @@
11
defmodule Expert.ExpertTest do
2-
alias Forge.Test.Fixtures
3-
4-
use ExUnit.Case, async: false
2+
use ExUnit.Case, async: true
53
use Patch
6-
use Forge.Test.EventualAssertions
74

85
require GenLSP.Test
96

107
import Expert.Test.Protocol.TransportSupport
118

12-
defp start_expert do
13-
patch(System, :argv, fn -> ["--port", "0"] end)
14-
15-
assert {:ok, _} = Application.ensure_all_started(:expert)
16-
17-
on_exit(fn -> Application.stop(:expert) end)
18-
end
19-
20-
describe "server testing" do
21-
setup do
22-
start_expert()
23-
24-
%{lsp: lsp} = :sys.get_state(Expert.Buffer)
25-
{:ok, port} = :inet.port(GenLSP.Buffer.comm_state(Expert.Buffer).lsocket)
26-
27-
expert = %{
28-
lsp: lsp,
29-
port: port
30-
}
31-
32-
client = GenLSP.Test.client(expert)
33-
34-
[expert: expert, client: client]
35-
end
36-
37-
test "replies to initialize with expert info and capabilities", %{client: client} do
38-
id = System.unique_integer([:positive])
39-
40-
project = Fixtures.project()
41-
42-
root_uri = project.root_uri
43-
root_path = Forge.Project.root_path(project)
44-
45-
assert :ok ==
46-
GenLSP.Test.request(client, %{
47-
"id" => id,
48-
"jsonrpc" => "2.0",
49-
"method" => "initialize",
50-
"params" => %{
51-
"rootPath" => root_path,
52-
"rootUri" => root_uri,
53-
"capabilities" => %{},
54-
"workspaceFolders" => [
55-
%{
56-
uri: root_uri,
57-
name: root_path
58-
}
59-
]
60-
}
61-
})
62-
63-
GenLSP.Test.assert_result(^id, result, 500)
64-
65-
{:ok, initialize_result} =
66-
GenLSP.Requests.Initialize.result()
67-
|> Schematic.dump(Expert.State.initialize_result())
68-
69-
assert result == initialize_result
70-
end
71-
end
72-
739
test "sends an error message on engine initialization error" do
7410
with_patched_transport()
7511

@@ -92,5 +28,13 @@ defmodule Expert.ExpertTest do
9228
message: ^error_message
9329
}
9430
}}
31+
32+
assert_receive {:transport,
33+
%GenLSP.Notifications.WindowShowMessage{
34+
params: %GenLSP.Structures.ShowMessageParams{
35+
type: ^error_message_type,
36+
message: ^error_message
37+
}
38+
}}
9539
end
9640
end

0 commit comments

Comments
 (0)