A replacement AST node with optional report metadata.
Mutators normally return a bare replacement node. Return a Mutation when the replacement also needs either of these fields:
note— text shown with a surviving mutant. It does not suppress the mutant or change its score.variant— one or more labels used by# mutare:ignore[family:label]. A mutator may attach the label here or derive it withMutare.Mutator.variant/2.producer— theMutare.Mutator.Specthis mutation is recorded under instead of the mutator that returned it. Set it only when relaying a mutation another family reasoned about — the selector-host sub-contract case, whereMutare.Mutator.MacroHost.host/2returns interior mutants collected from core's families viaMutare.Analyze.expression_mutations/3: the site (and its# mutare:ignorevocabulary) then belongs to the producing family, not the host.nil(the default) records the mutation under the returning mutator, exactly as before.attribution— decouples where the mutant is reported from what is spliced into the metamutant. Set it when:nodeis a whole-node rewrite whose textual footprint is one inner clause — amutate/2that rebuilds and returns an entirefrom(...)query but only changed itsorder_by:. Without it the site's line/column and before/after diff are pinned to the offered node (the wholefrom), so a multi-line rewrite reports every mutant at thefromline and# mutare:ignore(line-keyed) cannot target the clause. Build one withat/2(a replacement clause) orat_drop/1(a removed clause); the metamutant is still built by splicing:node, attribution only moves the report.nil(the default) attributes to the offered node, exactly as before.
Mutation values are accepted by Mutare.Mutator.mutate/1, Mutare.Mutator.mutate/2, and Mutare.Mutator.MacroHost.host/2. Use this struct rather than a plain map, because a map is also a valid replacement AST node.
Summary
Types
A produced mutation's variant label(s): nil, one label, or a list (see Mutare.Mutator.variant/2).
Functions
Builds a report-location override that shows original replaced by mutated.
Builds a report-location override that shows original removed.
Builds a mutation for replacement node.
Builds a mutation with one or more ignore-variant labels.
Types
@type t() :: %Mutare.Mutator.Mutation{ attribution: Mutare.Mutator.Mutation.Attribution.t() | nil, node: Macro.t(), note: String.t() | nil, producer: Mutare.Mutator.Spec.t() | nil, variant: variant() }
A produced mutation's variant label(s): nil, one label, or a list (see Mutare.Mutator.variant/2).
Functions
@spec at(Macro.t(), Macro.t()) :: Mutare.Mutator.Mutation.Attribution.t()
Builds a report-location override that shows original replaced by mutated.
Pass the result as a mutation's :attribution (see the moduledoc). original and mutated
are the clause before and after the change — the site is located at original's range
and its diff renders original → mutated, even though the mutation's :node splices a larger
rewrite into the metamutant.
Examples
iex> alias Mutare.Mutator.Mutation
iex> %Mutation.Attribution{mutated: :desc} = Mutation.at(:asc, :desc)
@spec at_drop(Macro.t()) :: Mutare.Mutator.Mutation.Attribution.t()
Builds a report-location override that shows original removed.
Pass the result as a mutation's :attribution (see the moduledoc). The site is located at
original's range and recorded as a deletion (a delete-style diff over the clause), even though
the mutation's :node splices the rewritten, clause-less node into the metamutant.
Examples
iex> alias Mutare.Mutator.Mutation
iex> Mutation.at_drop(:some_clause).mutated
:drop
Builds a mutation for replacement node.
The second argument may be a note string or a keyword list containing :note,
:variant, :producer, and :attribution:
Mutation.new(mutated)
Mutation.new(mutated, "kill needs boundary data")
Mutation.new(mutated, note: "kill needs boundary data", variant: "zero")
Mutation.new(mutated, variant: "zero")
Mutation.new(mutated, producer: literal_spec)
Mutation.new(rebuilt_from, attribution: Mutation.at(order_by, flipped_order_by))note must be a string or nil. variant may be one label, a list of labels,
or nil. producer must be a Mutare.Mutator.Spec or nil (see the moduledoc).
attribution must be a Mutare.Mutator.Mutation.Attribution (from at/2/at_drop/1)
or nil. Unknown options raise ArgumentError.
Examples
iex> alias Mutare.Mutator.Mutation
iex> mutation = Mutation.new(:replacement, note: "needs a boundary test", variant: "zero")
iex> {mutation.node, mutation.note, mutation.variant}
{:replacement, "needs a boundary test", "zero"}
iex> alias Mutare.Mutator.Mutation
iex> Mutation.new(:replacement, "shown for survivors").note
"shown for survivors"
Builds a mutation with one or more ignore-variant labels.
This is equivalent to new(node, variant: variant).
Examples
iex> alias Mutare.Mutator.Mutation
iex> Mutation.tagged(:replacement, ["pred", "zero"]).variant
["pred", "zero"]