solargraph 0.58.0 → 0.59.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (219) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +3 -0
  3. data/.gitattributes +2 -0
  4. data/.github/workflows/linting.yml +6 -5
  5. data/.github/workflows/plugins.yml +48 -35
  6. data/.github/workflows/rspec.yml +15 -28
  7. data/.github/workflows/typecheck.yml +3 -2
  8. data/.gitignore +1 -0
  9. data/.rubocop.yml +38 -6
  10. data/.rubocop_todo.yml +53 -966
  11. data/CHANGELOG.md +24 -0
  12. data/Gemfile +3 -1
  13. data/README.md +3 -3
  14. data/Rakefile +26 -23
  15. data/bin/solargraph +9 -8
  16. data/lib/solargraph/api_map/cache.rb +110 -110
  17. data/lib/solargraph/api_map/constants.rb +288 -279
  18. data/lib/solargraph/api_map/index.rb +204 -193
  19. data/lib/solargraph/api_map/source_to_yard.rb +110 -97
  20. data/lib/solargraph/api_map/store.rb +395 -384
  21. data/lib/solargraph/api_map.rb +1029 -945
  22. data/lib/solargraph/bench.rb +44 -45
  23. data/lib/solargraph/complex_type/conformance.rb +176 -0
  24. data/lib/solargraph/complex_type/type_methods.rb +240 -228
  25. data/lib/solargraph/complex_type/unique_type.rb +641 -482
  26. data/lib/solargraph/complex_type.rb +557 -444
  27. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -61
  28. data/lib/solargraph/convention/data_definition/data_definition_node.rb +93 -91
  29. data/lib/solargraph/convention/data_definition.rb +108 -105
  30. data/lib/solargraph/convention/gemfile.rb +15 -15
  31. data/lib/solargraph/convention/gemspec.rb +23 -23
  32. data/lib/solargraph/convention/rakefile.rb +17 -17
  33. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +62 -61
  34. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +103 -102
  35. data/lib/solargraph/convention/struct_definition.rb +168 -164
  36. data/lib/solargraph/convention.rb +78 -78
  37. data/lib/solargraph/converters/dd.rb +19 -17
  38. data/lib/solargraph/converters/dl.rb +17 -15
  39. data/lib/solargraph/converters/dt.rb +17 -15
  40. data/lib/solargraph/converters/misc.rb +3 -1
  41. data/lib/solargraph/diagnostics/require_not_found.rb +54 -53
  42. data/lib/solargraph/diagnostics/rubocop.rb +119 -118
  43. data/lib/solargraph/diagnostics/rubocop_helpers.rb +70 -68
  44. data/lib/solargraph/diagnostics/type_check.rb +56 -55
  45. data/lib/solargraph/diagnostics/update_errors.rb +37 -41
  46. data/lib/solargraph/doc_map.rb +438 -439
  47. data/lib/solargraph/equality.rb +34 -34
  48. data/lib/solargraph/gem_pins.rb +98 -98
  49. data/lib/solargraph/language_server/error_codes.rb +20 -20
  50. data/lib/solargraph/language_server/host/diagnoser.rb +89 -89
  51. data/lib/solargraph/language_server/host/dispatch.rb +130 -130
  52. data/lib/solargraph/language_server/host/message_worker.rb +113 -112
  53. data/lib/solargraph/language_server/host/sources.rb +100 -99
  54. data/lib/solargraph/language_server/host.rb +886 -878
  55. data/lib/solargraph/language_server/message/base.rb +97 -97
  56. data/lib/solargraph/language_server/message/client/register_capability.rb +13 -15
  57. data/lib/solargraph/language_server/message/completion_item/resolve.rb +58 -60
  58. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +108 -114
  59. data/lib/solargraph/language_server/message/extended/document.rb +24 -23
  60. data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -32
  61. data/lib/solargraph/language_server/message/extended/download_core.rb +20 -19
  62. data/lib/solargraph/language_server/message/extended/search.rb +20 -20
  63. data/lib/solargraph/language_server/message/initialize.rb +197 -191
  64. data/lib/solargraph/language_server/message/text_document/completion.rb +58 -56
  65. data/lib/solargraph/language_server/message/text_document/definition.rb +49 -40
  66. data/lib/solargraph/language_server/message/text_document/document_highlight.rb +23 -16
  67. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +36 -26
  68. data/lib/solargraph/language_server/message/text_document/formatting.rb +150 -148
  69. data/lib/solargraph/language_server/message/text_document/hover.rb +58 -58
  70. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +18 -11
  71. data/lib/solargraph/language_server/message/text_document/references.rb +23 -16
  72. data/lib/solargraph/language_server/message/text_document/rename.rb +26 -19
  73. data/lib/solargraph/language_server/message/text_document/signature_help.rb +25 -24
  74. data/lib/solargraph/language_server/message/text_document/type_definition.rb +33 -25
  75. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +41 -35
  76. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +48 -40
  77. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +32 -26
  78. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +33 -23
  79. data/lib/solargraph/language_server/message.rb +94 -94
  80. data/lib/solargraph/language_server/request.rb +29 -27
  81. data/lib/solargraph/language_server/transport/data_reader.rb +72 -74
  82. data/lib/solargraph/language_server/uri_helpers.rb +49 -49
  83. data/lib/solargraph/library.rb +702 -683
  84. data/lib/solargraph/location.rb +85 -82
  85. data/lib/solargraph/logging.rb +55 -37
  86. data/lib/solargraph/page.rb +92 -92
  87. data/lib/solargraph/parser/comment_ripper.rb +84 -69
  88. data/lib/solargraph/parser/flow_sensitive_typing.rb +471 -255
  89. data/lib/solargraph/parser/node_processor/base.rb +122 -92
  90. data/lib/solargraph/parser/node_processor.rb +63 -62
  91. data/lib/solargraph/parser/parser_gem/class_methods.rb +165 -149
  92. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +19 -19
  93. data/lib/solargraph/parser/parser_gem/node_chainer.rb +191 -166
  94. data/lib/solargraph/parser/parser_gem/node_methods.rb +507 -486
  95. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +22 -22
  96. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +61 -59
  97. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +24 -15
  98. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +45 -46
  99. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +60 -53
  100. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +38 -37
  101. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +53 -23
  102. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +42 -40
  103. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +30 -29
  104. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +61 -59
  105. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +98 -98
  106. data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
  107. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +17 -17
  108. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +39 -38
  109. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +51 -52
  110. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +302 -291
  111. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -29
  112. data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
  113. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +33 -29
  114. data/lib/solargraph/parser/parser_gem/node_processors.rb +74 -70
  115. data/lib/solargraph/parser/parser_gem.rb +14 -12
  116. data/lib/solargraph/parser/region.rb +75 -69
  117. data/lib/solargraph/parser/snippet.rb +19 -17
  118. data/lib/solargraph/parser.rb +25 -23
  119. data/lib/solargraph/pin/base.rb +773 -729
  120. data/lib/solargraph/pin/base_variable.rb +375 -126
  121. data/lib/solargraph/pin/block.rb +127 -104
  122. data/lib/solargraph/pin/breakable.rb +15 -9
  123. data/lib/solargraph/pin/callable.rb +275 -231
  124. data/lib/solargraph/pin/closure.rb +69 -72
  125. data/lib/solargraph/pin/common.rb +97 -79
  126. data/lib/solargraph/pin/compound_statement.rb +55 -0
  127. data/lib/solargraph/pin/constant.rb +43 -45
  128. data/lib/solargraph/pin/conversions.rb +129 -123
  129. data/lib/solargraph/pin/delegated_method.rb +131 -120
  130. data/lib/solargraph/pin/documenting.rb +116 -114
  131. data/lib/solargraph/pin/instance_variable.rb +38 -34
  132. data/lib/solargraph/pin/keyword.rb +16 -20
  133. data/lib/solargraph/pin/local_variable.rb +31 -75
  134. data/lib/solargraph/pin/method.rb +724 -672
  135. data/lib/solargraph/pin/method_alias.rb +42 -34
  136. data/lib/solargraph/pin/namespace.rb +122 -115
  137. data/lib/solargraph/pin/parameter.rb +339 -275
  138. data/lib/solargraph/pin/proxy_type.rb +42 -39
  139. data/lib/solargraph/pin/reference/override.rb +47 -47
  140. data/lib/solargraph/pin/reference/superclass.rb +17 -15
  141. data/lib/solargraph/pin/reference/type_alias.rb +16 -0
  142. data/lib/solargraph/pin/reference.rb +59 -39
  143. data/lib/solargraph/pin/search.rb +62 -61
  144. data/lib/solargraph/pin/signature.rb +64 -61
  145. data/lib/solargraph/pin/symbol.rb +54 -53
  146. data/lib/solargraph/pin/until.rb +16 -18
  147. data/lib/solargraph/pin/while.rb +16 -18
  148. data/lib/solargraph/pin.rb +46 -44
  149. data/lib/solargraph/pin_cache.rb +248 -245
  150. data/lib/solargraph/position.rb +139 -119
  151. data/lib/solargraph/range.rb +113 -112
  152. data/lib/solargraph/rbs_map/conversions.rb +952 -823
  153. data/lib/solargraph/rbs_map/core_fills.rb +91 -84
  154. data/lib/solargraph/rbs_map/core_map.rb +65 -58
  155. data/lib/solargraph/rbs_map/stdlib_map.rb +71 -43
  156. data/lib/solargraph/rbs_map.rb +207 -163
  157. data/lib/solargraph/server_methods.rb +16 -16
  158. data/lib/solargraph/shell.rb +555 -352
  159. data/lib/solargraph/source/chain/array.rb +39 -37
  160. data/lib/solargraph/source/chain/call.rb +377 -337
  161. data/lib/solargraph/source/chain/class_variable.rb +13 -13
  162. data/lib/solargraph/source/chain/constant.rb +30 -26
  163. data/lib/solargraph/source/chain/global_variable.rb +13 -13
  164. data/lib/solargraph/source/chain/hash.rb +37 -34
  165. data/lib/solargraph/source/chain/if.rb +30 -28
  166. data/lib/solargraph/source/chain/instance_variable.rb +36 -13
  167. data/lib/solargraph/source/chain/link.rb +99 -109
  168. data/lib/solargraph/source/chain/literal.rb +51 -48
  169. data/lib/solargraph/source/chain/or.rb +29 -23
  170. data/lib/solargraph/source/chain/q_call.rb +13 -11
  171. data/lib/solargraph/source/chain/variable.rb +15 -13
  172. data/lib/solargraph/source/chain/z_super.rb +28 -30
  173. data/lib/solargraph/source/chain.rb +304 -291
  174. data/lib/solargraph/source/change.rb +89 -82
  175. data/lib/solargraph/source/cursor.rb +172 -166
  176. data/lib/solargraph/source/encoding_fixes.rb +22 -23
  177. data/lib/solargraph/source/source_chainer.rb +218 -194
  178. data/lib/solargraph/source/updater.rb +59 -55
  179. data/lib/solargraph/source.rb +522 -498
  180. data/lib/solargraph/source_map/clip.rb +245 -226
  181. data/lib/solargraph/source_map/data.rb +37 -34
  182. data/lib/solargraph/source_map/mapper.rb +286 -259
  183. data/lib/solargraph/source_map.rb +224 -212
  184. data/lib/solargraph/type_checker/problem.rb +34 -32
  185. data/lib/solargraph/type_checker/rules.rb +157 -84
  186. data/lib/solargraph/type_checker.rb +888 -814
  187. data/lib/solargraph/version.rb +5 -5
  188. data/lib/solargraph/workspace/config.rb +258 -255
  189. data/lib/solargraph/workspace/gemspecs.rb +367 -0
  190. data/lib/solargraph/workspace/require_paths.rb +98 -97
  191. data/lib/solargraph/workspace.rb +242 -220
  192. data/lib/solargraph/yard_map/helpers.rb +49 -44
  193. data/lib/solargraph/yard_map/mapper/to_method.rb +136 -130
  194. data/lib/solargraph/yard_map/mapper/to_namespace.rb +32 -31
  195. data/lib/solargraph/yard_map/mapper.rb +84 -79
  196. data/lib/solargraph/yard_map.rb +17 -18
  197. data/lib/solargraph/yard_tags.rb +20 -20
  198. data/lib/solargraph/yardoc.rb +90 -87
  199. data/lib/solargraph.rb +128 -105
  200. data/rbs/fills/rubygems/0/dependency.rbs +193 -0
  201. data/rbs/fills/tuple/tuple.rbs +28 -0
  202. data/rbs/shims/ast/0/node.rbs +5 -0
  203. data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
  204. data/rbs_collection.yaml +1 -1
  205. data/solargraph.gemspec +37 -35
  206. metadata +52 -51
  207. data/lib/solargraph/type_checker/checks.rb +0 -124
  208. data/lib/solargraph/type_checker/param_def.rb +0 -37
  209. data/lib/solargraph/yard_map/to_method.rb +0 -89
  210. data/sig/shims/ast/0/node.rbs +0 -5
  211. /data/{sig → rbs}/shims/ast/2.4/.rbs_meta.yaml +0 -0
  212. /data/{sig → rbs}/shims/ast/2.4/ast.rbs +0 -0
  213. /data/{sig → rbs}/shims/parser/3.2.0.1/builders/default.rbs +0 -0
  214. /data/{sig → rbs}/shims/parser/3.2.0.1/manifest.yaml +0 -0
  215. /data/{sig → rbs}/shims/parser/3.2.0.1/parser.rbs +0 -0
  216. /data/{sig → rbs}/shims/parser/3.2.0.1/polyfill.rbs +0 -0
  217. /data/{sig → rbs}/shims/thor/1.2.0.1/.rbs_meta.yaml +0 -0
  218. /data/{sig → rbs}/shims/thor/1.2.0.1/manifest.yaml +0 -0
  219. /data/{sig → rbs}/shims/thor/1.2.0.1/thor.rbs +0 -0
