Packages

Custom Credo checks targeting anti-patterns LLMs commonly generate: wasteful Enum chains, with-macro misuse, broad typespecs, inline regex, telemetry control flow, unsupervised spawns, and more.

Current section

Files

Jump to
forge_credo_checks lib forge_credo_checks.ex
Raw

lib/forge_credo_checks.ex

defmodule ForgeCredoChecks do
@moduledoc """
Custom Credo checks targeting anti-patterns that LLMs commonly produce.
Stock Credo ships checks for `filter |> filter`, `reject |> reject`,
`map |> join`, `map |> into`, etc. but not the cases where one operation
composes with the *complementary* one, nor the common map-building,
sort-then-pick, and map-shape normalization anti-patterns. These checks fill
those gaps.
## Two-pass Enum chains (suggests `Enum.reduce/3`)
* `ForgeCredoChecks.FilterMap`: `Enum.filter |> Enum.map`
* `ForgeCredoChecks.RejectMap`: `Enum.reject |> Enum.map`
* `ForgeCredoChecks.MapReject`: `Enum.map |> Enum.reject`
* `ForgeCredoChecks.MapRejectNil`: `Enum.map |> Enum.reject(&is_nil/1)`
## Hand-rolled map building (suggests `Map.new/2`)
* `ForgeCredoChecks.MapNewFromInto`: `Enum.into(%{}, fn ...)`
* `ForgeCredoChecks.MapNewFromReduce`: `Enum.reduce(_, %{}, &Map.put(acc, k, v))`
## Wasteful list-extremum patterns
* `ForgeCredoChecks.ReverseListFirst`: `xs |> Enum.reverse() |> List.first()` becomes `List.last(xs)`
* `ForgeCredoChecks.SortListFirst`: `Enum.sort \\| List.first` becomes `Enum.min`/`Enum.max`/`*_by`
## Map shape normalization
* `ForgeCredoChecks.MapGetWithOr`: `Map.get(_, _) || fallback`
* `ForgeCredoChecks.ChainedMapGet`: `Map.get(_, _) || Map.get(_, _)`
## LLM tells
* `ForgeCredoChecks.NoInlineRegex`: inline `~r`/`~R` regex sigils inside function bodies
* `ForgeCredoChecks.NoAnyOrTermTypes`: `any()` / `term()` in specs, callbacks, and type definitions
* `ForgeCredoChecks.MultilineStringConcat`: multi-line string-literal `<>` concatenation (use a heredoc)
## Architecture and test discipline
* `ForgeCredoChecks.OneModulePerFile`: every `defmodule` after the first in a source file (test files excluded by default)
* `ForgeCredoChecks.TaintedSourceInspection`: source-grep constructs applied to text read from non-test `.ex` / `.exs` files
* `ForgeCredoChecks.TimingAndPrivateStateGuard`: `Process.sleep/1` and `:sys.replace_state/2` call nodes
* `ForgeCredoChecks.NoApplicationGetEnvInLib`: `Application.get_env/2,3` inside `lib/` (use `compile_env` or `fetch_env!` instead)
* `ForgeCredoChecks.TelemetryControlFlow`: `:telemetry.attach`/`attach_many` with an inline handler that performs control flow (`send`, `GenServer.call`/`cast`) instead of observation-only recording
"""
end