Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions lib/repl_type_completor/result.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def completion_candidates
in [:require_relative, name]
RequirePaths.require_relative_completions(name, @source_file)
in [:call_or_const, name, type, self_call]
((self_call ? type.all_methods : type.methods).map(&:to_s) - HIDDEN_METHODS) | type.constants
((self_call ? type.all_methods : type.methods).map(&:to_s) - HIDDEN_METHODS).sort | type.constants.sort
in [:const, name, type, scope]
if type
scope_constants = type.types.flat_map do |t|
Expand All @@ -60,28 +60,32 @@ def completion_candidates
ivars = scope.instance_variables.sort
name == '@' ? ivars + scope.class_variables.sort : ivars
in [:cvar, name, scope]
scope.class_variables
scope.class_variables.sort
in [:gvar, name, scope]
scope.global_variables
scope.global_variables.sort
in [:symbol, name]
filter_symbol_candidates(Symbol.all_symbols, name, limit: 100)
in [:aref, key_type, name, receiver_type]
key_type = key_type == :string ? String : Symbol
keys = receiver_type.types.grep(Types::InstanceType).select do |t|
Hash == t.klass
end.flat_map do |t|
t.instances.flat_map(&:keys).grep(key_type).uniq.sort
t.instances.flat_map(&:keys).grep(key_type).uniq
end
if key_type == Symbol
keys = Symbol.all_symbols if keys.empty? && name.size >= 1
filter_symbol_candidates(keys, name, limit: 100)
else
keys.select { _1.start_with?(name) }.sort
keys.sort
end
in [:call, name, type, self_call]
(self_call ? type.all_methods : type.methods).map(&:to_s) - HIDDEN_METHODS
methods = (self_call ? type.all_methods : type.methods).map(&:to_s) - HIDDEN_METHODS
# Alphabetical order, but internal methods (leading underscore) last.
# `_1[0] == '_'` because `start_with?('_')` raises EncodingError if the
# method name's encoding is incompatible with US-ASCII.
methods.sort_by { [_1[0] == '_' ? 1 : 0, _1] }
in [:lvar_or_method, name, scope]
scope.self_type.all_methods.map(&:to_s) | scope.local_variables | RESERVED_WORDS
scope.local_variables.sort | scope.self_type.all_methods.map(&:to_s).sort | RESERVED_WORDS
else
[]
end
Expand Down
37 changes: 37 additions & 0 deletions test/repl_type_completor/test_repl_type_completor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,43 @@ def with_failing_method(klass, method_name, message)
klass.define_method(method_name, original_method)
end

def test_call_candidates_are_sorted_with_underscore_methods_last
type = Struct.new(:methods).new(%i[_zeta beta _alpha alpha])
result = ReplTypeCompletor::Result.new([:call, '', type, false], binding, __FILE__)

assert_equal %w[alpha beta _alpha _zeta], result.completion_candidates
end

def test_call_or_const_candidates_are_sorted_within_groups
type = Struct.new(:methods, :constants).new(%i[z_method a_method], %i[ZConst AConst])
result = ReplTypeCompletor::Result.new([:call_or_const, '', type, false], binding, __FILE__)

assert_equal %w[a_method z_method AConst ZConst], result.completion_candidates
end

def test_const_candidates_are_sorted_before_reserved_words
scope = Struct.new(:constants).new(%w[ZConst AConst])
result = ReplTypeCompletor::Result.new([:const, '', nil, scope], binding, __FILE__)

assert_equal %w[AConst ZConst] + ReplTypeCompletor::Result::RESERVED_WORDS, result.completion_candidates
end

def test_ivar_candidates_are_sorted_within_groups
scope = Struct.new(:instance_variables, :class_variables).new(%w[@z @a], %w[@@z @@a])
result = ReplTypeCompletor::Result.new([:ivar, '@', scope], binding, __FILE__)

assert_equal %w[a z @a @z], result.completion_candidates
end

def test_lvar_or_method_candidates_are_sorted_within_groups
type = Struct.new(:all_methods).new(%i[z_method a_method])
scope = Struct.new(:self_type, :local_variables).new(type, %w[z_local a_local])
result = ReplTypeCompletor::Result.new([:lvar_or_method, '', scope], binding, __FILE__)

expected = %w[a_local z_local a_method z_method] + ReplTypeCompletor::Result::RESERVED_WORDS
assert_equal expected, result.completion_candidates
end

def test_analyze_error
with_failing_method(ReplTypeCompletor.singleton_class, :analyze_code, 'error_in_analyze_code') do
assert_nil ReplTypeCompletor.analyze('1.', binding: binding)
Expand Down
Loading