From: "Eregon (Benoit Daloze) via ruby-core" Date: 2026-05-26T20:39:42+00:00 Subject: [ruby-core:125577] [Ruby Feature#21998] Add {Method,UnboundMethod,Proc}#source_range Issue #21998 has been updated by Eregon (Benoit Daloze). PR is ready: https://github.com/ruby/ruby/pull/16835 When implementing I realized it's not a good idea to have the start of the `Ruby::SourceRange` to be the `p` of `proc { foo }`. It should be the `{`/`do` for a bunch of reasons: * That's what is currently used by `{ methods: true }` coverage in `test_method_coverage_for_define_method`. * That's what the extended `source_location` used. * That's what the compilers (compile.c, prism_compile.c) expect, and changing that is awkward (`rb_iseq_compile_node()` expects a `NODE_SCOPE`, which is the block in this context, and the `ISEQ_BODY(block_iseq)->location.code_location` should rather clearly refer to the block only, not including the call, because `rb_iseq_compile_node()` compiles the block, not the call, so it seems weird to give it a wider `code_location`). * When talking about the "source location/range" of "a block" I believe most people will expect from the `{`/`do`, not from the call to which the block is given. * The many reasons @headius mentioned. There are a few benefits to include the call, but I don't think they can compare to these, so let's not include the call. --- More details: You can see the complications in compile.c, prism_compile.c as reverted in [this commit](https://github.com/ruby/ruby/pull/16835/changes/9ec948fa7bacbf0f409dcd83c83eba73424f1d1d#diff-a5ba41b51e3655f9f244362a616282b5119d3e15dd6c52ee999bbdfcc5b86a77). So to include the call we actually have to overwrite the `code_location` of the block iseq, which doesn't feel nice and conceptually introduces separate compile & location nodes, which seems clearly not worth it. If we decide to include the call we'd also need to change Coverage information, which I don't think is a good idea. It would mean for `methods: true` Coverage we'd get `define_method(:a) do; end` for method `a` instead of `do; end`. If it was something like `define_method((sleep(1); :a)) do; end` it'd be misleading to include the call, because the `sleep(1)` is not executed in that method but outside. ---------------------------------------- Feature #21998: Add {Method,UnboundMethod,Proc}#source_range https://bugs.ruby-lang.org/issues/21998#change-117407 * Author: Eregon (Benoit Daloze) * Status: Open ---------------------------------------- I'm using matz's suggestion almost as-is from https://bugs.ruby-lang.org/issues/6012#note-53. The only change is the proposed class name. ## Use Cases Use cases have been discussed extensively and matz said: > The use cases are real and I want to support them So I think we don't need to discuss that anymore :) ## Background Adding column and last line information to `#source_location` is deemed too incompatible given the usages of `obj.source_location.last` which expect the start line (they would get the end column instead). ## Proposal So instead we add a new method, `{Method,UnboundMethod,Proc}#source_range`, which returns a `Ruby::SourceRange` and has these methods: * `start_line`: 1-indexed (same as `source_location.first`) * `end_line`: 1-indexed * `start_column`: in bytes, 0-indexed, I think `start_byte_column` could be good for extra clarity * `end_column`: in bytes, 0-indexed, I think `end_byte_column` could be good for extra clarity * `inspect` which shows something like `#`. For the edge case of a heredoc spanning further than the end of a method/block, we would not include it in the `end_line` & `end_column` methods, but instead document it and provide a small code snippet in the docs to compute that if desired with Prism. ## Alternative An alternative could be a `Ruby::SourceLocation` class and `obj.source_location(object: true)`/`obj.source_location(extended: true)` but it feels less nice. Since we are designing something new I think it's best to go for the cleanest design. ## Consistency The above methods match the name of methods on `Prism::Node` and have the same semantics, which is good for consistency and to avoid confusion. ## Scope The scope is intentionally minimal to keep the discussion focused. ## Implementation I'm happy to implement this, it should be pretty trivial and very similar to the extended `source_location`. I would prefer to get an approval for this feature before implementing. -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/