steep-relaxed 1.9.3.3

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.
Files changed (165) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.gitmodules +0 -0
  4. data/CHANGELOG.md +1032 -0
  5. data/LICENSE +21 -0
  6. data/README.md +260 -0
  7. data/Rakefile +227 -0
  8. data/STDGEM_DEPENDENCIES.txt +59 -0
  9. data/Steepfile +68 -0
  10. data/bin/console +14 -0
  11. data/bin/generate-diagnostics-docs.rb +112 -0
  12. data/bin/mem_graph.rb +67 -0
  13. data/bin/mem_prof.rb +102 -0
  14. data/bin/output_rebaseline.rb +34 -0
  15. data/bin/output_test.rb +60 -0
  16. data/bin/rbs +20 -0
  17. data/bin/rbs-inline +19 -0
  18. data/bin/setup +9 -0
  19. data/bin/stackprof_test.rb +19 -0
  20. data/bin/steep +19 -0
  21. data/bin/steep-check.rb +251 -0
  22. data/bin/steep-prof +16 -0
  23. data/doc/narrowing.md +195 -0
  24. data/doc/shape.md +194 -0
  25. data/exe/steep +18 -0
  26. data/guides/README.md +5 -0
  27. data/guides/src/gem-rbs-collection/gem-rbs-collection.md +126 -0
  28. data/guides/src/getting-started/getting-started.md +163 -0
  29. data/guides/src/nil-optional/nil-optional.md +195 -0
  30. data/lib/steep/annotation_parser.rb +199 -0
  31. data/lib/steep/ast/annotation/collection.rb +172 -0
  32. data/lib/steep/ast/annotation.rb +137 -0
  33. data/lib/steep/ast/builtin.rb +104 -0
  34. data/lib/steep/ast/ignore.rb +148 -0
  35. data/lib/steep/ast/node/type_application.rb +88 -0
  36. data/lib/steep/ast/node/type_assertion.rb +81 -0
  37. data/lib/steep/ast/types/any.rb +35 -0
  38. data/lib/steep/ast/types/boolean.rb +45 -0
  39. data/lib/steep/ast/types/bot.rb +35 -0
  40. data/lib/steep/ast/types/class.rb +43 -0
  41. data/lib/steep/ast/types/factory.rb +557 -0
  42. data/lib/steep/ast/types/helper.rb +40 -0
  43. data/lib/steep/ast/types/instance.rb +42 -0
  44. data/lib/steep/ast/types/intersection.rb +93 -0
  45. data/lib/steep/ast/types/literal.rb +59 -0
  46. data/lib/steep/ast/types/logic.rb +84 -0
  47. data/lib/steep/ast/types/name.rb +128 -0
  48. data/lib/steep/ast/types/nil.rb +41 -0
  49. data/lib/steep/ast/types/proc.rb +117 -0
  50. data/lib/steep/ast/types/record.rb +79 -0
  51. data/lib/steep/ast/types/self.rb +43 -0
  52. data/lib/steep/ast/types/shared_instance.rb +11 -0
  53. data/lib/steep/ast/types/top.rb +35 -0
  54. data/lib/steep/ast/types/tuple.rb +60 -0
  55. data/lib/steep/ast/types/union.rb +97 -0
  56. data/lib/steep/ast/types/var.rb +65 -0
  57. data/lib/steep/ast/types/void.rb +35 -0
  58. data/lib/steep/cli.rb +401 -0
  59. data/lib/steep/diagnostic/deprecated/else_on_exhaustive_case.rb +20 -0
  60. data/lib/steep/diagnostic/deprecated/unknown_constant_assigned.rb +28 -0
  61. data/lib/steep/diagnostic/helper.rb +18 -0
  62. data/lib/steep/diagnostic/lsp_formatter.rb +78 -0
  63. data/lib/steep/diagnostic/result_printer2.rb +48 -0
  64. data/lib/steep/diagnostic/ruby.rb +1221 -0
  65. data/lib/steep/diagnostic/signature.rb +570 -0
  66. data/lib/steep/drivers/annotations.rb +52 -0
  67. data/lib/steep/drivers/check.rb +339 -0
  68. data/lib/steep/drivers/checkfile.rb +210 -0
  69. data/lib/steep/drivers/diagnostic_printer.rb +105 -0
  70. data/lib/steep/drivers/init.rb +66 -0
  71. data/lib/steep/drivers/langserver.rb +56 -0
  72. data/lib/steep/drivers/print_project.rb +113 -0
  73. data/lib/steep/drivers/stats.rb +203 -0
  74. data/lib/steep/drivers/utils/driver_helper.rb +143 -0
  75. data/lib/steep/drivers/utils/jobs_option.rb +26 -0
  76. data/lib/steep/drivers/vendor.rb +27 -0
  77. data/lib/steep/drivers/watch.rb +194 -0
  78. data/lib/steep/drivers/worker.rb +58 -0
  79. data/lib/steep/equatable.rb +23 -0
  80. data/lib/steep/expectations.rb +228 -0
  81. data/lib/steep/index/rbs_index.rb +350 -0
  82. data/lib/steep/index/signature_symbol_provider.rb +185 -0
  83. data/lib/steep/index/source_index.rb +167 -0
  84. data/lib/steep/interface/block.rb +103 -0
  85. data/lib/steep/interface/builder.rb +843 -0
  86. data/lib/steep/interface/function.rb +1090 -0
  87. data/lib/steep/interface/method_type.rb +330 -0
  88. data/lib/steep/interface/shape.rb +239 -0
  89. data/lib/steep/interface/substitution.rb +159 -0
  90. data/lib/steep/interface/type_param.rb +115 -0
  91. data/lib/steep/located_value.rb +20 -0
  92. data/lib/steep/method_name.rb +42 -0
  93. data/lib/steep/module_helper.rb +24 -0
  94. data/lib/steep/node_helper.rb +273 -0
  95. data/lib/steep/path_helper.rb +30 -0
  96. data/lib/steep/project/dsl.rb +268 -0
  97. data/lib/steep/project/group.rb +31 -0
  98. data/lib/steep/project/options.rb +63 -0
  99. data/lib/steep/project/pattern.rb +59 -0
  100. data/lib/steep/project/target.rb +92 -0
  101. data/lib/steep/project.rb +78 -0
  102. data/lib/steep/rake_task.rb +132 -0
  103. data/lib/steep/range_extension.rb +29 -0
  104. data/lib/steep/server/base_worker.rb +97 -0
  105. data/lib/steep/server/change_buffer.rb +73 -0
  106. data/lib/steep/server/custom_methods.rb +77 -0
  107. data/lib/steep/server/delay_queue.rb +45 -0
  108. data/lib/steep/server/interaction_worker.rb +492 -0
  109. data/lib/steep/server/lsp_formatter.rb +455 -0
  110. data/lib/steep/server/master.rb +922 -0
  111. data/lib/steep/server/target_group_files.rb +205 -0
  112. data/lib/steep/server/type_check_controller.rb +366 -0
  113. data/lib/steep/server/type_check_worker.rb +303 -0
  114. data/lib/steep/server/work_done_progress.rb +64 -0
  115. data/lib/steep/server/worker_process.rb +176 -0
  116. data/lib/steep/services/completion_provider.rb +802 -0
  117. data/lib/steep/services/content_change.rb +61 -0
  118. data/lib/steep/services/file_loader.rb +74 -0
  119. data/lib/steep/services/goto_service.rb +441 -0
  120. data/lib/steep/services/hover_provider/rbs.rb +88 -0
  121. data/lib/steep/services/hover_provider/ruby.rb +221 -0
  122. data/lib/steep/services/hover_provider/singleton_methods.rb +20 -0
  123. data/lib/steep/services/path_assignment.rb +46 -0
  124. data/lib/steep/services/signature_help_provider.rb +202 -0
  125. data/lib/steep/services/signature_service.rb +428 -0
  126. data/lib/steep/services/stats_calculator.rb +68 -0
  127. data/lib/steep/services/type_check_service.rb +394 -0
  128. data/lib/steep/services/type_name_completion.rb +236 -0
  129. data/lib/steep/signature/validator.rb +651 -0
  130. data/lib/steep/source/ignore_ranges.rb +69 -0
  131. data/lib/steep/source.rb +691 -0
  132. data/lib/steep/subtyping/cache.rb +30 -0
  133. data/lib/steep/subtyping/check.rb +1113 -0
  134. data/lib/steep/subtyping/constraints.rb +341 -0
  135. data/lib/steep/subtyping/relation.rb +101 -0
  136. data/lib/steep/subtyping/result.rb +324 -0
  137. data/lib/steep/subtyping/variable_variance.rb +89 -0
  138. data/lib/steep/test.rb +9 -0
  139. data/lib/steep/thread_waiter.rb +43 -0
  140. data/lib/steep/type_construction.rb +5183 -0
  141. data/lib/steep/type_inference/block_params.rb +416 -0
  142. data/lib/steep/type_inference/case_when.rb +303 -0
  143. data/lib/steep/type_inference/constant_env.rb +56 -0
  144. data/lib/steep/type_inference/context.rb +195 -0
  145. data/lib/steep/type_inference/logic_type_interpreter.rb +613 -0
  146. data/lib/steep/type_inference/method_call.rb +193 -0
  147. data/lib/steep/type_inference/method_params.rb +531 -0
  148. data/lib/steep/type_inference/multiple_assignment.rb +194 -0
  149. data/lib/steep/type_inference/send_args.rb +712 -0
  150. data/lib/steep/type_inference/type_env.rb +341 -0
  151. data/lib/steep/type_inference/type_env_builder.rb +138 -0
  152. data/lib/steep/typing.rb +321 -0
  153. data/lib/steep/version.rb +3 -0
  154. data/lib/steep.rb +369 -0
  155. data/manual/annotations.md +181 -0
  156. data/manual/ignore.md +20 -0
  157. data/manual/ruby-diagnostics.md +1879 -0
  158. data/sample/Steepfile +22 -0
  159. data/sample/lib/conference.rb +49 -0
  160. data/sample/lib/length.rb +35 -0
  161. data/sample/sig/conference.rbs +42 -0
  162. data/sample/sig/generics.rbs +15 -0
  163. data/sample/sig/length.rbs +34 -0
  164. data/steep-relaxed.gemspec +56 -0
  165. metadata +340 -0
