From 48bd1a73017a1c8a5e388a5898780cb13221998b Mon Sep 17 00:00:00 2001 From: robmckinnon Date: Mon, 20 Mar 2023 09:08:25 +0000 Subject: [PATCH] Add extract function as an execute command --- .../code_mod/refactor_extract_function.ex | 18 +++++++++ .../providers/execute_command.ex | 1 + .../execute_command/extract_function.ex | 39 +++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 apps/language_server/lib/language_server/experimental/code_mod/refactor_extract_function.ex create mode 100644 apps/language_server/lib/language_server/providers/execute_command/extract_function.ex diff --git a/apps/language_server/lib/language_server/experimental/code_mod/refactor_extract_function.ex b/apps/language_server/lib/language_server/experimental/code_mod/refactor_extract_function.ex new file mode 100644 index 000000000..128d7d781 --- /dev/null +++ b/apps/language_server/lib/language_server/experimental/code_mod/refactor_extract_function.ex @@ -0,0 +1,18 @@ +defmodule ElixirLS.LanguageServer.Experimental.CodeMod.RefactorExtractFunction do + alias ElixirLS.LanguageServer.Experimental.CodeMod.Diff + alias ElixirLS.LanguageServer.Experimental.CodeMod.ExtractFunction + + alias Sourceror.Zipper + + require Logger + + def text_edits(original_text, tree, start_line, end_line, new_function_name) do + result = + tree + |> Zipper.zip() + |> ExtractFunction.extract_function(start_line + 1, end_line + 1, new_function_name) + |> Sourceror.to_string() + + {:ok, Diff.diff(original_text, result)} + end +end diff --git a/apps/language_server/lib/language_server/providers/execute_command.ex b/apps/language_server/lib/language_server/providers/execute_command.ex index 414759acc..9acec43b3 100644 --- a/apps/language_server/lib/language_server/providers/execute_command.ex +++ b/apps/language_server/lib/language_server/providers/execute_command.ex @@ -8,6 +8,7 @@ defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand do @handlers %{ "spec" => ExecuteCommand.ApplySpec, "expandMacro" => ExecuteCommand.ExpandMacro, + "extractFunction" => ExecuteCommand.ExtractFunction, "manipulatePipes" => ExecuteCommand.ManipulatePipes, "restart" => ExecuteCommand.Restart, "mixClean" => ExecuteCommand.MixClean, diff --git a/apps/language_server/lib/language_server/providers/execute_command/extract_function.ex b/apps/language_server/lib/language_server/providers/execute_command/extract_function.ex new file mode 100644 index 000000000..22d1f6e45 --- /dev/null +++ b/apps/language_server/lib/language_server/providers/execute_command/extract_function.ex @@ -0,0 +1,39 @@ +defmodule ElixirLS.LanguageServer.Providers.ExecuteCommand.ExtractFunction do + @moduledoc """ + This module implements a custom command extract function. + Sends applyEdit request. + """ + + alias ElixirLS.LanguageServer.JsonRpc + alias ElixirLS.LanguageServer.Server + alias ElixirLS.LanguageServer.Experimental.CodeMod.Ast + alias ElixirLS.LanguageServer.Experimental.CodeMod.RefactorExtractFunction + + require Logger + + @behaviour ElixirLS.LanguageServer.Providers.ExecuteCommand + + @impl ElixirLS.LanguageServer.Providers.ExecuteCommand + def execute([uri, start_line, end_line, new_function_name], state) do + with source_file <- Server.get_source_file(state, uri), + {:ok, tree} <- Ast.from(source_file.text, include_comments: true), + {:ok, text_edits} <- + RefactorExtractFunction.text_edits( + source_file.text, + tree, + start_line, + end_line, + new_function_name + ) do + apply_edits(uri, text_edits) + {:ok, nil} + end + end + + def apply_edits(uri, text_edits) do + JsonRpc.send_request("workspace/applyEdit", %{ + "label" => "Extract function", + "edit" => %{"changes" => %{uri => text_edits}} + }) |> IO.inspect(label: :rpc_response, limit: :infinity) + end +end