harn_rules/lib.rs
1//! # harn-rules
2//!
3//! The declarative structural rule engine for Harn — the Rust core that
4//! powers `harn rules` / lint / codemod surfaces. A **rule** describes
5//! *what to match* (a pattern snippet, a node kind, or a regex) and
6//! optionally *how to rewrite* it (a `fix`); the engine compiles that rule
7//! against the tree-sitter machinery in [`harn_hostlib::ast`] and produces
8//! [`RuleMatch`]es with metavariable bindings.
9//!
10//! This crate delivers the **atomic matching tier** (#2832), the
11//! **relational + composite algebra** (#2833), the **predicate + rewrite
12//! layer** (#2834), and the **safety + idempotency gate** (#2835):
13//!
14//! - [`model`] — the serde rule data model: the recursive [`RuleNode`]
15//! (atomic `pattern` / `kind` / `regex`, relational `inside` / `has` /
16//! `follows` / `precedes`, composite `all` / `any` / `not` / `matches`)
17//! plus `where` / `transform` / `fix` and `utils`.
18//! - [`pattern`] — the snippet → tree-sitter-query compiler (`$VAR`
19//! metavariable lifting, unification, literal patterns).
20//! - [`evaluator`] — the tree-walking match algebra (relational + composite
21//! + utility-rule reuse).
22//! - [`constraint`] — `where` predicates on captured metavars (regex,
23//! comparison, recursive sub-pattern).
24//! - [`transform`] — synthesize new metavars (`replace` / `substring` /
25//! `convert`) before fixing.
26//! - [`fix`] — `fix` template interpolation and format-preserving splice.
27//! - [`engine`] — compile a [`Rule`], run it to produce matches,
28//! [`CompiledRule::apply`] / [`CompiledRule::auto_apply`] /
29//! [`CompiledRule::apply_checked`] a codemod (safety-gated, idempotency
30//! checked), and emit [`Diagnostic`]s.
31//! - [`recipe`] — the whole-project scan → accumulate → edit lifecycle,
32//! with file create/delete ([`ScanningRecipe`], [`run_recipe`]).
33//! - [`report`] — report-only [`DataTable`]s: columnar findings + metrics.
34//! - [`loader`] — load rules from a TOML file or a directory.
35//!
36//! The whole-project scan lifecycle (#2836) layers onto this surface.
37//!
38//! ```
39//! use harn_rules::{Rule, CompiledRule};
40//!
41//! let rule = Rule::from_toml_str(
42//! r#"
43//! id = "destructure-default"
44//! language = "typescript"
45//! fix = "{ $KEY: $SRC }"
46//! [rule]
47//! pattern = "$SRC?.$KEY ?? $DEFAULT"
48//! "#,
49//! ).unwrap();
50//! let compiled = CompiledRule::compile(&rule).unwrap();
51//! let matches = compiled.run("const a = cfg?.timeout ?? 30;").unwrap();
52//! assert_eq!(matches[0].bindings["KEY"].text, "timeout");
53//! ```
54
55#![forbid(unsafe_code)]
56
57pub mod constraint;
58pub mod engine;
59pub mod error;
60pub mod evaluator;
61pub mod fix;
62pub mod loader;
63pub mod model;
64pub mod pattern;
65pub mod recipe;
66pub mod report;
67pub mod transform;
68
69pub use engine::{Binding, CodemodResult, CompiledRule, Diagnostic, RuleMatch, Span};
70pub use error::RulesError;
71pub use fix::{interpolate, AppliedEdit};
72pub use loader::{load_rule_dir, load_rule_file};
73pub use model::{
74 Applicability, AtomicMatcher, Comparison, Constraint, ConvertOp, Rule, RuleKind, RuleNode,
75 Safety, Severity, StopBy, StopKeyword, Transform,
76};
77pub use pattern::{compile_pattern, CompiledPattern};
78pub use recipe::{run_recipe, FileChange, RecipeRun, RuleRecipe, ScanningRecipe, SourceFile};
79pub use report::{data_table, DataTable, TableRow, TableSummary};