/ src / languages / zig.rs
zig.rs
  1  use crate::languages::LanguageSupport;
  2  use std::sync::OnceLock;
  3  use tracing::error;
  4  use tree_sitter::{Language, Query};
  5  
  6  pub struct Zig;
  7  
  8  static REFERENCE_QUERY: OnceLock<Query> = OnceLock::new();
  9  static BINDING_QUERY: OnceLock<Query> = OnceLock::new();
 10  static IMPORT_QUERY: OnceLock<Query> = OnceLock::new();
 11  static COMPLETION_QUERY: OnceLock<Query> = OnceLock::new();
 12  static REASSIGNMENT_QUERY: OnceLock<Query> = OnceLock::new();
 13  static IDENTIFIER_QUERY: OnceLock<Query> = OnceLock::new();
 14  static EXPORT_QUERY: OnceLock<Query> = OnceLock::new();
 15  static ASSIGNMENT_QUERY: OnceLock<Query> = OnceLock::new();
 16  static DESTRUCTURE_QUERY: OnceLock<Query> = OnceLock::new();
 17  static SCOPE_QUERY: OnceLock<Query> = OnceLock::new();
 18  
 19  fn compile_query(grammar: &Language, source: &str, query_name: &str) -> Query {
 20      match Query::new(grammar, source) {
 21          Ok(query) => query,
 22          Err(e) => {
 23              error!(
 24                  language = "zig",
 25                  query = query_name,
 26                  error = %e,
 27                  "Failed to compile query, failing fast"
 28              );
 29              panic!("Failed to compile query '{}': {}", query_name, e)
 30          }
 31      }
 32  }
 33  
 34  impl LanguageSupport for Zig {
 35      fn id(&self) -> &'static str {
 36          "zig"
 37      }
 38  
 39      fn extensions(&self) -> &'static [&'static str] {
 40          &["zig"]
 41      }
 42  
 43      fn language_ids(&self) -> &'static [&'static str] {
 44          &["zig"]
 45      }
 46  
 47      fn grammar(&self) -> Language {
 48          tree_sitter_zig::LANGUAGE.into()
 49      }
 50  
 51      fn reference_query(&self) -> &Query {
 52          REFERENCE_QUERY.get_or_init(|| {
 53              compile_query(
 54                  &self.grammar(),
 55                  include_str!("../../queries/zig/references.scm"),
 56                  "references",
 57              )
 58          })
 59      }
 60  
 61      fn binding_query(&self) -> Option<&Query> {
 62          Some(BINDING_QUERY.get_or_init(|| {
 63              compile_query(
 64                  &self.grammar(),
 65                  include_str!("../../queries/zig/bindings.scm"),
 66                  "bindings",
 67              )
 68          }))
 69      }
 70  
 71      fn import_query(&self) -> Option<&Query> {
 72          Some(IMPORT_QUERY.get_or_init(|| {
 73              compile_query(
 74                  &self.grammar(),
 75                  include_str!("../../queries/zig/imports.scm"),
 76                  "imports",
 77              )
 78          }))
 79      }
 80  
 81      fn completion_query(&self) -> Option<&Query> {
 82          Some(COMPLETION_QUERY.get_or_init(|| {
 83              compile_query(
 84                  &self.grammar(),
 85                  include_str!("../../queries/zig/completion.scm"),
 86                  "completion",
 87              )
 88          }))
 89      }
 90  
 91      fn reassignment_query(&self) -> Option<&Query> {
 92          Some(REASSIGNMENT_QUERY.get_or_init(|| {
 93              compile_query(
 94                  &self.grammar(),
 95                  include_str!("../../queries/zig/reassignments.scm"),
 96                  "reassignments",
 97              )
 98          }))
 99      }
