solargraph 0.51.2 → 0.54.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 (183) 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/.yardopts +2 -2
  6. data/CHANGELOG.md +127 -5
  7. data/README.md +13 -16
  8. data/SPONSORS.md +1 -7
  9. data/lib/solargraph/api_map/cache.rb +50 -20
  10. data/lib/solargraph/api_map/source_to_yard.rb +17 -10
  11. data/lib/solargraph/api_map/store.rb +60 -15
  12. data/lib/solargraph/api_map.rb +282 -123
  13. data/lib/solargraph/bench.rb +3 -2
  14. data/lib/solargraph/cache.rb +29 -5
  15. data/lib/solargraph/complex_type/type_methods.rb +122 -39
  16. data/lib/solargraph/complex_type/unique_type.rb +310 -76
  17. data/lib/solargraph/complex_type.rb +166 -44
  18. data/lib/solargraph/convention.rb +0 -1
  19. data/lib/solargraph/converters/dd.rb +5 -0
  20. data/lib/solargraph/converters/dl.rb +3 -0
  21. data/lib/solargraph/converters/dt.rb +3 -0
  22. data/lib/solargraph/diagnostics/rubocop.rb +8 -7
  23. data/lib/solargraph/diagnostics/rubocop_helpers.rb +1 -0
  24. data/lib/solargraph/diagnostics/type_check.rb +1 -0
  25. data/lib/solargraph/diagnostics.rb +2 -2
  26. data/lib/solargraph/doc_map.rb +187 -0
  27. data/lib/solargraph/gem_pins.rb +72 -0
  28. data/lib/solargraph/language_server/host/diagnoser.rb +2 -2
  29. data/lib/solargraph/language_server/host/dispatch.rb +22 -5
  30. data/lib/solargraph/language_server/host/message_worker.rb +49 -5
  31. data/lib/solargraph/language_server/host/sources.rb +8 -65
  32. data/lib/solargraph/language_server/host.rb +65 -84
  33. data/lib/solargraph/language_server/message/base.rb +19 -12
  34. data/lib/solargraph/language_server/message/completion_item/resolve.rb +3 -1
  35. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +13 -1
  36. data/lib/solargraph/language_server/message/initialize.rb +19 -2
  37. data/lib/solargraph/language_server/message/text_document/completion.rb +0 -3
  38. data/lib/solargraph/language_server/message/text_document/definition.rb +3 -3
  39. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +3 -3
  40. data/lib/solargraph/language_server/message/text_document/formatting.rb +1 -0
  41. data/lib/solargraph/language_server/message/text_document/hover.rb +3 -1
  42. data/lib/solargraph/language_server/message/text_document/type_definition.rb +3 -3
  43. data/lib/solargraph/language_server/message/text_document.rb +0 -1
  44. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +5 -0
  45. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +2 -2
  46. data/lib/solargraph/language_server/progress.rb +135 -0
  47. data/lib/solargraph/language_server/transport/adapter.rb +16 -1
  48. data/lib/solargraph/language_server/transport/data_reader.rb +2 -0
  49. data/lib/solargraph/language_server.rb +1 -0
  50. data/lib/solargraph/library.rb +207 -111
  51. data/lib/solargraph/location.rb +15 -1
  52. data/lib/solargraph/page.rb +6 -0
  53. data/lib/solargraph/parser/comment_ripper.rb +4 -0
  54. data/lib/solargraph/parser/node_methods.rb +47 -7
  55. data/lib/solargraph/parser/node_processor/base.rb +11 -1
  56. data/lib/solargraph/parser/node_processor.rb +1 -0
  57. data/lib/solargraph/parser/{legacy → parser_gem}/class_methods.rb +31 -9
  58. data/lib/solargraph/parser/{legacy → parser_gem}/flawed_builder.rb +3 -1
  59. data/lib/solargraph/parser/{legacy → parser_gem}/node_chainer.rb +62 -43
  60. data/lib/solargraph/parser/parser_gem/node_methods.rb +495 -0
  61. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/alias_node.rb +1 -1
  62. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +57 -0
  63. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/begin_node.rb +1 -1
  64. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/block_node.rb +3 -2
  65. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/casgn_node.rb +2 -2
  66. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/cvasgn_node.rb +1 -1
  67. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/def_node.rb +7 -20
  68. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/defs_node.rb +2 -2
  69. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/gvasgn_node.rb +1 -1
  70. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/ivasgn_node.rb +2 -2
  71. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/lvasgn_node.rb +4 -4
  72. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +53 -0
  73. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/namespace_node.rb +2 -2
  74. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/orasgn_node.rb +1 -1
  75. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/resbody_node.rb +3 -3
  76. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/sclass_node.rb +1 -1
  77. data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/send_node.rb +8 -6
  78. data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/sym_node.rb +1 -1
  79. data/lib/solargraph/parser/parser_gem/node_processors.rb +56 -0
  80. data/lib/solargraph/parser/parser_gem.rb +12 -0
  81. data/lib/solargraph/parser/region.rb +1 -1
  82. data/lib/solargraph/parser/snippet.rb +2 -0
  83. data/lib/solargraph/parser.rb +8 -12
  84. data/lib/solargraph/pin/base.rb +78 -10
  85. data/lib/solargraph/pin/base_variable.rb +40 -7
  86. data/lib/solargraph/pin/block.rb +69 -46
  87. data/lib/solargraph/pin/callable.rb +147 -0
  88. data/lib/solargraph/pin/closure.rb +23 -3
  89. data/lib/solargraph/pin/common.rb +6 -6
  90. data/lib/solargraph/pin/conversions.rb +36 -5
  91. data/lib/solargraph/pin/delegated_method.rb +6 -2
  92. data/lib/solargraph/pin/documenting.rb +25 -32
  93. data/lib/solargraph/pin/instance_variable.rb +6 -2
  94. data/lib/solargraph/pin/local_variable.rb +13 -1
  95. data/lib/solargraph/pin/method.rb +205 -32
  96. data/lib/solargraph/pin/namespace.rb +20 -7
  97. data/lib/solargraph/pin/parameter.rb +41 -36
  98. data/lib/solargraph/pin/proxy_type.rb +1 -1
  99. data/lib/solargraph/pin/reference/override.rb +2 -2
  100. data/lib/solargraph/pin/reference.rb +8 -0
  101. data/lib/solargraph/pin/search.rb +3 -3
  102. data/lib/solargraph/pin/signature.rb +8 -14
  103. data/lib/solargraph/pin.rb +4 -2
  104. data/lib/solargraph/range.rb +4 -6
  105. data/lib/solargraph/rbs_map/conversions.rb +326 -76
  106. data/lib/solargraph/rbs_map/core_fills.rb +16 -33
  107. data/lib/solargraph/rbs_map/core_map.rb +3 -13
  108. data/lib/solargraph/rbs_map/stdlib_map.rb +2 -8
  109. data/lib/solargraph/rbs_map.rb +32 -13
  110. data/lib/solargraph/shell.rb +95 -72
  111. data/lib/solargraph/source/chain/array.rb +33 -0
  112. data/lib/solargraph/source/chain/block_symbol.rb +13 -0
  113. data/lib/solargraph/source/chain/block_variable.rb +1 -1
  114. data/lib/solargraph/source/chain/call.rb +152 -69
  115. data/lib/solargraph/source/chain/constant.rb +15 -1
  116. data/lib/solargraph/source/chain/if.rb +23 -0
  117. data/lib/solargraph/source/chain/link.rb +17 -2
  118. data/lib/solargraph/source/chain/or.rb +2 -2
  119. data/lib/solargraph/source/chain/z_super.rb +3 -3
  120. data/lib/solargraph/source/chain.rb +85 -26
  121. data/lib/solargraph/source/change.rb +3 -0
  122. data/lib/solargraph/source/cursor.rb +16 -2
  123. data/lib/solargraph/source/source_chainer.rb +8 -5
  124. data/lib/solargraph/source/updater.rb +1 -0
  125. data/lib/solargraph/source.rb +120 -148
  126. data/lib/solargraph/source_map/clip.rb +16 -27
  127. data/lib/solargraph/source_map/data.rb +30 -0
  128. data/lib/solargraph/source_map/mapper.rb +15 -3
  129. data/lib/solargraph/source_map.rb +48 -24
  130. data/lib/solargraph/type_checker/checks.rb +10 -2
  131. data/lib/solargraph/type_checker/rules.rb +6 -1
  132. data/lib/solargraph/type_checker.rb +150 -39
  133. data/lib/solargraph/version.rb +1 -1
  134. data/lib/solargraph/views/environment.erb +3 -5
  135. data/lib/solargraph/workspace/config.rb +9 -6
  136. data/lib/solargraph/workspace.rb +30 -3
  137. data/lib/solargraph/yard_map/cache.rb +6 -0
  138. data/lib/solargraph/yard_map/helpers.rb +1 -1
  139. data/lib/solargraph/yard_map/mapper/to_method.rb +16 -3
  140. data/lib/solargraph/yard_map/mapper.rb +1 -1
  141. data/lib/solargraph/yard_map/to_method.rb +11 -4
  142. data/lib/solargraph/yard_map.rb +1 -292
  143. data/lib/solargraph/yard_tags.rb +20 -0
  144. data/lib/solargraph/yardoc.rb +52 -0
  145. data/lib/solargraph.rb +6 -4
  146. data/solargraph.gemspec +7 -6
  147. metadata +71 -82
  148. data/lib/solargraph/api_map/bundler_methods.rb +0 -22
  149. data/lib/solargraph/documentor.rb +0 -76
  150. data/lib/solargraph/language_server/host/cataloger.rb +0 -56
  151. data/lib/solargraph/parser/legacy/node_methods.rb +0 -325
  152. data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +0 -23
  153. data/lib/solargraph/parser/legacy/node_processors/args_node.rb +0 -50
  154. data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +0 -15
  155. data/lib/solargraph/parser/legacy/node_processors/sym_node.rb +0 -18
  156. data/lib/solargraph/parser/legacy/node_processors.rb +0 -55
  157. data/lib/solargraph/parser/legacy.rb +0 -12
  158. data/lib/solargraph/parser/rubyvm/class_methods.rb +0 -153
  159. data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -160
  160. data/lib/solargraph/parser/rubyvm/node_methods.rb +0 -317
  161. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +0 -85
  162. data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +0 -42
  163. data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +0 -33
  164. data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +0 -23
  165. data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +0 -75
  166. data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +0 -68
  167. data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +0 -23
  168. data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +0 -38
  169. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +0 -39
  170. data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +0 -20
  171. data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +0 -27
  172. data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +0 -39
  173. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +0 -26
  174. data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +0 -15
  175. data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +0 -51
  176. data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +0 -32
  177. data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +0 -15
  178. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +0 -279
  179. data/lib/solargraph/parser/rubyvm/node_processors.rb +0 -64
  180. data/lib/solargraph/parser/rubyvm/node_wrapper.rb +0 -47
  181. data/lib/solargraph/parser/rubyvm.rb +0 -40
  182. data/lib/solargraph/rbs_map/core_signs.rb +0 -33
  183. data/lib/yard-solargraph.rb +0 -33
