From 2e12fac38ef16fc5d56d6ba1c726a8490fda923e Mon Sep 17 00:00:00 2001 From: st0012 Date: Thu, 6 Oct 2022 11:49:51 +0100 Subject: [PATCH 1/6] Add tests for primitive types' method completion --- test/irb/test_completion.rb | 64 +++++++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 16 deletions(-) diff --git a/test/irb/test_completion.rb b/test/irb/test_completion.rb index 8d7476b8f..35c17b230 100644 --- a/test/irb/test_completion.rb +++ b/test/irb/test_completion.rb @@ -27,9 +27,54 @@ def test_nonstring_module_name end end - def test_complete_numeric - assert_include(IRB::InputCompletor.retrieve_completion_data("1r.positi", bind: binding), "1r.positive?") - assert_empty(IRB::InputCompletor.retrieve_completion_data("1i.positi", bind: binding)) + class TestMethodCompletion < TestCompletion + def test_complete_string + assert_include(IRB::InputCompletor.retrieve_completion_data("'foo'.up", bind: binding), "'foo'.upcase") + assert_equal(IRB::InputCompletor.retrieve_completion_data("'foo'.upcase", bind: binding, doc_namespace: true), "String.upcase") + end + + def test_complete_regexp + assert_include(IRB::InputCompletor.retrieve_completion_data("/foo/.ma", bind: binding), "/foo/.match") + assert_equal(IRB::InputCompletor.retrieve_completion_data("/foo/.match", bind: binding, doc_namespace: true), "Regexp.match") + end + + def test_complete_array + assert_include(IRB::InputCompletor.retrieve_completion_data("[].an", bind: binding), "[].any?") + assert_equal(IRB::InputCompletor.retrieve_completion_data("[].any?", bind: binding, doc_namespace: true), "Array.any?") + end + + def test_complete_hash_and_proc + # hash + assert_include(IRB::InputCompletor.retrieve_completion_data("{}.an", bind: binding), "{}.any?") + assert_include(IRB::InputCompletor.retrieve_completion_data("{}.any?", bind: binding, doc_namespace: true), "Proc.any?", "Hash.any?") + + # proc + assert_include(IRB::InputCompletor.retrieve_completion_data("{}.bin", bind: binding), "{}.binding") + assert_include(IRB::InputCompletor.retrieve_completion_data("{}.binding", bind: binding, doc_namespace: true), "Proc.binding", "Hash.binding") + end + + def test_complete_numeric + assert_include(IRB::InputCompletor.retrieve_completion_data("1.positi", bind: binding), "1.positive?") + assert_equal(IRB::InputCompletor.retrieve_completion_data("1.positive?", bind: binding, doc_namespace: true), "Integer.positive?") + + assert_include(IRB::InputCompletor.retrieve_completion_data("1r.positi", bind: binding), "1r.positive?") + assert_equal(IRB::InputCompletor.retrieve_completion_data("1r.positive?", bind: binding, doc_namespace: true), "Rational.positive?") + + assert_include(IRB::InputCompletor.retrieve_completion_data("0xFFFF.positi", bind: binding), "0xFFFF.positive?") + assert_equal(IRB::InputCompletor.retrieve_completion_data("0xFFFF.positive?", bind: binding, doc_namespace: true), "Integer.positive?") + + assert_empty(IRB::InputCompletor.retrieve_completion_data("1i.positi", bind: binding)) + end + + def test_complete_symbol + assert_include(IRB::InputCompletor.retrieve_completion_data(":foo.to_p", bind: binding), ":foo.to_proc") + assert_equal(IRB::InputCompletor.retrieve_completion_data(":foo.to_proc", bind: binding, doc_namespace: true), "Symbol.to_proc") + end + + def test_complete_class + assert_include(IRB::InputCompletor.retrieve_completion_data("String.ne", bind: binding), "String.new") + assert_equal(IRB::InputCompletor.retrieve_completion_data("String.new", bind: binding, doc_namespace: true), "String.new") + end end def test_complete_symbol @@ -70,14 +115,6 @@ def test_complete_reserved_words end end - def test_complete_predicate? - candidates = IRB::InputCompletor.retrieve_completion_data("1.posi", bind: binding) - assert_include candidates, '1.positive?' - - namespace = IRB::InputCompletor.retrieve_completion_data("1.positive?", bind: binding, doc_namespace: true) - assert_equal "Integer.positive?", namespace - end - def test_complete_require candidates = IRB::InputCompletor::CompletionProc.("'irb", "require ", "") %w['irb/init 'irb/ruby-lex].each do |word| @@ -204,11 +241,6 @@ def instance_variables; end assert_include(IRB::InputCompletor.retrieve_completion_data("private_hoge", bind: bind, doc_namespace: true), "private_hoge") end - def test_complete_class_method - assert_include(IRB::InputCompletor.retrieve_completion_data("String.new", bind: binding), "String.new") - assert_equal(IRB::InputCompletor.retrieve_completion_data("String.new", bind: binding, doc_namespace: true), "String.new") - end - def test_complete_sort_variables xzy, xzy_1, xzy2 = '', '', '' From 71631287c84728e1028a642637526cdd222c494a Mon Sep 17 00:00:00 2001 From: st0012 Date: Thu, 6 Oct 2022 11:59:49 +0100 Subject: [PATCH 2/6] Regroup completion tests --- test/irb/test_completion.rb | 230 ++++++++++++++++++------------------ 1 file changed, 117 insertions(+), 113 deletions(-) diff --git a/test/irb/test_completion.rb b/test/irb/test_completion.rb index 35c17b230..6b75cf9ee 100644 --- a/test/irb/test_completion.rb +++ b/test/irb/test_completion.rb @@ -77,6 +77,123 @@ def test_complete_class end end + class TestRequireComepletion < TestCompletion + def test_complete_require + candidates = IRB::InputCompletor::CompletionProc.("'irb", "require ", "") + %w['irb/init 'irb/ruby-lex].each do |word| + assert_include candidates, word + end + # Test cache + candidates = IRB::InputCompletor::CompletionProc.("'irb", "require ", "") + %w['irb/init 'irb/ruby-lex].each do |word| + assert_include candidates, word + 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) + $LOAD_PATH << test_path + + candidates = IRB::InputCompletor::CompletionProc.("'foo", "require ", "") + assert_include candidates, "'foo" + ensure + $LOAD_PATH.pop if test_path + FileUtils.remove_entry(temp_dir) if temp_dir + end + + def test_complete_require_with_string_convertable_in_load_path + temp_dir = Dir.mktmpdir + File.write(File.join(temp_dir, "foo.rb"), "test") + object = Object.new + object.define_singleton_method(:to_s) { temp_dir } + $LOAD_PATH << object + + candidates = IRB::InputCompletor::CompletionProc.("'foo", "require ", "") + assert_include candidates, "'foo" + ensure + $LOAD_PATH.pop if object + 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_nothing_raised do + IRB::InputCompletor::CompletionProc.("'foo", "require ", "") + end + 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 ", "") + assert_equal "'csv", candidates.first + end + + def test_complete_require_relative + candidates = Dir.chdir(__dir__ + "/../..") do + IRB::InputCompletor::CompletionProc.("'lib/irb", "require_relative ", "") + end + %w['lib/irb/init 'lib/irb/ruby-lex].each do |word| + assert_include candidates, word + end + # Test cache + candidates = Dir.chdir(__dir__ + "/../..") do + IRB::InputCompletor::CompletionProc.("'lib/irb", "require_relative ", "") + end + %w['lib/irb/init 'lib/irb/ruby-lex].each do |word| + assert_include candidates, word + end + end + end + + class TestVariableCompletion < TestCompletion + def test_complete_variable + # Bug fix issues https://github.com/ruby/irb/issues/368 + # Variables other than `str_example` and `@str_example` are defined to ensure that irb completion does not cause unintended behavior + str_example = '' + @str_example = '' + private_methods = '' + methods = '' + global_variables = '' + local_variables = '' + instance_variables = '' + + # suppress "assigned but unused variable" warning + str_example.clear + @str_example.clear + private_methods.clear + methods.clear + global_variables.clear + local_variables.clear + instance_variables.clear + + assert_include(IRB::InputCompletor.retrieve_completion_data("str_examp", bind: binding), "str_example") + assert_equal(IRB::InputCompletor.retrieve_completion_data("str_example", bind: binding, doc_namespace: true), "String") + assert_equal(IRB::InputCompletor.retrieve_completion_data("str_example.to_s", bind: binding, doc_namespace: true), "String.to_s") + + assert_include(IRB::InputCompletor.retrieve_completion_data("@str_examp", bind: binding), "@str_example") + assert_equal(IRB::InputCompletor.retrieve_completion_data("@str_example", bind: binding, doc_namespace: true), "String") + assert_equal(IRB::InputCompletor.retrieve_completion_data("@str_example.to_s", bind: binding, doc_namespace: true), "String.to_s") + end + + def test_complete_sort_variables + xzy, xzy_1, xzy2 = '', '', '' + + xzy.clear + xzy_1.clear + xzy2.clear + + candidates = IRB::InputCompletor.retrieve_completion_data("xz", bind: binding, doc_namespace: false) + assert_equal(candidates, %w[xzy xzy2 xzy_1]) + end + end + def test_complete_symbol %w"UTF-16LE UTF-7".each do |enc| "K".force_encoding(enc).to_sym @@ -115,108 +232,6 @@ def test_complete_reserved_words end end - def test_complete_require - candidates = IRB::InputCompletor::CompletionProc.("'irb", "require ", "") - %w['irb/init 'irb/ruby-lex].each do |word| - assert_include candidates, word - end - # Test cache - candidates = IRB::InputCompletor::CompletionProc.("'irb", "require ", "") - %w['irb/init 'irb/ruby-lex].each do |word| - assert_include candidates, word - 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) - $LOAD_PATH << test_path - - candidates = IRB::InputCompletor::CompletionProc.("'foo", "require ", "") - assert_include candidates, "'foo" - ensure - $LOAD_PATH.pop if test_path - FileUtils.remove_entry(temp_dir) if temp_dir - end - - def test_complete_require_with_string_convertable_in_load_path - temp_dir = Dir.mktmpdir - File.write(File.join(temp_dir, "foo.rb"), "test") - object = Object.new - object.define_singleton_method(:to_s) { temp_dir } - $LOAD_PATH << object - - candidates = IRB::InputCompletor::CompletionProc.("'foo", "require ", "") - assert_include candidates, "'foo" - ensure - $LOAD_PATH.pop if object - 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_nothing_raised do - IRB::InputCompletor::CompletionProc.("'foo", "require ", "") - end - 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 ", "") - assert_equal "'csv", candidates.first - end - - def test_complete_require_relative - candidates = Dir.chdir(__dir__ + "/../..") do - IRB::InputCompletor::CompletionProc.("'lib/irb", "require_relative ", "") - end - %w['lib/irb/init 'lib/irb/ruby-lex].each do |word| - assert_include candidates, word - end - # Test cache - candidates = Dir.chdir(__dir__ + "/../..") do - IRB::InputCompletor::CompletionProc.("'lib/irb", "require_relative ", "") - end - %w['lib/irb/init 'lib/irb/ruby-lex].each do |word| - assert_include candidates, word - end - end - - def test_complete_variable - # Bug fix issues https://github.com/ruby/irb/issues/368 - # Variables other than `str_example` and `@str_example` are defined to ensure that irb completion does not cause unintended behavior - str_example = '' - @str_example = '' - private_methods = '' - methods = '' - global_variables = '' - local_variables = '' - instance_variables = '' - - # suppress "assigned but unused variable" warning - str_example.clear - @str_example.clear - private_methods.clear - methods.clear - global_variables.clear - local_variables.clear - instance_variables.clear - - assert_include(IRB::InputCompletor.retrieve_completion_data("str_examp", bind: binding), "str_example") - assert_equal(IRB::InputCompletor.retrieve_completion_data("str_example", bind: binding, doc_namespace: true), "String") - assert_equal(IRB::InputCompletor.retrieve_completion_data("str_example.to_s", bind: binding, doc_namespace: true), "String.to_s") - - assert_include(IRB::InputCompletor.retrieve_completion_data("@str_examp", bind: binding), "@str_example") - assert_equal(IRB::InputCompletor.retrieve_completion_data("@str_example", bind: binding, doc_namespace: true), "String") - assert_equal(IRB::InputCompletor.retrieve_completion_data("@str_example.to_s", bind: binding, doc_namespace: true), "String.to_s") - end - def test_complete_methods obj = Object.new obj.singleton_class.class_eval { @@ -240,16 +255,5 @@ def instance_variables; end assert_include(IRB::InputCompletor.retrieve_completion_data("private_hoge.to_s", bind: bind), "private_hoge.to_s") assert_include(IRB::InputCompletor.retrieve_completion_data("private_hoge", bind: bind, doc_namespace: true), "private_hoge") end - - def test_complete_sort_variables - xzy, xzy_1, xzy2 = '', '', '' - - xzy.clear - xzy_1.clear - xzy2.clear - - candidates = IRB::InputCompletor.retrieve_completion_data("xz", bind: binding, doc_namespace: false) - assert_equal(candidates, %w[xzy xzy2 xzy_1]) - end end end From 39f8fcb0588c425c94dfc6678527d196926ff9f4 Mon Sep 17 00:00:00 2001 From: st0012 Date: Thu, 6 Oct 2022 12:27:16 +0100 Subject: [PATCH 3/6] Add constant completion test --- test/irb/test_completion.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/irb/test_completion.rb b/test/irb/test_completion.rb index 6b75cf9ee..92228e2f4 100644 --- a/test/irb/test_completion.rb +++ b/test/irb/test_completion.rb @@ -194,6 +194,22 @@ def test_complete_sort_variables end end + class TestConstantCompletion < TestCompletion + class Foo + B1 = 1 + B2 = 2 + end + + def test_complete_constants + assert_equal(["Foo"], IRB::InputCompletor.retrieve_completion_data("Fo", bind: binding)) + assert_equal(["Foo::B1", "Foo::B2"], IRB::InputCompletor.retrieve_completion_data("Foo::B", bind: binding)) + assert_equal(["Foo::B1.positive?"], IRB::InputCompletor.retrieve_completion_data("Foo::B1.pos", bind: binding)) + + assert_equal(["::Forwardable"], IRB::InputCompletor.retrieve_completion_data("::Fo", bind: binding)) + assert_equal("Forwardable", IRB::InputCompletor.retrieve_completion_data("::Forwardable", bind: binding, doc_namespace: true)) + end + end + def test_complete_symbol %w"UTF-16LE UTF-7".each do |enc| "K".force_encoding(enc).to_sym From 00f90d40ad7540f03129832eb77eb17f437f9633 Mon Sep 17 00:00:00 2001 From: st0012 Date: Thu, 6 Oct 2022 12:30:18 +0100 Subject: [PATCH 4/6] Correct assert_equal's usage in completion tests https://test-unit.github.io/test-unit/en/Test/Unit/Assertions.html#assert_equal-instance_method --- test/irb/test_completion.rb | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/test/irb/test_completion.rb b/test/irb/test_completion.rb index 92228e2f4..4ca7f298f 100644 --- a/test/irb/test_completion.rb +++ b/test/irb/test_completion.rb @@ -30,50 +30,50 @@ def test_nonstring_module_name class TestMethodCompletion < TestCompletion def test_complete_string assert_include(IRB::InputCompletor.retrieve_completion_data("'foo'.up", bind: binding), "'foo'.upcase") - assert_equal(IRB::InputCompletor.retrieve_completion_data("'foo'.upcase", bind: binding, doc_namespace: true), "String.upcase") + assert_equal("String.upcase", IRB::InputCompletor.retrieve_completion_data("'foo'.upcase", bind: binding, doc_namespace: true)) end def test_complete_regexp assert_include(IRB::InputCompletor.retrieve_completion_data("/foo/.ma", bind: binding), "/foo/.match") - assert_equal(IRB::InputCompletor.retrieve_completion_data("/foo/.match", bind: binding, doc_namespace: true), "Regexp.match") + assert_equal("Regexp.match", IRB::InputCompletor.retrieve_completion_data("/foo/.match", bind: binding, doc_namespace: true)) end def test_complete_array assert_include(IRB::InputCompletor.retrieve_completion_data("[].an", bind: binding), "[].any?") - assert_equal(IRB::InputCompletor.retrieve_completion_data("[].any?", bind: binding, doc_namespace: true), "Array.any?") + assert_equal("Array.any?", IRB::InputCompletor.retrieve_completion_data("[].any?", bind: binding, doc_namespace: true)) end def test_complete_hash_and_proc # hash assert_include(IRB::InputCompletor.retrieve_completion_data("{}.an", bind: binding), "{}.any?") - assert_include(IRB::InputCompletor.retrieve_completion_data("{}.any?", bind: binding, doc_namespace: true), "Proc.any?", "Hash.any?") + assert_equal(["Proc.any?", "Hash.any?"], IRB::InputCompletor.retrieve_completion_data("{}.any?", bind: binding, doc_namespace: true)) # proc assert_include(IRB::InputCompletor.retrieve_completion_data("{}.bin", bind: binding), "{}.binding") - assert_include(IRB::InputCompletor.retrieve_completion_data("{}.binding", bind: binding, doc_namespace: true), "Proc.binding", "Hash.binding") + assert_equal(["Proc.binding", "Hash.binding"], IRB::InputCompletor.retrieve_completion_data("{}.binding", bind: binding, doc_namespace: true)) end def test_complete_numeric assert_include(IRB::InputCompletor.retrieve_completion_data("1.positi", bind: binding), "1.positive?") - assert_equal(IRB::InputCompletor.retrieve_completion_data("1.positive?", bind: binding, doc_namespace: true), "Integer.positive?") + assert_equal("Integer.positive?", IRB::InputCompletor.retrieve_completion_data("1.positive?", bind: binding, doc_namespace: true)) assert_include(IRB::InputCompletor.retrieve_completion_data("1r.positi", bind: binding), "1r.positive?") - assert_equal(IRB::InputCompletor.retrieve_completion_data("1r.positive?", bind: binding, doc_namespace: true), "Rational.positive?") + assert_equal("Rational.positive?", IRB::InputCompletor.retrieve_completion_data("1r.positive?", bind: binding, doc_namespace: true)) assert_include(IRB::InputCompletor.retrieve_completion_data("0xFFFF.positi", bind: binding), "0xFFFF.positive?") - assert_equal(IRB::InputCompletor.retrieve_completion_data("0xFFFF.positive?", bind: binding, doc_namespace: true), "Integer.positive?") + assert_equal("Integer.positive?", IRB::InputCompletor.retrieve_completion_data("0xFFFF.positive?", bind: binding, doc_namespace: true)) assert_empty(IRB::InputCompletor.retrieve_completion_data("1i.positi", bind: binding)) end def test_complete_symbol assert_include(IRB::InputCompletor.retrieve_completion_data(":foo.to_p", bind: binding), ":foo.to_proc") - assert_equal(IRB::InputCompletor.retrieve_completion_data(":foo.to_proc", bind: binding, doc_namespace: true), "Symbol.to_proc") + assert_equal("Symbol.to_proc", IRB::InputCompletor.retrieve_completion_data(":foo.to_proc", bind: binding, doc_namespace: true)) end def test_complete_class assert_include(IRB::InputCompletor.retrieve_completion_data("String.ne", bind: binding), "String.new") - assert_equal(IRB::InputCompletor.retrieve_completion_data("String.new", bind: binding, doc_namespace: true), "String.new") + assert_equal("String.new", IRB::InputCompletor.retrieve_completion_data("String.new", bind: binding, doc_namespace: true)) end end @@ -174,12 +174,12 @@ def test_complete_variable instance_variables.clear assert_include(IRB::InputCompletor.retrieve_completion_data("str_examp", bind: binding), "str_example") - assert_equal(IRB::InputCompletor.retrieve_completion_data("str_example", bind: binding, doc_namespace: true), "String") - assert_equal(IRB::InputCompletor.retrieve_completion_data("str_example.to_s", bind: binding, doc_namespace: true), "String.to_s") + assert_equal("String", IRB::InputCompletor.retrieve_completion_data("str_example", bind: binding, doc_namespace: true)) + assert_equal("String.to_s", IRB::InputCompletor.retrieve_completion_data("str_example.to_s", bind: binding, doc_namespace: true)) assert_include(IRB::InputCompletor.retrieve_completion_data("@str_examp", bind: binding), "@str_example") - assert_equal(IRB::InputCompletor.retrieve_completion_data("@str_example", bind: binding, doc_namespace: true), "String") - assert_equal(IRB::InputCompletor.retrieve_completion_data("@str_example.to_s", bind: binding, doc_namespace: true), "String.to_s") + assert_equal("String", IRB::InputCompletor.retrieve_completion_data("@str_example", bind: binding, doc_namespace: true)) + assert_equal("String.to_s", IRB::InputCompletor.retrieve_completion_data("@str_example.to_s", bind: binding, doc_namespace: true)) end def test_complete_sort_variables @@ -190,7 +190,7 @@ def test_complete_sort_variables xzy2.clear candidates = IRB::InputCompletor.retrieve_completion_data("xz", bind: binding, doc_namespace: false) - assert_equal(candidates, %w[xzy xzy2 xzy_1]) + assert_equal(%w[xzy xzy2 xzy_1], candidates) end end From 19a2fcbd87092eece8e61fd1fea9e42c26e02463 Mon Sep 17 00:00:00 2001 From: st0012 Date: Thu, 6 Oct 2022 11:54:11 +0100 Subject: [PATCH 5/6] Lazily evaluate candidates locals --- lib/irb/completion.rb | 54 +++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/lib/irb/completion.rb b/lib/irb/completion.rb index 35767feeb..9d386bbec 100644 --- a/lib/irb/completion.rb +++ b/lib/irb/completion.rb @@ -171,10 +171,10 @@ def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace receiver = $1 message = $3 - candidates = String.instance_methods.collect{|m| m.to_s} if doc_namespace "String.#{message}" else + candidates = String.instance_methods.collect{|m| m.to_s} select_message(receiver, message, candidates) end @@ -183,10 +183,10 @@ def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace receiver = $1 message = $2 - candidates = Regexp.instance_methods.collect{|m| m.to_s} if doc_namespace "Regexp.#{message}" else + candidates = Regexp.instance_methods.collect{|m| m.to_s} select_message(receiver, message, candidates) end @@ -195,10 +195,10 @@ def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace receiver = $1 message = $2 - candidates = Array.instance_methods.collect{|m| m.to_s} if doc_namespace "Array.#{message}" else + candidates = Array.instance_methods.collect{|m| m.to_s} select_message(receiver, message, candidates) end @@ -207,29 +207,33 @@ def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace receiver = $1 message = $2 - proc_candidates = Proc.instance_methods.collect{|m| m.to_s} - hash_candidates = Hash.instance_methods.collect{|m| m.to_s} if doc_namespace ["Proc.#{message}", "Hash.#{message}"] else + proc_candidates = Proc.instance_methods.collect{|m| m.to_s} + hash_candidates = Hash.instance_methods.collect{|m| m.to_s} select_message(receiver, message, proc_candidates | hash_candidates) end when /^(:[^:.]*)$/ # Symbol - return nil if doc_namespace - sym = $1 - candidates = Symbol.all_symbols.collect do |s| - ":" + s.id2name.encode(Encoding.default_external) - rescue EncodingError - # ignore + if doc_namespace + nil + else + sym = $1 + candidates = Symbol.all_symbols.collect do |s| + ":" + s.id2name.encode(Encoding.default_external) + rescue EncodingError + # ignore + end + candidates.grep(/^#{Regexp.quote(sym)}/) end - candidates.grep(/^#{Regexp.quote(sym)}/) - when /^::([A-Z][^:\.\(\)]*)$/ # Absolute Constant or class methods receiver = $1 + candidates = Object.constants.collect{|m| m.to_s} + if doc_namespace candidates.find { |i| i == receiver } else @@ -240,15 +244,17 @@ def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace # Constant or class methods receiver = $1 message = $2 - begin - candidates = eval("#{receiver}.constants.collect{|m| m.to_s}", bind) - candidates |= eval("#{receiver}.methods.collect{|m| m.to_s}", bind) - rescue Exception - candidates = [] - end + if doc_namespace "#{receiver}::#{message}" else + begin + candidates = eval("#{receiver}.constants.collect{|m| m.to_s}", bind) + candidates |= eval("#{receiver}.methods.collect{|m| m.to_s}", bind) + rescue Exception + candidates = [] + end + select_message(receiver, message, candidates, "::") end @@ -258,10 +264,10 @@ def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace sep = $2 message = $3 - candidates = Symbol.instance_methods.collect{|m| m.to_s} if doc_namespace "Symbol.#{message}" else + candidates = Symbol.instance_methods.collect{|m| m.to_s} select_message(receiver, message, candidates, sep) end @@ -273,6 +279,7 @@ def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace begin instance = eval(receiver, bind) + if doc_namespace "#{instance.class.name}.#{message}" else @@ -283,7 +290,7 @@ def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace if doc_namespace nil else - candidates = [] + [] end end @@ -305,7 +312,7 @@ def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace if doc_namespace nil else - candidates = [] + [] end end @@ -313,6 +320,7 @@ def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace # global var gvar = $1 all_gvars = global_variables.collect{|m| m.to_s} + if doc_namespace all_gvars.find{ |i| i == gvar } else @@ -356,6 +364,7 @@ def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace candidates.sort! candidates.uniq! end + if doc_namespace rec_class = rec.is_a?(Module) ? rec : rec.class "#{rec_class.name}#{sep}#{candidates.find{ |i| i == message }}" @@ -370,6 +379,7 @@ def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace message = $1 candidates = String.instance_methods(true).collect{|m| m.to_s} + if doc_namespace "String.#{candidates.find{ |i| i == message }}" else From ee9b33c8171d5d2a1094aed9ceebff397e02e2eb Mon Sep 17 00:00:00 2001 From: st0012 Date: Thu, 6 Oct 2022 12:37:37 +0100 Subject: [PATCH 6/6] Sort constant completion's candidates --- lib/irb/completion.rb | 2 +- test/irb/test_completion.rb | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/irb/completion.rb b/lib/irb/completion.rb index 9d386bbec..dbd652769 100644 --- a/lib/irb/completion.rb +++ b/lib/irb/completion.rb @@ -255,7 +255,7 @@ def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace candidates = [] end - select_message(receiver, message, candidates, "::") + select_message(receiver, message, candidates.sort, "::") end when /^(:[^:.]+)(\.|::)([^.]*)$/ diff --git a/test/irb/test_completion.rb b/test/irb/test_completion.rb index 4ca7f298f..df5a78c69 100644 --- a/test/irb/test_completion.rb +++ b/test/irb/test_completion.rb @@ -196,13 +196,14 @@ def test_complete_sort_variables class TestConstantCompletion < TestCompletion class Foo + B3 = 1 B1 = 1 - B2 = 2 + B2 = 1 end def test_complete_constants assert_equal(["Foo"], IRB::InputCompletor.retrieve_completion_data("Fo", bind: binding)) - assert_equal(["Foo::B1", "Foo::B2"], IRB::InputCompletor.retrieve_completion_data("Foo::B", bind: binding)) + assert_equal(["Foo::B1", "Foo::B2", "Foo::B3"], IRB::InputCompletor.retrieve_completion_data("Foo::B", bind: binding)) assert_equal(["Foo::B1.positive?"], IRB::InputCompletor.retrieve_completion_data("Foo::B1.pos", bind: binding)) assert_equal(["::Forwardable"], IRB::InputCompletor.retrieve_completion_data("::Fo", bind: binding))