# credence v0.8.0 - Table of Contents

An Elixir semantic linter that detects performance issues and non-idiomatic code via AST analysis.

## Modules

- [Credence](Credence.md): Credence — Semantic Linter for Elixir.
- [Credence.Assumptions](Credence.Assumptions.md): Safety switches — the promises Credence is allowed to make about your data.
- [Credence.Corpus](Credence.Corpus.md): Real-world corpus of popular hex packages **and beefy application repos**, used
by the over-firing test layer (`test/corpus/over_firing_test.exs`) and the
`mix credence.corpus` / `mix credence.corpus.fetch` maintainer tasks.
- [Credence.Corpus.Findings](Credence.Corpus.Findings.md): Resolves every Pattern finding on a corpus package to a stable identity, used
for snapshot-based over-fire *regression* testing.
- [Credence.Corpus.Progress](Credence.Corpus.Progress.md): Lightweight, parallel-safe progress counters for the corpus test layers.
- [Credence.FunctionMatcher](Credence.FunctionMatcher.md): Finds the closest matching defined function for an undefined function call.
- [Credence.Issue](Credence.Issue.md): Defines the structured issue format for any rule violations.

- [Credence.Pattern](Credence.Pattern.md): Pattern phase — detects and fixes anti-patterns in Elixir code.
- [Credence.Pattern.AvoidGraphemesEnumCount](Credence.Pattern.AvoidGraphemesEnumCount.md): Performance rule: Detects `Enum.count/1` on the result of
`String.graphemes/1` (without a predicate).
- [Credence.Pattern.AvoidGraphemesEnumCountWithPredicate](Credence.Pattern.AvoidGraphemesEnumCountWithPredicate.md): Performance rule: Detects `Enum.count/2` with an equality predicate or
`Enum.sum_by/2` with a counting function on the result of `String.graphemes/1`.
- [Credence.Pattern.AvoidGraphemesLength](Credence.Pattern.AvoidGraphemesLength.md): Performance rule: Detects the use of `length/1` on the result of
`String.graphemes/1`.
- [Credence.Pattern.AvoidLengthGuardLessThan2](Credence.Pattern.AvoidLengthGuardLessThan2.md): Performance rule: Detects function guards that check `length(x) < 2` (or
`length(x) <= 1`) and rewrites them into two O(1) pattern-matched clauses.
- [Credence.Pattern.HallucinatedGuard](Credence.Pattern.HallucinatedGuard.md): Fixes calls to guard functions that don't exist in Elixir.
- [Credence.Pattern.NoAnonFnApplicationInPipe](Credence.Pattern.NoAnonFnApplicationInPipe.md): Readability rule: Detects anonymous functions applied with `.()` inside
a pipeline.
- [Credence.Pattern.NoBareValueInMapNew](Credence.Pattern.NoBareValueInMapNew.md): Repairs `Map.new/2` whose mapper returns a bare (non-`{key, value}`) value.
- [Credence.Pattern.NoCaptureFnApply](Credence.Pattern.NoCaptureFnApply.md): Detects capture expressions that are immediately applied with `.()`.
- [Credence.Pattern.NoCaseBooleanResult](Credence.Pattern.NoCaseBooleanResult.md): Detects a two-clause `case` that converts a value to a boolean by matching
a specific pattern against a trailing wildcard, and rewrites it to `match?/2`.
- [Credence.Pattern.NoCaseDestructureInPipe](Credence.Pattern.NoCaseDestructureInPipe.md): Readability rule: Detects a single-clause `case` used inside a pipeline
whose clause head is an **irrefutable** variable pattern (a bare variable
or `_`, with no guard). That shape is exactly equivalent to `then/1` and
is non-idiomatic.
- [Credence.Pattern.NoCaseOnParamDispatch](Credence.Pattern.NoCaseOnParamDispatch.md): Detects a single-parameter function clause whose entire body is a `case`
that dispatches on that parameter, and rewrites it into multi-clause
function heads — the idiomatic Elixir way to express this.
- [Credence.Pattern.NoCaseTrueFalse](Credence.Pattern.NoCaseTrueFalse.md): Detects `case expr do true -> …; false -> … end` that should be `if/else`.
- [Credence.Pattern.NoCaseTupleGuardDispatch](Credence.Pattern.NoCaseTupleGuardDispatch.md): Detects `case` on a tuple of variables where every clause's pattern
is the same tuple of the same variables — all dispatch is via guards.
This is a `cond` in disguise.
- [Credence.Pattern.NoChunkByIdentityForDedup](Credence.Pattern.NoChunkByIdentityForDedup.md): Detects `Enum.chunk_by(enum, identity_fn)` followed by extracting the
first element of each chunk, which is a verbose reimplementation of
`Enum.dedup/1`.
- [Credence.Pattern.NoCodepointStringReverse](Credence.Pattern.NoCodepointStringReverse.md): 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`.
- [Credence.Pattern.NoCondTwoClauses](Credence.Pattern.NoCondTwoClauses.md): Detects `cond` with exactly two clauses where the second guard is
redundant — either literal `true` or the logical complement of the
first guard. Both patterns are just an `if/else` in disguise.
- [Credence.Pattern.NoDeadMapUpdate](Credence.Pattern.NoDeadMapUpdate.md): Detects a *no-op* `Map.update(key, literal, & &1) |> Map.drop([key])` (and the
`Map.delete`/direct-call variants) where the updated value is immediately
thrown away by dropping the same key.
- [Credence.Pattern.NoDestructureReconstruct](Credence.Pattern.NoDestructureReconstruct.md): Detects patterns where a list is destructured into individual variables
and then immediately reassembled into the same list.
- [Credence.Pattern.NoDocFalseOnPrivate](Credence.Pattern.NoDocFalseOnPrivate.md): Style rule: Detects any `@doc` annotation placed before private functions (`defp`).
- [Credence.Pattern.NoDoubleFilter](Credence.Pattern.NoDoubleFilter.md): Detects two **adjacent** `Enum.filter/2` calls on the **same** variable
whose predicates are exact logical complements, which can be replaced
with a single `Enum.split_with/2` pass.
- [Credence.Pattern.NoDoubleSortSameList](Credence.Pattern.NoDoubleSortSameList.md): Performance rule: Detects sorting the same list twice — once ascending and
once descending — when a single sort plus `Enum.reverse/1` would suffice.
- [Credence.Pattern.NoDuplicateFunctionClauses](Credence.Pattern.NoDuplicateFunctionClauses.md): Detects duplicate function clauses with identical argument patterns.
- [Credence.Pattern.NoDuplicateSpec](Credence.Pattern.NoDuplicateSpec.md): Detects duplicate `@spec` annotations before function clauses.
- [Credence.Pattern.NoEagerWithIndexInReduce](Credence.Pattern.NoEagerWithIndexInReduce.md): Performance rule: Detects `Enum.with_index/1` passed directly as the
enumerable argument to `Enum.reduce/3` (or piped into it).
- [Credence.Pattern.NoEmptyMapNew](Credence.Pattern.NoEmptyMapNew.md): Detects `Map.new()` called with no arguments and suggests the empty map
literal `%{}` instead.
- [Credence.Pattern.NoEnumCountForLength](Credence.Pattern.NoEnumCountForLength.md): Detects `Enum.count/1` (without a predicate) on a **provably-list** argument
and rewrites it to `length/1`.
- [Credence.Pattern.NoEnumIntoEmptyMapset](Credence.Pattern.NoEnumIntoEmptyMapset.md): Detects `Enum.into/2` and `Enum.into/3` targeting an empty `MapSet.new()`
and suggests `MapSet.new/1` or `MapSet.new/2` instead.
- [Credence.Pattern.NoEnumTakeNegative](Credence.Pattern.NoEnumTakeNegative.md): Performance rule: Detects `Enum.take(list, -n)` where `n` is a positive
integer literal.
- [Credence.Pattern.NoExplicitProductReduce](Credence.Pattern.NoExplicitProductReduce.md): Flags explicit product-reduction patterns inside Enum.reduce/3.
- [Credence.Pattern.NoExplicitSumReduce](Credence.Pattern.NoExplicitSumReduce.md): Flags explicit sum-reduction patterns inside Enum.reduce/3.
- [Credence.Pattern.NoFetchThenUpdate](Credence.Pattern.NoFetchThenUpdate.md): Detects `Map.update!/3` or `Map.update/4` called inside a
`case Map.fetch/2` `{:ok, val}` branch on the same map and key, and
rewrites the redundant update into a `Map.put/3`.
- [Credence.Pattern.NoFilterThenCount](Credence.Pattern.NoFilterThenCount.md): Detects `Enum.filter/2` piped into `length/1` or `Enum.count/1`, which
creates an unnecessary intermediate list.
- [Credence.Pattern.NoFilterThenFirst](Credence.Pattern.NoFilterThenFirst.md): Performance rule (fixable): Detects `Stream.filter/2` piped into `Enum.at/2`
with a literal `0` index.
- [Credence.Pattern.NoFindValueDefaultCase](Credence.Pattern.NoFindValueDefaultCase.md): Detects `Enum.find_value/2` where the result is immediately checked
against `nil` to provide a default, instead of using the 3-arity
version that accepts a default argument.
- [Credence.Pattern.NoGraphemePalindrome](Credence.Pattern.NoGraphemePalindrome.md): Readability & performance rule: Detects the pattern of decomposing a string
into graphemes, only to compare it with its own `Enum.reverse`.
- [Credence.Pattern.NoGroupByForFrequencies](Credence.Pattern.NoGroupByForFrequencies.md): Detects `Enum.group_by(enum, key_fn) |> Map.new(fn {k, group} -> {k, length(group)} end)`
which counts occurrences by key — exactly what `Enum.frequencies_by/2` does, but with
unnecessary intermediate per-group lists.
- [Credence.Pattern.NoGuardEqualityForPatternMatch](Credence.Pattern.NoGuardEqualityForPatternMatch.md): Readability rule: Detects guard clauses that compare a parameter to a
literal value with `==` when pattern matching in the function head would
be clearer and more idiomatic.
- [Credence.Pattern.NoHdTlWhenConsBound](Credence.Pattern.NoHdTlWhenConsBound.md): Detects `hd(var)` / `tl(var)` calls in a function body where `var` is
already bound to a non-empty list by an **anonymous** cons pattern
(`var = [_ | _]` or `[_ | _] = var`) in the function clause head, and
rewrites them to destructure `[head | tail]` in the head, using `head` /
`tail` directly instead of `Kernel.hd/1` / `Kernel.tl/1`.
- [Credence.Pattern.NoIdentityEnumMap](Credence.Pattern.NoIdentityEnumMap.md): Detects `Enum.map/2` called with an identity function callback, which is just
a verbose `Enum.to_list/1`.
- [Credence.Pattern.NoIdentityFunctionInEnum](Credence.Pattern.NoIdentityFunctionInEnum.md): Detects `Enum._by` functions called with an identity function callback,
which can be simplified to the non-`_by` variant.
- [Credence.Pattern.NoIfEmptyForEnumMinMax](Credence.Pattern.NoIfEmptyForEnumMinMax.md): Flags `if Enum.empty?(var), do: default, else: Enum.min(var)` (and `Enum.max`),
and the negated form `if !Enum.empty?(var), do: Enum.min(var), else: default`
(also `not Enum.empty?(var)`).
- [Credence.Pattern.NoIfTrueFalse](Credence.Pattern.NoIfTrueFalse.md): Detects redundant `if/else` wrappers around boolean expressions.
- [Credence.Pattern.NoIsNilGuard](Credence.Pattern.NoIsNilGuard.md): Detects `is_nil(param)` in function guards that can be replaced with
pattern matching `nil` directly in the function head.
- [Credence.Pattern.NoKernelOpInPipeline](Credence.Pattern.NoKernelOpInPipeline.md): Detects qualified `Kernel.op/2` calls used as steps in a pipeline.
- [Credence.Pattern.NoKeywordGetIntegerKey](Credence.Pattern.NoKeywordGetIntegerKey.md): Detects `Keyword.get(list, integer)` where the key is an integer literal.
- [Credence.Pattern.NoLengthBasedIndexing](Credence.Pattern.NoLengthBasedIndexing.md): Detects `n = length(list)` followed by `Enum.at(list, n - K)` — a Python
`list[len(list) - 1]` idiom. Elixir's `Enum.at/2` natively supports
negative indices, so `Enum.at(list, -1)` is the idiomatic equivalent.
- [Credence.Pattern.NoLengthComparisonForEmpty](Credence.Pattern.NoLengthComparisonForEmpty.md): Detects `length(list)` comparisons with small integers (0–5) that can be
replaced with O(1) pattern matching.
- [Credence.Pattern.NoLengthGuardToPattern](Credence.Pattern.NoLengthGuardToPattern.md): Refactoring rule: Detects guards that check list length with a literal
comparison that can be replaced by a pattern match in the function head.
- [Credence.Pattern.NoListAppendInRecursion](Credence.Pattern.NoListAppendInRecursion.md): Performance rule: Detects `acc ++ [expr]` passed directly in a recursive
tail call, where a matching base case returns the accumulator.
- [Credence.Pattern.NoListAppendInReduce](Credence.Pattern.NoListAppendInReduce.md): Performance rule: Detects `acc ++ [expr]` as the return value inside
`Enum.reduce/3` when the initial accumulator is `[]`.
- [Credence.Pattern.NoListConcatWithRecursiveResult](Credence.Pattern.NoListConcatWithRecursiveResult.md): Detects a **list-literal prefix** concatenated onto a recursive call with
`++` in the return expression of a recursive function, and rewrites the
`++` to a cons
- [Credence.Pattern.NoListDeleteAtLength](Credence.Pattern.NoListDeleteAtLength.md): Detects `List.delete_at(list, length(list) - 1)` — computing the length
of a list just to index its last element for deletion.
- [Credence.Pattern.NoListDeleteAtWithLength](Credence.Pattern.NoListDeleteAtWithLength.md): Detects `List.delete_at(list, length(list) - 1)` where `length/1` is
computed inline only to build the *last* index for `List.delete_at/2`,
and rewrites it to the native negative index `List.delete_at(list, -1)`.
- [Credence.Pattern.NoListDuplicateFlatten](Credence.Pattern.NoListDuplicateFlatten.md): Detects `Enum.concat(List.duplicate(list, n))` (or the piped
`list |> List.duplicate(n) |> Enum.concat()`) and suggests
`Enum.flat_map/2` instead.
- [Credence.Pattern.NoListDuplicateJoin](Credence.Pattern.NoListDuplicateJoin.md): Detects `List.duplicate(string_literal, n) |> Enum.join()` (and the nested
`Enum.join(List.duplicate(string_literal, n))`) and suggests
`String.duplicate/2` instead.
- [Credence.Pattern.NoListFoldl](Credence.Pattern.NoListFoldl.md): Detects `List.foldl/3` on a provably-list argument and suggests `Enum.reduce/3`.
- [Credence.Pattern.NoListPopAtForAccess](Credence.Pattern.NoListPopAtForAccess.md): Detects `List.pop_at(list, 0) |> elem(n)` used to extract only the head
(`n = 0`) or only the rest-after-head (`n = 1`) of a list, and rewrites
it to the direct `List` accessor.
- [Credence.Pattern.NoLiteralListTypespec](Credence.Pattern.NoLiteralListTypespec.md): Correctness rule: Detects a multi-element **literal list** used as an
`@spec` return type — e.g. `[pos_integer(), pos_integer()]`. This is not
valid Elixir: in a typespec `[type]` means "a list of `type`", and a list
with two or more comma-separated element types raises
`Kernel.TypespecError` at compile time. LLMs translating fixed-size return
values from other languages (a Python tuple, say) emit this shape.
- [Credence.Pattern.NoManualCountWithPredicate](Credence.Pattern.NoManualCountWithPredicate.md): Detects hand-rolled recursive counting functions that should use `Enum.count/2`.
- [Credence.Pattern.NoManualFind](Credence.Pattern.NoManualFind.md): Detects hand-rolled recursive "find first matching element" functions that
should use `Enum.find/3`.
- [Credence.Pattern.NoManualFrequencies](Credence.Pattern.NoManualFrequencies.md): Readability rule: Detects manual frequency counting with
`Enum.reduce(list, %{}, fn x, acc -> Map.update(acc, KEY, 1, &(&1 + 1)) end)`.
- [Credence.Pattern.NoManualListLast](Credence.Pattern.NoManualListLast.md): Detects hand-rolled reimplementations of `List.last/1`.
- [Credence.Pattern.NoManualListReduce](Credence.Pattern.NoManualListReduce.md): Detects hand-rolled recursive list-folding functions that should use
`Enum.reduce/3`.
- [Credence.Pattern.NoManualMax](Credence.Pattern.NoManualMax.md): Detects `if` expressions that manually reimplement `Kernel.max/2`.
- [Credence.Pattern.NoManualMin](Credence.Pattern.NoManualMin.md): Detects `if` expressions that manually reimplement `Kernel.min/2`.
- [Credence.Pattern.NoManualStringReverse](Credence.Pattern.NoManualStringReverse.md): Readability & performance rule: Detects the pattern
`String.graphemes(s) |> Enum.reverse() |> Enum.join()` (and the
`IO.iodata_to_binary/1` reassemble variant) which is a manual
reimplementation of `String.reverse/1`.
- [Credence.Pattern.NoMapKeysEnumLookup](Credence.Pattern.NoMapKeysEnumLookup.md): Detects `Map.keys(var)` piped into an `Enum` function whose callback
also looks up values from the same map variable.
- [Credence.Pattern.NoMapKeysForMembership](Credence.Pattern.NoMapKeysForMembership.md): Detects `x in Map.keys(m)` and `x not in Map.keys(m)` used for membership
testing, and rewrites to `Map.has_key?(m, x)` / `not Map.has_key?(m, x)`.
- [Credence.Pattern.NoMapKeysOrValuesForIteration](Credence.Pattern.NoMapKeysOrValuesForIteration.md): Performance rule: Detects `Map.values(map)` or `Map.keys(map)` passed
directly into an `Enum` function, which creates an unnecessary intermediate
list.
- [Credence.Pattern.NoMapPutGetIncrement](Credence.Pattern.NoMapPutGetIncrement.md): Detects `Map.put(map, key, Map.get(map, key, 0) + 1)` and rewrites
to `Map.update(map, key, 1, &(&1 + 1))`.
- [Credence.Pattern.NoMapThenAggregate](Credence.Pattern.NoMapThenAggregate.md): Detects `Enum.map/2` immediately followed by `Enum.sum/1`, which creates an
unnecessary intermediate list, and fuses it into a single `Enum.reduce/3`.
- [Credence.Pattern.NoMapUpdateThenFetch](Credence.Pattern.NoMapUpdateThenFetch.md): Performance rule: Detects calling `Map.update/4` (or `Map.update!/3`) on a
map variable and then immediately reading the same key back with
`Map.fetch!/2` or `Map.get/2`.
- [Credence.Pattern.NoMissingRequireLogger](Credence.Pattern.NoMissingRequireLogger.md): Detects Logger macro calls without a `require Logger` in the enclosing module.
- [Credence.Pattern.NoNestedEnumOnSameEnumerable](Credence.Pattern.NoNestedEnumOnSameEnumerable.md): Detects `Enum.member?/2` calls nested inside another `Enum.*` traversal
of the **same** enumerable and rewrites them to use `MapSet.member?/2`.
- [Credence.Pattern.NoPipedRegexReplace](Credence.Pattern.NoPipedRegexReplace.md): Detects `Regex.replace` used as a pipe target and replaces it with
`String.replace`, which accepts the string as its first argument.
- [Credence.Pattern.NoReduceForGroupBy](Credence.Pattern.NoReduceForGroupBy.md): Detects a manual `Enum.group_by/2` written as `Enum.reduce/3` with an
empty-map accumulator that prepends each element onto a per-key list via
`Map.update(acc, key, [elem], &[elem | &1])`, **immediately followed by**
`|> Map.new(fn {k, v} -> {k, Enum.reverse(v)} end)` to restore insertion
order.
- [Credence.Pattern.NoReduceForMapBuilding](Credence.Pattern.NoReduceForMapBuilding.md): Detects `Enum.reduce/3` with an empty-map accumulator `%{}` and a body
consisting solely of `Map.put(acc, key, value)`, and suggests `Map.new/2`
instead. Also detects `Enum.reduce/3` building a `MapSet` via
`MapSet.put/2` and suggests `MapSet.new/1`.
- [Credence.Pattern.NoReduceWhileWithoutHalt](Credence.Pattern.NoReduceWhileWithoutHalt.md): Detects `Enum.reduce_while/3` where every callback clause returns only
`{:cont, value}` — never `:halt` or `{:halt, value}`. This is equivalent
to plain `Enum.reduce/3` and the `reduce_while` adds unnecessary ceremony.
- [Credence.Pattern.NoRedundantAssignment](Credence.Pattern.NoRedundantAssignment.md): Detects a single plain variable being assigned and immediately returned as
the last two statements of a block.
- [Credence.Pattern.NoRedundantBinarySyntax](Credence.Pattern.NoRedundantBinarySyntax.md): Detects string literals needlessly wrapped in `<<>>` binary syntax.
- [Credence.Pattern.NoRedundantCaseNilClause](Credence.Pattern.NoRedundantCaseNilClause.md): Detects `case` expressions where a `nil` clause and a trailing wildcard
clause have identical bodies, and the intermediate guarded clause can be
extended with `not is_nil/1` to absorb the `nil` case.
- [Credence.Pattern.NoRedundantComparisonGuard](Credence.Pattern.NoRedundantComparisonGuard.md): Detects redundant comparison guards in multi-clause functions.
- [Credence.Pattern.NoRedundantDedupBeforeMapset](Credence.Pattern.NoRedundantDedupBeforeMapset.md): Detects `Enum.dedup/1` or `Enum.uniq/1` used before `MapSet.new/1`,
making the deduplication a redundant intermediate step.
- [Credence.Pattern.NoRedundantEnumJoinSeparator](Credence.Pattern.NoRedundantEnumJoinSeparator.md): Readability rule: Detects `Enum.join("")` and `Enum.map_join("", mapper)`
where the empty-string separator is passed explicitly.
- [Credence.Pattern.NoRedundantListTraversal](Credence.Pattern.NoRedundantListTraversal.md): Detects multiple traversals of the same list that could be merged into
a single pass.
- [Credence.Pattern.NoRedundantLocalCapture](Credence.Pattern.NoRedundantLocalCapture.md): Detects redundant capture of a local function with immediate call.
- [Credence.Pattern.NoRedundantNegatedGuard](Credence.Pattern.NoRedundantNegatedGuard.md): Detects guard clauses that are logically redundant because a preceding
clause of the same function already handles the complementary case.
- [Credence.Pattern.NoRedundantToList](Credence.Pattern.NoRedundantToList.md): Detects `Enum.to_list/1` used before a function that already accepts
any enumerable, making the conversion a redundant intermediate step.
- [Credence.Pattern.NoRedundantUnderscoreBind](Credence.Pattern.NoRedundantUnderscoreBind.md): Detects `_ = var` bindings in **pattern position** (function heads, `case`/`fn`
clause heads, `with`/`for` generators) and simplifies them to just `var`.
- [Credence.Pattern.NoRepeatedDivRem](Credence.Pattern.NoRepeatedDivRem.md): Detects a `div/2` or `rem/2` result that is **already bound to a variable**
by an anchor statement and then re-computed verbatim later in the same
function clause body, and rewrites the later occurrences to read the bound
variable instead.
- [Credence.Pattern.NoSortForTopK](Credence.Pattern.NoSortForTopK.md): Detects inefficient patterns where a full sort is performed only to
retrieve the minimum or maximum element via `Enum.at(0)`.
- [Credence.Pattern.NoSortThenAt](Credence.Pattern.NoSortThenAt.md): Performance rule (fixable): Detects `Enum.sort |> Enum.at(index)` where the
index is a **literal** `0` or `-1` and the sort direction can be statically
determined. These are replaced with `Enum.min`/`Enum.max`, avoiding the
O(n log n) sort entirely.
- [Credence.Pattern.NoSortThenReverse](Credence.Pattern.NoSortThenReverse.md): Performance & readability rule: Detects the pattern of calling `Enum.sort/1,2`
followed by `Enum.reverse/1` on the result, where the sort direction can be
statically determined.
- [Credence.Pattern.NoStringConcatInLoop](Credence.Pattern.NoStringConcatInLoop.md): Performance rule: Detects string concatenation with `<>` inside
`Enum.reduce` calls with an empty string initial accumulator that can
be automatically fixed.
- [Credence.Pattern.NoStringLengthForCharCheck](Credence.Pattern.NoStringLengthForCharCheck.md): Performance rule: Detects `String.length(x) == 1` (or `!= 1`) used to
validate that a string is a single character.
`String.length/1` traverses the entire string to count grapheme clusters,
making it O(n). For a simple single-character check, pattern matching on
the result of `String.graphemes/1` is more expressive and idiomatic.
This rule automatically rewrites the comparison to use `match?/2` with
`String.graphemes/1`, which produces a clean boolean result that works
in any expression context.
## Bad
    if String.length(target_char) != 1 do
      raise ArgumentError, "expected a single character"
    end
    String.length(s) == 1
    1 === String.length(s)
## Good
    if not match?([_], String.graphemes(target_char)) do
      raise ArgumentError, "expected a single character"
    end
    match?([_], String.graphemes(s))

- [Credence.Pattern.NoStringLengthForEmptyCheck](Credence.Pattern.NoStringLengthForEmptyCheck.md): Rewrites `String.length(s) == 0` (and `!= 0`, and the flipped operand order)
to the O(1) empty-string check `s == ""` / `s != ""` — but ONLY when `s` is
provably a binary.
- [Credence.Pattern.NoTakeWhileLengthCheck](Credence.Pattern.NoTakeWhileLengthCheck.md): Detects `Enum.take_while/2` piped into `length/1` or `Enum.count/1`,
which materializes an intermediate list only to count it.
- [Credence.Pattern.NoTautologicalIf](Credence.Pattern.NoTautologicalIf.md): Detects `if/else` expressions where both branches return the same value.
- [Credence.Pattern.NoTrailingNewlineInDoc](Credence.Pattern.NoTrailingNewlineInDoc.md): Detects `@doc`, `@moduledoc`, and `@typedoc` strings that contain a
trailing `\n` escape sequence.
- [Credence.Pattern.NoUnderscoreFunctionName](Credence.Pattern.NoUnderscoreFunctionName.md): Detects function names that use a leading underscore to indicate privacy,
a convention borrowed from Python that is non-idiomatic in Elixir.
- [Credence.Pattern.NoUniqThenCount](Credence.Pattern.NoUniqThenCount.md): Detects `Enum.uniq/1` piped into `length/1` or `Enum.count/1`, which
creates an unnecessary intermediate list only to count its size.
- [Credence.Pattern.NoUnlessElse](Credence.Pattern.NoUnlessElse.md): Detects `unless ... do ... else ... end` — a style guide violation.
- [Credence.Pattern.NoUnusedComputation](Credence.Pattern.NoUnusedComputation.md): Removes a dead `_`-prefixed assignment of a **total, provably-typed** call.
- [Credence.Pattern.NoUnusedUnderscoreAssignment](Credence.Pattern.NoUnusedUnderscoreAssignment.md): Removes a dead `_var = <pure>` binding left behind by the unused-variable fix.
- [Credence.Pattern.NoZipThenMap](Credence.Pattern.NoZipThenMap.md): Detects `Enum.zip/2` followed by `Enum.map/2` that destructures the
resulting 2-tuples, which can be replaced by `Enum.zip_with/3`.
- [Credence.Pattern.NonGroupedClauses](Credence.Pattern.NonGroupedClauses.md): Fixes function clauses that are not grouped together.
- [Credence.Pattern.PreferComprehensionForFilteredRange](Credence.Pattern.PreferComprehensionForFilteredRange.md): Detects `Enum.reduce/3` over a range that filters elements into an
accumulator list followed by `Enum.reverse/1`, and rewrites it as a
`for` comprehension with a guard.
- [Credence.Pattern.PreferConcatOverFlatMapIdentity](Credence.Pattern.PreferConcatOverFlatMapIdentity.md): Detects `Enum.flat_map(enumerable, fn x -> x end)` which is an identity
flat-map and can be simplified to `Enum.concat(enumerable)`.
- [Credence.Pattern.PreferCondForNestedIf](Credence.Pattern.PreferCondForNestedIf.md): Detects nested `if/else` blocks where the `else` branch contains another `if`
(with its own `else`), and flattens them into a `cond` for readability.
- [Credence.Pattern.PreferCountsForLength](Credence.Pattern.PreferCountsForLength.md): Detects `length(String.codepoints(string))` when a `counts` map from
`Enum.frequencies/1` on the same codepoints already exists.
- [Credence.Pattern.PreferDescSortOverNegativeTake](Credence.Pattern.PreferDescSortOverNegativeTake.md): Prefer `Enum.sort(nums, :desc) |> Enum.take(n) |> Enum.reverse()`
over `Enum.sort(nums) |> Enum.take(-n)`.
- [Credence.Pattern.PreferEnumCount](Credence.Pattern.PreferEnumCount.md): Detects `Enum.reduce/3` calls that count elements matching a predicate
(using 0 as initial accumulator and `if pred, do: acc + 1, else: acc` as body)
and rewrites them to the more concise `Enum.count/2`.
- [Credence.Pattern.PreferEnumReverseTwo](Credence.Pattern.PreferEnumReverseTwo.md): Performance rule: Flags `Enum.reverse(list) ++ other_list`.
`Enum.reverse/1` creates a new list, and `++` traverses that new list
entirely to append the second. This is a 2-pass operation.
Using `Enum.reverse/2` performs both actions in a single optimized pass.
## Bad
    defp do_merge([], l2, acc), do: Enum.reverse(acc) ++ l2
## Good
    defp do_merge([], l2, acc), do: Enum.reverse(acc, l2)

- [Credence.Pattern.PreferEnumSlice](Credence.Pattern.PreferEnumSlice.md): Readability rule: flags `Enum.drop/2` followed by `Enum.take/2` and rewrites it
to `Enum.slice/3`.
- [Credence.Pattern.PreferEnumSplit](Credence.Pattern.PreferEnumSplit.md): Performance rule: collapses two adjacent assignments that take and drop the
same prefix of the same list variable into a single `Enum.split/2`, which
produces both results in one pass.
- [Credence.Pattern.PreferErlangFloat](Credence.Pattern.PreferErlangFloat.md): Replaces float-coercion arithmetic tricks with explicit `:erlang.float/1`.
- [Credence.Pattern.PreferExplicitBinaryArithmetic](Credence.Pattern.PreferExplicitBinaryArithmetic.md): Readability rule: flags piping into binary arithmetic functions like `rem/2`
or `div/2`. Piping obscures which argument is the dividend — prefer an
explicit call for clarity.
- [Credence.Pattern.PreferFrequenciesOverGroupBy](Credence.Pattern.PreferFrequenciesOverGroupBy.md): Detects `Enum.group_by/1` with an identity function piped into `Enum.map/2`
that counts group lengths, then piped into `Enum.count/2` with a `> 1`
predicate — a manual "count duplicate occurrences" pattern that
`Enum.frequencies/1` followed by `Enum.count/2` handles more idiomatically.
- [Credence.Pattern.PreferFunctionCapture](Credence.Pattern.PreferFunctionCapture.md): Detects single-argument anonymous functions that simply delegate to a
function call and rewrites them using the more concise function capture
syntax (`&Module.function/1` or `&function/1`).
- [Credence.Pattern.PreferFunctionClausesForListPatterns](Credence.Pattern.PreferFunctionClausesForListPatterns.md): Detects a redundant `case` inside a *guarded* function clause that dispatches
on the same list parameter checked by `is_list/1` in the guard, and promotes
the `case` clauses to pattern-matching function heads.
- [Credence.Pattern.PreferGraphemesForCharacterUniqueness](Credence.Pattern.PreferGraphemesForCharacterUniqueness.md): Readability & correctness rule: Detects the pattern
`String.to_charlist(s) |> Enum.uniq() |> Enum.count() |> (&(&1 == String.length(s))).()`.
- [Credence.Pattern.PreferGuardOverIf](Credence.Pattern.PreferGuardOverIf.md): Detects function clauses whose body is a single `if/else` with a
guard-eligible condition. In idiomatic Elixir, prefer multi-clause
functions with guards over wrapping the entire body in `if/else`.
- [Credence.Pattern.PreferHeredocForMultiLineDoc](Credence.Pattern.PreferHeredocForMultiLineDoc.md): Detects `@doc`, `@moduledoc`, and `@typedoc` strings that contain
escaped newlines (`\n`) and should use heredoc syntax instead.
- [Credence.Pattern.PreferLookupForDigitConversion](Credence.Pattern.PreferLookupForDigitConversion.md): Detects the anti-pattern of mapping each hex digit (0–15) to its character
representation via 16 separate function clauses, and rewrites it to a single
clause using `String.at/2` on the lookup string `"0123456789ABCDEF"`.
- [Credence.Pattern.PreferMapIntersectOverMapsetIntersection](Credence.Pattern.PreferMapIntersectOverMapsetIntersection.md): Detects MapSet-based intersection of map keys that can be replaced with
`Map.intersect/3` (Elixir 1.14+).
- [Credence.Pattern.PreferMapNew](Credence.Pattern.PreferMapNew.md): Detects `Enum.into(enum, %{})` and suggests `Map.new(enum)` instead.
- [Credence.Pattern.PreferMapNewWithTransform](Credence.Pattern.PreferMapNewWithTransform.md): Detects `Enum.map/2` followed by `Map.new/0` and suggests combining them
into a single `Map.new/2` call.
- [Credence.Pattern.PreferMapPutNew](Credence.Pattern.PreferMapPutNew.md): Performance and idiomatic code rule: detects an `if`/`unless` guard
using `Map.has_key?/2` that only calls `Map.put/3` when the key is
absent, and suggests `Map.put_new/3` instead.
- [Credence.Pattern.PreferMapsetForSetEquality](Credence.Pattern.PreferMapsetForSetEquality.md): Detects two `String.codepoints/1` (or `String.graphemes/1`) results that are
each run through `Enum.uniq() |> Enum.sort()` and then compared with `==` for
set-equality checking, and rewrites them to compare `MapSet.new/1` directly.
- [Credence.Pattern.PreferMultiClauseReduceFn](Credence.Pattern.PreferMultiClauseReduceFn.md): Detects a two-argument anonymous function whose single clause is a nested
`if/else` chain and rewrites it as a multi-clause pattern-matching `fn`,
turning each `if` condition into a `when` guard.
- [Credence.Pattern.PreferNegateIfTrueFalse](Credence.Pattern.PreferNegateIfTrueFalse.md): Detects `if cond do false else body end` and rewrites it to
`if !cond do body else false end`.
- [Credence.Pattern.PreferNoQuestionMarkForNonBoolean](Credence.Pattern.PreferNoQuestionMarkForNonBoolean.md): Detects functions with a `?` suffix whose `@spec` declares a non-boolean
return type and renames them to drop the suffix.
- [Credence.Pattern.PreferPatternMatchEmptyString](Credence.Pattern.PreferPatternMatchEmptyString.md): Detects `byte_size(var) == 0` in function guards that can be replaced with
pattern matching `""` directly in the function head.
- [Credence.Pattern.PreferPatternMatchOverConditionalInRecursiveCount](Credence.Pattern.PreferPatternMatchOverConditionalInRecursiveCount.md): Readability rule: Detects recursive function clauses that use an `if`/`else`
to conditionally count matches, when the same logic is more idiomatically
expressed via multiple pattern-matching function clauses with a guard.
- [Credence.Pattern.PreferPipeMapsetIntersection](Credence.Pattern.PreferPipeMapsetIntersection.md): Detects a sequence of `MapSet.new/1` assignments followed by nested
`MapSet.intersection/2` calls piped into `MapSet.to_list/0`, and rewrites
them into a single pipeline using `|>`.
- [Credence.Pattern.PreferReduceWhileWithHaltValue](Credence.Pattern.PreferReduceWhileWithHaltValue.md): Detects `Enum.reduce_while/3` that carries a boolean flag in the accumulator
solely to signal whether to halt, when the halt value itself could convey the
answer directly.
- [Credence.Pattern.PreferRegexMatch](Credence.Pattern.PreferRegexMatch.md): Rewrites a `case` over `Regex.run/2` that only tests **whether** the regex
matched — never the captured groups — into the idiomatic boolean form built
on `Regex.match?/2`.
- [Credence.Pattern.PreferSigilCharlist](Credence.Pattern.PreferSigilCharlist.md): Rewrites a single-quoted charlist literal `'abc'` to the `~c"abc"` sigil.
- [Credence.Pattern.PreferStringSliceForTrimLastChar](Credence.Pattern.PreferStringSliceForTrimLastChar.md): Detects the verbose `case String.graphemes(str)` idiom for removing the
last character from a string, and rewrites it to the idiomatic
`String.slice(str, 0..-2//1)`.
- [Credence.Pattern.PreferStringSplitTrim](Credence.Pattern.PreferStringSplitTrim.md): Detects `String.split/2` followed by `Enum.filter/2` that removes empty strings,
which can be replaced with the `:trim` option on `String.split/3`.
- [Credence.Pattern.PreferThenOverCaptureInvocation](Credence.Pattern.PreferThenOverCaptureInvocation.md): Detects immediately-invoked captures `(&body).()` in pipelines and
rewrites them to use `Kernel.then/2` (Elixir 1.12+), which is the
idiomatic replacement.
- [Credence.Pattern.PreferTupleDestructureAfterWithIndex](Credence.Pattern.PreferTupleDestructureAfterWithIndex.md): Detects `Enum.map` calls that follow `Enum.with_index()` in a pipe chain
but use a multi-argument anonymous function instead of destructuring the
`{element, index}` tuple that `with_index/1` produces.
- [Credence.Pattern.RedundantListGuard](Credence.Pattern.RedundantListGuard.md): Detects `is_list/1` guards on a cons-pattern tail variable
(`[head | tail] when is_list(tail)`) that are redundant **under the
`proper_lists` promise**.
- [Credence.Pattern.RemoveUnreachableClausesAfterCatchall](Credence.Pattern.RemoveUnreachableClausesAfterCatchall.md): Removes a redundant duplicate catch-all clause — a bare catch-all clause
(all arguments bare variables / underscores, no guard) that follows an
earlier catch-all clause for the same name and arity and is therefore
unreachable at runtime.
- [Credence.Pattern.Rule](Credence.Pattern.Rule.md): Behaviour for pattern-level rules that detect and auto-fix anti-patterns.
- [Credence.Pattern.UnnecessaryGraphemeChunking](Credence.Pattern.UnnecessaryGraphemeChunking.md): Detects the common n-gram generation pipeline that converts a string
to graphemes, creates sliding window chunks of step 1, and joins them
back into strings. This pattern is automatically fixed by replacing it
with `String.slice/3` which avoids intermediate list allocations.
- [Credence.Pattern.UseMapJoin](Credence.Pattern.UseMapJoin.md): Detects `Enum.map/2` chained into `Enum.join/1` or `Enum.join/2`,
and suggests `Enum.map_join/3` instead.
- [Credence.RuleHelpers](Credence.RuleHelpers.md): Shared utilities used by all three Credence phases (Syntax, Semantic, Pattern).
- [Credence.RuleName](Credence.RuleName.md): The one place that turns a rule's name into every derived form — snake, Pascal,
rule atom, rule module, and the conventional paths/modules of its test files.
- [Credence.RuleScaffold](Credence.RuleScaffold.md): Pure templates for a new rule and its test files. `files/2` returns
`[{path, content}]` for a type — no disk I/O — so it is testable in memory and
reused by both the Mix task (`mix credence.gen.rule`) that writes the files and
the pin (`Credence.GeneratorMetaTest`) that proves the output passes every
structural gate.
- [Credence.Semantic](Credence.Semantic.md): Semantic phase — fixes compiler warnings and errors.
- [Credence.Semantic.MissingUseExunitCase](Credence.Semantic.MissingUseExunitCase.md): Fixes test modules that are missing `use ExUnit.Case`.
- [Credence.Semantic.NoBareDocAttribute](Credence.Semantic.NoBareDocAttribute.md): Removes bare `@doc` attributes (no arguments) before `def` declarations.
- [Credence.Semantic.NoBareNamesInSpec](Credence.Semantic.NoBareNamesInSpec.md): Fixes compiler errors about undefined types caused by bare names in @spec.
- [Credence.Semantic.NoCaptureAsBitwiseAnd](Credence.Semantic.NoCaptureAsBitwiseAnd.md): Repairs the common Python→Elixir translation error where `&` is written as
the bitwise-AND operator.
- [Credence.Semantic.NoDocOnPrivateFunction](Credence.Semantic.NoDocOnPrivateFunction.md): Fixes compiler warnings about `@doc` on private functions.
- [Credence.Semantic.NoNonNegatedInteger](Credence.Semantic.NoNonNegatedInteger.md): Fixes compiler errors about the undefined type `non_negated_integer/0`.
- [Credence.Semantic.NoUnderscoreInExpression](Credence.Semantic.NoUnderscoreInExpression.md): Fixes compiler errors caused by using `_` in expression position,
such as a tuple key in a for-comprehension body.
- [Credence.Semantic.OutdentedHeredoc](Credence.Semantic.OutdentedHeredoc.md): Fixes compiler warnings about outdented heredoc lines by re-indenting
all body content to match the closing delimiter.
- [Credence.Semantic.PreferExplicitRangeStep](Credence.Semantic.PreferExplicitRangeStep.md): Makes the implicit step of a descending literal range explicit.
- [Credence.Semantic.PreferKernelMaxOverLocal](Credence.Semantic.PreferKernelMaxOverLocal.md): Removes a local `defp max/2`/`defp min/2` that *exactly* re-implements the
auto-imported `Kernel.max/2`/`Kernel.min/2`.
- [Credence.Semantic.RemoveUnusedTypespecWhenVar](Credence.Semantic.RemoveUnusedTypespecWhenVar.md): Fixes compiler errors caused by unused type variables in @spec clauses.
- [Credence.Semantic.RequireDefmoduleWrapper](Credence.Semantic.RequireDefmoduleWrapper.md): The canonical "module attributes / code outside a `defmodule`" rule.
- [Credence.Semantic.Rule](Credence.Semantic.Rule.md): Behaviour for semantic-level rules that fix compiler warnings.
- [Credence.Semantic.UndefinedFunction](Credence.Semantic.UndefinedFunction.md): Fixes compiler diagnostics about undefined, private, or deprecated functions.
- [Credence.Semantic.UndefinedStringAlphanumeric](Credence.Semantic.UndefinedStringAlphanumeric.md): Fixes the common LLM hallucination where `String.alphanumeric?/1` is called
as if it were a real Elixir standard library function. It is not.
- [Credence.Semantic.UnusedVariable](Credence.Semantic.UnusedVariable.md): Fixes compiler warnings about unused variables by adding `_` prefix.
- [Credence.Semantic.UsedUnderscoreVariable](Credence.Semantic.UsedUnderscoreVariable.md): Fixes compiler warnings about underscored variables that are referenced
after being set, by removing the leading underscore.
- [Credence.Syntax](Credence.Syntax.md): Syntax phase — fixes code that won't parse.
- [Credence.Syntax.CloseUnclosedDocHeredoc](Credence.Syntax.CloseUnclosedDocHeredoc.md): Detects and fixes unclosed `@doc` heredocs where the LLM jumps
straight into function code without ever closing the triple-quote block.
- [Credence.Syntax.CloseUnclosedFnDelimiter](Credence.Syntax.CloseUnclosedFnDelimiter.md): Repairs an `fn` closed with `)` **and** a leftover stray `end` on the next line.
- [Credence.Syntax.FixDivRem](Credence.Syntax.FixDivRem.md): Fixes `div` and `rem` used as infix operators (Python `//` and `%` style).
- [Credence.Syntax.FixDoBlockFusion](Credence.Syntax.FixDoBlockFusion.md): Fixes LLM confusions between the `do ... end` block form and the `, do:`
one-liner form of definitions.
- [Credence.Syntax.FixMalformedSpec](Credence.Syntax.FixMalformedSpec.md): Fixes `@spec` declarations where the `::` return type separator is
misplaced inside the argument parentheses.
- [Credence.Syntax.FixMissingModuleEnd](Credence.Syntax.FixMissingModuleEnd.md): Repairs source whose trailing `do` blocks were never closed — most commonly a
`defmodule` (or `def`) missing its final `end`.
- [Credence.Syntax.FixPythonAugmentedAssignment](Credence.Syntax.FixPythonAugmentedAssignment.md): Replaces Python's augmented assignment operators (`+=`, `-=`, `*=`, `/=`)
with Elixir's rebinding syntax.
- [Credence.Syntax.FixPythonFloorDiv](Credence.Syntax.FixPythonFloorDiv.md): Replaces Python's `//` floor-division operator with Elixir's `div/2`.
- [Credence.Syntax.FixPythonModulo](Credence.Syntax.FixPythonModulo.md): Replaces Python's `%` modulo operator with Elixir's `rem/2`.
- [Credence.Syntax.FixScientificNotation](Credence.Syntax.FixScientificNotation.md): Fixes Python-style scientific notation that is invalid in Elixir.
- [Credence.Syntax.FixStaleAccessModifier](Credence.Syntax.FixStaleAccessModifier.md): Removes non-Elixir access modifier keywords prepended to `def`/`defp`/`defmacro`/`defmacrop`.
- [Credence.Syntax.FixTruncatedBinaryClose](Credence.Syntax.FixTruncatedBinaryClose.md): Fixes truncated binary close delimiters caused by LLM output truncation.
- [Credence.Syntax.NoDocWithDoBlock](Credence.Syntax.NoDocWithDoBlock.md): Repairs a documentation attribute written with a stray `do` block.
- [Credence.Syntax.NoElseIf](Credence.Syntax.NoElseIf.md): Detects and rewrites Python-style `else if` (two words) chains to idiomatic `cond`.
- [Credence.Syntax.NoFnWithCapture](Credence.Syntax.NoFnWithCapture.md): Repairs `fn(&1 ...)` — the `fn` keyword mistakenly mixed with capture syntax.
- [Credence.Syntax.NoMarkdownCodeFences](Credence.Syntax.NoMarkdownCodeFences.md): Removes the markdown code-fence lines that wrap generated Elixir source.
- [Credence.Syntax.NoUnclosedFnDelimiter](Credence.Syntax.NoUnclosedFnDelimiter.md): Repairs an `fn` clause that is closed with `)` instead of `end`.
- [Credence.Syntax.PreferCondDoKeyword](Credence.Syntax.PreferCondDoKeyword.md): Repairs `cond ->` written in place of `cond do`.
- [Credence.Syntax.PreferSpecArrowOperator](Credence.Syntax.PreferSpecArrowOperator.md): Fixes `@spec` declarations where the `::` arrow operator is missing
before the return type.
- [Credence.Syntax.Rule](Credence.Syntax.Rule.md): Behaviour for syntax-level rules that fix code which won't parse.

## Mix Tasks

- [mix credence.ast](Mix.Tasks.Credence.Ast.md): Print the `Sourceror.parse_string!/1` AST of a code snippet — the exact tree a
Pattern rule's `check/2` pattern-matches against — in two views
- [mix credence.corpus](Mix.Tasks.Credence.Corpus.md): Runs `Credence.Pattern.analyze/1` over the `lib/` source of the pinned popular
hex packages in `corpus/` (see `Credence.Corpus`) and reports what Credence
flags — the over-firing signal.
- [mix credence.corpus.fetch](Mix.Tasks.Credence.Corpus.Fetch.md): Fetches the source of the pinned popular hex packages (see `Credence.Corpus`)
into the gitignored `corpus/` directory, using `mix hex.package fetch` — source
only, no transitive deps, no compilation.
- [mix credence.covers](Mix.Tasks.Credence.Covers.md): Behavioural novelty check (Tunex `07` §3.7): run a snippet through
`Credence.fix/2` + `Credence.analyze/2` in the **default (helpful)
`assumptions:` mode** (the same mode solve's Validator runs — never `:strict`,
else a switch-gated pattern reads NOVEL here but COVERED in solve), and decide
whether a **real rule already engaged**
- [mix credence.equiv](Mix.Tasks.Credence.Equiv.md): Classify-time behavioural-equivalence pre-check (Tunex `07` §3.11, `08` T1.4).
- [mix credence.fix_tests](Mix.Tasks.Credence.FixTests.md): Deterministic helper for the tunex rule-gen flow (tunex docs/10).
- [mix credence.gen.rule](Mix.Tasks.Credence.Gen.Rule.md): Generate a correctly-shaped rule plus its test files for a type.
- [mix credence.normalize_tests](Mix.Tasks.Credence.NormalizeTests.md): Cosmetic cleanup for agent-authored rule tests (tunex docs/10).

