solargraph 0.58.0 → 0.59.0

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 (219) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +3 -0
  3. data/.gitattributes +2 -0
  4. data/.github/workflows/linting.yml +6 -5
  5. data/.github/workflows/plugins.yml +48 -35
  6. data/.github/workflows/rspec.yml +15 -28
  7. data/.github/workflows/typecheck.yml +3 -2
  8. data/.gitignore +1 -0
  9. data/.rubocop.yml +38 -6
  10. data/.rubocop_todo.yml +53 -966
  11. data/CHANGELOG.md +24 -0
  12. data/Gemfile +3 -1
  13. data/README.md +3 -3
  14. data/Rakefile +26 -23
  15. data/bin/solargraph +9 -8
  16. data/lib/solargraph/api_map/cache.rb +110 -110
  17. data/lib/solargraph/api_map/constants.rb +288 -279
  18. data/lib/solargraph/api_map/index.rb +204 -193
  19. data/lib/solargraph/api_map/source_to_yard.rb +110 -97
  20. data/lib/solargraph/api_map/store.rb +395 -384
  21. data/lib/solargraph/api_map.rb +1029 -945
  22. data/lib/solargraph/bench.rb +44 -45
  23. data/lib/solargraph/complex_type/conformance.rb +176 -0
  24. data/lib/solargraph/complex_type/type_methods.rb +240 -228
  25. data/lib/solargraph/complex_type/unique_type.rb +641 -482
  26. data/lib/solargraph/complex_type.rb +557 -444
  27. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -61
  28. data/lib/solargraph/convention/data_definition/data_definition_node.rb +93 -91
  29. data/lib/solargraph/convention/data_definition.rb +108 -105
  30. data/lib/solargraph/convention/gemfile.rb +15 -15
  31. data/lib/solargraph/convention/gemspec.rb +23 -23
  32. data/lib/solargraph/convention/rakefile.rb +17 -17
  33. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +62 -61
  34. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +103 -102
  35. data/lib/solargraph/convention/struct_definition.rb +168 -164
  36. data/lib/solargraph/convention.rb +78 -78
  37. data/lib/solargraph/converters/dd.rb +19 -17
  38. data/lib/solargraph/converters/dl.rb +17 -15
  39. data/lib/solargraph/converters/dt.rb +17 -15
  40. data/lib/solargraph/converters/misc.rb +3 -1
  41. data/lib/solargraph/diagnostics/require_not_found.rb +54 -53
  42. data/lib/solargraph/diagnostics/rubocop.rb +119 -118
  43. data/lib/solargraph/diagnostics/rubocop_helpers.rb +70 -68
  44. data/lib/solargraph/diagnostics/type_check.rb +56 -55
  45. data/lib/solargraph/diagnostics/update_errors.rb +37 -41
  46. data/lib/solargraph/doc_map.rb +438 -439
  47. data/lib/solargraph/equality.rb +34 -34
  48. data/lib/solargraph/gem_pins.rb +98 -98
  49. data/lib/solargraph/language_server/error_codes.rb +20 -20
  50. data/lib/solargraph/language_server/host/diagnoser.rb +89 -89
  51. data/lib/solargraph/language_server/host/dispatch.rb +130 -130
  52. data/lib/solargraph/language_server/host/message_worker.rb +113 -112
  53. data/lib/solargraph/language_server/host/sources.rb +100 -99
  54. data/lib/solargraph/language_server/host.rb +886 -878
  55. data/lib/solargraph/language_server/message/base.rb +97 -97
  56. data/lib/solargraph/language_server/message/client/register_capability.rb +13 -15
  57. data/lib/solargraph/language_server/message/completion_item/resolve.rb +58 -60
  58. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +108 -114
  59. data/lib/solargraph/language_server/message/extended/document.rb +24 -23
  60. data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -32
  61. data/lib/solargraph/language_server/message/extended/download_core.rb +20 -19
  62. data/lib/solargraph/language_server/message/extended/search.rb +20 -20
  63. data/lib/solargraph/language_server/message/initialize.rb +197 -191
  64. data/lib/solargraph/language_server/message/text_document/completion.rb +58 -56
  65. data/lib/solargraph/language_server/message/text_document/definition.rb +49 -40
  66. data/lib/solargraph/language_server/message/text_document/document_highlight.rb +23 -16
  67. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +36 -26
  68. data/lib/solargraph/language_server/message/text_document/formatting.rb +150 -148
  69. data/lib/solargraph/language_server/message/text_document/hover.rb +58 -58
  70. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +18 -11
  71. data/lib/solargraph/language_server/message/text_document/references.rb +23 -16
  72. data/lib/solargraph/language_server/message/text_document/rename.rb +26 -19
  73. data/lib/solargraph/language_server/message/text_document/signature_help.rb +25 -24
  74. data/lib/solargraph/language_server/message/text_document/type_definition.rb +33 -25
  75. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +41 -35
  76. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +48 -40
  77. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +32 -26
  78. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +33 -23
  79. data/lib/solargraph/language_server/message.rb +94 -94
  80. data/lib/solargraph/language_server/request.rb +29 -27
  81. data/lib/solargraph/language_server/transport/data_reader.rb +72 -74
  82. data/lib/solargraph/language_server/uri_helpers.rb +49 -49
  83. data/lib/solargraph/library.rb +702 -683
  84. data/lib/solargraph/location.rb +85 -82
  85. data/lib/solargraph/logging.rb +55 -37
  86. data/lib/solargraph/page.rb +92 -92
  87. data/lib/solargraph/parser/comment_ripper.rb +84 -69
  88. data/lib/solargraph/parser/flow_sensitive_typing.rb +471 -255
  89. data/lib/solargraph/parser/node_processor/base.rb +122 -92
  90. data/lib/solargraph/parser/node_processor.rb +63 -62
  91. data/lib/solargraph/parser/parser_gem/class_methods.rb +165 -149
  92. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +19 -19
  93. data/lib/solargraph/parser/parser_gem/node_chainer.rb +191 -166
  94. data/lib/solargraph/parser/parser_gem/node_methods.rb +507 -486
  95. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +22 -22
  96. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +61 -59
  97. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +24 -15
  98. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +45 -46
  99. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +60 -53
  100. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +38 -37
  101. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +53 -23
  102. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +42 -40
  103. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +30 -29
  104. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +61 -59
  105. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +98 -98
  106. data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
  107. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +17 -17
  108. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +39 -38
  109. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +51 -52
  110. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +302 -291
  111. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -29
  112. data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
  113. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +33 -29
  114. data/lib/solargraph/parser/parser_gem/node_processors.rb +74 -70
  115. data/lib/solargraph/parser/parser_gem.rb +14 -12
  116. data/lib/solargraph/parser/region.rb +75 -69
  117. data/lib/solargraph/parser/snippet.rb +19 -17
  118. data/lib/solargraph/parser.rb +25 -23
  119. data/lib/solargraph/pin/base.rb +773 -729
  120. data/lib/solargraph/pin/base_variable.rb +375 -126
  121. data/lib/solargraph/pin/block.rb +127 -104
  122. data/lib/solargraph/pin/breakable.rb +15 -9
  123. data/lib/solargraph/pin/callable.rb +275 -231
  124. data/lib/solargraph/pin/closure.rb +69 -72
  125. data/lib/solargraph/pin/common.rb +97 -79
  126. data/lib/solargraph/pin/compound_statement.rb +55 -0
  127. data/lib/solargraph/pin/constant.rb +43 -45
  128. data/lib/solargraph/pin/conversions.rb +129 -123
  129. data/lib/solargraph/pin/delegated_method.rb +131 -120
  130. data/lib/solargraph/pin/documenting.rb +116 -114
  131. data/lib/solargraph/pin/instance_variable.rb +38 -34
  132. data/lib/solargraph/pin/keyword.rb +16 -20
  133. data/lib/solargraph/pin/local_variable.rb +31 -75
  134. data/lib/solargraph/pin/method.rb +724 -672
  135. data/lib/solargraph/pin/method_alias.rb +42 -34
  136. data/lib/solargraph/pin/namespace.rb +122 -115
  137. data/lib/solargraph/pin/parameter.rb +339 -275
  138. data/lib/solargraph/pin/proxy_type.rb +42 -39
  139. data/lib/solargraph/pin/reference/override.rb +47 -47
  140. data/lib/solargraph/pin/reference/superclass.rb +17 -15
  141. data/lib/solargraph/pin/reference/type_alias.rb +16 -0
  142. data/lib/solargraph/pin/reference.rb +59 -39
  143. data/lib/solargraph/pin/search.rb +62 -61
  144. data/lib/solargraph/pin/signature.rb +64 -61
  145. data/lib/solargraph/pin/symbol.rb +54 -53
  146. data/lib/solargraph/pin/until.rb +16 -18
  147. data/lib/solargraph/pin/while.rb +16 -18
  148. data/lib/solargraph/pin.rb +46 -44
  149. data/lib/solargraph/pin_cache.rb +248 -245
  150. data/lib/solargraph/position.rb +139 -119
  151. data/lib/solargraph/range.rb +113 -112
  152. data/lib/solargraph/rbs_map/conversions.rb +952 -823
  153. data/lib/solargraph/rbs_map/core_fills.rb +91 -84
  154. data/lib/solargraph/rbs_map/core_map.rb +65 -58
  155. data/lib/solargraph/rbs_map/stdlib_map.rb +71 -43
  156. data/lib/solargraph/rbs_map.rb +207 -163
  157. data/lib/solargraph/server_methods.rb +16 -16
  158. data/lib/solargraph/shell.rb +555 -352
  159. data/lib/solargraph/source/chain/array.rb +39 -37
  160. data/lib/solargraph/source/chain/call.rb +377 -337
  161. data/lib/solargraph/source/chain/class_variable.rb +13 -13
  162. data/lib/solargraph/source/chain/constant.rb +30 -26
  163. data/lib/solargraph/source/chain/global_variable.rb +13 -13
  164. data/lib/solargraph/source/chain/hash.rb +37 -34
  165. data/lib/solargraph/source/chain/if.rb +30 -28
  166. data/lib/solargraph/source/chain/instance_variable.rb +36 -13
  167. data/lib/solargraph/source/chain/link.rb +99 -109
  168. data/lib/solargraph/source/chain/literal.rb +51 -48
  169. data/lib/solargraph/source/chain/or.rb +29 -23
  170. data/lib/solargraph/source/chain/q_call.rb +13 -11
  171. data/lib/solargraph/source/chain/variable.rb +15 -13
  172. data/lib/solargraph/source/chain/z_super.rb +28 -30
  173. data/lib/solargraph/source/chain.rb +304 -291
  174. data/lib/solargraph/source/change.rb +89 -82
  175. data/lib/solargraph/source/cursor.rb +172 -166
  176. data/lib/solargraph/source/encoding_fixes.rb +22 -23
  177. data/lib/solargraph/source/source_chainer.rb +218 -194
  178. data/lib/solargraph/source/updater.rb +59 -55
  179. data/lib/solargraph/source.rb +522 -498
  180. data/lib/solargraph/source_map/clip.rb +245 -226
  181. data/lib/solargraph/source_map/data.rb +37 -34
  182. data/lib/solargraph/source_map/mapper.rb +286 -259
  183. data/lib/solargraph/source_map.rb +224 -212
  184. data/lib/solargraph/type_checker/problem.rb +34 -32
  185. data/lib/solargraph/type_checker/rules.rb +157 -84
  186. data/lib/solargraph/type_checker.rb +888 -814
  187. data/lib/solargraph/version.rb +5 -5
  188. data/lib/solargraph/workspace/config.rb +258 -255
  189. data/lib/solargraph/workspace/gemspecs.rb +367 -0
  190. data/lib/solargraph/workspace/require_paths.rb +98 -97
  191. data/lib/solargraph/workspace.rb +242 -220
  192. data/lib/solargraph/yard_map/helpers.rb +49 -44
  193. data/lib/solargraph/yard_map/mapper/to_method.rb +136 -130
  194. data/lib/solargraph/yard_map/mapper/to_namespace.rb +32 -31
  195. data/lib/solargraph/yard_map/mapper.rb +84 -79
  196. data/lib/solargraph/yard_map.rb +17 -18
  197. data/lib/solargraph/yard_tags.rb +20 -20
  198. data/lib/solargraph/yardoc.rb +90 -87
  199. data/lib/solargraph.rb +128 -105
  200. data/rbs/fills/rubygems/0/dependency.rbs +193 -0
  201. data/rbs/fills/tuple/tuple.rbs +28 -0
  202. data/rbs/shims/ast/0/node.rbs +5 -0
  203. data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
  204. data/rbs_collection.yaml +1 -1
  205. data/solargraph.gemspec +37 -35
  206. metadata +52 -51
  207. data/lib/solargraph/type_checker/checks.rb +0 -124
  208. data/lib/solargraph/type_checker/param_def.rb +0 -37
  209. data/lib/solargraph/yard_map/to_method.rb +0 -89
  210. data/sig/shims/ast/0/node.rbs +0 -5
  211. /data/{sig → rbs}/shims/ast/2.4/.rbs_meta.yaml +0 -0
  212. /data/{sig → rbs}/shims/ast/2.4/ast.rbs +0 -0
  213. /data/{sig → rbs}/shims/parser/3.2.0.1/builders/default.rbs +0 -0
  214. /data/{sig → rbs}/shims/parser/3.2.0.1/manifest.yaml +0 -0
  215. /data/{sig → rbs}/shims/parser/3.2.0.1/parser.rbs +0 -0
  216. /data/{sig → rbs}/shims/parser/3.2.0.1/polyfill.rbs +0 -0
  217. /data/{sig → rbs}/shims/thor/1.2.0.1/.rbs_meta.yaml +0 -0
  218. /data/{sig → rbs}/shims/thor/1.2.0.1/manifest.yaml +0 -0
  219. /data/{sig → rbs}/shims/thor/1.2.0.1/thor.rbs +0 -0
