Packages

Elixir-native, protocol-focused Language Server Protocol toolkit.

Current section

Files

Jump to
elixir_lsp lib mix tasks lsp.gen.handler.ex
Raw

lib/mix/tasks/lsp.gen.handler.ex

defmodule Mix.Tasks.Lsp.Gen.Handler do
use Mix.Task
import Mix.Generator
@shortdoc "Generates an LSP handler module and test scaffold"
@moduledoc """
Generates an idiomatic handler and matching test template.
mix lsp.gen.handler Hover
"""
@impl true
def run(args) do
Mix.Task.run("app.start")
case args do
[name] ->
create_handler(name)
_ ->
Mix.raise("Usage: mix lsp.gen.handler NAME")
end
end
defp create_handler(name) do
app = Mix.Project.config()[:app] |> to_string()
app_module = Mix.Project.config()[:app] |> to_string() |> Macro.camelize()
module_base = Macro.camelize(name)
module = "#{app_module}.Handlers.#{module_base}Handler"
lib_path = "lib/#{app}/handlers/#{Macro.underscore(name)}_handler.ex"
test_path = "test/#{app}/handlers/#{Macro.underscore(name)}_handler_test.exs"
create_file(lib_path, handler_template(module))
create_file(test_path, test_template(module, module_base))
end
defp handler_template(module) do
"""
defmodule #{module} do
use ElixirLsp.Server
defrequest :initialize do
ElixirLsp.HandlerContext.reply(ctx, ElixirLsp.Responses.initialize(%{}, name: "#{module}"))
end
end
"""
end
defp test_template(module, module_base) do
"""
defmodule #{module}Test do
use ExUnit.Case, async: true
alias ElixirLsp.{Message, Protocol, Server}
test \"#{module_base} handler responds to initialize\" do
parent = self()
{:ok, server} =
Server.start_link(
handler: #{module},
send: fn payload -> send(parent, {:outbound, IO.iodata_to_binary(payload)}) end
)
req = Protocol.request(1, :initialize, %{}) |> Protocol.encode() |> IO.iodata_to_binary()
Server.feed(server, req)
assert_receive {:outbound, payload}, 500
assert {:ok, [%Message.Response{}], _} = Protocol.decode(payload, Protocol.new_state())
end
end
"""
end
end