Skip to content

Commit cfdb0d2

Browse files
committed
Limit the number of symbol completion candidates and make it faster
1 parent c9dfd60 commit cfdb0d2

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

lib/repl_type_completor/result.rb

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def completion_candidates
6464
in [:gvar, name, scope]
6565
scope.global_variables
6666
in [:symbol, name]
67-
Symbol.all_symbols.map { _1.inspect[1..] }
67+
filter_symbol_candidates(Symbol.all_symbols, name, limit: 100)
6868
in [:call, name, type, self_call]
6969
(self_call ? type.all_methods : type.methods).map(&:to_s) - HIDDEN_METHODS
7070
in [:lvar_or_method, name, scope]
@@ -116,6 +116,25 @@ def doc_namespace(matched)
116116

117117
private
118118

119+
def filter_symbol_candidates(symbols, prefix, limit:)
120+
sym_prefix = ":#{prefix}"
121+
candidates = symbols.filter_map do |s|
122+
next unless s.start_with?(prefix) # Fast and inaccurate check before calling inspect
123+
124+
inspect = s.inspect
125+
inspect[1..] if inspect.start_with?(sym_prefix) # Reject `:"a b"` when completing `:a`
126+
rescue EncodingError
127+
# ignore
128+
end
129+
130+
if candidates.size > limit
131+
# min(n) + max(n) is faster than sort and slice
132+
candidates.min(limit - limit / 2) + candidates.max(limit / 2).reverse
133+
else
134+
candidates.sort
135+
end
136+
end
137+
119138
def method_doc(type, name)
120139
type = type.types.find { _1.all_methods.include? name.to_sym }
121140
case type

test/repl_type_completor/test_repl_type_completor.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@ def test_symbol
6363
assert_completion(prefix, include: sym.inspect.delete_prefix(prefix))
6464
end
6565

66+
def test_symbol_limit
67+
result = ReplTypeCompletor::Result.new([:symbol, 'sym'], binding, 'file')
68+
symbols = [:ae, :ad, :ab1, :ab2, :ac, :aa, :b, :"a a", 75.chr('utf-7').to_sym]
69+
assert_equal(%w[aa ab1 ab2 ac ad ae], result.send(:filter_symbol_candidates, symbols, 'a', limit: 100))
70+
assert_equal(%w[aa ab1 ab2 ad ae], result.send(:filter_symbol_candidates, symbols, 'a', limit: 5))
71+
assert_equal(%w[aa ab1 ad ae], result.send(:filter_symbol_candidates, symbols, 'a', limit: 4))
72+
assert_equal(%w[ab1 ab2], result.send(:filter_symbol_candidates, symbols, 'ab', limit: 4))
73+
assert_equal([], result.send(:filter_symbol_candidates, symbols, 'c', limit: 4))
74+
end
75+
6676
def test_call
6777
assert_completion('1.', include: 'abs')
6878
assert_completion('1.a', include: 'bs')

0 commit comments

Comments
 (0)