solargraph 0.52.0 → 0.53.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 (157) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/plugins.yml +40 -0
  3. data/.github/workflows/rspec.yml +1 -3
  4. data/.github/workflows/typecheck.yml +34 -0
  5. data/CHANGELOG.md +53 -0
  6. data/README.md +13 -16
  7. data/SPONSORS.md +1 -7
  8. data/lib/solargraph/api_map/cache.rb +59 -21
  9. data/lib/solargraph/api_map/source_to_yard.rb +17 -10
  10. data/lib/solargraph/api_map/store.rb +45 -9
  11. data/lib/solargraph/api_map.rb +178 -113
  12. data/lib/solargraph/bench.rb +3 -2
  13. data/lib/solargraph/cache.rb +29 -5
  14. data/lib/solargraph/complex_type/type_methods.rb +53 -8
  15. data/lib/solargraph/complex_type/unique_type.rb +171 -58
  16. data/lib/solargraph/complex_type.rb +62 -9
  17. data/lib/solargraph/convention.rb +0 -1
  18. data/lib/solargraph/converters/dd.rb +5 -0
  19. data/lib/solargraph/converters/dl.rb +3 -0
  20. data/lib/solargraph/converters/dt.rb +3 -0
  21. data/lib/solargraph/diagnostics/rubocop.rb +8 -7
  22. data/lib/solargraph/diagnostics/rubocop_helpers.rb +1 -0
  23. data/lib/solargraph/diagnostics/type_check.rb +1 -0
  24. data/lib/solargraph/diagnostics.rb +2 -2
  25. data/lib/solargraph/doc_map.rb +171 -0
  26. data/lib/solargraph/gem_pins.rb +64 -0
  27. data/lib/solargraph/language_server/host/cataloger.rb +1 -0
  28. data/lib/solargraph/language_server/host/diagnoser.rb +2 -2
  29. data/lib/solargraph/language_server/host/dispatch.rb +15 -5
  30. data/lib/solargraph/language_server/host/message_worker.rb +4 -0
  31. data/lib/solargraph/language_server/host/sources.rb +7 -4
  32. data/lib/solargraph/language_server/host.rb +35 -7
  33. data/lib/solargraph/language_server/message/completion_item/resolve.rb +3 -1
  34. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +13 -1
  35. data/lib/solargraph/language_server/message/initialize.rb +5 -2
  36. data/lib/solargraph/language_server/message/text_document/hover.rb +2 -0
  37. data/lib/solargraph/language_server/message/text_document.rb +0 -1
  38. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +5 -0
  39. data/lib/solargraph/language_server/transport/adapter.rb +16 -1
  40. data/lib/solargraph/language_server/transport/data_reader.rb +2 -0
  41. data/lib/solargraph/library.rb +71 -12
  42. data/lib/solargraph/location.rb +1 -0
  43. data/lib/solargraph/page.rb +6 -0
  44. data/lib/solargraph/parser/comment_ripper.rb +3 -0
  45. data/lib/solargraph/parser/node_methods.rb +47 -8
  46. data/lib/solargraph/parser/node_processor/base.rb +9 -0
  47. data/lib/solargraph/parser/{legacy → parser_gem}/class_methods.rb +29 -3
  48. data/lib/solargraph/parser/{legacy → parser_gem}/flawed_builder.rb +3 -1
  49. data/lib/solargraph/parser/{legacy → parser_gem}/node_chainer.rb +42 -34
  50. data/lib/solargraph/parser/{legacy → parser_gem}/node_methods.rb +201 -29
  51. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/alias_node.rb +1 -1
  52. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/args_node.rb +4 -1
  53. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/begin_node.rb +1 -1
  54. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/block_node.rb +3 -2
  55. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/casgn_node.rb +2 -2
  56. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/cvasgn_node.rb +1 -1
  57. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/def_node.rb +7 -20
  58. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/defs_node.rb +2 -2
  59. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/gvasgn_node.rb +1 -1
  60. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/ivasgn_node.rb +2 -2
  61. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/lvasgn_node.rb +2 -2
  62. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/namespace_node.rb +2 -2
  63. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/orasgn_node.rb +1 -1
  64. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/resbody_node.rb +3 -3
  65. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/sclass_node.rb +1 -1
  66. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/send_node.rb +2 -2
  67. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/sym_node.rb +1 -1
  68. data/lib/solargraph/parser/parser_gem/node_processors.rb +54 -0
  69. data/lib/solargraph/parser/parser_gem.rb +12 -0
  70. data/lib/solargraph/parser/snippet.rb +2 -0
  71. data/lib/solargraph/parser.rb +8 -11
  72. data/lib/solargraph/pin/base.rb +63 -8
  73. data/lib/solargraph/pin/base_variable.rb +7 -3
  74. data/lib/solargraph/pin/block.rb +26 -38
  75. data/lib/solargraph/pin/closure.rb +17 -2
  76. data/lib/solargraph/pin/common.rb +7 -3
  77. data/lib/solargraph/pin/conversions.rb +33 -3
  78. data/lib/solargraph/pin/documenting.rb +25 -34
  79. data/lib/solargraph/pin/instance_variable.rb +4 -0
  80. data/lib/solargraph/pin/local_variable.rb +13 -1
  81. data/lib/solargraph/pin/method.rb +110 -16
  82. data/lib/solargraph/pin/namespace.rb +16 -10
  83. data/lib/solargraph/pin/parameter.rb +41 -10
  84. data/lib/solargraph/pin/reference/override.rb +2 -2
  85. data/lib/solargraph/pin/reference.rb +8 -0
  86. data/lib/solargraph/pin/search.rb +3 -3
  87. data/lib/solargraph/pin/signature.rb +114 -2
  88. data/lib/solargraph/pin.rb +0 -1
  89. data/lib/solargraph/range.rb +2 -2
  90. data/lib/solargraph/rbs_map/conversions.rb +213 -61
  91. data/lib/solargraph/rbs_map/core_fills.rb +12 -28
  92. data/lib/solargraph/rbs_map/core_map.rb +2 -12
  93. data/lib/solargraph/rbs_map/stdlib_map.rb +2 -8
  94. data/lib/solargraph/rbs_map.rb +24 -12
  95. data/lib/solargraph/shell.rb +62 -59
  96. data/lib/solargraph/source/chain/array.rb +4 -1
  97. data/lib/solargraph/source/chain/block_symbol.rb +13 -0
  98. data/lib/solargraph/source/chain/call.rb +95 -26
  99. data/lib/solargraph/source/chain/constant.rb +15 -1
  100. data/lib/solargraph/source/chain/if.rb +23 -0
  101. data/lib/solargraph/source/chain/link.rb +7 -1
  102. data/lib/solargraph/source/chain/or.rb +1 -1
  103. data/lib/solargraph/source/chain/z_super.rb +2 -2
  104. data/lib/solargraph/source/chain.rb +20 -4
  105. data/lib/solargraph/source/change.rb +3 -0
  106. data/lib/solargraph/source/cursor.rb +2 -0
  107. data/lib/solargraph/source/source_chainer.rb +6 -5
  108. data/lib/solargraph/source.rb +15 -16
  109. data/lib/solargraph/source_map/clip.rb +14 -9
  110. data/lib/solargraph/source_map/mapper.rb +10 -0
  111. data/lib/solargraph/source_map.rb +12 -10
  112. data/lib/solargraph/type_checker/checks.rb +10 -2
  113. data/lib/solargraph/type_checker.rb +96 -21
  114. data/lib/solargraph/version.rb +1 -1
  115. data/lib/solargraph/workspace/config.rb +8 -6
  116. data/lib/solargraph/workspace.rb +15 -2
  117. data/lib/solargraph/yard_map/cache.rb +6 -0
  118. data/lib/solargraph/yard_map/helpers.rb +1 -1
  119. data/lib/solargraph/yard_map/mapper/to_method.rb +16 -3
  120. data/lib/solargraph/yard_map/to_method.rb +11 -4
  121. data/lib/solargraph/yard_map.rb +0 -292
  122. data/lib/solargraph/yardoc.rb +52 -0
  123. data/lib/solargraph.rb +4 -1
  124. data/solargraph.gemspec +2 -2
  125. metadata +35 -58
  126. data/lib/solargraph/api_map/bundler_methods.rb +0 -22
  127. data/lib/solargraph/documentor.rb +0 -76
  128. data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +0 -23
  129. data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +0 -15
  130. data/lib/solargraph/parser/legacy/node_processors/sym_node.rb +0 -18
  131. data/lib/solargraph/parser/legacy/node_processors.rb +0 -55
  132. data/lib/solargraph/parser/legacy.rb +0 -12
  133. data/lib/solargraph/parser/rubyvm/class_methods.rb +0 -151
  134. data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -163
  135. data/lib/solargraph/parser/rubyvm/node_methods.rb +0 -317
  136. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +0 -85
  137. data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +0 -42
  138. data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +0 -33
  139. data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +0 -23
  140. data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +0 -75
  141. data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +0 -68
  142. data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +0 -23
  143. data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +0 -38
  144. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +0 -39
  145. data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +0 -20
  146. data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +0 -27
  147. data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +0 -39
  148. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +0 -26
  149. data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +0 -15
  150. data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +0 -51
  151. data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +0 -32
  152. data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +0 -15
  153. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +0 -279
  154. data/lib/solargraph/parser/rubyvm/node_processors.rb +0 -64
  155. data/lib/solargraph/parser/rubyvm/node_wrapper.rb +0 -47
  156. data/lib/solargraph/parser/rubyvm.rb +0 -40
  157. data/lib/solargraph/rbs_map/core_signs.rb +0 -33
