1use tree_sitter_language::LanguageFn;
4
5extern "C" {
6 fn tree_sitter_harn() -> *const ();
7}
8
9pub const LANGUAGE: LanguageFn = unsafe { LanguageFn::from_raw(tree_sitter_harn) };
11
12pub const NODE_TYPES: &str = include_str!("../../src/node-types.json");
14
15pub const HIGHLIGHTS_QUERY: &str = include_str!("../../queries/highlights.scm");
17
18pub const INJECTIONS_QUERY: &str = include_str!("../../queries/injections.scm");
20
21#[cfg(test)]
22mod tests {
23 use tree_sitter::{Query, QueryCursor, StreamingIterator};
24
25 #[test]
26 fn can_load_grammar() {
27 let mut parser = tree_sitter::Parser::new();
28 parser
29 .set_language(&super::LANGUAGE.into())
30 .expect("load Harn parser");
31 }
32
33 #[test]
34 fn bundled_queries_compile() {
35 let language = super::LANGUAGE.into();
36 tree_sitter::Query::new(&language, super::HIGHLIGHTS_QUERY)
37 .expect("highlight query should compile");
38 tree_sitter::Query::new(&language, super::INJECTIONS_QUERY)
39 .expect("injection query should compile");
40 }
41
42 #[test]
43 fn injection_query_captures_postgres_template_content() {
44 let source = r#"fn build_sql(user_id) {
45 let q = sql("""
46select *
47from users
48where id = {user_id}
49""", {user_id: user_id})
50 let named = named_sql("users_by_id", "one", "select * from users where id = {user_id}", {user_id: user_id})
51 let raw = query.sql(r"select * from users where name = {name}", {name: "Ada"})
52 let other = render("select * from ignored")
53}"#;
54
55 let language = super::LANGUAGE.into();
56 let mut parser = tree_sitter::Parser::new();
57 parser.set_language(&language).expect("load Harn parser");
58 let tree = parser.parse(source, None).expect("parse Harn source");
59 assert!(
60 !tree.root_node().has_error(),
61 "fixture should parse cleanly"
62 );
63
64 let query =
65 Query::new(&language, super::INJECTIONS_QUERY).expect("injection query should compile");
66 let capture_index = query
67 .capture_names()
68 .iter()
69 .position(|name| *name == "injection.content")
70 .expect("query should expose injection.content") as u32;
71
72 let mut cursor = QueryCursor::new();
73 let mut matches = cursor.matches(&query, tree.root_node(), source.as_bytes());
74 let mut captured = Vec::new();
75 while let Some(query_match) = matches.next() {
76 for capture in query_match.captures {
77 if capture.index == capture_index {
78 captured.push(capture.node.utf8_text(source.as_bytes()).unwrap());
79 }
80 }
81 }
82
83 assert_eq!(
84 captured,
85 vec![
86 "\nselect *\nfrom users\nwhere id = {user_id}\n",
87 "select * from users where id = {user_id}",
88 "select * from users where name = {name}",
89 ]
90 );
91 }
92}