solargraph 0.58.2 → 0.59.0.dev.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) 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 +41 -34
  5. data/.github/workflows/rspec.yml +44 -23
  6. data/.github/workflows/typecheck.yml +2 -2
  7. data/.rubocop.yml +32 -5
  8. data/.rubocop_todo.yml +50 -966
  9. data/Gemfile +3 -1
  10. data/README.md +3 -3
  11. data/Rakefile +26 -23
  12. data/bin/solargraph +2 -1
  13. data/lib/solargraph/api_map/cache.rb +3 -3
  14. data/lib/solargraph/api_map/constants.rb +13 -3
  15. data/lib/solargraph/api_map/index.rb +23 -18
  16. data/lib/solargraph/api_map/source_to_yard.rb +22 -9
  17. data/lib/solargraph/api_map/store.rb +33 -28
  18. data/lib/solargraph/api_map.rb +150 -82
  19. data/lib/solargraph/bench.rb +44 -45
  20. data/lib/solargraph/complex_type/conformance.rb +176 -0
  21. data/lib/solargraph/complex_type/type_methods.rb +28 -17
  22. data/lib/solargraph/complex_type/unique_type.rb +218 -57
  23. data/lib/solargraph/complex_type.rb +170 -57
  24. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -61
  25. data/lib/solargraph/convention/data_definition/data_definition_node.rb +7 -5
  26. data/lib/solargraph/convention/data_definition.rb +5 -2
  27. data/lib/solargraph/convention/gemfile.rb +15 -15
  28. data/lib/solargraph/convention/gemspec.rb +23 -23
  29. data/lib/solargraph/convention/rakefile.rb +17 -17
  30. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +2 -1
  31. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +4 -3
  32. data/lib/solargraph/convention/struct_definition.rb +8 -4
  33. data/lib/solargraph/convention.rb +78 -78
  34. data/lib/solargraph/converters/dd.rb +19 -17
  35. data/lib/solargraph/converters/dl.rb +17 -15
  36. data/lib/solargraph/converters/dt.rb +17 -15
  37. data/lib/solargraph/converters/misc.rb +3 -1
  38. data/lib/solargraph/diagnostics/require_not_found.rb +1 -0
  39. data/lib/solargraph/diagnostics/rubocop.rb +11 -10
  40. data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
  41. data/lib/solargraph/diagnostics/type_check.rb +11 -10
  42. data/lib/solargraph/diagnostics/update_errors.rb +37 -41
  43. data/lib/solargraph/doc_map.rb +133 -373
  44. data/lib/solargraph/equality.rb +4 -4
  45. data/lib/solargraph/gem_pins.rb +21 -20
  46. data/lib/solargraph/language_server/error_codes.rb +20 -20
  47. data/lib/solargraph/language_server/host/diagnoser.rb +1 -1
  48. data/lib/solargraph/language_server/host/dispatch.rb +3 -3
  49. data/lib/solargraph/language_server/host/message_worker.rb +4 -3
  50. data/lib/solargraph/language_server/host/sources.rb +2 -1
  51. data/lib/solargraph/language_server/host.rb +30 -22
  52. data/lib/solargraph/language_server/message/base.rb +97 -97
  53. data/lib/solargraph/language_server/message/client/register_capability.rb +13 -15
  54. data/lib/solargraph/language_server/message/completion_item/resolve.rb +58 -60
  55. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +12 -18
  56. data/lib/solargraph/language_server/message/extended/document.rb +1 -0
  57. data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -32
  58. data/lib/solargraph/language_server/message/extended/download_core.rb +20 -19
  59. data/lib/solargraph/language_server/message/extended/search.rb +20 -20
  60. data/lib/solargraph/language_server/message/initialize.rb +197 -191
  61. data/lib/solargraph/language_server/message/text_document/completion.rb +10 -8
  62. data/lib/solargraph/language_server/message/text_document/definition.rb +41 -32
  63. data/lib/solargraph/language_server/message/text_document/document_highlight.rb +23 -16
  64. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +29 -19
  65. data/lib/solargraph/language_server/message/text_document/formatting.rb +8 -6
  66. data/lib/solargraph/language_server/message/text_document/hover.rb +5 -5
  67. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +18 -11
  68. data/lib/solargraph/language_server/message/text_document/references.rb +23 -16
  69. data/lib/solargraph/language_server/message/text_document/rename.rb +26 -19
  70. data/lib/solargraph/language_server/message/text_document/signature_help.rb +3 -2
  71. data/lib/solargraph/language_server/message/text_document/type_definition.rb +25 -17
  72. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +41 -35
  73. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +48 -40
  74. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +32 -26
  75. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +27 -17
  76. data/lib/solargraph/language_server/message.rb +94 -94
  77. data/lib/solargraph/language_server/request.rb +29 -27
  78. data/lib/solargraph/language_server/transport/data_reader.rb +72 -74
  79. data/lib/solargraph/language_server/uri_helpers.rb +49 -49
  80. data/lib/solargraph/library.rb +85 -44
  81. data/lib/solargraph/location.rb +17 -14
  82. data/lib/solargraph/logging.rb +24 -4
  83. data/lib/solargraph/page.rb +92 -92
  84. data/lib/solargraph/parser/comment_ripper.rb +19 -4
  85. data/lib/solargraph/parser/flow_sensitive_typing.rb +326 -108
  86. data/lib/solargraph/parser/node_processor/base.rb +34 -4
  87. data/lib/solargraph/parser/node_processor.rb +8 -7
  88. data/lib/solargraph/parser/parser_gem/class_methods.rb +32 -14
  89. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +19 -19
  90. data/lib/solargraph/parser/parser_gem/node_chainer.rb +50 -25
  91. data/lib/solargraph/parser/parser_gem/node_methods.rb +91 -70
  92. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +4 -4
  93. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +13 -11
  94. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +9 -0
  95. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +12 -12
  96. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +10 -3
  97. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +38 -37
  98. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +36 -6
  99. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +5 -3
  100. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
  101. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -1
  102. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +3 -3
  103. data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
  104. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -1
  105. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
  106. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +4 -5
  107. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +124 -113
  108. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -29
  109. data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
  110. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +6 -2
  111. data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
  112. data/lib/solargraph/parser/parser_gem.rb +14 -12
  113. data/lib/solargraph/parser/region.rb +9 -3
  114. data/lib/solargraph/parser/snippet.rb +3 -1
  115. data/lib/solargraph/parser.rb +25 -23
  116. data/lib/solargraph/pin/base.rb +126 -80
  117. data/lib/solargraph/pin/base_variable.rb +273 -24
  118. data/lib/solargraph/pin/block.rb +29 -6
  119. data/lib/solargraph/pin/breakable.rb +7 -1
  120. data/lib/solargraph/pin/callable.rb +65 -21
  121. data/lib/solargraph/pin/closure.rb +7 -10
  122. data/lib/solargraph/pin/common.rb +24 -6
  123. data/lib/solargraph/pin/compound_statement.rb +55 -0
  124. data/lib/solargraph/pin/constant.rb +43 -45
  125. data/lib/solargraph/pin/conversions.rb +10 -4
  126. data/lib/solargraph/pin/delegated_method.rb +19 -8
  127. data/lib/solargraph/pin/documenting.rb +4 -2
  128. data/lib/solargraph/pin/instance_variable.rb +5 -1
  129. data/lib/solargraph/pin/keyword.rb +0 -4
  130. data/lib/solargraph/pin/local_variable.rb +15 -59
  131. data/lib/solargraph/pin/method.rb +153 -104
  132. data/lib/solargraph/pin/method_alias.rb +8 -0
  133. data/lib/solargraph/pin/namespace.rb +19 -12
  134. data/lib/solargraph/pin/parameter.rb +100 -36
  135. data/lib/solargraph/pin/proxy_type.rb +4 -1
  136. data/lib/solargraph/pin/reference/override.rb +1 -1
  137. data/lib/solargraph/pin/reference/superclass.rb +2 -0
  138. data/lib/solargraph/pin/reference.rb +19 -0
  139. data/lib/solargraph/pin/search.rb +3 -2
  140. data/lib/solargraph/pin/signature.rb +15 -12
  141. data/lib/solargraph/pin/symbol.rb +2 -1
  142. data/lib/solargraph/pin/until.rb +2 -4
  143. data/lib/solargraph/pin/while.rb +2 -4
  144. data/lib/solargraph/pin.rb +2 -0
  145. data/lib/solargraph/pin_cache.rb +490 -73
  146. data/lib/solargraph/position.rb +14 -10
  147. data/lib/solargraph/range.rb +16 -15
  148. data/lib/solargraph/rbs_map/conversions.rb +343 -214
  149. data/lib/solargraph/rbs_map/core_fills.rb +91 -84
  150. data/lib/solargraph/rbs_map/core_map.rb +24 -17
  151. data/lib/solargraph/rbs_map/stdlib_map.rb +33 -5
  152. data/lib/solargraph/rbs_map.rb +77 -32
  153. data/lib/solargraph/server_methods.rb +16 -16
  154. data/lib/solargraph/shell.rb +128 -73
  155. data/lib/solargraph/source/chain/array.rb +39 -37
  156. data/lib/solargraph/source/chain/call.rb +96 -56
  157. data/lib/solargraph/source/chain/class_variable.rb +13 -13
  158. data/lib/solargraph/source/chain/constant.rb +5 -1
  159. data/lib/solargraph/source/chain/global_variable.rb +13 -13
  160. data/lib/solargraph/source/chain/hash.rb +8 -5
  161. data/lib/solargraph/source/chain/if.rb +12 -10
  162. data/lib/solargraph/source/chain/instance_variable.rb +24 -1
  163. data/lib/solargraph/source/chain/link.rb +99 -109
  164. data/lib/solargraph/source/chain/literal.rb +9 -6
  165. data/lib/solargraph/source/chain/or.rb +10 -4
  166. data/lib/solargraph/source/chain/q_call.rb +13 -11
  167. data/lib/solargraph/source/chain/variable.rb +15 -13
  168. data/lib/solargraph/source/chain/z_super.rb +28 -30
  169. data/lib/solargraph/source/chain.rb +49 -38
  170. data/lib/solargraph/source/change.rb +12 -5
  171. data/lib/solargraph/source/cursor.rb +23 -17
  172. data/lib/solargraph/source/encoding_fixes.rb +6 -7
  173. data/lib/solargraph/source/source_chainer.rb +56 -32
  174. data/lib/solargraph/source/updater.rb +5 -1
  175. data/lib/solargraph/source.rb +59 -35
  176. data/lib/solargraph/source_map/clip.rb +48 -29
  177. data/lib/solargraph/source_map/data.rb +4 -1
  178. data/lib/solargraph/source_map/mapper.rb +71 -42
  179. data/lib/solargraph/source_map.rb +21 -9
  180. data/lib/solargraph/type_checker/problem.rb +3 -1
  181. data/lib/solargraph/type_checker/rules.rb +81 -8
  182. data/lib/solargraph/type_checker.rb +195 -120
  183. data/lib/solargraph/version.rb +1 -1
  184. data/lib/solargraph/workspace/config.rb +13 -10
  185. data/lib/solargraph/workspace/gemspecs.rb +367 -0
  186. data/lib/solargraph/workspace/require_paths.rb +1 -0
  187. data/lib/solargraph/workspace.rb +149 -30
  188. data/lib/solargraph/yard_map/helpers.rb +8 -3
  189. data/lib/solargraph/yard_map/mapper/to_method.rb +13 -7
  190. data/lib/solargraph/yard_map/mapper/to_namespace.rb +2 -1
  191. data/lib/solargraph/yard_map/mapper.rb +13 -8
  192. data/lib/solargraph/yard_tags.rb +20 -20
  193. data/lib/solargraph/yardoc.rb +33 -23
  194. data/lib/solargraph.rb +29 -8
  195. data/rbs/fills/rubygems/0/dependency.rbs +193 -0
  196. data/rbs/fills/tuple/tuple.rbs +28 -0
  197. data/rbs/shims/ast/0/node.rbs +1 -1
  198. data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
  199. data/solargraph.gemspec +36 -34
  200. metadata +38 -33
  201. data/lib/solargraph/type_checker/checks.rb +0 -124
  202. data/lib/solargraph/type_checker/param_def.rb +0 -37
  203. data/lib/solargraph/yard_map/to_method.rb +0 -89
