# `Mutare.CallRouting.Call`
[🔗](https://github.com/foxbenjaminfox/mutare/blob/v0.5.1/lib/mutare/call_routing/call.ex#L1)

Stable, resolved view of a known-macro call passed to routing and hosting callbacks.

`arguments` are the call's arguments, all of them, however the call was written: Mutare
treats a piped routed call as the direct call `Kernel.|>/2` would build, so
`(p in Post) |> from(order_by: …)` is shown as `from(p in Post, order_by: …)`. A classifier
routes the piped operand as the first argument it is, and a host or mutator can read and
rewrite it like any other. `rebuild.(name, arguments)` preserves the source's bare,
qualified, or aliased call form; reports still show the pipe the user wrote.

At classification, arguments retain their written syntax. After routing, hosts see Elixir
arguments resolved and `:raw`/`:hosted` fragments preserved, including their pipe operators.

A module named in an argument is written as the call site's aliases make it (`Post` for
`MyApp.Post` under `alias MyApp.Post`), or through `__MODULE__` (`__MODULE__`,
`__MODULE__.Comment`). Arguments are not resolved at classification, so `resolved_module/2`
reads such a name through the aliases and the module in force at the call site. It answers
for the call handed to `c:Mutare.CallRouting.route_arguments/1`; a call obtained any other
way carries neither, and resolves only an `Elixir.`-qualified name.

The struct is produced by Mutare. Extension callbacks should match only the fields they need so
additional fields can be added compatibly. `alias_env` and `enclosing_module` are internal,
read only through `resolved_module/2`. To build one in a test, use `new/4` or `new/5`.

# `t`

```elixir
@type t() :: %Mutare.CallRouting.Call{
  alias_env: map() | nil,
  arguments: [Macro.t()],
  enclosing_module: module() | nil,
  module: module() | atom() | nil,
  name: atom(),
  node: Macro.t(),
  rebuild: (atom(), [Macro.t()] -&gt; Macro.t())
}
```

# `new`

```elixir
@spec new(Macro.t(), module() | atom() | nil, atom(), (atom(), [Macro.t()] -&gt;
                                                   Macro.t())) :: t()
```

Build a call value from the written call `node`, the resolved `module` and `name`, and the
`rebuild` function. `arguments` are read off `node`, so the two always agree.

    iex> node = quote(do: where(Post, x > 1))
    iex> call = Mutare.CallRouting.Call.new(node, Ecto.Query, :where,
    ...>   fn name, args -> {name, [], args} end)
    iex> length(call.arguments)
    2

# `new`

```elixir
@spec new(
  Macro.t(),
  module() | atom() | nil,
  atom(),
  (atom(), [Macro.t()] -&gt; Macro.t()),
  aliases: %{required(atom()) =&gt; module()},
  enclosing_module: module() | nil
) :: t()
```

`new/4`, with what is in force at the call site, for `resolved_module/2` to read:

  * `aliases: %{Short => Module}` — the aliases, the way an `alias Module, as: Short` would
    bind them;
  * `enclosing_module: Module` — the module the call is written in, which `__MODULE__` names;
    `nil` for a file's top level.

Either may be left out; a call without it resolves no name that needs it.

    iex> node = quote(do: where(Post, x > 1))
    iex> call = Mutare.CallRouting.Call.new(node, Ecto.Query, :where,
    ...>   fn name, args -> {name, [], args} end, aliases: %{Post: MyApp.Post})
    iex> Mutare.CallRouting.Call.resolved_module(call, hd(call.arguments))
    {:ok, MyApp.Post}

# `resolved_module`

```elixir
@spec resolved_module(t(), Macro.t()) :: {:ok, module()} | :error
```

The module a node in the call's arguments names, read through the aliases and the module in
force at the call site: `{:ok, module}`, or `:error` for a node that is not a module name, or
that needs something the call does not carry (see the moduledoc). An `Elixir.`-qualified name
ignores aliases, as the compiler does, and so resolves either way. `__MODULE__` is the module
the call is written in, and `__MODULE__.Comment` a name beneath it, as the compiler reads
them: at a file's top level `__MODULE__` is `:error` and `__MODULE__.Comment` is `Comment`,
and in a module whose name is computed (`defmodule Module.concat(…)`) both are `:error`.
Whether the module exists is not checked.

    iex> node = quote(do: from(p in Post))
    iex> call = Mutare.CallRouting.Call.new(node, Ecto.Query, :from,
    ...>   fn name, args -> {name, [], args} end, aliases: %{Post: MyApp.Post})
    iex> {:in, _, [_binding, source]} = hd(call.arguments)
    iex> Mutare.CallRouting.Call.resolved_module(call, source)
    {:ok, MyApp.Post}
    iex> Mutare.CallRouting.Call.resolved_module(call, quote(do: Post.Comment))
    {:ok, MyApp.Post.Comment}
    iex> Mutare.CallRouting.Call.resolved_module(call, quote(do: p))
    :error

`__MODULE__` reads the module the call is written in:

    iex> node = quote(do: from(p in __MODULE__))
    iex> call = Mutare.CallRouting.Call.new(node, Ecto.Query, :from,
    ...>   fn name, args -> {name, [], args} end, enclosing_module: MyApp.Post)
    iex> {:in, _, [_binding, source]} = hd(call.arguments)
    iex> Mutare.CallRouting.Call.resolved_module(call, source)
    {:ok, MyApp.Post}
    iex> Mutare.CallRouting.Call.resolved_module(call, quote(do: __MODULE__.Comment))
    {:ok, MyApp.Post.Comment}
    iex> unplaced = Mutare.CallRouting.Call.new(node, Ecto.Query, :from,
    ...>   fn name, args -> {name, [], args} end)
    iex> Mutare.CallRouting.Call.resolved_module(unplaced, source)
    :error

---

*Consult [api-reference.md](api-reference.md) for complete listing*
