ucp_codegraph/programmatic/
graph.rs1use 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}