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 HIGHLIGHTS_QUERY: &str = concat!(
40 include_str!("../../queries/c/highlights.scm"),
41 "\n",
42 include_str!("../../queries/highlights.scm")
43);
44
45pub const TAGS_QUERY: &str = include_str!("../../queries/tags.scm");
47
48pub const INJECTIONS_QUERY: &str = include_str!("../../queries/injections.scm");
50
51#[cfg(test)]
52mod tests {
53 use tree_sitter::StreamingIterator;
54
55 #[test]
56 fn test_can_load_grammar() {
57 let mut parser = tree_sitter::Parser::new();
58 parser
59 .set_language(&super::LANGUAGE.into())
60 .expect("Error loading C++ parser");
61 }
62
63 #[test]
64 fn highlights_c_and_cpp_syntax() {
65 let source = "class Example { int value = 1; };\n";
66 for (name, texts) in [
67 ("keyword", vec!["class"]),
68 ("type", vec!["Example", "int"]),
69 ("property", vec!["value"]),
70 ("number", vec!["1"]),
71 ] {
72 assert_eq!(captured_texts(source, super::HIGHLIGHTS_QUERY, name), texts);
73 }
74 }
75
76 #[test]
77 fn extracts_symbol_definitions() {
78 let source = "struct Example { void method() {} };\nvoid function() {}\n";
79 assert_eq!(
80 captured_texts(source, super::TAGS_QUERY, "name"),
81 ["Example", "method", "function"]
82 );
83 }
84
85 #[test]
86 fn extracts_raw_string_injections() {
87 let source =
88 "const char* embedded = R\"sql(SELECT 1)sql\";\nconst char* plain = \"SELECT 2\";\n";
89 assert_eq!(
90 captured_texts(source, super::INJECTIONS_QUERY, "injection.language"),
91 ["sql"]
92 );
93 assert_eq!(
94 captured_texts(source, super::INJECTIONS_QUERY, "injection.content"),
95 ["SELECT 1"]
96 );
97 }
98
99 fn captured_texts(source: &str, query_source: &str, capture_name: &str) -> Vec<String> {
100 let language = super::LANGUAGE.into();
101 let mut parser = tree_sitter::Parser::new();
102 parser.set_language(&language).unwrap();
103 let tree = parser.parse(source, None).unwrap();
104 assert!(!tree.root_node().has_error());
105
106 let query = tree_sitter::Query::new(&language, query_source).unwrap();
107 let name_index = query.capture_index_for_name(capture_name).unwrap();
108 let mut cursor = tree_sitter::QueryCursor::new();
109 let mut captures = cursor.captures(&query, tree.root_node(), source.as_bytes());
110 let mut texts = Vec::new();
111 while let Some((query_match, capture_index)) = captures.next() {
112 let capture = query_match.captures()[*capture_index];
113 if capture.index == name_index {
114 texts.push(
115 capture
116 .node
117 .utf8_text(source.as_bytes())
118 .unwrap()
119 .to_owned(),
120 );
121 }
122 }
123 texts
124 }
125}