Skip to main content

tree_sitter_plsql_sqry/
lib.rs

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