@@ -3,126 +3,147 @@
3
3
  module Solargraph
4
4
  class Source
5
5
  class Chain
6
- class Call < Link
6
+ class Call < Chain::Link
7
+ include Solargraph::Parser::NodeMethods
8
+
7
9
  # @return [String]
8
10
  attr_reader :word
9
11
 
10
- # @return [Array<Chain>]
12
+ # @return [::Array<Chain>]
11
13
  attr_reader :arguments
12
14
 
15
+ # @return [Chain, nil]
16
+ attr_reader :block
17
+
13
18
  # @param word [String]
14
- # @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
19
+ # @param arguments [::Array<Chain>]
20
+ # @param block [Chain, nil]
21
+ def initialize word, arguments = [], block = nil
18
22
  @word = word
19
23
  @arguments = arguments
20
- @with_block = with_block
24
+ @block = block
25
+ fix_block_pass
21
26
  end
22
27
 
23
28
  def with_block?
24
- @with_block
29
+ !!@block
25
30
  end
26
31
 
27
32
  # @param api_map [ApiMap]
28
- # @param name_pin [Pin::Base]
29
- # @param locals [Array<Pin::Base>]
33
+ # @param name_pin [Pin::Closure] name_pin.binder should give us the object on which 'word' will be invoked
34
+ # @param locals [::Array<Pin::LocalVariable>]
30
35
  def resolve api_map, name_pin, locals
