use std::collections::HashSet;
use crate::config::Config;
use crate::linter::diagnostics::Diagnostic;
use crate::linter::index::LintIndex;
use crate::syntax::{SyntaxKind, SyntaxNode, SyntaxToken};
pub mod adjacent_footnote_refs;
pub mod chunk_label_spaces;
pub mod citation_keys;
pub mod crossref_as_link_target;
pub mod duplicate_references;
pub mod emoji_aliases;
pub mod empty_list_item;
pub mod figure_crossref_captions;
pub mod footnote_ref_in_footnote_def;
pub mod heading_eaten_attrs;
pub mod heading_hierarchy;
pub mod heading_strip_comments_residue;
pub mod html_entities;
pub mod link_text_is_url;
pub mod math_content;
pub mod missing_chunk_labels;
pub mod stray_fenced_div_markers;
pub mod undefined_anchor;
pub mod undefined_references;
pub mod unused_definitions;
pub trait Rule {
fn name(&self) -> &str;
fn node_interests(&self) -> &'static [SyntaxKind] {
&[]
}
fn wants_text_tokens(&self) -> bool {
false
}
fn check(&self, cx: &LintContext) -> Vec<Diagnostic>;
fn check_tree(
&self,
tree: &SyntaxNode,
input: &str,
config: &Config,
metadata: Option<&crate::metadata::DocumentMetadata>,
) -> Vec<Diagnostic> {
let want_kinds: HashSet<SyntaxKind> = self.node_interests().iter().copied().collect();
let index = LintIndex::build(tree, &want_kinds, self.wants_text_tokens());
let cx = LintContext {
tree,
input,
config,
metadata,
index: &index,
};
self.check(&cx)
}
}
pub struct LintContext<'a> {
pub tree: &'a SyntaxNode,
pub input: &'a str,
pub config: &'a Config,
pub metadata: Option<&'a crate::metadata::DocumentMetadata>,
pub index: &'a LintIndex,
}
impl LintContext<'_> {
pub fn nodes(&self, kind: SyntaxKind) -> &[SyntaxNode] {
self.index.nodes(kind)
}
pub fn text_tokens(&self) -> &[SyntaxToken] {
self.index.text_tokens()
}
}
pub struct RuleRegistry {
rules: Vec<Box<dyn Rule>>,
}
impl RuleRegistry {
pub fn new() -> Self {
Self { rules: Vec::new() }
}
pub fn register(&mut self, rule: Box<dyn Rule>) {
self.rules.push(rule);
}
pub fn rules(&self) -> &[Box<dyn Rule>] {
&self.rules
}
}
impl Default for RuleRegistry {
fn default() -> Self {
Self::new()
}
}