Skip to content

Commit b2f5621

Browse files
committed
Handle non-String $LOAD_PATH values more carefully
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.
1 parent 4192683 commit b2f5621

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

lib/irb/completion.rb

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,14 @@ def self.retrieve_gem_and_system_load_path
6060
end
6161
}
6262
}.flatten if defined?(Gem::Specification)
63-
(gem_paths.to_a | $LOAD_PATH).sort
63+
candidates = (gem_paths.to_a | $LOAD_PATH)
64+
candidates.map do |p|
65+
if p.respond_to?(:to_path)
66+
p.to_path
67+
else
68+
String(p) rescue nil
69+
end
70+
end.compact.sort
6471
end
6572

6673
def self.retrieve_files_to_require_from_load_path

test/irb/test_completion.rb

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44

55
module TestIRB
66
class TestCompletion < Test::Unit::TestCase
7+
def setup
8+
# make sure require completion candidates are not cached
9+
IRB::InputCompletor.class_variable_set(:@@files_from_load_path, nil)
10+
end
11+
712
def test_nonstring_module_name
813
begin
914
require "irb/completion"
@@ -84,6 +89,43 @@ def test_complete_require
8489
end
8590
end
8691

92+
def test_complete_require_with_pathname_in_load_path
93+
temp_dir = Dir.mktmpdir
94+
File.write(File.join(temp_dir, "foo.rb"), "test")
95+
test_path = Pathname.new(temp_dir)
96+
$LOAD_PATH << test_path
97+
98+
candidates = IRB::InputCompletor::CompletionProc.("'foo", "require ", "")
99+
assert_equal ["'foo"], candidates
100+
ensure
101+
$LOAD_PATH.pop if test_path
102+
FileUtils.remove_entry(temp_dir) if temp_dir
103+
end
104+
105+
def test_complete_require_with_string_convertable_in_load_path
106+
temp_dir = Dir.mktmpdir
107+
File.write(File.join(temp_dir, "foo.rb"), "test")
108+
object = Object.new
109+
object.define_singleton_method(:to_s) { temp_dir }
110+
$LOAD_PATH << object
111+
112+
candidates = IRB::InputCompletor::CompletionProc.("'foo", "require ", "")
113+
assert_equal ["'foo"], candidates
114+
ensure
115+
$LOAD_PATH.pop if object
116+
FileUtils.remove_entry(temp_dir) if temp_dir
117+
end
118+
119+
def test_complete_require_with_malformed_object_in_load_path
120+
object = Object.new
121+
def object.to_s; raise; end
122+
$LOAD_PATH << object
123+
124+
assert_empty IRB::InputCompletor::CompletionProc.("'foo", "require ", "")
125+
ensure
126+
$LOAD_PATH.pop if object
127+
end
128+
87129
def test_complete_require_library_name_first
88130
pend 'Need to use virtual library paths'
89131
candidates = IRB::InputCompletor::CompletionProc.("'csv", "require ", "")

0 commit comments

Comments
 (0)