Skip to content
This repository was archived by the owner on Sep 9, 2025. It is now read-only.

Commit c8f83d8

Browse files
author
Hendrik van Antwerpen
authored
Merge pull request #277 from github/add-debug-info-edges
Include edge debug information in visualization
2 parents b500136 + 47345c2 commit c8f83d8

File tree

7 files changed

+136
-26
lines changed

7 files changed

+136
-26
lines changed

languages/tree-sitter-stack-graphs-typescript/rust/util.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pub const PKG_M_NS: &str = "%PkgM";
2222
pub fn add_debug_name(graph: &mut StackGraph, node: Handle<Node>, name: &str) {
2323
let key = graph.add_string("name");
2424
let value = graph.add_string(name);
25-
graph.debug_info_mut(node).add(key, value);
25+
graph.node_debug_info_mut(node).add(key, value);
2626
}
2727

2828
pub fn add_pop(

stack-graphs/src/graph.rs

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1292,7 +1292,7 @@ pub struct Edge {
12921292
pub precedence: i32,
12931293
}
12941294

1295-
struct OutgoingEdge {
1295+
pub(crate) struct OutgoingEdge {
12961296
sink: Handle<Node>,
12971297
precedence: i32,
12981298
}
@@ -1387,13 +1387,40 @@ pub struct DebugEntry {
13871387

13881388
impl StackGraph {
13891389
/// Returns debug information about the stack graph node.
1390-
pub fn debug_info(&self, node: Handle<Node>) -> Option<&DebugInfo> {
1391-
self.debug_info.get(node)
1390+
pub fn node_debug_info(&self, node: Handle<Node>) -> Option<&DebugInfo> {
1391+
self.node_debug_info.get(node)
13921392
}
13931393

13941394
/// Returns a mutable reference to the debug info about the stack graph node.
1395-
pub fn debug_info_mut(&mut self, node: Handle<Node>) -> &mut DebugInfo {
1396-
&mut self.debug_info[node]
1395+
pub fn node_debug_info_mut(&mut self, node: Handle<Node>) -> &mut DebugInfo {
1396+
&mut self.node_debug_info[node]
1397+
}
1398+
1399+
/// Returns debug information about the stack graph edge.
1400+
pub fn edge_debug_info(&self, source: Handle<Node>, sink: Handle<Node>) -> Option<&DebugInfo> {
1401+
self.edge_debug_info.get(source).and_then(|es| {
1402+
match es.binary_search_by_key(&sink, |e| e.0) {
1403+
Ok(idx) => Some(&es[idx].1),
1404+
Err(_) => None,
1405+
}
1406+
})
1407+
}
1408+
1409+
/// Returns a mutable reference to the debug info about the stack graph edge.
1410+
pub fn edge_debug_info_mut(
1411+
&mut self,
1412+
source: Handle<Node>,
1413+
sink: Handle<Node>,
1414+
) -> &mut DebugInfo {
1415+
let es = &mut self.edge_debug_info[source];
1416+
let idx = match es.binary_search_by_key(&sink, |e| e.0) {
1417+
Ok(idx) => idx,
1418+
Err(idx) => {
1419+
es.insert(idx, (sink, DebugInfo::default()));
1420+
idx
1421+
}
1422+
};
1423+
&mut es[idx].1
13971424
}
13981425
}
13991426

@@ -1413,7 +1440,8 @@ pub struct StackGraph {
14131440
pub(crate) source_info: SupplementalArena<Node, SourceInfo>,
14141441
node_id_handles: NodeIDHandles,
14151442
outgoing_edges: SupplementalArena<Node, SmallVec<[OutgoingEdge; 8]>>,
1416-
pub(crate) debug_info: SupplementalArena<Node, DebugInfo>,
1443+
pub(crate) node_debug_info: SupplementalArena<Node, DebugInfo>,
1444+
pub(crate) edge_debug_info: SupplementalArena<Node, SmallVec<[(Handle<Node>, DebugInfo); 8]>>,
14171445
}
14181446

14191447
impl StackGraph {
@@ -1546,8 +1574,8 @@ impl StackGraph {
15461574
definiens_span: source_info.definiens_span.clone(),
15471575
};
15481576
}
1549-
if let Some(debug_info) = other.debug_info(other_node) {
1550-
*self.debug_info_mut(node) = DebugInfo {
1577+
if let Some(debug_info) = other.node_debug_info(other_node) {
1578+
*self.node_debug_info_mut(node) = DebugInfo {
15511579
entries: debug_info
15521580
.entries
15531581
.iter()
@@ -1591,7 +1619,8 @@ impl Default for StackGraph {
15911619
source_info: SupplementalArena::new(),
15921620
node_id_handles: NodeIDHandles::new(),
15931621
outgoing_edges: SupplementalArena::new(),
1594-
debug_info: SupplementalArena::new(),
1622+
node_debug_info: SupplementalArena::new(),
1623+
edge_debug_info: SupplementalArena::new(),
15951624
}
15961625
}
15971626
}

stack-graphs/src/serde/graph.rs

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use thiserror::Error;
1212
use crate::arena::Handle;
1313

1414
use super::Filter;
15+
use super::ImplicationFilter;
1516
use super::NoFilter;
1617

1718
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
@@ -41,9 +42,10 @@ impl StackGraph {
4142
}
4243

4344
pub fn from_graph_filter<'a>(graph: &crate::graph::StackGraph, filter: &'a dyn Filter) -> Self {
44-
let files = graph.filter_files(filter);
45-
let nodes = graph.filter_nodes(filter);
46-
let edges = graph.filter_edges(filter);
45+
let filter = ImplicationFilter(filter);
46+
let files = graph.filter_files(&filter);
47+
let nodes = graph.filter_nodes(&filter);
48+
let edges = graph.filter_edges(&filter);
4749
Self {
4850
files,
4951
nodes,
@@ -146,7 +148,7 @@ impl StackGraph {
146148

147149
// load debug-info of each node
148150
if let Some(debug_info) = node.debug_info() {
149-
*graph.debug_info_mut(handle) = debug_info.data.iter().fold(
151+
*graph.node_debug_info_mut(handle) = debug_info.data.iter().fold(
150152
crate::graph::DebugInfo::default(),
151153
|mut info, entry| {
152154
let key = graph.add_string(&entry.key);
@@ -167,6 +169,7 @@ impl StackGraph {
167169
source,
168170
sink,
169171
precedence,
172+
debug_info,
170173
} in &self.edges.data
171174
{
172175
let source_id = source.to_node_id(graph)?;
@@ -180,6 +183,19 @@ impl StackGraph {
180183
.ok_or(Error::InvalidGlobalNodeID(sink.local_id))?;
181184

182185
graph.add_edge(source_handle, sink_handle, *precedence);
186+
187+
// load debug-info of each node
188+
if let Some(debug_info) = debug_info {
189+
*graph.edge_debug_info_mut(source_handle, sink_handle) = debug_info
190+
.data
191+
.iter()
192+
.fold(crate::graph::DebugInfo::default(), |mut info, entry| {
193+
let key = graph.add_string(&entry.key);
194+
let value = graph.add_string(&entry.value);
195+
info.add(key, value);
196+
info
197+
});
198+
}
183199
}
184200
Ok(())
185201
}
@@ -392,6 +408,8 @@ pub struct Edge {
392408
pub source: NodeID,
393409
pub sink: NodeID,
394410
pub precedence: i32,
411+
#[serde(skip_serializing_if = "Option::is_none")]
412+
pub debug_info: Option<DebugInfo>,
395413
}
396414

397415
impl crate::graph::StackGraph {
@@ -430,12 +448,12 @@ impl crate::graph::StackGraph {
430448
})
431449
}
432450

433-
fn filter_debug_info<'a>(
451+
fn filter_node_debug_info<'a>(
434452
&self,
435453
_filter: &'a dyn Filter,
436454
handle: Handle<crate::graph::Node>,
437455
) -> Option<DebugInfo> {
438-
self.debug_info(handle).map(|info| DebugInfo {
456+
self.node_debug_info(handle).map(|info| DebugInfo {
439457
data: info
440458
.iter()
441459
.map(|entry| DebugEntry {
@@ -455,7 +473,7 @@ impl crate::graph::StackGraph {
455473
let node = &self[handle];
456474
let id = self.filter_node(filter, node.id());
457475
let source_info = self.filter_source_info(filter, handle);
458-
let debug_info = self.filter_debug_info(filter, handle);
476+
let debug_info = self.filter_node_debug_info(filter, handle);
459477

460478
match node {
461479
crate::graph::Node::DropScopes(_node) => Node::DropScopes {
@@ -525,10 +543,29 @@ impl crate::graph::StackGraph {
525543
source: self.filter_node(filter, self[e.source].id()),
526544
sink: self.filter_node(filter, self[e.sink].id()),
527545
precedence: e.precedence,
546+
debug_info: self.filter_edge_debug_info(filter, e.source, e.sink),
528547
})
529548
})
530549
.flatten()
531550
.collect::<Vec<_>>(),
532551
}
533552
}
553+
554+
fn filter_edge_debug_info<'a>(
555+
&self,
556+
_filter: &'a dyn Filter,
557+
source_handle: Handle<crate::graph::Node>,
558+
sink_handle: Handle<crate::graph::Node>,
559+
) -> Option<DebugInfo> {
560+
self.edge_debug_info(source_handle, sink_handle)
561+
.map(|info| DebugInfo {
562+
data: info
563+
.iter()
564+
.map(|entry| DebugEntry {
565+
key: self[entry.key].to_owned(),
566+
value: self[entry.value].to_owned(),
567+
})
568+
.collect(),
569+
})
570+
}
534571
}

stack-graphs/src/visualization.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ impl StackGraph {
3636
filter: &dyn Filter,
3737
) -> Result<String, Error> {
3838
let filter = VisualizationFilter(filter);
39-
let graph = serde_json::to_string(&self.to_serializable())?;
39+
let graph = serde_json::to_string(&self.to_serializable_filter(&filter))?;
4040
let paths = serde_json::to_string(&db.to_serializable_filter(self, partials, &filter))?;
4141
let html = format!(
4242
r#"

stack-graphs/tests/it/serde.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ fn serde_json_stack_graph() {
6868
local_id: 0,
6969
},
7070
precedence: 0,
71+
debug_info: Some(serde::DebugInfo { data: vec![] }),
7172
}],
7273
},
7374
};
@@ -77,6 +78,7 @@ fn serde_json_stack_graph() {
7778
{
7879
"edges" : [
7980
{
81+
"debug_info" : [],
8082
"precedence" : 0,
8183
"sink" : {
8284
"file" : "index.ts",
@@ -320,7 +322,7 @@ fn can_load_serialized_stack_graph() {
320322
.find(|handle| matches!(sg[*handle], graph::Node::Scope(..)))
321323
.unwrap();
322324
assert!(sg.source_info(handle).is_some());
323-
assert!(sg.debug_info(handle).is_some());
325+
assert!(sg.node_debug_info(handle).is_some());
324326
}
325327

326328
#[test]
@@ -376,6 +378,12 @@ fn can_serialize_graph() {
376378
}
377379
},
378380
{
381+
"debug_info" : [
382+
{
383+
"key" : "dsl_position",
384+
"value" : "line 23 column 4"
385+
}
386+
],
379387
"precedence" : 0,
380388
"sink" : {
381389
"local_id" : 1

stack-graphs/tests/it/test_graphs/simple.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,18 +112,22 @@ pub fn new() -> StackGraph {
112112
let str_lexical_scope = graph.add_string("lexical_scope");
113113
let str_pos_one = graph.add_string("line 31 column 20");
114114
let str_pos_two = graph.add_string("line 8 column 11");
115+
let str_pos_three = graph.add_string("line 23 column 4");
115116
graph
116-
.debug_info_mut(scope_x)
117+
.node_debug_info_mut(scope_x)
117118
.add(str_dsl_var, str_arg_scope);
118119
graph
119-
.debug_info_mut(scope_x)
120+
.node_debug_info_mut(scope_x)
120121
.add(str_dsl_position, str_pos_one);
121122
graph
122-
.debug_info_mut(scope)
123+
.node_debug_info_mut(scope)
123124
.add(str_dsl_var, str_lexical_scope);
124125
graph
125-
.debug_info_mut(scope)
126+
.node_debug_info_mut(scope)
126127
.add(str_dsl_position, str_pos_two);
128+
graph
129+
.edge_debug_info_mut(scope, root)
130+
.add(str_dsl_position, str_pos_three);
127131

128132
graph
129133
}

tree-sitter-stack-graphs/src/lib.rs

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ use std::time::Instant;
329329
use thiserror::Error;
330330
use tree_sitter::Parser;
331331
use tree_sitter_graph::functions::Functions;
332+
use tree_sitter_graph::graph::Edge;
332333
use tree_sitter_graph::graph::Graph;
333334
use tree_sitter_graph::graph::GraphNode;
334335
use tree_sitter_graph::graph::GraphNodeRef;
@@ -881,7 +882,7 @@ impl<'a> Builder<'a> {
881882
NodeType::Scope => self.load_scope(node_ref)?,
882883
};
883884
self.load_span(node_ref, handle)?;
884-
self.load_debug_info(node_ref, handle)?;
885+
self.load_node_debug_info(node_ref, handle)?;
885886
}
886887

887888
for node in self.stack_graph.nodes_for_file(self.file) {
@@ -906,6 +907,12 @@ impl<'a> Builder<'a> {
906907
let sink_handle = self.stack_graph.node_for_id(sink_node_id).unwrap();
907908
self.stack_graph
908909
.add_edge(source_handle, sink_handle, precedence);
910+
Self::load_edge_debug_info(
911+
&mut self.stack_graph,
912+
source_handle,
913+
sink_handle,
914+
edge,
915+
)?;
909916
}
910917
}
911918

@@ -1105,7 +1112,7 @@ impl<'a> Builder<'a> {
11051112
Ok(())
11061113
}
11071114

1108-
fn load_debug_info(
1115+
fn load_node_debug_info(
11091116
&mut self,
11101117
node_ref: GraphNodeRef,
11111118
node_handle: Handle<Node>,
@@ -1122,7 +1129,32 @@ impl<'a> Builder<'a> {
11221129
.stack_graph
11231130
.add_string(&name[DEBUG_ATTR_PREFIX.len()..]);
11241131
let value = self.stack_graph.add_string(&value);
1125-
self.stack_graph.debug_info_mut(node_handle).add(key, value);
1132+
self.stack_graph
1133+
.node_debug_info_mut(node_handle)
1134+
.add(key, value);
1135+
}
1136+
}
1137+
Ok(())
1138+
}
1139+
1140+
fn load_edge_debug_info(
1141+
stack_graph: &mut StackGraph,
1142+
source_handle: Handle<Node>,
1143+
sink_handle: Handle<Node>,
1144+
edge: &Edge,
1145+
) -> Result<(), BuildError> {
1146+
for (name, value) in edge.attributes.iter() {
1147+
let name = name.to_string();
1148+
if name.starts_with(DEBUG_ATTR_PREFIX) {
1149+
let value = match value {
1150+
Value::String(value) => value.clone(),
1151+
value => value.to_string(),
1152+
};
1153+
let key = stack_graph.add_string(&name[DEBUG_ATTR_PREFIX.len()..]);
1154+
let value = stack_graph.add_string(&value);
1155+
stack_graph
1156+
.edge_debug_info_mut(source_handle, sink_handle)
1157+
.add(key, value);
11261158
}
11271159
}
11281160
Ok(())

0 commit comments

Comments
 (0)