[rust] add node_ext module with full_name methods for constant nodes#3887
[rust] add node_ext module with full_name methods for constant nodes#3887
node_ext module with full_name methods for constant nodes#3887Conversation
node_ext module with full_name methods for constant nodesnode_ext module with full_name methods for constant nodes
Port Ruby's `node_ext.rb` functionality to Rust bindings, providing `full_name` and `full_name_parts` methods for `ConstantReadNode`, `ConstantWriteNode`, `ConstantTargetNode`, `ConstantPathNode`, and `ConstantPathTargetNode`. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
ed95c4e to
f3f9590
Compare
rust/ruby-prism/src/node_ext.rs
Outdated
| /// assert_eq!(constant.full_name_parts(), vec!["Foo"]); | ||
| /// ``` | ||
| #[must_use] | ||
| pub fn full_name_parts(&self) -> Vec<Cow<'pr, str>> { |
There was a problem hiding this comment.
Why copy on write here?
There was a problem hiding this comment.
The Cow<'pr, str> was a byproduct of using String::from_utf8_lossy(), which returns Cow<'_, str>. It was not an intentional design choice. Addressed in ec991ae by switching to &'pr [u8], which removed the need for Cow entirely.
rust/ruby-prism/src/node_ext.rs
Outdated
| /// ``` | ||
| #[must_use] | ||
| pub fn full_name(&self) -> Cow<'pr, str> { | ||
| String::from_utf8_lossy(self.name().as_slice()) |
There was a problem hiding this comment.
I don't feel great about utf8 here, it's not guaranteed by the parser (there are ~90 encodings supported).
There was a problem hiding this comment.
Good point. Fixed in ec991ae by switching from String::from_utf8_lossy / Cow<str> to raw &'pr [u8], so we no longer assume any specific encoding.
Address review feedback: stop assuming UTF-8 encoding since the parser supports ~90 encodings. Return &[u8] / Vec<u8> instead of Cow<str> / String to avoid silently corrupting non-UTF-8 data via from_utf8_lossy. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Thanks for the review!
The
Agreed. I've updated the PR to return raw bytes ( |
rust/ruby-prism/src/node_ext.rs
Outdated
| let mut parts = Vec::new(); | ||
| let mut current: Option<Node<'pr>> = Some(self.as_node()); | ||
|
|
||
| while let Some(ref node) = current { |
There was a problem hiding this comment.
Can we make full_name and full_name_parts into a trait? It is an interface, and it should make the ConstantPathNode implementation simpler.
There was a problem hiding this comment.
Done in 33b4e6f. Extracted a FullName<'pr> trait with full_name_parts and a default full_name implementation. This simplified the ConstantPathNode impl significantly — replaced the iterative while-loop + reverse() + is_stovetop() pattern with recursive delegation via a full_name_parts_for_node helper.
Address review feedback: make full_name and full_name_parts into a FullName trait. This simplifies the ConstantPathNode implementation by replacing the iterative while-loop + reverse + is_stovetop pattern with recursive delegation via a helper function. The default full_name implementation in the trait also eliminates duplicate join logic. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
node_ext.rbfunctionality to Rust bindingsFullNametrait withfull_nameandfull_name_partsmethods, implemented forConstantReadNode,ConstantWriteNode,ConstantTargetNode,ConstantPathNode, andConstantPathTargetNodeConstantPathErrorenum for error handlingTest Coverage
Rust bindings include 11 unit tests compared to Ruby's 8 tests. Additional coverage includes:
ConstantWriteNode(not tested in Ruby)ConstantTargetNode(not tested in Ruby)MissingNodeserror case (not tested in Ruby)Public API Changes (cargo-public-api)
Test plan
bundle exec rake cargo:testpassesbundle exec rake cargo:lintpasses🤖 Generated with Claude Code