@@ -7,26 +7,29 @@ module Solargraph
7
7
  # @return [String]
8
8
  attr_reader :word
9
9
 
10
- # @return [Array<Chain>]
10
+ # @return [::Array<Chain>]
11
11
  attr_reader :arguments
12
12
 
13
+ # @return [Chain, nil]
14
+ attr_reader :block
15
+
13
16
  # @param word [String]
14
17
  # @param arguments [::Array<Chain>]
15
- # @param with_block [Boolean] True if the chain is inside a block
16
- # @param head [Boolean] True if the call is the start of its chain
17
- def initialize word, arguments = [], with_block = false
18
+ # @param block [Chain, nil]
19
+ def initialize word, arguments = [], block = nil
18
20
  @word = word
19
21
  @arguments = arguments
20
- @with_block = with_block
22
+ @block = block
23
+ fix_block_pass
21
24
  end
22
25
 
23
26
  def with_block?
24
- @with_block
27
+ !!@block
25
28
  end
26
29
 
27
30
  # @param api_map [ApiMap]
28
31
  # @param name_pin [Pin::Base]
29
- # @param locals [::Array<Pin::Base>]
32
+ # @param locals [::Array<Pin::LocalVariable>]
30
33
  def resolve api_map, name_pin, locals
31
34
  return super_pins(api_map, name_pin) if word == 'super'
