solargraph 0.58.2 → 0.59.0.dev.2

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 (203) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +3 -0
  3. data/.github/workflows/linting.yml +4 -5
  4. data/.github/workflows/plugins.yml +41 -34
  5. data/.github/workflows/rspec.yml +44 -23
  6. data/.github/workflows/typecheck.yml +2 -2
  7. data/.rubocop.yml +32 -5
  8. data/.rubocop_todo.yml +50 -966
  9. data/Gemfile +3 -1
  10. data/README.md +3 -3
  11. data/Rakefile +26 -23
  12. data/bin/solargraph +2 -1
  13. data/lib/solargraph/api_map/cache.rb +3 -3
  14. data/lib/solargraph/api_map/constants.rb +13 -3
  15. data/lib/solargraph/api_map/index.rb +23 -18
  16. data/lib/solargraph/api_map/source_to_yard.rb +22 -9
  17. data/lib/solargraph/api_map/store.rb +33 -28
  18. data/lib/solargraph/api_map.rb +150 -82
  19. data/lib/solargraph/bench.rb +44 -45
  20. data/lib/solargraph/complex_type/conformance.rb +176 -0
  21. data/lib/solargraph/complex_type/type_methods.rb +28 -17
  22. data/lib/solargraph/complex_type/unique_type.rb +218 -57
  23. data/lib/solargraph/complex_type.rb +170 -57
  24. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -61
  25. data/lib/solargraph/convention/data_definition/data_definition_node.rb +7 -5
  26. data/lib/solargraph/convention/data_definition.rb +5 -2
  27. data/lib/solargraph/convention/gemfile.rb +15 -15
  28. data/lib/solargraph/convention/gemspec.rb +23 -23
  29. data/lib/solargraph/convention/rakefile.rb +17 -17
  30. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +2 -1
  31. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +4 -3
  32. data/lib/solargraph/convention/struct_definition.rb +8 -4
  33. data/lib/solargraph/convention.rb +78 -78
  34. data/lib/solargraph/converters/dd.rb +19 -17
  35. data/lib/solargraph/converters/dl.rb +17 -15
  36. data/lib/solargraph/converters/dt.rb +17 -15
  37. data/lib/solargraph/converters/misc.rb +3 -1
  38. data/lib/solargraph/diagnostics/require_not_found.rb +1 -0
  39. data/lib/solargraph/diagnostics/rubocop.rb +11 -10
  40. data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
  41. data/lib/solargraph/diagnostics/type_check.rb +11 -10
  42. data/lib/solargraph/diagnostics/update_errors.rb +37 -41
  43. data/lib/solargraph/doc_map.rb +133 -373
  44. data/lib/solargraph/equality.rb +4 -4
  45. data/lib/solargraph/gem_pins.rb +21 -20
  46. data/lib/solargraph/language_server/error_codes.rb +20 -20
  47. data/lib/solargraph/language_server/host/diagnoser.rb +1 -1
  48. data/lib/solargraph/language_server/host/dispatch.rb +3 -3
  49. data/lib/solargraph/language_server/host/message_worker.rb +4 -3
  50. data/lib/solargraph/language_server/host/sources.rb +2 -1
  51. data/lib/solargraph/language_server/host.rb +30 -22
  52. data/lib/solargraph/language_server/message/base.rb +97 -97
  53. data/lib/solargraph/language_server/message/client/register_capability.rb +13 -15
  54. data/lib/solargraph/language_server/message/completion_item/resolve.rb +58 -60
  55. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +12 -18
  56. data/lib/solargraph/language_server/message/extended/document.rb +1 -0
  57. data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -32
  58. data/lib/solargraph/language_server/message/extended/download_core.rb +20 -19
  59. data/lib/solargraph/language_server/message/extended/search.rb +20 -20
  60. data/lib/solargraph/language_server/message/initialize.rb +197 -191
  61. data/lib/solargraph/language_server/message/text_document/completion.rb +10 -8
  62. data/lib/solargraph/language_server/message/text_document/definition.rb +41 -32
  63. data/lib/solargraph/language_server/message/text_document/document_highlight.rb +23 -16
  64. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +29 -19
  65. data/lib/solargraph/language_server/message/text_document/formatting.rb +8 -6
  66. data/lib/solargraph/language_server/message/text_document/hover.rb +5 -5
  67. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +18 -11
  68. data/lib/solargraph/language_server/message/text_document/references.rb +23 -16
  69. data/lib/solargraph/language_server/message/text_document/rename.rb +26 -19
  70. data/lib/solargraph/language_server/message/text_document/signature_help.rb +3 -2
  71. data/lib/solargraph/language_server/message/text_document/type_definition.rb +25 -17
  72. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +41 -35
  73. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +48 -40
  74. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +32 -26
  75. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +27 -17
  76. data/lib/solargraph/language_server/message.rb +94 -94
  77. data/lib/solargraph/language_server/request.rb +29 -27
  78. data/lib/solargraph/language_server/transport/data_reader.rb +72 -74
  79. data/lib/solargraph/language_server/uri_helpers.rb +49 -49
  80. data/lib/solargraph/library.rb +85 -44
  81. data/lib/solargraph/location.rb +17 -14
  82. data/lib/solargraph/logging.rb +24 -4
  83. data/lib/solargraph/page.rb +92 -92
  84. data/lib/solargraph/parser/comment_ripper.rb +19 -4
  85. data/lib/solargraph/parser/flow_sensitive_typing.rb +326 -108
  86. data/lib/solargraph/parser/node_processor/base.rb +34 -4
  87. data/lib/solargraph/parser/node_processor.rb +8 -7
  88. data/lib/solargraph/parser/parser_gem/class_methods.rb +32 -14
  89. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +19 -19
  90. data/lib/solargraph/parser/parser_gem/node_chainer.rb +50 -25
  91. data/lib/solargraph/parser/parser_gem/node_methods.rb +91 -70
  92. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +4 -4
  93. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +13 -11
  94. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +9 -0
  95. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +12 -12
  96. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +10 -3
  97. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +38 -37
  98. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +36 -6
  99. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +5 -3
  100. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
  101. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -1
  102. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +3 -3
  103. data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
  104. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -1
  105. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
  106. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +4 -5
  107. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +124 -113
  108. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -29
  109. data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
  110. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +6 -2
  111. data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
  112. data/lib/solargraph/parser/parser_gem.rb +14 -12
  113. data/lib/solargraph/parser/region.rb +9 -3
  114. data/lib/solargraph/parser/snippet.rb +3 -1
  115. data/lib/solargraph/parser.rb +25 -23
  116. data/lib/solargraph/pin/base.rb +126 -80
  117. data/lib/solargraph/pin/base_variable.rb +273 -24
  118. data/lib/solargraph/pin/block.rb +29 -6
  119. data/lib/solargraph/pin/breakable.rb +7 -1
  120. data/lib/solargraph/pin/callable.rb +65 -21
  121. data/lib/solargraph/pin/closure.rb +7 -10
  122. data/lib/solargraph/pin/common.rb +24 -6
  123. data/lib/solargraph/pin/compound_statement.rb +55 -0
  124. data/lib/solargraph/pin/constant.rb +43 -45
  125. data/lib/solargraph/pin/conversions.rb +10 -4
  126. data/lib/solargraph/pin/delegated_method.rb +19 -8
  127. data/lib/solargraph/pin/documenting.rb +4 -2
  128. data/lib/solargraph/pin/instance_variable.rb +5 -1
  129. data/lib/solargraph/pin/keyword.rb +0 -4
  130. data/lib/solargraph/pin/local_variable.rb +15 -59
  131. data/lib/solargraph/pin/method.rb +153 -104
  132. data/lib/solargraph/pin/method_alias.rb +8 -0
  133. data/lib/solargraph/pin/namespace.rb +19 -12
  134. data/lib/solargraph/pin/parameter.rb +100 -36
  135. data/lib/solargraph/pin/proxy_type.rb +4 -1
  136. data/lib/solargraph/pin/reference/override.rb +1 -1
  137. data/lib/solargraph/pin/reference/superclass.rb +2 -0
  138. data/lib/solargraph/pin/reference.rb +19 -0
  139. data/lib/solargraph/pin/search.rb +3 -2
  140. data/lib/solargraph/pin/signature.rb +15 -12
  141. data/lib/solargraph/pin/symbol.rb +2 -1
  142. data/lib/solargraph/pin/until.rb +2 -4
  143. data/lib/solargraph/pin/while.rb +2 -4
  144. data/lib/solargraph/pin.rb +2 -0
  145. data/lib/solargraph/pin_cache.rb +490 -73
  146. data/lib/solargraph/position.rb +14 -10
  147. data/lib/solargraph/range.rb +16 -15
  148. data/lib/solargraph/rbs_map/conversions.rb +343 -214
  149. data/lib/solargraph/rbs_map/core_fills.rb +91 -84
  150. data/lib/solargraph/rbs_map/core_map.rb +24 -17
  151. data/lib/solargraph/rbs_map/stdlib_map.rb +33 -5
  152. data/lib/solargraph/rbs_map.rb +77 -32
  153. data/lib/solargraph/server_methods.rb +16 -16
  154. data/lib/solargraph/shell.rb +128 -73
  155. data/lib/solargraph/source/chain/array.rb +39 -37
  156. data/lib/solargraph/source/chain/call.rb +96 -56
  157. data/lib/solargraph/source/chain/class_variable.rb +13 -13
  158. data/lib/solargraph/source/chain/constant.rb +5 -1
  159. data/lib/solargraph/source/chain/global_variable.rb +13 -13
  160. data/lib/solargraph/source/chain/hash.rb +8 -5
  161. data/lib/solargraph/source/chain/if.rb +12 -10
  162. data/lib/solargraph/source/chain/instance_variable.rb +24 -1
  163. data/lib/solargraph/source/chain/link.rb +99 -109
  164. data/lib/solargraph/source/chain/literal.rb +9 -6
  165. data/lib/solargraph/source/chain/or.rb +10 -4
  166. data/lib/solargraph/source/chain/q_call.rb +13 -11
  167. data/lib/solargraph/source/chain/variable.rb +15 -13
  168. data/lib/solargraph/source/chain/z_super.rb +28 -30
  169. data/lib/solargraph/source/chain.rb +49 -38
  170. data/lib/solargraph/source/change.rb +12 -5
  171. data/lib/solargraph/source/cursor.rb +23 -17
  172. data/lib/solargraph/source/encoding_fixes.rb +6 -7
  173. data/lib/solargraph/source/source_chainer.rb +56 -32
  174. data/lib/solargraph/source/updater.rb +5 -1
  175. data/lib/solargraph/source.rb +59 -35
  176. data/lib/solargraph/source_map/clip.rb +48 -29
  177. data/lib/solargraph/source_map/data.rb +4 -1
  178. data/lib/solargraph/source_map/mapper.rb +71 -42
  179. data/lib/solargraph/source_map.rb +21 -9
  180. data/lib/solargraph/type_checker/problem.rb +3 -1
  181. data/lib/solargraph/type_checker/rules.rb +81 -8
  182. data/lib/solargraph/type_checker.rb +195 -120
  183. data/lib/solargraph/version.rb +1 -1
  184. data/lib/solargraph/workspace/config.rb +13 -10
  185. data/lib/solargraph/workspace/gemspecs.rb +367 -0
  186. data/lib/solargraph/workspace/require_paths.rb +1 -0
  187. data/lib/solargraph/workspace.rb +149 -30
  188. data/lib/solargraph/yard_map/helpers.rb +8 -3
  189. data/lib/solargraph/yard_map/mapper/to_method.rb +13 -7
  190. data/lib/solargraph/yard_map/mapper/to_namespace.rb +2 -1
  191. data/lib/solargraph/yard_map/mapper.rb +13 -8
  192. data/lib/solargraph/yard_tags.rb +20 -20
  193. data/lib/solargraph/yardoc.rb +33 -23
  194. data/lib/solargraph.rb +29 -8
  195. data/rbs/fills/rubygems/0/dependency.rbs +193 -0
  196. data/rbs/fills/tuple/tuple.rbs +28 -0
  197. data/rbs/shims/ast/0/node.rbs +1 -1
  198. data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
  199. data/solargraph.gemspec +36 -34
  200. metadata +38 -33
  201. data/lib/solargraph/type_checker/checks.rb +0 -124
  202. data/lib/solargraph/type_checker/param_def.rb +0 -37
  203. data/lib/solargraph/yard_map/to_method.rb +0 -89
@@ -11,11 +11,6 @@ module Solargraph
11
11
 
12
12
  attr_reader :all_params, :subtypes, :key_types
13
13
 
14
- # @sg-ignore Fix "Not enough arguments to Module#protected"
15
- protected def equality_fields
16
- [@name, @all_params, @subtypes, @key_types]
17
- end
18
-
19
14
  # Create a UniqueType with the specified name and an optional substring.
20
15
  # The substring is the parameter section of a parametrized type, e.g.,
21
16
  # for the type `Array<String>`, the name is `Array` and the substring is
@@ -26,11 +21,9 @@ module Solargraph
26
21
  # @param make_rooted [Boolean, nil]
27
22
  # @return [UniqueType]
28
23
  def self.parse name, substring = '', make_rooted: nil
29
- if name.start_with?(':::')
30
- raise ComplexTypeError, "Illegal prefix: #{name}"
31
- end
24
+ raise ComplexTypeError, "Illegal prefix: #{name}" if name.start_with?(':::')
32
25
  if name.start_with?('::')
33
- name = name[2..-1]
26
+ name = name[2..]
34
27
  rooted = true
35
28
  elsif !can_root_name?(name)
36
29
  rooted = true
@@ -46,15 +39,20 @@ module Solargraph
46
39
  parameters_type = nil