100  
101      fn identifier_query(&self) -> Option<&Query> {
102          Some(IDENTIFIER_QUERY.get_or_init(|| {
103              compile_query(
104                  &self.grammar(),
105                  include_str!("../../queries/zig/identifiers.scm"),
106                  "identifiers",
107              )
108          }))
109      }
110  
111      fn export_query(&self) -> Option<&Query> {
112          Some(EXPORT_QUERY.get_or_init(|| {
113              compile_query(
114                  &self.grammar(),
115                  include_str!("../../queries/zig/exports.scm"),
116                  "exports",
117              )
118          }))
119      }
120  
121      fn assignment_query(&self) -> Option<&Query> {
122          Some(ASSIGNMENT_QUERY.get_or_init(|| {
123              compile_query(
124                  &self.grammar(),
125                  include_str!("../../queries/zig/assignments.scm"),
126                  "assignments",
127              )
128          }))
129      }
130  
131      fn destructure_query(&self) -> Option<&Query> {
132          Some(DESTRUCTURE_QUERY.get_or_init(|| {
133              compile_query(
134                  &self.grammar(),
135                  include_str!("../../queries/zig/destructures.scm"),
136                  "destructures",
137              )
138          }))
139      }
140  
141      fn scope_query(&self) -> Option<&Query> {
142          Some(SCOPE_QUERY.get_or_init(|| {
143              compile_query(
144                  &self.grammar(),
145                  include_str!("../../queries/zig/scopes.scm"),
146                  "scopes",
147              )
148          }))
149      }
150  
151      fn completion_trigger_characters(&self) -> &'static [&'static str] {
152          &["(\"", "('"]
153      }
154  
155      fn is_standard_env_object(&self, name: &str) -> bool {
156          name == "std"
157      }
158  
159      fn comment_node_kinds(&self) -> &'static [&'static str] {
160          &["line_comment", "doc_comment", "container_doc_comment"]
161      }
162  
163      fn is_scope_node(&self, node: tree_sitter::Node) -> bool {
164          matches!(
165              node.kind(),
166              "FnProto"
167                  | "Block"
168                  | "ForStatement"
169                  | "WhileStatement"
170                  | "IfStatement"
171                  | "SwitchExpr"
172                  | "ContainerDecl"
173          )
174      }
175  }
176  
177  #[cfg(test)]
178  mod tests {
179      use super::*;
180  
181      fn get_zig() -> Zig {
182          Zig
183      }
184  
185      #[test]
186      fn test_id() {
187          assert_eq!(get_zig().id(), "zig");
188      }
189  
190      #[test]
191      fn test_extensions() {
192          let exts = get_zig().extensions();
193          assert!(exts.contains(&"zig"));
194      }
195  
196      #[test]
197      fn test_language_ids() {
198          let ids = get_zig().language_ids();
199          assert!(ids.contains(&"zig"));
200      }
201  
202      #[test]
203      fn test_grammar_compiles() {
204          let zig = get_zig();
205          let _grammar = zig.grammar();
206      }
207  
208      #[test]
209      fn test_reference_query_compiles() {
210          let zig = get_zig();
211          let _query = zig.reference_query();
212      }
213  
214      #[test]
215      fn test_binding_query_compiles() {
216          let zig = get_zig();
217          assert!(zig.binding_query().is_some());
218      }
219  
220      #[test]
221      fn test_import_query_compiles() {
222          let zig = get_zig();
223          assert!(zig.import_query().is_some());
224      }
225  
226      #[test]
227      fn test_completion_query_compiles() {
228          let zig = get_zig();
229          assert!(zig.completion_query().is_some());
230      }
231  
232      #[test]
233      fn test_reassignment_query_compiles() {
234          let zig = get_zig();
235          assert!(zig.reassignment_query().is_some());
236      }
237  
238      #[test]
239      fn test_identifier_query_compiles() {
240          let zig = get_zig();
241          assert!(zig.identifier_query().is_some());
242      }
243  
244      #[test]
245      fn test_export_query_compiles() {
246          let zig = get_zig();
247          assert!(zig.export_query().is_some());
248      }
249  
250      #[test]
251      fn test_assignment_query_compiles() {
252          let zig = get_zig();
253          assert!(zig.assignment_query().is_some());
254      }
255  
256      #[test]
257      fn test_scope_query_compiles() {
258          let zig = get_zig();
259          assert!(zig.scope_query().is_some());
260      }
261  
262      #[test]
263      fn test_destructure_query_compiles() {
264          let zig = get_zig();
265          assert!(zig.destructure_query().is_some());
266      }
267  }