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

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