solargraph 0.54.4 → 0.58.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 (238) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +2 -0
  3. data/.github/workflows/linting.yml +127 -0
  4. data/.github/workflows/plugins.yml +185 -6
  5. data/.github/workflows/rspec.yml +55 -5
  6. data/.github/workflows/typecheck.yml +8 -3
  7. data/.gitignore +8 -0
  8. data/.overcommit.yml +72 -0
  9. data/.rspec +1 -0
  10. data/.rubocop.yml +66 -0
  11. data/.rubocop_todo.yml +1279 -0
  12. data/.yardopts +1 -0
  13. data/CHANGELOG.md +143 -0
  14. data/README.md +20 -6
  15. data/Rakefile +125 -13
  16. data/bin/solargraph +3 -0
  17. data/lib/solargraph/api_map/cache.rb +110 -109
  18. data/lib/solargraph/api_map/constants.rb +279 -0
  19. data/lib/solargraph/api_map/index.rb +193 -167
  20. data/lib/solargraph/api_map/source_to_yard.rb +97 -88
  21. data/lib/solargraph/api_map/store.rb +384 -241
  22. data/lib/solargraph/api_map.rb +945 -875
  23. data/lib/solargraph/bench.rb +45 -28
  24. data/lib/solargraph/complex_type/type_methods.rb +228 -217
  25. data/lib/solargraph/complex_type/unique_type.rb +482 -386
  26. data/lib/solargraph/complex_type.rb +444 -394
  27. data/lib/solargraph/convention/active_support_concern.rb +111 -0
  28. data/lib/solargraph/convention/base.rb +20 -3
  29. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -0
  30. data/lib/solargraph/convention/data_definition/data_definition_node.rb +91 -0
  31. data/lib/solargraph/convention/data_definition.rb +105 -0
  32. data/lib/solargraph/convention/gemfile.rb +15 -15
  33. data/lib/solargraph/convention/gemspec.rb +23 -22
  34. data/lib/solargraph/convention/rakefile.rb +17 -17
  35. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +61 -0
  36. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +102 -0
  37. data/lib/solargraph/convention/struct_definition.rb +164 -0
  38. data/lib/solargraph/convention.rb +78 -47
  39. data/lib/solargraph/converters/dd.rb +17 -17
  40. data/lib/solargraph/converters/dl.rb +15 -15
  41. data/lib/solargraph/converters/dt.rb +15 -15
  42. data/lib/solargraph/converters/misc.rb +1 -1
  43. data/lib/solargraph/diagnostics/require_not_found.rb +53 -53
  44. data/lib/solargraph/diagnostics/rubocop.rb +118 -113
  45. data/lib/solargraph/diagnostics/rubocop_helpers.rb +68 -66
  46. data/lib/solargraph/diagnostics/type_check.rb +55 -55
  47. data/lib/solargraph/diagnostics/update_errors.rb +41 -41
  48. data/lib/solargraph/doc_map.rb +439 -188
  49. data/lib/solargraph/environ.rb +9 -2
  50. data/lib/solargraph/equality.rb +34 -33
  51. data/lib/solargraph/gem_pins.rb +98 -72
  52. data/lib/solargraph/language_server/error_codes.rb +20 -20
  53. data/lib/solargraph/language_server/host/diagnoser.rb +89 -89
  54. data/lib/solargraph/language_server/host/dispatch.rb +130 -128
  55. data/lib/solargraph/language_server/host/message_worker.rb +112 -106
  56. data/lib/solargraph/language_server/host/sources.rb +99 -99
  57. data/lib/solargraph/language_server/host.rb +878 -861
  58. data/lib/solargraph/language_server/message/base.rb +97 -96
  59. data/lib/solargraph/language_server/message/client/register_capability.rb +15 -15
  60. data/lib/solargraph/language_server/message/completion_item/resolve.rb +60 -60
  61. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +114 -112
  62. data/lib/solargraph/language_server/message/extended/document.rb +23 -20
  63. data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -32
  64. data/lib/solargraph/language_server/message/extended/download_core.rb +19 -19
  65. data/lib/solargraph/language_server/message/extended/search.rb +20 -20
  66. data/lib/solargraph/language_server/message/initialize.rb +191 -191
  67. data/lib/solargraph/language_server/message/text_document/completion.rb +56 -56
  68. data/lib/solargraph/language_server/message/text_document/definition.rb +40 -38
  69. data/lib/solargraph/language_server/message/text_document/document_highlight.rb +16 -16
  70. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +26 -26
  71. data/lib/solargraph/language_server/message/text_document/formatting.rb +148 -131
  72. data/lib/solargraph/language_server/message/text_document/hover.rb +58 -58
  73. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +11 -11
  74. data/lib/solargraph/language_server/message/text_document/references.rb +16 -16
  75. data/lib/solargraph/language_server/message/text_document/rename.rb +19 -19
  76. data/lib/solargraph/language_server/message/text_document/signature_help.rb +24 -24
  77. data/lib/solargraph/language_server/message/text_document/type_definition.rb +25 -24
  78. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +35 -35
  79. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +40 -40
  80. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +26 -24
  81. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +23 -23
  82. data/lib/solargraph/language_server/message.rb +94 -94
  83. data/lib/solargraph/language_server/progress.rb +8 -0
  84. data/lib/solargraph/language_server/request.rb +27 -24
  85. data/lib/solargraph/language_server/transport/data_reader.rb +74 -74
  86. data/lib/solargraph/language_server/uri_helpers.rb +49 -49
  87. data/lib/solargraph/library.rb +683 -662
  88. data/lib/solargraph/location.rb +82 -58
  89. data/lib/solargraph/logging.rb +37 -27
  90. data/lib/solargraph/page.rb +92 -89
  91. data/lib/solargraph/parser/comment_ripper.rb +69 -56
  92. data/lib/solargraph/parser/flow_sensitive_typing.rb +255 -0
  93. data/lib/solargraph/parser/node_processor/base.rb +92 -87
  94. data/lib/solargraph/parser/node_processor.rb +62 -45
  95. data/lib/solargraph/parser/parser_gem/class_methods.rb +149 -157
  96. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +19 -18
  97. data/lib/solargraph/parser/parser_gem/node_chainer.rb +166 -164
  98. data/lib/solargraph/parser/parser_gem/node_methods.rb +486 -495
  99. data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +2 -1
  100. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +22 -0
  101. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +59 -57
  102. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +15 -15
  103. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +46 -43
  104. data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +2 -1
  105. data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +2 -1
  106. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +53 -50
  107. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +37 -36
  108. data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +2 -1
  109. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +23 -0
  110. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +40 -38
  111. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +29 -28
  112. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +59 -53
  113. data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +8 -7
  114. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +98 -0
  115. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +17 -16
  116. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +38 -36
  117. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +52 -42
  118. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +291 -259
  119. data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +3 -1
  120. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -0
  121. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +29 -0
  122. data/lib/solargraph/parser/parser_gem/node_processors.rb +70 -56
  123. data/lib/solargraph/parser/parser_gem.rb +12 -12
  124. data/lib/solargraph/parser/region.rb +69 -66
  125. data/lib/solargraph/parser/snippet.rb +17 -15
  126. data/lib/solargraph/parser.rb +23 -22
  127. data/lib/solargraph/pin/base.rb +729 -378
  128. data/lib/solargraph/pin/base_variable.rb +126 -118
  129. data/lib/solargraph/pin/block.rb +104 -101
  130. data/lib/solargraph/pin/breakable.rb +9 -0
  131. data/lib/solargraph/pin/callable.rb +231 -147
  132. data/lib/solargraph/pin/closure.rb +72 -57
  133. data/lib/solargraph/pin/common.rb +79 -70
  134. data/lib/solargraph/pin/constant.rb +45 -43
  135. data/lib/solargraph/pin/conversions.rb +123 -123
  136. data/lib/solargraph/pin/delegated_method.rb +120 -101
  137. data/lib/solargraph/pin/documenting.rb +114 -98
  138. data/lib/solargraph/pin/instance_variable.rb +34 -34
  139. data/lib/solargraph/pin/keyword.rb +20 -15
  140. data/lib/solargraph/pin/local_variable.rb +75 -67
  141. data/lib/solargraph/pin/method.rb +672 -527
  142. data/lib/solargraph/pin/method_alias.rb +34 -31
  143. data/lib/solargraph/pin/namespace.rb +115 -107
  144. data/lib/solargraph/pin/parameter.rb +275 -212
  145. data/lib/solargraph/pin/proxy_type.rb +39 -29
  146. data/lib/solargraph/pin/reference/override.rb +47 -29
  147. data/lib/solargraph/pin/reference/require.rb +2 -2
  148. data/lib/solargraph/pin/reference/superclass.rb +15 -10
  149. data/lib/solargraph/pin/reference.rb +39 -22
  150. data/lib/solargraph/pin/search.rb +61 -56
  151. data/lib/solargraph/pin/signature.rb +61 -17
  152. data/lib/solargraph/pin/singleton.rb +1 -1
  153. data/lib/solargraph/pin/symbol.rb +53 -47
  154. data/lib/solargraph/pin/until.rb +18 -0
  155. data/lib/solargraph/pin/while.rb +18 -0
  156. data/lib/solargraph/pin.rb +44 -41
  157. data/lib/solargraph/pin_cache.rb +245 -0
  158. data/lib/solargraph/position.rb +132 -107
  159. data/lib/solargraph/range.rb +112 -98
  160. data/lib/solargraph/rbs_map/conversions.rb +823 -646
  161. data/lib/solargraph/rbs_map/core_fills.rb +84 -50
  162. data/lib/solargraph/rbs_map/core_map.rb +58 -28
  163. data/lib/solargraph/rbs_map/stdlib_map.rb +43 -33
  164. data/lib/solargraph/rbs_map.rb +163 -93
  165. data/lib/solargraph/server_methods.rb +16 -16
  166. data/lib/solargraph/shell.rb +363 -269
  167. data/lib/solargraph/source/chain/array.rb +37 -33
  168. data/lib/solargraph/source/chain/block_symbol.rb +1 -1
  169. data/lib/solargraph/source/chain/block_variable.rb +1 -1
  170. data/lib/solargraph/source/chain/call.rb +337 -303
  171. data/lib/solargraph/source/chain/class_variable.rb +13 -13
  172. data/lib/solargraph/source/chain/constant.rb +26 -89
  173. data/lib/solargraph/source/chain/global_variable.rb +13 -13
  174. data/lib/solargraph/source/chain/hash.rb +34 -33
  175. data/lib/solargraph/source/chain/head.rb +1 -1
  176. data/lib/solargraph/source/chain/if.rb +28 -28
  177. data/lib/solargraph/source/chain/instance_variable.rb +13 -13
  178. data/lib/solargraph/source/chain/link.rb +109 -98
  179. data/lib/solargraph/source/chain/literal.rb +48 -28
  180. data/lib/solargraph/source/chain/or.rb +23 -23
  181. data/lib/solargraph/source/chain/q_call.rb +11 -11
  182. data/lib/solargraph/source/chain/variable.rb +13 -13
  183. data/lib/solargraph/source/chain/z_super.rb +30 -30
  184. data/lib/solargraph/source/chain.rb +291 -252
  185. data/lib/solargraph/source/change.rb +82 -82
  186. data/lib/solargraph/source/cursor.rb +166 -167
  187. data/lib/solargraph/source/encoding_fixes.rb +23 -23
  188. data/lib/solargraph/source/source_chainer.rb +194 -194
  189. data/lib/solargraph/source/updater.rb +55 -55
  190. data/lib/solargraph/source.rb +498 -495
  191. data/lib/solargraph/source_map/clip.rb +226 -232
  192. data/lib/solargraph/source_map/data.rb +34 -30
  193. data/lib/solargraph/source_map/mapper.rb +259 -255
  194. data/lib/solargraph/source_map.rb +212 -217
  195. data/lib/solargraph/type_checker/checks.rb +124 -120
  196. data/lib/solargraph/type_checker/param_def.rb +37 -35
  197. data/lib/solargraph/type_checker/problem.rb +32 -32
  198. data/lib/solargraph/type_checker/rules.rb +84 -62
  199. data/lib/solargraph/type_checker.rb +814 -672
  200. data/lib/solargraph/version.rb +5 -5
  201. data/lib/solargraph/views/_method.erb +10 -10
  202. data/lib/solargraph/views/_namespace.erb +3 -3
  203. data/lib/solargraph/views/document.erb +10 -10
  204. data/lib/solargraph/workspace/config.rb +255 -239
  205. data/lib/solargraph/workspace/require_paths.rb +97 -0
  206. data/lib/solargraph/workspace.rb +220 -239
  207. data/lib/solargraph/yard_map/helpers.rb +44 -16
  208. data/lib/solargraph/yard_map/mapper/to_constant.rb +7 -5
  209. data/lib/solargraph/yard_map/mapper/to_method.rb +130 -94
  210. data/lib/solargraph/yard_map/mapper/to_namespace.rb +31 -28
  211. data/lib/solargraph/yard_map/mapper.rb +79 -78
  212. data/lib/solargraph/yard_map/to_method.rb +89 -86
  213. data/lib/solargraph/yard_tags.rb +20 -20
  214. data/lib/solargraph/yardoc.rb +87 -52
  215. data/lib/solargraph.rb +105 -72
  216. data/rbs/fills/bundler/0/bundler.rbs +4271 -0
  217. data/rbs/fills/open3/0/open3.rbs +172 -0
  218. data/rbs/fills/rubygems/0/basic_specification.rbs +326 -0
  219. data/rbs/fills/rubygems/0/errors.rbs +364 -0
  220. data/rbs/fills/rubygems/0/spec_fetcher.rbs +107 -0
  221. data/rbs/fills/rubygems/0/specification.rbs +1753 -0
  222. data/rbs/fills/tuple/tuple.rbs +149 -0
  223. data/rbs/shims/ast/0/node.rbs +5 -0
  224. data/rbs/shims/ast/2.4/.rbs_meta.yaml +9 -0
  225. data/rbs/shims/ast/2.4/ast.rbs +73 -0
  226. data/rbs/shims/parser/3.2.0.1/builders/default.rbs +195 -0
  227. data/rbs/shims/parser/3.2.0.1/manifest.yaml +7 -0
  228. data/rbs/shims/parser/3.2.0.1/parser.rbs +201 -0
  229. data/rbs/shims/parser/3.2.0.1/polyfill.rbs +4 -0
  230. data/rbs/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
  231. data/rbs/shims/thor/1.2.0.1/manifest.yaml +7 -0
  232. data/rbs/shims/thor/1.2.0.1/thor.rbs +17 -0
  233. data/rbs_collection.yaml +19 -0
  234. data/solargraph.gemspec +27 -5
  235. metadata +215 -18
  236. data/lib/.rubocop.yml +0 -22
  237. data/lib/solargraph/cache.rb +0 -77
  238. data/lib/solargraph/parser/node_methods.rb +0 -83
