solargraph 0.58.3 → 0.59.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 (229) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +3 -0
  3. data/.github/workflows/linting.yml +12 -5
  4. data/.github/workflows/plugins.yml +54 -34
  5. data/.github/workflows/rspec.yml +15 -28
  6. data/.github/workflows/typecheck.yml +6 -3
  7. data/.rubocop.yml +38 -6
  8. data/.rubocop_todo.yml +53 -966
  9. data/CHANGELOG.md +24 -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 +40 -30
  19. data/lib/solargraph/api_map.rb +160 -78
  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 +31 -18
  23. data/lib/solargraph/complex_type/unique_type.rb +221 -63
  24. data/lib/solargraph/complex_type.rb +173 -59
  25. data/lib/solargraph/convention/active_support_concern.rb +111 -111
  26. data/lib/solargraph/convention/base.rb +50 -50
  27. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +1 -1
  28. data/lib/solargraph/convention/data_definition/data_definition_node.rb +7 -5
  29. data/lib/solargraph/convention/data_definition.rb +5 -2
  30. data/lib/solargraph/convention/gemfile.rb +1 -1
  31. data/lib/solargraph/convention/gemspec.rb +1 -1
  32. data/lib/solargraph/convention/rakefile.rb +1 -1
  33. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +2 -1
  34. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +4 -3
  35. data/lib/solargraph/convention/struct_definition.rb +8 -4
  36. data/lib/solargraph/convention.rb +2 -2
  37. data/lib/solargraph/converters/dd.rb +2 -0
  38. data/lib/solargraph/converters/dl.rb +2 -0
  39. data/lib/solargraph/converters/dt.rb +2 -0
  40. data/lib/solargraph/converters/misc.rb +2 -0
  41. data/lib/solargraph/diagnostics/require_not_found.rb +1 -0
  42. data/lib/solargraph/diagnostics/rubocop.rb +11 -10
  43. data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
  44. data/lib/solargraph/diagnostics/type_check.rb +11 -10
  45. data/lib/solargraph/diagnostics/update_errors.rb +4 -8
  46. data/lib/solargraph/diagnostics.rb +55 -55
  47. data/lib/solargraph/doc_map.rb +38 -39
  48. data/lib/solargraph/environ.rb +52 -52
  49. data/lib/solargraph/equality.rb +4 -4
  50. data/lib/solargraph/gem_pins.rb +4 -15
  51. data/lib/solargraph/language_server/error_codes.rb +10 -10
  52. data/lib/solargraph/language_server/host/diagnoser.rb +1 -1
  53. data/lib/solargraph/language_server/host/dispatch.rb +3 -3
  54. data/lib/solargraph/language_server/host/message_worker.rb +4 -3
  55. data/lib/solargraph/language_server/host/sources.rb +2 -1
  56. data/lib/solargraph/language_server/host.rb +35 -28
  57. data/lib/solargraph/language_server/message/base.rb +1 -1
  58. data/lib/solargraph/language_server/message/client/register_capability.rb +1 -3
  59. data/lib/solargraph/language_server/message/completion_item/resolve.rb +6 -8
  60. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +12 -18
  61. data/lib/solargraph/language_server/message/extended/document.rb +1 -0
  62. data/lib/solargraph/language_server/message/extended/document_gems.rb +7 -7
  63. data/lib/solargraph/language_server/message/extended/download_core.rb +2 -1
  64. data/lib/solargraph/language_server/message/extended/environment.rb +25 -25
  65. data/lib/solargraph/language_server/message/extended/search.rb +1 -1
  66. data/lib/solargraph/language_server/message/initialize.rb +20 -14
  67. data/lib/solargraph/language_server/message/initialized.rb +28 -28
  68. data/lib/solargraph/language_server/message/text_document/completion.rb +10 -8
  69. data/lib/solargraph/language_server/message/text_document/definition.rb +41 -32
  70. data/lib/solargraph/language_server/message/text_document/document_highlight.rb +17 -10
  71. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +29 -19
  72. data/lib/solargraph/language_server/message/text_document/formatting.rb +8 -6
  73. data/lib/solargraph/language_server/message/text_document/hover.rb +5 -5
  74. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +13 -6
  75. data/lib/solargraph/language_server/message/text_document/references.rb +17 -10
  76. data/lib/solargraph/language_server/message/text_document/rename.rb +20 -13
  77. data/lib/solargraph/language_server/message/text_document/signature_help.rb +3 -2
  78. data/lib/solargraph/language_server/message/text_document/type_definition.rb +25 -17
  79. data/lib/solargraph/language_server/message/text_document.rb +28 -28
  80. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +34 -28
  81. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +38 -30
  82. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +23 -17
  83. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +27 -17
  84. data/lib/solargraph/language_server/message.rb +1 -1
  85. data/lib/solargraph/language_server/progress.rb +143 -143
  86. data/lib/solargraph/language_server/request.rb +4 -2
  87. data/lib/solargraph/language_server/transport/adapter.rb +68 -68
  88. data/lib/solargraph/language_server/transport/data_reader.rb +11 -13
  89. data/lib/solargraph/language_server/uri_helpers.rb +2 -2
  90. data/lib/solargraph/language_server.rb +20 -20
  91. data/lib/solargraph/library.rb +57 -38
  92. data/lib/solargraph/location.rb +17 -14
  93. data/lib/solargraph/logging.rb +22 -4
  94. data/lib/solargraph/page.rb +1 -1
  95. data/lib/solargraph/parser/comment_ripper.rb +19 -4
  96. data/lib/solargraph/parser/flow_sensitive_typing.rb +324 -108
  97. data/lib/solargraph/parser/node_processor/base.rb +34 -4
  98. data/lib/solargraph/parser/node_processor.rb +8 -7
  99. data/lib/solargraph/parser/parser_gem/class_methods.rb +30 -14
  100. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -1
  101. data/lib/solargraph/parser/parser_gem/node_chainer.rb +51 -25
  102. data/lib/solargraph/parser/parser_gem/node_methods.rb +181 -73
  103. data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +24 -24
  104. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +4 -4
  105. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +13 -11
  106. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +9 -0
  107. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +11 -12
  108. data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +36 -36
  109. data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +24 -24
  110. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +10 -3
  111. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +9 -8
  112. data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +24 -24
  113. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +36 -6
  114. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +5 -3
  115. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
  116. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -1
  117. data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +40 -40
  118. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +3 -3
  119. data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
  120. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -1
  121. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
  122. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +4 -5
  123. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +124 -113
  124. data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +20 -20
  125. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +1 -1
  126. data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
  127. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +6 -2
  128. data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
  129. data/lib/solargraph/parser/parser_gem.rb +2 -0
  130. data/lib/solargraph/parser/region.rb +9 -3
  131. data/lib/solargraph/parser/snippet.rb +3 -1
  132. data/lib/solargraph/parser.rb +2 -0
  133. data/lib/solargraph/pin/base.rb +126 -82
  134. data/lib/solargraph/pin/base_variable.rb +273 -24
  135. data/lib/solargraph/pin/block.rb +29 -6
  136. data/lib/solargraph/pin/breakable.rb +7 -1
  137. data/lib/solargraph/pin/callable.rb +65 -21
  138. data/lib/solargraph/pin/closure.rb +7 -10
  139. data/lib/solargraph/pin/common.rb +24 -6
  140. data/lib/solargraph/pin/compound_statement.rb +55 -0
  141. data/lib/solargraph/pin/constant.rb +3 -5
  142. data/lib/solargraph/pin/conversions.rb +10 -4
  143. data/lib/solargraph/pin/delegated_method.rb +19 -8
  144. data/lib/solargraph/pin/documenting.rb +4 -2
  145. data/lib/solargraph/pin/instance_variable.rb +5 -1
  146. data/lib/solargraph/pin/keyword.rb +0 -4
  147. data/lib/solargraph/pin/local_variable.rb +15 -59
  148. data/lib/solargraph/pin/method.rb +158 -104
  149. data/lib/solargraph/pin/method_alias.rb +8 -0
  150. data/lib/solargraph/pin/namespace.rb +19 -12
  151. data/lib/solargraph/pin/parameter.rb +102 -36
  152. data/lib/solargraph/pin/proxy_type.rb +4 -1
  153. data/lib/solargraph/pin/reference/override.rb +1 -1
  154. data/lib/solargraph/pin/reference/require.rb +14 -14
  155. data/lib/solargraph/pin/reference/superclass.rb +2 -0
  156. data/lib/solargraph/pin/reference/type_alias.rb +16 -0
  157. data/lib/solargraph/pin/reference.rb +20 -0
  158. data/lib/solargraph/pin/search.rb +8 -7
  159. data/lib/solargraph/pin/signature.rb +15 -12
  160. data/lib/solargraph/pin/singleton.rb +11 -11
  161. data/lib/solargraph/pin/symbol.rb +2 -1
  162. data/lib/solargraph/pin/until.rb +2 -4
  163. data/lib/solargraph/pin/while.rb +2 -4
  164. data/lib/solargraph/pin.rb +2 -0
  165. data/lib/solargraph/pin_cache.rb +22 -19
  166. data/lib/solargraph/position.rb +17 -10
  167. data/lib/solargraph/range.rb +16 -15
  168. data/lib/solargraph/rbs_map/conversions.rb +367 -231
  169. data/lib/solargraph/rbs_map/core_fills.rb +18 -11
  170. data/lib/solargraph/rbs_map/core_map.rb +24 -17
  171. data/lib/solargraph/rbs_map/stdlib_map.rb +33 -5
  172. data/lib/solargraph/rbs_map.rb +76 -32
  173. data/lib/solargraph/server_methods.rb +1 -1
  174. data/lib/solargraph/shell.rb +258 -66
  175. data/lib/solargraph/source/chain/array.rb +3 -12
  176. data/lib/solargraph/source/chain/block_symbol.rb +13 -13
  177. data/lib/solargraph/source/chain/block_variable.rb +13 -13
  178. data/lib/solargraph/source/chain/call.rb +96 -56
  179. data/lib/solargraph/source/chain/class_variable.rb +1 -1
  180. data/lib/solargraph/source/chain/constant.rb +5 -1
  181. data/lib/solargraph/source/chain/global_variable.rb +1 -1
  182. data/lib/solargraph/source/chain/hash.rb +8 -5
  183. data/lib/solargraph/source/chain/head.rb +19 -19
  184. data/lib/solargraph/source/chain/if.rb +12 -10
  185. data/lib/solargraph/source/chain/instance_variable.rb +24 -1
  186. data/lib/solargraph/source/chain/link.rb +12 -22
  187. data/lib/solargraph/source/chain/literal.rb +22 -15
  188. data/lib/solargraph/source/chain/or.rb +10 -4
  189. data/lib/solargraph/source/chain/q_call.rb +2 -0
  190. data/lib/solargraph/source/chain/variable.rb +3 -1
  191. data/lib/solargraph/source/chain/z_super.rb +1 -3
  192. data/lib/solargraph/source/chain.rb +51 -38
  193. data/lib/solargraph/source/change.rb +12 -5
  194. data/lib/solargraph/source/cursor.rb +33 -18
  195. data/lib/solargraph/source/encoding_fixes.rb +6 -7
  196. data/lib/solargraph/source/source_chainer.rb +56 -32
  197. data/lib/solargraph/source/updater.rb +5 -1
  198. data/lib/solargraph/source.rb +59 -35
  199. data/lib/solargraph/source_map/clip.rb +54 -30
  200. data/lib/solargraph/source_map/data.rb +4 -1
  201. data/lib/solargraph/source_map/mapper.rb +69 -42
  202. data/lib/solargraph/source_map.rb +21 -9
  203. data/lib/solargraph/type_checker/problem.rb +3 -1
  204. data/lib/solargraph/type_checker/rules.rb +81 -8
  205. data/lib/solargraph/type_checker.rb +196 -122
  206. data/lib/solargraph/version.rb +1 -1
  207. data/lib/solargraph/workspace/config.rb +14 -11
  208. data/lib/solargraph/workspace/gemspecs.rb +367 -0
  209. data/lib/solargraph/workspace/require_paths.rb +1 -0
  210. data/lib/solargraph/workspace.rb +50 -28
  211. data/lib/solargraph/yard_map/cache.rb +25 -25
  212. data/lib/solargraph/yard_map/helpers.rb +8 -3
  213. data/lib/solargraph/yard_map/mapper/to_constant.rb +28 -28
  214. data/lib/solargraph/yard_map/mapper/to_method.rb +13 -7
  215. data/lib/solargraph/yard_map/mapper/to_namespace.rb +2 -1
  216. data/lib/solargraph/yard_map/mapper.rb +13 -8
  217. data/lib/solargraph/yard_map.rb +17 -18
  218. data/lib/solargraph/yard_tags.rb +2 -2
  219. data/lib/solargraph/yardoc.rb +7 -4
  220. data/lib/solargraph.rb +33 -10
  221. data/rbs/fills/rubygems/0/dependency.rbs +193 -0
  222. data/rbs/shims/ast/0/node.rbs +1 -1
  223. data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
  224. data/solargraph.gemspec +37 -35
  225. metadata +41 -42
  226. data/lib/solargraph/type_checker/checks.rb +0 -124
  227. data/lib/solargraph/type_checker/param_def.rb +0 -37
  228. data/lib/solargraph/yard_map/to_method.rb +0 -89
  229. data/rbs/fills/tuple/tuple.rbs +0 -149
