solargraph 0.58.3 → 0.60.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (238) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +3 -0
  3. data/.github/workflows/linting.yml +12 -5
  4. data/.github/workflows/plugins.yml +53 -37
  5. data/.github/workflows/rspec.yml +18 -28
  6. data/.github/workflows/typecheck.yml +6 -3
  7. data/.rubocop.yml +39 -6
  8. data/.rubocop_todo.yml +53 -966
  9. data/CHANGELOG.md +67 -0
  10. data/Gemfile +6 -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 +13 -4
  16. data/lib/solargraph/api_map/index.rb +42 -20
  17. data/lib/solargraph/api_map/source_to_yard.rb +22 -9
  18. data/lib/solargraph/api_map/store.rb +61 -36
  19. data/lib/solargraph/api_map.rb +191 -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 +225 -63
  24. data/lib/solargraph/complex_type.rb +190 -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 +39 -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 +63 -40
  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 +222 -72
  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 +73 -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 +157 -85
  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 +67 -23
  138. data/lib/solargraph/pin/closure.rb +7 -10
  139. data/lib/solargraph/pin/common.rb +36 -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 +208 -113
  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 +227 -238
  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/rbs_translator.rb +206 -0
  174. data/lib/solargraph/server_methods.rb +1 -1
  175. data/lib/solargraph/shell.rb +330 -71
  176. data/lib/solargraph/source/chain/array.rb +3 -12
  177. data/lib/solargraph/source/chain/block_symbol.rb +13 -13
  178. data/lib/solargraph/source/chain/block_variable.rb +13 -13
  179. data/lib/solargraph/source/chain/call.rb +159 -89
  180. data/lib/solargraph/source/chain/class_variable.rb +1 -1
  181. data/lib/solargraph/source/chain/constant.rb +5 -1
  182. data/lib/solargraph/source/chain/global_variable.rb +1 -1
  183. data/lib/solargraph/source/chain/hash.rb +8 -5
  184. data/lib/solargraph/source/chain/head.rb +19 -19
  185. data/lib/solargraph/source/chain/if.rb +12 -10
  186. data/lib/solargraph/source/chain/instance_variable.rb +19 -1
  187. data/lib/solargraph/source/chain/link.rb +12 -22
  188. data/lib/solargraph/source/chain/literal.rb +22 -15
  189. data/lib/solargraph/source/chain/or.rb +10 -4
  190. data/lib/solargraph/source/chain/q_call.rb +2 -0
  191. data/lib/solargraph/source/chain/variable.rb +3 -1
  192. data/lib/solargraph/source/chain/z_super.rb +1 -3
  193. data/lib/solargraph/source/chain.rb +87 -43
  194. data/lib/solargraph/source/change.rb +12 -5
  195. data/lib/solargraph/source/cursor.rb +33 -18
  196. data/lib/solargraph/source/encoding_fixes.rb +6 -7
  197. data/lib/solargraph/source/source_chainer.rb +56 -32
  198. data/lib/solargraph/source/updater.rb +5 -1
  199. data/lib/solargraph/source.rb +71 -43
  200. data/lib/solargraph/source_map/clip.rb +54 -30
  201. data/lib/solargraph/source_map/data.rb +4 -1
  202. data/lib/solargraph/source_map/mapper.rb +30 -133
  203. data/lib/solargraph/source_map.rb +35 -9
  204. data/lib/solargraph/type_checker/problem.rb +3 -1
  205. data/lib/solargraph/type_checker/rules.rb +81 -8
  206. data/lib/solargraph/type_checker.rb +208 -125
  207. data/lib/solargraph/version.rb +1 -1
  208. data/lib/solargraph/workspace/config.rb +14 -11
  209. data/lib/solargraph/workspace/gemspecs.rb +373 -0
  210. data/lib/solargraph/workspace/require_paths.rb +1 -0
  211. data/lib/solargraph/workspace.rb +50 -28
  212. data/lib/solargraph/yard_map/cache.rb +25 -25
  213. data/lib/solargraph/yard_map/directives/attribute_directive.rb +65 -0
  214. data/lib/solargraph/yard_map/directives/domain_directive.rb +30 -0
  215. data/lib/solargraph/yard_map/directives/method_directive.rb +51 -0
  216. data/lib/solargraph/yard_map/directives/override_directive.rb +30 -0
  217. data/lib/solargraph/yard_map/directives/parse_directive.rb +53 -0
  218. data/lib/solargraph/yard_map/directives/visibility_directive.rb +70 -0
  219. data/lib/solargraph/yard_map/directives.rb +35 -0
  220. data/lib/solargraph/yard_map/helpers.rb +8 -3
  221. data/lib/solargraph/yard_map/macro.rb +113 -0
  222. data/lib/solargraph/yard_map/mapper/to_constant.rb +28 -28
  223. data/lib/solargraph/yard_map/mapper/to_method.rb +13 -7
  224. data/lib/solargraph/yard_map/mapper/to_namespace.rb +2 -1
  225. data/lib/solargraph/yard_map/mapper.rb +65 -9
  226. data/lib/solargraph/yard_map.rb +19 -18
  227. data/lib/solargraph/yard_tags.rb +2 -2
  228. data/lib/solargraph/yardoc.rb +7 -4
  229. data/lib/solargraph.rb +34 -10
  230. data/rbs/fills/rubygems/0/dependency.rbs +193 -0
  231. data/rbs/shims/ast/0/node.rbs +1 -1
  232. data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
  233. data/solargraph.gemspec +39 -35
  234. metadata +77 -41
  235. data/lib/solargraph/type_checker/checks.rb +0 -124
  236. data/lib/solargraph/type_checker/param_def.rb +0 -37
  237. data/lib/solargraph/yard_map/to_method.rb +0 -89
  238. 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,78 @@ 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, rules) 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