@@ -1,394 +1,444 @@
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
- end
21
-
22
- # @sg-ignore Fix "Not enough arguments to Module#protected"
23
- protected def equality_fields
24
- [self.class, items]
25
- end
26
-
27
- # @param api_map [ApiMap]
28
- # @param context [String]
29
- # @return [ComplexType]
30
- def qualify api_map, context = ''
31
- red = reduce_object
32
- types = red.items.map do |t|
33
- next t if ['nil', 'void', 'undefined'].include?(t.name)
34
- next t if ['::Boolean'].include?(t.rooted_name)
35
- t.qualify api_map, context
36
- end
37
- ComplexType.new(types).reduce_object
38
- end
39
-
40
- # @param generics_to_resolve [Enumerable<String>]]
41
- # @param context_type [UniqueType, nil]
42
- # @param resolved_generic_values [Hash{String => ComplexType}] Added to as types are encountered or resolved
43
- # @return [self]
44
- def resolve_generics_from_context generics_to_resolve, context_type, resolved_generic_values: {}
45
- return self unless generic?
46
-
47
- ComplexType.new(@items.map { |i| i.resolve_generics_from_context(generics_to_resolve, context_type, resolved_generic_values: resolved_generic_values) })
48
- end
49
-
50
- # @return [UniqueType]
51
- def first
52
- @items.first
53
- end
54
-
55
- # @return [String]
56
- def to_rbs
57
- ((@items.length > 1 ? '(' : '') +
58
- @items.map(&:to_rbs).join(' | ') +
59
- (@items.length > 1 ? ')' : ''))
60
- end
61
-
62
- # @param dst [ComplexType]
63
- # @return [ComplexType]
64
- def self_to_type dst
65
- object_type_dst = dst.reduce_class_type
66
- transform do |t|
67
- next t if t.name != 'self'
68
- object_type_dst
69
- end
70
- end
71
-
72
- # @yieldparam [UniqueType]
73
- # @return [Array]
74
- def map &block
75
- @items.map &block
76
- end
77
-
78
- # @yieldparam [UniqueType]
79
- # @return [Enumerable<UniqueType>]
80
- def each &block
81
- @items.each &block
82
- end
83
-
84
- # @yieldparam [UniqueType]
85
- # @return [void]
86
- # @overload each_unique_type()
87
- # @return [Enumerator<UniqueType>]
88
- def each_unique_type &block
89
- return enum_for(__method__) unless block_given?
90
-
91
- @items.each do |item|
92
- item.each_unique_type &block
93
- end
94
- end
95
-
96
- # @return [Integer]
97
- def length
98
- @items.length
99
- end
100
-
101
- # @return [Array<UniqueType>]
102
- def to_a
103
- @items
104
- end
105
-
106
- def tags
107
- @items.map(&:tag).join(', ')
108
- end
109
-
110
- # @param index [Integer]
111
- # @return [UniqueType]
112
- def [](index)
113
- @items[index]
114
- end
115
-
116
- # @return [Array<UniqueType>]
117
- def select &block
118
- @items.select &block
119
- end
120
-
121
- # @return [String]
122
- def namespace
123
- # cache this attr for high frequency call
124
- @namespace ||= method_missing(:namespace).to_s
125
- end
126
-
127
- # @return [Array<String>]
128
- def namespaces
129
- @items.map(&:namespace)
130
- end
131
-
132
- # @param name [Symbol]
133
- # @return [Object, nil]
134
- def method_missing name, *args, &block
135
- return if @items.first.nil?
136
- return @items.first.send(name, *args, &block) if respond_to_missing?(name)
137
- super
138
- end
139
-
140
- # @param name [Symbol]
141
- # @param include_private [Boolean]
142
- def respond_to_missing?(name, include_private = false)
143
- TypeMethods.public_instance_methods.include?(name) || super
144
- end
145
-
146
- def to_s
147
- map(&:tag).join(', ')
148
- end
149
-
150
- def desc
151
- rooted_tags
152
- end
153
-
154
- def rooted_tags
155
- map(&:rooted_tag).join(', ')
156
- end
157
-
158
- # @yieldparam [UniqueType]
159
- def all? &block
160
- @items.all? &block
161
- end
162
-
163
- # @yieldparam [UniqueType]
164
- # @yieldreturn [Boolean]
165
- # @return [Boolean]
166
- def any? &block
167
- @items.compact.any? &block
168
- end
169
-
170
- def selfy?
171
- @items.any?(&:selfy?)
172
- end
173
-
174
- def generic?
175
- any?(&:generic?)
176
- end
177
-
178
- # @param new_name [String, nil]
179
- # @yieldparam t [UniqueType]
180
- # @yieldreturn [UniqueType]
181
- # @return [ComplexType]
182
- def transform(new_name = nil, &transform_type)
183
- raise "Please remove leading :: and set rooted with recreate() instead - #{new_name}" if new_name&.start_with?('::')
184
- ComplexType.new(map { |ut| ut.transform(new_name, &transform_type) })
185
- end
186
-
187
- # @return [self]
188
- def force_rooted
189
- transform do |t|
190
- t.recreate(make_rooted: true)
191
- end
192
- end
193
-
194
- # @param definitions [Pin::Namespace, Pin::Method]
195
- # @param context_type [ComplexType]
196
- # @return [ComplexType]
197
- def resolve_generics definitions, context_type
198
- result = @items.map { |i| i.resolve_generics(definitions, context_type) }
199
- ComplexType.new(result)
200
- end
201
-
202
- def nullable?
203
- @items.any?(&:nil_type?)
204
- end
205
-
206
- # @return [Array<ComplexType>]
207
- def all_params
208
- @items.first.all_params || []
209
- end
210
-
211
- # @return [ComplexType]
212
- def reduce_class_type
213
- new_items = items.flat_map do |type|
214
- next type unless ['Module', 'Class'].include?(type.name)
215
-
216
- type.all_params
217
- end
218
- ComplexType.new(new_items)
219
- end
220
-
221
- # every type and subtype in this union have been resolved to be
222
- # fully qualified
223
- def all_rooted?
224
- all?(&:all_rooted?)
225
- end
226
-
227
- # every top-level type has resolved to be fully qualified; see
228
- # #all_rooted? to check their subtypes as well
229
- def rooted?
230
- all?(&:rooted?)
231
- end
232
-
233
- attr_reader :items
234
-
235
- def rooted?
236
- @items.all?(&:rooted?)
237
- end
238
-
239
- protected
240
-
241
- # @return [ComplexType]
242
- def reduce_object
243
- new_items = items.flat_map do |ut|
244
- next [ut] if ut.name != 'Object' || ut.subtypes.empty?
245
- ut.subtypes
246
- end
247
- ComplexType.new(new_items)
248
- end
249
-
250
- def bottom?
251
- @items.all?(&:bot?)
252
- end
253
-
254
- class << self
255
- # Parse type strings into a ComplexType.
256
- #
257
- # @example
258
- # ComplexType.parse 'String', 'Foo', 'nil' #=> [String, Foo, nil]
259
- #
260
- # @note
261
- # The `partial` parameter is used to indicate that the method is
262
- # receiving a string that will be used inside another ComplexType.
263
- # It returns arrays of ComplexTypes instead of a single cohesive one.
264
- # Consumers should not need to use this parameter; it should only be
265
- # used internally.
266
- #
267
- # @param strings [Array<String>] The type definitions to parse
268
- # @return [ComplexType]
269
- # # @overload parse(*strings, partial: false)
270
- # # @todo Need ability to use a literal true as a type below
271
- # # @param partial [Boolean] True if the string is part of a another type
272
- # # @return [Array<UniqueType>]
273
- # @sg-ignore
274
- # @todo To be able to select the right signature above,
275
- # Chain::Call needs to know the decl type (:arg, :optarg,
276
- # :kwarg, etc) of the arguments given, instead of just having
277
- # an array of Chains as the arguments.
278
- def parse *strings, partial: false
279
- # @type [Hash{Array<String> => ComplexType}]
280
- @cache ||= {}
281
- unless partial
282
- cached = @cache[strings]
283
- return cached unless cached.nil?
284
- end
285
- types = []
286
- key_types = nil
287
- strings.each do |type_string|
288
- point_stack = 0
289
- curly_stack = 0
290
- paren_stack = 0
291
- base = String.new
292
- subtype_string = String.new
293
- type_string&.each_char do |char|
294
- if char == '='
295
- #raise ComplexTypeError, "Invalid = in type #{type_string}" unless curly_stack > 0
296
- elsif char == '<'
297
- point_stack += 1
298
- elsif char == '>'
299
- if subtype_string.end_with?('=') && curly_stack > 0
300
- subtype_string += char
301
- elsif base.end_with?('=')
302
- raise ComplexTypeError, "Invalid hash thing" unless key_types.nil?
303
- # types.push ComplexType.new([UniqueType.new(base[0..-2].strip)])
304
- types.push UniqueType.parse(base[0..-2].strip, subtype_string)
305
- # @todo this should either expand key_type's type
306
- # automatically or complain about not being
307
- # compatible with key_type's type in type checking
308
- key_types = types
309
- types = []
310
- base.clear
311
- subtype_string.clear
312
- next
313
- else
314
- raise ComplexTypeError, "Invalid close in type #{type_string}" if point_stack == 0
315
- point_stack -= 1
316
- subtype_string += char
317
- end
318
- next
319
- elsif char == '{'
320
- curly_stack += 1
321
- elsif char == '}'
322
- curly_stack -= 1
323
- subtype_string += char
324
- raise ComplexTypeError, "Invalid close in type #{type_string}" if curly_stack < 0
325
- next
326
- elsif char == '('
327
- paren_stack += 1
328
- elsif char == ')'
329
- paren_stack -= 1
330
- subtype_string += char
331
- raise ComplexTypeError, "Invalid close in type #{type_string}" if paren_stack < 0
332
- next
333
- elsif char == ',' && point_stack == 0 && curly_stack == 0 && paren_stack == 0
334
- # types.push ComplexType.new([UniqueType.new(base.strip, subtype_string.strip)])
335
- types.push UniqueType.parse(base.strip, subtype_string.strip)
336
- base.clear
337
- subtype_string.clear
338
- next
339
- end
340
- if point_stack == 0 && curly_stack == 0 && paren_stack == 0
341
- base.concat char
342
- else
343
- subtype_string.concat char
344
- end
345
- end
346
- raise ComplexTypeError, "Unclosed subtype in #{type_string}" if point_stack != 0 || curly_stack != 0 || paren_stack != 0
347
- # types.push ComplexType.new([UniqueType.new(base, subtype_string)])
348
- types.push UniqueType.parse(base.strip, subtype_string.strip)
349
- end
350
- unless key_types.nil?
351
- raise ComplexTypeError, "Invalid use of key/value parameters" unless partial
352
- return key_types if types.empty?
353
- return [key_types, types]
354
- end
355
- result = partial ? types : ComplexType.new(types)
356
- @cache[strings] = result unless partial
357
- result
358
- end
359
-
360
- # @param strings [Array<String>]
361
- # @return [ComplexType]
362
- def try_parse *strings
363
- parse *strings
364
- rescue ComplexTypeError => e
365
- Solargraph.logger.info "Error parsing complex type `#{strings.join(', ')}`: #{e.message}"
366
- ComplexType::UNDEFINED
367
- end
368
- end
369
-
370
- VOID = ComplexType.parse('void')
371
- UNDEFINED = ComplexType.parse('undefined')
372
- SYMBOL = ComplexType.parse('::Symbol')
373
- ROOT = ComplexType.parse('::Class<>')
374
- NIL = ComplexType.parse('nil')
375
- SELF = ComplexType.parse('self')
376
- BOOLEAN = ComplexType.parse('::Boolean')
377
- BOT = ComplexType.parse('bot')
378
-
379
- private
380
-
381
- # @todo This is a quick and dirty hack that forces `self` keywords
382
- # to reference an instance of their class and never the class itself.
383
- # This behavior may change depending on which result is expected
384
- # from YARD conventions. See https://github.com/lsegal/yard/issues/1257
385
- # @param dst [String]
386
- # @return [String]
387
- def reduce_class dst
388
- while dst =~ /^(Class|Module)\<(.*?)\>$/
389
- dst = dst.sub(/^(Class|Module)\</, '').sub(/\>$/, '')
390
- end
391
- dst
392
- end
393
- end
394
- 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'.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