Skip to main content

ucp_codegraph/programmatic/
graph.rs

1use std::{fs, path::Path, sync::Arc};
2
3use anyhow::Result;
4use ucm_core::{BlockId, Document};
5
6use crate::{build_code_graph, CodeGraphBuildInput};
7
8use super::{
9    query,
10    session::CodeGraphNavigatorSession,
11    types::{
12        CodeGraphFindQuery, CodeGraphNodeSummary, CodeGraphPathResult,
13        CodeGraphSelectorResolutionExplanation,
14    },
15};
16
17#[derive(Debug, Clone)]
18pub struct CodeGraphNavigator {
19    document: Arc<Document>,
20    graph: ucp_graph::GraphNavigator,
21}
22
23impl CodeGraphNavigator {
24    pub fn new(document: Document) -> Self {
25        let graph = ucp_graph::GraphNavigator::from_document(document.clone());
26        Self {
27            document: Arc::new(document),
28            graph,
29        }
30    }
31
32    pub fn build(input: &CodeGraphBuildInput) -> Result<Self> {
33        let result = build_code_graph(input)?;
34        Ok(Self::new(result.document))
35    }
36
37    pub fn document(&self) -> &Document {
38        self.document.as_ref()
39    }
40
41    pub fn graph(&self) -> &ucp_graph::GraphNavigator {
42        &self.graph
43    }
44
45    pub fn session(&self) -> CodeGraphNavigatorSession {
46        CodeGraphNavigatorSession::new(self.clone())
47    }
48
49    pub fn resolve_selector(&self, selector: &str) -> Option<BlockId> {
50        crate::resolve_codegraph_selector(self.document(), selector)
51    }
52
53    pub fn describe_node(&self, block_id: BlockId) -> Option<CodeGraphNodeSummary> {
54        query::describe_node(self.document(), block_id)
55    }
56
57    pub fn explain_selector(&self, selector: &str) -> CodeGraphSelectorResolutionExplanation {
58        query::explain_selector(self.document(), selector)
59    }
60
61    pub fn find_nodes(&self, query: &CodeGraphFindQuery) -> Result<Vec<CodeGraphNodeSummary>> {
62        query::find_nodes(self.document(), query)
63    }
64
65    pub fn path_between(
66        &self,
67        start: BlockId,
68        end: BlockId,
69        max_hops: usize,
70    ) -> Option<CodeGraphPathResult> {
71        query::path_between(self.document(), start, end, max_hops)
72    }
73
74    pub(crate) fn resolve_required(&self, selector: &str) -> Result<BlockId> {
75        query::resolve_required(self.document(), selector)
76    }
77
78    pub fn load_session_json(&self, payload: &str) -> Result<CodeGraphNavigatorSession> {
79        let persisted = serde_json::from_str(payload)?;
80        CodeGraphNavigatorSession::from_persisted(self.clone(), persisted)
81    }
82
83    pub fn load_session(&self, path: impl AsRef<Path>) -> Result<CodeGraphNavigatorSession> {
84        self.load_session_json(&fs::read_to_string(path)?)
85    }
86}