@@ -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,7 +108,46 @@ 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?
150
+ return false
113
151
  non_literal_name != name
114
152
  end
115
153
 
@@ -118,6 +156,13 @@ module Solargraph
118
156
  @non_literal_name ||= determine_non_literal_name
119
157
  end
120
158
 
159
+ # @return [self]
160
+ def without_nil
161
+ return UniqueType::UNDEFINED if nil_type?
162
+
163
+ self
164
+ end
165
+
121
166
  # @return [String]
122
167
  def determine_non_literal_name
123
168
  # https://github.com/ruby/rbs/blob/master/docs/syntax.md
@@ -129,37 +174,113 @@ module Solargraph
129
174
  # | `false`
130
175
  return name if name.empty?
131
176
  return 'NilClass' if name == 'nil'
132
- return 'Boolean' if ['true', 'false'].include?(name)
177
+ return 'Boolean' if %w[true false].include?(name)
133
178
  return 'Symbol' if name[0] == ':'
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 Hash::_Key.
240
+ def interface?
241
+ name.start_with?('_') || name.include?('::_')
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,55 +364,59 @@ 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]
258
377
  def downcast_to_literal_if_possible
378
+ return self
259
379
  SINGLE_SUBTYPE.fetch(rooted_tag, self)
260
380
  end
