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.
@@ -1,235 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'prism'
4
- require 'irb/completion'
5
- require_relative 'type_analyzer'
6
-
7
- module IRB
8
- module TypeCompletion
9
- class Completor < BaseCompletor # :nodoc:
10
- HIDDEN_METHODS = %w[Namespace TypeName] # defined by rbs, should be hidden
11
-
12
- class << self
13
- attr_accessor :last_completion_error
14
- end
15
-
16
- def inspect
17
- name = 'TypeCompletion::Completor'
18
- prism_info = "Prism: #{Prism::VERSION}"
19
- if Types.rbs_builder
20
- "#{name}(#{prism_info}, RBS: #{RBS::VERSION})"
21
- elsif Types.rbs_load_error
22
- "#{name}(#{prism_info}, RBS: #{Types.rbs_load_error.inspect})"
23
- else
24
- "#{name}(#{prism_info}, RBS: loading)"
25
- end
26
- end
27
-
28
- def completion_candidates(preposing, target, _postposing, bind:)
29
- @preposing = preposing
30
- verbose, $VERBOSE = $VERBOSE, nil
31
- code = "#{preposing}#{target}"
32
- @result = analyze code, bind
33
- name, candidates = candidates_from_result(@result)
34
-
35
- all_symbols_pattern = /\A[ -\/:-@\[-`\{-~]*\z/
36
- candidates.map(&:to_s).select { !_1.match?(all_symbols_pattern) && _1.start_with?(name) }.uniq.sort.map do
37
- target + _1[name.size..]
38
- end
39
- rescue SyntaxError, StandardError => e
40
- Completor.last_completion_error = e
41
- handle_error(e)
42
- []
43
- ensure
44
- $VERBOSE = verbose
45
- end
46
-
47
- def doc_namespace(preposing, matched, postposing, bind:)
48
- name = matched[/[a-zA-Z_0-9]*[!?=]?\z/]
49
- method_doc = -> type do
50
- type = type.types.find { _1.all_methods.include? name.to_sym }
51
- case type
52
- when Types::SingletonType
53
- "#{Types.class_name_of(type.module_or_class)}.#{name}"
54
- when Types::InstanceType
55
- "#{Types.class_name_of(type.klass)}##{name}"
56
- end
57
- end
58
- call_or_const_doc = -> type do
59
- if name =~ /\A[A-Z]/
60
- type = type.types.grep(Types::SingletonType).find { _1.module_or_class.const_defined?(name) }
61
- type.module_or_class == Object ? name : "#{Types.class_name_of(type.module_or_class)}::#{name}" if type
62
- else
63
- method_doc.call(type)
64
- end
65
- end
66
-
67
- value_doc = -> type do
68
- return unless type
69
- type.types.each do |t|
70
- case t
71
- when Types::SingletonType
72
- return Types.class_name_of(t.module_or_class)
73
- when Types::InstanceType
74
- return Types.class_name_of(t.klass)
75
- end
76
- end
77
- nil
78
- end
79
-
80
- case @result
81
- in [:call_or_const, type, _name, _self_call]
82
- call_or_const_doc.call type
83
- in [:const, type, _name, scope]
84
- if type
85
- call_or_const_doc.call type
86
- else
87
- value_doc.call scope[name]
88
- end
89
- in [:gvar, _name, scope]
90
- value_doc.call scope["$#{name}"]
91
- in [:ivar, _name, scope]
92
- value_doc.call scope["@#{name}"]
93
- in [:cvar, _name, scope]
94
- value_doc.call scope["@@#{name}"]
95
- in [:call, type, _name, _self_call]
96
- method_doc.call type
97
- in [:lvar_or_method, _name, scope]
98
- if scope.local_variables.include?(name)
99
- value_doc.call scope[name]
100
- else
101
- method_doc.call scope.self_type
102
- end
103
- else
104
- end
105
- end
106
-
107
- def candidates_from_result(result)
108
- candidates = case result
109
- in [:require, name]
110
- retrieve_files_to_require_from_load_path
111
- in [:require_relative, name]
112
- retrieve_files_to_require_relative_from_current_dir
113
- in [:call_or_const, type, name, self_call]
114
- ((self_call ? type.all_methods : type.methods).map(&:to_s) - HIDDEN_METHODS) | type.constants
115
- in [:const, type, name, scope]
116
- if type
117
- scope_constants = type.types.flat_map do |t|
118
- scope.table_module_constants(t.module_or_class) if t.is_a?(Types::SingletonType)
119
- end
120
- (scope_constants.compact | type.constants.map(&:to_s)).sort
121
- else
122
- scope.constants.sort | ReservedWords
123
- end
124
- in [:ivar, name, scope]
125
- ivars = scope.instance_variables.sort
126
- name == '@' ? ivars + scope.class_variables.sort : ivars
127
- in [:cvar, name, scope]
128
- scope.class_variables
129
- in [:gvar, name, scope]
130
- scope.global_variables
131
- in [:symbol, name]
132
- Symbol.all_symbols.map { _1.inspect[1..] }
133
- in [:call, type, name, self_call]
134
- (self_call ? type.all_methods : type.methods).map(&:to_s) - HIDDEN_METHODS
135
- in [:lvar_or_method, name, scope]
136
- scope.self_type.all_methods.map(&:to_s) | scope.local_variables | ReservedWords
137
- else
138
- []
139
- end
140
- [name || '', candidates]
141
- end
142
-
143
- def analyze(code, binding = Object::TOPLEVEL_BINDING)
144
- # Workaround for https://github.com/ruby/prism/issues/1592
145
- return if code.match?(/%[qQ]\z/)
146
-
147
- ast = Prism.parse(code, scopes: [binding.local_variables]).value
148
- name = code[/(@@|@|\$)?\w*[!?=]?\z/]
149
- *parents, target_node = find_target ast, code.bytesize - name.bytesize
150
- return unless target_node
151
-
152
- calculate_scope = -> { TypeAnalyzer.calculate_target_type_scope(binding, parents, target_node).last }
153
- calculate_type_scope = ->(node) { TypeAnalyzer.calculate_target_type_scope binding, [*parents, target_node], node }
154
-
155
- case target_node
156
- when Prism::StringNode, Prism::InterpolatedStringNode
157
- call_node, args_node = parents.last(2)
158
- return unless call_node.is_a?(Prism::CallNode) && call_node.receiver.nil?
159
- return unless args_node.is_a?(Prism::ArgumentsNode) && args_node.arguments.size == 1
160
-
161
- case call_node.name
162
- when :require
163
- [:require, name.rstrip]
164
- when :require_relative
165
- [:require_relative, name.rstrip]
166
- end
167
- when Prism::SymbolNode
168
- if parents.last.is_a? Prism::BlockArgumentNode # method(&:target)
169
- receiver_type, _scope = calculate_type_scope.call target_node
170
- [:call, receiver_type, name, false]
171
- else
172
- [:symbol, name] unless name.empty?
173
- end
174
- when Prism::CallNode
175
- return [:lvar_or_method, name, calculate_scope.call] if target_node.receiver.nil?
176
-
177
- self_call = target_node.receiver.is_a? Prism::SelfNode
178
- op = target_node.call_operator
179
- receiver_type, _scope = calculate_type_scope.call target_node.receiver
180
- receiver_type = receiver_type.nonnillable if op == '&.'
181
- [op == '::' ? :call_or_const : :call, receiver_type, name, self_call]
182
- when Prism::LocalVariableReadNode, Prism::LocalVariableTargetNode
183
- [:lvar_or_method, name, calculate_scope.call]
184
- when Prism::ConstantReadNode, Prism::ConstantTargetNode
185
- if parents.last.is_a? Prism::ConstantPathNode
186
- path_node = parents.last
187
- if path_node.parent # A::B
188
- receiver, scope = calculate_type_scope.call(path_node.parent)
189
- [:const, receiver, name, scope]
190
- else # ::A
191
- scope = calculate_scope.call
192
- [:const, Types::SingletonType.new(Object), name, scope]
193
- end
194
- else
195
- [:const, nil, name, calculate_scope.call]
196
- end
197
- when Prism::GlobalVariableReadNode, Prism::GlobalVariableTargetNode
198
- [:gvar, name, calculate_scope.call]
199
- when Prism::InstanceVariableReadNode, Prism::InstanceVariableTargetNode
200
- [:ivar, name, calculate_scope.call]
201
- when Prism::ClassVariableReadNode, Prism::ClassVariableTargetNode
202
- [:cvar, name, calculate_scope.call]
203
- end
204
- end
205
-
206
- def find_target(node, position)
207
- location = (
208
- case node
209
- when Prism::CallNode
210
- node.message_loc
211
- when Prism::SymbolNode
212
- node.value_loc
213
- when Prism::StringNode
214
- node.content_loc
215
- when Prism::InterpolatedStringNode
216
- node.closing_loc if node.parts.empty?
217
- end
218
- )
219
- return [node] if location&.start_offset == position
220
-
221
- node.compact_child_nodes.each do |n|
222
- match = find_target(n, position)
223
- next unless match
224
- match.unshift node
225
- return match
226
- end
227
-
228
- [node] if node.location.start_offset == position
229
- end
230
-
231
- def handle_error(e)
232
- end
233
- end
234
- end
235
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module IRB
4
- module TypeCompletion
5
- module Methods
6
- OBJECT_SINGLETON_CLASS_METHOD = Object.instance_method(:singleton_class)
7
- OBJECT_INSTANCE_VARIABLES_METHOD = Object.instance_method(:instance_variables)
8
- OBJECT_INSTANCE_VARIABLE_GET_METHOD = Object.instance_method(:instance_variable_get)
9
- OBJECT_CLASS_METHOD = Object.instance_method(:class)
10
- MODULE_NAME_METHOD = Module.instance_method(:name)
11
- end
12
- end
13
- end
@@ -1,412 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'set'
4
- require_relative 'types'
5
-
6
- module IRB
7
- module TypeCompletion
8
-
9
- class RootScope
10
- attr_reader :module_nesting, :self_object
11
-
12
- def initialize(binding, self_object, local_variables)
13
- @binding = binding
14
- @self_object = self_object
15
- @cache = {}
16
- modules = [*binding.eval('::Module.nesting'), Object]
17
- @module_nesting = modules.map { [_1, []] }
18
- binding_local_variables = binding.local_variables
19
- uninitialized_locals = local_variables - binding_local_variables
20
- uninitialized_locals.each { @cache[_1] = Types::NIL }
21
- @local_variables = (local_variables | binding_local_variables).map(&:to_s).to_set
22
- @global_variables = Kernel.global_variables.map(&:to_s).to_set
23
- @owned_constants_cache = {}
24
- end
25
-
26
- def level() = 0
27
-
28
- def level_of(_name, _var_type) = 0
29
-
30
- def mutable?() = false
31
-
32
- def module_own_constant?(mod, name)
33
- set = (@owned_constants_cache[mod] ||= Set.new(mod.constants.map(&:to_s)))
34
- set.include? name
35
- end
36
-
37
- def get_const(nesting, path, _key = nil)
38
- return unless nesting
39
-
40
- result = path.reduce nesting do |mod, name|
41
- return nil unless mod.is_a?(Module) && module_own_constant?(mod, name)
42
- mod.const_get name
43
- end
44
- Types.type_from_object result
45
- end
46
-
47
- def get_cvar(nesting, path, name, _key = nil)
48
- return Types::NIL unless nesting
49
-
50
- result = path.reduce nesting do |mod, n|
51
- return Types::NIL unless mod.is_a?(Module) && module_own_constant?(mod, n)
52
- mod.const_get n
53
- end
54
- value = result.class_variable_get name if result.is_a?(Module) && name.size >= 3 && result.class_variable_defined?(name)
55
- Types.type_from_object value
56
- end
57
-
58
- def [](name)
59
- @cache[name] ||= (
60
- value = case RootScope.type_by_name name
61
- when :ivar
62
- begin
63
- Methods::OBJECT_INSTANCE_VARIABLE_GET_METHOD.bind_call(@self_object, name)
64
- rescue NameError
65
- end
66
- when :lvar
67
- begin
68
- @binding.local_variable_get(name)
69
- rescue NameError
70
- end
71
- when :gvar
72
- @binding.eval name if @global_variables.include? name
73
- end
74
- Types.type_from_object(value)
75
- )
76
- end
77
-
78
- def self_type
79
- Types.type_from_object @self_object
80
- end
81
-
82
- def local_variables() = @local_variables.to_a
83
-
84
- def global_variables() = @global_variables.to_a
85
-
86
- def self.type_by_name(name)
87
- if name.start_with? '@@'
88
- # "@@cvar" or "@@cvar::[module_id]::[module_path]"
89
- :cvar
90
- elsif name.start_with? '@'
91
- :ivar
92
- elsif name.start_with? '$'
93
- :gvar
94
- elsif name.start_with? '%'
95
- :internal
96
- elsif name[0].downcase != name[0] || name[0].match?(/\d/)
97
- # "ConstName" or "[module_id]::[const_path]"
98
- :const
99
- else
100
- :lvar
101
- end
102
- end
103
- end
104
-
105
- class Scope
106
- BREAK_RESULT = '%break'
107
- NEXT_RESULT = '%next'
108
- RETURN_RESULT = '%return'
109
- PATTERNMATCH_BREAK = '%match'
110
-
111
- attr_reader :parent, :mergeable_changes, :level, :module_nesting
112
-
113
- def self.from_binding(binding, locals) = new(RootScope.new(binding, binding.receiver, locals))
114
-
115
- def initialize(parent, table = {}, trace_ivar: true, trace_lvar: true, self_type: nil, nesting: nil)
116
- @parent = parent
117
- @level = parent.level + 1
118
- @trace_ivar = trace_ivar
119
- @trace_lvar = trace_lvar
120
- @module_nesting = nesting ? [nesting, *parent.module_nesting] : parent.module_nesting
121
- @self_type = self_type
122
- @terminated = false
123
- @jump_branches = []
124
- @mergeable_changes = @table = table.transform_values { [level, _1] }
125
- end
126
-
127
- def mutable? = true
128
-
129
- def terminated?
130
- @terminated
131
- end
132
-
133
- def terminate_with(type, value)
134
- return if terminated?
135
- store_jump type, value, @mergeable_changes
136
- terminate
137
- end
138
-
139
- def store_jump(type, value, changes)
140
- return if terminated?
141
- if has_own?(type)
142
- changes[type] = [level, value]
143
- @jump_branches << changes
144
- elsif @parent.mutable?
145
- @parent.store_jump(type, value, changes)
146
- end
147
- end
148
-
149
- def terminate
150
- return if terminated?
151
- @terminated = true
152
- @table = @mergeable_changes.dup
153
- end
154
-
155
- def trace?(name)
156
- return false unless @parent
157
- type = RootScope.type_by_name(name)
158
- type == :ivar ? @trace_ivar : type == :lvar ? @trace_lvar : true
159
- end
160
-
161
- def level_of(name, var_type)
162
- case var_type
163
- when :ivar
164
- return level unless @trace_ivar
165
- when :gvar
166
- return 0
167
- end
168
- variable_level, = @table[name]
169
- variable_level || parent.level_of(name, var_type)
170
- end
171
-
172
- def get_const(nesting, path, key = nil)
173
- key ||= [nesting.__id__, path].join('::')
174
- _l, value = @table[key]
175
- value || @parent.get_const(nesting, path, key)
176
- end
177
-
178
- def get_cvar(nesting, path, name, key = nil)
179
- key ||= [name, nesting.__id__, path].join('::')
180
- _l, value = @table[key]
181
- value || @parent.get_cvar(nesting, path, name, key)
182
- end
183
-
184
- def [](name)
185
- type = RootScope.type_by_name(name)
186
- if type == :const
187
- return get_const(nil, nil, name) || Types::NIL if name.include?('::')
188
-
189
- module_nesting.each do |(nesting, path)|
190
- value = get_const nesting, [*path, name]
191
- return value if value
192
- end
193
- return Types::NIL
194
- elsif type == :cvar
195
- return get_cvar(nil, nil, nil, name) if name.include?('::')
196
-
197
- nesting, path = module_nesting.first
198
- return get_cvar(nesting, path, name)
199
- end
200
- level, value = @table[name]
201
- if level
202
- value
203
- elsif trace? name
204
- @parent[name]
205
- elsif type == :ivar
206
- self_instance_variable_get name
207
- end
208
- end
209
-
210
- def set_const(nesting, path, value)
211
- key = [nesting.__id__, path].join('::')
212
- @table[key] = [0, value]
213
- end
214
-
215
- def set_cvar(nesting, path, name, value)
216
- key = [name, nesting.__id__, path].join('::')
217
- @table[key] = [0, value]
218
- end
219
-
220
- def []=(name, value)
221
- type = RootScope.type_by_name(name)
222
- if type == :const
223
- if name.include?('::')
224
- @table[name] = [0, value]
225
- else
226
- parent_module, parent_path = module_nesting.first
227
- set_const parent_module, [*parent_path, name], value
228
- end
229
- return
230
- elsif type == :cvar
231
- if name.include?('::')
232
- @table[name] = [0, value]
233
- else
234
- parent_module, parent_path = module_nesting.first
235
- set_cvar parent_module, parent_path, name, value
236
- end
237
- return
238
- end
239
- variable_level = level_of name, type
240
- @table[name] = [variable_level, value] if variable_level
241
- end
242
-
243
- def self_type
244
- @self_type || @parent.self_type
245
- end
246
-
247
- def global_variables
248
- gvar_keys = @table.keys.select do |name|
249
- RootScope.type_by_name(name) == :gvar
250
- end
251
- gvar_keys | @parent.global_variables
252
- end
253
-
254
- def local_variables
255
- lvar_keys = @table.keys.select do |name|
256
- RootScope.type_by_name(name) == :lvar
257
- end
258
- lvar_keys |= @parent.local_variables if @trace_lvar
259
- lvar_keys
260
- end
261
-
262
- def table_constants
263
- constants = module_nesting.flat_map do |mod, path|
264
- prefix = [mod.__id__, *path].join('::') + '::'
265
- @table.keys.select { _1.start_with? prefix }.map { _1.delete_prefix(prefix).split('::').first }
266
- end.uniq
267
- constants |= @parent.table_constants if @parent.mutable?
268
- constants
269
- end
270
-
271
- def table_module_constants(mod)
272
- prefix = "#{mod.__id__}::"
273
- constants = @table.keys.select { _1.start_with? prefix }.map { _1.delete_prefix(prefix).split('::').first }
274
- constants |= @parent.table_constants if @parent.mutable?
275
- constants
276
- end
277
-
278
- def base_scope
279
- @parent.mutable? ? @parent.base_scope : @parent
280
- end
281
-
282
- def table_instance_variables
283
- ivars = @table.keys.select { RootScope.type_by_name(_1) == :ivar }
284
- ivars |= @parent.table_instance_variables if @parent.mutable? && @trace_ivar
285
- ivars
286
- end
287
-
288
- def instance_variables
289
- self_singleton_types = self_type.types.grep(Types::SingletonType)
290
- singleton_classes = self_type.types.grep(Types::InstanceType).map(&:klass).select(&:singleton_class?)
291
- base_self = base_scope.self_object
292
- self_instance_variables = singleton_classes.flat_map do |singleton_class|
293
- if singleton_class.respond_to? :attached_object
294
- Methods::OBJECT_INSTANCE_VARIABLES_METHOD.bind_call(singleton_class.attached_object).map(&:to_s)
295
- elsif singleton_class == Methods::OBJECT_SINGLETON_CLASS_METHOD.bind_call(base_self)
296
- Methods::OBJECT_INSTANCE_VARIABLES_METHOD.bind_call(base_self).map(&:to_s)
297
- else
298
- []
299
- end
300
- end
301
- [
302
- self_singleton_types.flat_map { _1.module_or_class.instance_variables.map(&:to_s) },
303
- self_instance_variables || [],
304
- table_instance_variables
305
- ].inject(:|)
306
- end
307
-
308
- def self_instance_variable_get(name)
309
- self_objects = self_type.types.grep(Types::SingletonType).map(&:module_or_class)
310
- singleton_classes = self_type.types.grep(Types::InstanceType).map(&:klass).select(&:singleton_class?)
311
- base_self = base_scope.self_object
312
- singleton_classes.each do |singleton_class|
313
- if singleton_class.respond_to? :attached_object
314
- self_objects << singleton_class.attached_object
315
- elsif singleton_class == base_self.singleton_class
316
- self_objects << base_self
317
- end
318
- end
319
- types = self_objects.map do |object|
320
- value = begin
321
- Methods::OBJECT_INSTANCE_VARIABLE_GET_METHOD.bind_call(object, name)
322
- rescue NameError
323
- end
324
- Types.type_from_object value
325
- end
326
- Types::UnionType[*types]
327
- end
328
-
329
- def table_class_variables
330
- cvars = @table.keys.filter_map { _1.split('::', 2).first if RootScope.type_by_name(_1) == :cvar }
331
- cvars |= @parent.table_class_variables if @parent.mutable?
332
- cvars
333
- end
334
-
335
- def class_variables
336
- cvars = table_class_variables
337
- m, = module_nesting.first
338
- cvars |= m.class_variables.map(&:to_s) if m.is_a? Module
339
- cvars
340
- end
341
-
342
- def constants
343
- module_nesting.flat_map do |nest,|
344
- nest.constants
345
- end.map(&:to_s) | table_constants
346
- end
347
-
348
- def merge_jumps
349
- if terminated?
350
- @terminated = false
351
- @table = @mergeable_changes
352
- merge @jump_branches
353
- @terminated = true
354
- else
355
- merge [*@jump_branches, {}]
356
- end
357
- end
358
-
359
- def conditional(&block)
360
- run_branches(block, ->(_s) {}).first || Types::NIL
361
- end
362
-
363
- def never(&block)
364
- block.call Scope.new(self, { BREAK_RESULT => nil, NEXT_RESULT => nil, PATTERNMATCH_BREAK => nil, RETURN_RESULT => nil })
365
- end
366
-
367
- def run_branches(*blocks)
368
- results = []
369
- branches = []
370
- blocks.each do |block|
371
- scope = Scope.new self
372
- result = block.call scope
373
- next if scope.terminated?
374
- results << result
375
- branches << scope.mergeable_changes
376
- end
377
- terminate if branches.empty?
378
- merge branches
379
- results
380
- end
381
-
382
- def has_own?(name)
383
- @table.key? name
384
- end
385
-
386
- def update(child_scope)
387
- current_level = level
388
- child_scope.mergeable_changes.each do |name, (level, value)|
389
- self[name] = value if level <= current_level
390
- end
391
- end
392
-
393
- protected
394
-
395
- def merge(branches)
396
- current_level = level
397
- merge = {}
398
- branches.each do |changes|
399
- changes.each do |name, (level, value)|
400
- next if current_level < level
401
- (merge[name] ||= []) << value
402
- end
403
- end
404
- merge.each do |name, values|
405
- values << self[name] unless values.size == branches.size
406
- values.compact!
407
- self[name] = Types::UnionType[*values.compact] unless values.empty?
408
- end
409
- end
410
- end
411
- end
412
- end