47
40
  unless substring.empty?
48
41
  subs = ComplexType.parse(substring[1..-2], partial: true)
42
+ # @sg-ignore Need to add nil check here
49
43
  parameters_type = PARAMETERS_TYPE_BY_STARTING_TAG.fetch(substring[0])
50
44
  if parameters_type == :hash
51
- raise ComplexTypeError, "Bad hash type: name=#{name}, substring=#{substring}" unless !subs.is_a?(ComplexType) and subs.length == 2 and !subs[0].is_a?(UniqueType) and !subs[1].is_a?(UniqueType)
45
+ unless !subs.is_a?(ComplexType) && (subs.length == 2) && !subs[0].is_a?(UniqueType) && !subs[1].is_a?(UniqueType)
46
+ raise ComplexTypeError,
47
+ "Bad hash type: name=#{name}, substring=#{substring}"
48
+ end
52
49
  key_types.concat(subs[0].map { |u| ComplexType.new([u]) })
53
50
  subtypes.concat(subs[1].map { |u| ComplexType.new([u]) })
54
51
  elsif parameters_type == :list && name == 'Hash'
55
52
  # Treat Hash<A, B> as Hash{A => B}
56
53
  if subs.length != 2
57
- raise ComplexTypeError, "Bad hash type: name=#{name}, substring=#{substring} - must have exactly two parameters"
54
+ raise ComplexTypeError,
55
+ "Bad hash type: name=#{name}, substring=#{substring} - must have exactly two parameters"
58
56
  end
