# `Lockstep.Rewriter`
[🔗](https://github.com/b-erdem/lockstep/blob/v0.1.0/lib/lockstep/rewriter.ex#L1)

Compile-time AST rewriter that converts vanilla OTP calls into their
`Lockstep.*` equivalents inside a `ctest` body. Lets test bodies
read like ordinary Elixir without sacrificing controlled scheduling.

Enabled with `use Lockstep.Test, rewrite: true`. With `rewrite: true`
the linter is also disabled (since the rewritten body is correct by
construction).

## Mappings

    vanilla                          rewritten
    -------                          ---------
    GenServer.call(s, m)             Lockstep.GenServer.call(s, m)
    GenServer.cast(s, m)             Lockstep.GenServer.cast(s, m)
    GenServer.start_link(M, A)       Lockstep.GenServer.start_link(M, A)
    Task.async(fn -> ... end)        Lockstep.Task.async(fn -> ... end)
    Task.await(t)                    Lockstep.Task.await(t)
    Task.await_many(ts)              Lockstep.Task.await_many(ts)
    spawn(fun)                       Lockstep.spawn(fun)
    spawn_link(fun)                  Lockstep.spawn_link(fun)
    send(p, m)                       Lockstep.send(p, m)
    Kernel.send(p, m)                Lockstep.send(p, m)
    :erlang.send(p, m)               Lockstep.send(p, m)
    Process.send_after(p, m, ms)     Lockstep.send_after(p, m, ms)
    Process.cancel_timer(ref)        Lockstep.cancel_timer(ref)
    Process.monitor(p)               Lockstep.monitor(p)
    Process.demonitor(ref[, opts])   Lockstep.demonitor(ref[, opts])
    Process.alive?(p)                Lockstep.alive?(p)
    Process.sleep(ms)                Lockstep.sleep(ms)
    Process.link(p)                  Lockstep.link(p)
    Process.unlink(p)                Lockstep.unlink(p)
    Process.flag(:trap_exit, b)      Lockstep.flag(:trap_exit, b)
    receive do clauses end           rewritten to Lockstep.recv_first/1

## Limitations

  * Only the *body* of `ctest` is rewritten, not helper functions
    defined elsewhere. Inline race code into the test body, or call
    Lockstep wrappers directly in helpers.
  * `receive ... after t -> ... end` (bare receive with timeout) is
    not yet rewritten -- bare receives without `after` are.
  * `:erlang.spawn/3` (the 3-arg MFA form) is not rewritten.

Functions defined locally that happen to be named `send/2` etc.
will be rewritten too. Suppress by qualifying the call (e.g.
`MyMod.send(...)` is left alone).

# `rewrite`

Walk `ast` and return the rewritten AST.

---

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