Skip to content

Commit

Permalink
feature(format): support format CLI opt-out
Browse files Browse the repository at this point in the history
  • Loading branch information
ckoch-cars committed Aug 4, 2022
1 parent db25c9f commit 2b7b09d
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 16 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Use at your peril, _for now._
- [X] Add Mix.Task tests
- [X] Add CLI tests
- [X] Add and configure CHANGELOG tracking.
- [X] Support opt-out of format-ing

## Roadmap TODO

Expand Down
24 changes: 12 additions & 12 deletions lib/ex_factor.ex
Original file line number Diff line number Diff line change
Expand Up @@ -36,38 +36,38 @@ defmodule ExFactor do
# remove should be last (before format)
removals = Remover.remove(opts)

format(%{additions: emplace, changes: changes, removals: removals}, dry_run)
format(%{additions: emplace, changes: changes, removals: removals}, dry_run, opts)
end

def path(module) do
Path.join(["lib", Macro.underscore(module) <> ".ex"])
end

defp format(%{path: nil} = struct, _dry_run), do: struct
defp format(%{path: nil} = struct, _dry_run, _format), do: struct

defp format(output, true), do: output
defp format(output, true, _format), do: output

defp format(%{additions: adds, changes: changes, removals: removals} = output, false) do
defp format(%{additions: adds, changes: changes, removals: removals} = output, false, opts) do
%{
additions: format(adds),
changes: format(changes),
removals: format(removals)
additions: format(adds, opts),
changes: format(changes, opts),
removals: format(removals, opts)
}

output
end

defp format(list) when is_list(list) do
defp format(list, opts) when is_list(list) do
Enum.map(list, fn elem ->
format(elem)
format(elem, opts)
Map.get_and_update(elem, :state, fn val -> {val, [:formatted | val]} end)
end)
end

defp format(%{state: [:unchanged]} = struct), do: struct
defp format(%{state: [:unchanged]} = struct, _opts), do: struct

defp format(struct) do
Formatter.format([struct.path])
defp format(struct, opts) do
Formatter.format([struct.path], opts)
Map.get_and_update(struct, :state, fn val -> {val, [:formatted | val]} end)
end
end
10 changes: 7 additions & 3 deletions lib/ex_factor/formatter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ defmodule ExFactor.Formatter do
`ExFactor.Formatter` Format a list of files
"""

def format([nil]), do: nil
def format(args, opts \\ [])

def format(args) do
Mix.Tasks.Format.run(args)
def format([nil], _opts), do: nil

def format(args, opts) do
if Keyword.get(opts, :format, true) do
Mix.Tasks.Format.run(args)
end
end
end
9 changes: 9 additions & 0 deletions lib/mix/tasks/ex_factor.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,20 @@ defmodule Mix.Tasks.ExFactor do
- `:source_path` Specify an alternate (non-standard) path for the destination file.
- `:dryrun` Don't write any updates, only return the built results.
- `:verbose` (Default false) include the :state and :file_contents key values.
- `:format` (Default true) when false don't run the formatter
Example Usage:
```
mix ex_factor --module MyModule.ToChange --function fn_to_change
--arity 2 --target YourModule.ChangeTo
```
Example Usage:
```
mix ex_factor --module MyModule.ToChange --function fn_to_change
--arity 2 --target YourModule.ChangeTo
--no-format --no-dryrun --no-verbose
```
"""

use Mix.Task
Expand All @@ -44,6 +52,7 @@ defmodule Mix.Tasks.ExFactor do
arity: :integer,
dryrun: :boolean,
verbose: :boolean,
format: :boolean,
function: :string,
key: :string,
module: :string,
Expand Down
37 changes: 36 additions & 1 deletion test/ex_factor/cli_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ defmodule ExFactor.CLITest do
use ExUnit.Case
import ExUnit.CaptureIO

setup_all do
setup do
File.mkdir_p("test/tmp")

on_exit(fn ->
Expand Down Expand Up @@ -60,4 +60,39 @@ defmodule ExFactor.CLITest do
# no new file gets written
assert {:error, :enoent} = File.read(target_path)
end

test "with --no-format" do
content = """
defmodule ExFactorSampleModule do
@somedoc "This is somedoc"
# a comment and no aliases
_docp = "here's an arbitrary module underscore"
@spec pub1(term()) :: term()
def pub1(arg1) do
:pub1_ok
end
end
"""

File.write("test/tmp/source_module.ex", content)
target_path = "test/tmp/target_module.ex"

opts = [
target_path: target_path,
target: "ExFactor.NewMod",
module: "ExFactorSampleModule",
source_path: "test/tmp/source_module.ex",
function: :pub1,
arity: 1,
format: false
]

argv = OptionParser.to_argv(opts)
|> IO.inspect(label: "")

{_cli_output, exit_status} = System.cmd("mix", ["ex_factor" | argv])
assert exit_status == 0
file = File.read!(target_path) |> IO.inspect(label: "")
assert file =~ "\n@spec pub1(term()) :: term()\ndef pub1(arg1) do\n :pub1_ok\nend\nend"
end
end
15 changes: 15 additions & 0 deletions test/ex_factor/formatter_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,20 @@ defmodule ExFactor.FormatterTest do
assert formatted_file =~ "\n # unindented line"
assert formatted_file =~ "\n # overindented line"
end

test "it should not format the specified files when format false" do
content = """
defmodule ExFactorSampleModule do
# unindented line
# overindented line
end
"""

File.write("test/tmp/test_module.ex", content)
Formatter.format(["test/tmp/test_module.ex"], [format: false])
{:ok, formatted_file} = File.read("test/tmp/test_module.ex")
assert formatted_file =~ "# unindented line"
assert formatted_file =~ "\n # overindented line"
end
end
end
48 changes: 48 additions & 0 deletions test/ex_factor_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,54 @@ defmodule ExFactorTest do
refute file =~ "def refactor1([]) do"
end

test "it skips formatting when specified in opts" 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
:empty
end
def refactor1(arg1) do
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.TargetModule",
source_module: "ExFactor.Tmp.SourceModule",
source_function: :refactor1,
arity: 1,
format: false
]

%{additions: _, changes: _, removals: _} = _results = ExFactor.refactor(opts)

file = File.read!("lib/ex_factor/tmp/target_module.ex")

assert file =~ "\ndef refactor1(arg1) do"
assert file =~ "defmodule ExFactor.Tmp.TargetModule do\n @doc \"some docs\""
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")
Expand Down

0 comments on commit 2b7b09d

Please sign in to comment.