59
57
  key_types.concat(subs[0].map { |u| ComplexType.new([u]) })
60
58
  subtypes.concat(subs[1].map { |u| ComplexType.new([u]) })
@@ -62,6 +60,7 @@ module Solargraph
62
60
  subtypes.concat subs
63
61
  end
64
62
  end
63
+ # @sg-ignore Need to add nil check here
65
64
  new(name, key_types, subtypes, rooted: rooted, parameters_type: parameters_type)
66
65
  end
67
66
 
@@ -70,9 +69,9 @@ module Solargraph
70
69
  # @param subtypes [Array<ComplexType>]
71
70
  # @param rooted [Boolean]
72
71
  # @param parameters_type [Symbol, nil]
73
- def initialize(name, key_types = [], subtypes = [], rooted:, parameters_type: nil)
74
- if parameters_type.nil?
75
- raise "You must supply parameters_type if you provide parameters" unless key_types.empty? && subtypes.empty?
72
+ def initialize name, key_types = [], subtypes = [], rooted:, parameters_type: nil
73
+ if parameters_type.nil? && !(key_types.empty? && subtypes.empty?)
74
+ raise 'You must supply parameters_type if you provide parameters'
76
75
  end
77
76
  raise "Please remove leading :: and set rooted instead - #{name.inspect}" if name.start_with?('::')
78
77
  @name = name
@@ -94,7 +93,7 @@ module Solargraph
94
93
  # @todo use api_map to establish number of generics in type;
95
94
  # if only one is allowed but multiple are passed in, treat
96
95
  # those as implicit unions
97
- ['Hash', 'Array', 'Set', '_ToAry', 'Enumerable', '_Each'].include?(name) && parameters_type != :fixed
96
+ %w[Hash Array Set _ToAry Enumerable _Each].include?(name) && parameters_type != :fixed
98
97
  end
99
98
 
100
99
  def to_s
@@ -109,6 +108,44 @@ module Solargraph
109
108
  end
110
109
  end
111
110
 
111
+ # @param exclude_types [ComplexType, nil]
112
+ # @param api_map [ApiMap]
113
+ # @return [ComplexType, self]
114
+ def exclude exclude_types, api_map
115
+ return self if exclude_types.nil?
116
+
117
+ types = items - exclude_types.items
118
+ types = [ComplexType::UniqueType::UNDEFINED] if types.empty?
119
+ ComplexType.new(types)
120
+ end
121
+
122
+ # @see https://en.wikipedia.org/wiki/Intersection_type
123
+ #
124
+ # @param intersection_type [ComplexType, ComplexType::UniqueType, nil]
125
+ # @param api_map [ApiMap]
126
+ # @return [self, ComplexType]
127
+ def intersect_with intersection_type, api_map
128
+ return self if intersection_type.nil?
129
+ return intersection_type if undefined?
130
+ types = []
131
+ # try to find common types via conformance
132
+ items.each do |ut|
133
+ intersection_type.each do |int_type|
134
+ if ut.conforms_to?(api_map, int_type, :assignment)
135
+ types << ut
136
+ elsif int_type.conforms_to?(api_map, ut, :assignment)
137
+ types << int_type
138
+ end
139
+ end
140
+ end
141
+ types = [ComplexType::UniqueType::UNDEFINED] if types.empty?
142
+ ComplexType.new(types)
143
+ end
144
+
145
+ def simplifyable_literal?
146
+ literal? && name != 'nil'
147
+ end
148
+
112
149
  def literal?
113
150
  non_literal_name != name
114
151
  end
