use std::collections::HashMap;
use tree_sitter::Node;
use crate::cop::{Cop, CopConfig};
use crate::correction::Correction;
use crate::diagnostic::Diagnostic;
use crate::parse::source::SourceFile;
pub struct BatchedWalker<'a> {
cops: Vec<&'a dyn Cop>,
configs: Vec<&'a CopConfig>,
kinds: HashMap<&'static str, Vec<usize>>,
}
impl<'a> BatchedWalker<'a> {
pub fn new(cops: Vec<&'a dyn Cop>, configs: Vec<&'a CopConfig>) -> Self {
let mut kinds: HashMap<&'static str, Vec<usize>> = HashMap::new();
for (i, cop) in cops.iter().enumerate() {
for &k in cop.interested_node_kinds() {
kinds.entry(k).or_default().push(i);
}
}
Self {
cops,
configs,
kinds,
}
}
pub fn walk(
&self,
source: &SourceFile,
root: Node<'_>,
diagnostics: &mut Vec<Diagnostic>,
mut corrections: Option<&mut Vec<Correction>>,
) {
self.visit(source, root, diagnostics, &mut corrections);
}
fn visit(
&self,
source: &SourceFile,
node: Node<'_>,
diagnostics: &mut Vec<Diagnostic>,
corrections: &mut Option<&mut Vec<Correction>>,
) {
if node.is_named() {
let kind = node.kind();
if let Some(idxs) = self.kinds.get(kind) {
for &i in idxs {
self.cops[i].check_node(
source,
node,
self.configs[i],
diagnostics,
corrections.as_deref_mut(),
);
}
}
}
let mut cursor = node.walk();
for child in node.children(&mut cursor) {
self.visit(source, child, diagnostics, corrections);
}
}
}