+ # @param rules [Array<Symbol>]
249
+ # @return [Boolean]
250
+ def duck_types_match? api_map, expected, inferred, rules = []
251
+ raise ArgumentError, 'Expected type must be duck type' unless expected.duck_type?
252
+ allow_any_match = rules.include?(:allow_any_match)
253
+ expected.each do |exp|
254
+ next unless exp.duck_type?
255
+ quack = exp.to_s[1..] || ''
256
+ matched = allow_any_match ? inferred.any? { |inf| duck_type_provides?(api_map, inf, quack) } : inferred.all? { |inf| duck_type_provides?(api_map, inf, quack) }
257
+ return false unless matched
258
+ end
259
+ true
260
+ end
261
+
262
+ # @param api_map [ApiMap]
263
+ # @param inf [UniqueType]
264
+ # @param quack [String]
265
+ # @return [Boolean]
266
+ def duck_type_provides? api_map, inf, quack
267
+ return true if inf.duck_type? && inf.to_s[1..] == quack
268
+
269
+ !api_map.get_method_stack(inf.namespace, quack, scope: inf.scope).empty?
270
+ end
271
+ private :duck_type_provides?
272
+
197
273
  # @return [String]
198
274
  def rooted_tags
199
275
  map(&:rooted_tag).join(', ')
@@ -201,14 +277,14 @@ module Solargraph
201
277
 
202
278
  # @yieldparam [UniqueType]
203
279
  def all? &block
204
- @items.all? &block
280
+ @items.all?(&block)
205
281
  end
206
282
 
207
283
  # @yieldparam [UniqueType]
208
284
  # @yieldreturn [Boolean]
209
285
  # @return [Boolean]
210
286
  def any? &block
211
- @items.compact.any? &block
287
+ @items.compact.any?(&block)
212
288
  end
213
289
 
214
290
  def selfy?
@@ -228,11 +304,17 @@ module Solargraph
228
304
  # @yieldparam t [UniqueType]
229
305
  # @yieldreturn [UniqueType]
230
306
  # @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?('::')
307
+ def transform new_name = nil, &transform_type
308
+ if new_name&.start_with?('::')
309
+ raise "Please remove leading :: and set rooted with recreate() instead - #{new_name}"
310
+ end
233
311
  ComplexType.new(map { |ut| ut.transform(new_name, &transform_type) })
234
312
  end
235
313
 
314
+ def expand named_types
315
+ ComplexType.new(map { |ut| ut.expand(named_types) })
316
+ end
317
+
236
318
  # @return [self]
237
319
  def force_rooted
238
320
  transform do |t|
@@ -252,6 +334,13 @@ module Solargraph
252
334
  @items.any?(&:nil_type?)
253
335
  end
254
336
 
337
+ # @return [ComplexType]
338
+ def without_nil
339
+ new_items = @items.reject(&:nil_type?)
340
+ return ComplexType::UNDEFINED if new_items.empty?
341
+ ComplexType.new(new_items)
342
+ end
343
+
255
344
  # @return [Array<ComplexType>]
256
345
  def all_params
257
346
  @items.first.all_params || []
@@ -260,7 +349,7 @@ module Solargraph
260
349
  # @return [ComplexType]
261
350
  def reduce_class_type
262
351
  new_items = items.flat_map do |type|
