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,444 +1,557 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- # A container for type data based on YARD type tags.
5
- #
6
- class ComplexType
7
- GENERIC_TAG_NAME = 'generic'.freeze
8
- # @!parse
9
- # include TypeMethods
10
- include Equality
11
-
12
- autoload :TypeMethods, 'solargraph/complex_type/type_methods'
13
- autoload :UniqueType, 'solargraph/complex_type/unique_type'
14
-
15
- # @param types [Array<UniqueType, ComplexType>]
16
- def initialize types = [UniqueType::UNDEFINED]
17
- # @todo @items here should not need an annotation
18
- # @type [Array<UniqueType>]
19
- items = types.flat_map(&:items).uniq(&:to_s)
20
- if items.any? { |i| i.name == 'false' } && items.any? { |i| i.name == 'true' }
21
- items.delete_if { |i| i.name == 'false' || i.name == 'true' }
22
- items.unshift(ComplexType::BOOLEAN)
23
- end
24
- items = [UniqueType::UNDEFINED] if items.any?(&:undefined?)
25
- @items = items
26
- end
27
-
28
- # @sg-ignore Fix "Not enough arguments to Module#protected"
29
- protected def equality_fields
30
- [self.class, items]
31
- end
32
-
33
- # @param api_map [ApiMap]
34
- # @param context [String]
35
- # @return [ComplexType]
36
- def qualify api_map, *gates
37
- red = reduce_object
38
- types = red.items.map do |t|
39
- next t if ['nil', 'void', 'undefined'].include?(t.name)
40
- next t if ['::Boolean'].include?(t.rooted_name)
41
- t.qualify api_map, *gates
42
- end
43
- ComplexType.new(types).reduce_object
44
- end
45
-
46
- # @param generics_to_resolve [Enumerable<String>]]
47
- # @param context_type [UniqueType, nil]
48
- # @param resolved_generic_values [Hash{String => ComplexType}] Added to as types are encountered or resolved
49
- # @return [self]
50
- def resolve_generics_from_context generics_to_resolve, context_type, resolved_generic_values: {}
51
- return self unless generic?
52
-
53
- ComplexType.new(@items.map { |i| i.resolve_generics_from_context(generics_to_resolve, context_type, resolved_generic_values: resolved_generic_values) })
54
- end
55
-
56
- # @return [UniqueType]
57
- def first
58
- @items.first
59
- end
60
-
61
- # @return [String]
62
- def to_rbs
63
- ((@items.length > 1 ? '(' : '') +
64
- @items.map(&:to_rbs).join(' | ') +
65
- (@items.length > 1 ? ')' : ''))
66
- end
67
-
68
- # @param dst [ComplexType]
69
- # @return [ComplexType]
70
- def self_to_type dst
71
- object_type_dst = dst.reduce_class_type
72
- transform do |t|
73
- next t if t.name != 'self'
74
- object_type_dst
75
- end
76
- end
77
-
78
- # @yieldparam [UniqueType]
79
- # @return [Array<UniqueType>]
80
- def map &block
81
- @items.map &block
82
- end
83
-
84
- # @yieldparam [UniqueType]
85
- # @return [Enumerable<UniqueType>]
86
- def each &block
87
- @items.each &block
88
- end
89
-
90
- # @yieldparam [UniqueType]
91
- # @return [void]
92
- # @overload each_unique_type()
93
- # @return [Enumerator<UniqueType>]
94
- def each_unique_type &block
95
- return enum_for(__method__) unless block_given?
96
-
97
- @items.each do |item|
98
- item.each_unique_type &block
99
- end
100
- end
101
-
102
- # @param atype [ComplexType] type which may be assigned to this type
103
- # @param api_map [ApiMap] The ApiMap that performs qualification
104
- def can_assign?(api_map, atype)
105
- any? { |ut| ut.can_assign?(api_map, atype) }
106
- end
107
-
108
- # @param new_name [String, nil]
109
- # @param make_rooted [Boolean, nil]
110
- # @param new_key_types [Array<ComplexType>, nil]
111
- # @param rooted [Boolean, nil]
112
- # @param new_subtypes [Array<ComplexType>, nil]
113
- # @return [self]
114
- def recreate(new_name: nil, make_rooted: nil, new_key_types: nil, new_subtypes: nil)
115
- ComplexType.new(map do |ut|
116
- ut.recreate(new_name: new_name,
117
- make_rooted: make_rooted,
118
- new_key_types: new_key_types,
119
- new_subtypes: new_subtypes)
120
- end)
121
- end
122
-
123
- # @return [Integer]
124
- def length
125
- @items.length
126
- end
127
-
128
- # @return [Array<UniqueType>]
129
- def to_a
130
- @items
131
- end
132
-
133
- # @param index [Integer]
134
- # @return [UniqueType]
135
- def [](index)
136
- @items[index]
137
- end
138
-
139
- # @return [Array<UniqueType>]
140
- def select &block
141
- @items.select &block
142
- end
143
-
144
- # @return [String]
145
- def namespace
146
- # cache this attr for high frequency call
147
- @namespace ||= method_missing(:namespace).to_s
148
- end
149
-
150
- # @return [Array<String>]
151
- def namespaces
152
- @items.map(&:namespace)
153
- end
154
-
155
- # @param name [Symbol]
156
- # @return [Object, nil]
157
- def method_missing name, *args, &block
158
- return if @items.first.nil?
159
- return @items.first.send(name, *args, &block) if respond_to_missing?(name)
160
- super
161
- end
162
-
163
- # @param name [Symbol]
164
- # @param include_private [Boolean]
165
- def respond_to_missing?(name, include_private = false)
166
- TypeMethods.public_instance_methods.include?(name) || super
167
- end
168
-
169
- def to_s
170
- map(&:tag).join(', ')
171
- end
172
-
173
- # @return [String]
174
- def tags
175
- map(&:tag).join(', ')
176
- end
177
-
178
- # @return [String]
179
- def simple_tags
180
- simplify_literals.tags
181
- end
182
-
183
- def literal?
184
- @items.any?(&:literal?)
185
- end
186
-
187
- # @return [ComplexType]
188
- def downcast_to_literal_if_possible
189
- ComplexType.new(items.map(&:downcast_to_literal_if_possible))
190
- end
191
-
192
- # @return [String]
193
- def desc
194
- rooted_tags
195
- end
196
-
197
- # @return [String]
198
- def rooted_tags
199
- map(&:rooted_tag).join(', ')
200
- end
201
-
202
- # @yieldparam [UniqueType]
203
- def all? &block
204
- @items.all? &block
205
- end
206
-
207
- # @yieldparam [UniqueType]
208
- # @yieldreturn [Boolean]
209
- # @return [Boolean]
210
- def any? &block
211
- @items.compact.any? &block
212
- end
213
-
214
- def selfy?
215
- @items.any?(&:selfy?)
216
- end
217
-
218
- def generic?
219
- any?(&:generic?)
220
- end
221
-
222
- # @return [self]
223
- def simplify_literals
224
- ComplexType.new(map(&:simplify_literals))
225
- end
226
-
227
- # @param new_name [String, nil]
228
- # @yieldparam t [UniqueType]
229
- # @yieldreturn [UniqueType]
230
- # @return [ComplexType]
231
- def transform(new_name = nil, &transform_type)
232
- raise "Please remove leading :: and set rooted with recreate() instead - #{new_name}" if new_name&.start_with?('::')
233
- ComplexType.new(map { |ut| ut.transform(new_name, &transform_type) })
234
- end
235
-
236
- # @return [self]
237
- def force_rooted
238
- transform do |t|
239
- t.recreate(make_rooted: true)
240
- end
241
- end
242
-
243
- # @param definitions [Pin::Namespace, Pin::Method]
244
- # @param context_type [ComplexType]
245
- # @return [ComplexType]
246
- def resolve_generics definitions, context_type
247
- result = @items.map { |i| i.resolve_generics(definitions, context_type) }
248
- ComplexType.new(result)
249
- end
250
-
251
- def nullable?
252
- @items.any?(&:nil_type?)
253
- end
254
-
255
- # @return [Array<ComplexType>]
256
- def all_params
257
- @items.first.all_params || []
258
- end
259
-
260
- # @return [ComplexType]
261
- def reduce_class_type
262
- new_items = items.flat_map do |type|
263
- next type unless ['Module', 'Class'].include?(type.name)
264
- next type if type.all_params.empty?
265
-
266
- type.all_params
267
- end
268
- ComplexType.new(new_items)
269
- end
270
-
271
- # every type and subtype in this union have been resolved to be
272
- # fully qualified
273
- def all_rooted?
274
- all?(&:all_rooted?)
275
- end
276
-
277
- # every top-level type has resolved to be fully qualified; see
278
- # #all_rooted? to check their subtypes as well
279
- def rooted?
280
- all?(&:rooted?)
281
- end
282
-
283
- attr_reader :items
284
-
285
- def rooted?
286
- @items.all?(&:rooted?)
287
- end
288
-
289
- protected
290
-
291
- # @return [ComplexType]
292
- def reduce_object
293
- new_items = items.flat_map do |ut|
294
- next [ut] if ut.name != 'Object' || ut.subtypes.empty?
295
- ut.subtypes
296
- end
297
- ComplexType.new(new_items)
298
- end
299
-
300
- def bottom?
301
- @items.all?(&:bot?)
302
- end
303
-
304
- class << self
305
- # Parse type strings into a ComplexType.
306
- #
307
- # @example
308
- # ComplexType.parse 'String', 'Foo', 'nil' #=> [String, Foo, nil]
309
- #
310
- # @note
311
- # The `partial` parameter is used to indicate that the method is
312
- # receiving a string that will be used inside another ComplexType.
313
- # It returns arrays of ComplexTypes instead of a single cohesive one.
314
- # Consumers should not need to use this parameter; it should only be
315
- # used internally.
316
- #
317
- # @param strings [Array<String>] The type definitions to parse
318
- # @return [ComplexType]
319
- # # @overload parse(*strings, partial: false)
320
- # # @todo Need ability to use a literal true as a type below
321
- # # @param partial [Boolean] True if the string is part of a another type
322
- # # @return [Array<UniqueType>]
323
- # @todo To be able to select the right signature above,
324
- # Chain::Call needs to know the decl type (:arg, :optarg,
325
- # :kwarg, etc) of the arguments given, instead of just having
326
- # an array of Chains as the arguments.
327
- def parse *strings, partial: false
328
- # @type [Hash{Array<String> => ComplexType}]
329
- @cache ||= {}
330
- unless partial
331
- cached = @cache[strings]
332
- return cached unless cached.nil?
333
- end
334
- types = []
335
- key_types = nil
336
- strings.each do |type_string|
337
- point_stack = 0
338
- curly_stack = 0
339
- paren_stack = 0
340
- base = String.new
341
- subtype_string = String.new
342
- # @param char [String]
343
- type_string&.each_char do |char|
344
- if char == '='
345
- #raise ComplexTypeError, "Invalid = in type #{type_string}" unless curly_stack > 0
346
- elsif char == '<'
347
- point_stack += 1
348
- elsif char == '>'
349
- if subtype_string.end_with?('=') && curly_stack > 0
350
- subtype_string += char
351
- elsif base.end_with?('=')
352
- raise ComplexTypeError, "Invalid hash thing" unless key_types.nil?
353
- # types.push ComplexType.new([UniqueType.new(base[0..-2].strip)])
354
- types.push UniqueType.parse(base[0..-2].strip, subtype_string)
355
- # @todo this should either expand key_type's type
356
- # automatically or complain about not being
357
- # compatible with key_type's type in type checking
358
- key_types = types
359
- types = []
360
- base.clear
361
- subtype_string.clear
362
- next
363
- else
364
- raise ComplexTypeError, "Invalid close in type #{type_string}" if point_stack == 0
365
- point_stack -= 1
366
- subtype_string += char
367
- end
368
- next
369
- elsif char == '{'
370
- curly_stack += 1
371
- elsif char == '}'
372
- curly_stack -= 1
373
- subtype_string += char
374
- raise ComplexTypeError, "Invalid close in type #{type_string}" if curly_stack < 0
375
- next
376
- elsif char == '('
377
- paren_stack += 1
378
- elsif char == ')'
379
- paren_stack -= 1
380
- subtype_string += char
381
- raise ComplexTypeError, "Invalid close in type #{type_string}" if paren_stack < 0
382
- next
383
- elsif char == ',' && point_stack == 0 && curly_stack == 0 && paren_stack == 0
384
- # types.push ComplexType.new([UniqueType.new(base.strip, subtype_string.strip)])
385
- types.push UniqueType.parse(base.strip, subtype_string.strip)
386
- base.clear
387
- subtype_string.clear
388
- next
389
- end
390
- if point_stack == 0 && curly_stack == 0 && paren_stack == 0
391
- base.concat char
392
- else
393
- subtype_string.concat char
394
- end
395
- end
396
- raise ComplexTypeError, "Unclosed subtype in #{type_string}" if point_stack != 0 || curly_stack != 0 || paren_stack != 0
397
- # types.push ComplexType.new([UniqueType.new(base, subtype_string)])
398
- types.push UniqueType.parse(base.strip, subtype_string.strip)
399
- end
400
- unless key_types.nil?
401
- raise ComplexTypeError, "Invalid use of key/value parameters" unless partial
402
- return key_types if types.empty?
403
- return [key_types, types]
404
- end
405
- result = partial ? types : ComplexType.new(types)
406
- @cache[strings] = result unless partial
407
- result
408
- end
409
-
410
- # @param strings [Array<String>]
411
- # @return [ComplexType]
412
- def try_parse *strings
413
- parse *strings
414
- rescue ComplexTypeError => e
415
- Solargraph.logger.info "Error parsing complex type `#{strings.join(', ')}`: #{e.message}"
416
- ComplexType::UNDEFINED
417
- end
418
- end
419
-
420
- VOID = ComplexType.parse('void')
421
- UNDEFINED = ComplexType.parse('undefined')
422
- SYMBOL = ComplexType.parse('::Symbol')
423
- ROOT = ComplexType.parse('::Class<>')
424
- NIL = ComplexType.parse('nil')
425
- SELF = ComplexType.parse('self')
426
- BOOLEAN = ComplexType.parse('::Boolean')
427
- BOT = ComplexType.parse('bot')
428
-
429
- private
430
-
431
- # @todo This is a quick and dirty hack that forces `self` keywords
432
- # to reference an instance of their class and never the class itself.
433
- # This behavior may change depending on which result is expected
434
- # from YARD conventions. See https://github.com/lsegal/yard/issues/1257
435
- # @param dst [String]
436
- # @return [String]
437
- def reduce_class dst
438
- while dst =~ /^(Class|Module)\<(.*?)\>$/
439
- dst = dst.sub(/^(Class|Module)\</, '').sub(/\>$/, '')
440
- end
441
- dst
442
- end
443
- end
444
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ # A container for type data based on YARD type tags.
5
+ #
6
+ class ComplexType
7
+ GENERIC_TAG_NAME = 'generic'
8
+ # @!parse
9
+ # include TypeMethods
10
+ include Equality
11
+
12
+ autoload :Conformance, 'solargraph/complex_type/conformance'
13
+ autoload :TypeMethods, 'solargraph/complex_type/type_methods'
14
+ autoload :UniqueType, 'solargraph/complex_type/unique_type'
15
+
16
+ # @param types [Array<UniqueType, ComplexType>]
17
+ def initialize types = [UniqueType::UNDEFINED]
18
+ # @todo @items here should not need an annotation
19
+ # @type [Array<UniqueType>]
20
+ items = types.flat_map(&:items).uniq(&:to_s)
21
+ if items.any? { |i| i.name == 'false' } && items.any? { |i| i.name == 'true' }
22
+ items.delete_if { |i| %w[false true].include?(i.name) }
23
+ items.unshift(UniqueType::BOOLEAN)
24
+ end
25
+ # @type [Array<UniqueType>]
26
+ items = [UniqueType::UNDEFINED] if items.any?(&:undefined?)
27
+ # @todo shouldn't need this cast - if statement above adds an 'Array' type
28
+ # @type [Array<UniqueType>]
29
+ @items = items
30
+ end
31
+
32
+ # @param api_map [ApiMap]
33
+ # @param gates [Array<String>]
34
+ #
35
+ # @return [ComplexType]
36
+ def qualify api_map, *gates
37
+ red = reduce_object
38
+ types = red.items.map do |t|
39
+ next t if %w[nil void undefined].include?(t.name)
40
+ next t if ['::Boolean'].include?(t.rooted_name)
41
+ api_map.unalias(t.name) || t.qualify(api_map, *gates)
42
+ end
43
+ ComplexType.new(types).reduce_object
44
+ end
45
+
46
+ # @param generics_to_resolve [Enumerable<String>]]
47
+ # @param context_type [ComplexType, ComplexType::UniqueType, nil]
48
+ # @param resolved_generic_values [Hash{String => ComplexType}] Added to as types are encountered or resolved
49
+ # @return [self]
50
+ def resolve_generics_from_context generics_to_resolve, context_type, resolved_generic_values: {}
51
+ return self unless generic?
52
+
53
+ ComplexType.new(@items.map do |i|
54
+ i.resolve_generics_from_context(generics_to_resolve, context_type,
55
+ resolved_generic_values: resolved_generic_values)
56
+ end)
57
+ end
58
+
59
+ # @return [UniqueType]
60
+ def first
61
+ @items.first
62
+ end
63
+
64
+ # @return [String]
65
+ def to_rbs
66
+ ((@items.length > 1 ? '(' : '') +
67
+ @items.map(&:to_rbs).join(' | ') +
68
+ (@items.length > 1 ? ')' : ''))
69
+ end
70
+
71
+ # @param dst [ComplexType, ComplexType::UniqueType]
72
+ # @return [ComplexType]
73
+ def self_to_type dst
74
+ object_type_dst = dst.reduce_class_type
75
+ transform do |t|
76
+ next t if t.name != 'self'
77
+ object_type_dst
78
+ end
79
+ end
80
+
81
+ # @yieldparam [UniqueType]
82
+ # @yieldreturn [UniqueType]
83
+ # @return [Array<UniqueType>]
84
+ # @sg-ignore Declared return type
85
+ # ::Array<::Solargraph::ComplexType::UniqueType> does not match
86
+ # inferred type ::Array<::Proc> for Solargraph::ComplexType#map
87
+ def map &block
88
+ @items.map(&block)
89
+ end
90
+
91
+ # @yieldparam [UniqueType]
92
+ # @return [Enumerable<UniqueType>]
93
+ def each &block
94
+ @items.each(&block)
95
+ end
96
+
97
+ # @yieldparam [UniqueType]
98
+ # @return [void]
99
+ # @overload each_unique_type()
100
+ # @return [Enumerator<UniqueType>]
101
+ def each_unique_type &block
102
+ return enum_for(__method__) unless block_given?
103
+
104
+ @items.each do |item|
105
+ item.each_unique_type(&block)
106
+ end
107
+ end
108
+
109
+ # @param new_name [String, nil]
110
+ # @param make_rooted [Boolean, nil]
111
+ # @param new_key_types [Array<ComplexType>, nil]
112
+ # @param make_rooted [Boolean, nil]
113
+ # @param new_subtypes [Array<ComplexType>, nil]
114
+ # @return [self]
115
+ def recreate new_name: nil, make_rooted: nil, new_key_types: nil, new_subtypes: nil
116
+ ComplexType.new(map do |ut|
117
+ ut.recreate(new_name: new_name,
118
+ make_rooted: make_rooted,
119
+ new_key_types: new_key_types,
120
+ new_subtypes: new_subtypes)
121
+ end)
122
+ end
123
+
124
+ # @return [Integer]
125
+ def length
126
+ @items.length
127
+ end
128
+
129
+ # @return [Array<UniqueType>]
130
+ def to_a
131
+ @items
132
+ end
133
+
134
+ # @param index [Integer]
135
+ # @return [UniqueType]
136
+ def [] index
137
+ @items[index]
138
+ end
139
+
140
+ # @return [Array<UniqueType>]
141
+ def select &block
142
+ @items.select(&block)
143
+ end
144
+
145
+ # @return [String]
146
+ def namespace
147
+ # cache this attr for high frequency call
148
+ @namespace ||= method_missing(:namespace).to_s
149
+ end
150
+
151
+ # @return [Array<String>]
152
+ def namespaces
153
+ @items.map(&:namespace)
154
+ end
155
+
156
+ # @param name [Symbol]
157
+ #
158
+ # @return [Object, nil]
159
+ # @param [Array<Object>] args
160
+ def method_missing name, *args, &block
161
+ return if @items.first.nil?
162
+ return @items.first.send(name, *args, &block) if respond_to_missing?(name)
163
+ super
164
+ end
165
+
166
+ # @param name [Symbol]
167
+ # @param include_private [Boolean]
168
+ def respond_to_missing? name, include_private = false
169
+ TypeMethods.public_instance_methods.include?(name) || super
170
+ end
171
+
172
+ def to_s
173
+ map(&:tag).join(', ')
174
+ end
175
+
176
+ # @return [String]
177
+ def tags
178
+ map(&:tag).join(', ')
179
+ end
180
+
181
+ # @return [String]
182
+ def simple_tags
183
+ simplify_literals.tags
184
+ end
185
+
186
+ def literal?
187
+ @items.any?(&:literal?)
188
+ end
189
+
190
+ # @return [ComplexType]
191
+ def downcast_to_literal_if_possible
192
+ ComplexType.new(items.map(&:downcast_to_literal_if_possible))
193
+ end
194
+
195
+ # @return [String]
196
+ def desc
197
+ rooted_tags
198
+ end
199
+
200
+ # @param api_map [ApiMap]
201
+ # @param expected [ComplexType, ComplexType::UniqueType]
202
+ # @param situation [:method_call, :return_type, :assignment]
203
+ # @param rules [Array<:allow_subtype_skew, :allow_empty_params, :allow_reverse_match, :allow_any_match, :allow_undefined, :allow_unresolved_generic, :allow_unmatched_interface>]
204
+ #
205
+ # allow_subtype_skew: if not provided, check if any subtypes of
206
+ # the expected type match the inferred type
207
+ #
208
+ # allow_reverse_match: check if any subtypes
209
+ # of the expected type match the inferred type
210
+ #
211
+ # allow_empty_params: allow a general inferred type without
212
+ # parameters to conform to a more specific expected type
213
+ #
214
+ # allow_any_match: any unique type matched in the inferred
215
+ # qualifies as a match
216
+ #
217
+ # allow_undefined: treat undefined as a wildcard that matches
218
+ # anything
219
+ #
220
+ # @param variance [:invariant, :covariant, :contravariant]
221
+ # @return [Boolean]
222
+ def conforms_to? api_map, expected,
223
+ situation,
224
+ rules = [],
225
+ variance: erased_variance(situation)
226
+ expected = expected.downcast_to_literal_if_possible
227
+ inferred = downcast_to_literal_if_possible
228
+
229
+ return duck_types_match?(api_map, expected, inferred) if expected.duck_type?
230
+
231
+ if rules.include? :allow_any_match
232
+ inferred.any? do |inf|
233
+ inf.conforms_to?(api_map, expected, situation, rules,
234
+ variance: variance)
235
+ end
236
+ else
237
+ inferred.all? do |inf|
238
+ inf.conforms_to?(api_map, expected, situation, rules,
239
+ variance: variance)
240
+ end
241
+ end
242
+ end
243
+
244
+ # @param api_map [ApiMap]
245
+ # @param expected [ComplexType, UniqueType]
246
+ # @param inferred [ComplexType, UniqueType]
247
+ # @return [Boolean]
248
+ def duck_types_match? api_map, expected, inferred
249
+ raise ArgumentError, 'Expected type must be duck type' unless expected.duck_type?
250
+ expected.each do |exp|
251
+ next unless exp.duck_type?
252
+ quack = exp.to_s[1..]
253
+ # @sg-ignore Need to add nil check here
254
+ return false if api_map.get_method_stack(inferred.namespace, quack, scope: inferred.scope).empty?
255
+ end
256
+ true
257
+ end
258
+
259
+ # @return [String]
260
+ def rooted_tags
261
+ map(&:rooted_tag).join(', ')
262
+ end
263
+
264
+ # @yieldparam [UniqueType]
265
+ def all? &block
266
+ @items.all?(&block)
267
+ end
268
+
269
+ # @yieldparam [UniqueType]
270
+ # @yieldreturn [Boolean]
271
+ # @return [Boolean]
272
+ def any? &block
273
+ @items.compact.any?(&block)
274
+ end
275
+
276
+ def selfy?
277
+ @items.any?(&:selfy?)
278
+ end
279
+
280
+ def generic?
281
+ any?(&:generic?)
282
+ end
283
+
284
+ # @return [self]
285
+ def simplify_literals
286
+ ComplexType.new(map(&:simplify_literals))
287
+ end
288
+
289
+ # @param new_name [String, nil]
290
+ # @yieldparam t [UniqueType]
291
+ # @yieldreturn [UniqueType]
292
+ # @return [ComplexType]
293
+ def transform new_name = nil, &transform_type
294
+ if new_name&.start_with?('::')
295
+ raise "Please remove leading :: and set rooted with recreate() instead - #{new_name}"
296
+ end
297
+ ComplexType.new(map { |ut| ut.transform(new_name, &transform_type) })
298
+ end
299
+
300
+ # @return [self]
301
+ def force_rooted
302
+ transform do |t|
303
+ t.recreate(make_rooted: true)
304
+ end
305
+ end
306
+
307
+ # @param definitions [Pin::Namespace, Pin::Method]
308
+ # @param context_type [ComplexType]
309
+ # @return [ComplexType]
310
+ def resolve_generics definitions, context_type
311
+ result = @items.map { |i| i.resolve_generics(definitions, context_type) }
312
+ ComplexType.new(result)
313
+ end
314
+
315
+ def nullable?
316
+ @items.any?(&:nil_type?)
317
+ end
318
+
319
+ # @return [ComplexType]
320
+ def without_nil
321
+ new_items = @items.reject(&:nil_type?)
322
+ return ComplexType::UNDEFINED if new_items.empty?
323
+ ComplexType.new(new_items)
324
+ end
325
+
326
+ # @return [Array<ComplexType>]
327
+ def all_params
328
+ @items.first.all_params || []
329
+ end
330
+
331
+ # @return [ComplexType]
332
+ def reduce_class_type
333
+ new_items = items.flat_map do |type|
334
+ next type unless %w[Module Class].include?(type.name)
335
+ next type if type.all_params.empty?
336
+
337
+ type.all_params
338
+ end
339
+ ComplexType.new(new_items)
340
+ end
341
+
342
+ # every type and subtype in this union have been resolved to be
343
+ # fully qualified
344
+ def all_rooted?
345
+ all?(&:all_rooted?)
346
+ end
347
+
348
+ # @param other [ComplexType, UniqueType]
349
+ def erased_version_of? other
350
+ return false if items.length != 1 || other.items.length != 1
351
+
352
+ @items.first.erased_version_of?(other.items.first)
353
+ end
354
+
355
+ # every top-level type has resolved to be fully qualified; see
356
+ # #all_rooted? to check their subtypes as well
357
+ def rooted?
358
+ all?(&:rooted?)
359
+ end
360
+
361
+ attr_reader :items
362
+
363
+ # @param exclude_types [ComplexType, nil]
364
+ # @param api_map [ApiMap]
365
+ # @return [ComplexType, self]
366
+ def exclude exclude_types, api_map
367
+ return self if exclude_types.nil?
368
+
369
+ types = items - exclude_types.items
370
+ types = [ComplexType::UniqueType::UNDEFINED] if types.empty?
371
+ ComplexType.new(types)
372
+ end
373
+
374
+ # @see https://en.wikipedia.org/wiki/Intersection_type
375
+ #
376
+ # @param intersection_type [ComplexType, ComplexType::UniqueType, nil]
377
+ # @param api_map [ApiMap]
378
+ # @return [self, ComplexType::UniqueType]
379
+ def intersect_with intersection_type, api_map
380
+ return self if intersection_type.nil?
381
+ return intersection_type if undefined?
382
+ types = []
383
+ # try to find common types via conformance
384
+ items.each do |ut|
385
+ intersection_type.each do |int_type|
386
+ if int_type.conforms_to?(api_map, ut, :assignment)
387
+ types << int_type
388
+ elsif ut.conforms_to?(api_map, int_type, :assignment)
389
+ types << ut
390
+ end
391
+ end
392
+ end
393
+ types = [ComplexType::UniqueType::UNDEFINED] if types.empty?
394
+ ComplexType.new(types)
395
+ end
396
+
397
+ protected
398
+
399
+ def equality_fields
400
+ [self.class, items]
401
+ end
402
+
403
+ # @return [ComplexType]
404
+ def reduce_object
405
+ new_items = items.flat_map do |ut|
406
+ next [ut] if ut.name != 'Object' || ut.subtypes.empty?
407
+ ut.subtypes
408
+ end
409
+ ComplexType.new(new_items)
410
+ end
411
+
412
+ def bottom?
413
+ @items.all?(&:bot?)
414
+ end
415
+
416
+ class << self
417
+ # Parse type strings into a ComplexType.
418
+ #
419
+ # @example
420
+ # ComplexType.parse 'String', 'Foo', 'nil' #=> [String, Foo, nil]
421
+ #
422
+ # @param partial [Boolean] if true, method is receiving a string
423
+ # that will be used inside another ComplexType. It returns
424
+ # arrays of ComplexTypes instead of a single cohesive one.
425
+ # Consumers should not need to use this parameter; it should
426
+ # only be used internally.
427
+ # @param strings [Array<String>] The type definitions to parse
428
+ # @return [ComplexType]
429
+ # # @overload parse(*strings, partial: false)
430
+ # # @todo Need ability to use a literal true as a type below
431
+ # # @param partial [Boolean] True if the string is part of a another type
432
+ # # @return [Array<UniqueType>]
433
+ # @sg-ignore To be able to select the right signature above,
434
+ # Chain::Call needs to know the decl type (:arg, :optarg,
435
+ # :kwarg, etc) of the arguments given, instead of just having
436
+ # an array of Chains as the arguments.
437
+ def parse *strings, partial: false
438
+ # @type [Hash{Array<String> => ComplexType, Array<ComplexType::UniqueType>}]
439
+ @cache ||= {}
440
+ unless partial
441
+ cached = @cache[strings]
442
+ return cached unless cached.nil?
443
+ end
444
+ # @types [Array<ComplexType::UniqueType>]
445
+ types = []
446
+ key_types = nil
447
+ strings.each do |type_string|
448
+ point_stack = 0
449
+ curly_stack = 0
450
+ paren_stack = 0
451
+ base = String.new
452
+ subtype_string = String.new
453
+ # @param char [String]
454
+ type_string&.each_char do |char|
455
+ if char == '='
456
+ # raise ComplexTypeError, "Invalid = in type #{type_string}" unless curly_stack > 0
457
+ elsif char == '<'
458
+ point_stack += 1
459
+ elsif char == '>'
460
+ if subtype_string.end_with?('=') && curly_stack.positive?
461
+ subtype_string += char
462
+ elsif base.end_with?('=')
463
+ raise ComplexTypeError, 'Invalid hash thing' unless key_types.nil?
464
+ # types.push ComplexType.new([UniqueType.new(base[0..-2].strip)])
465
+ # @sg-ignore Need to add nil check here
466
+ types.push UniqueType.parse(base[0..-2].strip, subtype_string)
467
+ # @todo this should either expand key_type's type
468
+ # automatically or complain about not being
469
+ # compatible with key_type's type in type checking
470
+ key_types = types
471
+ types = []
472
+ base.clear
473
+ subtype_string.clear
474
+ next
475
+ else
476
+ raise ComplexTypeError, "Invalid close in type #{type_string}" if point_stack.zero?
477
+ point_stack -= 1
478
+ subtype_string += char
479
+ end
480
+ next
481
+ elsif char == '{'
482
+ curly_stack += 1
483
+ elsif char == '}'
484
+ curly_stack -= 1
485
+ subtype_string += char
486
+ raise ComplexTypeError, "Invalid close in type #{type_string}" if curly_stack.negative?
487
+ next
488
+ elsif char == '('
489
+ paren_stack += 1
490
+ elsif char == ')'
491
+ paren_stack -= 1
492
+ subtype_string += char
493
+ raise ComplexTypeError, "Invalid close in type #{type_string}" if paren_stack.negative?
494
+ next
495
+ elsif char == ',' && point_stack.zero? && curly_stack.zero? && paren_stack.zero?
496
+ # types.push ComplexType.new([UniqueType.new(base.strip, subtype_string.strip)])
497
+ types.push UniqueType.parse(base.strip, subtype_string.strip)
498
+ base.clear
499
+ subtype_string.clear
500
+ next
501
+ end
502
+ if point_stack.zero? && curly_stack.zero? && paren_stack.zero?
503
+ base.concat char
504
+ else
505
+ subtype_string.concat char
506
+ end
507
+ end
508
+ if point_stack != 0 || curly_stack != 0 || paren_stack != 0
509
+ raise ComplexTypeError,
510
+ "Unclosed subtype in #{type_string}"
511
+ end
512
+ # types.push ComplexType.new([UniqueType.new(base, subtype_string)])
513
+ types.push UniqueType.parse(base.strip, subtype_string.strip)
514
+ end
515
+ unless key_types.nil?
516
+ raise ComplexTypeError, 'Invalid use of key/value parameters' unless partial
517
+ return key_types if types.empty?
518
+ return [key_types, types]
519
+ end
520
+ result = partial ? types : ComplexType.new(types)
521
+ @cache[strings] = result unless partial
522
+ result
523
+ end
524
+
525
+ # @param strings [Array<String>]
526
+ # @return [ComplexType]
527
+ def try_parse *strings
528
+ parse(*strings)
529
+ rescue ComplexTypeError => e
530
+ Solargraph.logger.info "Error parsing complex type `#{strings.join(', ')}`: #{e.message}"
531
+ ComplexType::UNDEFINED
532
+ end
533
+ end
534
+
535
+ VOID = ComplexType.parse('void')
536
+ UNDEFINED = ComplexType.parse('undefined')
537
+ SYMBOL = ComplexType.parse('::Symbol')
538
+ ROOT = ComplexType.parse('::Class<>')
539
+ NIL = ComplexType.parse('nil')
540
+ SELF = ComplexType.parse('self')
541
+ BOOLEAN = ComplexType.parse('::Boolean')
542
+ BOT = ComplexType.parse('bot')
543
+
544
+ private
545
+
546
+ # @todo This is a quick and dirty hack that forces `self` keywords
547
+ # to reference an instance of their class and never the class itself.
548
+ # This behavior may change depending on which result is expected
549
+ # from YARD conventions. See https://github.com/lsegal/yard/issues/1257
550
+ # @param dst [String]
551
+ # @return [String]
552
+ def reduce_class dst
553
+ dst = dst.sub(/^(Class|Module)</, '').sub(/>$/, '') while dst =~ /^(Class|Module)<(.*?)>$/
554
+ dst
555
+ end
556
+ end
557
+ end