Packages
igniter
0.5.15
0.8.2
0.8.1
0.8.0
0.7.9
0.7.8
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.30
0.6.29
0.6.28
0.6.27
0.6.26
0.6.25
0.6.24
0.6.23
0.6.22
0.6.21
0.6.20
0.6.19
0.6.18
0.6.17
0.6.16
0.6.15
0.6.14
0.6.13
0.6.12
0.6.11
0.6.10
0.6.9
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.52
0.5.51
0.5.50
0.5.49
0.5.48
0.5.47
0.5.46
0.5.45
0.5.44
0.5.43
0.5.42
0.5.41
0.5.40
0.5.39
0.5.38
0.5.37
0.5.36
0.5.35
0.5.34
0.5.33
0.5.32
0.5.31
0.5.30
0.5.29
0.5.28
0.5.27
0.5.26
0.5.25
0.5.24
0.5.23
0.5.22
0.5.21
0.5.20
0.5.19
0.5.18
0.5.17
0.5.16
0.5.15
0.5.14
0.5.13
0.5.12
0.5.11
0.5.10
0.5.9
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.78
0.3.77
0.3.76
0.3.75
0.3.74
0.3.73
0.3.72
0.3.71
0.3.70
0.3.69
0.3.68
0.3.67
0.3.66
0.3.65
0.3.64
0.3.63
0.3.62
0.3.61
0.3.60
0.3.59
0.3.58
0.3.57
0.3.56
0.3.55
0.3.54
0.3.53
0.3.52
0.3.51
0.3.50
0.3.49
0.3.48
0.3.47
0.3.46
0.3.45
0.3.44
0.3.43
0.3.42
0.3.41
0.3.40
0.3.39
0.3.38
0.3.37
0.3.36
0.3.35
0.3.34
0.3.33
0.3.32
0.3.31
0.3.30
0.3.29
0.3.28
0.3.27
0.3.26
0.3.25
0.3.24
0.3.23
0.3.22
0.3.21
0.3.20
0.3.19
0.3.18
0.3.17
0.3.16
0.3.15
0.3.14
0.3.13
0.3.12
0.3.11
0.3.10
0.3.9
0.3.8
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.13
0.2.12
0.2.11
0.2.10
0.2.9
0.2.8
0.2.7
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
A code generation and project patching framework
Current section
Files
Jump to
Current section
Files
lib/igniter/code/module.ex
defmodule Igniter.Code.Module do
@moduledoc "Utilities for working with Elixir modules"
require Igniter.Code.Common
alias Igniter.Code.Common
alias Sourceror.Zipper
require Logger
@doc "The module name prefix based on the mix project's module name"
@deprecated "Use `Igniter.Project.Module.module_name_prefix/1` instead"
@spec module_name_prefix() :: module()
def module_name_prefix do
Mix.Project.get!()
|> Module.split()
|> :lists.droplast()
|> Module.concat()
end
@doc "The module name prefix based on the mix project's module name"
@spec module_name_prefix(Igniter.t()) :: module()
@deprecated "Use `Igniter.Project.Module.module_name_prefix/1` instead"
def module_name_prefix(igniter) do
Igniter.Project.Module.module_name_prefix(igniter)
end
@doc "Moves the zipper to a defmodule call"
@spec move_to_defmodule(Zipper.t()) :: {:ok, Zipper.t()} | :error
def move_to_defmodule(zipper) do
Igniter.Code.Function.move_to_function_call_in_current_scope(zipper, :defmodule, 2)
end
@doc "Moves the zipper to a specific defmodule call"
@spec move_to_defmodule(Zipper.t(), module()) :: {:ok, Zipper.t()} | :error
def move_to_defmodule(zipper, module) do
Igniter.Code.Function.move_to_function_call(
zipper,
:defmodule,
2,
fn zipper ->
case Igniter.Code.Function.move_to_nth_argument(zipper, 0) do
{:ok, zipper} ->
Igniter.Code.Common.nodes_equal?(zipper, module)
_ ->
false
end
end
)
end
@doc "Moves the zipper to the body of a module that `use`s the provided module (or one of the provided modules)."
@spec move_to_module_using(Zipper.t(), module | list(module)) :: {:ok, Zipper.t()} | :error
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
with {:ok, mod_zipper} <- move_to_defmodule(zipper),
{:ok, mod_zipper} <- Igniter.Code.Common.move_to_do_block(mod_zipper),
{:ok, _} <- move_to_use(mod_zipper, module) do
{:ok, mod_zipper}
else
_ ->
:error
end
end
@deprecated "Use `move_to_use/2` instead."
def move_to_using(zipper, module), do: move_to_use(zipper, module)
@doc "Moves the zipper to the `use` statement for a provided module."
def move_to_use(zipper, [module]), do: move_to_use(zipper, module)
def move_to_use(zipper, [module | rest]) do
case move_to_use(zipper, module) do
{:ok, zipper} -> {:ok, zipper}
_ -> move_to_use(zipper, rest)
end
end
def move_to_use(zipper, module) do
Igniter.Code.Function.move_to_function_call_in_current_scope(zipper, :use, [1, 2], fn call ->
Igniter.Code.Function.argument_matches_predicate?(
call,
0,
&Igniter.Code.Common.nodes_equal?(&1, module)
)
end)
end
@deprecated "Use `Igniter.Code.Function.move_to_defp/3` instead"
def move_to_defp(zipper, fun, arity) do
Igniter.Code.Function.move_to_defp(zipper, fun, arity)
end
@deprecated "Use `Igniter.Code.Function.move_to_def/3` instead"
def move_to_def(zipper, fun, arity) do
Igniter.Code.Function.move_to_def(zipper, fun, arity)
end
def module?(zipper) do
Common.node_matches_pattern?(zipper, {:__aliases__, _, [_ | _]})
end
@doc """
Finds a module and updates its contents wherever it is.
If the module does not yet exist, it is created with the provided contents. In that case,
the path is determined with `Igniter.Code.Module.proper_location/2`, but may optionally be overwritten with options below.
# Options
- `:path` - Path where to create the module, relative to the project root. Default: `nil` (uses `:kind` to determine the path).
"""
@deprecated "Use `Igniter.Project.Module.find_and_update_or_create_module/5` instead"
def find_and_update_or_create_module(igniter, module_name, contents, updater, opts \\ []) do
Igniter.Project.Module.find_and_update_or_create_module(
igniter,
module_name,
contents,
updater,
opts
)
end
@doc "Checks if the value is a module that matches a given predicate"
def module_matching?(zipper, pred) do
zipper =
zipper
|> Igniter.Code.Common.maybe_move_to_single_child_block()
|> Igniter.Code.Common.expand_aliases()
case zipper.node do
{:__aliases__, _, parts} ->
pred.(Module.concat(parts))
value when is_atom(value) ->
pred.(value)
_ ->
false
end
end
@doc "Creates a new file & module in its appropriate location."
@deprecated "Use `Igniter.Project.Module.create_module/4` instead"
def create_module(igniter, module_name, contents, opts \\ []) do
Igniter.Project.Module.create_module(igniter, module_name, contents, opts)
end
@doc "Checks if a module is defined somewhere in the project. The returned igniter should not be discarded."
@deprecated "Use `Igniter.Project.Module.module_exists/2` instead"
def module_exists?(igniter, module_name) do
Igniter.Project.Module.module_exists(igniter, module_name)
end
@deprecated "Use `Igniter.Project.Module.find_and_update_module!/3` instead"
def find_and_update_module!(igniter, module_name, updater) do
Igniter.Project.Module.find_and_update_module!(igniter, module_name, updater)
end
@doc "Finds a module and updates its contents. Returns `{:error, igniter}` if the module could not be found. Do not discard this igniter."
@spec find_and_update_module(Igniter.t(), module(), (Zipper.t() -> {:ok, Zipper.t()} | :error)) ::
{:ok, Igniter.t()} | {:error, Igniter.t()}
@deprecated "Use `Igniter.Project.Module.find_and_update_module/3` instead"
def find_and_update_module(igniter, module_name, updater) do
Igniter.Project.Module.find_and_update_module(igniter, module_name, updater)
end
@doc """
Finds a module, returning a new igniter, and the source and zipper location. This new igniter should not be discarded.
In general, you should not use the returned source and zipper to update the module, instead, use this to interrogate
the contents or source in some way, and then call `find_and_update_module/3` with a function to perform an update.
"""
@spec find_module(Igniter.t(), module()) ::
{:ok, {Igniter.t(), Rewrite.Source.t(), Zipper.t()}} | {:error, Igniter.t()}
@deprecated "Use `Igniter.Project.Module.find_module/2` instead"
def find_module(igniter, module_name) do
Igniter.Project.Module.find_module(igniter, module_name)
end
@doc """
Finds a module, raising an error if its not found.
See `find_module/2` for more information.
"""
@spec find_module!(Igniter.t(), module()) ::
{Igniter.t(), Rewrite.Source.t(), Zipper.t()} | no_return
@deprecated "Use `Igniter.Project.Module.find_module!/2` instead"
def find_module!(igniter, module_name) do
Igniter.Project.Module.find_module!(igniter, module_name)
end
@spec find_all_matching_modules(igniter :: Igniter.t(), (module(), Zipper.t() -> boolean)) ::
{Igniter.t(), [module()]}
@deprecated "Use `Igniter.Project.Module.find_all_matching_modules/2` instead"
def find_all_matching_modules(igniter, predicate) do
Igniter.Project.Module.find_all_matching_modules(igniter, predicate)
end
@doc "Given a suffix, returns a module name with the prefix of the current project."
@spec module_name(String.t()) :: module()
@deprecated "Use `module_name/2` instead."
def module_name(suffix) do
Module.concat(module_name_prefix(), suffix)
end
@doc "Given a suffix, returns a module name with the prefix of the current project."
@spec module_name(Igniter.t(), String.t()) :: module()
@deprecated "Use `Igniter.Project.Module.module_name/2` instead."
def module_name(igniter, suffix) do
Igniter.Project.Module.module_name(igniter, suffix)
end
@doc "Parses a string into a module name"
@deprecated "Use `Igniter.Project.Module.parse/1` instead."
@spec parse(String.t()) :: module()
def parse(module_name) do
Igniter.Project.Module.parse(module_name)
end
@doc """
Returns the idiomatic file location for a given module, starting with "lib/".
"""
@spec proper_location(module(), source_folder :: String.t()) :: Path.t()
@deprecated "Use `Igniter.Project.Module.proper_location/3`"
def proper_location(module_name, source_folder \\ "lib") do
Igniter.Project.Module.proper_location(
Igniter.new(),
module_name,
{:source_folder, source_folder}
)
end
@doc """
Returns the test file location for a given module, according to
`mix test` expectations, starting with "test/" and ending with "_test.exs".
"""
@spec proper_test_location(module()) :: Path.t()
@deprecated "Use `Igniter.Project.Module.proper_location/3`"
def proper_test_location(module_name) do
Igniter.Project.Module.proper_location(Igniter.new(), module_name, :test)
end
@doc """
Returns the test support location for a given module, starting with
"test/support/" and dropping the module name prefix in the path.
"""
@spec proper_test_support_location(module()) :: Path.t()
@deprecated "Use `Igniter.Project.Module.proper_location/3`"
def proper_test_support_location(module_name) do
Igniter.Project.Module.proper_location(
Igniter.new(),
module_name,
{:source_folder, "test/support"}
)
end
end