1use tree_sitter_language::LanguageFn;
25
26unsafe extern "C" {
27 fn tree_sitter_cpp() -> *const ();
28}
29
30pub const LANGUAGE: LanguageFn = unsafe { LanguageFn::from_raw(tree_sitter_cpp) };
32
33pub const NODE_TYPES: &str = include_str!("../../src/node-types.json");
37
38pub const TAGS_QUERY: &str = include_str!("../../queries/tags.scm");
40
41pub const INJECTIONS_QUERY: &str = include_str!("../../queries/injections.scm");
43
44#[cfg(test)]
45mod tests {
46 use tree_sitter::StreamingIterator;
47
48 #[test]
49 fn test_can_load_grammar() {
50 let mut parser = tree_sitter::Parser::new();
51 parser
52 .set_language(&super::LANGUAGE.into())
53 .expect("Error loading C++ parser");
54 }
55
56 #[test]
57 fn extracts_symbol_definitions() {
58 let source = "struct Example { void method() {} };\nvoid function() {}\n";
59 assert_eq!(
60 captured_texts(source, super::TAGS_QUERY, "name"),
61 ["Example", "method", "function"]
62 );
63 }
64
65 #[test]
66 fn extracts_raw_string_injections() {
67 let source =
68 "const char* embedded = R\"sql(SELECT 1)sql\";\nconst char* plain = \"SELECT 2\";\n";
69 assert_eq!(
70 captured_texts(source, super::INJECTIONS_QUERY, "injection.language"),
71 ["sql"]
72 );
73 assert_eq!(
74 captured_texts(source, super::INJECTIONS_QUERY, "injection.content"),
75 ["SELECT 1"]
76 );
77 }
78
79 fn captured_texts(source: &str, query_source: &str, capture_name: &str) -> Vec<String> {
80 let language = super::LANGUAGE.into();
81 let mut parser = tree_sitter::Parser::new();
82 parser.set_language(&language).unwrap();
83 let tree = parser.parse(source, None).unwrap();
84 assert!(!tree.root_node().has_error());
85
86 let query = tree_sitter::Query::new(&language, query_source).unwrap();
87 let name_index = query.capture_index_for_name(capture_name).unwrap();
88 let mut cursor = tree_sitter::QueryCursor::new();
89 let mut captures = cursor.captures(&query, tree.root_node(), source.as_bytes());
90 let mut texts = Vec::new();
91 while let Some((query_match, capture_index)) = captures.next() {
92 let capture = query_match.captures()[*capture_index];
93 if capture.index == name_index {
94 texts.push(
95 capture
96 .node
97 .utf8_text(source.as_bytes())
98 .unwrap()
99 .to_owned(),
100 );
101 }
102 }
103 texts
104 }
105}