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