From e735de54815464e82d55f7939a0d32eadaca237c Mon Sep 17 00:00:00 2001 From: Mitchell Hanberg Date: Wed, 1 Nov 2023 10:05:58 -0400 Subject: [PATCH] feat(extension,credo): ability to disable Credo extension --- lib/next_ls.ex | 40 +++++++++++++++++-- lib/next_ls/extensions/credo_extension.ex | 37 +++++++++++------ .../extensions/credo_extension_test.exs | 18 +++++++++ test/support/utils.ex | 4 +- 4 files changed, 81 insertions(+), 18 deletions(-) diff --git a/lib/next_ls.ex b/lib/next_ls.ex index 2d901b8a..62ddb045 100644 --- a/lib/next_ls.ex +++ b/lib/next_ls.ex @@ -67,7 +67,7 @@ defmodule NextLS do registry = Keyword.fetch!(args, :registry) - extensions = Keyword.get(args, :extensions, [NextLS.ElixirExtension, NextLS.CredoExtension]) + extensions = Keyword.get(args, :extensions, elixir: NextLS.ElixirExtension, credo: NextLS.CredoExtension) cache = Keyword.fetch!(args, :cache) {:ok, logger} = DynamicSupervisor.start_child(dynamic_supervisor, {NextLS.Logger, lsp: lsp}) @@ -598,16 +598,23 @@ defmodule NextLS do ) end - for extension <- lsp.assigns.extensions do - {:ok, _} = + for {id, extension} <- lsp.assigns.extensions do + child = DynamicSupervisor.start_child( lsp.assigns.dynamic_supervisor, {extension, + settings: Map.fetch!(lsp.assigns.init_opts.extensions, id), + logger: lsp.assigns.logger, cache: lsp.assigns.cache, registry: lsp.assigns.registry, publisher: self(), task_supervisor: lsp.assigns.runtime_task_supervisor} ) + + case child do + {:ok, _pid} -> :ok + :ignore -> :ok + end end with %{dynamic_registration: true} <- lsp.assigns.client_capabilities.workspace.did_change_watched_files do @@ -1092,11 +1099,25 @@ defmodule NextLS do defstruct completions: %{enable: false} end + defmodule InitOpts.Extensions.Credo do + @moduledoc false + defstruct enable: true + end + + defmodule InitOpts.Extensions do + @moduledoc false + defstruct elixir: %{enable: true}, + credo: %NextLS.InitOpts.Extensions.Credo{} + end + defmodule InitOpts do @moduledoc false import Schematic - defstruct mix_target: "host", mix_env: "dev", experimental: %NextLS.InitOpts.Experimental{} + defstruct mix_target: "host", + mix_env: "dev", + experimental: %NextLS.InitOpts.Experimental{}, + extensions: %NextLS.InitOpts.Extensions{} def validate(opts) do schematic = @@ -1110,6 +1131,17 @@ defmodule NextLS do map(%{ {"enable", :enable} => bool() }) + }), + optional(:extensions) => + schema(NextLS.InitOpts.Extensions, %{ + optional(:credo) => + schema(NextLS.InitOpts.Extensions.Credo, %{ + optional(:enable) => bool() + }), + optional(:elixir) => + map(%{ + {"enable", :enable} => bool() + }) }) }) ) diff --git a/lib/next_ls/extensions/credo_extension.ex b/lib/next_ls/extensions/credo_extension.ex index b0662eb9..aa5e89b1 100644 --- a/lib/next_ls/extensions/credo_extension.ex +++ b/lib/next_ls/extensions/credo_extension.ex @@ -13,7 +13,7 @@ defmodule NextLS.CredoExtension do def start_link(args) do GenServer.start_link( __MODULE__, - Keyword.take(args, [:cache, :registry, :publisher, :task_supervisor]), + Keyword.take(args, [:cache, :registry, :publisher, :task_supervisor, :settings, :logger]), Keyword.take(args, [:name]) ) end @@ -24,18 +24,29 @@ defmodule NextLS.CredoExtension do registry = Keyword.fetch!(args, :registry) publisher = Keyword.fetch!(args, :publisher) task_supervisor = Keyword.fetch!(args, :task_supervisor) - - Registry.register(registry, :extensions, :credo) - - {:ok, - %{ - runtimes: Map.new(), - cache: cache, - registry: registry, - task_supervisor: task_supervisor, - publisher: publisher, - refresh_refs: Map.new() - }} + settings = Keyword.fetch!(args, :settings) + logger = Keyword.fetch!(args, :logger) + + if settings.enable do + Registry.register(registry, :extensions, :credo) + + NextLS.Logger.log(logger, "[extension] Credo initializing with options #{inspect(settings)}") + + {:ok, + %{ + runtimes: Map.new(), + cache: cache, + registry: registry, + task_supervisor: task_supervisor, + publisher: publisher, + settings: settings, + logger: logger, + refresh_refs: Map.new() + }} + else + NextLS.Logger.log(logger, "[extension] Credo disabled") + :ignore + end end @impl GenServer diff --git a/test/next_ls/extensions/credo_extension_test.exs b/test/next_ls/extensions/credo_extension_test.exs index 8fe60d23..fc302a85 100644 --- a/test/next_ls/extensions/credo_extension_test.exs +++ b/test/next_ls/extensions/credo_extension_test.exs @@ -38,6 +38,19 @@ defmodule NextLS.CredoExtensionTest do setup :with_lsp + @tag init_options: %{"extensions" => %{"credo" => %{"enable" => false}}} + test "disables Credo", %{client: client, foo: foo} = context do + assert :ok == notify(client, %{method: "initialized", jsonrpc: "2.0", params: %{}}) + + assert_is_ready(context, "my_proj") + assert_compiled(context, "my_proj") + + assert_notification "window/logMessage", %{ + "message" => "[NextLS] [extension] Credo disabled", + "type" => 4 + } + end + test "publishes credo diagnostics", %{client: client, foo: foo} = context do assert :ok == notify(client, %{method: "initialized", jsonrpc: "2.0", params: %{}}) @@ -45,6 +58,11 @@ defmodule NextLS.CredoExtensionTest do assert_compiled(context, "my_proj") assert_notification "$/progress", %{"value" => %{"kind" => "end", "message" => "Finished indexing!"}} + assert_notification "window/logMessage", %{ + "message" => "[NextLS] [extension] Credo initializing with options" <> _, + "type" => 4 + } + uri = uri(foo) assert_notification "textDocument/publishDiagnostics", %{ diff --git a/test/support/utils.ex b/test/support/utils.ex index 8c38a384..58b936f1 100644 --- a/test/support/utils.ex +++ b/test/support/utils.ex @@ -44,8 +44,9 @@ defmodule NextLS.Support.Utils do r_tvisor = start_supervised!(Supervisor.child_spec(Task.Supervisor, id: :two)) rvisor = start_supervised!({DynamicSupervisor, [strategy: :one_for_one]}) start_supervised!({Registry, [keys: :duplicate, name: context.module]}) - extensions = [NextLS.ElixirExtension, NextLS.CredoExtension] + extensions = [elixir: NextLS.ElixirExtension, credo: NextLS.CredoExtension] cache = start_supervised!(NextLS.DiagnosticCache) + init_options = context[:init_options] || %{} server = server(NextLS, @@ -67,6 +68,7 @@ defmodule NextLS.Support.Utils do id: 1, jsonrpc: "2.0", params: %{ + initializationOptions: init_options, capabilities: %{ workspace: %{ workspaceFolders: true