Current section
Files
Jump to
Current section
Files
lib/swap.ex
defmodule Swap do
defmacro __using__(_opts) do
quote do
import unquote(__MODULE__)
end
end
defmacro swap(swapped_module, delegate_module, opts \\ [])
defmacro swap(swapped_module, delegate_module, do: block) do
quote do
swap(unquote(swapped_module), unquote(delegate_module), [])
result = unquote(block)
revert(unquote(swapped_module))
result
end
end
defmacro swap(swapped_module, delegate_module, opts) do
quote bind_quoted: [swapped_module: swapped_module, delegate_module: delegate_module, opts: opts] do
Code.compiler_options(ignore_module_conflict: true)
if is_nil(opts[:when]) || opts[:when] == true do
swapped_module_functions = swapped_module.__info__(:functions)
delegate_module_functions = delegate_module.__info__(:functions)
defmodule swapped_module do
for {s_m_func_name, arity} <- swapped_module_functions do
args = Macro.generate_arguments(arity, swapped_module)
if delegate_module_functions[s_m_func_name] == arity do
defdelegate unquote(s_m_func_name)(unquote_splicing(args)), to: delegate_module
else
def unquote(s_m_func_name)(unquote_splicing(args)) do
raise("#{unquote(s_m_func_name)}/#{unquote(arity)} is not defined in #{unquote(delegate_module)}")
end
end
end
end
end
end
end
defmacro revert(swapped_module) do
quote do
result =
unquote(swapped_module).module_info[:compile][:source]
|> to_string()
|> Code.load_file()
Code.compiler_options(ignore_module_conflict: false)
result
end
end
end