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

feat: isolated node #32

Merged
merged 7 commits into from
May 31, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 13 additions & 3 deletions .credo.exs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,12 @@
"apps/*/test/",
"apps/*/web/"
],
excluded: [~r"/_build/", ~r"/deps/", ~r"/node_modules/", "test/support/fixtures/**"]
excluded: [
~r"/_build/",
~r"/deps/",
~r"/node_modules/",
"test/support/project/**"
]
},
#
# Load and configure plugins here:
Expand Down Expand Up @@ -83,7 +88,11 @@
# Priority values are: `low, normal, high, higher`
#
{Credo.Check.Design.AliasUsage,
[priority: :low, if_nested_deeper_than: 2, if_called_more_often_than: 0]},
[
priority: :low,
if_nested_deeper_than: 2,
if_called_more_often_than: 0
]},
# You can also customize the exit_status of each check.
# If you don't want TODO comments to cause `mix credo` to fail, just
# set this value to 0 (zero).
Expand All @@ -97,7 +106,8 @@
{Credo.Check.Readability.AliasOrder, []},
{Credo.Check.Readability.FunctionNames, []},
{Credo.Check.Readability.LargeNumbers, []},
{Credo.Check.Readability.MaxLineLength, [priority: :low, max_length: 120]},
{Credo.Check.Readability.MaxLineLength,
[priority: :low, max_length: 120]},
{Credo.Check.Readability.ModuleAttributeNames, []},
{Credo.Check.Readability.ModuleDoc, []},
{Credo.Check.Readability.ModuleNames, []},
Expand Down
10 changes: 9 additions & 1 deletion .formatter.exs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@
notify: 2,
request: 2
],
line_length: 78,
import_deps: [:gen_lsp],
inputs: [".credo.exs", "{mix,.formatter}.exs", "{config,lib,test,}/**/*.{ex,exs}"]
inputs: [
".credo.exs",
"{mix,.formatter}.exs",
"{config,lib,}/**/*.{ex,exs}",
"test/credo_language_server_test.exs",
"test/test_helper.exs",
"test/credo_language_server/**/*.{ex,exs}"
]
]
7 changes: 6 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
test:
Expand Down Expand Up @@ -48,6 +47,12 @@ jobs:
if: steps.cache.outputs.cache-hit != 'true'
run: mix deps.get --only test

- name: Start EPMD
run: epmd -daemon

- name: Compile test project
run: (cd test/support/project && mix deps.get && mix compile)

- name: Run tests
run: mix test

Expand Down
73 changes: 63 additions & 10 deletions lib/credo_language_server.ex
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ defmodule CredoLanguageServer do
alias CredoLanguageServer.Cache, as: Diagnostics

def start_link(args) do
{args, opts} = Keyword.split(args, [:cache, :task_supervisor])
{args, opts} = Keyword.split(args, [:cache, :task_supervisor, :runtime])

GenLSP.start_link(__MODULE__, args, opts)
end
Expand All @@ -54,19 +54,56 @@ defmodule CredoLanguageServer do
def init(lsp, args) do
cache = Keyword.fetch!(args, :cache)
task_supervisor = Keyword.fetch!(args, :task_supervisor)
runtime = Keyword.fetch!(args, :runtime)

with false <- wait_until_runtime_ready(runtime) do
raise "Failed to boot runtime"
end

{:ok, _} =
CredoLanguageServer.Runtime.call(
runtime,
{Application, :ensure_all_started, [:credo]}
)

CredoLanguageServer.Runtime.call(
runtime,
{GenServer, :call, [Credo.CLI.Output.Shell, {:suppress_output, true}]}
)

{:ok,
assign(lsp,
exit_code: 1,
cache: cache,
documents: %{},
refresh_refs: %{},
task_supervisor: task_supervisor
task_supervisor: task_supervisor,
runtime: runtime
)}
end

defp wait_until_runtime_ready(runtime) do
wait_until_runtime_ready(10, runtime)
end

defp wait_until_runtime_ready(0, _runtime) do
false
end

defp wait_until_runtime_ready(n, runtime) do
if CredoLanguageServer.Runtime.ready?(runtime) do
true
else
Process.sleep(1000)
wait_until_runtime_ready(n - 1, runtime)
end
end

