use crate::semantic::adapters;
use crate::semantic::graphs::ReferenceIndex;
use crate::semantic::symbol_table::SymbolTable;
use crate::semantic::workspace::WorkspaceFile;
use crate::syntax::SyntaxFile;
use std::collections::HashMap;
use std::path::PathBuf;
pub struct WorkspacePopulator<'a> {
files: &'a HashMap<PathBuf, WorkspaceFile<SyntaxFile>>,
symbol_table: &'a mut SymbolTable,
reference_index: &'a mut ReferenceIndex,
}
impl<'a> WorkspacePopulator<'a> {
pub fn new(
files: &'a HashMap<PathBuf, WorkspaceFile<SyntaxFile>>,
symbol_table: &'a mut SymbolTable,
reference_index: &'a mut ReferenceIndex,
) -> Self {
Self {
files,
symbol_table,
reference_index,
}
}
pub fn populate_all(&mut self) -> Result<Vec<PathBuf>, String> {
let paths = Self::get_sorted_paths(self.files);
for path in &paths {
if let Err(_e) = self.populate_file(path) {
}
}
Ok(paths)
}
pub fn populate_affected(&mut self) -> Result<Vec<PathBuf>, String> {
let unpopulated = Self::get_unpopulated_paths(self.files);
for path in &unpopulated {
if let Err(_e) = self.populate_file(path) {
}
}
Ok(unpopulated)
}
pub fn populate_file(&mut self, path: &PathBuf) -> Result<(), String> {
let content = self
.files
.get(path)
.map(|f| f.content().clone())
.ok_or_else(|| format!("File not found in workspace: {}", path.display()))?;
let file_path_str = path.to_string_lossy().to_string();
self.reference_index
.remove_references_from_file(&file_path_str);
self.symbol_table.remove_imports_from_file(&file_path_str);
self.symbol_table.remove_symbols_from_file(&file_path_str);
self.symbol_table
.set_current_file(Some(file_path_str.clone()));
adapters::populate_syntax_file(&content, self.symbol_table, self.reference_index)
.map_err(|errors| format!("Failed to populate {file_path_str}: {errors:?}"))
}
fn get_sorted_paths(files: &HashMap<PathBuf, WorkspaceFile<SyntaxFile>>) -> Vec<PathBuf> {
let mut paths: Vec<_> = files.keys().cloned().collect();
paths.sort();
paths
}
fn get_unpopulated_paths(files: &HashMap<PathBuf, WorkspaceFile<SyntaxFile>>) -> Vec<PathBuf> {
let mut unpopulated: Vec<_> = files
.keys()
.filter(|path| !files[*path].is_populated())
.cloned()
.collect();
unpopulated.sort();
unpopulated
}
}