steep 1.5.0.pre.5 → 1.5.0.pre.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ed79428764aa83fbd2e7f3c5a8e52ff863b4e65bef05aae43ba9ca4b7c9d2f4e
4
- data.tar.gz: be79772ce19f152e3048ae565802640cae96f1bfca98adf60eab47a28ab3ccad
3
+ metadata.gz: d00242c259b7c8d2a4a0f7022874ac5bb5f08491ab3edade6165ff1a9fbe89a7
4
+ data.tar.gz: e02d896359c4eb88c730601320bb9137342c19b9ad1956d4ac417ffa5926d74a
5
5
  SHA512:
6
- metadata.gz: aa071be8eaf425a2a36ffed4c8d0a97446997f9cbf85c9dc4190b5bf26c9bf5f66c7106ab27b96378d05e246a6327689ef491dedbd16ad7cb9eb8d8079b3818d
7
- data.tar.gz: d7f842d51c84a2f48bdfd79a07de3e6265dd746497aa9661871f12b062832c2a24f46b37ce1ddb614ac5ba1c65f4c408e9e1eafec27fd69d7158514fe77e0fec
6
+ metadata.gz: 5be83d84d984d215342c030e9ea590c419a1e12963361266f4bc57e2b2ceec110a3f08313754b2f46a274fc8b0d2acca497c71f2eff24c3fd4505cb1ff2ac5a7
7
+ data.tar.gz: 7a30b064aa7ec6e27e3811e93b1ddf7ff4824cdeb5dfe70075f34311f7e22016bf4f3a2b107307a5247c54532451a25155fc2ba277842fec85f71aa23fdaced1
data/CHANGELOG.md CHANGED
@@ -2,6 +2,24 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 1.5.0.pre.6 (2023-07-11)
6
+
7
+ ### Type checker core
8
+
9
+ * Report RBS validation errors in Ruby code ([#859](https://github.com/soutaro/steep/pull/859))
10
+ * Fix proc type assignment ([#858](https://github.com/soutaro/steep/pull/858))
11
+ * Report `UnexpectedKeywordArgument` even if no keyword param is accepted ([#856](https://github.com/soutaro/steep/pull/856))
12
+ * Unfold type alias on unwrap optional ([#855](https://github.com/soutaro/steep/pull/855))
13
+
14
+ ### Language server
15
+
16
+ * Keyword completion in block call ([#865](https://github.com/soutaro/steep/pull/865))
17
+ * Indicate the current or next argument on signature help ([#850](https://github.com/soutaro/steep/pull/850))
18
+ * Support completion for keyword arguments ([#851](https://github.com/soutaro/steep/pull/851))
19
+ * Let hover show the type of method call node ([#864](https://github.com/soutaro/steep/pull/864))
20
+ * Fix UnknownNodeError in SignatureHelp ([#863](https://github.com/soutaro/steep/pull/863))
21
+ * hover: Fix NoMethodError on generating hover for not supported files ([#853](https://github.com/soutaro/steep/pull/853))
22
+
5
23
  ## 1.5.0.pre.5 (2023-07-07)
6
24
 
7
25
  ### Type checker core
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- steep (1.5.0.pre.5)
4
+ steep (1.5.0.pre.6)
5
5
  activesupport (>= 5.1)
6
6
  concurrent-ruby (>= 1.1.10)
7
7
  csv (>= 3.0.9)
@@ -37,10 +37,12 @@ module Steep
37
37
  ty = ty.map_type_name {|name| resolver.resolve(name, context: context) || name.absolute! }
38
38
 
39
39
  validator = Signature::Validator.new(checker: subtyping)
40
- validator.validate_type(ty)
40
+ validator.rescue_validation_errors do
41
+ validator.validate_type(ty)
42
+ end
41
43
 
42
44
  if validator.has_error?
43
- return
45
+ return validator.each_error
44
46
  end
45
47
 
46
48
  ty = subtyping.factory.type(ty)
@@ -58,7 +60,7 @@ module Steep
58
60
 
59
61
  def types?(context, subtyping, type_vars)
60
62
  case types = types(context, subtyping, type_vars)
61
- when RBS::ParsingError
63
+ when RBS::ParsingError, Enumerator
62
64
  nil
63
65
  else
64
66
  types
@@ -22,10 +22,14 @@ module Steep
22
22
  ty = ty.map_type_name {|name| resolver.resolve(name, context: context) || name.absolute! }
23
23
 
24
24
  validator = Signature::Validator.new(checker: subtyping)
25
- validator.validate_type(ty)
25
+ validator.rescue_validation_errors do
26
+ validator.validate_type(ty)
27
+ end
26
28
 
27
29
  unless validator.has_error?
28
30
  subtyping.factory.type(ty)
31
+ else
32
+ validator.each_error.to_a
29
33
  end
30
34
  else
31
35
  nil
@@ -37,7 +41,7 @@ module Steep
37
41
  def type_syntax?
38
42
  RBS::Parser.parse_type(type_location.buffer, range: type_location.range, variables: [], require_eof: true)
39
43
  true
40
- rescue::RBS::ParsingError
44
+ rescue ::RBS::ParsingError
41
45
  false
42
46
  end
43
47
 
@@ -45,7 +49,7 @@ module Steep
45
49
  type = type(context, subtyping, type_vars)
46
50
 
47
51
  case type
48
- when RBS::ParsingError, nil
52
+ when RBS::ParsingError, nil, Array
49
53
  nil
50
54
  else
51
55
  type
@@ -401,6 +401,13 @@ module Steep
401
401
  end
402
402
  when AST::Types::Nil
403
403
  nil
404
+ when AST::Types::Name::Alias
405
+ type_ = expand_alias(type)
406
+ if type_ == type
407
+ type_
408
+ else
409
+ unwrap_optional(type_)
410
+ end
404
411
  else
405
412
  type
406
413
  end
@@ -964,6 +964,19 @@ module Steep
964
964
  end
965
965
  end
966
966
 
967
+ class RBSError < Base
968
+ attr_reader :error
969
+
970
+ def initialize(error:, node:, location:)
971
+ @error = error
972
+ super(node: node, location: location)
973
+ end
974
+
975
+ def header_line
976
+ error.header_line
977
+ end
978
+ end
979
+
967
980
  ALL = ObjectSpace.each_object(Class).with_object([]) do |klass, array|
968
981
  if klass < Base
969
982
  array << klass
@@ -217,5 +217,28 @@ module Steep
217
217
  false
218
218
  end
219
219
  end
220
+
221
+ def deconstruct_sendish_and_block_nodes(*nodes)
222
+ send_node, block_node = nodes.take(2)
223
+
224
+ if send_node
225
+ case send_node.type
226
+ when :send, :csend, :super
227
+ if block_node
228
+ case block_node.type
229
+ when :block, :numblock
230
+ if send_node.equal?(block_node.children[0])
231
+ return [send_node, block_node]
232
+ end
233
+ end
234
+ end
235
+
236
+ [send_node, nil]
237
+ when :zsuper
238
+ # zsuper doesn't receive block
239
+ [send_node, nil]
240
+ end
241
+ end
242
+ end
220
243
  end
221
244
  end
@@ -361,6 +361,17 @@ module Steep
361
361
  new_text: item.identifier.to_s
362
362
  )
363
363
  )
364
+ when Services::CompletionProvider::KeywordArgumentItem
365
+ LSP::Interface::CompletionItem.new(
366
+ label: item.identifier.to_s,
367
+ kind: LSP::Constant::CompletionItemKind::FIELD,
368
+ label_details: LSP::Interface::CompletionItemLabelDetails.new(description: 'Keyword argument'),
369
+ documentation: LSPFormatter.markup_content { LSPFormatter.format_completion_docs(item) },
370
+ text_edit: LSP::Interface::TextEdit.new(
371
+ range: range,
372
+ new_text: item.identifier.to_s
373
+ )
374
+ )
364
375
  when Services::CompletionProvider::TypeNameItem
365
376
  kind =
366
377
  case
@@ -397,6 +408,8 @@ module Steep
397
408
  signatures = items.map do |item|
398
409
  LSP::Interface::SignatureInformation.new(
399
410
  label: "(#{item.method_type.type.param_to_s})",
411
+ parameters: item.parameters.map { |param| LSP::Interface::ParameterInformation.new(label: param)},
412
+ active_parameter: item.active_parameter,
400
413
  documentation: item.comment&.yield_self do |comment|
401
414
  LSP::Interface::MarkupContent.new(
402
415
  kind: LSP::Constant::MarkupKind::MARKDOWN,
@@ -28,7 +28,16 @@ module Steep
28
28
 
29
29
  case call
30
30
  when TypeInference::MethodCall::Typed
31
+ io.puts <<~MD
32
+ ```rbs
33
+ #{call.actual_method_type.type.return_type}
34
+ ```
35
+
36
+ ----
37
+ MD
38
+
31
39
  method_types = call.method_decls.map(&:method_type)
40
+
32
41
  if call.is_a?(TypeInference::MethodCall::Special)
33
42
  method_types = [
34
43
  call.actual_method_type.with(
@@ -250,6 +259,10 @@ module Steep
250
259
  end
251
260
 
252
261
  io.string
262
+ when Services::CompletionProvider::KeywordArgumentItem
263
+ <<~MD
264
+ **Keyword argument**: `#{item.identifier}`
265
+ MD
253
266
  end
254
267
  end
255
268
 
@@ -1,6 +1,8 @@
1
1
  module Steep
2
2
  module Services
3
3
  class CompletionProvider
4
+ include NodeHelper
5
+
4
6
  Position = _ = Struct.new(:line, :column, keyword_init: true) do
5
7
  # @implements Position
6
8
  def -(size)
@@ -11,6 +13,7 @@ module Steep
11
13
  Range = _ = Struct.new(:start, :end, keyword_init: true)
12
14
 
13
15
  InstanceVariableItem = _ = Struct.new(:identifier, :range, :type, keyword_init: true)
16
+ KeywordArgumentItem = _ = Struct.new(:identifier, :range, keyword_init: true)
14
17
  LocalVariableItem = _ = Struct.new(:identifier, :range, :type, keyword_init: true)
15
18
  ConstantItem = _ = Struct.new(:env, :identifier, :range, :type, :full_name, keyword_init: true) do
16
19
  # @implements ConstantItem
@@ -267,7 +270,9 @@ module Steep
267
270
  []
268
271
  end
269
272
  else
270
- []
273
+ items = [] #: Array[item]
274
+ items_for_following_keyword_arguments(source_text, index: index, line: line, column: column, items: items)
275
+ items
271
276
  end
272
277
  end
273
278
  end
@@ -302,10 +307,10 @@ module Steep
302
307
  end
303
308
 
304
309
  def items_for_trigger(position:)
305
- node, *_parents = source.find_nodes(line: position.line, column: position.column)
310
+ node, *parents = source.find_nodes(line: position.line, column: position.column)
306
311
  node ||= source.node
307
312
 
308
- return [] unless node
313
+ return [] unless node && parents
309
314
 
310
315
  items = [] #: Array[item]
311
316
 
@@ -319,6 +324,16 @@ module Steep
319
324
  method_items_for_receiver_type(context.self_type, include_private: true, prefix: prefix, position: position, items: items)
320
325
  local_variable_items_for_context(context, position: position, prefix: prefix, items: items)
321
326
 
327
+ if (send_node, block_node = deconstruct_sendish_and_block_nodes(*parents))
328
+ keyword_argument_items_for_method(
329
+ call_node: block_node || send_node,
330
+ send_node: send_node,
331
+ position: position,
332
+ prefix: prefix,
333
+ items: items
334
+ )
335
+ end
336
+
322
337
  when node.type == :lvar && at_end?(position, of: node.loc)
323
338
  # foo ← (lvar)
324
339
  local_variable_items_for_context(context, position: position, prefix: node.children[0].to_s, items: items)
@@ -527,6 +542,37 @@ module Steep
527
542
  items
528
543
  end
529
544
 
545
+ def items_for_following_keyword_arguments(text, index:, line:, column:, items:)
546
+ return if text[index - 1] !~ /[a-zA-Z0-9]/
547
+
548
+ text = text.dup
549
+ argname = [] #: Array[String]
550
+ while text[index - 1] =~ /[a-zA-Z0-9]/
551
+ argname.unshift(text[index - 1] || '')
552
+ source_text[index - 1] = " "
553
+ index -= 1
554
+ end
555
+
556
+ begin
557
+ type_check!(source_text, line: line, column: column)
558
+ rescue Parser::SyntaxError
559
+ return
560
+ end
561
+
562
+ if nodes = source.find_nodes(line: line, column: column)
563
+ if (send_node, block_node = deconstruct_sendish_and_block_nodes(*nodes))
564
+ position = Position.new(line: line, column: column)
565
+ keyword_argument_items_for_method(
566
+ call_node: block_node || send_node,
567
+ send_node: send_node,
568
+ position: position,
569
+ prefix: argname.join,
570
+ items: items
571
+ )
572
+ end
573
+ end
574
+ end
575
+
530
576
  def method_items_for_receiver_type(type, include_private:, prefix:, position:, items:)
531
577
  range = range_for(position, prefix: prefix)
532
578
  context = typing.context_at(line: position.line, column: position.column)
@@ -641,6 +687,42 @@ module Steep
641
687
  end
642
688
  end
643
689
 
690
+ def keyword_argument_items_for_method(call_node:, send_node:, position:, prefix:, items:)
691
+ receiver_node, method_name, argument_nodes = deconstruct_send_node!(send_node)
692
+
693
+ call = typing.call_of(node: call_node)
694
+
695
+ case call
696
+ when TypeInference::MethodCall::Typed, TypeInference::MethodCall::Error
697
+ type = call.receiver_type
698
+ shape = subtyping.builder.shape(
699
+ type,
700
+ public_only: !!receiver_node,
701
+ config: Interface::Builder::Config.new(self_type: type, class_type: nil, instance_type: nil, variable_bounds: {})
702
+ )
703
+ if shape
704
+ if method = shape.methods[call.method_name]
705
+ method.method_types.each.with_index do |method_type, i|
706
+ defn = method_type.method_decls.to_a[0]&.method_def
707
+ if defn
708
+ range = range_for(position, prefix: prefix)
709
+ kwargs = argument_nodes.find { |arg| arg.type == :kwargs }&.children || []
710
+ used_kwargs = kwargs.filter_map { |arg| arg.type == :pair && arg.children.first.children.first }
711
+
712
+ kwargs = defn.type.type.required_keywords.keys + defn.type.type.optional_keywords.keys
713
+ kwargs.each do |name|
714
+ if name.to_s.start_with?(prefix) && !used_kwargs.include?(name)
715
+ items << KeywordArgumentItem.new(identifier: "#{name}:", range: range)
716
+ end
717
+ end
718
+ end
719
+ end
720
+ end
721
+ end
722
+ end
723
+ end
724
+
725
+
644
726
  def index_for(string, line:, column:)
645
727
  index = 0
646
728
 
@@ -110,7 +110,7 @@ module Steep
110
110
  end
111
111
 
112
112
  def content_for(target:, path:, line:, column:)
113
- file = service.source_files[path]
113
+ file = service.source_files[path] or return
114
114
  typing = typecheck(target, path: path, content: file.content, line: line, column: column) or return
115
115
  node, *parents = typing.source.find_nodes(line: line, column: column)
116
116
 
@@ -3,7 +3,21 @@ module Steep
3
3
  class SignatureHelpProvider
4
4
  MethodCall = TypeInference::MethodCall
5
5
 
6
- Item = _ = Struct.new(:method_type, :comment)
6
+ Item = _ = Struct.new(:method_type, :comment, :active_parameter) do
7
+ # @implements Item
8
+
9
+ def parameters
10
+ arguments = [] #: Array[String]
11
+ arguments.push(*method_type.type.required_positionals.map(&:to_s))
12
+ arguments.push(*method_type.type.optional_positionals.map {|p| "?#{p}"})
13
+ arguments.push("*#{self.method_type.type.rest_positionals}") if method_type.type.rest_positionals
14
+ arguments.push(*method_type.type.trailing_positionals.map(&:to_s))
15
+ arguments.push(*method_type.type.required_keywords.map {|name, param| "#{name}: #{param}" })
16
+ arguments.push(*method_type.type.optional_keywords.map {|name, param| "?#{name}: #{param}" })
17
+ arguments.push("**#{method_type.type.rest_keywords}") if method_type.type.rest_keywords
18
+ arguments
19
+ end
20
+ end
7
21
 
8
22
  attr_reader :source, :path, :subtyping, :typing, :buffer
9
23
 
@@ -23,12 +37,14 @@ module Steep
23
37
  return unless nodes
24
38
 
25
39
  typing = type_check!(line: line, column: column)
40
+ argument_nodes = [] #: Array[Parser::AST::Node]
26
41
 
27
42
  while true
28
43
  node = nodes.shift()
29
44
  parent = nodes.first
30
45
 
31
46
  node or return
47
+ argument_nodes << node
32
48
 
33
49
  if node.type == :send || node.type == :csend
34
50
  pos = buffer.loc_to_pos([line, column])
@@ -40,12 +56,13 @@ module Steep
40
56
  # Given position is between open/close parens of args of send node
41
57
 
42
58
  if parent && (parent.type == :block || parent.type == :numblock)
43
- send_node = parent.children[0]
59
+ send_node = parent
44
60
  else
45
61
  send_node = node
46
62
  end
47
63
 
48
- return signature_help_for(send_node, typing)
64
+ last_argument_nodes = last_argument_nodes_for(argument_nodes: argument_nodes, line: line, column: column)
65
+ return signature_help_for(send_node, argument_nodes, last_argument_nodes, typing)
49
66
  end
50
67
  end
51
68
  end
@@ -58,7 +75,24 @@ module Steep
58
75
  TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: resolver)
59
76
  end
60
77
 
61
- def signature_help_for(node, typing)
78
+ def last_argument_nodes_for(argument_nodes:, line:, column:)
79
+ return unless argument_nodes.last.children[2] # No arguments
80
+ return argument_nodes if argument_nodes.size > 1 # Cursor is on the last argument
81
+
82
+ pos = buffer.loc_to_pos([line, column])
83
+
84
+ while true
85
+ pos -= 1
86
+ line, column = buffer.pos_to_loc(pos)
87
+ nodes = source.find_nodes(line: line, column: column)
88
+ return unless nodes
89
+
90
+ index = nodes.index { |n| n.type == :send || n.type == :csend }
91
+ return nodes[..index] if index.to_i > 0
92
+ end
93
+ end
94
+
95
+ def signature_help_for(node, argument, last_argument, typing)
62
96
  call = typing.call_of(node: node)
63
97
  context = typing.context_at(line: node.loc.expression.line, column: node.loc.expression.column)
64
98
 
@@ -82,7 +116,8 @@ module Steep
82
116
  method.method_types.each.with_index do |method_type, i|
83
117
  defn = method_type.method_decls.to_a[0]&.method_def
84
118
 
85
- items << Item.new(subtyping.factory.method_type_1(method_type), defn&.comment)
119
+ active_parameter = active_parameter_for(defn&.type, argument, last_argument, node)
120
+ items << Item.new(subtyping.factory.method_type_1(method_type), defn&.comment, active_parameter)
86
121
 
87
122
  if call.is_a?(MethodCall::Typed)
88
123
  if method_type.method_decls.intersect?(call.method_decls)
@@ -98,6 +133,66 @@ module Steep
98
133
 
99
134
  [items, index]
100
135
  end
136
+
137
+ def active_parameter_for(method_type, argument_nodes, last_argument_nodes, node)
138
+ return unless method_type
139
+
140
+ positionals = method_type.type.required_positionals.size + method_type.type.optional_positionals.size + (method_type.type.rest_positionals ? 1 : 0) + method_type.type.trailing_positionals.size
141
+
142
+ if argument_nodes.size == 1
143
+ # Cursor is not on the argument (maybe on comma after argument)
144
+ return 0 if last_argument_nodes.nil? # No arguments
145
+
146
+ case last_argument_nodes[-2].type
147
+ when :splat
148
+ method_type.type.required_positionals.size + method_type.type.optional_positionals.size + 1 if method_type.type.rest_positionals
149
+ when :kwargs
150
+ case last_argument_nodes[-3].type
151
+ when :pair
152
+ argname = last_argument_nodes[-3].children.first.children.first
153
+ if method_type.type.required_keywords[argname]
154
+ positionals + method_type.type.required_keywords.keys.index(argname).to_i + 1
155
+ elsif method_type.type.optional_keywords[argname]
156
+ positionals + method_type.type.required_keywords.size + method_type.type.optional_keywords.keys.index(argname).to_i + 1
157
+ elsif method_type.type.rest_keywords
158
+ positionals + method_type.type.required_keywords.size + method_type.type.optional_keywords.size
159
+ end
160
+ when :kwsplat
161
+ positionals + method_type.type.required_keywords.size + method_type.type.optional_keywords.size if method_type.type.rest_keywords
162
+ end
163
+ else
164
+ pos = node.children[2...].index { |c| c.location == last_argument_nodes[-2].location }.to_i
165
+ if method_type.type.rest_positionals
166
+ [pos + 1, positionals - 1].min
167
+ else
168
+ [pos + 1, positionals].min
169
+ end
170
+ end
171
+ else
172
+ # Cursor is on the argument
173
+ case argument_nodes[-2].type
174
+ when :splat
175
+ method_type.type.required_positionals.size + method_type.type.optional_positionals.size if method_type.type.rest_positionals
176
+ when :kwargs
177
+ case argument_nodes[-3].type
178
+ when :pair
179
+ argname = argument_nodes[-3].children.first.children.first
180
+ if method_type.type.required_keywords[argname]
181
+ positionals + method_type.type.required_keywords.keys.index(argname).to_i
182
+ elsif method_type.type.optional_keywords[argname]
183
+ positionals + method_type.type.required_keywords.size + method_type.type.optional_keywords.keys.index(argname).to_i
184
+ elsif method_type.type.rest_keywords
185
+ positionals + method_type.type.required_keywords.size + method_type.type.optional_keywords.size
186
+ end
187
+ when :kwsplat
188
+ positionals + method_type.type.required_keywords.size + method_type.type.optional_keywords.size if method_type.type.rest_keywords
189
+ end
190
+ else
191
+ pos = node.children[2...].index { |c| c.location == argument_nodes[-2].location }.to_i
192
+ [pos, positionals - 1].min
193
+ end
194
+ end
195
+ end
101
196
  end
102
197
  end
103
198
  end
@@ -1950,10 +1950,6 @@ module Steep
1950
1950
  branch_results = [] #: Array[Pair]
1951
1951
 
1952
1952
  cond_type, constr = constr.synthesize(cond)
1953
- _, cond_vars = interpreter.decompose_value(cond)
1954
- SPECIAL_LVAR_NAMES.each do |name|
1955
- cond_vars.delete(name)
1956
- end
1957
1953
 
1958
1954
  var_name = :"_a[#{SecureRandom.alphanumeric(4)}]"
1959
1955
  var_cond, value_node = transform_condition_node(cond, var_name)
@@ -2621,7 +2617,26 @@ module Steep
2621
2617
  # @type var as_type: AST::Node::TypeAssertion
2622
2618
  asserted_node, as_type = node.children
2623
2619
 
2624
- if type = as_type.type?(module_context.nesting, checker, [])
2620
+ type = as_type.type(module_context.nesting, checker, [])
2621
+
2622
+ case type
2623
+ when Array
2624
+ type.each do |error|
2625
+ typing.add_error(
2626
+ Diagnostic::Ruby::RBSError.new(
2627
+ error: error,
2628
+ node: node,
2629
+ location: error.location || raise
2630
+ )
2631
+ )
2632
+ end
2633
+
2634
+ synthesize(asserted_node, hint: hint)
2635
+
2636
+ when nil, RBS::ParsingError
2637
+ synthesize(asserted_node, hint: hint)
2638
+
2639
+ else
2625
2640
  actual_type, constr = synthesize(asserted_node, hint: type)
2626
2641
 
2627
2642
  if no_subtyping?(sub_type: type, super_type: actual_type) && no_subtyping?(sub_type: actual_type, super_type: type)
@@ -2635,22 +2650,34 @@ module Steep
2635
2650
  end
2636
2651
 
2637
2652
  constr.add_typing(node, type: type)
2638
- else
2639
- synthesize(asserted_node, hint: hint)
2640
2653
  end
2641
2654
  end
2642
2655
 
2643
- when :block, :numblock, :send, :csend
2644
- synthesize_sendish(node, hint: hint, tapp: nil)
2645
-
2646
2656
  when :tapp
2647
2657
  yield_self do
2658
+ # @type var tapp: AST::Node::TypeApplication
2648
2659
  sendish, tapp = node.children
2660
+
2661
+ if (array = tapp.types(module_context.nesting, checker, [])).is_a?(Enumerator)
2662
+ array.each do |error|
2663
+ typing.add_error(
2664
+ Diagnostic::Ruby::RBSError.new(
2665
+ error: error,
2666
+ node: node,
2667
+ location: error.location || raise
2668
+ )
2669
+ )
2670
+ end
2671
+ end
2672
+
2649
2673
  type, constr = synthesize_sendish(sendish, hint: hint, tapp: tapp)
2650
2674
 
2651
2675
  constr.add_typing(node, type: type)
2652
2676
  end
2653
2677
 
2678
+ when :block, :numblock, :send, :csend
2679
+ synthesize_sendish(node, hint: hint, tapp: nil)
2680
+
2654
2681
  when :forwarded_args, :forward_arg
2655
2682
  add_typing(node, type: AST::Builtin.any_type)
2656
2683
 
@@ -3077,7 +3104,8 @@ module Steep
3077
3104
  type_hint = deep_expand_alias(type_hint) || type_hint
3078
3105
 
3079
3106
  procs = flatten_union(type_hint).select do |type|
3080
- check_relation(sub_type: type, super_type: AST::Builtin::Proc.instance_type).success?
3107
+ check_relation(sub_type: type, super_type: AST::Builtin::Proc.instance_type).success? &&
3108
+ !type.is_a?(AST::Types::Any)
3081
3109
  end
3082
3110
 
3083
3111
  proc_instances, proc_types = procs.partition {|type| AST::Builtin::Proc.instance_type?(type) }
@@ -681,7 +681,15 @@ module Steep
681
681
  when KeywordArgs::MissingKeyword
682
682
  missing_keywords.push(*error.keywords.to_a)
683
683
  when PositionalArgs::UnexpectedArg
684
- diagnostics << Diagnostic::Ruby::UnexpectedPositionalArgument.new(node: error.node, params: params)
684
+ if error.node.type == :kwargs
685
+ error.node.children.each do |kwarg|
686
+ if kwarg.type == :pair
687
+ diagnostics << Diagnostic::Ruby::UnexpectedKeywordArgument.new(node: kwarg, params: params)
688
+ end
689
+ end
690
+ else
691
+ diagnostics << Diagnostic::Ruby::UnexpectedPositionalArgument.new(node: error.node, params: params)
692
+ end
685
693
  when PositionalArgs::MissingArg
686
694
  diagnostics << Diagnostic::Ruby::InsufficientPositionalArguments.new(node: node, params: params)
687
695
  end
data/lib/steep/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Steep
2
- VERSION = "1.5.0.pre.5"
2
+ VERSION = "1.5.0.pre.6"
3
3
  end
@@ -12,7 +12,7 @@ module Steep
12
12
 
13
13
  def initialize: (RBS::Location[untyped, untyped]) -> void
14
14
 
15
- def types: (RBS::Resolver::context, Subtyping::Check, Array[Symbol] type_vars) -> (Array[Types::t] | RBS::ParsingError | nil)
15
+ def types: (RBS::Resolver::context, Subtyping::Check, Array[Symbol] type_vars) -> (Array[Types::t] | RBS::ParsingError | Enumerator[Diagnostic::Signature::Base, void] | nil)
16
16
 
17
17
  def types?: (RBS::Resolver::context, Subtyping::Check, Array[Symbol] type_vars) -> Array[Types::t]?
18
18
 
@@ -10,7 +10,7 @@ module Steep
10
10
 
11
11
  def initialize: (RBS::Location[untyped, untyped]) -> void
12
12
 
13
- def type: (RBS::Resolver::context, Subtyping::Check, Array[Symbol] type_vars) -> (Types::t | RBS::ParsingError | nil)
13
+ def type: (RBS::Resolver::context, Subtyping::Check, Array[Symbol] type_vars) -> (Types::t | RBS::ParsingError | Array[Diagnostic::Signature::Base] | nil)
14
14
 
15
15
  def type?: (RBS::Resolver::context, Subtyping::Check, Array[Symbol] type_vars) -> Types::t?
16
16
 
@@ -495,7 +495,7 @@ module Steep
495
495
  # ```
496
496
  #
497
497
  # This diagnostic allows writing `raise` or `return`, by checking the type of the branch body is `bot` or not.
498
- #
498
+ #
499
499
  class UnreachableValueBranch < Base
500
500
  attr_reader type: AST::Types::t
501
501
 
@@ -622,6 +622,14 @@ module Steep
622
622
  def initialize: (hint_type: AST::Types::t, node: Parser::AST::Node) -> void
623
623
  end
624
624
 
625
+ # RBS embedded in the Ruby code has validation error
626
+ #
627
+ class RBSError < Base
628
+ attr_reader error: Signature::Base
629
+
630
+ def initialize: (error: Signature::Base, node: Parser::AST::Node, location: location) -> void
631
+ end
632
+
625
633
  # Argument forwarding `...` cannot be done safely, because of
626
634
  #
627
635
  # 1. The arguments are incompatible, or
@@ -65,5 +65,14 @@ module Steep
65
65
  def deconstruct_send_node!: (Node) -> [Node?, Symbol, Array[Node], send_loc]
66
66
 
67
67
  def test_send_node: (Node) { (Node?, Symbol, Array[Node], send_loc) -> bool } -> bool
68
+
69
+ # Deconstruct sendish node and it's associated block node
70
+ #
71
+ # Receives a sequence of node tree where the leaf node comes first.
72
+ # If the first node is `send`, `csend`, `super`, or `zsuper`, it is the sendish node.
73
+ #
74
+ # If the next node is a `block` or `numblock` that is associated to the *sendish node*, it is the block node.
75
+ #
76
+ def deconstruct_sendish_and_block_nodes: (*Parser::AST::Node) -> [Parser::AST::Node, Parser::AST::Node?]?
68
77
  end
69
78
  end
@@ -4,6 +4,8 @@ use Steep::TypeInference::MethodCall
4
4
  module Steep
5
5
  module Services
6
6
  class CompletionProvider
7
+ include NodeHelper
8
+
7
9
  # Cursor position
8
10
  class Position
9
11
  attr_reader line: Integer
@@ -33,6 +35,14 @@ module Steep
33
35
  def initialize: (identifier: Symbol, range: Range, type: AST::Types::t) -> void
34
36
  end
35
37
 
38
+ class KeywordArgumentItem
39
+ attr_reader identifier: String
40
+
41
+ attr_reader range: Range
42
+
43
+ def initialize: (identifier: String, range: Range) -> void
44
+ end
45
+
36
46
  class LocalVariableItem
37
47
  attr_reader identifier: Symbol
38
48
 
@@ -169,6 +179,7 @@ module Steep
169
179
  end
170
180
 
171
181
  type item = InstanceVariableItem
182
+ | KeywordArgumentItem
172
183
  | LocalVariableItem
173
184
  | ConstantItem
174
185
  | SimpleMethodNameItem
@@ -216,6 +227,8 @@ module Steep
216
227
 
217
228
  def items_for_rbs: (position: Position, buffer: RBS::Buffer) -> Array[item]
218
229
 
230
+ def items_for_following_keyword_arguments: (String text, index: Integer, line: Integer, column: Integer, items: Array[item]) -> void
231
+
219
232
  def method_items_for_receiver_type: (AST::Types::t, include_private: bool, prefix: String, position: Position, items: Array[item]) -> void
220
233
 
221
234
  def word_name?: (String name) -> bool
@@ -226,12 +239,13 @@ module Steep
226
239
 
227
240
  def instance_variable_items_for_context: (TypeInference::Context context, position: Position, prefix: String, items: Array[item]) -> void
228
241
 
242
+ def keyword_argument_items_for_method: (call_node: Parser::AST::Node, send_node: Parser::AST::Node, position: Position, prefix: String, items: Array[item]) -> void
243
+
229
244
  def index_for: (String, line: Integer, column: Integer) -> Integer
230
245
 
231
246
  def disallowed_method?: (Symbol name) -> bool
232
247
 
233
248
  def unwrap_optional: (AST::Types::t) -> AST::Types::t
234
-
235
249
  end
236
250
  end
237
251
  end
@@ -10,7 +10,11 @@ module Steep
10
10
 
11
11
  attr_reader comment: RBS::AST::Comment?
12
12
 
13
- def initialize: (RBS::MethodType, RBS::AST::Comment?) -> void
13
+ attr_reader active_parameter: Integer?
14
+
15
+ def initialize: (RBS::MethodType, RBS::AST::Comment?, Integer?) -> void
16
+
17
+ def parameters: () -> Array[String]
14
18
  end
15
19
 
16
20
  attr_reader source: Source
@@ -31,7 +35,13 @@ module Steep
31
35
 
32
36
  private
33
37
 
34
- def signature_help_for: (Parser::AST::Node, Typing) -> [Array[Item], Integer?]?
38
+ def active_parameter_for: (RBS::MethodType?, Array[Parser::AST::Node], Array[Parser::AST::Node]?, Parser::AST::Node) -> Integer?
39
+
40
+ def arguments_for: (RBS::MethodType) -> Array[String]
41
+
42
+ def last_argument_nodes_for: (argument_nodes: Array[Parser::AST::Node], line: Integer, column: Integer) -> Array[Parser::AST::Node]?
43
+
44
+ def signature_help_for: (Parser::AST::Node, Array[Parser::AST::Node], Array[Parser::AST::Node]?, Typing) -> [Array[Item], Integer?]?
35
45
 
36
46
  def type_check!: (line: Integer, column: Integer) -> Typing
37
47
  end
@@ -38,7 +38,7 @@ module Steep
38
38
 
39
39
  def validate_type_application: (RBS::Types::t) -> void
40
40
 
41
- def validate_type: (RBS::Types::t `type`) -> untyped
41
+ def validate_type: (RBS::Types::t `type`) -> void
42
42
 
43
43
  def ancestor_to_type: (RBS::Definition::Ancestor::t ancestor) -> (AST::Types::Name::Interface | AST::Types::Name::Instance)
44
44
 
@@ -69,7 +69,7 @@ module Steep
69
69
  def validate_one_alias: (RBS::TypeName name, ?RBS::Environment::TypeAliasEntry entry) -> void
70
70
 
71
71
  def validate_one_class_decl: (RBS::TypeName) -> void
72
-
72
+
73
73
  def validate_one_class_alias: (RBS::TypeName, RBS::Environment::ClassAliasEntry | RBS::Environment::ModuleAliasEntry) -> void
74
74
 
75
75
  def validate_alias: () -> void
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: steep
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0.pre.5
4
+ version: 1.5.0.pre.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Soutaro Matsumoto
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-07-07 00:00:00.000000000 Z
11
+ date: 2023-07-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser