steep 1.4.0.dev.3 → 1.4.0.dev.4

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.
@@ -26,43 +26,78 @@ module Steep
26
26
  def comments
27
27
  case entry = env.constant_entry(full_name)
28
28
  when RBS::Environment::ConstantEntry
29
- [entry.decl.comment].compact
29
+ [entry.decl.comment]
30
30
  when RBS::Environment::ClassEntry, RBS::Environment::ModuleEntry
31
- entry.decls.filter_map {|d| d.decl.comment }
31
+ entry.decls.map {|d| d.decl.comment }
32
32
  when RBS::Environment::ClassAliasEntry, RBS::Environment::ModuleAliasEntry
33
- [entry.decl.comment].compact
33
+ [entry.decl.comment]
34
+ else
35
+ raise
36
+ end
37
+ end
38
+
39
+ def decl
40
+ case entry = env.constant_entry(full_name)
41
+ when RBS::Environment::ConstantEntry
42
+ entry.decl
43
+ when RBS::Environment::ClassEntry, RBS::Environment::ModuleEntry
44
+ entry.primary.decl
45
+ when RBS::Environment::ClassAliasEntry, RBS::Environment::ModuleAliasEntry
46
+ entry.decl
34
47
  else
35
48
  raise
36
49
  end
37
50
  end
38
51
  end
39
- MethodNameItem = _ = Struct.new(:identifier, :range, :receiver_type, :method_type, :method_decls, keyword_init: true) do
40
- # @implements MethodNameItem
52
+
53
+ SimpleMethodNameItem = _ = Struct.new(:identifier, :range, :receiver_type, :method_types, :method_member, :method_name, keyword_init: true) do
54
+ # @implements SimpleMethodNameItem
41
55
 
42
56
  def comment
43
- case method_decls.size
44
- when 0
45
- nil
46
- when 1
47
- method = method_decls.to_a.first or raise
48
- method.method_def&.comment
49
- else
50
- nil
57
+ method_member.comment
58
+ end
59
+ end
60
+
61
+ ComplexMethodNameItem = _ = Struct.new(:identifier, :range, :receiver_type, :method_types, :method_decls, keyword_init: true) do
62
+ # @implements ComplexMethodNameItem
63
+
64
+ def method_names
65
+ method_definitions.keys
66
+ end
67
+
68
+ def method_definitions
69
+ method_decls.each.with_object({}) do |decl, hash| #$ Hash[method_name, RBS::Definition::Method::method_member]
70
+ method_name = defining_method_name(
71
+ decl.method_def.defined_in,
72
+ decl.method_name.method_name,
73
+ decl.method_def.member
74
+ )
75
+ hash[method_name] = decl.method_def.member
51
76
  end
52
77
  end
53
78
 
54
- def inherited?
55
- case receiver_type = receiver_type()
56
- when AST::Types::Name::Instance, AST::Types::Name::Singleton, AST::Types::Name::Interface
57
- method_decls.any? do |decl|
58
- decl.method_name.type_name != receiver_type.name
79
+ def defining_method_name(type_name, name, member)
80
+ case member
81
+ when RBS::AST::Members::MethodDefinition
82
+ if member.instance?
83
+ InstanceMethodName.new(type_name: type_name, method_name: name)
84
+ else
85
+ SingletonMethodName.new(type_name: type_name, method_name: name)
86
+ end
87
+ when RBS::AST::Members::Attribute
88
+ if member.kind == :instance
89
+ InstanceMethodName.new(type_name: type_name, method_name: name)
90
+ else
91
+ SingletonMethodName.new(type_name: type_name, method_name: name)
59
92
  end
60
- else
61
- false
62
93
  end
63
94
  end
64
95
  end
65
96
 
97
+ GeneratedMethodNameItem = _ = Struct.new(:identifier, :range, :receiver_type, :method_types, keyword_init: true) do
98
+ # @implements GeneratedMethodNameItem
99
+ end
100
+
66
101
  attr_reader :source_text
67
102
  attr_reader :path
68
103
  attr_reader :subtyping
@@ -168,51 +203,40 @@ module Steep
168
203
 
169
204
  return [] unless node
170
205
 
171
- items = []
206
+ items = [] #: Array[item]
172
207
 
173
208
  context = typing.context_at(line: position.line, column: position.column)
174
209
 
175
210
  case
176
- when node.type == :send && node.children[0] == nil && at_end?(position, of: node.loc.selector)
211
+ when node.type == :send && node.children[0] == nil && at_end?(position, of: (_ = node.loc).selector)
177
212
  # foo ←
178
213
  prefix = node.children[1].to_s
