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.
c671d39020
In addition to String values, $LOAD_PATH can also take objects that
respond_to the `to_path` method, like Pathname objects. So `irb` should
be able to handle those objects too.
And if $LOAD_PATH contains objects that can't be converted into String,
`irb` should simply ignore it.
b2f562176b
There are two directories where csv*/**/*.rb exist, lib/ and
test/, and depending on the order of tests, test/ may be placed
before lib/. In that case, as "shortest" names were not sorted,
csv/helper.rb will be the first candidate for "csv".
2af7c6bf71
There are cases where ruby is installed without rdoc and e.g.
lib/irb/cmd/help.rb also handles the LoadError
Here is how to replicate the issue:
```
$ docker run -it alpine:3.13.3 sh
/ # apk add ruby ruby-irb ruby-io-console
/ # irb
irb(main):001:0> Class[TAB][TAB]
```
And you end up with something like:
```
irb(main):001:0> ClassTraceback (most recent call last):
34: from /usr/bin/irb:23:in `<main>'
33: from /usr/bin/irb:23:in `load'
32: from /usr/lib/ruby/gems/2.7.0/gems/irb-1.2.6/exe/irb:11:in `<top (required)>'
31: from /usr/lib/ruby/2.7.0/irb.rb:400:in `start'
30: from /usr/lib/ruby/2.7.0/irb.rb:471:in `run'
29: from /usr/lib/ruby/2.7.0/irb.rb:471:in `catch'
28: from /usr/lib/ruby/2.7.0/irb.rb:472:in `block in run'
27: from /usr/lib/ruby/2.7.0/irb.rb:537:in `eval_input'
26: from /usr/lib/ruby/2.7.0/irb/ruby-lex.rb:150:in `each_top_level_statement'
25: from /usr/lib/ruby/2.7.0/irb/ruby-lex.rb:150:in `catch'
24: from /usr/lib/ruby/2.7.0/irb/ruby-lex.rb:151:in `block in each_top_level_statement'
23: from /usr/lib/ruby/2.7.0/irb/ruby-lex.rb:151:in `loop'
22: from /usr/lib/ruby/2.7.0/irb/ruby-lex.rb:154:in `block (2 levels) in each_top_level_statement'
21: from /usr/lib/ruby/2.7.0/irb/ruby-lex.rb:182:in `lex'
20: from /usr/lib/ruby/2.7.0/irb.rb:518:in `block in eval_input'
19: from /usr/lib/ruby/2.7.0/irb.rb:704:in `signal_status'
18: from /usr/lib/ruby/2.7.0/irb.rb:519:in `block (2 levels) in eval_input'
17: from /usr/lib/ruby/2.7.0/irb/input-method.rb:294:in `gets'
16: from /usr/lib/ruby/2.7.0/forwardable.rb:235:in `readmultiline'
15: from /usr/lib/ruby/2.7.0/forwardable.rb:235:in `readmultiline'
14: from /usr/lib/ruby/2.7.0/reline.rb:175:in `readmultiline'
13: from /usr/lib/ruby/2.7.0/reline.rb:238:in `inner_readline'
12: from /usr/lib/ruby/2.7.0/reline.rb:238:in `loop'
11: from /usr/lib/ruby/2.7.0/reline.rb:239:in `block in inner_readline'
10: from /usr/lib/ruby/2.7.0/reline.rb:270:in `read_io'
9: from /usr/lib/ruby/2.7.0/reline.rb:270:in `loop'
8: from /usr/lib/ruby/2.7.0/reline.rb:311:in `block in read_io'
7: from /usr/lib/ruby/2.7.0/reline.rb:240:in `block (2 levels) in inner_readline'
6: from /usr/lib/ruby/2.7.0/reline.rb:240:in `each'
5: from /usr/lib/ruby/2.7.0/reline.rb:241:in `block (3 levels) in inner_readline'
4: from /usr/lib/ruby/2.7.0/reline/line_editor.rb:820:in `input_key'
3: from /usr/lib/ruby/2.7.0/reline/line_editor.rb:608:in `complete'
2: from /usr/lib/ruby/2.7.0/irb/completion.rb:269:in `block in <module:InputCompletor>'
1: from /usr/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require'
/usr/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require': cannot load such file -- rdoc (LoadError)
```
a2d299c2ac
* Reverts part of 3198e7abd7.
* If the rule is #send should be deprecated, that should be ruled by matz,
there is no such rule currently and gems seem to prefer #send
overwhelmingly.
Rails before 5.2 added Array#append as an alias to Array#<< ,
so that it expects only one argument.
However ruby-2.5 added Array#append as an alias to Array#push
which takes any number of arguments.
If irb completion is used in `rails c` (for example "IO.<tab>")
it fails with:
irb/completion.rb:206:in `<<': wrong number of arguments (given 3, expected 1) (ArgumentError)
Using Array#push instead of Array#append fixes compatibility.
5b7bbf9c34
IRB completion logic always needed exponential notation for complex literal
such as 3e6i but it's bug. I fixed to support complex literal without
exponential notation such as 3i.
In IRB, Time.new is split as "Time", ".", and "new". The receiver "Time"
is processed by #class method but it means that "Time" changes to
"Class". This commit fixes it.