31
36
  return super_pins(api_map, name_pin) if word == 'super'
37
+ return yield_pins(api_map, name_pin) if word == 'yield'
32
38
  found = if head?
33
39
  locals.select { |p| p.name == word }
34
40
  else
35
41
  []
36
42
  end
37
- return inferred_pins(found, api_map, name_pin.context, locals) unless found.empty?
38
- # @param [ComplexType::UniqueType]
43
+ return inferred_pins(found, api_map, name_pin, locals) unless found.empty?
39
44
  pins = name_pin.binder.each_unique_type.flat_map do |context|
40
- api_map.get_method_stack(context.namespace, word, scope: context.scope)
45
+ ns = context.namespace == '' ? '' : context.namespace_type.tag
46
+ api_map.get_method_stack(ns, word, scope: context.scope)
41
47
  end
42
48
  return [] if pins.empty?
43
- inferred_pins(pins, api_map, name_pin.context, locals)
49
+ inferred_pins(pins, api_map, name_pin, locals)
44
50
  end
45
51
 
46
52
  private
47
53
 
48
- # @param pins [Array<Pin::Base>]
54
+ # @param pins [::Enumerable<Pin::Method>]
49
55
  # @param api_map [ApiMap]
50
- # @param context [ComplexType]
51
- # @param locals [Pin::LocalVariable]
52
- # @return [Array<Pin::Base>]
53
- def inferred_pins pins, api_map, context, locals
56
+ # @param name_pin [Pin::Base]
57
+ # @param locals [::Array<Pin::LocalVariable>]
58
+ # @return [::Array<Pin::Base>]
59
+ def inferred_pins pins, api_map, name_pin, locals
54
60
  result = pins.map do |p|