@@ -118,6 +155,13 @@ module Solargraph
118
155
  @non_literal_name ||= determine_non_literal_name
119
156
  end
120
157
 
158
+ # @return [self]
159
+ def without_nil
160
+ return UniqueType::UNDEFINED if nil_type?
161
+
162
+ self
163
+ end
164
+
121
165
  # @return [String]
122
166
  def determine_non_literal_name
123
167
  # https://github.com/ruby/rbs/blob/master/docs/syntax.md
@@ -129,37 +173,114 @@ module Solargraph
129
173
  # | `false`
130
174
  return name if name.empty?
131
175
  return 'NilClass' if name == 'nil'
132
- return 'Boolean' if ['true', 'false'].include?(name)
176
+ return 'Boolean' if %w[true false].include?(name)
133
177
  return 'Symbol' if name[0] == ':'
178
+ # @sg-ignore Need to add nil check here
134
179
  return 'String' if ['"', "'"].include?(name[0])
135
180
  return 'Integer' if name.match?(/^-?\d+$/)
136
181
  name
137
182
  end
138
183
 
139
- def eql?(other)
184
+ def eql? other
140
185
  self.class == other.class &&
141
- # @sg-ignore https://github.com/castwide/solargraph/pull/1114
186
+ # @sg-ignore flow sensitive typing should support .class == .class
142
187
  @name == other.name &&
143
- # @sg-ignore https://github.com/castwide/solargraph/pull/1114
188
+ # @sg-ignore flow sensitive typing should support .class == .class
144
189
  @key_types == other.key_types &&
145
- # @sg-ignore https://github.com/castwide/solargraph/pull/1114
190
+ # @sg-ignore flow sensitive typing should support .class == .class
146
191
  @subtypes == other.subtypes &&
147
- # @sg-ignore https://github.com/castwide/solargraph/pull/1114
192
+ # @sg-ignore flow sensitive typing should support .class == .class
148
193
  @rooted == other.rooted? &&
149
- # @sg-ignore https://github.com/castwide/solargraph/pull/1114
194
+ # @sg-ignore flow sensitive typing should support .class == .class
150
195
  @all_params == other.all_params &&
151
- # @sg-ignore https://github.com/castwide/solargraph/pull/1114
196
+ # @sg-ignore flow sensitive typing should support .class == .class
152
197
  @parameters_type == other.parameters_type
153
198
  end
154
199
 
155
- def ==(other)
200
+ def == other
156
201
  eql?(other)
157
202
  end
158
203
 
204
+ # https://www.playfulpython.com/type-hinting-covariance-contra-variance/
205
+
206
+ # "[Expected] type variables that are COVARIANT can be substituted with
207
+ # a more specific [inferred] type without causing errors"
208
+ #
209
+ # "[Expected] type variables that are CONTRAVARIANT can be substituted
210
+ # with a more general [inferred] type without causing errors"
211
+ #
212
+ # "[Expected] types where neither is possible are INVARIANT"
213
+ #
214
+ # @param _situation [:method_call, :return_type]
215
+ # @param default [Symbol] The default variance to return if the type is not one of the special cases
216
+ #
217
+ # @return [:invariant, :covariant, :contravariant]
218
+ def parameter_variance _situation, default = :covariant
219
+ # @todo RBS can specify variance - maybe we can use that info
220
+ # and also let folks specify?
221
+ #
222
+ # Array/Set: ideally invariant, since we don't know if user is
223
+ # going to add new stuff into it or read it. But we don't
224
+ # have a way to specify, so we use covariant
225
+ # Enumerable: covariant: can't be changed, so we can pass
226
+ # in more specific subtypes
227
+ # Hash: read-only would be covariant, read-write would be
228
+ # invariant if we could distinguish that - should default to
229
+ # covariant
230
+ # contravariant?: Proc - can be changed, so we can pass
231
+ # in less specific super types
232
+ if %w[Hash Tuple Array Set Enumerable].include?(name) && fixed_parameters?
233
+ :covariant
234
+ else
235
+ default
236
+ end
237
+ end
238
+
239
+ # Whether this is an RBS interface like _ToAry or _Each.
240
+ def interface?
241
+ name.start_with?('_')
242
+ end
243
+
244
+ # @param other [UniqueType]
245
+ def erased_version_of? other
246
+ name == other.name && (all_params.empty? || all_params.all?(&:undefined?))
247
+ end
248
+
249
+ # @param api_map [ApiMap]
250
+ # @param expected [ComplexType::UniqueType, ComplexType]
251
+ # @param situation [:method_call, :assignment, :return_type]
252
+ # @param rules [Array<:allow_subtype_skew, :allow_empty_params, :allow_reverse_match, :allow_any_match, :allow_undefined, :allow_unresolved_generic>]
253
+ # @param variance [:invariant, :covariant, :contravariant]
254
+ def conforms_to? api_map, expected, situation, rules = [],
255
+ variance: erased_variance(situation)
256
+ return true if undefined? && rules.include?(:allow_undefined)
257
+
258
+ # @todo teach this to validate duck types as inferred type
259
+ return true if duck_type?
260
+
261
+ # complex types as expectations are unions - we only need to
262
+ # match one of their unique types
263
+ expected.any? do |expected_unique_type|
264
+ # :nocov:
265
+ unless expected_unique_type.instance_of?(UniqueType)
266
+ raise "Expected type must be a UniqueType, got #{expected_unique_type.class} in #{expected.inspect}"
267
+ end
268
+ # :nocov:
269
+ conformance = Conformance.new(api_map, self, expected_unique_type, situation,
270
+ rules, variance: variance)
271
+ conformance.conforms_to_unique_type?
272
+ end
273
+ end
274
+
159
275
  def hash
