Lint
is the linter's core: the rule registry, the AST walker, and the
public entry points (lint, lint-with, lint-source,
lint-source-with). Plugin authors interact with it via
register-rule!. See
WRITING-RULES.md
for the rule-author guide.
lint
(Fn [(Ref (Array (Box Located)) a)] (Array Diagnostic))
(lint forms)
applies every registered rule to every node in forms,
recursing into compound forms. Returns one Diagnostic per finding.
lint-source
(Fn [(Ref String a)] (Result (Array Diagnostic) ParseErr))
(lint-source src)
parses src via Reader.parse and lints with
every registered rule. Returns (Result (Array Diagnostic) ParseErr)
so a parse failure surfaces distinctly from a clean parse with
diagnostics.
lint-source-with
(Fn [(Ref (Fn [(Ref String StaticLifetime)] Bool) a), (Ref String b)] (Result (Array Diagnostic) ParseErr))
(lint-source-with keep? src)
like lint-source, but only runs rules whose
names satisfy keep?.
lint-with
(Fn [(Ref (Fn [(Ref String StaticLifetime)] Bool) a), (Ref (Array (Box Located)) b)] (Array Diagnostic))
(lint-with keep? forms)
like lint, but only runs rules whose names satisfy
keep?.
list-rules
(Fn [] (Array Rule))
(list-rules)
returns a copy of the currently registered rule
registry. Useful for angler --list-rules and for plugins that want
to inspect the active rule set.
lst-head?
(Fn [(Ref Form a), (Ref String b)] Bool)
(lst-head? f name)
true iff f is (Form.Lst …) whose first child is
a Form.Sym matching name.
nth-form
(Fn [(Ref (Array (Box Located)) a), Int] (Ref Form a))
(nth-form items i)
pulls the Form out of the i-th Located child of
an Array (Box Located). Most rules want the structural shape, not
the position, when descending into a compound form's children.
register-rule!
(Fn [String, String, (Fn [(Ref Located a)] (Maybe Diagnostic))] ())
(register-rule! name description fn)
registers a rule under name with a one-line
description. Subsequent runs of Lint.lint / Lint.lint-source
include it. Built-ins call this at load time; plugins do the same
after loading angler.
Caveat: Carp initializes global defs in dependency-graph order,
not in textual or load order. If your plugin uses a top-level def
to call register-rule!, its slot in the registry — and therefore
its slot in the diagnostic output for any one form — is unspecified
relative to angler's built-ins. Rule firing is still correct;
only the order of diagnostics on a single node varies. If you need
strict ordering, register from main instead of from a top-level
def.
sym?
(Fn [(Ref Form a), (Ref String b)] Bool)
(sym? f name)
true iff f is a Form.Sym whose dotted name equals
name. name may itself contain . to match a multi-segment
symbol — e.g. (sym? f "Parser.try") matches Parser.try.