32
35
  return yield_pins(api_map, name_pin) if word == 'yield'
@@ -38,7 +41,7 @@ module Solargraph
38
41
  return inferred_pins(found, api_map, name_pin.context, locals) unless found.empty?
39
42
  # @param [ComplexType::UniqueType]
40
43
  pins = name_pin.binder.each_unique_type.flat_map do |context|
41
- api_map.get_method_stack(context.namespace, word, scope: context.scope)
44
+ api_map.get_method_stack(context.namespace == '' ? '' : context.tag, word, scope: context.scope)
42
45
  end
43
46
  return [] if pins.empty?
44
47
  inferred_pins(pins, api_map, name_pin.context, locals)
@@ -46,43 +49,58 @@ module Solargraph
46
49
 
47
50
  private
48
51
 
49
- # @param pins [Array<Pin::Base>]
52
+ # @param pins [::Enumerable<Pin::Method>]
50
53
  # @param api_map [ApiMap]
51
54
  # @param context [ComplexType]
52
- # @param locals [Pin::LocalVariable]
53
- # @return [Array<Pin::Base>]
55
+ # @param locals [::Array<Pin::LocalVariable>]
56
+ # @return [::Array<Pin::Base>]
54
57
  def inferred_pins pins, api_map, context, locals
55
58
  result = pins.map do |p|
56
59
  next p unless p.is_a?(Pin::Method)
57
60
  overloads = p.signatures
58
61
  # next p if overloads.empty?
59
62
  type = ComplexType::UNDEFINED
60
- overloads.each do |ol|
61
- next unless arguments_match(arguments, ol)
62
- # next if ol.parameters.last && ol.parameters.last.first.start_with?('&') && ol.parameters.last.last.nil? && !with_block?
63
+ # start with overloads that require blocks; if we are
64
+ # passing a block, we want to find a signature that will
65
+ # use it. If we didn't pass a block, the logic below will
66
+ # reject it regardless
67
+
68
+ sorted_overloads = overloads.sort { |ol| ol.block? ? -1 : 1 }
69
+ new_signature_pin = nil
70
+ sorted_overloads.each do |ol|
71
+ next unless arity_matches?(arguments, ol)
63
72
  match = true
73
+
74
+ atypes = []
64
75
  arguments.each_with_index do |arg, idx|
65
76
  param = ol.parameters[idx]
66
77
  if param.nil?
67
- match = false unless ol.parameters.any?(&:restarg?)
78
+ match = ol.parameters.any?(&:restarg?)
68
79
  break
69
80
  end
70
- atype = arg.infer(api_map, Pin::ProxyType.anonymous(context), locals)
81
+ atype = atypes[idx] ||= arg.infer(api_map, Pin::ProxyType.anonymous(context), locals)
71
82
  # @todo Weak type comparison
72
83
  # unless atype.tag == param.return_type.tag || api_map.super_and_sub?(param.return_type.tag, atype.tag)
73
- unless param.return_type.undefined? || atype.name == param.return_type.name || api_map.super_and_sub?(param.return_type.name, atype.name)
84
+ unless param.return_type.undefined? || atype.name == param.return_type.name || api_map.super_and_sub?(param.return_type.name, atype.name) || param.return_type.generic?
74
85
  match = false