263
- next type unless ['Module', 'Class'].include?(type.name)
352
+ next type unless %w[Module Class].include?(type.name)
264
353
  next type if type.all_params.empty?
265
354
 
266
355
  type.all_params
@@ -274,6 +363,13 @@ module Solargraph
274
363
  all?(&:all_rooted?)
275
364
  end
276
365
 
366
+ # @param other [ComplexType, UniqueType]
367
+ def erased_version_of? other
368
+ return false if items.length != 1 || other.items.length != 1
369
+
370
+ @items.first.erased_version_of?(other.items.first)
371
+ end
372
+
277
373
  # every top-level type has resolved to be fully qualified; see
278
374
  # #all_rooted? to check their subtypes as well
279
375
  def rooted?
@@ -282,12 +378,46 @@ module Solargraph
282
378
 
283
379
  attr_reader :items
284
380
 
285
- def rooted?
286
- @items.all?(&:rooted?)
381
+ # @param exclude_types [ComplexType, nil]
382
+ # @param api_map [ApiMap]
383
+ # @return [ComplexType, self]
384
+ def exclude exclude_types, api_map
385
+ return self if exclude_types.nil?
386
+
387
+ types = items - exclude_types.items
388
+ types = [ComplexType::UniqueType::UNDEFINED] if types.empty?
389
+ ComplexType.new(types)
390
+ end
391
+
392
+ # @see https://en.wikipedia.org/wiki/Intersection_type
393
+ #
394
+ # @param intersection_type [ComplexType, ComplexType::UniqueType, nil]
395
+ # @param api_map [ApiMap]
396
+ # @return [self, ComplexType::UniqueType]
397
+ def intersect_with intersection_type, api_map
398
+ return self if intersection_type.nil?
399
+ return intersection_type if undefined?
400
+ types = []
401
+ # try to find common types via conformance
402
+ items.each do |ut|
403
+ intersection_type.each do |int_type|
404
+ if int_type.conforms_to?(api_map, ut, :assignment)
405
+ types << int_type
406
+ elsif ut.conforms_to?(api_map, int_type, :assignment)
407
+ types << ut
408
+ end
409
+ end
410
+ end
411
+ types = [ComplexType::UniqueType::UNDEFINED] if types.empty?
412
+ ComplexType.new(types)
287
413
  end
288
414
 
289
415
  protected
290
416
 
417
+ def equality_fields
418
+ [self.class, items]
419
+ end
420
+
291
421
  # @return [ComplexType]
292
422
  def reduce_object
293
423
  new_items = items.flat_map do |ut|
@@ -307,30 +437,29 @@ module Solargraph
307
437
  # @example
308
438
  # ComplexType.parse 'String', 'Foo', 'nil' #=> [String, Foo, nil]
309
439
  #
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
- #
440
+ # @param partial [Boolean] if true, method is receiving a string
441
+ # that will be used inside another ComplexType. It returns
442
+ # arrays of ComplexTypes instead of a single cohesive one.
443
+ # Consumers should not need to use this parameter; it should
444
+ # only be used internally.
317
445
  # @param strings [Array<String>] The type definitions to parse
318
446
  # @return [ComplexType]
319
447
  # # @overload parse(*strings, partial: false)
320
448
  # # @todo Need ability to use a literal true as a type below
321
449
  # # @param partial [Boolean] True if the string is part of a another type
322
450
  # # @return [Array<UniqueType>]
323
- # @todo To be able to select the right signature above,
451
+ # @sg-ignore To be able to select the right signature above,
324
452
  # Chain::Call needs to know the decl type (:arg, :optarg,
325
453
  # :kwarg, etc) of the arguments given, instead of just having
326
454
  # an array of Chains as the arguments.
327
455
  def parse *strings, partial: false
328
- # @type [Hash{Array<String> => ComplexType}]
456
+ # @type [Hash{Array<String> => ComplexType, Array<ComplexType::UniqueType>}]
329
457
  @cache ||= {}
330
458
  unless partial
331
459
  cached = @cache[strings]
332
460
  return cached unless cached.nil?
333
461
  end
462
+ # @types [Array<ComplexType::UniqueType>]
334
463
  types = []
335
464
  key_types = nil
336
465
  strings.each do |type_string|
@@ -342,15 +471,16 @@ module Solargraph
342
471
  # @param char [String]
343
472
  type_string&.each_char do |char|
344
473
  if char == '='
345
- #raise ComplexTypeError, "Invalid = in type #{type_string}" unless curly_stack > 0
474
+ # raise ComplexTypeError, "Invalid = in type #{type_string}" unless curly_stack > 0
346
475
  elsif char == '<'