261
381
 
262
382
  # @param generics_to_resolve [Enumerable<String>]
263
- # @param context_type [UniqueType, nil]
383
+ # @param context_type [ComplexType, UniqueType, nil]
264
384
  # @param resolved_generic_values [Hash{String => ComplexType, ComplexType::UniqueType}] Added to as types are encountered or resolved
265
385
  # @return [UniqueType, ComplexType]
266
386
  def resolve_generics_from_context generics_to_resolve, context_type, resolved_generic_values: {}
267
387
  if name == ComplexType::GENERIC_TAG_NAME
268
388
  type_param = subtypes.first&.name
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,21 +451,19 @@ 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)
330
458
  else
331
459
  next ComplexType::UNDEFINED
332
460
  end
333
- elsif context_type.all?(&:implicit_union?)
334
- if idx == 0 && !context_type.all_params.empty?
335
- ComplexType.new(context_type.all_params)
336
- else
337
- ComplexType::UNDEFINED
338
- end
461
+ # @todo Treating parameterized classes and tuples the same for now
462
+ # elsif context_type.all?(&:implicit_union?) || true
463
+ elsif idx.zero? && !context_type.all_params.empty?
464
+ ComplexType.new(context_type.all_params)
339
465
  else
340
- context_type.all_params[idx] || definitions.generic_defaults[generic_name] || ComplexType::UNDEFINED
466
+ ComplexType::UNDEFINED
341
467
  end