160
276
  [self.class, @name, @key_types, @sub_types, @rooted, @all_params, @parameters_type].hash
161
277
  end
162
278
 
279
+ # @return [self]
280
+ def erase_parameters
281
+ UniqueType.new(name, rooted: rooted?, parameters_type: parameters_type)
282
+ end
283
+
163
284
  # @return [Array<UniqueType>]
164
285
  def items
165
286
  [self]
@@ -181,6 +302,7 @@ module Solargraph
181
302
  rooted_tags
182
303
  end
183
304
 
305
+ # @sg-ignore Need better if/elseanalysis
184
306
  # @return [String]
185
307
  def to_rbs
186
308
  if duck_type?
@@ -190,10 +312,10 @@ module Solargraph
190
312
  elsif name.downcase == 'nil'
191
313
  'nil'
192
314
  elsif name == GENERIC_TAG_NAME
193
- all_params.first.name
194
- elsif ['Class', 'Module'].include?(name)
315
+ all_params.first&.name
316
+ elsif %w[Class Module].include?(name)
195
317
  rbs_name
196
- elsif ['Tuple', 'Array'].include?(name) && fixed_parameters?
318
+ elsif %w[Tuple Array].include?(name) && fixed_parameters?
197
319
  # tuples don't have a name; they're just [foo, bar, baz].
198
320
  if substring == '()'
199
321
  # but there are no zero element tuples, so we go with an array
@@ -218,7 +340,7 @@ module Solargraph
218
340
 
219
341
  # @param types [Array<UniqueType, ComplexType>]
220
342
  # @return [String]
221
- def rbs_union(types)
343
+ def rbs_union types
222
344
  if types.length == 1
223
345
  types.first.to_rbs
224
346
  else
@@ -242,16 +364,13 @@ module Solargraph
242
364
  name == GENERIC_TAG_NAME || all_params.any?(&:generic?)
243
365
  end
244
366
 
245
- # @param api_map [ApiMap] The ApiMap that performs qualification
246
- # @param atype [ComplexType] type which may be assigned to this type
247
- def can_assign?(api_map, atype)
248
- logger.debug { "UniqueType#can_assign?(self=#{rooted_tags.inspect}, atype=#{atype.rooted_tags.inspect})" }
249
- downcasted_atype = atype.downcast_to_literal_if_possible
250
- out = downcasted_atype.all? do |autype|
251
- autype.name == name || api_map.super_and_sub?(name, autype.name)
252
- end
253
- logger.debug { "UniqueType#can_assign?(self=#{rooted_tags.inspect}, atype=#{atype.rooted_tags.inspect}) => #{out}" }
254
- out
367
+ def nullable?
368
+ nil_type?
369
+ end
370
+
371
+ # @yieldreturn [Boolean]
372
+ def all? &block
373
+ block.yield self
255
374
  end
256
375
 
257
376
  # @return [UniqueType]
@@ -260,37 +379,44 @@ module Solargraph
260
379
  end
261
380
 
262
381
  # @param generics_to_resolve [Enumerable<String>]
263
- # @param context_type [UniqueType, nil]
382
+ # @param context_type [ComplexType, UniqueType, nil]
264
383
  # @param resolved_generic_values [Hash{String => ComplexType, ComplexType::UniqueType}] Added to as types are encountered or resolved
265
384
  # @return [UniqueType, ComplexType]
266
385
  def resolve_generics_from_context generics_to_resolve, context_type, resolved_generic_values: {}
267
386
  if name == ComplexType::GENERIC_TAG_NAME
268
387
  type_param = subtypes.first&.name
388
+ # @sg-ignore flow sensitive typing needs to eliminate literal from union with [:bar].include?(foo)
269
389
  return self unless generics_to_resolve.include? type_param