@@ -6,31 +6,127 @@ module Solargraph
6
6
  # include Solargraph::Source::NodeMethods
7
7
  include Solargraph::Parser::NodeMethods
8
8
 
9
- # @return [Parser::AST::Node, nil]
10
- attr_reader :assignment
9
+ # @return [Array<Parser::AST::Node>]
10
+ attr_reader :assignments
11
11
 
12
12
  attr_accessor :mass_assignment
13
13
 
14
+ # @return [Range, nil]
15
+ attr_reader :presence
16
+
14
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
15
22
  # @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
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
18
53
  super(**splat)
19
- @assignment = assignment
54
+ @assignments = (assignment.nil? ? [] : [assignment]) + assignments
20
55
  # @type [nil, ::Array(Parser::AST::Node, Integer)]
21
- @mass_assignment = nil
56
+ @mass_assignment = mass_assignment
22
57
  @return_type = return_type
58
+ @intersection_return_type = intersection_return_type
59
+ @exclude_return_type = exclude_return_type
60
+ @presence = presence
23
61
  end
24
62
 
25
- def combine_with(other, attrs={})
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)
26
87
  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
- })
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
+ })
31
100
  super(other, new_attrs)
32
101
  end
33
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
+
34
130
  def completion_item_kind
35
131
  Solargraph::LanguageServer::CompletionItemKinds::VARIABLE