342
468
  else
343
469
  t
@@ -352,6 +478,13 @@ module Solargraph
352
478
  [block.yield(self)]
353
479
  end
354
480
 
481
+ # @yieldparam t [self]
482
+ # @yieldreturn [self]
483
+ # @return [Enumerable<self>]
484
+ def each(&)
485
+ [self].each(&)
486
+ end
487
+
355
488
  # @return [Array<UniqueType>]
356
489
  def to_a
357
490
  [self]
@@ -360,16 +493,17 @@ module Solargraph
360
493
  # @param new_name [String, nil]
361
494
  # @param make_rooted [Boolean, nil]
362
495
  # @param new_key_types [Array<ComplexType>, nil]
363
- # @param rooted [Boolean, nil]
496
+ # @param make_rooted [Boolean, nil]
364
497
  # @param new_subtypes [Array<ComplexType>, nil]
365
498
  # @return [self]
366
- def recreate(new_name: nil, make_rooted: nil, new_key_types: nil, new_subtypes: nil)
499
+ def recreate new_name: nil, make_rooted: nil, new_key_types: nil, new_subtypes: nil
367
500
  raise "Please remove leading :: and set rooted instead - #{new_name}" if new_name&.start_with?('::')
368
501
 
369
502
  new_name ||= name
370
503
  new_key_types ||= @key_types
