Skip to content

Commit

Permalink
improvement: Tools for removing formatter plugins & imported deps
Browse files Browse the repository at this point in the history
fix: various fixes for test formatting
  • Loading branch information
zachdaniel committed Nov 2, 2024
1 parent 9bfb920 commit cac9b66
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 43 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ mix igniter.new app_name --install ash
Or if you want to use a different project creator, specify the mix task name with the `--with` flag. Any arguments will be passed through to that task, with the exception of `--install` and `--example`.

```
mix igniter.new app_name --install ash --with phx.new --no-ecto
mix igniter.new app_name --install ash --with phx.new --with-args="--no-ecto"
```

## Patterns
Expand Down
70 changes: 43 additions & 27 deletions lib/igniter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -169,20 +169,32 @@ defmodule Igniter do
def include_glob(igniter, glob) do
glob =
case glob do
%{__struct__: GlobEx} = glob -> glob
string -> GlobEx.compile!(Path.expand(string))
%{__struct__: GlobEx} = glob ->
if Path.type(glob.source) == :relative do
GlobEx.compile!(Path.expand(glob.source))
else
glob
end

string ->
GlobEx.compile!(Path.expand(string))
end

if igniter.assigns[:test_mode?] do
igniter.assigns[:test_files]
|> Map.keys()
|> Enum.filter(&GlobEx.match?(glob, Path.expand(&1)))
|> Enum.filter(fn key ->
expanded = Path.expand(key)
glob.source == expanded || GlobEx.match?(glob, expanded)
end)
|> Enum.map(&Path.relative_to_cwd/1)
|> Enum.reject(fn path ->
Rewrite.has_source?(igniter.rewrite, path)
end)
|> Enum.map(fn path ->
read_ex_source!(igniter, path)
source_handler = source_handler(path)

read_source!(igniter, path, source_handler)
end)
|> Enum.reduce(igniter, fn source, igniter ->
%{igniter | rewrite: Rewrite.put!(igniter.rewrite, source)}
Expand Down Expand Up @@ -1177,7 +1189,8 @@ defmodule Igniter do
""")
end

defp format(igniter, adding_paths, reevaluate_igniter_config? \\ true) do
@doc false
def format(igniter, adding_paths, reevaluate_igniter_config? \\ true) do
igniter =
igniter
|> include_existing_elixir_file("config/config.exs", require?: false)
Expand Down Expand Up @@ -1206,32 +1219,35 @@ defmodule Igniter do
dot_formatter = Rewrite.dot_formatter(rewrite)

rewrite =
Rewrite.map!(rewrite, fn source ->
Enum.reduce(rewrite, rewrite, fn source, rewrite ->
path = source |> Rewrite.Source.get(:path)

if is_nil(adding_paths) || path in List.wrap(adding_paths) do
try do
formatted =
with_evaled_configs(rewrite, fn ->
source
|> Rewrite.Source.format!(dot_formatter: dot_formatter)
|> Rewrite.Source.get(:content)
end)

Rewrite.Source.update(source, :content, formatted)
rescue
e ->
Rewrite.Source.add_issue(source, """
Igniter would have produced invalid syntax.
This is almost certainly a bug in Igniter, or in the implementation
of the task/function you are using.
#{Exception.format(:error, e, __STACKTRACE__)}
""")
end
source =
try do
formatted =
with_evaled_configs(rewrite, fn ->
source
|> Rewrite.Source.format!(dot_formatter: dot_formatter)
|> Rewrite.Source.get(:content)
end)

Rewrite.Source.update(source, :content, formatted)
rescue
e ->
Rewrite.Source.add_issue(source, """
Igniter would have produced invalid syntax.
This is almost certainly a bug in Igniter, or in the implementation
of the task/function you are using.
#{Exception.format(:error, e, __STACKTRACE__)}
""")
end

Rewrite.update!(rewrite, source)
else
source
rewrite
end
end)

Expand Down
20 changes: 15 additions & 5 deletions lib/igniter/code/list.ex
Original file line number Diff line number Diff line change
Expand Up @@ -92,19 +92,29 @@ defmodule Igniter.Code.List do
Common.within(zipper, fn zipper ->
zipper
|> Zipper.down()
|> Common.move_right(predicate)
|> case do
:error ->
:error
nil ->
{:ok, zipper}

{:ok, zipper} ->
{:ok, Zipper.remove(zipper)}
zipper ->
zipper
|> Common.move_right(predicate)
|> case do
:error ->
:error

{:ok, zipper} ->
{:ok, Zipper.remove(zipper)}
end
end
end)
|> case do
:error ->
{:ok, zipper}

{:ok, ^zipper} ->
{:ok, zipper}

{:ok, zipper} ->
remove_from_list(zipper, predicate)
end
Expand Down
104 changes: 99 additions & 5 deletions lib/igniter/project/formatter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ defmodule Igniter.Project.Formatter do
[import_deps: [unquote(dep)]]
end

Common.add_code(zipper, code)
{:ok, Common.add_code(zipper, code)}

zipper ->
zipper
Expand Down Expand Up @@ -56,6 +56,52 @@ defmodule Igniter.Project.Formatter do
end)
end

@doc """
Removes an imported dep from the list of imported deps in the root `.formatter.exs`
"""
@spec remove_imported_dep(Igniter.t(), dep :: atom) :: Igniter.t()
def remove_imported_dep(igniter, dep) do
igniter
|> Igniter.include_or_create_file(".formatter.exs", @default_formatter)
|> Igniter.update_elixir_file(".formatter.exs", fn zipper ->
zipper
|> Zipper.down()
|> case do
nil ->
{:ok, zipper}

zipper ->
zipper
|> Zipper.rightmost()
|> Igniter.Code.Keyword.put_in_keyword([:import_deps], [], fn nested_zipper ->
Igniter.Code.List.remove_from_list(
nested_zipper,
&Igniter.Code.Common.nodes_equal?(&1, dep)
)
end)
|> case do
{:ok, zipper} ->
zipper

:error ->
{:warning,
"""
Could not remove imported dependency #{inspect(dep)} from `.formatter.exs`.
Please remove the import manually, i.e replacing
import_deps: [:foo, #{inspect(dep)}, :bar]
with
import_deps: [:foo, :bar]
"""}
end
end
end)
end

@doc """
Adds a new plugin to the list of plugins in the root `.formatter.exs`
"""
Expand All @@ -73,8 +119,7 @@ defmodule Igniter.Project.Formatter do
[plugins: [unquote(plugin)]]
end

zipper
|> Common.add_code(code)
{:ok, Common.add_code(zipper, code)}

zipper ->
zipper
Expand All @@ -91,19 +136,68 @@ defmodule Igniter.Project.Formatter do
)
|> case do
{:ok, zipper} ->
zipper
{:ok, zipper}

_ ->
{:warning,
"""
Could not add formatter plugin #{inspect(plugin)} into `.formatter.exs`.
Please add the import manually, i.e
Please add the plugin manually, i.e
plugins: [#{inspect(plugin)}]
"""}
end
end
end)
end

@doc """
REmoves a plugin to the list of plugins in the root `.formatter.exs`
"""
@spec remove_formatter_plugin(Igniter.t(), plugin :: module()) :: Igniter.t()
def remove_formatter_plugin(igniter, plugin) do
igniter
|> Igniter.include_or_create_file(".formatter.exs", @default_formatter)
|> Igniter.update_elixir_file(".formatter.exs", fn zipper ->
zipper
|> Zipper.down()
|> case do
nil ->
{:ok, zipper}

zipper ->
zipper
|> Zipper.rightmost()
|> Igniter.Code.Keyword.put_in_keyword(
[:plugins],
[],
fn nested_zipper ->
Igniter.Code.List.remove_from_list(
nested_zipper,
&Igniter.Code.Common.nodes_equal?(&1, plugin)
)
end
)
|> case do
{:ok, zipper} ->
zipper

_ ->
{:warning,
"""
Could not remove formatter plugin #{inspect(plugin)} from `.formatter.exs`.
Please remove the plugin manually, i.e by replacing
plugins: [Foo, #{inspect(plugin)}, Bar]
with
plugins: [Foo, Bar]
"""}
end
end
end)
end
end
5 changes: 4 additions & 1 deletion lib/igniter/project/module.ex
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,10 @@ defmodule Igniter.Project.Module do
|> Zipper.node()

new_source = Rewrite.Source.update(source, :quoted, new_quoted)
{:ok, %{igniter | rewrite: Rewrite.update!(igniter.rewrite, new_source)}}

{:ok,
%{igniter | rewrite: Rewrite.update!(igniter.rewrite, new_source)}
|> Igniter.format([source.path])}

{:error, error} ->
{:ok, Igniter.add_issue(igniter, error)}
Expand Down
21 changes: 19 additions & 2 deletions lib/igniter/test.ex
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,14 @@ defmodule Igniter.Test do
def test_project(opts \\ []) do
Igniter.new()
|> Igniter.assign(:test_mode?, true)
|> Igniter.assign(:test_files, add_mix_new(opts))
|> Igniter.assign(
:test_files,
add_mix_new(opts)
)
# need them all back in the igniter
|> Igniter.include_glob("**/.formatter.exs")
|> Igniter.include_glob(".formatter.exs")
|> Igniter.include_glob("**/*.*")
|> Igniter.Project.IgniterConfig.setup()
|> apply_igniter!()
end
Expand Down Expand Up @@ -324,7 +331,13 @@ defmodule Igniter.Test do
end)
|> then(fn test_files ->
igniter
|> Map.put(:rewrite, Rewrite.new())
|> Map.put(
:rewrite,
Rewrite.new(
hooks: [Rewrite.Hook.DotFormatterUpdater],
dot_formatter: igniter.rewrite.dot_formatter
)
)
|> Map.put(:tasks, [])
|> Map.put(:warnings, [])
|> Map.put(:notices, [])
Expand All @@ -334,6 +347,10 @@ defmodule Igniter.Test do
test_files: test_files,
igniter_exs: igniter.assigns[:igniter_exs]
})
# need them all back in the igniter
|> Igniter.include_glob("**/.formatter.exs")
|> Igniter.include_glob(".formatter.exs")
|> Igniter.include_glob("**/*.*")
end)
end

Expand Down
2 changes: 1 addition & 1 deletion lib/mix/task.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ defmodule Igniter.Mix.Task do
from `c:info/2`. See `Igniter.Mix.Task.Info` for more.
"""

alias Igniter.Mix.Task.Info
alias Igniter.Mix.Task.Args
alias Igniter.Mix.Task.Info

require Logger

Expand Down
2 changes: 1 addition & 1 deletion test/igniter/code/module_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ defmodule Igniter.Code.ModuleTest do
""")
|> Igniter.create_new_file("test.txt", "Foo")

assert {_igniter, [Foo, Test, TestTest]} =
assert {_igniter, [Foo, Test, Test.MixProject, TestTest]} =
Igniter.Project.Module.find_all_matching_modules(igniter, fn _module, _zipper ->
true
end)
Expand Down

0 comments on commit cac9b66

Please sign in to comment.