# credence v0.4.5 - 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.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.AvoidGraphemesLength](Credence.Pattern.AvoidGraphemesLength.md): Performance rule: Detects the use of `length/1` on the result of
`String.graphemes/1`.
- [Credence.Pattern.HallucinatedGuard](Credence.Pattern.HallucinatedGuard.md): Fixes calls to guard functions that don't exist in Elixir.
- [Credence.Pattern.InconsistentParamNames](Credence.Pattern.InconsistentParamNames.md): Detects functions where the same positional parameter uses different
variable names across clauses.
- [Credence.Pattern.NoAnonFnApplicationInPipe](Credence.Pattern.NoAnonFnApplicationInPipe.md): Readability rule: Detects anonymous functions applied with `.()` inside
a pipeline.
- [Credence.Pattern.NoCaseTrueFalse](Credence.Pattern.NoCaseTrueFalse.md): Detects `case expr do true -> …; false -> … end` that should be `if/else`.
- [Credence.Pattern.NoCondTwoClauses](Credence.Pattern.NoCondTwoClauses.md): Detects `cond` with exactly two clauses where the second guard is
`true` — a pattern that is just an `if/else` in disguise.
- [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 `@doc false` placed before private functions (`defp`).
- [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.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.NoEnumAtBinarySearch](Credence.Pattern.NoEnumAtBinarySearch.md): Performance rule: Flags `Enum.at/2` inside **recursive** binary search functions.
- [Credence.Pattern.NoEnumAtInLoop](Credence.Pattern.NoEnumAtInLoop.md): Performance rule: Detects `Enum.at/2` inside looping constructs
(`Enum.reduce`, `Enum.map`, `Enum.each`, `Enum.filter`, `Enum.flat_map`,
`for` comprehensions) or recursive functions.
- [Credence.Pattern.NoEnumAtLoopAccess](Credence.Pattern.NoEnumAtLoopAccess.md): Performance heuristic rule: warns when `Enum.at/2` is used inside loops.
- [Credence.Pattern.NoEnumAtMidpointAccess](Credence.Pattern.NoEnumAtMidpointAccess.md): Performance rule: Flags `Enum.at/2` with a midpoint index inside
**non-recursive** functions.
- [Credence.Pattern.NoEnumAtNegativeIndex](Credence.Pattern.NoEnumAtNegativeIndex.md): Detects `Enum.at/2` called with a negative integer literal index.
- [Credence.Pattern.NoEnumCountForLength](Credence.Pattern.NoEnumCountForLength.md): Detects `Enum.count/1` (without a predicate) and suggests `length/1`
or a more specific size function.
- [Credence.Pattern.NoEnumDropNegative](Credence.Pattern.NoEnumDropNegative.md): Performance rule: Detects `Enum.drop(list, -n)` where `n` is a positive
integer literal.
- [Credence.Pattern.NoEnumTakeNegative](Credence.Pattern.NoEnumTakeNegative.md): Performance rule: Detects `Enum.take(list, -n)` where `n` is a positive
integer literal.
- [Credence.Pattern.NoExplicitMaxReduce](Credence.Pattern.NoExplicitMaxReduce.md): Strict semantic rule: Flags ONLY explicit max-reduction patterns inside `Enum.reduce/3`.
- [Credence.Pattern.NoExplicitMinReduce](Credence.Pattern.NoExplicitMinReduce.md): Flags explicit min-reduction patterns inside Enum.reduce/3.
- [Credence.Pattern.NoExplicitSumReduce](Credence.Pattern.NoExplicitSumReduce.md): Flags explicit sum-reduction patterns inside Enum.reduce/3.
- [Credence.Pattern.NoGraphemePalindromeCheck](Credence.Pattern.NoGraphemePalindromeCheck.md): Readability & performance rule: Detects the pattern of decomposing a string
into graphemes or a charlist, only to compare it with its own `Enum.reverse`.
- [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.NoIdentityFloatCoercion](Credence.Pattern.NoIdentityFloatCoercion.md): Detects identity arithmetic used to coerce an integer to a float.
- [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.NoIntegerToStringDigits](Credence.Pattern.NoIntegerToStringDigits.md): Performance rule: Detects converting an integer to a string representation
in a given base and then to a charlist, when `Integer.digits/2` can extract
the digits directly as a list of integers.
- [Credence.Pattern.NoIsPrefixForNonGuard](Credence.Pattern.NoIsPrefixForNonGuard.md): Detects `def`/`defp` functions with an `is_` prefix, which in Elixir
is reserved for guard-safe functions defined with `defguard` or Erlang BIFs.
- [Credence.Pattern.NoKernelOpInPipeline](Credence.Pattern.NoKernelOpInPipeline.md): Detects qualified `Kernel.op/2` calls used as steps in a pipeline.
- [Credence.Pattern.NoKernelShadowing](Credence.Pattern.NoKernelShadowing.md): Idiomatic rule: fixes variables that shadow `Kernel` functions.
- [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.NoLengthInGuard](Credence.Pattern.NoLengthInGuard.md): Performance rule: Detects the use of `length/1` inside guard clauses (`when`)
in cases that cannot be automatically rewritten as pattern matches.
- [Credence.Pattern.NoListAppendInLoop](Credence.Pattern.NoListAppendInLoop.md): Performance rule: Detects the use of `++` inside looping constructs
that cannot be auto-fixed.
- [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.NoListDeleteAtInLoop](Credence.Pattern.NoListDeleteAtInLoop.md): Performance rule: Detects `List.delete_at/2` inside looping constructs
(`for`, `Enum.reduce`, `Enum.map`, `Enum.flat_map`) or recursive functions.
- [Credence.Pattern.NoListFold](Credence.Pattern.NoListFold.md): Detects usage of `List.foldl/3` and `List.foldr/3` and suggests
`Enum.reduce/3` instead.
- [Credence.Pattern.NoListToTupleForAccess](Credence.Pattern.NoListToTupleForAccess.md): Performance & style rule: Detects converting a list to a tuple via
`List.to_tuple/1` and then accessing elements with `elem/2`.
Tuples are meant for small, fixed-size collections. Copying a
dynamically-sized list into a tuple just for indexed access defeats the
purpose and allocates a full copy of the data. Use pattern matching
(`[a, b | _] = list`) or `Enum.at/2` on the list directly instead.
For string processing, use `binary_part/3` or binary pattern matching.
## Bad
    t = List.to_tuple(graphemes)
    first = elem(t, 0)
    last = elem(t, tuple_size(t) - 1)
## Good
    [first | _] = graphemes
    last = List.last(graphemes)
    # Or for indexed access on strings:
    <<first::utf8, _rest::binary>> = string

- [Credence.Pattern.NoManualEnumUniq](Credence.Pattern.NoManualEnumUniq.md): Performance and idiomatic code rule: warns when `Enum.uniq/1` is manually
reimplemented using `Enum.reduce/3` and `MapSet`.
- [Credence.Pattern.NoManualFrequencies](Credence.Pattern.NoManualFrequencies.md): Readability rule: Detects manual frequency counting with
`Enum.reduce(list, %{}, fn x, acc -> Map.update(acc, x, 1, ...) end)`.
- [Credence.Pattern.NoManualListLast](Credence.Pattern.NoManualListLast.md): Detects hand-rolled reimplementations of `List.last/1`.
- [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 nested
equivalent `Enum.join(Enum.reverse(String.graphemes(s)))`) which is a manual
reimplementation of `String.reverse/1`.
- [Credence.Pattern.NoMapAsSet](Credence.Pattern.NoMapAsSet.md): Style rule: Detects using a `Map` with boolean literal values (`true`/`false`)
purely for membership tracking, when `MapSet` is more appropriate.
- [Credence.Pattern.NoMapGetSentinel](Credence.Pattern.NoMapGetSentinel.md): Detects `Map.get(map, key, -1)` followed by a comparison against
the sentinel — a Python `dict.get(key, -1)` idiom that leaks into
LLM-generated Elixir.
- [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.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.NoMapKeysOrValuesForRawIteration](Credence.Pattern.NoMapKeysOrValuesForRawIteration.md): Detects `Map.values(map)` or `Map.keys(map)` passed directly into `Enum`
functions that return complex structures and **cannot** be safely auto-fixed.
- [Credence.Pattern.NoMapThenAggregate](Credence.Pattern.NoMapThenAggregate.md): Detects `Enum.map/2` immediately followed by a terminal aggregation
like `Enum.max/1`, `Enum.min/1`, or `Enum.sum/1`, which creates an
unnecessary intermediate list.
- [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.NoMultipleEnumAt](Credence.Pattern.NoMultipleEnumAt.md): Readability & performance rule: Detects multiple `Enum.at/2` calls on the
same variable with literal indices. Each `Enum.at/2` traverses the list
from the head, so N calls cost O(N × len). Pattern matching destructures
the list in a single pass.
- [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.NoNestedEnumOnSameEnumerableUnfixable](Credence.Pattern.NoNestedEnumOnSameEnumerableUnfixable.md): Detects nested `Enum.*` calls operating on the **same** enumerable
where the inner call **cannot** be safely auto-fixed.
- [Credence.Pattern.NoParamRebinding](Credence.Pattern.NoParamRebinding.md): Style & correctness rule: Detects rebinding of parameter names inside
anonymous function (`fn`) bodies.
When a variable from the parameter destructure is rebound inside the body,
readers lose track of which binding is "live" at each point. This is a
common source of subtle bugs, especially in `Enum.reduce` callbacks where
the accumulator is destructured.
- [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.NoRedundantAssignment](Credence.Pattern.NoRedundantAssignment.md): Detects a variable (or tuple/list of plain variables) being assigned and
immediately returned as the last two statements of a block.
- [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.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.NoRepeatedEnumTraversal](Credence.Pattern.NoRepeatedEnumTraversal.md): Performance rule: warns when the same variable is traversed multiple
times using different `Enum` functions.
- [Credence.Pattern.NoSortForTopK](Credence.Pattern.NoSortForTopK.md): Detects inefficient patterns where a full sort is performed only to
retrieve a single element (the minimum or maximum).
- [Credence.Pattern.NoSortForTopKReduce](Credence.Pattern.NoSortForTopKReduce.md): Detects inefficient patterns where a full sort is performed only to
retrieve a small number of elements (top-k) that cannot be reduced to
a single `Enum.min/1` or `Enum.max/1` call.
- [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 can be safely replaced with `Enum.min/1` or `Enum.max/1`,
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.NoSplitToCount](Credence.Pattern.NoSplitToCount.md): Detects `length(String.split(string, separator)) - 1` used to count
substring occurrences.
- [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.NoStringConcatInLoopComplex](Credence.Pattern.NoStringConcatInLoopComplex.md): Performance rule: Detects string concatenation with `<>` inside complex
looping constructs that cannot be safely auto-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.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.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.NoUnlessElse](Credence.Pattern.NoUnlessElse.md): Detects `unless ... do ... else ... end` — a style guide violation.
- [Credence.Pattern.NoUnnecessaryCatchAllRaise](Credence.Pattern.NoUnnecessaryCatchAllRaise.md): Detects function clauses where every argument is a wildcard and the
body does nothing but `raise`.
- [Credence.Pattern.NonGroupedClauses](Credence.Pattern.NonGroupedClauses.md): Fixes function clauses that are not grouped together.
- [Credence.Pattern.PreferDescSortOverNegativeTake](Credence.Pattern.PreferDescSortOverNegativeTake.md): Prefer `Enum.sort(nums, :desc) |> Enum.take(n)`
over `Enum.sort(nums) |> Enum.take(-n)`.
This is about readability and intent clarity, not performance.
- [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 and Intent rule: Flags usage of `Enum.drop/2` followed by `Enum.take/2`.
Calling `Enum.drop(list, start)` piped into `Enum.take(length)` is a verbose way
of slicing a collection. It can be confusing to read at a glance. Elixir provides
`Enum.slice/3`, which explicitly communicates the intent of extracting a sublist
and handles the operation cleanly.
- [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.PreferMapFetchOverHasKey](Credence.Pattern.PreferMapFetchOverHasKey.md): Detects `Map.has_key?/2` used in `if`/`cond` conditions, which typically
leads to a double map lookup — once to check existence, again to get
the value.
- [Credence.Pattern.RedundantListGuard](Credence.Pattern.RedundantListGuard.md): Detects redundant `is_list/1` guards on variables already bound by a
cons pattern `[head | tail]`).
- [Credence.Pattern.Rule](Credence.Pattern.Rule.md): Behaviour for pattern-level rules that detect and 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.UnnecessaryGraphemeChunking.Unfixable](Credence.Pattern.UnnecessaryGraphemeChunking.Unfixable.md): Detects inefficient string transformation pipelines that convert strings
to graphemes or codepoints, perform chunking or grouping, and reconstruct
strings from the result. These patterns cannot be automatically fixed.
- [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.Semantic](Credence.Semantic.md): Semantic phase — fixes compiler warnings.
- [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.Rule](Credence.Semantic.Rule.md): Behaviour for semantic-level rules that fix compiler warnings.
- [Credence.Semantic.UndefinedFunction](Credence.Semantic.UndefinedFunction.md): Fixes compiler warnings about undefined or deprecated functions with known replacements.
- [Credence.Semantic.UndefinedLocalFunction](Credence.Semantic.UndefinedLocalFunction.md): Fixes compiler errors about undefined local functions with known replacements.
- [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.FixDivRem](Credence.Syntax.FixDivRem.md): Fixes `div` and `rem` used as infix operators (Python `//` and `%` style).
- [Credence.Syntax.FixScientificNotation](Credence.Syntax.FixScientificNotation.md): Fixes Python-style scientific notation that is invalid in Elixir.
- [Credence.Syntax.Rule](Credence.Syntax.Rule.md): Behaviour for syntax-level rules that fix code which won't parse.

