Skip to content

Commit

Permalink
Handle non-String $LOAD_PATH values more carefully
Browse files Browse the repository at this point in the history
In addition to String values, $LOAD_PATH can also take objects that
respond_to the `to_path` method, like Pathname objects. So `irb` should
be able to handle those objects too.

And if $LOAD_PATH contains objects that can't be converted into String,
`irb` should simply ignore it.
  • Loading branch information
st0012 committed Sep 20, 2022
1 parent 4192683 commit 67a8e79
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 1 deletion.
9 changes: 8 additions & 1 deletion lib/irb/completion.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,14 @@ def self.retrieve_gem_and_system_load_path
end
}
}.flatten if defined?(Gem::Specification)
(gem_paths.to_a | $LOAD_PATH).sort
candidates = (gem_paths.to_a | $LOAD_PATH)
candidates.map do |p|
if p.respond_to?(:to_path)
p.to_path
else
String(p) rescue nil
end
end.compact.sort
end

def self.retrieve_files_to_require_from_load_path
Expand Down
28 changes: 28 additions & 0 deletions test/irb/test_completion.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@

module TestIRB
class TestCompletion < Test::Unit::TestCase
def setup
# make sure require completion candidates are not cached
IRB::InputCompletor.class_variable_set(:@@files_from_load_path, nil)
end

def test_nonstring_module_name
begin
require "irb/completion"
Expand Down Expand Up @@ -84,6 +89,29 @@ def test_complete_require
end
end

def test_complete_require_with_pathname_in_load_path
temp_dir = Dir.mktmpdir
File.write(File.join(temp_dir, "foo.rb"), "test")
test_path = Pathname.new(temp_dir.to_s)
$LOAD_PATH << test_path

candidates = IRB::InputCompletor::CompletionProc.("'foo", "require ", "")
assert_equal ["'foo"], candidates
ensure
$LOAD_PATH.pop if test_path
FileUtils.remove_entry(temp_dir) if temp_dir
end

def test_complete_require_with_malformed_object_in_load_path
object = Object.new
def object.to_s; raise; end
$LOAD_PATH << object

assert_empty IRB::InputCompletor::CompletionProc.("'foo", "require ", "")
ensure
$LOAD_PATH.pop if object
end

def test_complete_require_library_name_first
pend 'Need to use virtual library paths'
candidates = IRB::InputCompletor::CompletionProc.("'csv", "require ", "")
Expand Down

0 comments on commit 67a8e79

Please sign in to comment.