diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-03-13 01:28:27 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-03-13 01:28:27 +0000 |
commit | 583d903c2ba5de82bd3eb2eb687b1c107938f9e2 (patch) | |
tree | fdcf85a724adbf449a0bfed09dcdfb2b5a131731 /lib/irb | |
parent | 0faf01862435676ba15552b99f282ba49dba620a (diff) | |
download | ruby-583d903c2ba5de82bd3eb2eb687b1c107938f9e2.tar.gz |
Speed up func1.func2 completion by using Set for ignored modules
And thus avoiding Module#name calls. Those are slow, especially in
larger projects, with lots of anonymous modules.
[Fix GH-1798]
From: Dmitry Gutov <dgutov@yandex.ru>
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62732 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/irb')
-rw-r--r-- | lib/irb/completion.rb | 39 |
1 files changed, 28 insertions, 11 deletions
diff --git a/lib/irb/completion.rb b/lib/irb/completion.rb index e7499a8e2b..1b9d96b8f9 100644 --- a/lib/irb/completion.rb +++ b/lib/irb/completion.rb @@ -169,18 +169,9 @@ module IRB else # func1.func2 candidates = [] + to_ignore = ignored_modules ObjectSpace.each_object(Module){|m| - begin - name = m.name - rescue Exception - name = "" - end - begin - next if name != "IRB::Context" and - /^(IRB|SLex|RubyLex|RubyToken)/ =~ name - rescue Exception - next - end + next if (to_ignore.include?(m) rescue true) candidates.concat m.instance_methods(false).collect{|x| x.to_s} } candidates.sort! @@ -218,6 +209,32 @@ module IRB end end end + + def self.ignored_modules + # We could cache the result, but this is very fast already. + # By using this approach, we avoid Module#name calls, which are + # relatively slow when there are a lot of anonymous modules defined. + require 'set' + s = Set.new + + scanner = lambda do |m| + next if s.include?(m) # IRB::ExtendCommandBundle::EXCB recurses. + s << m + m.constants(false).each do |c| + value = m.const_get(c) + scanner.call(value) if value.is_a?(Module) + end + end + + %i(IRB SLex RubyLex RubyToken).each do |sym| + next unless Object.const_defined?(sym) + scanner.call(Object.const_get(sym)) + end + + s.delete(IRB::Context) if defined?(IRB::Context) + + s + end end end |