75
86
  break
76
87
  end
77
88
  end
78
89
  if match
79
- type = with_params(ol.return_type.self_to(context.to_s), context).qualify(api_map, context.namespace) if ol.return_type.defined?
90
+ if ol.block && with_block?
91
+ block_atypes = ol.block.parameters.map(&:return_type)
92
+ blocktype = block_call_type(api_map, context, block_atypes, locals)
93
+ end
94
+ new_signature_pin = ol.resolve_generics_from_context_until_complete(ol.generics, atypes, nil, nil, blocktype)
95
+ new_return_type = new_signature_pin.return_type
96
+ type = with_params(new_return_type.self_to(context.to_s), context).qualify(api_map, context.namespace) if new_return_type.defined?
80
97
  type ||= ComplexType::UNDEFINED
81
98
  end
82
99
  break if type.defined?
83
100
  end
101
+ p = p.with_single_signature(new_signature_pin) unless new_signature_pin.nil?
84
102
  next p.proxy(type) if type.defined?
85
- if p.is_a?(Pin::Method) && !p.macros.empty?
103
+ if !p.macros.empty?
86
104
  result = process_macro(p, api_map, context, locals)
87
105
  next result unless result.return_type.undefined?
88
106
  elsif !p.directives.empty?
@@ -102,13 +120,19 @@ module Solargraph
102
120
  end
103
121
  end
104
122
 
105
- # @param pin [Pin::Method]
123
+ # @param pin [Pin::Base]
106
124
  # @param api_map [ApiMap]
107
125
  # @param context [ComplexType]
108
- # @param locals [Pin::Base]
126
+ # @param locals [Enumerable<Pin::Base>]
109
127
  # @return [Pin::Base]
110
128
  def process_macro pin, api_map, context, locals
111
129
  pin.macros.each do |macro|
130
+ # @todo 'Wrong argument type for
131
+ # Solargraph::Source::Chain::Call#inner_process_macro:
132
+ # macro expected YARD::Tags::MacroDirective, received
133
+ # generic<Elem>' is because we lose 'rooted' information
134
+ # in the 'Chain::Array' class internally, leaving
135
+ # ::Array#each shadowed when it shouldn't be.
112
136
  result = inner_process_macro(pin, macro, api_map, context, locals)
113
137
  return result unless result.return_type.undefined?
114
138
  end
@@ -118,7 +142,7 @@ module Solargraph
118
142
  # @param pin [Pin::Method]
119
143
  # @param api_map [ApiMap]
120
144
  # @param context [ComplexType]
121
- # @param locals [Pin::Base]
145
+ # @param locals [Enumerable<Pin::Base>]
122
146
  # @return [Pin::ProxyType]
123
147
  def process_directive pin, api_map, context, locals
124
148
  pin.directives.each do |dir|
@@ -130,11 +154,11 @@ module Solargraph
130
154
  Pin::ProxyType.anonymous ComplexType::UNDEFINED
131
155
  end
132
156
 
133
- # @param pin [Pin]
157
+ # @param pin [Pin::Base]
134
158
  # @param macro [YARD::Tags::MacroDirective]
135
159
  # @param api_map [ApiMap]
136
160
  # @param context [ComplexType]
137
- # @param locals [Array<Pin::Base>]
161
+ # @param locals [Enumerable<Pin::Base>]
138
162
  # @return [Pin::ProxyType]
139
163
  def inner_process_macro pin, macro, api_map, context, locals
140
164
  vals = arguments.map{ |c| Pin::ProxyType.anonymous(c.infer(api_map, pin, locals)) }
@@ -156,10 +180,22 @@ module Solargraph
156
180
  Pin::ProxyType.anonymous(ComplexType::UNDEFINED)
157
181
  end
158
182
 
159
- # @param arguments [Array<Chain>]
183
+ # @param docstring [YARD::Docstring]
184
+ # @param context [ComplexType]
185
+ # @return [ComplexType, nil]
186
+ def extra_return_type docstring, context
187
+ if docstring.has_tag?('return_single_parameter') #&& context.subtypes.one?
188
+ return context.subtypes.first || ComplexType::UNDEFINED
189
+ elsif docstring.has_tag?('return_value_parameter') && context.value_types.one?
190
+ return context.value_types.first
191
+ end
192
+ nil
193
+ end
194
+
195
+ # @param arguments [::Array<Chain>]
160
196
  # @param signature [Pin::Signature]
161
197
  # @return [Boolean]
162
- def arguments_match arguments, signature
198
+ def arity_matches? arguments, signature
163
199
  parameters = signature.parameters
164
200
  argcount = arguments.length
165
201
  parcount = parameters.length
@@ -189,10 +225,43 @@ module Solargraph
189
225
 