55
61
  next p unless p.is_a?(Pin::Method)
56
62
  overloads = p.signatures
57
63
  # next p if overloads.empty?
58
64
  type = ComplexType::UNDEFINED
59
- overloads.each do |ol|
60
- next unless arguments_match(arguments, ol)
61
- # next if ol.parameters.last && ol.parameters.last.first.start_with?('&') && ol.parameters.last.last.nil? && !with_block?
65
+ # start with overloads that require blocks; if we are
66
+ # passing a block, we want to find a signature that will
67
+ # use it. If we didn't pass a block, the logic below will
68
+ # reject it regardless
69
+
70
+ sorted_overloads = overloads.sort { |ol| ol.block? ? -1 : 1 }
71
+ new_signature_pin = nil
72
+ sorted_overloads.each do |ol|
73
+ next unless ol.arity_matches?(arguments, with_block?)
62
74
  match = true
75
+
76
+ atypes = []
63
77
  arguments.each_with_index do |arg, idx|
64
78
  param = ol.parameters[idx]
65
79
  if param.nil?
66
- match = false unless ol.parameters.any?(&:restarg?)
80
+ match = ol.parameters.any?(&:restarg?)
67
81
  break
68
82
  end
69
- atype = arg.infer(api_map, Pin::ProxyType.anonymous(context), locals)
83
+ atype = atypes[idx] ||= arg.infer(api_map, Pin::ProxyType.anonymous(name_pin.context), locals)
84
+ # make sure we get types from up the method
85
+ # inheritance chain if we don't have them on this pin
86
+ ptype = param.typify api_map
70
87
  # @todo Weak type comparison
71
88
  # unless atype.tag == param.return_type.tag || api_map.super_and_sub?(param.return_type.tag, atype.tag)
72
- unless param.return_type.undefined? || atype.name == param.return_type.name || api_map.super_and_sub?(param.return_type.name, atype.name)
89
+ unless ptype.undefined? || atype.name == ptype.name || ptype.any? { |current_ptype| api_map.super_and_sub?(current_ptype.name, atype.name) } || ptype.generic? || param.restarg?
73
90
  match = false
