diff --git a/README.md b/README.md index bcccac7..332d06e 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,6 @@ Use at your peril, _for now._ - [] find private functions references in refactored fn bodies. - [] update test file refs by CLI option - [] format changes - - [] CLI output, list files changed and created. - [] ElixirLS integration for VSCode? - [] Write the module code to rename usages of the refactored function - [] guthub actions, run test suite @@ -34,6 +33,7 @@ Use at your peril, _for now._ ## Roadmap TODONE - [X] Write a mix task to invoke the Refactorer - [X] dry-run option + - [X] CLI output, list files changed and created. ## Installation diff --git a/lib/ex_factor/extractor.ex b/lib/ex_factor/extractor.ex index 97e1764..34d8b66 100644 --- a/lib/ex_factor/extractor.ex +++ b/lib/ex_factor/extractor.ex @@ -30,9 +30,12 @@ defmodule ExFactor.Extractor do source_path = Keyword.get(opts, :source_path, path(source_module)) dry_run = Keyword.get(opts, :dry_run, false) {_ast, block_contents} = Parser.block_contents(source_path) - to_extract = block_contents - |> Neighbors.walk(source_function, arity) - |> Enum.map(&(Macro.to_string(&1))) + + to_extract = + block_contents + |> Neighbors.walk(source_function, arity) + |> Enum.map(&Macro.to_string(&1)) + # |> IO.inspect(label: "to string") string_fns = Enum.join(to_extract, "\n") @@ -48,7 +51,7 @@ defmodule ExFactor.Extractor do |> List.insert_at(end_line - 1, refactor_message()) |> List.insert_at(end_line, string_fns) |> Enum.join("\n") - |> then(fn contents -> write_file(target_path, contents, dry_run) end) + |> then(fn contents -> write_file(target_path, contents, target_module, dry_run) end) _ -> contents = @@ -60,7 +63,7 @@ defmodule ExFactor.Extractor do end |> Macro.to_string() - write_file(target_path, contents, dry_run) + write_file(target_path, contents, source_module, dry_run) end end @@ -70,10 +73,16 @@ defmodule ExFactor.Extractor do defp refactor_message, do: "#refactored function moved with ExFactor" - defp write_file(_target_path, contents, true) do - contents + defp write_file(target_path, contents, module, true) do + %{ + module: module, + path: target_path, + message: "--dry_run changes to make", + file_contents: contents + } end - defp write_file(target_path, contents, _) do + + defp write_file(target_path, contents, _module, _dry_run) do File.write(target_path, contents, [:write]) end end diff --git a/lib/ex_factor/remover.ex b/lib/ex_factor/remover.ex index 4e543bc..bdc6fd9 100644 --- a/lib/ex_factor/remover.ex +++ b/lib/ex_factor/remover.ex @@ -14,8 +14,6 @@ defmodule ExFactor.Remover do arity = Keyword.fetch!(opts, :arity) source_path = Keyword.get(opts, :source_path, path(source_module)) dry_run = Keyword.get(opts, :dry_run, false) - # |> IO.inspect(label: "REMOVE source_path") - {_ast, block_contents} = Parser.all_functions(source_path) fns_to_remove = Enum.filter(block_contents, &(&1.name == source_function)) @@ -34,7 +32,7 @@ defmodule ExFactor.Remover do |> List.insert_at(function.start_line, comment(source_function, arity, function.defn)) end) |> Enum.join("\n") - |> then(fn str -> write_file(source_path, str, dry_run) end) + |> then(fn str -> write_file(source_path, str, source_module, dry_run) end) end defp comment(name, arity, "@spec") do @@ -54,11 +52,16 @@ defmodule ExFactor.Remover do """ end - defp write_file(_path, contents, true) do - contents + defp write_file(path, contents, source_module, true) do + %{ + module: source_module, + path: path, + message: "--dry_run changes to make", + file_contents: contents + } end - defp write_file(path, contents, _) do + defp write_file(path, contents, _source_module, _) do File.write(path, contents, [:write]) end diff --git a/lib/mix/tasks/ex_factor/refactor.ex b/lib/mix/tasks/ex_factor/refactor.ex index 11e827f..5e1c13b 100644 --- a/lib/mix/tasks/ex_factor/refactor.ex +++ b/lib/mix/tasks/ex_factor/refactor.ex @@ -29,18 +29,19 @@ defmodule Mix.Tasks.ExFactor.Refactor do use Mix.Task def run(argv) do - {parsed_opts, _, _} = OptionParser.parse(argv, strict: - [ - arity: :integer, - dry_run: :boolean, - function: :string, - key: :string, - module: :string, - source_path: :string, - target: :string, - target_path: :string - ] - ) + {parsed_opts, _, _} = + OptionParser.parse(argv, + strict: [ + arity: :integer, + dry_run: :boolean, + function: :string, + key: :string, + module: :string, + source_path: :string, + target: :string, + target_path: :string + ] + ) # parsed_opts # |> IO.inspect(label: "PARSED ARGS") diff --git a/mix.exs b/mix.exs index 5c2ef94..181a4e0 100644 --- a/mix.exs +++ b/mix.exs @@ -44,7 +44,6 @@ defmodule ExFactor.MixProject do # license* CHANGELOG* changelog* src), licenses: ["CC-BY-NC-ND-4.0"], links: %{"GitHub" => "https://github.com/ckochx/ex_factor"} - ] end end diff --git a/test/ex_factor/extractor_test.exs b/test/ex_factor/extractor_test.exs index 663f51b..9d4aa4a 100644 --- a/test/ex_factor/extractor_test.exs +++ b/test/ex_factor/extractor_test.exs @@ -20,7 +20,9 @@ defmodule ExFactor.ExtractorTest do arity: 1 ] - assert_raise KeyError, "key :target_module not found in: #{inspect(opts)}", fn -> Extractor.emplace(opts) end + assert_raise KeyError, "key :target_module not found in: #{inspect(opts)}", fn -> + Extractor.emplace(opts) + end end test "write a new file with the function" do @@ -96,7 +98,9 @@ defmodule ExFactor.ExtractorTest do output = Extractor.emplace(opts) assert {:error, :enoent} = File.read(target_path) - assert output =~ "defmodule(ExFactor.NewMod) do" + assert output.file_contents + assert output.message == "--dry_run changes to make" + assert output.module == ExFactorSampleModule end test "write a new file with the function, infer some defaults" do diff --git a/test/ex_factor/remover_test.exs b/test/ex_factor/remover_test.exs index dc7c9a1..3df149c 100644 --- a/test/ex_factor/remover_test.exs +++ b/test/ex_factor/remover_test.exs @@ -69,12 +69,14 @@ defmodule ExFactor.RemoverTest do """ File.write("test/tmp/source_module.ex", module) + opts = [ source_module: ExFactorSampleModule, source_path: "test/tmp/source_module.ex", source_function: :pub1, arity: 1 ] + Remover.remove(opts) updated_file = File.read!("test/tmp/source_module.ex") @@ -112,6 +114,7 @@ defmodule ExFactor.RemoverTest do """ File.write("test/tmp/source_module.ex", module) + opts = [ dry_run: true, source_module: ExFactorSampleModule, @@ -119,17 +122,22 @@ defmodule ExFactor.RemoverTest do source_function: :pub1, arity: 1 ] - changes = Remover.remove(opts) + + changes = + Remover.remove(opts) + |> IO.inspect(label: "") unchanged_file = File.read!("test/tmp/source_module.ex") assert unchanged_file =~ "def pub1(arg1) do" refute unchanged_file =~ "Function: pub1/1 removed by ExFactor" assert unchanged_file =~ "@spec pub1(term()) :: term()" - assert changes =~ "Function: pub1/1 removed by ExFactor" - refute changes =~ "@spec pub1(term()) :: term()" - refute changes =~ "def pub1(arg1) do" + assert changes.file_contents =~ "Function: pub1/1 removed by ExFactor" + refute changes.file_contents =~ "@spec pub1(term()) :: term()" + refute changes.file_contents =~ "def pub1(arg1) do" + assert changes.path == "test/tmp/source_module.ex" + assert changes.module == ExFactorSampleModule + assert changes.message == "--dry_run changes to make" end - end end diff --git a/test/ex_factor_test.exs b/test/ex_factor_test.exs index a28976e..a3ef6a5 100644 --- a/test/ex_factor_test.exs +++ b/test/ex_factor_test.exs @@ -1,7 +1,7 @@ defmodule ExFactorTest do use ExUnit.Case - setup_all do + setup_all do File.mkdir_p("lib/ex_factor/tmp") on_exit(fn -> @@ -63,8 +63,64 @@ defmodule ExFactorTest do # |> IO.inspect(label: "") refute file =~ "def refactor1(arg1) do" refute file =~ "def refactor1([]) do" + assert results == {:ok, :ok} + end + + test "it returns the results of the dry_run changes" do + File.rm("lib/ex_factor/tmp/source_module.ex") + File.rm("lib/ex_factor/tmp/target_module.ex") + + content = """ + defmodule ExFactor.Tmp.SourceModule do + @somedoc "This is somedoc" + @doc "this is some documentation for refactor1/1" + def refactor1(arg1) do + :ok + end + def refactor1([]) do + :empty + end + end + """ + + File.write("lib/ex_factor/tmp/source_module.ex", content) + + content = """ + defmodule ExFactor.Tmp.TargetModule do + @somedoc "This is somedoc TargetModule" + @doc "some docs" + def pub_exists(arg_exists) do + :ok + end + def pub_exists(:error) do + :error + end + end + """ + + File.write("lib/ex_factor/tmp/target_module.ex", content) + + opts = [ + target_module: ExFactor.Tmp.TargetModule, + source_module: ExFactor.Tmp.SourceModule, + source_function: :refactor1, + arity: 1, + dry_run: true + ] + + {extract_contents, remove_contents} = ExFactor.refactor(opts) + + # assert that the original files are unchanged + file = File.read!("lib/ex_factor/tmp/target_module.ex") + refute file =~ "def(refactor1(arg1)) do" + refute file =~ "def(refactor1([])) do" + + file = File.read!("lib/ex_factor/tmp/source_module.ex") + assert file =~ "def refactor1(arg1) do" + assert file =~ "def refactor1([]) do" - results |> IO.inspect(label: "ExFactorTest results") + # extract_contents |> IO.inspect(label: "") + # remove_contents |> IO.inspect(label: "") end end end