Feature #6012
openProc#source_location also return the column
Added by rogerdpack (Roger Pack) almost 13 years ago. Updated about 2 months ago.
Description
As originally suggested in http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/42418
Suggestion/feature request:
have #source_location also return the beginning column where it was defined.
["test.rb", 8, 33]
Thanks!
-roger-
Updated by rogerdpack (Roger Pack) almost 13 years ago
oops make that a feature request, but I'm unable to edit them myself.
Cheers!
-r
Updated by nahi (Hiroshi Nakamura) almost 13 years ago
- Tracker changed from Bug to Feature
Updated by ko1 (Koichi Sasada) over 12 years ago
- Category set to core
- Assignee set to nobu (Nobuyoshi Nakada)
- Target version set to 2.0.0
Updated by trans (Thomas Sawyer) over 12 years ago
Would this effect Method#source_location too?
I'm not sure I am really digging this idea. First of all it means I have to go back and fix some code. Secondly it means I have to always worry about the additional piece of data even though most of the time it doesn't matter. And if the return can vary between 2 or 3 elements that's another thing to worry with.
On the other hand I can understand that it could be useful information in some cases.
In times like this that I think "Embrace the Object".
proc.source_location #=> #<SourceLocation @file="foo.rb" @line=12 @column=14>
And then a few different methods could provide that information in various useful forms.
proc.source_location.to_a #=> ["foo.rb", 12, 14]
proc.source_location.to_s #=> "foo.rb:12"
proc.source_location.values_at(:file, :line) #=> ["foo.rb", 12]
Or what have you.
Updated by trans (Thomas Sawyer) over 12 years ago
BTW & OT: When is any one going to explain how we format code examples as monospace text on this site?
Updated by drbrain (Eric Hodel) over 12 years ago
On Feb 26, 2012, at 6:33 AM, Thomas Sawyer wrote:
BTW & OT: When is any one going to explain how we format code examples as monospace text on this site?
Click the RD button and use RD formatting (two spaces).
Here's a bash alias to help, which works for rdoc too.
alias rdindent='pr -l1 -o2'
Updated by trans (Thomas Sawyer) over 12 years ago
Thanks Eric! I ((never)) noticed that ((%RD%)) "button" before (hardly looks like a button).
Why did it put:
=begin
=end
In the textarea when I clicked on it? ... maybe I'll find out by submitting this...
=begin
What's with the =begin =end?
Testing 1 2 3...
Try ((em)) (({code})) ((|ls|)) ((%var%)).
=end
Sorry for the noise.
Updated by trans (Thomas Sawyer) over 12 years ago
Well, that failed miserably. LOL :-)
Updated by shyouhei (Shyouhei Urabe) over 12 years ago
- Status changed from Open to Assigned
Updated by yhara (Yutaka HARA) about 12 years ago
- Target version changed from 2.0.0 to 2.6
Updated by mame (Yusuke Endoh) almost 6 years ago
Now the abstract syntax tree has column information, so we can implement this issue. We even add the last point of method.
# test.rb
◆def foo # ◆: line 2, column 0
end★ # ★: line 3, column 3
p method(:foo).source_location #=> ["test.rb", 2, 0, 3, 3]
Updated by ioquatix (Samuel Williams) almost 6 years ago
If changing this API is too complicated due to backwards compatibility, why not introduce new more general API:
Method#source -> Source.new(path, line_number, line_count, code, ...)
Usage:
method.source.code
method.source.path
method.source.location -> [2, 0, 3, 3]
Maybe including byte offset and length would also be useful (for seek).
Updated by ioquatix (Samuel Williams) almost 6 years ago
I also wish there was some meaningful implementation of proc.source.hash
that was reasonably consistent across invocations of Ruby. Even if it was just best effort.
Updated by ioquatix (Samuel Williams) almost 6 years ago
I was playing around with this idea trying to make an implementation of class Source
.
Is the source file cached in Ruby? Or should we use File.read
to load it into memory?
It seems inefficient for large files, to find line/column offset. It would be nice to have absolute offset to seek to.
Maybe it's possible for source_location
to append one more thing - the actual source code - if possible. This would be useful for situations like eval, where you might define something for a path that doesn't actually exist, but the source code is still available.
Updated by duerst (Martin Dürst) almost 6 years ago
ioquatix (Samuel Williams) wrote:
I also wish there was some meaningful implementation of
proc.source.hash
that was reasonably consistent across invocations of Ruby. Even if it was just best effort.
Please make that a separate feature if you are serious about it.
Updated by Eregon (Benoit Daloze) about 2 months ago
- Related to Feature #17930: Add column information into error backtrace added
Updated by Eregon (Benoit Daloze) about 2 months ago
It seems good to revisit this, the workarounds are pretty messy and CRuby-specific, e.g. https://github.com/rails/rails/pull/53055/files
I think @mame (Yusuke Endoh) 's suggestion in https://bugs.ruby-lang.org/issues/6012#note-12 is fine although I think it would be convenient to also expose the byte offsets (start and end):
.source_location #=> [path, start_line, start_column, start_offset, end_line, end_column, end_offset]
Then it would be really easy to "get the source code of a Proc".
And of course we should do the same for Method/UnboundMethod (#8751).
Updated by Eregon (Benoit Daloze) about 2 months ago · Edited
I also really like @ioquatix (Samuel Williams) 's suggestion in https://bugs.ruby-lang.org/issues/6012#note-13 and it is a lot more flexible and more efficient too (since computing e.g. column information if unused is not cheap).
For instance method.source.code
is great because it completely hides the details how to get the source code and slice it.
TruffleRuby currently keeps the source code in memory and so could provide this automatically without needing to reread the file from disk.
CRuby keeps it but only if RubyVM.keep_script_lines = true
, so then could use that if available and automatically fallback to read the file from disk (great, because we should avoid users/gems referring to RubyVM
in their code).
One question is where would we place/how would we name this class?
We could reuse Thread::Backtrace::Location
as it's quite similar and already has path
, lineno
.
But it's not really related to a backtrace here.
Still it seems quite a good fit, and I don't have much idea where to place it otherwise (top-level Source
seems way too prone for conflicts).
I think in term of the interface we should have:
- start_line
- start_column
- start_offset
- end_line
- end_column
- end_offset
- code: gets the source of the Proc/Method/UnboundMethod
Related and similar ideas in #18231.
Updated by Eregon (Benoit Daloze) about 2 months ago
- Related to Feature #18231: `RubyVM.keep_script_lines` added