@@ -0,0 +1,221 @@
1
+ module Steep
2
+ module Services
3
+ module HoverProvider
4
+ class Ruby
5
+ TypeContent = _ = Struct.new(:node, :type, :location, keyword_init: true)
6
+ VariableContent = _ = Struct.new(:node, :name, :type, :location, keyword_init: true)
7
+ TypeAssertionContent = _ = Struct.new(:node, :original_type, :asserted_type, :location, keyword_init: true)
8
+ MethodCallContent = _ = Struct.new(:node, :method_call, :location, keyword_init: true)
9
+ DefinitionContent = _ = Struct.new(:node, :method_name, :method_type, :definition, :location, keyword_init: true)
10
+ ConstantContent = _ = Struct.new(:location, :full_name, :type, :decl, keyword_init: true) do
11
+ # @implements ConstantContent
12
+
13
+ def comments
14
+ case
15
+ when decl = class_decl
16
+ decl.decls.map {|d| d.decl.comment }
17
+ when decl = class_alias
18
+ [decl.decl.comment]
19
+ when decl = constant_decl
20
+ [decl.decl.comment]
21
+ else
22
+ raise
23
+ end.compact
24
+ end
25
+
26
+ def class_decl
27
+ case decl
28
+ when ::RBS::Environment::ClassEntry, ::RBS::Environment::ModuleEntry
29
+ decl
30
+ end
31
+ end
32
+
33
+ def class_alias
34
+ case decl
35
+ when ::RBS::Environment::ClassAliasEntry, ::RBS::Environment::ModuleAliasEntry
36
+ decl
37
+ end
38
+ end
39
+
40
+ def constant_decl
41
+ if decl.is_a?(::RBS::Environment::ConstantEntry)
42
+ decl
43
+ end
44
+ end
45
+
46
+ def constant?
47
+ constant_decl ? true : false
48
+ end
49
+
50
+ def class_or_module?
51
+ (class_decl || class_alias) ? true : false
52
+ end
53
+ end
54
+
55
+ attr_reader :service
56
+
57
+ def initialize(service:)
58
+ @service = service
59
+ end
60
+
61
+ def project
62
+ service.project
63
+ end
64
+
65
+ def method_definition_for(factory, type_name, singleton_method: nil, instance_method: nil)
66
+ case
67
+ when instance_method
68
+ factory.definition_builder.build_instance(type_name).methods.fetch(instance_method)
69
+ when singleton_method
70
+ methods = factory.definition_builder.build_singleton(type_name).methods
71
+
72
+ if singleton_method == :new
73
+ methods[:new] || methods.fetch(:initialize)
74
+ else
75
+ methods.fetch(singleton_method)
76
+ end
77
+ else
78
+ raise "One of the instance_method or singleton_method is required"
79
+ end
80
+ end
81
+
82
+ def typecheck(target, path:, content:, line:, column:)
83
+ subtyping = service.signature_services.fetch(target.name).current_subtyping or return
84
+ source = Source.parse(content, path: path, factory: subtyping.factory)
85
+ source = source.without_unrelated_defs(line: line, column: column)
86
+ resolver = ::RBS::Resolver::ConstantResolver.new(builder: subtyping.factory.definition_builder)
87
+ pos = source.buffer.loc_to_pos([line, column])
88
+ Services::TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: resolver, cursor: pos)
89
+ rescue
90
+ nil
91
+ end
92
+
93
+ def method_name_from_method(context, builder:)
94
+ context.method or raise
95
+ defined_in = context.method.defined_in or raise
96
+ method_name = context.name or raise
97
+
98
+ case
99
+ when defined_in.class?
100
+ case
101
+ when builder.build_instance(defined_in).methods.key?(method_name)
102
+ InstanceMethodName.new(type_name: defined_in, method_name: method_name)
103
+ when builder.build_singleton(defined_in).methods.key?(method_name)
104
+ SingletonMethodName.new(type_name: defined_in, method_name: method_name)
105
+ else
106
+ raise
107
+ end
108
+ else
109
+ InstanceMethodName.new(type_name: defined_in, method_name: method_name)
110
+ end
111
+ end
112
+
113
+ def content_for(target:, path:, line:, column:)
114
+ file = service.source_files[path] or return
115
+ typing = typecheck(target, path: path, content: file.content, line: line, column: column) or return
116
+ node, *parents = typing.source.find_nodes(line: line, column: column)
117
+
118
+ if node && parents
119
+ case node.type
120
+ when :lvar
121
+ var_name = node.children[0]
122
+ context = typing.cursor_context.context or raise
123
+ var_type = context.type_env[var_name] || AST::Types::Any.instance()
124
+
125
+ return VariableContent.new(
126
+ node: node,
127
+ name: var_name,
128
+ type: var_type,
129
+ location: node.location.name # steep:ignore NoMethod
130
+ )
131
+
132
+ when :lvasgn
133
+ var_name, rhs = node.children
134
+ context = typing.cursor_context.context or raise
135
+ type = context.type_env[var_name] || typing.type_of(node: node)
136
+
137
+ return VariableContent.new(
138
+ node: node,
139
+ name: var_name,
140
+ type: type,
141
+ location: node.location.name # steep:ignore NoMethod
142
+ )
143
+
144
+ when :send, :csend
145
+ result_node =
146
+ case parents[0]&.type
147
+ when :block, :numblock
148
+ if node == parents.fetch(0).children[0]
149
+ parents.fetch(0)
150
+ else
151
+ node
152
+ end
153
+ else
154
+ node
155
+ end
156
+
157
+ case call = typing.call_of(node: result_node)
158
+ when TypeInference::MethodCall::Typed, TypeInference::MethodCall::Error
159
+ unless call.method_decls.empty?
160
+ return MethodCallContent.new(
161
+ node: result_node,
162
+ method_call: call,
163
+ location: node.location.selector # steep:ignore NoMethod
164
+ )
165
+ end
166
+ end
167
+
168
+ when :def, :defs
169
+ context = typing.cursor_context.context or raise
170
+ method_context = context.method_context
171
+
172
+ if method_context && method_context.method
173
+ if method_context.method_type
174
+ return DefinitionContent.new(
175
+ node: node,
176
+ method_name: method_name_from_method(method_context, builder: context.factory.definition_builder),
177
+ method_type: method_context.method_type,
178
+ definition: method_context.method,
179
+ location: node.loc.name # steep:ignore NoMethod
180
+ )
181
+ end
182
+ end
183
+
184
+ when :const, :casgn
185
+ context = typing.cursor_context.context or raise
186
+
187
+ type = typing.type_of(node: node)
188
+ const_name = typing.source_index.reference(constant_node: node)
189
+
190
+ if const_name
191
+ entry = context.env.constant_entry(const_name) or return
192
+
193
+ return ConstantContent.new(
194
+ location: node.location.name, # steep:ignore NoMethod
195
+ full_name: const_name,
196
+ type: type,
197
+ decl: entry
198
+ )
199
+ end
200
+ when :assertion
201
+ original_node, _ = node.children
202
+
203
+ original_type = typing.type_of(node: original_node)
204
+ asserted_type = typing.type_of(node: node)
205
+
206
+ if original_type != asserted_type
207
+ return TypeAssertionContent.new(node: node, original_type: original_type, asserted_type: asserted_type, location: node.location.expression)
208
+ end
209
+ end
210
+
211
+ TypeContent.new(
212
+ node: node,
213
+ type: typing.type_of(node: node),
214
+ location: node.location.expression
215
+ )
216
+ end
217
+ end
218
+ end
219
+ end
220
+ end
221
+ end
@@ -0,0 +1,20 @@
1
+ module Steep
2
+ module Services
3
+ module HoverProvider
4
+ module SingletonMethods
5
+ def content_for(service:, path:, line:, column:)
6
+ project = service.project
7
+
8
+ case
9
+ when target = project.target_for_source_path(path)
10
+ Ruby.new(service: service).content_for(target: target, path: path, line: line, column: column)
11
+ when target = project.target_for_signature_path(path)
12
+ RBS.new(service: service).content_for(target: target, path: path, line: line, column: column)
13
+ end
14
+ end
15
+ end
16
+
17
+ extend SingletonMethods
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,46 @@
1
+ module Steep
2
+ module Services
3
+ class PathAssignment
4
+ attr_reader :index, :max_index, :cache
5
+
6
+ def initialize(index:, max_index:)
7
+ @index = index
8
+ @max_index = max_index
9
+ @cache = {}
10
+ end
11
+
12
+ def self.all
13
+ new(index: 0, max_index: 1)
14
+ end
15
+
16
+ def =~(target_path)
17
+ key = stringify(target_path)
18
+ (cache[key] ||= self.class.index_for(key: key, max_index: max_index)) == index
19
+ end
20
+
21
+ alias === =~
22
+
23
+ def assign!(path, index)
24
+ key = stringify(path)
25
+ cache[key] = index
26
+ self
27
+ end
28
+
29
+ def stringify(target_path)
30
+ target =
31
+ case target_path[0]
32
+ when Project::Target
33
+ target_path[0].name.to_s
34
+ else
35
+ target_path[0].to_s
36
+ end
37
+ path = target_path[1].to_s
38
+ "#{target}::#{path}"
39
+ end
40
+
41
+ def self.index_for(key:, max_index:)
42
+ Digest::MD5.hexdigest(key).hex % max_index
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,202 @@
1
+ module Steep
2
+ module Services
3
+ class SignatureHelpProvider
4
+ MethodCall = TypeInference::MethodCall
5
+
6
+ Item = _ = Struct.new(:method_type, :comment, :active_parameter) do
7
+ # @implements Item
8
+
9
+ def parameters
10
+ if method_type.type.is_a?(RBS::Types::Function)
11
+ arguments = [] #: Array[String]
12
+ arguments.push(*method_type.type.required_positionals.map(&:to_s))
13
+ arguments.push(*method_type.type.optional_positionals.map {|p| "?#{p}"})
14
+ arguments.push("*#{method_type.type.rest_positionals}") if method_type.type.rest_positionals
15
+ arguments.push(*method_type.type.trailing_positionals.map(&:to_s))
16
+ arguments.push(*method_type.type.required_keywords.map {|name, param| "#{name}: #{param}" })
17
+ arguments.push(*method_type.type.optional_keywords.map {|name, param| "?#{name}: #{param}" })
18
+ arguments.push("**#{method_type.type.rest_keywords}") if method_type.type.rest_keywords
19
+ arguments
20
+ end
21
+ end
22
+ end
23
+
24
+ include NodeHelper
25
+
26
+ attr_reader :source, :path, :subtyping, :typing, :buffer
27
+
28
+ def env
29
+ subtyping.factory.env
30
+ end
31
+
32
+ def initialize(source:, subtyping:)
33
+ @source = source
34
+ @subtyping = subtyping
35
+ @buffer = source.buffer
36
+ end
37
+
38
+ def run(line:, column:)
39
+ nodes = source.find_nodes(line: line, column: column)
40
+
41
+ return unless nodes
42
+
43
+ typing = type_check!(line: line, column: column)
44
+ argument_nodes = [] #: Array[Parser::AST::Node]
45
+
46
+ while true
47
+ node = nodes.shift()
48
+ parent = nodes.first
49
+
50
+ node or return
51
+ argument_nodes << node
52
+
53
+ if node.type == :send || node.type == :csend
54
+ pos = buffer.loc_to_pos([line, column])
55
+ begin_loc = (_ = node.loc).begin #: Parser::Source::Range?
56
+ end_loc = (_ = node.loc).end #: Parser::Source::Range?
57
+
58
+ if begin_loc && end_loc
59
+ if begin_loc.end_pos <= pos && pos <= end_loc.begin_pos
60
+ # Given position is between open/close parens of args of send node
61
+
62
+ if parent && (parent.type == :block || parent.type == :numblock) && node.equal?(parent.children[0])
63
+ send_node = parent
64
+ else
65
+ send_node = node
66
+ end
67
+
68
+ last_argument_nodes = last_argument_nodes_for(argument_nodes: argument_nodes, line: line, column: column)
69
+ return signature_help_for(send_node, argument_nodes, last_argument_nodes, typing)
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+ def type_check!(line:, column:)
77
+ source = self.source.without_unrelated_defs(line: line, column: column)
78
+ resolver = RBS::Resolver::ConstantResolver.new(builder: subtyping.factory.definition_builder)
79
+ pos = self.source.buffer.loc_to_pos([line, column])
80
+ TypeCheckService.type_check(source: source, subtyping: subtyping, constant_resolver: resolver, cursor: pos)
81
+ end
82
+
83
+ def last_argument_nodes_for(argument_nodes:, line:, column:)
84
+ last = argument_nodes.last or raise
85
+ return unless last.children[2] # No arguments
86
+ return argument_nodes if argument_nodes.size > 1 # Cursor is on the last argument
87
+
88
+ pos = buffer.loc_to_pos([line, column])
89
+
90
+ while true
91
+ pos -= 1
92
+ line, column = buffer.pos_to_loc(pos)
93
+ nodes = source.find_nodes(line: line, column: column)
94
+ return unless nodes
95
+
96
+ index = nodes.index { |n| n.type == :send || n.type == :csend }
97
+ return nodes[..index] if index.to_i > 0
98
+ end
99
+ end
100
+
101
+ def signature_help_for(node, argument, last_argument, typing)
102
+ call = typing.call_of(node: node)
103
+ context = typing.cursor_context.context or raise
104
+
105
+ items = [] #: Array[Item]
106
+ index = nil #: Integer?
107
+
108
+ case call
109
+ when MethodCall::Typed, MethodCall::Error
110
+ type = call.receiver_type
111
+ config = Interface::Builder::Config.new(self_type: context.self_type, variable_bounds: context.variable_context.upper_bounds)
112
+
113
+ if shape = subtyping.builder.shape(type, config)
114
+ shape = shape.public_shape if private_send?(node)
115
+
116
+ if method = shape.methods[call.method_name]
117
+ method.overloads.each.with_index do |overload, i|
118
+ defn = overload.method_defs[0]
119
+
120
+ active_parameter = active_parameter_for(defn&.type, argument, last_argument, node)
121
+ items << Item.new(subtyping.factory.method_type_1(overload.method_type), defn&.comment, active_parameter)
122
+
123
+ if call.is_a?(MethodCall::Typed)
124
+ if call.method_decls.intersect?(overload.method_decls(call.method_name).to_set)
125
+ index = i
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
131
+ when MethodCall::Untyped, MethodCall::NoMethodError
132
+ return
133
+ end
134
+
135
+ [items, index]
136
+ end
137
+
138
+ def active_parameter_for(method_type, argument_nodes, last_argument_nodes, node)
139
+ return unless method_type
140
+ return unless method_type.type.is_a?(RBS::Types::Function)
141
+
142
+ 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
143
+
144
+ if argument_nodes.size == 1
145
+ # Cursor is not on the argument (maybe on comma after argument)
146
+ return 0 if last_argument_nodes.nil? # No arguments
147
+
148
+ case last_argument_nodes.fetch(-2).type
149
+ when :splat
150
+ method_type.type.required_positionals.size + method_type.type.optional_positionals.size + 1 if method_type.type.rest_positionals
151
+ when :kwargs
152
+ case last_argument_nodes.fetch(-3).type
153
+ when :pair
154
+ argname = last_argument_nodes.fetch(-3).children.first.children.first
155
+ if method_type.type.required_keywords.key?(argname)
156
+ positionals + method_type.type.required_keywords.keys.index(argname).to_i + 1
157
+ elsif method_type.type.optional_keywords.key?(argname)
158
+ positionals + method_type.type.required_keywords.size + method_type.type.optional_keywords.keys.index(argname).to_i + 1
159
+ elsif method_type.type.rest_keywords
160
+ positionals + method_type.type.required_keywords.size + method_type.type.optional_keywords.size
161
+ end
162
+ when :kwsplat
163
+ positionals + method_type.type.required_keywords.size + method_type.type.optional_keywords.size if method_type.type.rest_keywords
164
+ end
165
+ else
166
+ pos = (node.children[2...] || raise).index { |c| c.location == last_argument_nodes.fetch(-2).location }.to_i
167
+ if method_type.type.rest_positionals
168
+ [pos + 1, positionals - 1].min
169
+ else
170
+ [pos + 1, positionals].min
171
+ end
172
+ end
173
+ else
174
+ # Cursor is on the argument
175
+ case argument_nodes.fetch(-2).type
176
+ when :splat
177
+ method_type.type.required_positionals.size + method_type.type.optional_positionals.size if method_type.type.rest_positionals
178
+ when :kwargs
179
+ if argument_nodes[-3]
180
+ case argument_nodes.fetch(-3).type
181
+ when :pair
182
+ argname = argument_nodes.fetch(-3).children.first.children.first
183
+ if method_type.type.required_keywords.key?(argname)
184
+ positionals + method_type.type.required_keywords.keys.index(argname).to_i
185
+ elsif method_type.type.optional_keywords.key?(argname)
186
+ positionals + method_type.type.required_keywords.size + method_type.type.optional_keywords.keys.index(argname).to_i
187
+ elsif method_type.type.rest_keywords
188
+ positionals + method_type.type.required_keywords.size + method_type.type.optional_keywords.size
189
+ end
190
+ when :kwsplat
191
+ positionals + method_type.type.required_keywords.size + method_type.type.optional_keywords.size if method_type.type.rest_keywords
192
+ end
193
+ end
194
+ else
195
+ pos = (node.children[2...] || raise).index { |c| c.location == argument_nodes.fetch(-2).location }.to_i
196
+ [pos, positionals - 1].min
197
+ end
198
+ end
199
+ end
200
+ end
201
+ end
202
+ end