179
214
 
180
- method_items_for_receiver_type(context.self_type,
181
- include_private: true,
182
- prefix: prefix,
183
- position: position,
184
- items: items)
215
+ method_items_for_receiver_type(context.self_type, include_private: true, prefix: prefix, position: position, items: items)
185
216
  local_variable_items_for_context(context, position: position, prefix: prefix, items: items)
186
217
 
187
218
  when node.type == :lvar && at_end?(position, of: node.loc)
188
219
  # foo ← (lvar)
189
220
  local_variable_items_for_context(context, position: position, prefix: node.children[0].to_s, items: items)
190
221
 
191
- when node.type == :send && node.children[0] && at_end?(position, of: node.loc.selector)
222
+ when node.type == :send && node.children[0] && at_end?(position, of: (_ = node.loc).selector)
192
223
  # foo.ba ←
193
- receiver_type = case (type = typing.type_of(node: node.children[0]))
194
- when AST::Types::Self
195
- context.self_type
196
- else
197
- type
198
- end
224
+ receiver_type =
225
+ case (type = typing.type_of(node: node.children[0]))
226
+ when AST::Types::Self
227
+ context.self_type
228
+ else
229
+ type
230
+ end
199
231
  prefix = node.children[1].to_s
200
232
 
201
- method_items_for_receiver_type(receiver_type,
202
- include_private: false,
203
- prefix: prefix,
204
- position: position,
205
- items: items)
233
+ method_items_for_receiver_type(receiver_type, include_private: false, prefix: prefix, position: position, items: items)
206
234
 
207
235
  when node.type == :const && node.children[0] == nil && at_end?(position, of: node.loc)
208
236
  # Foo ← (const)
209
237
  prefix = node.children[1].to_s
210
238
 
211
- method_items_for_receiver_type(context.self_type,
212
- include_private: false,
213
- prefix: prefix,
214
- position: position,
215
- items: items)
239
+ method_items_for_receiver_type(context.self_type, include_private: false, prefix: prefix, position: position, items: items)
216
240
  constant_items_for_context(context, prefix: prefix, position: position, items: items)
217
241
 
218
242
  when node.type == :const && node.children[0] && at_end?(position, of: node.loc)
@@ -223,30 +247,23 @@ module Steep
223
247
  if parent_type
224
248
  prefix = node.children[1].to_s
225
249
 
226
- method_items_for_receiver_type(parent_type,
227
- include_private: false,
228
- prefix: prefix,
229
- position: position,
230
- items: items)
250
+ method_items_for_receiver_type(parent_type, include_private: false, prefix: prefix, position: position, items: items)
231
251
  constant_items_for_context(context, parent: parent_node, prefix: prefix, position: position, items: items)
232
252
  end
233
253
 
234
- when node.type == :send && at_end?(position, of: node.loc.dot) && node.loc.dot.source == "."
254
+ when node.type == :send && at_end?(position, of: (_ = node.loc).dot) && (_ = node.loc).dot.source == "."
235
255
  # foo.← ba
236
- receiver_type = case (type = typing.type_of(node: node.children[0]))
237
- when AST::Types::Self
238
- context.self_type
239
- else
240
- type
241
- end
242
-
243
- method_items_for_receiver_type(receiver_type,
244
- include_private: false,
245
- prefix: "",
246
- position: position,
247
- items: items)
248
-
249
- when node.type == :send && at_end?(position, of: node.loc.dot) && node.loc.dot.source == "::"
256
+ receiver_type =
257
+ case (type = typing.type_of(node: node.children[0]))
258
+ when AST::Types::Self
259
+ context.self_type
260
+ else
261
+ type
262
+ end
263
+
264
+ method_items_for_receiver_type(receiver_type, include_private: false, prefix: "", position: position, items: items)
265
+
266
+ when node.type == :send && at_end?(position, of: (_ = node.loc).dot) && (_ = node.loc).dot.source == "::"
250
267
  # foo::← ba
251
268
  items.push(*items_for_colon2(position: position))
252
269
 
@@ -255,11 +272,7 @@ module Steep
255
272
  instance_variable_items_for_context(context, position: position, prefix: node.children[0].to_s, items: items)
256
273
 
257
274
  else
258
- method_items_for_receiver_type(context.self_type,
259
- include_private: true,
260
- prefix: "",
261
- position: position,
262
- items: items)
275
+ method_items_for_receiver_type(context.self_type, include_private: true, prefix: "", position: position, items: items)
263
276
  local_variable_items_for_context(context, position: position, prefix: "", items: items)
264
277
  instance_variable_items_for_context(context, position: position, prefix: "", items: items)
265
278
  constant_items_for_context(context, position: position, prefix: "", items: items)
@@ -279,19 +292,16 @@ module Steep
279
292
  if at_end?(shift_pos, of: node.loc)
280
293
  begin
281
294
  context = typing.context_at(line: position.line, column: position.column)
282
- receiver_type = case (type = typing.type_of(node: node))
283
- when AST::Types::Self
284
- context.self_type
285
- else
286
- type
287
- end
288
-
289
- items = []
290
- method_items_for_receiver_type(receiver_type,
291
- include_private: false,
292
- prefix: "",
293
- position: position,
294
- items: items)
295
+ receiver_type =
296
+ case (type = typing.type_of(node: node))
297
+ when AST::Types::Self
298
+ context.self_type
299
+ else
300
+ type
301
+ end
302
+
303
+ items = [] #: Array[item]
304
+ method_items_for_receiver_type(receiver_type, include_private: false, prefix: "", position: position, items: items)
295
305
  items
296
306
  rescue Typing::UnknownNodeError
297
307
  []
@@ -307,7 +317,7 @@ module Steep
307
317
  node, *_ = source.find_nodes(line: shift_pos.line, column: shift_pos.column)
308
318
  node ||= source.node
309
319
 
310
- items = []
320
+ items = [] #: Array[item]
311
321
  case node&.type
312
322
  when :const
313
323
  # Constant:: ←
@@ -335,7 +345,7 @@ module Steep
335
345
  return [] unless node
336
346
 
337
347
  context = typing.context_at(line: position.line, column: position.column)
338
- items = []
348
+ items = [] #: Array[item]
339
349
  instance_variable_items_for_context(context, prefix: "@", position: position, items: items)
340
350
  items
341
351
  end
@@ -354,31 +364,60 @@ module Steep
354
364
  variable_bounds: context.variable_context.upper_bounds
355
365
  )
356
366
  )
357
- # factory.shape(type, self_type: type, private: include_private)
358
367
 
359
- shape.methods.each do |name, method_entry|
360
- next if disallowed_method?(name)
368
+ if shape
369
+ shape.methods.each do |name, method_entry|
370
+ next if disallowed_method?(name)
361
371
 
362
- if name.to_s.start_with?(prefix)
363
- if word_name?(name.to_s)
364
- method_entry.method_types.each do |method_type|
365
- items << MethodNameItem.new(
366
- identifier: name,
367
- range: range,
368
- receiver_type: type,
369
- method_type: subtyping.factory.method_type_1(method_type),
370
- method_decls: method_type.method_decls
371
- )
372
+ if name.to_s.start_with?(prefix)
373
+ if word_name?(name.to_s)
374
+ case type
375
+ when AST::Types::Name::Instance, AST::Types::Name::Interface, AST::Types::Name::Singleton
376
+ # Simple method type
377
+ all_decls = Set.new(method_entry.method_types.flat_map {|method_type| method_type.method_decls.to_a }).sort_by {|decl| decl.method_name.to_s }
378
+ all_members = Set.new(all_decls.flat_map {|decl| decl.method_def.member })
379
+ all_members.each do |member|
380
+ associated_decl = all_decls.find {|decl| decl.method_def.member == member } or next
381
+ method_types = method_entry.method_types.select {|method_type| method_type.method_decls.any? {|decl| decl.method_def.member == member }}
382
+ items << SimpleMethodNameItem.new(
383
+ identifier: name,
384
+ range: range,
385
+ receiver_type: type,
386
+ method_name: associated_decl.method_name,
387
+ method_types: method_types.map {|type| subtyping.factory.method_type_1(type) },
388
+ method_member: member
389
+ )
390
+ end
391
+ else
392
+ generated_method_types, defined_method_types = method_entry.method_types.partition {|method_type| method_type.method_decls.empty? }
393
+
394
+ unless defined_method_types.empty?
395
+ items << ComplexMethodNameItem.new(
396
+ identifier: name,
397
+ range: range,
398
+ receiver_type: type,
399
+ method_types: defined_method_types.map {|type| subtyping.factory.method_type_1(type) },
400
+ method_decls: defined_method_types.flat_map {|type| type.method_decls.to_a }.sort_by {|decl| decl.method_name.to_s }
401
+ )
402
+ end
403
+
404
+ unless generated_method_types.empty?
405
+ items << GeneratedMethodNameItem.new(
406
+ identifier: name,
407
+ range: range,
408
+ receiver_type: type,
409
+ method_types: generated_method_types.map {|type| subtyping.factory.method_type_1(type) }
410
+ )
411
+ end
412
+ end
372
413
  end
373
414
  end
374
415
  end
375
416
  end
376
- rescue RuntimeError => _exn
377
- # nop
378
417
  end
379
418
 
380
419
  def word_name?(name)
381
- name =~ /\w/
420
+ name =~ /\w/ ? true : false
382
421
  end
383
422
 
384
423
  def local_variable_items_for_context(context, position:, prefix:, items:)
@@ -420,9 +459,7 @@ module Steep
420
459
  range = range_for(position, prefix: prefix)
421
460
  context.type_env.instance_variable_types.each do |name, type|
422
461
  if name.to_s.start_with?(prefix)
423
- items << InstanceVariableItem.new(identifier: name,
424
- range: range,
425
- type: type)
462
+ items << InstanceVariableItem.new(identifier: name, range: range, type: type)
426
463
  end
427
464
  end
428
465
  end
@@ -29,54 +29,59 @@ module Steep
29
29
 
30
30
  case head
31
31
  when ::RBS::Types::Alias
32
- alias_decl = service.latest_env.type_alias_decls[head.name]&.decl or raise
32
+ content_for_type_name(head.name, env: env, location: head.location || raise)
33
33
 
34
- TypeAliasContent.new(
35
- location: head.location || raise,
36
- decl: alias_decl
37
- )
38
34
  when ::RBS::Types::ClassInstance, ::RBS::Types::ClassSingleton
39
35
  if loc_key == :name
40
36
  location = head.location&.[](:name) or raise
41
-
42
- class_entry = service.latest_env.module_class_entry(head.name) or raise
43
- case class_entry
44
- when ::RBS::Environment::ClassEntry, ::RBS::Environment::ModuleEntry
45
- class_decl = class_entry.primary.decl
46
- when ::RBS::Environment::ClassAliasEntry, ::RBS::Environment::ModuleAliasEntry
47
- class_decl = class_entry.decl
48
- end
49
-
50
- ClassContent.new(
51
- location: location,
52
- decl: class_decl
53
- )
37
+ content_for_type_name(head.name, env: env, location: location)
54
38
  end
39
+
55
40
  when ::RBS::Types::Interface
56
- env = service.latest_env
57
- interface_decl = env.interface_decls[head.name]&.decl or raise
58
41
  location = head.location&.[](:name) or raise
42
+ content_for_type_name(head.name, env: env, location: location)
59
43
 
60
- InterfaceContent.new(
61
- location: location,
62
- decl: interface_decl
63
- )
64
44
  when ::RBS::AST::Declarations::ClassAlias, ::RBS::AST::Declarations::ModuleAlias
65
45
  if loc_key == :old_name
66
46
  location = head.location&.[](:old_name) or raise
47
+ content_for_type_name(head.old_name, env: env, location: location)
48
+ end
67
49
 
68
- class_entry = service.latest_env.module_class_entry(head.old_name) or raise
69
- case class_entry
70
- when ::RBS::Environment::ClassEntry, ::RBS::Environment::ModuleEntry
71
- class_decl = class_entry.primary.decl
72
- when ::RBS::Environment::ClassAliasEntry, ::RBS::Environment::ModuleAliasEntry
73
- class_decl = class_entry.decl
74
- end
50
+ when ::RBS::AST::Directives::Use::SingleClause
51
+ if loc_key == :type_name
52
+ location = head.location&.[](:type_name) or raise
53
+ content_for_type_name(head.type_name.absolute!, env: env, location: location)
54
+ end
75
55
 
76
- ClassContent.new(location: location, decl: class_decl)
56
+ when ::RBS::AST::Directives::Use::WildcardClause
57
+ if loc_key == :namespace
58
+ location = head.location&.[](:namespace) or raise
59
+ content_for_type_name(head.namespace.to_type_name.absolute!, env: env, location: location)
77
60
  end
78
61
  end
79
62
  end
63
+
64
+ def content_for_type_name(type_name, env:, location:)
65
+ case
66
+ when type_name.alias?
67
+ alias_decl = env.type_alias_decls[type_name]&.decl or return
68
+ TypeAliasContent.new(location: location, decl: alias_decl)
69
+ when type_name.interface?
70
+ interface_decl = env.interface_decls[type_name]&.decl or return
71
+ InterfaceContent.new(location: location, decl: interface_decl)
72
+ when type_name.class?
73
+ class_entry = env.module_class_entry(type_name) or return
74
+
75
+ case class_entry
76
+ when ::RBS::Environment::ClassEntry, ::RBS::Environment::ModuleEntry
77
+ class_decl = class_entry.primary.decl
78
+ when ::RBS::Environment::ClassAliasEntry, ::RBS::Environment::ModuleAliasEntry
79
+ class_decl = class_entry.decl
80
+ end
81
+
82
+ ClassContent.new(location: location, decl: class_decl)
83
+ end
84
+ end
80
85
  end
