Bug #21784
openProc#source_location start column seems strange for -> {}
Description
$ ruby -e 'p -> { a }.source_location'
["-e", 1, 4, 1, 10]
So it considers the stabby lambda to be at:
p -> { a }.source_location
^^^^^^
Note it starts at a whitespace after the ->.
I think it should just include the ->, i.e. return ["-e", 1, 2, 1, 10].
Or possibly start at the {, i.e. return ["-e", 1, 3, 1, 10].
But starting on a whitespace like here seems really strange, it looks like a bug.
It's the same result with --parser=parse.y, so I don't show it.
For context:
For Procs/block it looks like this:
$ ruby -e 'p proc { a }.source_location'
["-e", 1, 7, 1, 12]
p proc { a }.source_location
^^^^^
This looks fine.
The block could of course be given to any other method so it won't always be proc in front.
Maybe it could include the method too (so it would return start column 2 here), I think either is fine.
For for blocks it looks like this:
$ ruby -e '
def self.each(&b); yield b; end;
for b in self
42
end
p b.source_location'
["-e", 3, 0, 5, 3]
That is, it covers the entire for expression from for until end.
I think that's good and fine as-is.
For def methods it covers everything from def to end (or end of line for def m = 42), as expected.
Updated by Eregon (Benoit Daloze) 1 day ago
- Related to Feature #21005: Update the source location method to include line start/stop and column start/stop details added
Updated by Eregon (Benoit Daloze) 1 day ago
- Related to Feature #6012: Proc#source_location also return the column added
Updated by tompng (tomoya ishida) about 21 hours ago
Except the problematic case -> { }, start position consistently excludes whitespaces just after ->.
So I think -> { }'s source location should be { }.
-> ( ) { }.source_location # ["(irb)", 1, 3, 1, 10]
^^^^^^^
-> * { }.source_location # ["(irb)", 1, 3, 1, 8]
^^^^^
-> a { }.source_location # ["(irb)", 1, 3, 1, 8]
^^^^^
-> { }.source_location # ["(irb)", 1, 2, 1, 8]
^^^^^^ (current)
^^^ (expected IMO)
Updated by Eregon (Benoit Daloze) about 20 hours ago
Interesting.
The arguments (parameters) between -> and { are AFAIK integral part of the stabby lambda syntax, so I think it should be either:
- All cases start at the
{:- consistent with non-stabby-lambda Procs
- but does not include the arguments which is an critical part of the lambda declaration (and this is not an issue for non-stabby-lambda Procs as the arguments come after
{like{ |args|)
- All cases start at the
->- covers the whole expression
- intuitive, I think most users would expect this one
- Also enables e.g.
eval()'ing the source string (in the right context) - Consistent with
for
Starting at the arguments but skipping -> and some spaces seems strange/inconsistent.
Updated by zverok (Victor Shepelev) about 20 hours ago
I too, would expect the whole expression to be covered. This would be also consistent with Method#source_location which includes def (and not starts from the argument, or from the beginning of the body).
Updated by Eregon (Benoit Daloze) about 16 hours ago
I made a PR to fix this: https://github.com/ruby/ruby/pull/15568
Looking at https://github.com/ruby/ruby/pull/9872/files it's clear in Prism it was just done to be compatible with parse.y.
And in parse.y it's probably not intentional to use the beginning of the args as the start location for the scope, the whole -> {} defines a new scope.
In fact the lambda itself already had the right location with RubyVM::AbstractSyntaxTree, just the scope within it had the wrong location:
$ RUBYOPT=--parser=parse.y irb
irb(main):001> l = -> { a }
=> #<Proc:0x00007fc276e9d8c0 (irb):1 (lambda)>
irb(main):002> a=RubyVM::AbstractSyntaxTree.of(l)
=>
(LAMBDA@1:4-1:12
...
irb(main):003> a.locations
=>
[#<RubyVM::AbstractSyntaxTree::Location:@1:4-1:12>,
#<RubyVM::AbstractSyntaxTree::Location:@1:4-1:6>,
#<RubyVM::AbstractSyntaxTree::Location:@1:7-1:8>,
#<RubyVM::AbstractSyntaxTree::Location:@1:11-1:12>]
irb(main):004> a
=>
(LAMBDA@1:4-1:12
(SCOPE@1:6-1:12
tbl: []
args:
(ARGS@1:6-1:6
pre_num: 0
pre_init: nil
opt: nil
first_post: nil
post_num: 0
post_init: nil
rest: nil
kw: nil
kwrest: nil
block: nil)
body: (VCALL@1:9-1:10 :a)))
Updated by matz (Yukihiro Matsumoto) about 10 hours ago
The column information from source_location will be canceled in 4.0. Let us discuss for the future. I think it's a matter of taste. I don't really care much.
Matz.