From e2ee4b8ed94047ec2b76fdca2a111e9085636942 Mon Sep 17 00:00:00 2001 From: Christian Koch Date: Thu, 4 Aug 2022 10:15:35 -0500 Subject: [PATCH] feature(CLI interface): add CLI for moduelonly Add tests for moduleonly CLI interface. --- lib/ex_factor.ex | 15 +++++++++ lib/mix/tasks/ex_factor.ex | 14 ++++++-- test/ex_factor/cli_test.exs | 35 ++++++++++++++++++-- test/ex_factor/mix_task_test.exs | 47 +++++++++++++++++++++++--- test/ex_factor_test.exs | 57 ++++++++++++++++++++++++++++++++ 5 files changed, 159 insertions(+), 9 deletions(-) diff --git a/lib/ex_factor.ex b/lib/ex_factor.ex index 7ffcb81..950a85b 100644 --- a/lib/ex_factor.ex +++ b/lib/ex_factor.ex @@ -39,6 +39,21 @@ defmodule ExFactor do format(%{additions: emplace, changes: changes, removals: removals}, dry_run, opts) end + def refactor_module(opts) do + source_module = Keyword.fetch!(opts, :source_module) + target_module = Keyword.fetch!(opts, :target_module) + dry_run = Keyword.get(opts, :dry_run, false) + + opts = + opts + |> Keyword.put_new(:target_path, path(target_module)) + |> Keyword.put_new(:source_path, path(source_module)) + + changes = Changer.rename_module(opts) + + format(%{additions: %ExFactor{}, changes: changes, removals: %ExFactor{}}, dry_run, opts) + end + def path(module) do Path.join(["lib", Macro.underscore(module) <> ".ex"]) end diff --git a/lib/mix/tasks/ex_factor.ex b/lib/mix/tasks/ex_factor.ex index 27a86f6..3f7d392 100644 --- a/lib/mix/tasks/ex_factor.ex +++ b/lib/mix/tasks/ex_factor.ex @@ -56,6 +56,7 @@ defmodule Mix.Tasks.ExFactor do function: :string, key: :string, module: :string, + moduleonly: :boolean, source_path: :string, target: :string, target_path: :string @@ -64,13 +65,22 @@ defmodule Mix.Tasks.ExFactor do parsed_opts |> options() - |> ExFactor.refactor() + |> choose_your_path() |> cli_output(parsed_opts) end + defp choose_your_path(opts) do + if Keyword.get(opts, :moduleonly, false) do + ExFactor.refactor_module(opts) + else + opts + |> Keyword.put(:source_function, Keyword.fetch!(opts, :function)) + |> ExFactor.refactor() + end + end + defp options(opts) do opts - |> Keyword.put(:source_function, Keyword.fetch!(opts, :function)) |> Keyword.put(:source_module, Keyword.fetch!(opts, :module)) |> Keyword.put(:target_module, Keyword.fetch!(opts, :target)) |> Keyword.put(:dry_run, Keyword.get(opts, :dryrun, false)) diff --git a/test/ex_factor/cli_test.exs b/test/ex_factor/cli_test.exs index 52e32fc..5d576e8 100644 --- a/test/ex_factor/cli_test.exs +++ b/test/ex_factor/cli_test.exs @@ -16,12 +16,13 @@ defmodule ExFactor.CLITest do function: "pub1", arity: 1 ] + argv = OptionParser.to_argv(opts) - capture_io fn -> + capture_io(fn -> {_, exit_status} = System.cmd("mix", ["ex_factor" | argv]) refute exit_status == 0 - end + end) end test "with dry run" do @@ -94,4 +95,34 @@ defmodule ExFactor.CLITest do file = File.read!(target_path) assert file =~ "\n@spec pub1(term()) :: term()\ndef pub1(arg1) do\n :pub1_ok\nend\nend" end + + test "with --moduleonly" do + File.mkdir_p("lib/ex_factor/tmp") + + content = """ + defmodule ExFactor.Module do + def pub1(arg1) do + ExFactorSampleModule.call_some_function(arg1) + end + end + """ + + File.write("lib/ex_factor/tmp/source_module.ex", content) + + opts = [ + target: "ExFactor.NewMod", + module: "ExFactorSampleModule", + moduleonly: true + ] + + argv = OptionParser.to_argv(opts) + + {_cli_output, exit_status} = System.cmd("mix", ["ex_factor" | argv]) + assert exit_status == 0 + file = File.read!("lib/ex_factor/tmp/source_module.ex") + assert file =~ "alias ExFactor.NewMod" + assert file =~ "def pub1(arg1) do\n NewMod.call_some_function(arg1)" + + File.rm_rf("lib/ex_factor/tmp") + end end diff --git a/test/ex_factor/mix_task_test.exs b/test/ex_factor/mix_task_test.exs index ae6760a..1421da6 100644 --- a/test/ex_factor/mix_task_test.exs +++ b/test/ex_factor/mix_task_test.exs @@ -17,6 +17,7 @@ defmodule ExFactor.MixTaskTest do function: "pub1", arity: 1 ] + argv = OptionParser.to_argv(opts) assert_raise KeyError, "key :target not found in: #{inspect(opts)}", fn -> @@ -51,7 +52,7 @@ defmodule ExFactor.MixTaskTest do argv = OptionParser.to_argv(opts) - capture_io fn -> Mix.Tasks.ExFactor.run(argv) end + capture_io(fn -> Mix.Tasks.ExFactor.run(argv) end) file = File.read!(target_path) @@ -89,7 +90,7 @@ defmodule ExFactor.MixTaskTest do ] argv = OptionParser.to_argv(opts) - capture_io fn -> Mix.Tasks.ExFactor.run(argv) end + capture_io(fn -> Mix.Tasks.ExFactor.run(argv) end) file = File.read!(target_path) assert file =~ "def pub1(arg1)" @@ -124,7 +125,7 @@ defmodule ExFactor.MixTaskTest do argv = OptionParser.to_argv(opts) - output = capture_io fn -> Mix.Tasks.ExFactor.run(argv) end + output = capture_io(fn -> Mix.Tasks.ExFactor.run(argv) end) # no new file gets written assert {:error, :enoent} = File.read(target_path) @@ -177,7 +178,7 @@ defmodule ExFactor.MixTaskTest do argv = OptionParser.to_argv(opts) - capture_io fn -> Mix.Tasks.ExFactor.run(argv) end + capture_io(fn -> Mix.Tasks.ExFactor.run(argv) end) file = File.read!(target_path) assert file =~ "def refactor1(arg1) do" @@ -185,5 +186,41 @@ defmodule ExFactor.MixTaskTest do assert file =~ " @doc \"some docs\"" end + setup do + File.mkdir_p("lib/ex_factor/tmp") + + on_exit(fn -> + File.rm_rf("lib/ex_factor/tmp") + end) + end + + test "with --moduleonly" do + content = """ + defmodule ExFactor.Module do + def pub1(arg1) do + ExFactorSampleModule.call_some_function(arg1) + end + end + """ + + File.write("lib/ex_factor/tmp/source_module.ex", content) + + opts = [ + target: "ExFactor.NewMod", + module: "ExFactorSampleModule", + moduleonly: true + ] + + argv = OptionParser.to_argv(opts) + + capture_io(fn -> + Mix.Tasks.ExFactor.run(argv) + end) + + file = File.read!("lib/ex_factor/tmp/source_module.ex") + assert file =~ "def pub1(arg1) do\n NewMod.call_some_function(arg1)\n end" + assert file =~ "alias ExFactor.NewMod" + end + end -end \ No newline at end of file +end diff --git a/test/ex_factor_test.exs b/test/ex_factor_test.exs index bbebf2d..db749a4 100644 --- a/test/ex_factor_test.exs +++ b/test/ex_factor_test.exs @@ -174,4 +174,61 @@ defmodule ExFactorTest do assert file =~ "def refactor1([]) do" end end + + describe "refactor_module/1" do + test "it refactors the refs to a module name only" 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 + @doc "this is some documentation for refactor1/1" + def refactor1([]) do + ExFactor.Tmp.TargetModule.pub_exists({}) + end + def refactor1(arg1) do + ExFactor.Tmp.TargetModule.pub_exists(arg1) + end + end + """ + + File.write("lib/ex_factor/tmp/source_module.ex", content) + + content = """ + defmodule ExFactor.Tmp.TargetModule do + @doc "some docs" + def pub_exists(:error) do + :error + end + def pub_exists(arg_exists) do + arg_exists + end + end + """ + + File.write("lib/ex_factor/tmp/target_module.ex", content) + + opts = [ + target_module: "ExFactor.Tmp.NewModule", + source_module: "ExFactor.Tmp.TargetModule" + ] + + %{additions: additions, changes: [changes], removals: removals} = + ExFactor.refactor_module(opts) + + assert additions == %ExFactor{} + assert removals == %ExFactor{} + + assert %ExFactor{ + module: ExFactor.Tmp.SourceModule, + path: "lib/ex_factor/tmp/source_module.ex", + state: [:alias_added, :changed, :changed] + } = changes + + file = File.read!("lib/ex_factor/tmp/source_module.ex") + assert file =~ "alias ExFactor.Tmp.NewModule" + assert file =~ "NewModule.pub_exists({})" + assert file =~ "NewModule.pub_exists(arg1)" + end + end end