use tree_sitter::Language;
unsafe extern "C" {
fn tree_sitter_ruby() -> Language;
}
#[must_use = "Language handles must be registered with tree-sitter consumers"]
pub fn language() -> Language {
let lang = unsafe { tree_sitter_ruby() };
sqry_tree_sitter_support::validate_language_or_panic(lang, "Ruby")
}
#[allow(clippy::missing_errors_doc)] pub fn try_language() -> Result<Language, sqry_tree_sitter_support::TreeSitterError> {
let lang = unsafe { tree_sitter_ruby() };
sqry_tree_sitter_support::validate_language(lang)
}
pub const NODE_TYPES: &str = include_str!("../grammar-src/node-types.json");
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_can_load_grammar() {
let lang = language();
assert!(lang.abi_version() > 0);
}
#[test]
fn test_try_language_succeeds() {
assert!(try_language().is_ok());
}
#[test]
#[allow(clippy::const_is_empty)]
fn test_node_types_not_empty() {
assert!(!NODE_TYPES.is_empty());
}
#[test]
fn heredoc_identifier_longer_than_255_chars_does_not_abort() {
let word = "A".repeat(300);
let source = format!("<<~{word}\ncontent\n{word}\n");
let mut parser = tree_sitter::Parser::new();
parser
.set_language(&language())
.expect("Ruby grammar should load");
let tree = parser.parse(&source, None).expect("parse should return");
assert_eq!(tree.root_node().kind(), "program");
}
#[test]
fn serialize_guard_admits_no_heredoc_it_cannot_fit() {
let mut parser = tree_sitter::Parser::new();
parser
.set_language(&language())
.expect("Ruby grammar should load");
for count in 88..=96 {
let openers: Vec<String> = (0..count).map(|i| format!("<<~H{i:06}")).collect();
let source = format!("x = [{}]\n", openers.join(", "));
let tree = parser
.parse(&source, None)
.expect("parse should return for every heredoc count");
assert_eq!(tree.root_node().kind(), "program");
}
}
#[test]
fn incremental_reparse_round_trips_heredoc_scanner_state() {
let mut parser = tree_sitter::Parser::new();
parser
.set_language(&language())
.expect("Ruby grammar should load");
let first = "x = <<~SHORT\ncontent\nSHORT\n";
let mut tree = parser.parse(first, None).expect("parse should return");
assert_eq!(tree.root_node().kind(), "program");
let word = "B".repeat(300);
let appended = format!("y = <<~{word}\ncontent\n{word}\n");
let second = format!("{first}{appended}");
tree.edit(&tree_sitter::InputEdit {
start_byte: first.len(),
old_end_byte: first.len(),
new_end_byte: second.len(),
start_position: tree_sitter::Point::new(3, 0),
old_end_position: tree_sitter::Point::new(3, 0),
new_end_position: tree_sitter::Point::new(6, 0),
});
let reparsed = parser
.parse(&second, Some(&tree))
.expect("incremental parse should return");
assert_eq!(reparsed.root_node().kind(), "program");
}
}