190
226
  # @param type [ComplexType]
191
227
  # @param context [ComplexType]
228
+ # @return [ComplexType]
192
229
  def with_params type, context
193
230
  return type unless type.to_s.include?('$')
194
231
  ComplexType.try_parse(type.to_s.gsub('$', context.value_types.map(&:tag).join(', ')).gsub('<>', ''))
195
232
  end
233
+
234
+ # @return [void]
235
+ def fix_block_pass
236
+ argument = @arguments.last&.links&.first
237
+ @block = @arguments.pop if argument.is_a?(BlockSymbol) || argument.is_a?(BlockVariable)
238
+ end
239
+
240
+ # @param api_map [ApiMap]
241
+ # @param context [ComplexType]
242
+ # @param block_parameter_types [::Array<ComplexType>]
243
+ # @param locals [::Array<Pin::LocalVariable>]
244
+ # @return [ComplexType, nil]
245
+ def block_call_type(api_map, context, block_parameter_types, locals)
246
+ return nil unless with_block?
247
+
248
+ # @todo Handle BlockVariable
249
+ if block.links.map(&:class) == [BlockSymbol]
250
+ # Ruby's shorthand for sending the passed in method name
251
+ # to the first yield parameter with no arguments
252
+ block_symbol_name = block.links.first.word
253
+ block_symbol_call_path = "#{block_parameter_types.first}##{block_symbol_name}"
254
+ callee = api_map.get_path_pins(block_symbol_call_path).first
255
+ return_type = callee&.return_type
256
+ # @todo: Figure out why we get unresolved generics at
257
+ # this point and need to assume method return types
258
+ # based on the generic type
259
+ return_type ||= api_map.get_path_pins("#{context.subtypes.first}##{block.links.first.word}").first&.return_type
260
+ return_type || ComplexType::UNDEFINED
261
+ else
262
+ block.infer(api_map, Pin::ProxyType.anonymous(context), locals)
263
+ end
264
+ end
196
265
  end
197
266
  end
198
267
  end
@@ -19,8 +19,14 @@ module Solargraph
19
19
  end
20
20
  parts = base.split('::')
21
21
  gates.each do |gate|
22
+ # @todo 'Wrong argument type for
23
+ # Solargraph::Source::Chain::Constant#deep_constant_type:
24
+ # gate expected String, received generic<Elem>' is because
25
+ # we lose 'rooted' information in the 'Chain::Array' class
26
+ # internally, leaving ::Array#each shadowed when it
27
+ # shouldn't be.
22
28
  type = deep_constant_type(gate, api_map)
23
- # Use deep inference to resolve root
29
+ # Use deep inference to resolve root
24
30
  parts[0..-2].each do |sym|
25
31
  pins = api_map.get_constants('', type.namespace).select{ |pin| pin.name == sym }
26
32
  type = first_pin_type(pins, api_map)
@@ -35,6 +41,8 @@ module Solargraph
35
41
 
36
42
  private
37
43
 
44
+ # @param pin [Pin::Base]
45
+ # @return [::Array<String>]
38
46
  def crawl_gates pin
39
47
  clos = pin
40
48
  until clos.nil?
@@ -48,6 +56,9 @@ module Solargraph
48
56
  ['']
49
57
  end
50
58
 
59
+ # @param pins [::Array<Pin::Base>]
60
+ # @param api_map [ApiMap]
61
+ # @return [ComplexType]
51
62
  def first_pin_type(pins, api_map)
52
63
  type = ComplexType::UNDEFINED
53
64
  pins.each do |pin|
@@ -59,6 +70,9 @@ module Solargraph
59
70
  type
60
71
  end
61
72
 
73
+ # @param gate [String]
74
+ # @param api_map [ApiMap]
75
+ # @return [ComplexType]
62
76
  def deep_constant_type(gate, api_map)
63
77
  type = ComplexType::ROOT
64
78
  return type if gate == ''
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ class Source
5
+ class Chain
6
+ class If < Link
7
+ def word
8
+ '<if>'
9
+ end
10
+
11
+ # @param links [::Array<Link>]
12
+ def initialize links
13
+ @links = links
14
+ end
15
+
16
+ def resolve api_map, name_pin, locals
17
+ types = @links.map { |link| link.infer(api_map, name_pin, locals) }
18
+ [Solargraph::Pin::ProxyType.anonymous(Solargraph::ComplexType.try_parse(types.map(&:tag).uniq.join(', ')))]
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -7,8 +7,10 @@ module Solargraph
7
7
  # @return [String]
8
8
  attr_reader :word
9
9
 
10
+ # @return [Pin::Base]
10
11
  attr_accessor :last_context
11
12
 
13
+ # @param word [String]
12
14
  def initialize word = '<undefined>'
13
15
  @word = word
