irb 1.9.1 → 1.10.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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