use std::path::Path;
use crate::bib::semantic::{BibFieldDb, Model};
use crate::bib::syntax::{SyntaxElement, SyntaxKind, SyntaxNode};
use crate::linter::diagnostic::{Diagnostic, Severity};
pub mod duplicate_field;
pub mod duplicate_key;
pub mod edits;
pub mod empty_field;
pub mod encoding_hints;
pub mod missing_required_field;
pub mod title_capitalization;
pub mod undefined_string;
pub mod unknown_field;
pub mod unused_string;
pub use duplicate_field::DuplicateField;
pub use duplicate_key::DuplicateKey;
pub use empty_field::EmptyField;
pub use encoding_hints::EncodingHints;
pub use missing_required_field::MissingRequiredField;
pub use title_capitalization::TitleCapitalization;
pub use undefined_string::UndefinedString;
pub use unknown_field::UnknownField;
pub use unused_string::UnusedString;
pub struct BibRuleContext<'a> {
pub path: &'a Path,
pub root: &'a SyntaxNode,
pub model: &'a Model,
pub db: &'a BibFieldDb,
}
pub trait BibRule: Send + Sync {
fn id(&self) -> &'static str;
fn default_severity(&self) -> Severity {
Severity::Warning
}
fn interests(&self) -> &'static [SyntaxKind] {
&[]
}
fn check(&self, el: &SyntaxElement, ctx: &BibRuleContext<'_>, sink: &mut Vec<Diagnostic>) {
let _ = (el, ctx, sink);
}
fn check_file(&self, ctx: &BibRuleContext<'_>, sink: &mut Vec<Diagnostic>) {
let _ = (ctx, sink);
}
}
pub fn all_rules() -> Vec<Box<dyn BibRule>> {
vec![
Box::new(DuplicateKey),
Box::new(MissingRequiredField),
Box::new(UnknownField),
Box::new(EmptyField),
Box::new(DuplicateField),
Box::new(UnusedString),
Box::new(UndefinedString),
Box::new(TitleCapitalization),
Box::new(EncodingHints),
]
}
pub const ALL_BIB_RULE_IDS: &[&str] = &[
"duplicate-key",
"missing-required-field",
"unknown-field",
"empty-field",
"duplicate-field",
"unused-string",
"undefined-string",
"title-capitalization",
"encoding-hints",
];
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn registry_and_id_list_agree() {
let ids: Vec<&str> = all_rules().iter().map(|r| r.id()).collect();
assert_eq!(ids, ALL_BIB_RULE_IDS);
}
}