Skip to content

Commit

Permalink
Refactor eval_path and SourceFinder::Source (#870)
Browse files Browse the repository at this point in the history
* Assign `@eval_path` through `irb_path=` method

This simplifies the original caching logic for the `eval_path` method
and makes it easier to understand.

* Refactor SourceFinder::Source
  • Loading branch information
st0012 authored Feb 13, 2024
1 parent 239683a commit c63e4c4
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 28 deletions.
42 changes: 26 additions & 16 deletions lib/irb/context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def initialize(irb, workspace = nil, input_method = nil)
else
@irb_name = IRB.conf[:IRB_NAME]+"#"+IRB.JobManager.n_jobs.to_s
end
@irb_path = "(" + @irb_name + ")"
self.irb_path = "(" + @irb_name + ")"

case input_method
when nil
Expand Down Expand Up @@ -121,11 +121,11 @@ def initialize(irb, workspace = nil, input_method = nil)
when '-'
@io = FileInputMethod.new($stdin)
@irb_name = '-'
@irb_path = '-'
self.irb_path = '-'
when String
@io = FileInputMethod.new(input_method)
@irb_name = File.basename(input_method)
@irb_path = input_method
self.irb_path = input_method
else
@io = input_method
end
Expand Down Expand Up @@ -246,9 +246,27 @@ def main
# Can be either name from <code>IRB.conf[:IRB_NAME]</code>, or the number of
# the current job set by JobManager, such as <code>irb#2</code>
attr_accessor :irb_name
# Can be either the #irb_name surrounded by parenthesis, or the
# +input_method+ passed to Context.new
attr_accessor :irb_path

# Can be one of the following:
# - the #irb_name surrounded by parenthesis
# - the +input_method+ passed to Context.new
# - the file path of the current IRB context in a binding.irb session
attr_reader :irb_path

# Sets @irb_path to the given +path+ as well as @eval_path
# @eval_path is used for evaluating code in the context of IRB session
# It's the same as irb_path, but with the IRB name postfix
# This makes sure users can distinguish the methods defined in the IRB session
# from the methods defined in the current file's context, especially with binding.irb
def irb_path=(path)
@irb_path = path

if File.exist?(path)
@eval_path = "#{path}(#{IRB.conf[:IRB_NAME]})"
else
@eval_path = path
end
end

# Whether multiline editor mode is enabled or not.
#
Expand Down Expand Up @@ -557,7 +575,7 @@ def evaluate(line, line_no) # :nodoc:

if IRB.conf[:MEASURE] && !IRB.conf[:MEASURE_CALLBACKS].empty?
last_proc = proc do
result = @workspace.evaluate(line, eval_path, line_no)
result = @workspace.evaluate(line, @eval_path, line_no)
end
IRB.conf[:MEASURE_CALLBACKS].inject(last_proc) do |chain, item|
_name, callback, arg = item
Expand All @@ -568,20 +586,12 @@ def evaluate(line, line_no) # :nodoc:
end
end.call
else
result = @workspace.evaluate(line, eval_path, line_no)
result = @workspace.evaluate(line, @eval_path, line_no)
end

set_last_value(result)
end

private def eval_path
# We need to use differente path to distinguish source_location of method defined in the actual file and method defined in irb session.
if !defined?(@irb_path_existence) || @irb_path_existence[0] != irb_path
@irb_path_existence = [irb_path, File.exist?(irb_path)]
end
@irb_path_existence[1] ? "#{irb_path}(#{IRB.conf[:IRB_NAME]})" : irb_path
end

def inspect_last_value # :nodoc:
@inspect_method.inspect_value(@last_value)
end
Expand Down
6 changes: 3 additions & 3 deletions lib/irb/ext/loader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,13 @@ def load_file(path, priv = nil)

def old # :nodoc:
back_io = @io
back_path = @irb_path
back_path = irb_path
back_name = @irb_name
back_scanner = @irb.scanner
begin
@io = FileInputMethod.new(path)
@irb_name = File.basename(path)
@irb_path = path
self.irb_path = path
@irb.signal_status(:IN_LOAD) do
if back_io.kind_of?(FileInputMethod)
@irb.eval_input
Expand All @@ -119,7 +119,7 @@ def old # :nodoc:
ensure
@io = back_io
@irb_name = back_name
@irb_path = back_path
self.irb_path = back_path
@irb.scanner = back_scanner
end
end
Expand Down
13 changes: 8 additions & 5 deletions lib/irb/source_finder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def file_content

def colorized_content
if !binary_file? && file_exist?
end_line = Source.find_end(file_content, @line)
end_line = find_end
# To correctly colorize, we need to colorize full content and extract the relevant lines.
colored = IRB::Color.colorize_code(file_content)
colored.lines[@line - 1...end_line].join
Expand All @@ -36,9 +36,12 @@ def colorized_content
end
end

def self.find_end(code, first_line)
private

def find_end
lex = RubyLex.new
lines = code.lines[(first_line - 1)..-1]
code = file_content
lines = code.lines[(@line - 1)..-1]
tokens = RubyLex.ripper_lex_without_warning(lines.join)
prev_tokens = []

Expand All @@ -49,10 +52,10 @@ def self.find_end(code, first_line)
continue = lex.should_continue?(prev_tokens)
syntax = lex.check_code_syntax(code, local_variables: [])
if !continue && syntax == :valid
return first_line + lnum
return @line + lnum
end
end
first_line
@line
end
end

Expand Down
11 changes: 7 additions & 4 deletions test/irb/test_context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -666,13 +666,16 @@ def test_lineno
], out)
end

def test_eval_path
def test_irb_path_setter
@context.irb_path = __FILE__
assert_equal("#{__FILE__}(irb)", @context.send(:eval_path))
assert_equal(__FILE__, @context.irb_path)
assert_equal("#{__FILE__}(irb)", @context.instance_variable_get(:@eval_path))
@context.irb_path = 'file/does/not/exist'
assert_equal('file/does/not/exist', @context.send(:eval_path))
assert_equal('file/does/not/exist', @context.irb_path)
assert_equal('file/does/not/exist', @context.instance_variable_get(:@eval_path))
@context.irb_path = "#{__FILE__}(irb)"
assert_equal("#{__FILE__}(irb)", @context.send(:eval_path))
assert_equal("#{__FILE__}(irb)", @context.irb_path)
assert_equal("#{__FILE__}(irb)", @context.instance_variable_get(:@eval_path))
end

def test_build_completor
Expand Down

0 comments on commit c63e4c4

Please sign in to comment.