Skip to content

Commit 3f9d4fa

Browse files
authored
Merge pull request #2864 from ruby/rust-parser-fix
Rust improvements
2 parents 30245c6 + 4b08eb4 commit 3f9d4fa

File tree

3 files changed

+73
-2
lines changed

3 files changed

+73
-2
lines changed

.github/workflows/rust.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ jobs:
4141
run: |
4242
cd rust
4343
cargo test --verbose
44+
- name: Test publish crates
45+
run: |
46+
cd rust
47+
cargo publish --dry-run
4448
4549
lint:
4650
name: cargo:lint

rust/ruby-rbs/src/node/mod.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@ pub fn parse(rbs_code: &[u8]) -> Result<SignatureNode<'_>, String> {
1616
unsafe {
1717
let start_ptr = rbs_code.as_ptr() as *const i8;
1818
let end_ptr = start_ptr.add(rbs_code.len());
19+
let bytes = rbs_code.len() as i32;
1920

2021
let raw_rbs_string_value = rbs_string_new(start_ptr, end_ptr);
2122

2223
let encoding_ptr = &rbs_encodings[RBS_ENCODING_UTF_8 as usize] as *const rbs_encoding_t;
23-
let parser = rbs_parser_new(raw_rbs_string_value, encoding_ptr, 0, rbs_code.len() as i32);
24+
let parser = rbs_parser_new(raw_rbs_string_value, encoding_ptr, 0, bytes);
2425

2526
let mut signature: *mut rbs_signature_t = std::ptr::null_mut();
2627
let result = rbs_parse_signature(parser, &mut signature);
@@ -34,7 +35,18 @@ pub fn parse(rbs_code: &[u8]) -> Result<SignatureNode<'_>, String> {
3435
if result {
3536
Ok(signature_node)
3637
} else {
37-
Err(String::from("Failed to parse RBS signature"))
38+
let error_message = (*parser)
39+
.error
40+
.as_ref()
41+
.filter(|error| !error.message.is_null())
42+
.map(|error| {
43+
std::ffi::CStr::from_ptr(error.message)
44+
.to_string_lossy()
45+
.into_owned()
46+
})
47+
.unwrap_or_else(|| String::from("Failed to parse RBS signature"));
48+
49+
Err(error_message)
3850
}
3951
}
4052
}
@@ -267,6 +279,14 @@ impl SymbolNode<'_> {
267279
mod tests {
268280
use super::*;
269281

282+
#[test]
283+
fn test_parse_error_contains_actual_message() {
284+
let rbs_code = "class { end";
285+
let result = parse(rbs_code.as_bytes());
286+
let error_message = result.unwrap_err();
287+
assert_eq!(error_message, "expected one of class/module/constant name");
288+
}
289+
270290
#[test]
271291
fn test_parse() {
272292
let rbs_code = r#"type foo = "hello""#;

rust/ruby-rbs/tests/sanity.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
use std::path::Path;
2+
3+
use ruby_rbs::node::parse;
4+
5+
fn collect_rbs_files(dir: &Path) -> Vec<std::path::PathBuf> {
6+
let mut files = Vec::new();
7+
8+
for entry in std::fs::read_dir(dir).unwrap() {
9+
let entry = entry.unwrap();
10+
let path = entry.path();
11+
12+
if path.is_dir() {
13+
files.extend(collect_rbs_files(&path));
14+
} else if path.extension().is_some_and(|ext| ext == "rbs") {
15+
files.push(path);
16+
}
17+
}
18+
19+
files
20+
}
21+
22+
#[test]
23+
fn all_included_rbs_can_be_parsed() {
24+
let repo_root = Path::new(env!("CARGO_MANIFEST_DIR")).join("../..");
25+
let dirs = [repo_root.join("core"), repo_root.join("stdlib")];
26+
27+
let mut files: Vec<_> = dirs.iter().flat_map(|d| collect_rbs_files(d)).collect();
28+
files.sort();
29+
assert!(!files.is_empty());
30+
31+
let mut failures = Vec::new();
32+
33+
for file in &files {
34+
let content = std::fs::read_to_string(file).unwrap();
35+
36+
if let Err(e) = parse(content.as_bytes()) {
37+
failures.push(format!("{}: {}", file.display(), e));
38+
}
39+
}
40+
41+
assert!(
42+
failures.is_empty(),
43+
"Failed to parse {} RBS file(s):\n{}",
44+
failures.len(),
45+
failures.join("\n")
46+
);
47+
}

0 commit comments

Comments
 (0)