Skip to content

Commit 2da03f8

Browse files
authored
Merge pull request #6 from ruby/remove_duplicated_require_paths
Dedupe require paths completion
2 parents de008f3 + 6e72b89 commit 2da03f8

File tree

2 files changed

+53
-4
lines changed

2 files changed

+53
-4
lines changed

lib/repl_type_completor/require_paths.rb

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,14 @@ def require_completions(target_path)
88
target ||= ''
99
paths = with_cache [:require_completions, dir] do
1010
gem_and_system_load_paths.flat_map do |load_path|
11+
reject_prefixes = gem_and_system_load_paths.filter_map do |lp|
12+
lp.delete_prefix(load_path).delete_prefix('/').delete_suffix('/') + '/' if lp.start_with? load_path
13+
end.reject(&:empty?)
1114
base_dir = File.absolute_path(File.join(load_path, *dir))
1215
with_cache [:requireable_paths, base_dir] do
13-
requireable_paths(base_dir)
16+
requireable_paths(base_dir, reject_prefixes: reject_prefixes)
1417
end
15-
end.sort
18+
end.uniq.sort
1619
end
1720
paths.filter_map do |path|
1821
[*dir, path].join('/') if path.start_with?(target)
@@ -59,14 +62,16 @@ def gem_and_system_load_paths
5962
end.sort
6063
end
6164

62-
def requireable_paths(base_dir)
65+
def requireable_paths(base_dir, reject_prefixes: [])
6366
ext = ".{rb,#{RbConfig::CONFIG['DLEXT']}}"
6467
ext_regexp = /\.(rb|#{RbConfig::CONFIG['DLEXT']})\z/
6568
files = Dir.glob(["*#{ext}", "*/*#{ext}"], base: base_dir).map { |p| p.sub(ext_regexp, '') }
6669
dirs = Dir.glob('*/*', base: base_dir).filter_map do |path|
6770
"#{path}/" if File.directory?(File.join(base_dir, path))
6871
end
69-
(files + dirs).sort
72+
(files + dirs).sort.reject do |path|
73+
reject_prefixes.any? { path.start_with?(_1) }
74+
end
7075
rescue Errno::EPERM
7176
[]
7277
end

test/repl_type_completor/test_require_paths.rb

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
require 'repl_type_completor'
44
require_relative './helper'
5+
require 'tmpdir'
56

67
module TestReplTypeCompletor
78
class RequirePathsTest < TestCase
@@ -22,5 +23,48 @@ def test_require_relative_paths
2223
assert_not_include ReplTypeCompletor::RequirePaths.require_relative_completions('li', project_root), 'lib/repl_type_completor/version'
2324
assert_include ReplTypeCompletor::RequirePaths.require_relative_completions('lib/', project_root), 'lib/repl_type_completor/version'
2425
end
26+
27+
def clear_cache
28+
ReplTypeCompletor::RequirePaths.instance_eval do
29+
remove_instance_variable(:@gem_and_system_load_paths) if defined? @gem_and_system_load_paths
30+
remove_instance_variable(:@cache) if defined? @cache
31+
end
32+
end
33+
34+
def test_require_paths_no_duplication
35+
# When base_dir/ base_dir/3.3.0 base_dir/3.3.0/arm64-darwin are in $LOAD_PATH,
36+
# "3.3.0/arm64-darwin/file", "arm64-darwin/file" and "file" will all require the same file.
37+
# Completion candidates should only include the shortest one.
38+
load_path_backup = $LOAD_PATH.dup
39+
dir0 = Dir.mktmpdir
40+
dir1 = File.join(dir0, '3.3.0')
41+
dir2 = File.join(dir1, 'arm64-darwin')
42+
dir3 = File.join(dir1, 'test_req_dir')
43+
Dir.mkdir dir1
44+
Dir.mkdir dir2
45+
Dir.mkdir dir3
46+
File.write File.join(dir0, 'test_require_a.rb'), ''
47+
File.write File.join(dir1, 'test_require_a.rb'), ''
48+
File.write File.join(dir2, 'test_require_a.rb'), ''
49+
File.write File.join(dir0, 'test_require_b.rb'), ''
50+
File.write File.join(dir1, 'test_require_c.rb'), ''
51+
File.write File.join(dir1, 'arm64-darwin-foobar.rb'), ''
52+
File.write File.join(dir2, 'test_require_d.rb'), ''
53+
File.write File.join(dir3, 'test_require_e.rb'), ''
54+
$LOAD_PATH.push(dir0, dir1, dir2)
55+
clear_cache
56+
57+
files = %w[test_req_dir/test_require_e test_require_a test_require_b test_require_c test_require_d]
58+
assert_equal files, ReplTypeCompletor::RequirePaths.require_completions('test_req').sort
59+
candidates = ReplTypeCompletor::RequirePaths.require_completions('')
60+
assert_include candidates, 'arm64-darwin-foobar'
61+
files.each do |path|
62+
assert_not_include candidates, "3.3.0/#{path}"
63+
assert_not_include candidates, "3.3.0/arm64-darwin/#{path}"
64+
assert_not_include candidates, "arm64-darwin/#{path}"
65+
end
66+
ensure
67+
$LOAD_PATH.replace load_path_backup
68+
end
2569
end
2670
end

0 commit comments

Comments
 (0)