81
86
  end
82
87
  end
@@ -0,0 +1,108 @@
1
+ module Steep
2
+ module Services
3
+ class SignatureHelpProvider
4
+ MethodCall = TypeInference::MethodCall
5
+
6
+ Item = _ = Struct.new(:method_type, :comment)
7
+
8
+ attr_reader :source, :path, :subtyping, :typing, :buffer
9
+
10
+ def env
11
+ subtyping.factory.env
12
+ end
13
+
14
+ def initialize(source:, subtyping:)
15
+ @source = source
16
+ @subtyping = subtyping
17
+
18
+ text =
19
+ if source.node
20
+ source.node.loc.expression.source
21
+ end
22
+ @buffer = RBS::Buffer.new(name: source.path, content: text || "")
23
+ end
24
+
25
+ def run(line:, column:)
26
+ nodes = source.find_nodes(line: line, column: column)
27
+
28
+ return unless nodes
29
+
30
+ typing = type_check!(line: line, column: column)
31
+
32
+ while true
33
+ node = nodes.shift()
34
+ parent = nodes.first
35
+
36
+ node or return
37
+
38
+ if node.type == :send
39
+ pos = buffer.loc_to_pos([line, column])
40
+ begin_loc = (_ = node.loc).begin #: Parser::Source::Range?
41
+ end_loc = (_ = node.loc).end #: Parser::Source::Range?
42
+
43
+ if begin_loc && end_loc
44
+ if begin_loc.end_pos <= pos && pos <= end_loc.begin_pos
45
+ # Given position is between open/close parens of args of send node
46
+
47
+ if parent && (parent.type == :block || parent.type == :numblock)
48
+ send_node = parent.children[0]
49
+ else
50
+ send_node = node
51
+ end
52
+
53
+ return signature_help_for(send_node, typing)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ def type_check!(line:, column:)
61
+ source = self.source.without_unrelated_defs(line: line, column: column)
62
+ resolver = RBS::Resolver::ConstantResolver.new(builder: subtyping.factory.definition_builder)
63
+ TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: resolver)
64
+ end
65
+
66
+ def signature_help_for(node, typing)
67
+ call = typing.call_of(node: node)
68
+ context = typing.context_at(line: node.loc.expression.line, column: node.loc.expression.column)
69
+
70
+ items = [] #: Array[Item]
71
+ index = nil #: Integer?
72
+
73
+ case call
74
+ when MethodCall::Typed, MethodCall::Error
75
+ type = call.receiver_type
76
+ if type.is_a?(AST::Types::Self)
77
+ type = context.self_type
78
+ end
79
+
80
+ shape = subtyping.builder.shape(
81
+ type,
82
+ public_only: !node.children[0].nil?,
83
+ config: Interface::Builder::Config.new(self_type: type, class_type: nil, instance_type: nil, variable_bounds: {})
84
+ )
85
+ if shape
86
+ if method = shape.methods[call.method_name]
87
+ method.method_types.each.with_index do |method_type, i|
88
+ defn = method_type.method_decls.to_a[0]&.method_def
89
+
90
+ items << Item.new(subtyping.factory.method_type_1(method_type), defn&.comment)
91
+
92
+ if call.is_a?(MethodCall::Typed)
93
+ if method_type.method_decls.intersect?(call.method_decls)
94
+ index = i
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+ when MethodCall::Untyped, MethodCall::NoMethodError
101
+ return
102
+ end
103
+
104
+ [items, index]
105
+ end
106
+ end
107
+ end
108
+ end
@@ -90,9 +90,17 @@ module Steep
90
90
 
91
91
  def each_type_name(&block)
92
92
  if block
93
+ env = self.env
94
+
93
95
  map.instance_eval do
94
96
  @map.each_key do |name|
95
- yield RBS::TypeName.new(name: name, namespace: RBS::Namespace.empty)
97
+ relative_name = RBS::TypeName.new(name: name, namespace: RBS::Namespace.empty)
98
+ if absolute_name = resolve?(relative_name)
99
+ if env.type_name?(absolute_name)
100
+ # Yields only if the relative type name resolves to existing absolute type name
101
+ yield relative_name
102
+ end
103
+ end
96
104
  end
97
105
  end
98
106
  env.class_decls.each_key(&block)