irb 1.9.1 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +4 -4
- data/README.md +10 -9
- data/Rakefile +2 -2
- data/lib/irb/cmd/history.rb +47 -0
- data/lib/irb/cmd/show_cmds.rb +6 -0
- data/lib/irb/cmd/show_source.rb +9 -2
- data/lib/irb/completion.rb +21 -0
- data/lib/irb/context.rb +22 -14
- data/lib/irb/debug.rb +18 -0
- data/lib/irb/extend-command.rb +6 -0
- data/lib/irb/history.rb +1 -1
- data/lib/irb/init.rb +3 -4
- data/lib/irb/lc/help-message +1 -0
- data/lib/irb/pager.rb +12 -11
- data/lib/irb/source_finder.rb +26 -6
- data/lib/irb/version.rb +2 -2
- data/lib/irb.rb +48 -40
- metadata +3 -7
- data/lib/irb/type_completion/completor.rb +0 -235
- data/lib/irb/type_completion/methods.rb +0 -13
- data/lib/irb/type_completion/scope.rb +0 -412
- data/lib/irb/type_completion/type_analyzer.rb +0 -1169
- data/lib/irb/type_completion/types.rb +0 -426
@@ -1,426 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'methods'
|
4
|
-
|
5
|
-
module IRB
|
6
|
-
module TypeCompletion
|
7
|
-
module Types
|
8
|
-
OBJECT_TO_TYPE_SAMPLE_SIZE = 50
|
9
|
-
|
10
|
-
singleton_class.attr_reader :rbs_builder, :rbs_load_error
|
11
|
-
|
12
|
-
def self.preload_in_thread
|
13
|
-
return if @preload_started
|
14
|
-
|
15
|
-
@preload_started = true
|
16
|
-
Thread.new do
|
17
|
-
load_rbs_builder
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.load_rbs_builder
|
22
|
-
require 'rbs'
|
23
|
-
require 'rbs/cli'
|
24
|
-
loader = RBS::CLI::LibraryOptions.new.loader
|
25
|
-
loader.add path: Pathname('sig')
|
26
|
-
@rbs_builder = RBS::DefinitionBuilder.new env: RBS::Environment.from_loader(loader).resolve_type_names
|
27
|
-
rescue LoadError, StandardError => e
|
28
|
-
@rbs_load_error = e
|
29
|
-
nil
|
30
|
-
end
|
31
|
-
|
32
|
-
def self.class_name_of(klass)
|
33
|
-
klass = klass.superclass if klass.singleton_class?
|
34
|
-
Methods::MODULE_NAME_METHOD.bind_call klass
|
35
|
-
end
|
36
|
-
|
37
|
-
def self.rbs_search_method(klass, method_name, singleton)
|
38
|
-
klass.ancestors.each do |ancestor|
|
39
|
-
name = class_name_of ancestor
|
40
|
-
next unless name && rbs_builder
|
41
|
-
type_name = RBS::TypeName(name).absolute!
|
42
|
-
definition = (singleton ? rbs_builder.build_singleton(type_name) : rbs_builder.build_instance(type_name)) rescue nil
|
43
|
-
method = definition.methods[method_name] if definition
|
44
|
-
return method if method
|
45
|
-
end
|
46
|
-
nil
|
47
|
-
end
|
48
|
-
|
49
|
-
def self.method_return_type(type, method_name)
|
50
|
-
receivers = type.types.map do |t|
|
51
|
-
case t
|
52
|
-
in SingletonType
|
53
|
-
[t, t.module_or_class, true]
|
54
|
-
in InstanceType
|
55
|
-
[t, t.klass, false]
|
56
|
-
end
|
57
|
-
end
|
58
|
-
types = receivers.flat_map do |receiver_type, klass, singleton|
|
59
|
-
method = rbs_search_method klass, method_name, singleton
|
60
|
-
next [] unless method
|
61
|
-
method.method_types.map do |method|
|
62
|
-
from_rbs_type(method.type.return_type, receiver_type, {})
|
63
|
-
end
|
64
|
-
end
|
65
|
-
UnionType[*types]
|
66
|
-
end
|
67
|
-
|
68
|
-
def self.rbs_methods(type, method_name, args_types, kwargs_type, has_block)
|
69
|
-
return [] unless rbs_builder
|
70
|
-
|
71
|
-
receivers = type.types.map do |t|
|
72
|
-
case t
|
73
|
-
in SingletonType
|
74
|
-
[t, t.module_or_class, true]
|
75
|
-
in InstanceType
|
76
|
-
[t, t.klass, false]
|
77
|
-
end
|
78
|
-
end
|
79
|
-
has_splat = args_types.include?(nil)
|
80
|
-
methods_with_score = receivers.flat_map do |receiver_type, klass, singleton|
|
81
|
-
method = rbs_search_method klass, method_name, singleton
|
82
|
-
next [] unless method
|
83
|
-
method.method_types.map do |method_type|
|
84
|
-
score = 0
|
85
|
-
score += 2 if !!method_type.block == has_block
|
86
|
-
reqs = method_type.type.required_positionals
|
87
|
-
opts = method_type.type.optional_positionals
|
88
|
-
rest = method_type.type.rest_positionals
|
89
|
-
trailings = method_type.type.trailing_positionals
|
90
|
-
keyreqs = method_type.type.required_keywords
|
91
|
-
keyopts = method_type.type.optional_keywords
|
92
|
-
keyrest = method_type.type.rest_keywords
|
93
|
-
args = args_types
|
94
|
-
if kwargs_type&.any? && keyreqs.empty? && keyopts.empty? && keyrest.nil?
|
95
|
-
kw_value_type = UnionType[*kwargs_type.values]
|
96
|
-
args += [InstanceType.new(Hash, K: SYMBOL, V: kw_value_type)]
|
97
|
-
end
|
98
|
-
if has_splat
|
99
|
-
score += 1 if args.count(&:itself) <= reqs.size + opts.size + trailings.size
|
100
|
-
elsif reqs.size + trailings.size <= args.size && (rest || args.size <= reqs.size + opts.size + trailings.size)
|
101
|
-
score += 2
|
102
|
-
centers = args[reqs.size...-trailings.size]
|
103
|
-
given = args.first(reqs.size) + centers.take(opts.size) + args.last(trailings.size)
|
104
|
-
expected = (reqs + opts.take(centers.size) + trailings).map(&:type)
|
105
|
-
if rest
|
106
|
-
given << UnionType[*centers.drop(opts.size)]
|
107
|
-
expected << rest.type
|
108
|
-
end
|
109
|
-
if given.any?
|
110
|
-
score += given.zip(expected).count do |t, e|
|
111
|
-
e = from_rbs_type e, receiver_type
|
112
|
-
intersect?(t, e) || (intersect?(STRING, e) && t.methods.include?(:to_str)) || (intersect?(INTEGER, e) && t.methods.include?(:to_int)) || (intersect?(ARRAY, e) && t.methods.include?(:to_ary))
|
113
|
-
end.fdiv(given.size)
|
114
|
-
end
|
115
|
-
end
|
116
|
-
[[method_type, given || [], expected || []], score]
|
117
|
-
end
|
118
|
-
end
|
119
|
-
max_score = methods_with_score.map(&:last).max
|
120
|
-
methods_with_score.select { _2 == max_score }.map(&:first)
|
121
|
-
end
|
122
|
-
|
123
|
-
def self.intersect?(a, b)
|
124
|
-
atypes = a.types.group_by(&:class)
|
125
|
-
btypes = b.types.group_by(&:class)
|
126
|
-
if atypes[SingletonType] && btypes[SingletonType]
|
127
|
-
aa, bb = [atypes, btypes].map {|types| types[SingletonType].map(&:module_or_class) }
|
128
|
-
return true if (aa & bb).any?
|
129
|
-
end
|
130
|
-
|
131
|
-
aa, bb = [atypes, btypes].map {|types| (types[InstanceType] || []).map(&:klass) }
|
132
|
-
(aa.flat_map(&:ancestors) & bb).any?
|
133
|
-
end
|
134
|
-
|
135
|
-
def self.type_from_object(object)
|
136
|
-
case object
|
137
|
-
when Array
|
138
|
-
InstanceType.new Array, { Elem: union_type_from_objects(object) }
|
139
|
-
when Hash
|
140
|
-
InstanceType.new Hash, { K: union_type_from_objects(object.keys), V: union_type_from_objects(object.values) }
|
141
|
-
when Module
|
142
|
-
SingletonType.new object
|
143
|
-
else
|
144
|
-
klass = Methods::OBJECT_SINGLETON_CLASS_METHOD.bind_call(object) rescue Methods::OBJECT_CLASS_METHOD.bind_call(object)
|
145
|
-
InstanceType.new klass
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
def self.union_type_from_objects(objects)
|
150
|
-
values = objects.size <= OBJECT_TO_TYPE_SAMPLE_SIZE ? objects : objects.sample(OBJECT_TO_TYPE_SAMPLE_SIZE)
|
151
|
-
klasses = values.map { Methods::OBJECT_CLASS_METHOD.bind_call(_1) }
|
152
|
-
UnionType[*klasses.uniq.map { InstanceType.new _1 }]
|
153
|
-
end
|
154
|
-
|
155
|
-
class SingletonType
|
156
|
-
attr_reader :module_or_class
|
157
|
-
def initialize(module_or_class)
|
158
|
-
@module_or_class = module_or_class
|
159
|
-
end
|
160
|
-
def transform() = yield(self)
|
161
|
-
def methods() = @module_or_class.methods
|
162
|
-
def all_methods() = methods | Kernel.methods
|
163
|
-
def constants() = @module_or_class.constants
|
164
|
-
def types() = [self]
|
165
|
-
def nillable?() = false
|
166
|
-
def nonnillable() = self
|
167
|
-
def inspect
|
168
|
-
"#{module_or_class}.itself"
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
class InstanceType
|
173
|
-
attr_reader :klass, :params
|
174
|
-
def initialize(klass, params = {})
|
175
|
-
@klass = klass
|
176
|
-
@params = params
|
177
|
-
end
|
178
|
-
def transform() = yield(self)
|
179
|
-
def methods() = rbs_methods.select { _2.public? }.keys | @klass.instance_methods
|
180
|
-
def all_methods() = rbs_methods.keys | @klass.instance_methods | @klass.private_instance_methods
|
181
|
-
def constants() = []
|
182
|
-
def types() = [self]
|
183
|
-
def nillable?() = (@klass == NilClass)
|
184
|
-
def nonnillable() = self
|
185
|
-
def rbs_methods
|
186
|
-
name = Types.class_name_of(@klass)
|
187
|
-
return {} unless name && Types.rbs_builder
|
188
|
-
|
189
|
-
type_name = RBS::TypeName(name).absolute!
|
190
|
-
Types.rbs_builder.build_instance(type_name).methods rescue {}
|
191
|
-
end
|
192
|
-
def inspect
|
193
|
-
if params.empty?
|
194
|
-
inspect_without_params
|
195
|
-
else
|
196
|
-
params_string = "[#{params.map { "#{_1}: #{_2.inspect}" }.join(', ')}]"
|
197
|
-
"#{inspect_without_params}#{params_string}"
|
198
|
-
end
|
199
|
-
end
|
200
|
-
def inspect_without_params
|
201
|
-
if klass == NilClass
|
202
|
-
'nil'
|
203
|
-
elsif klass == TrueClass
|
204
|
-
'true'
|
205
|
-
elsif klass == FalseClass
|
206
|
-
'false'
|
207
|
-
else
|
208
|
-
klass.singleton_class? ? klass.superclass.to_s : klass.to_s
|
209
|
-
end
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
NIL = InstanceType.new NilClass
|
214
|
-
OBJECT = InstanceType.new Object
|
215
|
-
TRUE = InstanceType.new TrueClass
|
216
|
-
FALSE = InstanceType.new FalseClass
|
217
|
-
SYMBOL = InstanceType.new Symbol
|
218
|
-
STRING = InstanceType.new String
|
219
|
-
INTEGER = InstanceType.new Integer
|
220
|
-
RANGE = InstanceType.new Range
|
221
|
-
REGEXP = InstanceType.new Regexp
|
222
|
-
FLOAT = InstanceType.new Float
|
223
|
-
RATIONAL = InstanceType.new Rational
|
224
|
-
COMPLEX = InstanceType.new Complex
|
225
|
-
ARRAY = InstanceType.new Array
|
226
|
-
HASH = InstanceType.new Hash
|
227
|
-
CLASS = InstanceType.new Class
|
228
|
-
MODULE = InstanceType.new Module
|
229
|
-
PROC = InstanceType.new Proc
|
230
|
-
|
231
|
-
class UnionType
|
232
|
-
attr_reader :types
|
233
|
-
|
234
|
-
def initialize(*types)
|
235
|
-
@types = []
|
236
|
-
singletons = []
|
237
|
-
instances = {}
|
238
|
-
collect = -> type do
|
239
|
-
case type
|
240
|
-
in UnionType
|
241
|
-
type.types.each(&collect)
|
242
|
-
in InstanceType
|
243
|
-
params = (instances[type.klass] ||= {})
|
244
|
-
type.params.each do |k, v|
|
245
|
-
(params[k] ||= []) << v
|
246
|
-
end
|
247
|
-
in SingletonType
|
248
|
-
singletons << type
|
249
|
-
end
|
250
|
-
end
|
251
|
-
types.each(&collect)
|
252
|
-
@types = singletons.uniq + instances.map do |klass, params|
|
253
|
-
InstanceType.new(klass, params.transform_values { |v| UnionType[*v] })
|
254
|
-
end
|
255
|
-
end
|
256
|
-
|
257
|
-
def transform(&block)
|
258
|
-
UnionType[*types.map(&block)]
|
259
|
-
end
|
260
|
-
|
261
|
-
def nillable?
|
262
|
-
types.any?(&:nillable?)
|
263
|
-
end
|
264
|
-
|
265
|
-
def nonnillable
|
266
|
-
UnionType[*types.reject { _1.is_a?(InstanceType) && _1.klass == NilClass }]
|
267
|
-
end
|
268
|
-
|
269
|
-
def self.[](*types)
|
270
|
-
type = new(*types)
|
271
|
-
if type.types.empty?
|
272
|
-
OBJECT
|
273
|
-
elsif type.types.size == 1
|
274
|
-
type.types.first
|
275
|
-
else
|
276
|
-
type
|
277
|
-
end
|
278
|
-
end
|
279
|
-
|
280
|
-
def methods() = @types.flat_map(&:methods).uniq
|
281
|
-
def all_methods() = @types.flat_map(&:all_methods).uniq
|
282
|
-
def constants() = @types.flat_map(&:constants).uniq
|
283
|
-
def inspect() = @types.map(&:inspect).join(' | ')
|
284
|
-
end
|
285
|
-
|
286
|
-
BOOLEAN = UnionType[TRUE, FALSE]
|
287
|
-
|
288
|
-
def self.array_of(*types)
|
289
|
-
type = types.size >= 2 ? UnionType[*types] : types.first || OBJECT
|
290
|
-
InstanceType.new Array, Elem: type
|
291
|
-
end
|
292
|
-
|
293
|
-
def self.from_rbs_type(return_type, self_type, extra_vars = {})
|
294
|
-
case return_type
|
295
|
-
when RBS::Types::Bases::Self
|
296
|
-
self_type
|
297
|
-
when RBS::Types::Bases::Bottom, RBS::Types::Bases::Nil
|
298
|
-
NIL
|
299
|
-
when RBS::Types::Bases::Any, RBS::Types::Bases::Void
|
300
|
-
OBJECT
|
301
|
-
when RBS::Types::Bases::Class
|
302
|
-
self_type.transform do |type|
|
303
|
-
case type
|
304
|
-
in SingletonType
|
305
|
-
InstanceType.new(self_type.module_or_class.is_a?(Class) ? Class : Module)
|
306
|
-
in InstanceType
|
307
|
-
SingletonType.new type.klass
|
308
|
-
end
|
309
|
-
end
|
310
|
-
UnionType[*types]
|
311
|
-
when RBS::Types::Bases::Bool
|
312
|
-
BOOLEAN
|
313
|
-
when RBS::Types::Bases::Instance
|
314
|
-
self_type.transform do |type|
|
315
|
-
if type.is_a?(SingletonType) && type.module_or_class.is_a?(Class)
|
316
|
-
InstanceType.new type.module_or_class
|
317
|
-
else
|
318
|
-
OBJECT
|
319
|
-
end
|
320
|
-
end
|
321
|
-
when RBS::Types::Union
|
322
|
-
UnionType[*return_type.types.map { from_rbs_type _1, self_type, extra_vars }]
|
323
|
-
when RBS::Types::Proc
|
324
|
-
PROC
|
325
|
-
when RBS::Types::Tuple
|
326
|
-
elem = UnionType[*return_type.types.map { from_rbs_type _1, self_type, extra_vars }]
|
327
|
-
InstanceType.new Array, Elem: elem
|
328
|
-
when RBS::Types::Record
|
329
|
-
InstanceType.new Hash, K: SYMBOL, V: OBJECT
|
330
|
-
when RBS::Types::Literal
|
331
|
-
InstanceType.new return_type.literal.class
|
332
|
-
when RBS::Types::Variable
|
333
|
-
if extra_vars.key? return_type.name
|
334
|
-
extra_vars[return_type.name]
|
335
|
-
elsif self_type.is_a? InstanceType
|
336
|
-
self_type.params[return_type.name] || OBJECT
|
337
|
-
elsif self_type.is_a? UnionType
|
338
|
-
types = self_type.types.filter_map do |t|
|
339
|
-
t.params[return_type.name] if t.is_a? InstanceType
|
340
|
-
end
|
341
|
-
UnionType[*types]
|
342
|
-
else
|
343
|
-
OBJECT
|
344
|
-
end
|
345
|
-
when RBS::Types::Optional
|
346
|
-
UnionType[from_rbs_type(return_type.type, self_type, extra_vars), NIL]
|
347
|
-
when RBS::Types::Alias
|
348
|
-
case return_type.name.name
|
349
|
-
when :int
|
350
|
-
INTEGER
|
351
|
-
when :boolish
|
352
|
-
BOOLEAN
|
353
|
-
when :string
|
354
|
-
STRING
|
355
|
-
else
|
356
|
-
# TODO: ???
|
357
|
-
OBJECT
|
358
|
-
end
|
359
|
-
when RBS::Types::Interface
|
360
|
-
# unimplemented
|
361
|
-
OBJECT
|
362
|
-
when RBS::Types::ClassInstance
|
363
|
-
klass = return_type.name.to_namespace.path.reduce(Object) { _1.const_get _2 }
|
364
|
-
if return_type.args
|
365
|
-
args = return_type.args.map { from_rbs_type _1, self_type, extra_vars }
|
366
|
-
names = rbs_builder.build_singleton(return_type.name).type_params
|
367
|
-
params = names.map.with_index { [_1, args[_2] || OBJECT] }.to_h
|
368
|
-
end
|
369
|
-
InstanceType.new klass, params || {}
|
370
|
-
end
|
371
|
-
end
|
372
|
-
|
373
|
-
def self.method_return_bottom?(method)
|
374
|
-
method.type.return_type.is_a? RBS::Types::Bases::Bottom
|
375
|
-
end
|
376
|
-
|
377
|
-
def self.match_free_variables(vars, types, values)
|
378
|
-
accumulator = {}
|
379
|
-
types.zip values do |t, v|
|
380
|
-
_match_free_variable(vars, t, v, accumulator) if v
|
381
|
-
end
|
382
|
-
accumulator.transform_values { UnionType[*_1] }
|
383
|
-
end
|
384
|
-
|
385
|
-
def self._match_free_variable(vars, rbs_type, value, accumulator)
|
386
|
-
case [rbs_type, value]
|
387
|
-
in [RBS::Types::Variable,]
|
388
|
-
(accumulator[rbs_type.name] ||= []) << value if vars.include? rbs_type.name
|
389
|
-
in [RBS::Types::ClassInstance, InstanceType]
|
390
|
-
names = rbs_builder.build_singleton(rbs_type.name).type_params
|
391
|
-
names.zip(rbs_type.args).each do |name, arg|
|
392
|
-
v = value.params[name]
|
393
|
-
_match_free_variable vars, arg, v, accumulator if v
|
394
|
-
end
|
395
|
-
in [RBS::Types::Tuple, InstanceType] if value.klass == Array
|
396
|
-
v = value.params[:Elem]
|
397
|
-
rbs_type.types.each do |t|
|
398
|
-
_match_free_variable vars, t, v, accumulator
|
399
|
-
end
|
400
|
-
in [RBS::Types::Record, InstanceType] if value.klass == Hash
|
401
|
-
# TODO
|
402
|
-
in [RBS::Types::Interface,]
|
403
|
-
definition = rbs_builder.build_interface rbs_type.name
|
404
|
-
convert = {}
|
405
|
-
definition.type_params.zip(rbs_type.args).each do |from, arg|
|
406
|
-
convert[from] = arg.name if arg.is_a? RBS::Types::Variable
|
407
|
-
end
|
408
|
-
return if convert.empty?
|
409
|
-
ac = {}
|
410
|
-
definition.methods.each do |method_name, method|
|
411
|
-
return_type = method_return_type value, method_name
|
412
|
-
method.defs.each do |method_def|
|
413
|
-
interface_return_type = method_def.type.type.return_type
|
414
|
-
_match_free_variable convert, interface_return_type, return_type, ac
|
415
|
-
end
|
416
|
-
end
|
417
|
-
convert.each do |from, to|
|
418
|
-
values = ac[from]
|
419
|
-
(accumulator[to] ||= []).concat values if values
|
420
|
-
end
|
421
|
-
else
|
422
|
-
end
|
423
|
-
end
|
424
|
-
end
|
425
|
-
end
|
426
|
-
end
|