API Reference credence v#0.2.0
Copy MarkdownModules
Credence (Semantic Linter for Elixir) Main entry point for analyzing Elixir code.
Defines the structured issue format for any rule violations.
Behaviour for all Credence semantic rules.
Performance rule: warns when String.graphemes/1 |> Enum.count() is used.
Performance rule: warns when String.graphemes/1 |> length() is used.
Maintainability rule: Flags single-letter variable names in function signatures.
Detects functions where the same positional parameter uses different variable names across clauses.
Readability rule: Detects anonymous functions applied with .() inside
a pipeline.
Detects patterns where a list is destructured into individual variables and then immediately reassembled into the same list.
Style rule: Detects @doc false placed before private functions (defp).
Performance rule: Detects sorting the same list twice — once ascending and
once descending — when a single sort plus Enum.reverse/1 would suffice.
Performance rule: Detects Enum.with_index/1 passed directly as the
enumerable argument to Enum.reduce/3 (or piped into it).
Performance rule: Flags potential binary search patterns using Enum.at/2.
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.
Performance heuristic rule: warns when Enum.at/2 is used inside loops.
Detects Enum.count/1 (without a predicate) and suggests length/1
or a more specific size function.
Performance rule: Detects Enum.drop(list, -n) where n is a positive
integer literal.
Performance rule: Detects Enum.take(list, -n) where n is a positive
integer literal.
Strict semantic rule: Flags ONLY explicit max-reduction patterns inside Enum.reduce/3.
Flags explicit min-reduction patterns inside Enum.reduce/3.
Flags explicit sum-reduction patterns inside Enum.reduce/3.
Readability & performance rule: Detects the pattern of decomposing a string
into graphemes or a charlist, only to compare it with its own Enum.reverse.
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.
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.
Style rule: Detects functions named with an is_ prefix that are not
guard-safe BIFs.
Detects def/defp functions with an is_ prefix, which in Elixir
is reserved for guard-safe functions defined with defguard.
Idiomatic rule: warns when variables shadow Kernel functions.
Performance rule: Detects the use of length/1 inside guard clauses (when).
Performance rule: Detects the use of ++ inside looping constructs
(Enum.reduce, for comprehensions) and inside recursive functions.
Performance rule: Detects List.delete_at/2 inside looping constructs
(for, Enum.reduce, Enum.map, Enum.flat_map) or recursive functions.
Detects usage of List.foldl/3 and List.foldr/3 and suggests
Enum.reduce/3 instead.
Performance rule: Flags usage of List.last/1.
Performance & style rule: Detects converting a list to a tuple via
List.to_tuple/1 and then accessing elements with elem/2.
Performance and idiomatic code rule: warns when Enum.uniq/1 is manually
reimplemented using Enum.reduce/3 and MapSet.
Readability rule: Detects manual frequency counting with
Enum.reduce(list, %{}, fn x, acc -> Map.update(acc, x, 1, ...) end).
Detects hand-rolled reimplementations of List.last/1.
Detects if expressions that manually reimplement Kernel.max/2.
Detects if expressions that manually reimplement Kernel.min/2.
Readability & performance rule: Detects the pattern
String.graphemes(s) |> Enum.reverse() |> Enum.join() which is a manual
reimplementation of String.reverse/1.
Detects Map.keys(var) piped into an Enum function whose callback
also looks up values from the same map variable.
Performance rule: Detects Map.values(map) or Map.keys(map) passed
directly into an Enum function, which creates an unnecessary intermediate
list.
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.
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.
Style & correctness rule: Detects rebinding of parameter names inside
anonymous function (fn) bodies.
Readability rule: Detects Enum.join("") where the empty-string separator
is passed explicitly.
Detects guard clauses that are logically redundant because a preceding clause of the same function already handles the complementary case.
Detects inefficient patterns where a full sort is performed only to retrieve a small number of elements (top-k).
Performance rule: Detects sorting an entire list only to retrieve a single
element by index via Enum.at/2.
Performance & readability rule: Detects the pattern of calling Enum.sort/1
followed by Enum.reverse/1 on the result.
Performance rule: Detects string concatenation with <> inside looping
constructs (Enum.reduce, Enum.reduce_while, for comprehensions) or
recursive functions.
Performance rule: Detects String.length(x) == 1 (or != 1) used to
validate that a string is a single character.
Detects Enum.take_while/2 piped into length/1 or Enum.count/1,
which materializes an intermediate list only to count it.
Detects function names that use a leading underscore to indicate privacy, a convention borrowed from Python that is non-idiomatic in Elixir.
Detects function clauses where every argument is a wildcard and the
body does nothing but raise.
Prefer Enum.sort(nums, :desc) |> Enum.take(n)
over Enum.sort(nums) |> Enum.take(-n).
Performance rule: Flags Enum.reverse(list) ++ other_list.
Readability and Intent rule: Flags usage of Enum.drop/2 followed by Enum.take/2.
Detects redundant is_list/1 guards on variables already bound by a
cons pattern ([head | tail]).
Detects inefficient string transformation pipelines that
Detects Enum.map/2 chained into Enum.join/1 or Enum.join/2,
and suggests Enum.map_join/3 instead.