use anyhow::{Context, Result};
use serde_json;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::{Path, PathBuf};
use super::schema::{PackageData, Vertex};
pub fn import_lsif(lsif_path: &Path) -> Result<ImportedPackage> {
let file = File::open(lsif_path)
.with_context(|| format!("Failed to open LSIF file: {:?}", lsif_path))?;
let reader = BufReader::new(file);
let mut package_info: Option<PackageData> = None;
let mut symbol_count = 0usize;
let mut document_count = 0usize;
for line in reader.lines() {
let line = line?;
if line.trim().is_empty() {
continue;
}
if let Ok(vertex) = serde_json::from_str::<Vertex>(&line) {
match vertex {
Vertex::Package { data, .. } => {
package_info = Some(data);
}
Vertex::Document { .. } => {
document_count += 1;
}
Vertex::Symbol { .. } => {
symbol_count += 1;
}
_ => {}
}
}
}
let package =
package_info.ok_or_else(|| anyhow::anyhow!("No package information found in LSIF file"))?;
Ok(ImportedPackage {
package,
symbol_count,
document_count,
source_path: lsif_path.to_path_buf(),
})
}
#[derive(Debug, Clone)]
pub struct ImportedPackage {
pub package: PackageData,
pub symbol_count: usize,
pub document_count: usize,
pub source_path: PathBuf,
}
pub fn import_lsif_directory(lsif_dir: &Path) -> Result<Vec<ImportedPackage>> {
let mut packages = Vec::new();
if !lsif_dir.exists() {
return Ok(packages);
}
for entry in std::fs::read_dir(lsif_dir)? {
let entry = entry?;
let path = entry.path();
if path.extension().and_then(|e| e.to_str()) == Some("lsif") {
match import_lsif(&path) {
Ok(pkg) => packages.push(pkg),
Err(e) => eprintln!("Warning: Failed to import {:?}: {}", path, e),
}
}
}
Ok(packages)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::graph::CodeGraph;
use crate::lsif::export::export_lsif;
use tempfile::TempDir;
#[test]
fn test_import_lsif_basic() {
let temp_dir = TempDir::new().unwrap();
let db_path = temp_dir.path().join("test.db");
let lsif_path = temp_dir.path().join("test.lsif");
let mut graph = CodeGraph::open(&db_path).unwrap();
let test_file = temp_dir.path().join("test.rs");
std::fs::write(&test_file, "fn main() {}").unwrap();
let _ = graph.scan_directory(temp_dir.path(), None);
let _ = export_lsif(&mut graph, &lsif_path, "test-crate", "0.1.0");
let result = import_lsif(&lsif_path);
assert!(result.is_ok());
let pkg = result.unwrap();
assert_eq!(pkg.package.name, "test-crate");
assert_eq!(pkg.package.version, "0.1.0");
assert!(pkg.symbol_count >= 1);
}
#[test]
fn test_import_lsif_directory() {
let temp_dir = TempDir::new().unwrap();
let db_path = temp_dir.path().join("test.db");
let lsif_path = temp_dir.path().join("test.lsif");
let mut graph = CodeGraph::open(&db_path).unwrap();
let test_file = temp_dir.path().join("test.rs");
std::fs::write(&test_file, "fn main() {}").unwrap();
let _ = graph.scan_directory(temp_dir.path(), None);
let _ = export_lsif(&mut graph, &lsif_path, "test-crate", "0.1.0");
let result = import_lsif_directory(temp_dir.path());
assert!(result.is_ok());
assert_eq!(result.unwrap().len(), 1);
}
}