Expand description
§harn-rules
The declarative structural rule engine for Harn — the Rust core that
powers harn rules / lint / codemod surfaces. A rule describes
what to match (a pattern snippet, a node kind, or a regex) and
optionally how to rewrite it (a fix); the engine compiles that rule
against the tree-sitter machinery in harn_hostlib::ast and produces
RuleMatches with metavariable bindings.
This crate delivers the atomic matching tier (#2832), the relational + composite algebra (#2833), the predicate + rewrite layer (#2834), and the safety + idempotency gate (#2835):
model— the serde rule data model: the recursiveRuleNode(atomicpattern/kind/regex, relationalinside/has/follows/precedes, compositeall/any/not/matches) pluswhere/transform/fixandutils.pattern— the snippet → tree-sitter-query compiler ($VARmetavariable lifting, unification, literal patterns, and typed$VAR:kindplaceholders).evaluator— the tree-walking match algebra (relational + composite- utility-rule reuse).
constraint—wherepredicates on captured metavars (regex, comparison, recursive sub-pattern, and Harn-only semantic filters).transform— synthesize new metavars (replace/substring/convert) before fixing.fix—fixtemplate interpolation and format-preserving splice.engine— compile aRule, run it to produce matches,CompiledRule::apply/CompiledRule::auto_apply/CompiledRule::apply_checkeda codemod (safety-gated, idempotency checked), and emitDiagnostics.recipe— the whole-project scan → accumulate → edit lifecycle, with file create/delete (ScanningRecipe,run_recipe).report— report-onlyDataTables: columnar findings + metrics.loader— load rules from a TOML file or a directory.- semantic capture metadata — Harn captures gain resolved binding identity and simple static type labels when the local syntax provides them.
The whole-project scan lifecycle (#2836) layers onto this surface.
use harn_rules::{Rule, CompiledRule};
let rule = Rule::from_toml_str(
r#"
id = "destructure-default"
language = "typescript"
fix = "{ $KEY: $SRC }"
[rule]
pattern = "$SRC?.$KEY ?? $DEFAULT"
"#,
).unwrap();
let compiled = CompiledRule::compile(&rule).unwrap();
let matches = compiled.run("const a = cfg?.timeout ?? 30;").unwrap();
assert_eq!(matches[0].bindings["KEY"].text, "timeout");Re-exports§
pub use engine::Binding;pub use engine::BindingMetadata;pub use engine::CodemodResult;pub use engine::CompiledRule;pub use engine::Diagnostic;pub use engine::ResolvedBinding;pub use engine::RuleMatch;pub use engine::Span;pub use error::RulesError;pub use fix::interpolate;pub use fix::AppliedEdit;pub use loader::load_rule_dir;pub use loader::load_rule_file;pub use model::Applicability;pub use model::AtomicMatcher;pub use model::Comparison;pub use model::Constraint;pub use model::ConvertOp;pub use model::ResolvedBindingConstraint;pub use model::Rule;pub use model::RuleKind;pub use model::RuleNode;pub use model::Safety;pub use model::Severity;pub use model::StopBy;pub use model::StopKeyword;pub use model::Transform;pub use pattern::compile_pattern;pub use pattern::CompiledPattern;pub use recipe::run_recipe;pub use recipe::FileChange;pub use recipe::RecipeRun;pub use recipe::RuleRecipe;pub use recipe::ScanningRecipe;pub use recipe::SourceFile;pub use report::data_table;pub use report::DataTable;pub use report::TableRow;pub use report::TableSummary;pub use testing::run_inline_test;pub use testing::Expectation;pub use testing::FailureKind;pub use testing::InlineTestReport;pub use testing::TestFailure;
Modules§
- constraint
whereconstraints: predicates on captured metavars (Semgrepmetavariable-regex/metavariable-comparison/metavariable-pattern).- engine
- Compile a
Ruleinto a runnable matcher and run it against source. - error
- Error type for the rule engine.
- evaluator
- The relational + composite matching algebra (#2833).
- fix
fixtemplate interpolation and application.- fold
- Fold consecutive destructure-with-defaults runs (#2824).
- loader
- Load rules from disk: a single TOML rule file, or a directory of them.
- model
- The declarative rule data model.
- pattern
- The pattern compiler: a code snippet with metavariable holes → a tree-sitter query.
- recipe
- Whole-project scan → accumulate → edit lifecycle (#2836).
- report
- Data tables — rules emit structured findings/metrics (#2837).
- testing
- A small rule-test harness (#2842).
- transform
- The
transformpipeline: synthesize new metavars from captured ones beforefixinterpolation (ast-greptransform:).