14
16
  end
@@ -23,12 +25,16 @@ module Solargraph
23
25
 
24
26
  # @param api_map [ApiMap]
25
27
  # @param name_pin [Pin::Base]
26
- # @param locals [Array<Pin::Base>]
28
+ # @param locals [::Enumerable<Pin::Base>]
27
29
  # @return [::Array<Pin::Base>]
28
30
  def resolve api_map, name_pin, locals
29
31
  []
30
32
  end
31
33
 
34
+ def inspect
35
+ "#{self.class} #{word}"
36
+ end
37
+
32
38
  def head?
33
39
  @head ||= false
34
40
  end
@@ -8,7 +8,7 @@ module Solargraph
8
8
  '<or>'
9
9
  end
10
10
 
11
- # @param type [String]
11
+ # @param links [::Array<Link>]
12
12
  def initialize links
13
13
  @links = links
14
14
  end
@@ -7,11 +7,11 @@ module Solargraph
7
7
  # @return [String]
8
8
  attr_reader :word
9
9
 
10
- # @return [Array<Chain>]
10
+ # @return [::Array<Chain>]
11
11
  attr_reader :arguments
12
12
 
13
13
  # @param word [String]
14
- # @param arguments [Array<Chain>]
14
+ # @param arguments [::Array<Chain>]
15
15
  # @param with_block [Boolean] True if the chain is inside a block
16
16
  # @param head [Boolean] True if the call is the start of its chain
17
17
  def initialize word, with_block = false
@@ -19,8 +19,10 @@ module Solargraph
19
19
  autoload :GlobalVariable, 'solargraph/source/chain/global_variable'
20
20
  autoload :Literal, 'solargraph/source/chain/literal'
21
21
  autoload :Head, 'solargraph/source/chain/head'
22
+ autoload :If, 'solargraph/source/chain/if'
22
23
  autoload :Or, 'solargraph/source/chain/or'
23
24
  autoload :BlockVariable, 'solargraph/source/chain/block_variable'
25
+ autoload :BlockSymbol, 'solargraph/source/chain/block_symbol'
24
26
  autoload :ZSuper, 'solargraph/source/chain/z_super'
25
27
  autoload :Hash, 'solargraph/source/chain/hash'
26
28
  autoload :Array, 'solargraph/source/chain/array'
@@ -36,7 +38,9 @@ module Solargraph
36
38
 
37
39
  attr_reader :node
38
40
 
41
+ # @param node [Parser::AST::Node, nil]
39
42
  # @param links [::Array<Chain::Link>]
43
+ # @param splat [Boolean]
40
44
  def initialize links, node = nil, splat = false
41
45
  @links = links.clone
42
46
  @links.push UNDEFINED_CALL if @links.empty?
@@ -57,7 +61,8 @@ module Solargraph
57
61
 
58
62
  # @param api_map [ApiMap]
59
63
  # @param name_pin [Pin::Base]
60
- # @param locals [Array<Pin::Base>]
64
+ # @param locals [::Enumerable<Pin::LocalVariable>]
65
+ #
61
66
  # @return [::Array<Pin::Base>]
62
67
  def define api_map, name_pin, locals
63
68
  return [] if undefined?
@@ -74,7 +79,7 @@ module Solargraph
74
79
 
75
80
  # @param api_map [ApiMap]
76
81
  # @param name_pin [Pin::Base]
77
- # @param locals [Array<Pin::Base>]
82
+ # @param locals [::Enumerable<Pin::LocalVariable>]
78
83
  # @return [ComplexType]
79
84
  def infer api_map, name_pin, locals
80
85
  from_here = base.infer(api_map, name_pin, locals) unless links.length == 1
@@ -114,12 +119,16 @@ module Solargraph
114
119
 
115
120
  private
116
121
 
117
- # @param pins [Array<Pin::Base>]
122
+ # @param pins [::Array<Pin::Base>]
118
123
  # @param context [Pin::Base]
119
124
  # @param api_map [ApiMap]
125
+ # @param locals [::Enumerable<Pin::LocalVariable>]
120
126
  # @return [ComplexType]
121
127
  def infer_first_defined pins, context, api_map, locals
122
128
  possibles = []
129
+ # @todo this param tag shouldn't be needed to probe the type
130
+ # @todo ...but given it is needed, typecheck should complain that it is needed
131
+ # @param pin [Pin::Base]
123
132
  pins.each do |pin|
124
133
  # Avoid infinite recursion
125
134
  next if @@inference_stack.include?(pin.identity)
@@ -129,6 +138,9 @@ module Solargraph
129
138
  @@inference_stack.pop
130
139
  if type.defined?
131
140
  if type.generic?
