struct graph
This commit is contained in:
@@ -903,3 +903,221 @@ fn function_graph_depth_namespaces_and_cycles() {
|
||||
);
|
||||
server.stop();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires clangd"]
|
||||
fn type_graph_constraints_and_members() {
|
||||
let temp = tempdir().unwrap();
|
||||
let root = temp.path();
|
||||
let build = root.join("build");
|
||||
fs::create_dir_all(build.join("meson-info")).unwrap();
|
||||
fs::write(build.join("meson-info/intro-projectinfo.json"), "{}").unwrap();
|
||||
fs::write(
|
||||
root.join("types.hpp"),
|
||||
include_str!("../../../../examples/types/types.hpp"),
|
||||
)
|
||||
.unwrap();
|
||||
fs::write(
|
||||
root.join("main.cpp"),
|
||||
include_str!("../../../../examples/types/main.cpp"),
|
||||
)
|
||||
.unwrap();
|
||||
fs::write(build.join("compile_commands.json"),serde_json::to_vec(&json!([{"directory":root,"file":root.join("main.cpp"),"arguments":["clang++","-std=c++23","-c",root.join("main.cpp")]}])).unwrap()).unwrap();
|
||||
let server = Clangd::start(crate::open(root, Some(&build), false).unwrap()).unwrap();
|
||||
let source = include_str!("../../../../examples/types/types.hpp");
|
||||
let position = |needle: &str| {
|
||||
let (line, text) = source
|
||||
.lines()
|
||||
.enumerate()
|
||||
.find(|(_, l)| l.contains(needle))
|
||||
.unwrap();
|
||||
Position {
|
||||
line: line as u32,
|
||||
character: (text.find(needle).unwrap() + 1) as u32,
|
||||
}
|
||||
};
|
||||
let pos = position("Box :");
|
||||
let graph = server
|
||||
.graph(
|
||||
"types.hpp",
|
||||
pos,
|
||||
&GraphOptions {
|
||||
depth: 1,
|
||||
excluded_namespaces: vec![],
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
for label in [
|
||||
"demo::Base",
|
||||
"demo::Helper",
|
||||
"demo::Box::value",
|
||||
"demo::Box::helper",
|
||||
"demo::Box::set",
|
||||
"demo::Box::run",
|
||||
"demo::Addable",
|
||||
"demo::Sized",
|
||||
"std::copyable",
|
||||
"std::constructible_from",
|
||||
"std::integral",
|
||||
"std::convertible_to",
|
||||
] {
|
||||
assert!(
|
||||
graph.nodes.iter().any(|n| n.label == label),
|
||||
"Missing {label}: {graph:?}"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
graph
|
||||
.nodes
|
||||
.iter()
|
||||
.any(|n| n.kind == "requires" && n.detail.contains("u.size()"))
|
||||
);
|
||||
assert!(
|
||||
graph
|
||||
.nodes
|
||||
.iter()
|
||||
.any(|n| n.kind == "parameter" && n.label == "argument x")
|
||||
);
|
||||
assert!(
|
||||
graph
|
||||
.nodes
|
||||
.iter()
|
||||
.any(|n| n.kind == "template-parameter" && n.label == "template T")
|
||||
);
|
||||
let default_graph = server
|
||||
.graph("types.hpp", pos, &GraphOptions::default())
|
||||
.unwrap();
|
||||
assert!(
|
||||
!default_graph
|
||||
.nodes
|
||||
.iter()
|
||||
.any(|n| n.label.starts_with("std::"))
|
||||
);
|
||||
let node = |label: &str| graph.nodes.iter().find(|n| n.label == label).unwrap();
|
||||
let edge = |from: &str, to: &str, label: &str| {
|
||||
graph
|
||||
.edges
|
||||
.iter()
|
||||
.any(|e| e.from == from && e.to == to && e.label == label)
|
||||
};
|
||||
assert!(edge(&node("demo::Base").id, "selected", "base of"));
|
||||
assert!(edge(
|
||||
&node("demo::Helper").id,
|
||||
&node("demo::Box::helper").id,
|
||||
"type of"
|
||||
));
|
||||
assert!(edge(
|
||||
&node("template T").id,
|
||||
&node("demo::Box::value").id,
|
||||
"type of"
|
||||
));
|
||||
assert!(edge(
|
||||
&node("std::integral").id,
|
||||
&node("argument n").id,
|
||||
"constrains"
|
||||
));
|
||||
let u = graph
|
||||
.nodes
|
||||
.iter()
|
||||
.find(|n| {
|
||||
n.label == "template U" && edge(&n.id, &node("demo::Box::set").id, "template parameter")
|
||||
})
|
||||
.unwrap();
|
||||
let argument = graph
|
||||
.nodes
|
||||
.iter()
|
||||
.find(|n| n.label == "argument u" && edge(&n.id, &node("demo::Box::set").id, "argument"))
|
||||
.unwrap();
|
||||
assert!(edge(&node("demo::Sized").id, &u.id, "constrains"));
|
||||
assert!(edge(&u.id, &argument.id, "type of"));
|
||||
let calls = server
|
||||
.graph(
|
||||
"types.hpp",
|
||||
pos,
|
||||
&GraphOptions {
|
||||
depth: 2,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let work = calls
|
||||
.nodes
|
||||
.iter()
|
||||
.find(|n| n.label == "demo::Helper::work")
|
||||
.unwrap();
|
||||
let set = calls
|
||||
.nodes
|
||||
.iter()
|
||||
.find(|n| n.label == "demo::Box::set")
|
||||
.unwrap();
|
||||
assert!(
|
||||
calls
|
||||
.edges
|
||||
.iter()
|
||||
.any(|e| e.from == work.id && e.to == set.id && e.label == "called by")
|
||||
);
|
||||
assert!(
|
||||
graph
|
||||
.nodes
|
||||
.iter()
|
||||
.any(|n| n.kind == "operator" && n.label == "||")
|
||||
);
|
||||
assert!(
|
||||
graph
|
||||
.nodes
|
||||
.iter()
|
||||
.any(|n| n.kind == "type" && n.label.starts_with("std::vector")),
|
||||
"{graph:?}"
|
||||
);
|
||||
let method = server
|
||||
.graph(
|
||||
"types.hpp",
|
||||
position("set("),
|
||||
&GraphOptions {
|
||||
depth: 1,
|
||||
excluded_namespaces: vec![],
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
assert!(method.title.ends_with("::set"), "{method:?}");
|
||||
assert!(
|
||||
method.nodes.iter().any(|n| n.label == "demo::Sized"),
|
||||
"{method:?}"
|
||||
);
|
||||
let constructor = server
|
||||
.graph(
|
||||
"types.hpp",
|
||||
position("Box(Addable"),
|
||||
&GraphOptions {
|
||||
depth: 1,
|
||||
excluded_namespaces: vec![],
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
assert!(
|
||||
constructor
|
||||
.nodes
|
||||
.iter()
|
||||
.any(|n| n.label == "std::constructible_from"),
|
||||
"{constructor:?}"
|
||||
);
|
||||
let alias = server
|
||||
.graph("types.hpp", position("IntBox ="), &GraphOptions::default())
|
||||
.unwrap();
|
||||
assert!(
|
||||
alias.title == "demo::Box"
|
||||
|| alias
|
||||
.nodes
|
||||
.iter()
|
||||
.any(|n| n.kind == "type" && n.label == "demo::Box"),
|
||||
"{alias:?}"
|
||||
);
|
||||
let enumeration = server
|
||||
.graph("types.hpp", position("State {"), &GraphOptions::default())
|
||||
.unwrap();
|
||||
assert!(
|
||||
enumeration.nodes.iter().any(|n| n.label == "idle"),
|
||||
"{enumeration:?}"
|
||||
);
|
||||
server.stop();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user