From: "tenderlovemaking (Aaron Patterson) via ruby-core" Date: 2025-01-08T17:22:04+00:00 Subject: [ruby-core:120559] [Ruby master Feature#21005] Update the source location method to include line start/stop and column start/stop details Issue #21005 has been updated by tenderlovemaking (Aaron Patterson). Eregon (Benoit Daloze) wrote in #note-14: > Maybe CRuby does not currently preserve the information of end line and start/end column for procs and methods? I think we do, but I can investigate. IIRC it's on the InstructionSequence object (so we'd still have to use RubyVM::InstructionSequence on CRuby). > For `def` it would be trivial to preserve it but I guess for blocks and `define_method` it might be trickier. > For such cases `source_location` could internally use the `node_id` stuff if that's easier or deemed a better trade-off on CRuby. I _think_ start / column info is always there, but not 100% sure. > In summary: > * I think we can build `Prism.node_for(Proc|Method|UnboundMethod)` on `(Proc|Method|UnboundMethod)#source_location` with start/end line/column. > * Those would all be public APIs working on all Ruby implementations. > * Users don't need to know about low-level implementation-specific (i.e. CRuby-only) concepts like `node_id`. ���� Dan0042 (Daniel DeLorme) wrote in #note-15: > Eregon (Benoit Daloze) wrote in #note-3: > > If it's a new method, I think we should return a "code location" object (could be `Ruby::CodeLocation` or `Ruby::Location` or `Ruby::SourceLocation` or so) and have the following methods (inspired from https://bugs.ruby-lang.org/issues/6012#note-19): > > * start_line > > * end_line > > I really like the idea of a `#source` method that returns a `Ruby::SourceLocation` object. However, when there's a start and end, I believe Ruby should ideally align with its own core conventions and return a `Range`. For example, `method.source.lines => start...end`. While I understand concerns about the allocation of `Range` objects and performance, I feel that: 1) this might be an example of premature micro-optimization, and 2) from an API design perspective, a `Range` object feels like the natural default. Separate `start`/`end` accessors could remain a low-level, performance-focused API if truly necessary. > > As an alternative to `start`/`end` accessors, it would be even better if the `Range`-returning method could be optimized via opcode. Referring back to the idea of `Range#bounds` in #20080, we could have something like `start_line, end_line = method.source.lines.bounds`, which could be optimized via opcode to avoid allocating a `Range` object entirely. > > It would be great to see Ruby continue to embrace its own language idioms and explore such optimizations for a more elegant API. As @mame was pointing out, I don't think a single range for lines makes sense. Consider the following code: ```ruby def foo; <