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