impactsense_parser/
project.rs1use std::path::Path;
4
5use thiserror::Error;
6
7use crate::extract::{parse_files_to_ir, scan_and_build_ir, scan_and_build_ir_async, ExtractOptions};
8use crate::pipeline::ScanOptions;
9use crate::store::{GraphStore, InMemoryGraph, RefreshReport};
10
11#[derive(Debug, Error)]
12pub enum ProjectError {
13 #[error("scan/extract failed: {0}")]
14 Extract(#[from] crate::extract::ExtractError),
15}
16
17pub fn parse_project(root: &Path, scan: &ScanOptions) -> Result<InMemoryGraph, ProjectError> {
22 let extract_opts = ExtractOptions::from(&scan.graph);
23 let ir = scan_and_build_ir(root, &extract_opts, scan)?;
24 Ok(InMemoryGraph::from_ir(ir))
25}
26
27pub async fn parse_project_async(
29 root: &Path,
30 scan: &ScanOptions,
31) -> Result<InMemoryGraph, ProjectError> {
32 let extract_opts = ExtractOptions::from(&scan.graph);
33 let ir = scan_and_build_ir_async(root, &extract_opts, scan).await?;
34 Ok(InMemoryGraph::from_ir(ir))
35}
36
37pub fn refresh_files(
39 graph: &mut InMemoryGraph,
40 root: &Path,
41 cleanup_targets: &[String],
42 parse_targets: &[String],
43 scan: &ScanOptions,
44) -> Result<RefreshReport, ProjectError> {
45 let extract_opts = ExtractOptions::from(&scan.graph);
46
47 for path in cleanup_targets {
48 graph.remove_file(path);
49 }
50
51 let nodes_before = graph.node_count();
52 let edges_before = graph.edge_count();
53
54 if !parse_targets.is_empty() {
55 let delta = parse_files_to_ir(root, parse_targets, &extract_opts, scan)?;
56 graph.merge_ir(delta);
57 }
58
59 Ok(RefreshReport {
60 cleanup_targets: cleanup_targets.len(),
61 parse_targets: parse_targets.len(),
62 nodes_merged: graph.node_count().saturating_sub(nodes_before),
63 edges_merged: graph.edge_count().saturating_sub(edges_before),
64 })
65}