@@ -1,275 +1,339 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- module Pin
5
- class Parameter < LocalVariable
6
- # @return [::Symbol]
7
- attr_reader :decl
8
-
9
- # @return [String]
10
- attr_reader :asgn_code
11
-
12
- # allow this to be set to the method after the method itself has
13
- # been created
14
- attr_writer :closure
15
-
16
- # @param decl [::Symbol] :arg, :optarg, :kwarg, :kwoptarg, :restarg, :kwrestarg, :block, :blockarg
17
- # @param asgn_code [String, nil]
18
- def initialize decl: :arg, asgn_code: nil, **splat
19
- super(**splat)
20
- @asgn_code = asgn_code
21
- @decl = decl
22
- end
23
-
24
- def type_location
25
- super || closure&.type_location
26
- end
27
-
28
- def location
29
- super || closure&.type_location
30
- end
31
-
32
- def combine_with(other, attrs={})
33
- new_attrs = {
34
- decl: assert_same(other, :decl),
35
- presence: choose(other, :presence),
36
- asgn_code: choose(other, :asgn_code),
37
- }.merge(attrs)
38
- super(other, new_attrs)
39
- end
40
-
41
- def keyword?
42
- [:kwarg, :kwoptarg].include?(decl)
43
- end
44
-
45
- def kwrestarg?
46
- decl == :kwrestarg || (assignment && [:HASH, :hash].include?(assignment.type))
47
- end
48
-
49
- def needs_consistent_name?
50
- keyword?
51
- end
52
-
53
- # @return [String]
54
- def arity_decl
55
- name = (self.name || '(anon)')
56
- type = (return_type&.to_rbs || 'untyped')
57
- case decl
58
- when :arg
59
- ""
60
- when :optarg
61
- "?"
62
- when :kwarg
63
- "#{name}:"
64
- when :kwoptarg
65
- "?#{name}:"
66
- when :restarg
67
- "*"
68
- when :kwrestarg
69
- "**"
70
- else
71
- "(unknown decl: #{decl})"
72
- end
73
- end
74
-
75
- def arg?
76
- decl == :arg
77
- end
78
-
79
- def restarg?
80
- decl == :restarg
81
- end
82
-
83
- def rest?
84
- decl == :restarg || decl == :kwrestarg
85
- end
86
-
87
- def block?
88
- [:block, :blockarg].include?(decl)
89
- end
90
-
91
- def to_rbs
92
- case decl
93
- when :optarg
94
- "?#{super}"
95
- when :kwarg
96
- "#{name}: #{return_type.to_rbs}"
97
- when :kwoptarg
98
- "?#{name}: #{return_type.to_rbs}"
99
- when :restarg
100
- "*#{super}"
101
- when :kwrestarg
102
- "**#{super}"
103
- else
104
- super
105
- end
106
- end
107
-
108
- # @return [String] the full name of the parameter, including any
109
- # declarative symbols such as `*` or `:` indicating type of
110
- # parameter. This is used in method signatures.
111
- def full_name
112
- case decl
113
- when :kwarg, :kwoptarg
114
- "#{name}:"
115
- when :restarg
116
- "*#{name}"
117
- when :kwrestarg
118
- "**#{name}"
119
- when :block, :blockarg
120
- "&#{name}"
121
- else
122
- name
123
- end
124
- end
125
-
126
- # @return [String]
127
- def full
128
- full_name + case decl
129
- when :optarg
130
- " = #{asgn_code || '?'}"
131
- when :kwoptarg
132
- " #{asgn_code || '?'}"
133
- else
134
- ''
135
- end
136
- end
137
-
138
- # @return [ComplexType]
139
- def return_type
140
- if @return_type.nil?
141
- @return_type = ComplexType::UNDEFINED
142
- found = param_tag
143
- @return_type = ComplexType.try_parse(*found.types) unless found.nil? or found.types.nil?
144
- if @return_type.undefined?
145
- if decl == :restarg
146
- @return_type = ComplexType.try_parse('::Array')
147
- elsif decl == :kwrestarg
148
- @return_type = ComplexType.try_parse('::Hash')
149
- elsif decl == :blockarg
150
- @return_type = ComplexType.try_parse('::Proc')
151
- end
152
- end
153
- end
154
- super
155
- @return_type
156
- end
157
-
158
- # The parameter's zero-based location in the block's signature.
159
- #
160
- # @return [Integer]
161
- def index
162
- # @type [Method, Block]
163
- method_pin = closure
164
- method_pin.parameter_names.index(name)
165
- end
166
-
167
- # @param api_map [ApiMap]
168
- def typify api_map
169
- return return_type.qualify(api_map, *closure.gates) unless return_type.undefined?
170
- closure.is_a?(Pin::Block) ? typify_block_param(api_map) : typify_method_param(api_map)
171
- end
172
-
173
- # @param atype [ComplexType]
174
- # @param api_map [ApiMap]
175
- def compatible_arg?(atype, api_map)
176
- # make sure we get types from up the method
177
- # inheritance chain if we don't have them on this pin
178
- ptype = typify api_map
179
- ptype.undefined? || ptype.can_assign?(api_map, atype) || ptype.generic?
180
- end
181
-
182
- def documentation
183
- tag = param_tag
184
- return '' if tag.nil? || tag.text.nil?
185
- tag.text
186
- end
187
-
188
- private
189
-
190
- # @return [YARD::Tags::Tag, nil]
191
- def param_tag
192
- params = closure.docstring.tags(:param)
193
- params.each do |p|
194
- return p if p.name == name
195
- end
196
- params[index] if index && params[index] && (params[index].name.nil? || params[index].name.empty?)
197
- end
198
-
199
- # @param api_map [ApiMap]
200
- # @return [ComplexType]
201
- def typify_block_param api_map
202
- block_pin = closure
203
- if block_pin.is_a?(Pin::Block) && block_pin.receiver
204
- return block_pin.typify_parameters(api_map)[index]
205
- end
206
- ComplexType::UNDEFINED
207
- end
208
-
209
- # @param api_map [ApiMap]
210
- # @return [ComplexType]
211
- def typify_method_param api_map
212
- meths = api_map.get_method_stack(closure.full_context.tag, closure.name, scope: closure.scope)
213
- # meths.shift # Ignore the first one
214
- meths.each do |meth|
215
- found = nil
216
- params = meth.docstring.tags(:param) + see_reference(docstring, api_map)
217
- params.each do |p|
218
- next unless p.name == name
219
- found = p
220
- break
221
- end
222
- if found.nil? and !index.nil?
223
- found = params[index] if params[index] && (params[index].name.nil? || params[index].name.empty?)
224
- end
225
- return ComplexType.try_parse(*found.types).qualify(api_map, *meth.closure.gates) unless found.nil? || found.types.nil?
226
- end
227
- ComplexType::UNDEFINED
228
- end
229
-
230
- # @param heredoc [YARD::Docstring]
231
- # @param api_map [ApiMap]
232
- # @param skip [::Array]
233
- # @return [::Array<YARD::Tags::Tag>]
234
- def see_reference heredoc, api_map, skip = []
235
- # This should actually be an intersection type
236
- # @param ref [YARD::Tags::Tag, Solargraph::Yard::Tags::RefTag]
237
- heredoc.ref_tags.each do |ref|
238
- # @sg-ignore ref should actually be an intersection type
239
- next unless ref.tag_name == 'param' && ref.owner
240
- # @sg-ignore ref should actually be an intersection type
241
- result = resolve_reference(ref.owner.to_s, api_map, skip)
242
- return result unless result.nil?
243
- end
244
- []
245
- end
246
-
247
- # @param ref [String]
248
- # @param api_map [ApiMap]
249
- # @param skip [::Array]
250
- # @return [::Array<YARD::Tags::Tag>, nil]
251
- def resolve_reference ref, api_map, skip
252
- return nil if skip.include?(ref)
253
- skip.push ref
254
- parts = ref.split(/[.#]/)
255
- if parts.first.empty?
256
- path = "#{namespace}#{ref}"
257
- else
258
- fqns = api_map.qualify(parts.first, namespace)
259
- return nil if fqns.nil?
260
- path = fqns + ref[parts.first.length] + parts.last
261
- end
262
- pins = api_map.get_path_pins(path)
263
- pins.each do |pin|
264
- params = pin.docstring.tags(:param)
265
- return params unless params.empty?
266
- end
267
- pins.each do |pin|
268
- params = see_reference(pin.docstring, api_map, skip)
269
- return params unless params.empty?
270
- end
271
- nil
272
- end
273
- end
274
- end
275
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Pin
5
+ class Parameter < LocalVariable
6
+ # @return [::Symbol]
7
+ attr_reader :decl
8
+
9
+ # @return [String]
10
+ attr_reader :asgn_code
11
+
12
+ # allow this to be set to the method after the method itself has
13
+ # been created
14
+ attr_writer :closure
15
+
16
+ # @param decl [::Symbol] :arg, :optarg, :kwarg, :kwoptarg, :restarg, :kwrestarg, :block, :blockarg
17
+ # @param asgn_code [String, nil]
18
+ # @param [Hash{Symbol => Object}] splat
19
+ def initialize decl: :arg, asgn_code: nil, **splat
20
+ super(**splat)
21
+ @asgn_code = asgn_code
22
+ @decl = decl
23
+ end
24
+
25
+ def type_location
26
+ super || closure&.type_location
27
+ end
28
+
29
+ def location
30
+ super || closure&.type_location
31
+ end
32
+
33
+ def combine_with other, attrs = {}
34
+ # Parameters can be combined with local variables
35
+ new_attrs = if other.is_a?(Parameter)
36
+ {
37
+ decl: assert_same(other, :decl),
38
+ asgn_code: choose(other, :asgn_code)
39
+ }
40
+ else
41
+ {
42
+ decl: decl,
43
+ asgn_code: asgn_code
44
+ }
45
+ end
46
+ super(other, new_attrs.merge(attrs))
47
+ end
48
+
49
+ def combine_return_type other
50
+ out = super
51
+ if out&.undefined?
52
+ # allow our return_type method to provide a better type
53
+ # using :param tag
54
+ out = nil
55
+ end
56
+ out
57
+ end
58
+
59
+ def keyword?
60
+ %i[kwarg kwoptarg].include?(decl)
61
+ end
62
+
63
+ def kwrestarg?
64
+ # @sg-ignore flow sensitive typing needs to handle attrs
65
+ decl == :kwrestarg || (assignment && %i[HASH hash].include?(assignment.type))
66
+ end
67
+
68
+ def needs_consistent_name?
69
+ keyword?
70
+ end
71
+
72
+ # @return [String]
73
+ def arity_decl
74
+ name = self.name || '(anon)'
75
+ return_type&.to_rbs || 'untyped'
76
+ case decl
77
+ when :arg
78
+ ''
79
+ when :optarg
80
+ '?'
81
+ when :kwarg
82
+ "#{name}:"
83
+ when :kwoptarg
84
+ "?#{name}:"
85
+ when :restarg
86
+ '*'
87
+ when :kwrestarg
88
+ '**'
89
+ else
90
+ "(unknown decl: #{decl})"
91
+ end
92
+ end
93
+
94
+ # @return [String]
95
+ def type_arity_decl
96
+ arity_decl + return_type.items.count.to_s
97
+ end
98
+
99
+ def arg?
100
+ decl == :arg
101
+ end
102
+
103
+ def restarg?
104
+ decl == :restarg
105
+ end
106
+
107
+ def mandatory_positional?
108
+ decl == :arg
109
+ end
110
+
111
+ def positional?
112
+ !keyword?
113
+ end
114
+
115
+ def rest?
116
+ %i[restarg kwrestarg].include?(decl)
117
+ end
118
+
119
+ def block?
120
+ %i[block blockarg].include?(decl)
121
+ end
122
+
123
+ def to_rbs
124
+ case decl
125
+ when :optarg
126
+ "?#{super}"
127
+ when :kwarg
128
+ "#{name}: #{return_type.to_rbs}"
129
+ when :kwoptarg
130
+ "?#{name}: #{return_type.to_rbs}"
131
+ when :restarg
132
+ "*#{super}"
133
+ when :kwrestarg
134
+ "**#{super}"
135
+ else
136
+ super
137
+ end
138
+ end
139
+
140
+ # @return [String] the full name of the parameter, including any
141
+ # declarative symbols such as `*` or `:` indicating type of
142
+ # parameter. This is used in method signatures.
143
+ def full_name
144
+ case decl
145
+ when :kwarg, :kwoptarg
146
+ "#{name}:"
147
+ when :restarg
148
+ "*#{name}"
149
+ when :kwrestarg
150
+ "**#{name}"
151
+ when :block, :blockarg
152
+ "&#{name}"
153
+ else
154
+ name
155
+ end
156
+ end
157
+
158
+ def reset_generated!
159
+ @return_type = nil if param_tag
160
+ super
161
+ end
162
+
163
+ # @return [String]
164
+ def full
165
+ full_name + case decl
166
+ when :optarg
167
+ " = #{asgn_code || '?'}"
168
+ when :kwoptarg
169
+ " #{asgn_code || '?'}"
170
+ else
171
+ ''
172
+ end
173
+ end
174
+
175
+ # @sg-ignore super always sets @return_type to something
176
+ # @return [ComplexType]
177
+ def return_type
178
+ if @return_type.nil?
179
+ @return_type = ComplexType::UNDEFINED
180
+ found = param_tag
181
+ @return_type = ComplexType.try_parse(*found.types) unless found.nil? || found.types.nil?
182
+ # @sg-ignore flow sensitive typing should be able to handle redefinition
183
+ if @return_type.undefined?
184
+ case decl
185
+ when :restarg
186
+ @return_type = ComplexType.try_parse('::Array')
187
+ when :kwrestarg
188
+ @return_type = ComplexType.try_parse('::Hash')
189
+ when :blockarg
190
+ @return_type = ComplexType.try_parse('::Proc')
191
+ end
192
+ end
193
+ end
194
+ super
195
+ end
196
+
197
+ # The parameter's zero-based location in the block's signature.
198
+ #
199
+ # @sg-ignore Need to add nil check here
200
+ # @return [Integer]
201
+ def index
202
+ method_pin = closure
203
+ # @sg-ignore Need to add nil check here
204
+ method_pin.parameter_names.index(name)
205
+ end
206
+
207
+ # @param api_map [ApiMap]
208
+ def typify api_map
209
+ new_type = super
210
+ return new_type if new_type.defined?
211
+
212
+ # sniff based on param tags
213
+ new_type = closure.is_a?(Pin::Block) ? typify_block_param(api_map) : typify_method_param(api_map)
214
+
215
+ return adjust_type api_map, new_type.self_to_type(full_context) if new_type.defined?
216
+
217
+ adjust_type api_map, super.self_to_type(full_context)
218
+ end
219
+
220
+ # @param atype [ComplexType]
221
+ # @param api_map [ApiMap]
222
+ def compatible_arg? atype, api_map
223
+ # make sure we get types from up the method
224
+ # inheritance chain if we don't have them on this pin
225
+ ptype = typify api_map
226
+ return true if ptype.undefined?
227
+
228
+ return true if atype.conforms_to?(api_map,
229
+ ptype,
230
+ :method_call,
231
+ %i[allow_empty_params allow_undefined])
232
+ ptype.generic?
233
+ end
234
+
235
+ # @sg-ignore flow sensitive typing needs to handle attrs
236
+ def documentation
237
+ tag = param_tag
238
+ return '' if tag.nil? || tag.text.nil?
239
+ tag.text
240
+ end
241
+
242
+ private
243
+
244
+ def generate_complex_type
245
+ nil
246
+ end
247
+
248
+ # @return [YARD::Tags::Tag, nil]
249
+ def param_tag
250
+ # @sg-ignore Need to add nil check here
251
+ params = closure.docstring.tags(:param)
252
+ # @sg-ignore Need to add nil check here
253
+ params.each do |p|
254
+ return p if p.name == name
255
+ end
256
+ # @sg-ignore Need to add nil check here
257
+ params[index] if index && params[index] && (params[index].name.nil? || params[index].name.empty?)
258
+ end
259
+
260
+ # @param api_map [ApiMap]
261
+ # @return [ComplexType]
262
+ def typify_block_param api_map
263
+ block_pin = closure
264
+ return block_pin.typify_parameters(api_map)[index] if block_pin.is_a?(Pin::Block) && block_pin.receiver && index
265
+ ComplexType::UNDEFINED
266
+ end
267
+
268
+ # @param api_map [ApiMap]
269
+ # @return [ComplexType]
270
+ def typify_method_param api_map
271
+ # @sg-ignore Need to add nil check here
272
+ meths = api_map.get_method_stack(closure.full_context.tag, closure.name, scope: closure.scope)
273
+ # meths.shift # Ignore the first one
274
+ meths.each do |meth|
275
+ found = nil
276
+ params = meth.docstring.tags(:param) + see_reference(docstring, api_map)
277
+ params.each do |p|
278
+ next unless p.name == name
279
+ found = p
280
+ break
281
+ end
282
+ if found.nil? && !index.nil? && params[index] && (params[index].name.nil? || params[index].name.empty?)
283
+ found = params[index]
284
+ end
285
+ unless found.nil? || found.types.nil?
286
+ return ComplexType.try_parse(*found.types).qualify(api_map,
287
+ # @sg-ignore Need to add nil check here
288
+ *meth.closure.gates)
289
+ end
290
+ end
291
+ ComplexType::UNDEFINED
292
+ end
293
+
294
+ # @param heredoc [YARD::Docstring]
295
+ # @param api_map [ApiMap]
296
+ # @param skip [::Array]
297
+ #
298
+ # @return [::Array<YARD::Tags::Tag>]
299
+ def see_reference heredoc, api_map, skip = []
300
+ # This should actually be an intersection type
301
+ # @param ref [YARD::Tags::Tag, Solargraph::Yard::Tags::RefTag]
302
+ heredoc.ref_tags.each do |ref|
303
+ # @sg-ignore ref should actually be an intersection type
304
+ next unless ref.tag_name == 'param' && ref.owner
305
+ # @todo ref should actually be an intersection type
306
+ result = resolve_reference(ref.owner.to_s, api_map, skip)
307
+ return result unless result.nil?
308
+ end
309
+ []
310
+ end
311
+
312
+ # @param ref [String]
313
+ # @param api_map [ApiMap]
314
+ # @param skip [::Array]
315
+ # @return [::Array<YARD::Tags::Tag>, nil]
316
+ def resolve_reference ref, api_map, skip
317
+ return nil if skip.include?(ref)
318
+ skip.push ref
319
+ parts = ref.split(/[.#]/)
320
+ if parts.first.empty?
321
+ path = "#{namespace}#{ref}"
322
+ else
323
+ fqns = api_map.qualify(parts.first, namespace)
324
+ return nil if fqns.nil?
325
+ # @sg-ignore Need to add nil check here
326
+ path = fqns + ref[parts.first.length] + parts.last
327
+ end
328
+ pins = api_map.get_path_pins(path)
329
+ pins.each do |pin|
330
+ params = pin.docstring.tags(:param)
331
+ return params unless params.empty?
332
+ params = see_reference(pin.docstring, api_map, skip)
333
+ return params unless params.empty?
334
+ end
335
+ nil
336
+ end
337
+ end
338
+ end
339
+ end