mod call_graph;
mod navigation;
mod parse;
#[cfg(test)]
mod tests;
use std::collections::HashMap;
use std::fs;
use std::path::Path;
use protobuf::Message;
use scip::types::{self as scip_types, Index};
pub struct ScipBackend {
pub(super) documents: HashMap<String, scip_types::Document>,
pub(super) symbol_info: HashMap<String, scip_types::SymbolInformation>,
}
impl ScipBackend {
pub fn load(index_path: &Path) -> anyhow::Result<Self> {
let bytes = fs::read(index_path)?;
let index = Index::parse_from_bytes(&bytes)?;
let mut symbol_info = HashMap::new();
for info in index.external_symbols {
if !info.symbol.is_empty() {
symbol_info.insert(info.symbol.clone(), info);
}
}
let mut documents = HashMap::new();
for doc in index.documents {
for info in &doc.symbols {
if !info.symbol.is_empty() && !symbol_info.contains_key(&info.symbol) {
symbol_info.insert(info.symbol.clone(), info.clone());
}
}
let path = doc.relative_path.clone();
if !path.is_empty() {
documents.insert(path, doc);
}
}
Ok(Self {
documents,
symbol_info,
})
}
pub fn detect(project_root: &Path) -> Option<std::path::PathBuf> {
let candidates = [
project_root.join("index.scip"),
project_root.join(".scip").join("index.scip"),
project_root.join(".codelens").join("index.scip"),
];
candidates.into_iter().find(|p| p.is_file())
}
pub fn file_count(&self) -> usize {
self.documents.len()
}
pub fn symbol_count(&self) -> usize {
self.symbol_info.len()
}
}