Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
zachdaniel committed Jun 4, 2024
1 parent f1e0fff commit 57ee3f9
Show file tree
Hide file tree
Showing 8 changed files with 359 additions and 72 deletions.
2 changes: 1 addition & 1 deletion installer/lib/mix/tasks/igniter.new.ex
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ defmodule Mix.Tasks.Igniter.New do
if options[:example] do
"--example"
end
Mix.shell().cmd("mix igniter.install #{Enum.join(install, ",")} --yes #{example}" |> IO.inspect())
Mix.shell().cmd("mix igniter.install #{Enum.join(install, ",")} --yes #{example}")
end

else
Expand Down
132 changes: 123 additions & 9 deletions lib/common.ex
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,26 @@ defmodule Igniter.Common do
value =
keywordify(rest, value)

to_append =
zipper
|> Zipper.subtree()
|> Zipper.node()
|> case do
[{{:__block__, meta, _}, {:__block__, _, _}} | _] ->
if meta[:format] do
{{:__block__, [format: meta[:format]], [key]}, {:__block__, [], [value]}}
else
{{:__block__, [], [key]}, {:__block__, [], [value]}}
end

_ ->
{key, value}
end

{:ok,
prepend_to_list(
append_to_list(
zipper,
[{key, value}]
to_append
)}

{:ok, zipper} ->
Expand All @@ -162,10 +178,26 @@ defmodule Igniter.Common do
end
end) do
:error ->
to_append =
zipper
|> Zipper.subtree()
|> Zipper.node()
|> case do
[{{:__block__, meta, _}, {:__block__, _, _}} | _] ->
if meta[:format] do
{{:__block__, [format: meta[:format]], [key]}, {:__block__, [], [value]}}
else
{{:__block__, [], [key]}, {:__block__, [], [value]}}
end

_ ->
{key, value}
end

