Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions rust/ruby-rbs/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ fn generate(config: &Config) -> Result<(), Box<dyn Error>> {
// TODO: Go through all of the nodes and generate the structs to back them up
for node in &config.nodes {
writeln!(file, "#[allow(dead_code)]")?; // TODO: Remove this once all nodes that need parser are implemented
writeln!(file, "#[derive(Debug)]")?;
writeln!(file, "pub struct {} {{", node.rust_name)?;
writeln!(file, " parser: *mut rbs_parser_t,")?;
writeln!(
Expand Down Expand Up @@ -188,6 +189,7 @@ fn generate(config: &Config) -> Result<(), Box<dyn Error>> {
}

// Generate the Node enum to wrap all of the structs
writeln!(file, "#[derive(Debug)]")?;
writeln!(file, "pub enum Node {{")?;
for node in &config.nodes {
let variant_name = node
Expand Down
38 changes: 35 additions & 3 deletions rust/ruby-rbs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ static INIT: Once = Once::new();
/// let signature = parse(rbs_code.as_bytes());
/// assert!(signature.is_ok(), "Failed to parse RBS signature");
/// ```
pub fn parse(rbs_code: &[u8]) -> Result<*mut rbs_signature_t, String> {
pub fn parse(rbs_code: &[u8]) -> Result<SignatureNode, String> {
unsafe {
INIT.call_once(|| {
rbs_constant_pool_init(RBS_GLOBAL_CONSTANT_POOL, 26);
Expand All @@ -30,16 +30,27 @@ pub fn parse(rbs_code: &[u8]) -> Result<*mut rbs_signature_t, String> {
let mut signature: *mut rbs_signature_t = std::ptr::null_mut();
let result = rbs_parse_signature(parser, &mut signature);

rbs_parser_free(parser);
let signature_node = SignatureNode {
parser,
pointer: signature,
};

if result {
Ok(signature)
Ok(signature_node)
} else {
Err(String::from("Failed to parse RBS signature"))
}
}
}

impl Drop for SignatureNode {
fn drop(&mut self) {
unsafe {
rbs_parser_free(self.parser);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@amomchilov one doubt we had that I wanted to double check with you: does this also free all of the nodes thanks to the arena allocator? Or do we also need to free the nodes?

Copy link
Author

@alexcrocha alexcrocha Nov 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll fix it forward if necessary. Merging as is for now.

}
}
}

pub struct NodeListIter {
parser: *mut rbs_parser_t,
current: *mut rbs_node_list_node_t,
Expand Down Expand Up @@ -140,6 +151,7 @@ impl RBSLocationList {
}
}

#[derive(Debug)]
pub struct RBSString {
pointer: *const rbs_string_t,
}
Expand Down Expand Up @@ -223,4 +235,24 @@ mod tests {
let signature2 = parse(rbs_code2.as_bytes());
assert!(signature2.is_ok(), "Failed to parse RBS signature");
}

#[test]
fn test_parse_integer() {
let rbs_code = r#"type foo = 1"#;
let signature = parse(rbs_code.as_bytes());
assert!(signature.is_ok(), "Failed to parse RBS signature");

let signature_node = signature.unwrap();
if let Node::TypeAlias(node) = signature_node.declarations().iter().next().unwrap()
&& let Node::LiteralType(literal) = node.type_()
&& let Node::Integer(integer) = literal.literal()
{
assert_eq!(
"1".to_string(),
String::from_utf8(integer.string_representation().as_bytes().to_vec()).unwrap()
);
} else {
panic!("No literal type node found");
}
}
}
Loading