74
91
  break
75
92
  end
76
93
  end
77
94
  if match
78
- type = extra_return_type(p.docstring, context)
79
- break if type
80
- type = with_params(ol.return_type.self_to(context.to_s), context).qualify(api_map, context.namespace) if ol.return_type.defined?
95
+ if ol.block && with_block?
96
+ block_atypes = ol.block.parameters.map(&:return_type)
97
+ if block.links.map(&:class) == [BlockSymbol]
98
+ # like the bar in foo(&:bar)
99
+ blocktype = block_symbol_call_type(api_map, name_pin.context, block_atypes, locals)
100
+ else
101
+ blocktype = block_call_type(api_map, name_pin, locals)
102
+ end
103
+ end
104
+ new_signature_pin = ol.resolve_generics_from_context_until_complete(ol.generics, atypes, nil, nil, blocktype)
105
+ new_return_type = new_signature_pin.return_type
106
+ type = with_params(new_return_type.self_to_type(name_pin.context), name_pin.context).qualify(api_map, name_pin.context.namespace) if new_return_type.defined?
81
107
  type ||= ComplexType::UNDEFINED
82
108
  end
83
109
  break if type.defined?
84
110
  end
111
+ p = p.with_single_signature(new_signature_pin) unless new_signature_pin.nil?
85
112
  next p.proxy(type) if type.defined?
86
- type = extra_return_type(p.docstring, context)
87
- if type
88
- next Solargraph::Pin::Method.new(
89
- location: p.location,
90
- closure: p.closure,
91
- name: p.name,
92
- comments: "@return [#{context.subtypes.first.to_s}]",
93
- scope: p.scope,
94
- visibility: p.visibility,
95
- parameters: p.parameters,
96
- node: p.node
97
- )
98
- end
99
- if p.is_a?(Pin::Method) && !p.macros.empty?
100
- result = process_macro(p, api_map, context, locals)
113
+ if !p.macros.empty?
114
+ result = process_macro(p, api_map, name_pin.context, locals)
101
115
  next result unless result.return_type.undefined?
102
116
  elsif !p.directives.empty?
103
- result = process_directive(p, api_map, context, locals)
117
+ result = process_directive(p, api_map, name_pin.context, locals)
104
118
  next result unless result.return_type.undefined?
105
119
  end
106
120
  p
107
121
  end
108
122
  result.map do |pin|
109
- if pin.path == 'Class#new' && context.tag != 'Class'
110
- pin.proxy(ComplexType.try_parse(context.namespace))
123
+ if pin.path == 'Class#new' && name_pin.context.tag != 'Class'
124
+ reduced_context = name_pin.context.reduce_class_type
125
+ pin.proxy(reduced_context)
111
126
  else
112
127
  next pin if pin.return_type.undefined?
113
- selfy = pin.return_type.self_to(context.tag)
128
+ selfy = pin.return_type.self_to_type(name_pin.context)
114
129
  selfy == pin.return_type ? pin : pin.proxy(selfy)
115
130
  end
116
131
  end
117
132
  end
118
133
 
119
- # @param pin [Pin::Method]
134
+ # @param pin [Pin::Base]
120
135
  # @param api_map [ApiMap]
121
136
  # @param context [ComplexType]
122
- # @param locals [Pin::Base]
137
+ # @param locals [Enumerable<Pin::Base>]
123
138
  # @return [Pin::Base]
124
139
  def process_macro pin, api_map, context, locals
125
140
  pin.macros.each do |macro|
141
+ # @todo 'Wrong argument type for
142
+ # Solargraph::Source::Chain::Call#inner_process_macro:
143
+ # macro expected YARD::Tags::MacroDirective, received
144
+ # generic<Elem>' is because we lose 'rooted' information
145
+ # in the 'Chain::Array' class internally, leaving
146
+ # ::Array#each shadowed when it shouldn't be.
126
147
  result = inner_process_macro(pin, macro, api_map, context, locals)
127
148
  return result unless result.return_type.undefined?
128
149
  end
@@ -132,7 +153,7 @@ module Solargraph
132
153
  # @param pin [Pin::Method]