@@ -1,126 +1,375 @@
1
- # frozen_string_literal: true
2
-
3
- module Solargraph
4
- module Pin
5
- class BaseVariable < Base
6
- # include Solargraph::Source::NodeMethods
7
- include Solargraph::Parser::NodeMethods
8
-
9
- # @return [Parser::AST::Node, nil]
10
- attr_reader :assignment
11
-
12
- attr_accessor :mass_assignment
13
-
14
- # @param return_type [ComplexType, nil]
15
- # @param mass_assignment [::Array(Parser::AST::Node, Integer), nil]
16
- # @param assignment [Parser::AST::Node, nil]
17
- def initialize assignment: nil, return_type: nil, mass_assignment: nil, **splat
18
- super(**splat)
19
- @assignment = assignment
20
- # @type [nil, ::Array(Parser::AST::Node, Integer)]
21
- @mass_assignment = nil
22
- @return_type = return_type
23
- end
24
-
25
- def combine_with(other, attrs={})
26
- new_attrs = attrs.merge({
27
- assignment: assert_same(other, :assignment),
28
- mass_assignment: assert_same(other, :mass_assignment),
29
- return_type: combine_return_type(other),
30
- })
31
- super(other, new_attrs)
32
- end
33
-
34
- def completion_item_kind
35
- Solargraph::LanguageServer::CompletionItemKinds::VARIABLE
36
- end
37
-
38
- # @return [Integer]
39
- def symbol_kind
40
- Solargraph::LanguageServer::SymbolKinds::VARIABLE
41
- end
42
-
43
- def return_type
44
- @return_type ||= generate_complex_type
45
- end
46
-
47
- def nil_assignment?
48
- # this will always be false - should it be return_type ==
49
- # ComplexType::NIL or somesuch?
50
- return_type.nil?
51
- end
52
-
53
- def variable?
54
- true
55
- end
56
-
57
- # @param parent_node [Parser::AST::Node]
58
- # @param api_map [ApiMap]
59
- # @return [::Array<ComplexType>]
60
- def return_types_from_node(parent_node, api_map)
61
- types = []
62
- value_position_nodes_only(parent_node).each do |node|
63
- # Nil nodes may not have a location
64
- if node.nil? || node.type == :NIL || node.type == :nil
65
- types.push ComplexType::NIL
66
- else
67
- rng = Range.from_node(node)
68
- next if rng.nil?
69
- pos = rng.ending
70
- clip = api_map.clip_at(location.filename, pos)
71
- # Use the return node for inference. The clip might infer from the
72
- # first node in a method call instead of the entire call.
73
- chain = Parser.chain(node, nil, nil)
74
- result = chain.infer(api_map, closure, clip.locals).self_to_type(closure.context)
75
- types.push result unless result.undefined?
76
- end
77
- end
78
- types
79
- end
80
-
81
- # @param api_map [ApiMap]
82
- # @return [ComplexType]
83
- def probe api_map
84
- unless @assignment.nil?
85
- types = return_types_from_node(@assignment, api_map)
86
- return ComplexType.new(types.uniq) unless types.empty?
87
- end
88
-
89
- unless @mass_assignment.nil?
90
- mass_node, index = @mass_assignment
91
- types = return_types_from_node(mass_node, api_map)
92
- types.map! do |type|
93
- if type.tuple?
94
- type.all_params[index]
95
- elsif ['::Array', '::Set', '::Enumerable'].include?(type.rooted_name)
96
- type.all_params.first
97
- end
98
- end.compact!
99
- return ComplexType.new(types.uniq) unless types.empty?
100
- end
101
-
102
- ComplexType::UNDEFINED
103
- end
104
-
105
- # @param other [Object]
106
- def == other
107
- return false unless super
108
- # @sg-ignore Should add type check on other
109
- assignment == other.assignment
110
- end
111
-
112
- def type_desc
113
- "#{super} = #{assignment&.type.inspect}"
114
- end
115
-
116
- private
117
-
118
- # @return [ComplexType]
119
- def generate_complex_type
120
- tag = docstring.tag(:type)
121
- return ComplexType.try_parse(*tag.types) unless tag.nil? || tag.types.nil? || tag.types.empty?
122
- ComplexType.new
123
- end
124
- end
125
- end
126
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ module Pin
5
+ class BaseVariable < Base
6
+ # include Solargraph::Source::NodeMethods
7
+ include Solargraph::Parser::NodeMethods
8
+
9
+ # @return [Array<Parser::AST::Node>]
10
+ attr_reader :assignments
11
+
12
+ attr_accessor :mass_assignment
13
+
14
+ # @return [Range, nil]
15
+ attr_reader :presence
16
+
17
+ # @param return_type [ComplexType, nil]
18
+ # @param assignment [Parser::AST::Node, nil] First assignment
19
+ # that was made to this variable
20
+ # @param assignments [Array<Parser::AST::Node>] Possible
21
+ # assignments that may have been made to this variable
22
+ # @param mass_assignment [::Array(Parser::AST::Node, Integer), nil]
23
+ # @param assignment [Parser::AST::Node, nil] First assignment
24
+ # that was made to this variable
25
+ # @param assignments [Array<Parser::AST::Node>] Possible
26
+ # assignments that may have been made to this variable
27
+ # @param exclude_return_type [ComplexType, nil] Ensure any
28
+ # return type returned will never include any of these unique
29
+ # types in the unique types of its complex type.
30
+ #
31
+ # Example: If a return type is 'Float | Integer | nil' and the
32
+ # exclude_return_type is 'Integer', the resulting return
33
+ # type will be 'Float | nil' because Integer is excluded.
34
+ # @param intersection_return_type [ComplexType, nil] Ensure each unique
35
+ # return type is compatible with at least one element of this
36
+ # complex type. If a ComplexType used as a return type is an
37
+ # union type - we can return any of these - these are
38
+ # intersection types - everything we return needs to meet at least
39
+ # one of these unique types.
40
+ #
41
+ # Example: If a return type is 'Numeric | nil' and the
42
+ # intersection_return_type is 'Float | nil', the resulting return
43
+ # type will be 'Float | nil' because Float is compatible
44
+ # with Numeric and nil is compatible with nil.
45
+ # @see https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types
46
+ # @see https://en.wikipedia.org/wiki/Intersection_type#TypeScript_example
47
+ # @param presence [Range, nil]
48
+ # @param [Hash{Symbol => Object}] splat
49
+ def initialize assignment: nil, assignments: [], mass_assignment: nil,
50
+ presence: nil, return_type: nil,
51
+ intersection_return_type: nil, exclude_return_type: nil,
52
+ **splat
53
+ super(**splat)
54
+ @assignments = (assignment.nil? ? [] : [assignment]) + assignments
55
+ # @type [nil, ::Array(Parser::AST::Node, Integer)]
56
+ @mass_assignment = mass_assignment
57
+ @return_type = return_type
58
+ @intersection_return_type = intersection_return_type
59
+ @exclude_return_type = exclude_return_type
60
+ @presence = presence
61
+ end
62
+
63
+ # @param presence [Range]
64
+ # @param exclude_return_type [ComplexType, nil]
65
+ # @param intersection_return_type [ComplexType, nil]
66
+ # @param source [::Symbol]
67
+ #
68
+ # @return [self]
69
+ def downcast presence:, exclude_return_type: nil, intersection_return_type: nil,
70
+ source: self.source
71
+ result = dup
72
+ result.exclude_return_type = exclude_return_type
73
+ result.intersection_return_type = intersection_return_type
74
+ result.source = source
75
+ result.presence = presence
76
+ result.reset_generated!
77
+ result
78
+ end
79
+
80
+ def reset_generated!
81
+ @assignment = nil
82
+ super
83
+ end
84
+
85
+ def combine_with other, attrs = {}
86
+ new_assignments = combine_assignments(other)
87
+ new_attrs = attrs.merge({
88
+ # default values don't exist in RBS parameters; it just
89
+ # tells you if the arg is optional or not. Prefer a
90
+ # provided value if we have one here since we can't rely on
91
+ # it from RBS so we can infer from it and typecheck on it.
92
+ assignment: choose(other, :assignment),
93
+ assignments: new_assignments,
94
+ mass_assignment: combine_mass_assignment(other),
95
+ return_type: combine_return_type(other),
96
+ intersection_return_type: combine_types(other, :intersection_return_type),
97
+ exclude_return_type: combine_types(other, :exclude_return_type),
98
+ presence: combine_presence(other)
99
+ })
100
+ super(other, new_attrs)
101
+ end
102
+
103
+ # @param other [self]
104
+ #
105
+ # @return [Array(AST::Node, Integer), nil]
106
+ def combine_mass_assignment other
107
+ # @todo pick first non-nil arbitrarily - we don't yet support
108
+ # mass assignment merging
109
+ mass_assignment || other.mass_assignment
110
+ end
111
+
112
+ # @return [Parser::AST::Node, nil]
113
+ def assignment
114
+ @assignment ||= assignments.last
115
+ end
116
+
117
+ # @param other [self]
118
+ #
119
+ # @return [::Array<Parser::AST::Node>]
120
+ def combine_assignments other
121
+ (other.assignments + assignments).uniq
122
+ end
123
+
124
+ def inner_desc
125
+ super + ", presence=#{presence.inspect}, assignments=#{assignments}, " \
126
+ "intersection_return_type=#{intersection_return_type&.rooted_tags.inspect}, " \
127
+ "exclude_return_type=#{exclude_return_type&.rooted_tags.inspect}"
128
+ end
129
+
130
+ def completion_item_kind
131
+ Solargraph::LanguageServer::CompletionItemKinds::VARIABLE
132
+ end
133
+
134
+ # @return [Integer]
135
+ def symbol_kind
136
+ Solargraph::LanguageServer::SymbolKinds::VARIABLE
137
+ end
138
+
139
+ def nil_assignment?
140
+ # this will always be false - should it be return_type ==
141
+ # ComplexType::NIL or somesuch?
142
+ return_type.nil?
143
+ end
144
+
145
+ def variable?
146
+ true
147
+ end
148
+
149
+ # @param parent_node [Parser::AST::Node]
150
+ # @param api_map [ApiMap]
151
+ # @return [::Array<ComplexType>]
152
+ def return_types_from_node parent_node, api_map
153
+ types = []
154
+ value_position_nodes_only(parent_node).each do |node|
155
+ # Nil nodes may not have a location
156
+ if node.nil? || node.type == :NIL || node.type == :nil
157
+ types.push ComplexType::NIL
158
+ else
159
+ rng = Range.from_node(node)
160
+ next if rng.nil?
161
+ pos = rng.ending
162
+ # @sg-ignore Need to add nil check here
163
+ clip = api_map.clip_at(location.filename, pos)
164
+ # Use the return node for inference. The clip might infer from the
165
+ # first node in a method call instead of the entire call.
166
+ chain = Parser.chain(node, nil, nil)
167
+ # @sg-ignore Need to add nil check here
168
+ result = chain.infer(api_map, closure, clip.locals).self_to_type(closure.context)
169
+ types.push result unless result.undefined?
170
+ end
171
+ end
172
+ types
173
+ end
174
+
175
+ # @param api_map [ApiMap]
176
+ # @return [ComplexType, ComplexType::UniqueType]
177
+ def probe api_map
178
+ assignment_types = assignments.flat_map { |node| return_types_from_node(node, api_map) }
179
+ type_from_assignment = ComplexType.new(assignment_types.flat_map(&:items).uniq) unless assignment_types.empty?
180
+ return adjust_type api_map, type_from_assignment unless type_from_assignment.nil?
181
+
182
+ # @todo should handle merging types from mass assignments as
183
+ # well so that we can do better flow sensitive typing with
184
+ # multiple assignments
185
+ unless @mass_assignment.nil?
186
+ mass_node, index = @mass_assignment
187
+ types = return_types_from_node(mass_node, api_map)
188
+ types.map! do |type|
189
+ if type.tuple?
190
+ type.all_params[index]
191
+ elsif ['::Array', '::Set', '::Enumerable'].include?(type.rooted_name)
192
+ type.all_params.first
193
+ end
194
+ end.compact!
195
+
196
+ return ComplexType::UNDEFINED if types.empty?
197
+
198
+ return adjust_type api_map, ComplexType.new(types.uniq).qualify(api_map, *gates)
199
+ end
200
+
201
+ ComplexType::UNDEFINED
202
+ end
203
+
204
+ # @param other [Object]
205
+ def == other
206
+ return false unless super
207
+ # @sg-ignore Should add type check on other
208
+ assignment == other.assignment
209
+ end
210
+
211
+ def type_desc
212
+ "#{super} = #{assignment&.type.inspect}"
213
+ end
214
+
215
+ # @return [ComplexType, nil]
216
+ def return_type
217
+ generate_complex_type || @return_type || intersection_return_type || ComplexType::UNDEFINED
218
+ end
219
+
220
+ def typify api_map
221
+ raw_return_type = super
222
+
223
+ adjust_type(api_map, raw_return_type)
224
+ end
225
+
226
+ # @sg-ignore need boolish support for ? methods
227
+ def presence_certain?
228
+ exclude_return_type || intersection_return_type
229
+ end
230
+
231
+ # @param other_loc [Location]
232
+ # @sg-ignore flow sensitive typing needs to handle attrs
233
+ def starts_at? other_loc
234
+ location&.filename == other_loc.filename &&
235
+ presence &&
236
+ # @sg-ignore flow sensitive typing needs to handle attrs
237
+ presence.start == other_loc.range.start
238
+ end
239
+
240
+ # Narrow the presence range to the intersection of both.
241
+ #
242
+ # @param other [self]
243
+ #
244
+ # @return [Range, nil]
245
+ def combine_presence other
246
+ return presence || other.presence if presence.nil? || other.presence.nil?
247
+
248
+ # @sg-ignore flow sensitive typing needs to handle attrs
249
+ Range.new([presence.start, other.presence.start].max, [presence.ending, other.presence.ending].min)
250
+ end
251
+
252
+ # @param other [self]
253
+ # @return [Pin::Closure, nil]
254
+ def combine_closure other
255
+ return closure if closure == other.closure
256
+
257
+ # choose first defined, as that establishes the scope of the variable
258
+ if closure.nil? || other.closure.nil?
259
+ Solargraph.assert_or_log(:varible_closure_missing) do
260
+ 'One of the local variables being combined is missing a closure: ' \
261
+ "#{inspect} vs #{other.inspect}"
262
+ end
263
+ return closure || other.closure
264
+ end
265
+
266
+ # @sg-ignore flow sensitive typing needs to handle attrs
267
+ if closure.location.nil? || other.closure.location.nil?
268
+ # @sg-ignore flow sensitive typing needs to handle attrs
269
+ return closure.location.nil? ? other.closure : closure
270
+ end
271
+
272
+ # if filenames are different, this will just pick one
273
+ # @sg-ignore flow sensitive typing needs to handle attrs
274
+ return closure if closure.location <= other.closure.location
275
+
276
+ other.closure
277
+ end
278
+
279
+ # @param other_closure [Pin::Closure]
280
+ # @param other_loc [Location]
281
+ def visible_at? other_closure, other_loc
282
+ # @sg-ignore flow sensitive typing needs to handle attrs
283
+ location.filename == other_loc.filename &&
284
+ # @sg-ignore flow sensitive typing needs to handle attrs
285
+ (!presence || presence.include?(other_loc.range.start)) &&
286
+ visible_in_closure?(other_closure)
287
+ end
288
+
289
+ protected
290
+
291
+ attr_accessor :exclude_return_type, :intersection_return_type
292
+
293
+ # @return [Range]
294
+ attr_writer :presence
295
+
296
+ private
297
+
298
+ # @param api_map [ApiMap]
299
+ # @param raw_return_type [ComplexType, ComplexType::UniqueType]
300
+ #
301
+ # @return [ComplexType, ComplexType::UniqueType]
302
+ def adjust_type api_map, raw_return_type
303
+ qualified_exclude = exclude_return_type&.qualify(api_map, *(closure&.gates || ['']))
304
+ minus_exclusions = raw_return_type.exclude qualified_exclude, api_map
305
+ qualified_intersection = intersection_return_type&.qualify(api_map, *(closure&.gates || ['']))
306
+ minus_exclusions.intersect_with qualified_intersection, api_map
307
+ end
308
+
309
+ # See if this variable is visible within 'viewing_closure'
310
+ #
311
+ # @param viewing_closure [Pin::Closure]
312
+ # @return [Boolean]
313
+ def visible_in_closure? viewing_closure
314
+ return false if closure.nil?
315
+
316
+ # if we're declared at top level, we can't be seen from within
317
+ # methods declared tere
318
+
319
+ # @sg-ignore Need to add nil check here
320
+ return false if viewing_closure.is_a?(Pin::Method) && closure.context.tags == 'Class<>'
321
+
322
+ # @sg-ignore Need to add nil check here
323
+ return true if viewing_closure.binder.namespace == closure.binder.namespace
324
+
325
+ # @sg-ignore Need to add nil check here
326
+ return true if viewing_closure.return_type == closure.context
327
+
328
+ # classes and modules can't see local variables declared
329
+ # in their parent closure, so stop here
330
+ return false if scope == :instance && viewing_closure.is_a?(Pin::Namespace)
331
+
332
+ parent_of_viewing_closure = viewing_closure.closure
333
+
334
+ return false if parent_of_viewing_closure.nil?
335
+
336
+ visible_in_closure?(parent_of_viewing_closure)
337
+ end
338
+
339
+ # @param other [self]
340
+ # @return [ComplexType, nil]
341
+ def combine_return_type other
342
+ combine_types(other, :return_type)
343
+ end
344
+
345
+ # @param other [self]
346
+ # @param attr [::Symbol]
347
+ #
348
+ # @return [ComplexType, nil]
349
+ def combine_types other, attr
350
+ # @type [ComplexType, nil]
351
+ type1 = send(attr)
352
+ # @type [ComplexType, nil]
353
+ type2 = other.send(attr)
354
+ if type1 && type2
355
+ types = (type1.items + type2.items).uniq
356
+ ComplexType.new(types)
357
+ else
358
+ type1 || type2
359
+ end
360
+ end
361
+
362
+ # @return [::Symbol]
363
+ def scope
364
+ :instance
365
+ end
366
+
367
+ # @return [ComplexType, nil]
368
+ def generate_complex_type
369
+ tag = docstring.tag(:type)
370
+ return ComplexType.try_parse(*tag.types) unless tag.nil? || tag.types.nil? || tag.types.empty?
371
+ nil
372
+ end
373
+ end
374
+ end
375
+ end