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}