From ce2cd59eb5a540a53d1d54c33ef7e1fe90f862cd Mon Sep 17 00:00:00 2001 From: robmckinnon Date: Sun, 12 Mar 2023 21:29:12 +0000 Subject: [PATCH] Error when lines not extractable to function --- .../experimental/code_mod/extract_function.ex | 45 ++++++++++--------- .../code_mod/extract_function_test.exs | 21 +++++++++ 2 files changed, 45 insertions(+), 21 deletions(-) diff --git a/apps/language_server/lib/language_server/experimental/code_mod/extract_function.ex b/apps/language_server/lib/language_server/experimental/code_mod/extract_function.ex index fc260b83a..4fe7e48f8 100644 --- a/apps/language_server/lib/language_server/experimental/code_mod/extract_function.ex +++ b/apps/language_server/lib/language_server/experimental/code_mod/extract_function.ex @@ -10,27 +10,30 @@ defmodule ElixirLS.LanguageServer.Experimental.CodeMod.ExtractFunction do """ def extract_function(zipper, start_line, end_line, function_name) do {quoted_after_extract, acc} = extract_lines(zipper, start_line, end_line, function_name) - - new_function_zipper = new_function(function_name, [], acc.lines) |> Z.zip() - declared_vars = vars_declared(new_function_zipper) |> Enum.uniq() - used_vars = vars_used(new_function_zipper) |> Enum.uniq() - - args = used_vars -- declared_vars - returns = declared_vars |> Enum.filter(&(&1 in acc.vars)) - - {zipper, extracted} = - add_returned_vars(Z.zip(quoted_after_extract), returns, function_name, args, acc.lines) - - enclosing = acc.def - - zipper - |> top_find(fn - {:def, _meta, [{^enclosing, _, _}, _]} -> true - _ -> false - end) - |> Z.insert_right(extracted) - |> fix_block() - |> Z.root() + if Enum.empty?(acc.lines) do + {:error, :not_extractable} + else + new_function_zipper = new_function(function_name, [], acc.lines) |> Z.zip() + declared_vars = vars_declared(new_function_zipper) |> Enum.uniq() + used_vars = vars_used(new_function_zipper) |> Enum.uniq() + + args = used_vars -- declared_vars + returns = declared_vars |> Enum.filter(&(&1 in acc.vars)) + + {zipper, extracted} = + add_returned_vars(Z.zip(quoted_after_extract), returns, function_name, args, acc.lines) + + enclosing = acc.def + + zipper + |> top_find(fn + {:def, _meta, [{^enclosing, _, _}, _]} -> true + _ -> false + end) + |> Z.insert_right(extracted) + |> fix_block() + |> Z.root() + end end @doc """ diff --git a/apps/language_server/test/experimental/code_mod/extract_function_test.exs b/apps/language_server/test/experimental/code_mod/extract_function_test.exs index e767ccfe7..44d8099eb 100644 --- a/apps/language_server/test/experimental/code_mod/extract_function_test.exs +++ b/apps/language_server/test/experimental/code_mod/extract_function_test.exs @@ -204,6 +204,11 @@ defmodule ElixirLS.LanguageServer.Experimental.CodeMod.ExtractFunctionTest do Code.eval_string(source) end + + @tag no: 6 + test "errors when extract on second line of multi-line function call", %{quoted: quoted} do + {:error, :not_extractable} = ExtractFunction.extract_function(Z.zip(quoted), 11, 11, :bar) + end end describe "extract_lines/3" do @@ -254,5 +259,21 @@ defmodule ElixirLS.LanguageServer.Experimental.CodeMod.ExtractFunctionTest do "{:vars, []}" ] = lines |> Enum.map(&Sourceror.to_string(&1)) end + + @tag no: 23 + test "noop when second line of multi-line function call", %{quoted: quoted} do + {zipper, lines} = ExtractFunction.extract_lines(Z.zip(quoted), 11, 11) + + assert "defmodule Baz23 do\n def foo(one, two) do\n three = 3\n IO.inspect(one)\n IO.inspect(two)\n IO.inspect(three)\n four = 4\n IO.inspect(three)\n\n IO.inspect(\n four: four,\n force_format_on_new_line_with_really_long_atom: true\n )\n\n # comment\n end\nend" = + Sourceror.to_string(zipper) + + assert [ + "{:def, :foo}", + "{:def_end, 15}", + "{:lines, []}", + "{:replace_with, nil}", + "{:vars, []}" + ] = lines |> Enum.map(&Sourceror.to_string(&1)) + end end end