Mutare.Gettext (mutare_gettext v0.2.0)

Copy Markdown View Source

A Mutare extension for Gettext macro expansion and argument routing. It configures the built-in mutators to mutate runtime arguments in a use Gettext module while preserving the literals required to compile the metamutant.

It produces no mutations, occupies no mutator slot, and does not appear in reports. List it under :extensions (in .mutare.exs or Mutare.run/2):

# .mutare.exs
[extensions: [Mutare.Gettext]]

What it does

The extension implements two capability behaviours (see Mutare.Extension):

  • Mutare.UseExpansion.expand_use/3 — supplies import Gettext.Macros directly for every use Gettext during Mutare's scan. Gettext (>= 0.26) compiles use Gettext, backend: MyApp.Gettext by mutating the caller module to register the backend, which raises when Mutare expands it in the scan process (the caller is already compiled), so import is not recovered and the bare gettext/ngettext calls remain unresolved. (The backend: value is a module alias, not a compile-time literal, so Mutare's requirement for static-literal options would prevent expansion regardless.) Supplying the import directly allows Mutare to resolve and route those calls.

  • Mutare.CallRouting.call_routes/0 — routes each Gettext macro's arguments. The compile-time literal positions — message id, plural id, domain, context, backend — must never be mutated: inserting a mutation selector there causes a macro expansion error and prevents compilation. The runtime positions — the ngettext plural count and the interpolation bindings — are mutated, so mutation testing can check whether tests detect changes to plural counts and interpolation values.

This is expressed as a whole-module :raw baseline ({Gettext.Macros, :*, :raw} — every argument of every macro left untouched, the safe default) plus a per-position override for each arity with a count or bindings argument, routing just those trailing positions :expression (a more specific route takes precedence; see Mutare.CallRouting). For example ngettext/4 routes [:raw, :raw, :expression, :expression] — the two message ids remain unchanged, while the count and bindings are mutated. The overrides are derived from the Gettext macro families; the test suite cross-checks every one against the Gettext.Macros exports.

Targets Gettext >= 0.26, which introduced Gettext.Macros. On older versions, the injected import Gettext.Macros refers to a module that isn't loaded. Mutare leaves unresolved calls unchanged, so the extension has no effect.