36
132
  end
@@ -40,10 +136,6 @@ module Solargraph
40
136
  Solargraph::LanguageServer::SymbolKinds::VARIABLE
41
137
  end
42
138
 
43
- def return_type
44
- @return_type ||= generate_complex_type
45
- end
46
-
47
139
  def nil_assignment?
48
140
  # this will always be false - should it be return_type ==
49
141
  # ComplexType::NIL or somesuch?
@@ -57,7 +149,7 @@ module Solargraph
57
149
  # @param parent_node [Parser::AST::Node]
58
150
  # @param api_map [ApiMap]
59
151
  # @return [::Array<ComplexType>]
60
- def return_types_from_node(parent_node, api_map)
152
+ def return_types_from_node parent_node, api_map
61
153
  types = []
62
154
  value_position_nodes_only(parent_node).each do |node|
63
155
  # Nil nodes may not have a location
@@ -67,10 +159,12 @@ module Solargraph
67
159
  rng = Range.from_node(node)
68
160
  next if rng.nil?
69
161
  pos = rng.ending
162
+ # @sg-ignore Need to add nil check here
70
163
  clip = api_map.clip_at(location.filename, pos)
71
164
  # Use the return node for inference. The clip might infer from the
72
165
  # first node in a method call instead of the entire call.