@impl true
def handle_request(%Initialize{params: %InitializeParams{root_uri: root_uri}}, lsp) do
def handle_request(
%Initialize{params: %InitializeParams{root_uri: root_uri}},
lsp
) do
{:reply,
%InitializeResult{
capabilities: %ServerCapabilities{
Expand Down Expand Up @@ -250,7 +287,10 @@ defmodule CredoLanguageServer do
{:noreply, assign(lsp, refresh_refs: refs)}
end

def handle_info({:DOWN, ref, :process, _pid, _reason}, %{assigns: %{refresh_refs: refs}} = lsp)
def handle_info(
{:DOWN, ref, :process, _pid, _reason},
%{assigns: %{refresh_refs: refs}} = lsp
)
when is_map_key(refs, ref) do
{token, refs} = Map.pop(refs, ref)

Expand All @@ -274,15 +314,22 @@ defmodule CredoLanguageServer do
dir = URI.parse(lsp.assigns.root_uri).path

issues =
["--strict", "--all", "--working-dir", dir]
|> Credo.run()
|> Credo.Execution.get_issues()
CredoLanguageServer.Runtime.call(
lsp.assigns.runtime,
{CredoLanguageServer.Monkey.Credo, :issues, [dir]}
)

for issue <- issues do
diagnostic = %Diagnostic{
range: %Range{
start: %Position{line: issue.line_no - 1, character: (issue.column || 1) - 1},
end: %Position{line: issue.line_no - 1, character: issue.column || 1}
start: %Position{
line: issue.line_no - 1,
character: (issue.column || 1) - 1
},
end: %Position{
line: issue.line_no - 1,
character: issue.column || 1
}
},
severity: category_to_severity(issue.category),
data: %{check: issue.check, file: issue.filename},
Expand All @@ -295,7 +342,13 @@ defmodule CredoLanguageServer do
"""
}

Diagnostics.put(lsp.assigns.cache, Path.absname(issue.filename), diagnostic)
Diagnostics.put(
lsp.assigns.cache,
Path.join(lsp.assigns.root_uri, issue.filename)
|> URI.parse()
|> Map.get(:path),
diagnostic
)
end

Enum.count(issues)
Expand Down
35 changes: 2 additions & 33 deletions lib/credo_language_server/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,10 @@ defmodule CredoLanguageServer.Application do

use Application

@env Mix.env()

@impl true
def start(_type, _args) do
children =
if @env == :test do
[]
else
{opts, _} = OptionParser.parse!(System.argv(), strict: [stdio: :boolean, port: :integer])
{:ok, _} = Application.ensure_all_started(:credo)
GenServer.call(Credo.CLI.Output.Shell, {:suppress_output, true})

buffer_opts =
cond do
opts[:stdio] ->
[]

is_integer(opts[:port]) ->
IO.puts("Starting on port #{opts[:port]}")
[communication: {GenLSP.Communication.TCP, [port: opts[:port]]}]

true ->
raise "Unknown option"
end

[
{Task.Supervisor, name: CredoLanguageServer.TaskSupervisor},
{GenLSP.Buffer, buffer_opts},
{CredoLanguageServer.Cache, [name: :credo_cache]},
{CredoLanguageServer,
cache: :credo_cache, task_supervisor: CredoLanguageServer.TaskSupervisor}
]
end

opts = [strategy: :one_for_one, name: CredoLanguageServer.Supervisor]
Supervisor.start_link(children, opts)

Supervisor.start_link([CredoLanguageServer.CredoSupervisor], opts)
end
end
2 changes: 1 addition & 1 deletion lib/credo_language_server/cache.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ defmodule CredoLanguageServer.Cache do

def put(cache, filename, diagnostic) do
Agent.update(cache, fn cache ->
Map.update(cache, Path.absname(filename), [diagnostic], fn v ->
Map.update(cache, filename, [diagnostic], fn v ->
[diagnostic | v]
end)
end)
Expand Down
7 changes: 6 additions & 1 deletion lib/credo_language_server/check.ex
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@ defmodule CredoLanguageServer.Check do
]
end

def fetch(%{check: check, diagnostic: diagnostic, uri: uri, document: document}) do
def fetch(%{
check: check,
diagnostic: diagnostic,
uri: uri,
document: document
}) do
[
CodeAction.DisableCheck.new(
uri: uri,
Expand Down
52 changes: 52 additions & 0 deletions lib/credo_language_server/credo_supervisor.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
defmodule CredoLanguageServer.CredoSupervisor do
@moduledoc false

use Supervisor

@env Mix.env()

def start_link(init_arg) do
Supervisor.start_link(__MODULE__, init_arg, name: __MODULE__)
end

@impl true
def init(_init_arg) do
if @env == :test do
:ignore
else
{opts, _} =
OptionParser.parse!(System.argv(),
strict: [stdio: :boolean, port: :integer]
)

{:ok, _} = Application.ensure_all_started(:credo)
GenServer.call(Credo.CLI.Output.Shell, {:suppress_output, true})

buffer_opts =
cond do
opts[:stdio] ->
[]

is_integer(opts[:port]) ->
IO.puts("Starting on port #{opts[:port]}")
[communication: {GenLSP.Communication.TCP, [port: opts[:port]]}]

true ->
raise "Unknown option"
end

children = [
{CredoLanguageServer.Runtime, name: CredoLanguageServer.Runtime},
{Task.Supervisor, name: CredoLanguageServer.TaskSupervisor},
{GenLSP.Buffer, buffer_opts},
{CredoLanguageServer.Cache, [name: :credo_cache]},
{CredoLanguageServer,
cache: :credo_cache,
task_supervisor: CredoLanguageServer.TaskSupervisor,
runtime: CredoLanguageServer.Runtime}
]

Supervisor.init(children, strategy: :one_for_one)
end
end
end