tree_sitter_groovy_sqry/lib.rs
1//! Tree-sitter grammar for Groovy (vendored for sqry)
2//!
3//! This is a first-party binding maintained in the sqry repository.
4//!
5//! **Source Grammar**: <https://github.com/murtaza64/tree-sitter-groovy>
6//! **Commit**: 86911590a8e46d71301c66468e5620d9faa5b6af
7//! **Date**: 2025-01-22
8//! **License**: MIT
9
10use tree_sitter::Language;
11
12unsafe extern "C" {
13 fn tree_sitter_groovy() -> Language;
14}
15
16/// Returns the tree-sitter Language for Groovy
17///
18/// # Panics
19///
20/// Panics if the loaded grammar fails validation:
21/// - Null pointer returned from C library
22/// - ABI version mismatch (outside 9-14 range)
23/// - Incompatible version (below tree-sitter minimum)
24/// - Invalid grammar (zero node kinds)
25///
26/// These failures indicate a serious build or linking problem that cannot
27/// be recovered from at runtime.
28///
29/// # Safety
30///
31/// This function wraps an `unsafe` FFI call to `tree_sitter_groovy()`.
32/// The returned Language handle is validated before being exposed to prevent
33/// undefined behavior from invalid pointers or ABI mismatches.
34#[must_use = "Language handles must be registered with tree-sitter consumers"]
35pub fn language() -> Language {
36 // SAFETY: tree_sitter_groovy() is an extern C function from the linked
37 // tree-sitter-groovy library. We immediately validate the returned Language
38 // handle (including null-pointer check) before any dereference occurs.
39 // If validation fails, we panic (per infallible API contract).
40 // The C library is assumed to be correctly built and linked (cargo
41 // build-time invariant).
42 let lang = unsafe { tree_sitter_groovy() };
43 sqry_tree_sitter_support::validate_language_or_panic(lang, "Groovy")
44}
45
46/// Returns the tree-sitter Language for Groovy, with error handling
47///
48/// This is a fallible alternative to [`language()`] for use cases that need
49/// to handle grammar loading errors gracefully.
50///
51/// # Errors
52///
53/// Returns an error if the loaded grammar fails validation. See
54/// [`sqry_tree_sitter_support::TreeSitterError`] for possible error variants.
55pub fn try_language() -> Result<Language, sqry_tree_sitter_support::TreeSitterError> {
56 // SAFETY: Same as language(), but with Result instead of panic
57 let lang = unsafe { tree_sitter_groovy() };
58 sqry_tree_sitter_support::validate_language(lang)
59}
60
61/// The content of the [`node-types.json`][] file for this grammar.
62///
63/// [`node-types.json`]: https://tree-sitter.github.io/tree-sitter/using-parsers#static-node-types
64pub const NODE_TYPES: &str = include_str!("../grammar-src/node-types.json");
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test]
71 fn test_can_load_grammar() {
72 let lang = language();
73 assert!(
74 lang.abi_version() > 0,
75 "Language ABI version should be non-zero"
76 );
77 }
78
79 #[test]
80 fn test_try_language_succeeds() {
81 let result = try_language();
82 assert!(
83 result.is_ok(),
84 "try_language() should succeed for valid grammar"
85 );
86 let lang = result.unwrap();
87 assert!(lang.abi_version() > 0);
88 }
89
90 #[test]
91 #[allow(clippy::const_is_empty)]
92 fn test_node_types_not_empty() {
93 assert!(!NODE_TYPES.is_empty(), "Node types should not be empty");
94 }
95}