73
166
  chain = Parser.chain(node, nil, nil)
167
+ # @sg-ignore Need to add nil check here
74
168
  result = chain.infer(api_map, closure, clip.locals).self_to_type(closure.context)
75
169
  types.push result unless result.undefined?
76
170
  end
@@ -79,13 +173,15 @@ module Solargraph
79
173
  end
80
174
 
81
175
  # @param api_map [ApiMap]
82
- # @return [ComplexType]
176
+ # @return [ComplexType, ComplexType::UniqueType]
83
177
  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
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?
88
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
89
185
  unless @mass_assignment.nil?
90
186
  mass_node, index = @mass_assignment
91
187
  types = return_types_from_node(mass_node, api_map)
@@ -96,7 +192,10 @@ module Solargraph
96
192
  type.all_params.first
97
193
  end
98
194
  end.compact!
99
- return ComplexType.new(types.uniq) unless types.empty?
195
+
196
+ return ComplexType::UNDEFINED if types.empty?
197
+
198
+ return adjust_type api_map, ComplexType.new(types.uniq).qualify(api_map, *gates)
100
199
  end
101
200
 
102
201
  ComplexType::UNDEFINED
@@ -113,13 +212,163 @@ module Solargraph
113
212
  "#{super} = #{assignment&.type.inspect}"
114
213
  end
115
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
+
116
296
  private
117
297
 
118
- # @return [ComplexType]
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]
119
368
  def generate_complex_type
120
369
  tag = docstring.tag(:type)
121
370
  return ComplexType.try_parse(*tag.types) unless tag.nil? || tag.types.nil? || tag.types.empty?
122
- ComplexType.new
371
+ nil
123
372
  end
124
373
  end
125
374
  end
@@ -15,12 +15,14 @@ module Solargraph
15
15
  # @param node [Parser::AST::Node, nil]
16
16
  # @param context [ComplexType, nil]
17
17
  # @param args [::Array<Parameter>]
18
+ # @param [Hash{Symbol => Object}] splat
18
19
  def initialize receiver: nil, args: [], context: nil, node: nil, **splat
19
20
  super(**splat, parameters: args)
20
21
  @receiver = receiver
21
22
  @context = context
22
23
  @return_type = ComplexType.parse('::Proc')
23
24
  @node = node
25
+ @name = '<block>'
24
26
  end
25
27
 
26
28
  # @param api_map [ApiMap]
