Skip to main content

tree_sitter_cpp/
lib.rs

1//! This crate provides C++ language support for the [tree-sitter] parsing library.
2//!
3//! The parser carries the ABI number of the WillBooster/tree-sitter fork, so it loads only with
4//! [willbooster-tree-sitter] 7.0.5 or later within major version 7; upstream's runtime rejects it.
5//!
6//! Typically, you will use the [`LANGUAGE`] constant to add this language to a
7//! tree-sitter [`Parser`], and then use the parser to parse some code:
8//!
9//! ```
10//! let code = "#include <iostream>\n\nint main() {\n    std::cout << \"Hello\\n\";\n}\n";
11//! let mut parser = tree_sitter::Parser::new();
12//! let language = tree_sitter_cpp::LANGUAGE;
13//! parser
14//!     .set_language(&language.into())
15//!     .expect("Error loading C++ parser");
16//! let tree = parser.parse(code, None).unwrap();
17//! assert!(!tree.root_node().has_error());
18//! ```
19//!
20//! [`Parser`]: https://docs.rs/willbooster-tree-sitter/7/tree_sitter/struct.Parser.html
21//! [willbooster-tree-sitter]: https://crates.io/crates/willbooster-tree-sitter
22//! [tree-sitter]: https://tree-sitter.github.io/
23
24use tree_sitter_language::LanguageFn;
25
26unsafe extern "C" {
27    fn tree_sitter_cpp() -> *const ();
28}
29
30/// The tree-sitter [`LanguageFn`] for this grammar.
31pub const LANGUAGE: LanguageFn = unsafe { LanguageFn::from_raw(tree_sitter_cpp) };
32
33/// The content of the [`node-types.json`] file for this grammar.
34///
35/// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers/6-static-node-types
36pub const NODE_TYPES: &str = include_str!("../../src/node-types.json");
37
38/// The query for extracting symbol definitions from C++ source.
39pub const TAGS_QUERY: &str = include_str!("../../queries/tags.scm");
40
41#[cfg(test)]
42mod tests {
43    use tree_sitter::StreamingIterator;
44
45    #[test]
46    fn test_can_load_grammar() {
47        let mut parser = tree_sitter::Parser::new();
48        parser
49            .set_language(&super::LANGUAGE.into())
50            .expect("Error loading C++ parser");
51    }
52
53    #[test]
54    fn extracts_symbol_definitions() {
55        let source = "struct Example { void method() {} };\nvoid function() {}\n";
56        let language = super::LANGUAGE.into();
57        let mut parser = tree_sitter::Parser::new();
58        parser.set_language(&language).unwrap();
59        let tree = parser.parse(source, None).unwrap();
60        assert!(!tree.root_node().has_error());
61
62        let query = tree_sitter::Query::new(&language, super::TAGS_QUERY).unwrap();
63        let name_index = query.capture_index_for_name("name").unwrap();
64        let mut cursor = tree_sitter::QueryCursor::new();
65        let mut captures = cursor.captures(&query, tree.root_node(), source.as_bytes());
66        let mut names = Vec::new();
67        while let Some((query_match, capture_index)) = captures.next() {
68            let capture = query_match.captures()[*capture_index];
69            if capture.index == name_index {
70                names.push(capture.node.utf8_text(source.as_bytes()).unwrap());
71            }
72        }
73        assert_eq!(names, ["Example", "method", "function"]);
74    }
75}