{:ok,
prepend_to_list(
append_to_list(
zipper,
{{:__block__, [format: :keyword], [key]}, {:__block__, [], [value]}}
to_append
)}

{:ok, zipper} ->
Expand Down Expand Up @@ -216,7 +248,7 @@ defmodule Igniter.Common do
value = mappify(rest, value)

{:ok,
prepend_to_list(
append_to_list(
zipper,
{{:__block__, [format: format], [key]}, {:__block__, [], [value]}}
)}
Expand Down Expand Up @@ -261,7 +293,7 @@ defmodule Igniter.Common do
format = map_keys_format(zipper)

{:ok,
prepend_to_list(
append_to_list(
zipper,
{{:__block__, [format: format], [key]}, {:__block__, [], [value]}}
)}
Expand Down Expand Up @@ -372,7 +404,7 @@ defmodule Igniter.Common do
|> nth_right(index)
|> case do
:error ->
nil
:error

{:ok, nth} ->
{:ok, func.(nth)}
Expand All @@ -385,7 +417,7 @@ defmodule Igniter.Common do
|> Zipper.down()
|> case do
nil ->
nil
:error

zipper ->
zipper
Expand All @@ -401,6 +433,67 @@ defmodule Igniter.Common do
end
end

def move_to_nth_argument(zipper, index) do
if pipeline?(zipper) do
if index == 0 do
zipper
|> Zipper.down()
|> case do
nil ->
:error

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

zipper ->
zipper
|> Zipper.rightmost()
|> Zipper.down()
|> case do
nil ->
:error

zipper ->
zipper
|> nth_right(index)
|> case do
:error ->
:error

{:ok, nth} ->
{:ok, nth}
end
end
end
end
else
zipper
|> Zipper.down()
|> case do
nil ->
:error

zipper ->
zipper
|> nth_right(index)
|> case do
:error ->
:error

{:ok, nth} ->
{:ok, nth}
end
end
end
end

def argument_matches_predicate?(zipper, index, func) do
if pipeline?(zipper) do
if index == 0 do
Expand Down Expand Up @@ -478,6 +571,21 @@ defmodule Igniter.Common do
end

# sobelow_skip ["DOS.StringToAtom"]
def move_to_module_using(zipper, [module]) do
move_to_module_using(zipper, module)
end

def move_to_module_using(zipper, [module | rest] = one_of_modules)
when is_list(one_of_modules) do
case move_to_module_using(zipper, module) do
{:ok, zipper} ->
{:ok, zipper}

:error ->
move_to_module_using(zipper, rest)
end
end

def move_to_module_using(zipper, module) do
split_module =
module
Expand Down Expand Up @@ -617,6 +725,12 @@ defmodule Igniter.Common do
|> Zipper.insert_child(quoted)
end

def append_to_list(zipper, quoted) do
zipper
|> maybe_move_to_block()
|> Zipper.append_child(quoted)
end

def remove_index(zipper, index) do
zipper
|> maybe_move_to_block()
Expand Down Expand Up @@ -760,7 +874,7 @@ defmodule Igniter.Common do
end

def keywordify([key | rest], value) do
[{key, keywordify(rest, value)}]
[{{:__block__, [format: :keyword], [key]}, {:__block__, [], [keywordify(rest, value)]}}]
end

@doc false
Expand Down
45 changes: 25 additions & 20 deletions lib/deps.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,36 @@ defmodule Igniter.Deps do
alias Igniter.Common
alias Sourceror.Zipper

def add_dependency(igniter, name, version) do
case get_dependency_declaration(igniter, name) do
nil ->
do_add_dependency(igniter, name, version)

current ->
desired = "`{#{inspect(name)}, #{inspect(version)}}`"
current = "`#{current}`"
def add_dependency(igniter, name, version, yes? \\ false) do
if name in List.wrap(igniter.assigns[:manually_installed]) do
igniter
else
case get_dependency_declaration(igniter, name) do
nil ->
do_add_dependency(igniter, name, version)

if desired == current do
igniter
else
if Mix.shell().yes?("""
Dependency #{name} is already in mix.exs. Should we replace it?
current ->
desired = "`{#{inspect(name)}, #{inspect(version)}}`"
current = "`#{current}`"

Desired: #{desired}
Found: #{current}
""") do
if desired == current do
igniter
|> remove_dependency(name)
|> do_add_dependency(name, version)
else
igniter
if yes? ||
Mix.shell().yes?("""
Dependency #{name} is already in mix.exs. Should we replace it?
Desired: #{desired}
Found: #{current}
""") do
igniter
|> remove_dependency(name)
|> do_add_dependency(name, version)
else
igniter
end
end
end
end
end
end

Expand Down
74 changes: 70 additions & 4 deletions lib/igniter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,61 @@ defmodule Igniter do
Igniter is a library for installing packages and generating code.
"""

defstruct [:rewrite, issues: [], tasks: []]
defstruct [:rewrite, issues: [], tasks: [], warnings: [], assigns: %{}]

@type t :: %__MODULE__{
rewrite: Rewrite.t(),
issues: [String.t()],
tasks: [{String.t() | list(String.t())}]
tasks: [{String.t() | list(String.t())}],
warnings: [String.t()],
assigns: map()
}

def new do
%__MODULE__{rewrite: Rewrite.new()}
end

def assign(igniter, key, value) do
%{igniter | assigns: Map.put(igniter.assigns, key, value)}
end

def assign(igniter, key_vals) do
Enum.reduce(key_vals, igniter, fn {key, value}, igniter ->
assign(igniter, key, value)
end)
end

def update_glob(igniter, glob, func) do
igniter =
glob
|> Path.wildcard()
|> Enum.reduce(igniter, fn path, igniter ->
if Path.extname(path) != ".ex" do
raise ArgumentError, "Expected a .ex file, got #{inspect(path)}"
end

Igniter.include_existing_elixir_file(igniter, path)
end)

Enum.reduce(igniter.rewrite, igniter, fn source, igniter ->

Check warning on line 42 in lib/igniter.ex

View workflow job for this annotation

GitHub Actions / ash-ci / mix dialyzer

no_return

The created anonymous function has no local return.
path = Rewrite.Source.get(source, :path)

if GlobEx.match?(glob, path) do

Check warning on line 45 in lib/igniter.ex

View workflow job for this annotation

GitHub Actions / ash-ci / mix dialyzer

call

The function call match? will not succeed.
update_elixir_file(igniter, path, func)
else
igniter
end
end)
end

def add_issue(igniter, issue) do
%{igniter | issues: [issue | igniter.issues]}
end

def add_warning(igniter, warning) do
%{igniter | issues: [warning | igniter.warnings]}
end

def add_task(igniter, task, argv \\ []) when is_binary(task) do
%{igniter | tasks: igniter.tasks ++ [{task, argv}]}
end
Expand Down Expand Up @@ -334,12 +373,18 @@ defmodule Igniter do
else
igniter =
"**/.formatter.exs"
|> Path.relative_to(File.cwd!())
|> Path.wildcard()
|> Enum.reduce(igniter, fn path, igniter ->
Igniter.include_existing_elixir_file(igniter, path)
end)

igniter =
if File.exists?(".formatter.exs") do
Igniter.include_existing_elixir_file(igniter, ".formatter.exs")
else
igniter
end

rewrite = igniter.rewrite

formatter_exs_files =
Expand Down Expand Up @@ -371,7 +416,10 @@ defmodule Igniter do
source

{:ok, opts} ->
formatted = Rewrite.Source.Ex.format(source, opts)
formatted =
with_evaled_configs(rewrite, fn ->
Rewrite.Source.Ex.format(source, opts)
end)

source
|> Rewrite.Source.Ex.put_formatter_opts(opts)
Expand All @@ -386,6 +434,24 @@ defmodule Igniter do
end
end

# for now we only eval `config.exs`
defp with_evaled_configs(rewrite, fun) do
case Rewrite.source(rewrite, "config/config.exs") do
{:ok, source} ->
content = Rewrite.Source.get(source, :content)

"config/config.exs"
|> Config.Reader.eval!(content)
|> Application.put_all_env()

# okay so right now we don't actually reset the config, mostly because I'm not sure it ever actually matters?
fun.()

_ ->
fun.()
end
end

# sobelow_skip ["RCE.CodeModule"]
defp find_formatter_exs_file_options(path, formatter_exs_files) do
case Map.fetch(formatter_exs_files, path) do
Expand Down
Loading

0 comments on commit 57ee3f9

Please sign in to comment.