133
154
  # @param api_map [ApiMap]
134
155
  # @param context [ComplexType]
135
- # @param locals [Pin::Base]
156
+ # @param locals [Enumerable<Pin::Base>]
136
157
  # @return [Pin::ProxyType]
137
158
  def process_directive pin, api_map, context, locals
138
159
  pin.directives.each do |dir|
@@ -144,11 +165,11 @@ module Solargraph
144
165
  Pin::ProxyType.anonymous ComplexType::UNDEFINED
145
166
  end
146
167
 
147
- # @param pin [Pin]
168
+ # @param pin [Pin::Base]
148
169
  # @param macro [YARD::Tags::MacroDirective]
149
170
  # @param api_map [ApiMap]
150
171
  # @param context [ComplexType]
151
- # @param locals [Array<Pin::Base>]
172
+ # @param locals [Enumerable<Pin::Base>]
152
173
  # @return [Pin::ProxyType]
153
174
  def inner_process_macro pin, macro, api_map, context, locals
154
175
  vals = arguments.map{ |c| Pin::ProxyType.anonymous(c.infer(api_map, pin, locals)) }
@@ -172,42 +193,104 @@ module Solargraph
172
193
 
173
194
  # @param docstring [YARD::Docstring]
174
195
  # @param context [ComplexType]
175
- # @return [ComplexType]
196
+ # @return [ComplexType, nil]
176
197
  def extra_return_type docstring, context
177
- if docstring.has_tag?(:return_single_parameter) #&& context.subtypes.one?
198
+ if docstring.has_tag?('return_single_parameter') #&& context.subtypes.one?
178
199
  return context.subtypes.first || ComplexType::UNDEFINED
179
- elsif docstring.has_tag?(:return_value_parameter) && context.value_types.one?
200
+ elsif docstring.has_tag?('return_value_parameter') && context.value_types.one?
180
201
  return context.value_types.first
181
202
  end
182
203
  nil
183
204
  end
184
205
 
185
- # @param arguments [Array<Chain>]
186
- # @param signature [Pin::Signature]
187
- # @return [Boolean]
188
- def arguments_match arguments, signature
189
- parameters = signature.parameters
190
- argcount = arguments.length
191
- parcount = parameters.length
192
- parcount -= 1 if !parameters.empty? && parameters.last.block?
193
- return false if signature.block? && !with_block?
194
- return false if argcount < parcount && !(argcount == parcount - 1 && parameters.last.restarg?)
195
- true
206
+ # @param name_pin [Pin::Base]
207
+ # @return [Pin::Method, nil]
208
+ def find_method_pin(name_pin)
209
+ method_pin = name_pin
210
+ until method_pin.is_a?(Pin::Method)
211
+ method_pin = method_pin.closure
212
+ return if method_pin.nil?
213
+ end
214
+ method_pin
196
215
  end
197
216
 
198
217
  # @param api_map [ApiMap]
199
218
  # @param name_pin [Pin::Base]
200
- # @return [Array<Pin::Base>]
219
+ # @return [::Array<Pin::Base>]
201
220
  def super_pins api_map, name_pin
202
- pins = api_map.get_method_stack(name_pin.namespace, name_pin.name, scope: name_pin.context.scope)
221
+ method_pin = find_method_pin(name_pin)
222
+ return [] if method_pin.nil?
223
+ pins = api_map.get_method_stack(method_pin.namespace, method_pin.name, scope: method_pin.context.scope)
203
224
  pins.reject{|p| p.path == name_pin.path}
204
225
  end
205
226
 
227
+ # @param api_map [ApiMap]
228
+ # @param name_pin [Pin::Base]
229
+ # @return [::Array<Pin::Base>]
230
+ def yield_pins api_map, name_pin
231
+ method_pin = find_method_pin(name_pin)
232
+ return [] unless method_pin
233
+
234
+ method_pin.signatures.map(&:block).compact.map do |signature_pin|
235
+ return_type = signature_pin.return_type.qualify(api_map, name_pin.namespace)
236
+ signature_pin.proxy(return_type)
237
+ end
238
+ end
239
+
206
240
  # @param type [ComplexType]
