Credence.Pattern.NoCodepointStringReverse
(credence v0.7.0)
Copy Markdown
Readability & performance rule: Detects
String.codepoints(s) |> Enum.reverse() |> IO.iodata_to_binary() (and the
Enum.join/0 reassemble variant, and the nested call forms) which is a manual
reimplementation of String.reverse/1.
Safety: behind a switch
Reversing a list of codepoints and gluing it back is not the same as
String.reverse/1 when a grapheme spans more than one codepoint — a decomposed
accent, a ZWJ emoji, or a flag sequence would be torn apart. So this rule needs
the single_codepoint_graphemes promise (see Credence.Assumptions): while it
is on, every grapheme is a single codepoint, the codepoint list equals the
grapheme list, and the rewrite is identical to the original. In :strict mode
the rule does not run.
This is the String.codepoints/1 half of the split described in the safety
plan (decision 4/12); the always-safe String.graphemes/1 half lives in
Credence.Pattern.NoManualStringReverse.
Bad (only rewritten while single_codepoint_graphemes is on)
reversed = str |> String.codepoints() |> Enum.reverse() |> IO.iodata_to_binary()
reversed = str |> String.codepoints() |> Enum.reverse() |> Enum.join()
reversed = IO.iodata_to_binary(Enum.reverse(String.codepoints(str)))Good
reversed = String.reverse(str)