390
+ # @sg-ignore flow sensitive typing needs to eliminate literal from union with [:bar].include?(foo)
270
391
  unless context_type.nil? || !resolved_generic_values[type_param].nil?
271
392
  new_binding = true
393
+ # @sg-ignore flow sensitive typing needs to eliminate literal from union with [:bar].include?(foo)
272
394
  resolved_generic_values[type_param] = context_type
273
395
  end
274
396
  if new_binding
275
397
  resolved_generic_values.transform_values! do |complex_type|
276
- complex_type.resolve_generics_from_context(generics_to_resolve, nil, resolved_generic_values: resolved_generic_values)
398
+ complex_type.resolve_generics_from_context(generics_to_resolve, nil,
399
+ resolved_generic_values: resolved_generic_values)
277
400
  end
278
401
  end
402
+ # @sg-ignore flow sensitive typing needs to eliminate literal from union with [:bar].include?(foo)
279
403
  return resolved_generic_values[type_param] || self
280
404
  end
281
405
 
282
406
  # @todo typechecking should complain when the method being called has no @yieldparam tag
283
- new_key_types = resolve_param_generics_from_context(generics_to_resolve, context_type, resolved_generic_values, &:key_types)
284
- new_subtypes = resolve_param_generics_from_context(generics_to_resolve, context_type, resolved_generic_values, &:subtypes)
407
+ new_key_types = resolve_param_generics_from_context(generics_to_resolve, context_type, resolved_generic_values,
408
+ &:key_types)
409
+ new_subtypes = resolve_param_generics_from_context(generics_to_resolve, context_type, resolved_generic_values,
410
+ &:subtypes)
285
411
  recreate(new_key_types: new_key_types, new_subtypes: new_subtypes)
286
412
  end
287
413
 
288
414
  # @param generics_to_resolve [Enumerable<String>]
289
- # @param context_type [UniqueType, nil]
415
+ # @param context_type [UniqueType, ComplexType, nil]
290
416
  # @param resolved_generic_values [Hash{String => ComplexType}]
291
417
  # @yieldreturn [Array<ComplexType>]
292
418
  # @return [Array<ComplexType>]
293
- def resolve_param_generics_from_context(generics_to_resolve, context_type, resolved_generic_values)
419
+ def resolve_param_generics_from_context generics_to_resolve, context_type, resolved_generic_values
294
420
  types = yield self
295
421
  types.each_with_index.flat_map do |ct, i|
296
422
  ct.items.flat_map do |ut|
@@ -298,10 +424,12 @@ module Solargraph
298
424
  if context_params && context_params[i]
299
425
  type_arg = context_params[i]
300
426
  type_arg.map do |new_unique_context_type|
301
- ut.resolve_generics_from_context generics_to_resolve, new_unique_context_type, resolved_generic_values: resolved_generic_values
427
+ ut.resolve_generics_from_context generics_to_resolve, new_unique_context_type,
428
+ resolved_generic_values: resolved_generic_values
302
429
  end
303
430
  else
304
- ut.resolve_generics_from_context generics_to_resolve, nil, resolved_generic_values: resolved_generic_values
431
+ ut.resolve_generics_from_context generics_to_resolve, nil,
432
+ resolved_generic_values: resolved_generic_values
305
433
  end
306
434
  end
307
435
  end
@@ -323,7 +451,7 @@ module Solargraph
323
451
  idx = definitions.generics.index(generic_name)
324
452
  next t if idx.nil?
325
453
  if context_type.parameters_type == :hash
326
- if idx == 0
454
+ if idx.zero?
327
455
  next ComplexType.new(context_type.key_types)
328
456
  elsif idx == 1
329
457
  next ComplexType.new(context_type.subtypes)
@@ -331,12 +459,13 @@ module Solargraph
331
459
  next ComplexType::UNDEFINED
332
460
  end
333
461
  elsif context_type.all?(&:implicit_union?)
334
- if idx == 0 && !context_type.all_params.empty?
462
+ if idx.zero? && !context_type.all_params.empty?
335
463
  ComplexType.new(context_type.all_params)
336
464
  else
337
465
  ComplexType::UNDEFINED
338
466
  end
339
467
  else
468
+ # @sg-ignore Need to add nil check here
340
469
  context_type.all_params[idx] || definitions.generic_defaults[generic_name] || ComplexType::UNDEFINED
341
470
  end
342
471
  else
@@ -352,6 +481,13 @@ module Solargraph
352
481
  [block.yield(self)]
353
482
  end
354
483
 
484
+ # @yieldparam t [self]
485
+ # @yieldreturn [self]
486
+ # @return [Enumerable<self>]
487
+ def each &block
488
+ [self].each(&block)
489
+ end
490
+
355
491
  # @return [Array<UniqueType>]
356
492
  def to_a
357
493
  [self]