207
241
  # @param context [ComplexType]
242
+ # @return [ComplexType]
208
243
  def with_params type, context
209
244
  return type unless type.to_s.include?('$')
210
- ComplexType.try_parse(type.to_s.gsub('$', context.value_types.map(&:tag).join(', ')).gsub('<>', ''))
245
+ ComplexType.try_parse(type.to_s.gsub('$', context.value_types.map(&:rooted_tag).join(', ')).gsub('<>', ''))
246
+ end
247
+
248
+ # @return [void]
249
+ def fix_block_pass
250
+ argument = @arguments.last&.links&.first
251
+ @block = @arguments.pop if argument.is_a?(BlockSymbol) || argument.is_a?(BlockVariable)
252
+ end
253
+
254
+ # @param api_map [ApiMap]
255
+ # @param context [ComplexType]
256
+ # @param block_parameter_types [::Array<ComplexType>]
257
+ # @param locals [::Array<Pin::LocalVariable>]
258
+ # @return [ComplexType, nil]
259
+ def block_symbol_call_type(api_map, context, block_parameter_types, locals)
260
+ # Ruby's shorthand for sending the passed in method name
261
+ # to the first yield parameter with no arguments
262
+ block_symbol_name = block.links.first.word
263
+ block_symbol_call_path = "#{block_parameter_types.first}##{block_symbol_name}"
264
+ callee = api_map.get_path_pins(block_symbol_call_path).first
265
+ return_type = callee&.return_type
266
+ # @todo: Figure out why we get unresolved generics at
267
+ # this point and need to assume method return types
268
+ # based on the generic type
269
+ return_type ||= api_map.get_path_pins("#{context.subtypes.first}##{block.links.first.word}").first&.return_type
270
+ return_type || ComplexType::UNDEFINED
271
+ end
272
+
273
+ # @param api_map [ApiMap]
274
+ # @return [Pin::Block, nil]
275
+ def find_block_pin(api_map)
276
+ node_location = Solargraph::Location.from_node(block.node)
277
+ return if node_location.nil?
278
+ block_pins = api_map.get_block_pins
279
+ block_pins.find { |pin| pin.location.contain?(node_location) }
280
+ end
281
+
282
+ # @param api_map [ApiMap]
283
+ # @param name_pin [Pin::Base]
284
+ # @param block_parameter_types [::Array<ComplexType>]
285
+ # @param locals [::Array<Pin::LocalVariable>]
286
+ # @return [ComplexType, nil]
287
+ def block_call_type(api_map, name_pin, locals)
288
+ return nil unless with_block?
289
+
290
+ block_context_pin = name_pin
291
+ block_pin = find_block_pin(api_map)
292
+ block_context_pin = block_pin.closure if block_pin
293
+ block.infer(api_map, block_context_pin, locals)
211
294
  end
212
295
  end
213
296
  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>]
27
- # @return [Array<Pin::Base>]
28
+ # @param locals [::Enumerable<Pin::Base>]
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
@@ -55,6 +61,15 @@ module Solargraph
55
61
  false
56
62
  end
57
63
 
64
+ # debugging description of contents; not for machine use
65
+ def desc
66
+ word
67
+ end
68
+
69
+ def inspect
70
+ "#<#{self.class} - `#{self.desc}`>"
71
+ end
72
+
58
73
  protected
59
74
 
60
75
  # Mark whether this link is the head of a chain
@@ -8,14 +8,14 @@ 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
15
15
 
16
16
  def resolve api_map, name_pin, locals
17
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(', ')))]
18
+ [Solargraph::Pin::ProxyType.anonymous(Solargraph::ComplexType.new(types.uniq))]
19
19
  end
20
20
  end
21
21
  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
@@ -20,7 +20,7 @@ module Solargraph
20
20
 
21
21
  # @param api_map [ApiMap]
22
22
  # @param name_pin [Pin::Base]
23
- # @param locals [Array<Pin::Base>]
23
+ # @param locals [::Array<Pin::Base>]
24
24
  def resolve api_map, name_pin, locals
25
25
  return super_pins(api_map, name_pin)
26
26
  end