141
+ # @todo even at strong, no typechecking complaint
142
+ # happens when a [Pin::Base,nil] is passed into a method
143
+ # that accepts only [Pin::Namespace] as an argument
132
144
  type = type.resolve_generics(pin.closure, context.return_type)
133
145
  end
134
146
  if type.defined?
@@ -142,6 +154,7 @@ module Solargraph
142
154
  return ComplexType::UNDEFINED if @@inference_depth >= 10 && pins.first.is_a?(Pin::Method)
143
155
 
144
156
  @@inference_depth += 1
157
+ # @param pin [Pin::Base]
145
158
  pins.each do |pin|
146
159
  # Avoid infinite recursion
147
160
  next if @@inference_stack.include?(pin.identity)
@@ -157,6 +170,7 @@ module Solargraph
157
170
  @@inference_depth -= 1
158
171
  end
159
172
  return ComplexType::UNDEFINED if possibles.empty?
173
+
160
174
  type = if possibles.length > 1
161
175
  sorted = possibles.map { |t| t.rooted? ? "::#{t}" : t.to_s }.sort { |a, _| a == 'nil' ? 1 : 0 }
162
176
  ComplexType.parse(*sorted)
@@ -164,10 +178,12 @@ module Solargraph
164
178
  ComplexType.parse(possibles.map(&:to_s).join(', '))
165
179
  end
166
180
  return type if context.nil? || context.return_type.undefined?
167
- type.self_to(context.return_type.namespace)
181
+
182
+ type.self_to(context.return_type.tag)
168
183
  end
169
184
 
170
185
  # @param type [ComplexType]
186
+ # @return [ComplexType]
171
187
  def maybe_nil type
172
188
  return type if type.undefined? || type.void? || type.nullable?
173
189
  return type unless nullable?
@@ -69,6 +69,9 @@ module Solargraph
69
69
 
70
70
  private
71
71
 
72
+ # @param text [String]
73
+ # @param insert [String]
74
+ # @return [String]
72
75
  def commit text, insert
73
76
  start_offset = Position.to_offset(text, range.start)
74
77
  end_offset = Position.to_offset(text, range.ending)
@@ -115,6 +115,7 @@ module Solargraph
115
115
  end
116
116
  alias receiver recipient
117
117
 
118
+ # @return [AST::Node]
118
119
  def node
119
120
  @node ||= source.node_at(position.line, position.column)
120
121
  end
@@ -135,6 +136,7 @@ module Solargraph
135
136
  end
136
137
  end
137
138
 
139
+ # @return [Parser::AST::Node, nil]
138
140
  def recipient_node
139
141
  @recipient_node ||= Solargraph::Parser::NodeMethods.find_recipient_node(self)
140
142
  end
@@ -14,10 +14,10 @@ module Solargraph
14
14
 
15
15
  class << self
16
16
  # @param source [Source]
17
- # @param position [Position]
17
+ # @param position [Position, Array(Integer, Integer)]
18
18
  # @return [Source::Chain]
19
19
  def chain source, position
20
- new(source, position).chain
20
+ new(source, Solargraph::Position.normalize(position)).chain
21
21
  end
22
22
  end
23
23
 
@@ -41,8 +41,6 @@ module Solargraph
41
41
  parent = nil
42
42
  if !source.repaired? && source.parsed? && source.synchronized?
43
43
  tree = source.tree_at(position.line, position.column)
44
- # node, parent = source.tree_at(position.line, position.column)[0..2]
45
- tree.shift while tree.length > 1 && tree.first.type == :SCOPE
46
44
  node, parent = tree[0..2]
47
45
  elsif source.parsed? && source.repaired? && end_of_phrase == '.'
48
46
  node, parent = source.tree_at(fixed_position.line, fixed_position.column)[0..2]
@@ -60,7 +58,7 @@ module Solargraph
60
58
  end
61
59
  return Chain.new([Chain::UNDEFINED_CALL]) if node.nil? || (node.type == :sym && !phrase.start_with?(':'))
62
60
  # chain = NodeChainer.chain(node, source.filename, parent && parent.type == :block)
63
- chain = Parser.chain(node, source.filename, parent && [:ITER, :block].include?(parent.type))
61
+ chain = Parser.chain(node, source.filename, parent)
64
62
  if source.repaired? || !source.parsed? || !source.synchronized?
65
63
  if end_of_phrase.strip == '.'
66
64
  chain.links.push Chain::UNDEFINED_CALL
@@ -128,10 +126,13 @@ module Solargraph
128
126
  Position.line_char_to_offset(@source.code, line, column)
129
127
  end
130
128
 
129
+ # @return [Integer]
131
130
  def signature_data
132
131
  @signature_data ||= get_signature_data_at(offset)
133
132
  end
134
133
 
134
+ # @param index [Integer]
135
+ # @return [Integer]
135
136
  def get_signature_data_at index