347
476
  point_stack += 1
348
477
  elsif char == '>'
349
- if subtype_string.end_with?('=') && curly_stack > 0
478
+ if subtype_string.end_with?('=') && curly_stack.positive?
350
479
  subtype_string += char
351
480
  elsif base.end_with?('=')
352
- raise ComplexTypeError, "Invalid hash thing" unless key_types.nil?
481
+ raise ComplexTypeError, 'Invalid hash thing' unless key_types.nil?
353
482
  # types.push ComplexType.new([UniqueType.new(base[0..-2].strip)])
483
+ # @sg-ignore Need to add nil check here
354
484
  types.push UniqueType.parse(base[0..-2].strip, subtype_string)
355
485
  # @todo this should either expand key_type's type
356
486
  # automatically or complain about not being
@@ -361,7 +491,7 @@ module Solargraph
361
491
  subtype_string.clear
362
492
  next
363
493
  else
364
- raise ComplexTypeError, "Invalid close in type #{type_string}" if point_stack == 0
494
+ raise ComplexTypeError, "Invalid close in type #{type_string}" if point_stack.zero?
365
495
  point_stack -= 1
366
496
  subtype_string += char
367
497
  end
@@ -371,34 +501,37 @@ module Solargraph
371
501
  elsif char == '}'
372
502
  curly_stack -= 1
373
503
  subtype_string += char
374
- raise ComplexTypeError, "Invalid close in type #{type_string}" if curly_stack < 0
504
+ raise ComplexTypeError, "Invalid close in type #{type_string}" if curly_stack.negative?
375
505
  next
376
506
  elsif char == '('
377
507
  paren_stack += 1
378
508
  elsif char == ')'
379
509
  paren_stack -= 1
380
510
  subtype_string += char
381
- raise ComplexTypeError, "Invalid close in type #{type_string}" if paren_stack < 0
511
+ raise ComplexTypeError, "Invalid close in type #{type_string}" if paren_stack.negative?
382
512
  next
383
- elsif char == ',' && point_stack == 0 && curly_stack == 0 && paren_stack == 0
513
+ elsif char == ',' && point_stack.zero? && curly_stack.zero? && paren_stack.zero?
384
514
  # types.push ComplexType.new([UniqueType.new(base.strip, subtype_string.strip)])
385
515
  types.push UniqueType.parse(base.strip, subtype_string.strip)
386
516
  base.clear
387
517
  subtype_string.clear
388
518
  next
389
519
  end
390
- if point_stack == 0 && curly_stack == 0 && paren_stack == 0
520
+ if point_stack.zero? && curly_stack.zero? && paren_stack.zero?
391
521
  base.concat char
392
522
  else
393
523
  subtype_string.concat char
394
524
  end
395
525
  end
396
- raise ComplexTypeError, "Unclosed subtype in #{type_string}" if point_stack != 0 || curly_stack != 0 || paren_stack != 0
526
+ if point_stack != 0 || curly_stack != 0 || paren_stack != 0
527
+ raise ComplexTypeError,
528
+ "Unclosed subtype in #{type_string}"
529
+ end
397
530
  # types.push ComplexType.new([UniqueType.new(base, subtype_string)])
398
531
  types.push UniqueType.parse(base.strip, subtype_string.strip)
399
532
  end
400
533
  unless key_types.nil?
401
- raise ComplexTypeError, "Invalid use of key/value parameters" unless partial
534
+ raise ComplexTypeError, 'Invalid use of key/value parameters' unless partial
402
535
  return key_types if types.empty?
403
536
  return [key_types, types]
404
537
  end
@@ -410,7 +543,7 @@ module Solargraph
410
543
  # @param strings [Array<String>]
411
544
  # @return [ComplexType]
412
545
  def try_parse *strings
413
- parse *strings
546
+ parse(*strings)
414
547
  rescue ComplexTypeError => e
415
548
  Solargraph.logger.info "Error parsing complex type `#{strings.join(', ')}`: #{e.message}"
416
549
  ComplexType::UNDEFINED
@@ -435,9 +568,7 @@ module Solargraph
435
568
  # @param dst [String]
436
569
  # @return [String]
437
570
  def reduce_class dst
438
- while dst =~ /^(Class|Module)\<(.*?)\>$/
439
- dst = dst.sub(/^(Class|Module)\</, '').sub(/\>$/, '')
440
- end
571
+ dst = dst.sub(/^(Class|Module)</, '').sub(/>$/, '') while dst =~ /^(Class|Module)<(.*?)>$/
441
572
  dst
442
573
  end
443
574
  end