Credence.Semantic.PreferExplicitRangeStep
(credence v0.8.0)
Copy Markdown
Makes the implicit step of a descending literal range explicit.
Since Elixir 1.19 a fully-literal range whose default step is -1
(first > last, e.g. 1..-2, 10..-5, 5..1) emits a deprecation warning:
1..-2 has a default step of -1, please write 1..-2//-1 insteadUnder --warnings-as-errors this blocks compilation. The fix appends //-1,
which is a no-op on behaviour: the warning states that -1 is already the
current default step, so 1..-2 and 1..-2//-1 are the identical Range
value.
Why the fix is AST-based, not text-based
The diagnostic carries no usable position — Code.with_diagnostics
reports the range-step deprecation at position 0, with no line or column —
and the message normalizes whitespace (a source range 1 .. -2 is
reported as 1..-2). A text-replacement fix keyed on the message string would
therefore (a) miss spaced ranges entirely and (b) blindly rewrite every
occurrence of that text — including the same digits sitting inside a string
literal, atom, or comment — silently changing a value. That is a behaviour
change, not a no-op.
Instead the fix parses the source and rewrites only genuine range operator
nodes ({:.., _, [lo, hi]}) whose two endpoints are integer literals (or the
unary minus of one) with lo > hi — exactly the inputs the compiler warns on,
and the only inputs for which the default step is -1. Strings, charlists,
atoms and comments carry no .. operator node, so they are never touched. A
range with a non-literal endpoint (a..-1) produces no diagnostic and matches
no node, so it is left alone.