136
137
  brackets = 0
137
138
  squares = 0
@@ -8,7 +8,6 @@ module Solargraph
8
8
  class Source
9
9
  autoload :Updater, 'solargraph/source/updater'
10
10
  autoload :Change, 'solargraph/source/change'
11
- autoload :Mapper, 'solargraph/source/mapper'
12
11
  autoload :EncodingFixes, 'solargraph/source/encoding_fixes'
13
12
  autoload :Cursor, 'solargraph/source/cursor'
14
13
  autoload :Chain, 'solargraph/source/chain'
@@ -213,6 +212,7 @@ module Solargraph
213
212
  end
214
213
  end
215
214
 
215
+ # @return [::Array<Range>]
216
216
  def string_ranges
217
217
  @string_ranges ||= Parser.string_ranges(node)
218
218
  end
@@ -250,7 +250,7 @@ module Solargraph
250
250
  end
251
251
 
252
252
  # @param node [Parser::AST::Node]
253
- # @return [String]
253
+ # @return [String, nil]
254
254
  def comments_for node
255
255
  rng = Range.from_node(node)
256
256
  stringified_comments[rng.start.line] ||= begin
@@ -301,7 +301,7 @@ module Solargraph
301
301
 
302
302
  # Get a hash of comments grouped by the line numbers of the associated code.
303
303
  #
304
- # @return [Hash{Integer => Array<Parser::Source::Comment>}]
304
+ # @return [Hash{Integer => String}]
305
305
  def associated_comments
306
306
  @associated_comments ||= begin
307
307
  result = {}
@@ -323,6 +323,8 @@ module Solargraph
323
323
 
324
324
  private
325
325
 
326
+ # @param line [Integer]
327
+ # @return [Integer]
326
328
  def first_not_empty_from line
327
329
  cursor = line
328
330
  cursor += 1 while cursor < code_lines.length && code_lines[cursor].strip.empty?
@@ -411,7 +413,7 @@ module Solargraph
411
413
  result
412
414
  end
413
415
 
414
- # @param n [Parser::AST::Node]
416
+ # @param n [Parser::AST::Node, nil]
415
417
  # @return [Array<Parser::AST::Node>]
416
418
  def string_nodes_in n
417
419
  result = []
@@ -425,30 +427,23 @@ module Solargraph
425
427
  result
426
428
  end
427
429
 
428
- # @param node [Parser::AST::Node]
430
+ # @param node [Parser::AST::Node, nil]
429
431
  # @param position [Position]
430
432
  # @param stack [Array<Parser::AST::Node>]
431
433
  # @return [void]
432
434
  def inner_tree_at node, position, stack
433
435
  return if node.nil?
434
436
  here = Range.from_node(node)
435
- if here.contain?(position) || colonized(here, position, node)
437
+ if here.contain?(position)
436
438
  stack.unshift node
437
439
  node.children.each do |c|
438
440
  next unless Parser.is_ast_node?(c)
439
- next if !Parser.rubyvm? && c.loc.expression.nil?
441
+ next if c.loc.expression.nil?
440
442
  inner_tree_at(c, position, stack)
441
443
  end
442
444
  end
443
445
  end
444
446
 
445
- def colonized range, position, node
446
- node.type == :COLON2 &&
447
- range.ending.line == position.line &&
448
- range.ending.character == position.character - 2 &&
449
- code[Position.to_offset(code, Position.new(position.line, position.character - 2)), 2] == '::'
450
- end
451
-
452
447
  protected
453
448
 
454
449
  # @return [String]
@@ -464,7 +459,7 @@ module Solargraph
464
459
  @code = val
465
460
  end
466
461
 
467
- # @return [Parser::AST::Node]
462
+ # @return [Parser::AST::Node, nil]
468
463
  attr_writer :node
469
464
 
470
465
  # @return [Array<Range>]
@@ -476,7 +471,7 @@ module Solargraph
476
471
  # @return [Boolean]
477
472
  attr_writer :parsed
478
473
 
479
- # @return [Array<Parser::Source::Comment>]
474
+ # @return [Hash{Integer => String}
480
475
  attr_writer :comments
481
476
 
482
477
  # @return [Boolean]
@@ -516,6 +511,10 @@ module Solargraph
516
511
  # HACK: Pass a dummy code object to the parser for plugins that
517
512
  # expect it not to be nil
518
513
  YARD::Docstring.parser.parse(comments, YARD::CodeObjects::Base.new(:root, 'stub'))
514
+ rescue StandardError => e
515
+ Solargraph.logger.info "YARD failed to parse docstring: [#{e.class}] #{e.message}"
516
+ Solargraph.logger.debug "Unparsed comment: #{comments}"
517
+ YARD::Docstring.parser
519
518
  end
520
519
  end
521
520
  end