From 9306948a8b04d5faa880d3b7da97e14d1f0f929f Mon Sep 17 00:00:00 2001 From: Soutaro Matsumoto Date: Tue, 24 Mar 2026 17:54:09 +0900 Subject: [PATCH] Include trailing colon in RBS keyword parameter offset Align RBS keyword parameter offsets with Ruby indexer behavior. The RBS indexer now includes the trailing colon in the offset for required and optional keyword parameters (e.g. `name:` instead of `name`). Adds `Offset::extend_end` helper to adjust byte ranges. Co-Authored-By: Claude Opus 4.6 (1M context) --- rust/rubydex/src/indexing/rbs_indexer.rs | 14 ++++++++------ rust/rubydex/src/offset.rs | 9 +++++++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/rust/rubydex/src/indexing/rbs_indexer.rs b/rust/rubydex/src/indexing/rbs_indexer.rs index 239934af..b5823a3d 100644 --- a/rust/rubydex/src/indexing/rbs_indexer.rs +++ b/rust/rubydex/src/indexing/rbs_indexer.rs @@ -271,14 +271,16 @@ impl<'a> RBSIndexer<'a> { for (key, _value) in function_node.required_keywords().iter() { let name = self.source_at(&key.location()); - let offset = Offset::from_rbs_location(&key.location()); + // Extend offset by 1 to include the trailing colon, matching Ruby indexer behavior + let offset = Offset::from_rbs_location(&key.location()).extend_end(1); let str_id = self.local_graph.intern_string(name); parameters.push(Parameter::RequiredKeyword(ParameterStruct::new(offset, str_id))); } for (key, _value) in function_node.optional_keywords().iter() { let name = self.source_at(&key.location()); - let offset = Offset::from_rbs_location(&key.location()); + // Extend offset by 1 to include the trailing colon, matching Ruby indexer behavior + let offset = Offset::from_rbs_location(&key.location()).extend_end(1); let str_id = self.local_graph.intern_string(name); parameters.push(Parameter::OptionalKeyword(ParameterStruct::new(offset, str_id))); } @@ -1257,12 +1259,12 @@ mod tests { assert_parameter!(&def.signatures().as_slice()[0][4], RequiredKeyword, |param| { assert_string_eq!(context, param.str(), "name"); - assert_offset_string!(context, param.offset(), "name"); + assert_offset_string!(context, param.offset(), "name:"); }); assert_parameter!(&def.signatures().as_slice()[0][5], OptionalKeyword, |param| { assert_string_eq!(context, param.str(), "age"); - assert_offset_string!(context, param.offset(), "age"); + assert_offset_string!(context, param.offset(), "age:"); }); assert_parameter!(&def.signatures().as_slice()[0][6], RestKeyword, |param| { @@ -1298,12 +1300,12 @@ mod tests { assert_parameter!(&def.signatures().as_slice()[0][4], RequiredKeyword, |param| { assert_string_eq!(context, param.str(), "name"); - assert_offset_string!(context, param.offset(), "name"); + assert_offset_string!(context, param.offset(), "name:"); }); assert_parameter!(&def.signatures().as_slice()[0][5], OptionalKeyword, |param| { assert_string_eq!(context, param.str(), "age"); - assert_offset_string!(context, param.offset(), "age"); + assert_offset_string!(context, param.offset(), "age:"); }); assert_parameter!(&def.signatures().as_slice()[0][6], RestKeyword, |param| { diff --git a/rust/rubydex/src/offset.rs b/rust/rubydex/src/offset.rs index 7bef5199..efdff4ca 100644 --- a/rust/rubydex/src/offset.rs +++ b/rust/rubydex/src/offset.rs @@ -74,6 +74,15 @@ impl Offset { self.end } + /// Returns a new offset with the end extended by the given number of bytes. + #[must_use] + pub const fn extend_end(self, bytes: u32) -> Self { + Self { + start: self.start, + end: self.end + bytes, + } + } + /// Converts an offset to a display range like `1:1-1:5` #[must_use] pub fn to_display_range(&self, document: &Document) -> String {