solargraph 0.58.1 → 0.59.0.dev.1

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