@@ -30,14 +32,20 @@ module Solargraph
30
32
  end
31
33
 
32
34
  def binder
33
- @rebind&.defined? ? @rebind : closure.binder
35
+ out = @rebind if @rebind&.defined?
36
+ out ||= super
37
+ end
38
+
39
+ def context
40
+ @context = @rebind if @rebind&.defined?
41
+ super
34
42
  end
35
43
 
36
44
  # @param yield_types [::Array<ComplexType>]
37
45
  # @param parameters [::Array<Parameter>]
38
46
  #
39
47
  # @return [::Array<ComplexType>]
40
- def destructure_yield_types(yield_types, parameters)
48
+ def destructure_yield_types yield_types, parameters
41
49
  # yielding a tuple into a block will destructure the tuple
42
50
  if yield_types.length == 1
43
51
  yield_type = yield_types.first
@@ -48,16 +56,19 @@ module Solargraph
48
56
 
49
57
  # @param api_map [ApiMap]
50
58
  # @return [::Array<ComplexType>]
51
- def typify_parameters(api_map)
59
+ def typify_parameters api_map
52
60
  chain = Parser.chain(receiver, filename, node)
61
+ # @sg-ignore Need to add nil check here
53
62
  clip = api_map.clip_at(location.filename, location.range.start)
54
63
  locals = clip.locals - [self]
64
+ # @sg-ignore Need to add nil check here
55
65
  meths = chain.define(api_map, closure, locals)
56
66
  # @todo Convert logic to use signatures
57
67
  # @param meth [Pin::Method]
58
68
  meths.each do |meth|
59
69
  next if meth.block.nil?
60
70
 
71
+ # @sg-ignore flow sensitive typing needs to handle attrs
61
72
  yield_types = meth.block.parameters.map(&:return_type)
62
73
  # 'arguments' is what the method says it will yield to the
63
74
  # block; 'parameters' is what the block accepts
@@ -67,6 +78,7 @@ module Solargraph
67
78
  param_type = chain.base.infer(api_map, param, locals)
68
79
  unless arg_type.nil?
69
80
  if arg_type.generic? && param_type.defined?
81
+ # @sg-ignore Need to add nil check here
70
82
  namespace_pin = api_map.get_namespace_pins(meth.namespace, closure.namespace).first
71
83
  arg_type.resolve_generics(namespace_pin, param_type)
72
84
  else
@@ -86,16 +98,27 @@ module Solargraph
86
98
  def maybe_rebind api_map
87
99
  return ComplexType::UNDEFINED unless receiver
88
100
 
89
- chain = Parser.chain(receiver, location.filename)
101
+ # @sg-ignore Need to add nil check here
102
+ chain = Parser.chain(receiver, location.filename, node)
103
+ # @sg-ignore Need to add nil check here
90
104
  locals = api_map.source_map(location.filename).locals_at(location)
105
+ # @sg-ignore Need to add nil check here
91
106
  receiver_pin = chain.define(api_map, closure, locals).first
92
107
  return ComplexType::UNDEFINED unless receiver_pin
93
108
 
94
109
  types = receiver_pin.docstring.tag(:yieldreceiver)&.types
95
110
  return ComplexType::UNDEFINED unless types&.any?
96
111
 
97
- target = chain.base.infer(api_map, receiver_pin, locals)
98
- target = full_context unless target.defined?
112
+ name_pin = self
113
+ # if we have Foo.bar { |x| ... }, and the bar method references self...
114
+ target = if chain.base.defined?
115
+ # figure out Foo
116
+ chain.base.infer(api_map, name_pin, locals)
117
+ else
118
+ # if not, any self there must be the context of our closure
119
+ # @sg-ignore Need to add nil check here
120
+ closure.full_context
121
+ end
99
122
 
100
123
  ComplexType.try_parse(*types).qualify(api_map, *receiver_pin.gates).self_to_type(target)
101
124
  end
@@ -1,9 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Solargraph
2
4
  module Pin
3
- # Mix-in for pins which enclose code which the 'break' statement works with-in - e.g., blocks, when, until, ...
5
+ # Mix-in for pins which enclose code which the 'break' statement
6
+ # works with-in - e.g., blocks, when, until, ...
4
7
  module Breakable
5
8
  # @return [Parser::AST::Node]
6
9
  attr_reader :node
10
+
11
+ # @return [Location, nil]
12
+ attr_reader :location
7
13
  end
8
14
  end
9
15
  end