use sqry_core::graph::GraphBuilder;
use sqry_core::graph::unified::StagingGraph;
use sqry_core::graph::unified::build::staging::StagingOp;
use std::collections::HashMap;
use std::path::Path;
fn staged_nodes(source: &str) -> Vec<(String, u32, u32)> {
let mut parser = tree_sitter::Parser::new();
parser
.set_language(&tree_sitter_c_sharp::LANGUAGE.into())
.expect("grammar");
let tree = parser.parse(source, None).expect("parse");
let mut staging = StagingGraph::new();
sqry_lang_csharp::relations::CSharpGraphBuilder::default()
.build_graph(&tree, source.as_bytes(), Path::new("P.cs"), &mut staging)
.expect("build graph");
let strings: HashMap<u32, String> = staging
.operations()
.iter()
.filter_map(|op| match op {
StagingOp::InternString { local_id, value } => Some((local_id.index(), value.clone())),
_ => None,
})
.collect();
staging
.operations()
.iter()
.filter_map(|op| match op {
StagingOp::AddNode { entry, .. } => {
let id = entry.qualified_name.unwrap_or(entry.name).index();
Some((
strings.get(&id).cloned().unwrap_or_default(),
entry.start_line,
entry.start_column,
))
}
_ => None,
})
.collect()
}
fn line_of(source: &str, offset: usize) -> u32 {
u32::try_from(source[..offset.min(source.len())].matches('\n').count() + 1)
.expect("line fits in u32")
}
#[test]
fn every_offset_named_node_reports_its_real_line() {
let source = "// pad\n// pad\n// pad\n// pad\nclass Holder {\n int Compute() {\n int answer = 42;\n return answer;\n }\n}\n";
let nodes = staged_nodes(source);
let mut checked = 0;
for (name, start_line, start_column) in &nodes {
let Some(offset) = name
.rsplit('@')
.next()
.and_then(|s| s.parse::<usize>().ok())
else {
continue;
};
checked += 1;
assert_eq!(
*start_line,
line_of(source, offset),
"`{name}` must report the line its byte offset falls on, got line {start_line} \
column {start_column} (a column equal to the offset is the issue #725 signature)"
);
}
assert!(
checked > 0,
"fixture produced no `symbol@offset` node, so this test would be vacuous: {nodes:?}"
);
}