371
504
  new_subtypes ||= @subtypes
372
505
  make_rooted = @rooted if make_rooted.nil?
506
+ # @sg-ignore flow sensitive typing needs better handling of ||= on lvars
373
507
  UniqueType.new(new_name, new_key_types, new_subtypes, rooted: make_rooted, parameters_type: parameters_type)
374
508
  end
375
509
 
@@ -396,8 +530,10 @@ module Solargraph
396
530
  # @yieldparam t [UniqueType]
397
531
  # @yieldreturn [self]
398
532
  # @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?('::')
533
+ def transform new_name = nil, &transform_type
534
+ if new_name&.start_with?('::')
535
+ raise "Please remove leading :: and set rooted with recreate() instead - #{new_name}"
536
+ end
401
537
  if name == ComplexType::GENERIC_TAG_NAME
402
538
  # doesn't make sense to manipulate the name of the generic
403
539
  new_key_types = @key_types
@@ -406,14 +542,15 @@ module Solargraph
406
542
  new_key_types = @key_types.flat_map { |ct| ct.items.map { |ut| ut.transform(&transform_type) } }
407
543
  new_subtypes = @subtypes.flat_map { |ct| ct.items.map { |ut| ut.transform(&transform_type) } }
408
544
  end
409
- new_type = recreate(new_name: new_name || name, new_key_types: new_key_types, new_subtypes: new_subtypes, make_rooted: @rooted)
545
+ new_type = recreate(new_name: new_name || name, new_key_types: new_key_types, new_subtypes: new_subtypes,
546
+ make_rooted: @rooted)
410
547
  yield new_type
411
548
  end
412
549
 
413
550
  # Generate a ComplexType that fully qualifies this type's namespaces.
414
551
  #
415
552
  # @param api_map [ApiMap] The ApiMap that performs qualification
416
- # @param context [String] The namespace from which to resolve names
553
+ # @param gates [Array<String>] The namespaces from which to resolve names
417
554
  # @return [self, ComplexType, UniqueType] The generated ComplexType
418
555
  def qualify api_map, *gates
419
556
  transform do |t|
@@ -443,6 +580,22 @@ module Solargraph
443
580
  end
444
581
  end
445
582
 
583
+ # @yieldreturn [Boolean]
584
+ def any? &block
585
+ block.yield self
586
+ end
587
+
588
+ # @return [ComplexType]
589
+ def reduce_class_type
590
+ new_items = items.flat_map do |type|
591
+ next type unless %w[Module Class].include?(type.name)
592
+ next type if type.all_params.empty?
593
+
594
+ type.all_params
595
+ end
596
+ ComplexType.new(new_items)
597
+ end
598
+
446
599
  def all_rooted?
447
600
  return true if name == GENERIC_TAG_NAME
448
601
  rooted? && all_params.all?(&:rooted?)
@@ -453,12 +606,12 @@ module Solargraph
453
606
  end
454
607
 
455
608
  # @param name_to_check [String]
456
- def can_root_name?(name_to_check = name)
609
+ def can_root_name? name_to_check = name
457
610
  self.class.can_root_name?(name_to_check)
458
611
  end
459
612
 
460
613
  # @param name [String]
461
- def self.can_root_name?(name)
614
+ def self.can_root_name? name
462
615
  # name is not lowercase
463
616
  !name.empty? && name != name.downcase
464
617
  end
@@ -475,8 +628,13 @@ module Solargraph
475
628
  '::NilClass' => UniqueType::NIL
476
629
  }.freeze
477
630
 
478
-
479
631
  include Logging
632
+
633
+ protected
634
+
635
+ def equality_fields
636
+ [@name, @all_params, @subtypes, @key_types]
637
+ end
480
638
  end
481
639
  end
482
640
  end