@@ -360,16 +496,17 @@ module Solargraph
360
496
  # @param new_name [String, nil]
361
497
  # @param make_rooted [Boolean, nil]
362
498
  # @param new_key_types [Array<ComplexType>, nil]
363
- # @param rooted [Boolean, nil]
499
+ # @param make_rooted [Boolean, nil]
364
500
  # @param new_subtypes [Array<ComplexType>, nil]
365
501
  # @return [self]
366
- def recreate(new_name: nil, make_rooted: nil, new_key_types: nil, new_subtypes: nil)
502
+ def recreate new_name: nil, make_rooted: nil, new_key_types: nil, new_subtypes: nil
367
503
  raise "Please remove leading :: and set rooted instead - #{new_name}" if new_name&.start_with?('::')
368
504
 
369
505
  new_name ||= name
370
506
  new_key_types ||= @key_types
371
507
  new_subtypes ||= @subtypes
372
508
  make_rooted = @rooted if make_rooted.nil?
509
+ # @sg-ignore flow sensitive typing needs better handling of ||= on lvars
373
510
  UniqueType.new(new_name, new_key_types, new_subtypes, rooted: make_rooted, parameters_type: parameters_type)
374
511
  end
375
512
 
@@ -396,8 +533,10 @@ module Solargraph
396
533
  # @yieldparam t [UniqueType]
397
534
  # @yieldreturn [self]
398
535
  # @return [self]
399
- def transform(new_name = nil, &transform_type)
400
- raise "Please remove leading :: and set rooted with recreate() instead - #{new_name}" if new_name&.start_with?('::')
536
+ def transform new_name = nil, &transform_type
537
+ if new_name&.start_with?('::')
538
+ raise "Please remove leading :: and set rooted with recreate() instead - #{new_name}"
539
+ end
401
540
  if name == ComplexType::GENERIC_TAG_NAME
402
541
  # doesn't make sense to manipulate the name of the generic
403
542
  new_key_types = @key_types
@@ -406,14 +545,15 @@ module Solargraph
406
545
  new_key_types = @key_types.flat_map { |ct| ct.items.map { |ut| ut.transform(&transform_type) } }
407
546
  new_subtypes = @subtypes.flat_map { |ct| ct.items.map { |ut| ut.transform(&transform_type) } }
408
547
  end
409
- new_type = recreate(new_name: new_name || name, new_key_types: new_key_types, new_subtypes: new_subtypes, make_rooted: @rooted)
548
+ new_type = recreate(new_name: new_name || name, new_key_types: new_key_types, new_subtypes: new_subtypes,
549
+ make_rooted: @rooted)
410
550
  yield new_type
411
551
  end
412
552
 
413
553
  # Generate a ComplexType that fully qualifies this type's namespaces.
414
554
  #
415
555
  # @param api_map [ApiMap] The ApiMap that performs qualification
416
- # @param context [String] The namespace from which to resolve names
556
+ # @param gates [Array<String>] The namespaces from which to resolve names
417
557
  # @return [self, ComplexType, UniqueType] The generated ComplexType
418
558
  def qualify api_map, *gates
419
559
  transform do |t|
@@ -443,6 +583,22 @@ module Solargraph
443
583
  end
444
584
  end
445
585
 
586
+ # @yieldreturn [Boolean]
587
+ def any? &block
588
+ block.yield self
589
+ end
590
+
591
+ # @return [ComplexType]
592
+ def reduce_class_type
593
+ new_items = items.flat_map do |type|
594
+ next type unless %w[Module Class].include?(type.name)
595
+ next type if type.all_params.empty?
596
+
597
+ type.all_params
598
+ end
599
+ ComplexType.new(new_items)
600
+ end
601
+
446
602
  def all_rooted?
447
603
  return true if name == GENERIC_TAG_NAME
448
604
  rooted? && all_params.all?(&:rooted?)
@@ -453,12 +609,12 @@ module Solargraph
453
609
  end
454
610
 
455
611
  # @param name_to_check [String]
456
- def can_root_name?(name_to_check = name)
612
+ def can_root_name? name_to_check = name
457
613
  self.class.can_root_name?(name_to_check)
458
614
  end
459
615
 
460
616
  # @param name [String]
461
- def self.can_root_name?(name)
617
+ def self.can_root_name? name
462
618
  # name is not lowercase
463
619
  !name.empty? && name != name.downcase
464
620
  end
@@ -475,8 +631,13 @@ module Solargraph
475
631
  '::NilClass' => UniqueType::NIL
476
632
  }.freeze
477
633
 
478
-
479
634
  include Logging
635
+
636
+ protected
637
+
638
+ def equality_fields
639
+ [@name, @all_params, @subtypes, @key_types]
640
+ end
480
641
  end
481
642
  end
482
643
  end