harn-rules
The declarative structural rule engine for Harn — the Rust core behind
harn rules / lint / codemod surfaces. Part of the
Rule Engine program
(Epic A, harn#2827).
A rule says what to match and optionally how to rewrite it. The
engine compiles the rule against the tree-sitter machinery in harn-hostlib
and produces matches with metavariable bindings — the structural complement
to regex/glob search.
This crate ships the atomic matching tier
(harn#2832). Relational /
composite matching (#2833) and where / transform / fix interpolation
(#2834) build on it.
Rule shape (TOML)
= "destructure-with-defaults"
= "typescript"
= "warning" # info | warning (default) | error
= "Collapse `?.x ?? default`"
= "{ $KEY: $SRC }" # presence makes the rule a codemod
[] # the matcher block — keep it LAST
= "$SRC?.$KEY ?? $DEFAULT" # one of: pattern | kind | regex
Key ordering: because
[rule]opens a TOML table, every scalar field (id,language,severity,message,fix) must appear before it.
A rule's kind is derived from its shape: a fix makes it a codemod; a
message with no fix makes it a lint; a bare matcher is a search.
Atomic matcher forms
pattern— a code snippet in the target grammar with$VARmetavariable holes. Compiled to a tree-sitter query: each$VARbecomes a capture, the snippet's operators/keywords are matched literally (so??≠||), and a repeated$VARunifies (must bind identical text). Variadic$$$holes land with the relational tier (#2833).kind— a bare tree-sitter node kind (e.g."call_expression").regex— a regular expression over the source text.
Usage
use ;
let rule = from_toml_str?;
let compiled = compile?;
for m in compiled.run?
Load from disk with load_rule_file(path) or load_rule_dir(dir).