1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

[ruby/irb] Don't lazily retrieve gem specs for completion

There are a few downsides of the current approach:

1. Because gem specs are lazily retrieved, this computation happens in
   every irb completion test case, which is not necessary. (In tests we
   don't cache the result of `retrieve_files_to_require_from_load_path`)
2. Gem::Specification.latest_specs is sensible to the content of
   LOAD_PATH. And when combined with 1, tests fail "randomly" if they
   try to mutate LOAD_PATH, even though the test subject it's something
   else.

So by pre-computing and storing the gem paths in a constant, it guarantees
that the computation only happens once and it doesn't get affected by test
cases.

One argument could be made against the change is that, it'll store
unnecessary data for users that disable autocompletion. But the
counter-arguments are:

1. Since autocompletion is enabled by default, this should not be the
   case for most users.
2. For users with autocompletion enabled, IRB already caches the
   result of `retrieve_files_to_require_from_load_path` in memory, which
   should have a similar size of GEM_SPECS. And we currently haven't
   received any report about problems caused by such memory consumption.

https://github.com/ruby/irb/commit/c671d39020
This commit is contained in:
Stan Lo 2022-11-06 14:55:24 +00:00 committed by git
parent 72c7dba436
commit ca0b592673

View file

@ -64,25 +64,27 @@ module IRB
if File.respond_to?(:absolute_path?)
File.absolute_path?(p)
else
if File.absolute_path(p) == p
true
else
false
end
File.absolute_path(p) == p
end
end
GEM_PATHS =
if defined?(Gem::Specification)
Gem::Specification.latest_specs(true).map { |s|
s.require_paths.map { |p|
if absolute_path?(p)
p
else
File.join(s.full_gem_path, p)
end
}
}.flatten
else
[]
end.freeze
def self.retrieve_gem_and_system_load_path
gem_paths = Gem::Specification.latest_specs(true).map { |s|
s.require_paths.map { |p|
if absolute_path?(p)
p
else
File.join(s.full_gem_path, p)
end
}
}.flatten if defined?(Gem::Specification)
candidates = (gem_paths.to_a | $LOAD_PATH)
candidates = (GEM_PATHS | $LOAD_PATH)
candidates.map do |p|
if p.respond_to?(:to_path)
p.to_path