Credence.Pattern.Rule behaviour (credence v0.6.0)

Copy Markdown

Behaviour for pattern-level rules that detect and auto-fix anti-patterns.

Every Pattern rule fixes the issue it detects — there is no "warn-only" mode. Rules that could only detect but not fix were archived to docs/unfixable_rules/ and removed from compilation.

Interface

Three callbacks, all mandatory (only priority/0 has a default):

  • priority() :: integer() — fire order, lower runs first. Default 500.
  • check(ast, opts) :: [Issue.t()] — detect issues in the AST.
  • fix_patches(ast, opts) :: [patch] — emit byte-range patches that, when applied, resolve the issues check/2 reported. Empty list = no change.

Both callbacks receive Sourceror AST (Sourceror.parse_string!/1) and opts containing :source for rules that need raw source bytes.

Implementation choices for fix_patches/2

All rules return [patch], but the way they compute those patches varies with what the transformation needs:

  • AST-walkingCredence.RuleHelpers.patches_from_postwalk/2 handles rules whose fix is a single Macro.postwalk/2 matcher.
  • AST-with-restructuringCredence.RuleHelpers.patches_from_ast_transform/3 for fixes that prune, reorder, or insert siblings (the rendered result is re-parsed for clean range diffing).
  • Direct patch emission — a rule walks the AST itself and builds [%{range: Sourceror.Range, change: String.t()}] manually. Useful when the kept subtree's source bytes must be preserved verbatim (e.g. parens metadata Sourceror's renderer would drop) — slice the original source bytes for the kept range instead of re-rendering.

See each helper's docstring for the rule-side calling convention.

Summary

Types

A byte-range patch against the source string.

Callbacks

Detect issues in the AST. Returns list of issues.

Auto-fix via byte-range patches. Returns a list of patches; [] means no change.

Types

patch()

@type patch() :: %{range: map(), change: String.t()}

A byte-range patch against the source string.

  • range carries Sourceror-style start/end positions ([line: L, column: C]).
  • change is the replacement text. Apply via Sourceror.patch_string/2.

Callbacks

check(ast, opts)

@callback check(ast :: Macro.t(), opts :: keyword()) :: [Credence.Issue.t()]

Detect issues in the AST. Returns list of issues.

fix_patches(ast, opts)

@callback fix_patches(ast :: Macro.t(), opts :: keyword()) :: [patch()]

Auto-fix via byte-range patches. Returns a list of patches; [] means no change.

priority()

@callback priority() :: integer()