use dashmap::DashMap;
use parking_lot::RwLock;
use std::collections::{HashMap, HashSet};
use std::sync::Arc;
#[derive(Debug, Clone)]
pub struct ChangeSet {
pub changed_files: HashSet<std::path::PathBuf>,
pub changed_symbols: HashSet<crate::salsa_full::Symbol>,
pub change_type: ChangeType,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ChangeType {
FileContent,
FileAdded,
FileDeleted,
SymbolModified,
}
pub struct DependencyGraph {
file_to_symbols: DashMap<std::path::PathBuf, HashSet<String>>,
symbol_dependents: DashMap<String, HashSet<std::path::PathBuf>>,
file_imports: DashMap<std::path::PathBuf, HashSet<std::path::PathBuf>>,
}
impl DependencyGraph {
pub fn new() -> Self {
Self {
file_to_symbols: DashMap::new(),
symbol_dependents: DashMap::new(),
file_imports: DashMap::new(),
}
}
pub fn register_symbol(&self, file: &std::path::PathBuf, symbol: String) {
self.file_to_symbols
.entry(file.clone())
.or_default()
.insert(symbol);
}
pub fn add_dependency(&self, from: &std::path::PathBuf, symbol: &str) {
self.symbol_dependents
.entry(symbol.to_string())
.or_default()
.insert(from.clone());
}
pub fn affected_files(&self, changes: &ChangeSet) -> HashSet<std::path::PathBuf> {
let mut affected = HashSet::new();
let mut queue: Vec<_> = changes.changed_files.iter().cloned().collect();
while let Some(file) = queue.pop() {
if affected.contains(&file) {
continue;
}
affected.insert(file.clone());
if let Some(dependents) = self.file_imports.get(&file) {
for dep in dependents.iter() {
if !affected.contains(dep) {
queue.push(dep.clone());
}
}
}
}
affected
}
}
impl Default for DependencyGraph {
fn default() -> Self {
Self::new()
}
}
pub struct IncrementalProcessor {
graph: Arc<DependencyGraph>,
cache: DashMap<String, Arc<str>>,
}
impl IncrementalProcessor {
pub fn new(graph: Arc<DependencyGraph>) -> Self {
Self {
graph,
cache: DashMap::new(),
}
}
pub fn process_changes(&self, changes: ChangeSet) -> Vec<String> {
use rayon::prelude::*;
let affected = self.graph.affected_files(&changes);
affected
.into_par_iter()
.map(|file| format!("Processed: {:?}", file))
.collect()
}
}