Skip to main content

meta_ast/
pipeline.rs

1use std::path::Path;
2use std::sync::Arc;
3
4use crate::error::Diagnostic;
5use crate::graph::{CodeGraph, GraphBuilder, SccAnalysis};
6use crate::input;
7use crate::language::LangId;
8use crate::model::{FileExtraction, SnapshotId};
9
10/// Metadata about a snapshot analysis run.
11#[derive(Debug, Clone)]
12pub struct SnapshotMeta {
13    pub id: SnapshotId,
14    pub datagraph_schema_version: u32,
15}
16
17/// Result of the full graph analysis pipeline.
18pub struct GraphAnalysis {
19    pub graph: CodeGraph,
20    pub scc: SccAnalysis,
21    pub snapshot_id: SnapshotId,
22    pub extractions: Vec<Arc<crate::model::FileExtraction>>,
23    /// Flattened scope cache from the same pass. Resolves a name for a file id.
24    pub scope: crate::graph::resolver::FlattenedScopeCache,
25    /// One record per resolved use site, in extraction and reference order.
26    pub references: Vec<crate::graph::resolver::ResolvedReference>,
27}
28
29/// Assemble the graph, the scope cache, the resolved references, the client
30/// call edges and the SCC analysis from a set of extractions.
31///
32/// Both the one-shot and the incremental entry point call this, so the analysis
33/// of a tree cannot depend on which entry point produced it. The returned
34/// diagnostics are in the canonical order.
35pub fn build_analysis(
36    extractions: Vec<Arc<FileExtraction>>,
37    root: &Path,
38    snapshot_id: SnapshotId,
39) -> (GraphAnalysis, Vec<Diagnostic>) {
40    let mut diagnostics = Vec::new();
41    let parts =
42        GraphBuilder::from_extractions_detailed(&extractions, root, snapshot_id, &mut diagnostics);
43    diagnostics.sort_by(|a, b| a.sort_key().cmp(&b.sort_key()));
44
45    (
46        GraphAnalysis {
47            graph: parts.graph,
48            scc: parts.scc,
49            snapshot_id,
50            extractions,
51            scope: parts.scope,
52            references: parts.references,
53        },
54        diagnostics,
55    )
56}
57
58/// Run the full graph analysis pipeline on a path.
59///
60/// Discovers files, extracts symbols/imports/references in parallel,
61/// builds the dependency graph, resolves cross-file references,
62/// and computes SCC analysis.
63pub fn analyze_graph(
64    root: &Path,
65    snapshot_id: SnapshotId,
66    languages: Option<&[LangId]>,
67) -> anyhow::Result<(GraphAnalysis, Vec<Diagnostic>)> {
68    let files = input::discover_files(root, languages)?;
69    let extraction = crate::extractor::extract(&files);
70    let mut diagnostics: Vec<Diagnostic> = extraction
71        .files
72        .iter()
73        .flat_map(|f| f.diagnostics.iter().cloned())
74        .collect();
75
76    let arc_extractions: Vec<_> = extraction.files.into_iter().map(Arc::new).collect();
77
78    let (analysis, mut graph_diagnostics) = build_analysis(arc_extractions, root, snapshot_id);
79    diagnostics.append(&mut graph_diagnostics);
80    diagnostics.sort_by(|a, b| a.sort_key().cmp(&b.sort_key()));
81
82    Ok((analysis, diagnostics))
83}
84
85/// Build a SnapshotMeta for the current analysis run.
86pub fn snapshot_meta(snapshot_id: SnapshotId) -> SnapshotMeta {
87    SnapshotMeta {
88        id: snapshot_id,
89        datagraph_schema_version: crate::output::graph::SCHEMA_VERSION,
90    }
91}