Credence.Pattern.NoCodepointStringReverse (credence v0.7.1)

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)