solargraph 0.39.0 → 0.39.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 71e5d6fa6baec1130d64df74ed6fcf49c6c41df2f1386cb5cd2760a7605a9e48
4
- data.tar.gz: 91d9d6c695a63a0defab2c31967b2828907c800a94eb220c9210db9b672f2f27
3
+ metadata.gz: b287c1f54a79a771b343e16110cc0640a948abd0a6a5d7f187cd43e7bbea8b45
4
+ data.tar.gz: 9b425158e5ee4f420c0ea84397d7d171f1893f2e49aed6ebbb3c7f920618679d
5
5
  SHA512:
6
- metadata.gz: 2b37f7a917d8c865063f14c62e185e919cb88f221219fdc611ef003aa0a17af99bdd762fd4d4fc36105f37c36b0bdd4017500abe17b3aa1506423df8b16ee55a
7
- data.tar.gz: 60110bec4c847690cecdfa0d73d0495d09340a56ddf650dfbfc737e1f8b62682e1cce3de568edec7e52f4d4ff052e4c4746a2ec907c20320b6b133de610b6f3a
6
+ metadata.gz: b7c6214462ba598bfd184367c39d05264f82a5b0f94503ffe55ab321b8a8e7c8ef9da470780a7608b47c2360b8dc647d05a0546ff4ecddc6005ff2b015371629
7
+ data.tar.gz: 6810ce41c48475b6875b1337f56f3cd4553abba55e51a0c42158678a6545a4255e0c2ae96b51961fe4c23bee95afb3c8a78322db93a36ac85506a433ee73aaf8
@@ -78,6 +78,10 @@ module Solargraph
78
78
  NodeChainer.chain *args
79
79
  end
80
80
 
81
+ def chain_string *args
82
+ NodeChainer.load_string *args
83
+ end
84
+
81
85
  def process_node *args
82
86
  Solargraph::Parser::NodeProcessor.process *args
83
87
  end
@@ -73,8 +73,11 @@ module Solargraph
73
73
  end
74
74
  elsif n.type == :self
75
75
  result.push Chain::Head.new('self')
76
- elsif [:super, :zsuper].include?(n.type)
77
- result.push Chain::Head.new('super')
76
+ elsif n.type == :zsuper
77
+ result.push Chain::ZSuper.new('super', @in_block || block_passed?(n))
78
+ elsif n.type == :super
79
+ args = n.children.map { |c| NodeChainer.chain(c) }
80
+ result.push Chain::Call.new('super', args, @in_block || block_passed?(n))
78
81
  elsif n.type == :const
79
82
  const = unpack_name(n)
80
83
  result.push Chain::Constant.new(const)
@@ -126,7 +126,7 @@ module Solargraph
126
126
  result.push node
127
127
  node.children[0].children[2..-1].each { |child| result.concat call_nodes_from(child) }
128
128
  node.children[1..-1].each { |child| result.concat call_nodes_from(child) }
129
- elsif node.type == :send
129
+ elsif [:send, :super, :zsuper].include?(node.type)
130
130
  result.push node
131
131
  node.children[2..-1].each { |child| result.concat call_nodes_from(child) }
132
132
  else
@@ -210,8 +210,12 @@ module Solargraph
210
210
  result.concat get_return_nodes_only(node.children[2])
211
211
  elsif node.type == :case
212
212
  node.children[1..-1].each do |cc|
213
- result.concat reduce_to_value_nodes(cc.children[1..-2])
214
- result.concat reduce_to_value_nodes([cc.children.last])
213
+ if cc.nil?
214
+ result.push NIL_NODE
215
+ else
216
+ result.concat reduce_to_value_nodes(cc.children[1..-2]) unless cc.children.length < 1
217
+ result.concat reduce_to_value_nodes([cc.children.last])
218
+ end
215
219
  end
216
220
  else
217
221
  result.push node
@@ -8,7 +8,7 @@ module Solargraph
8
8
  # @param filename [String]
9
9
  # @return [Array(Parser::AST::Node, Array<Parser::Source::Comment>)]
10
10
  def parse_with_comments code, filename = nil
11
- node = RubyVM::AbstractSyntaxTree.parse(code)
11
+ node = RubyVM::AbstractSyntaxTree.parse(code).children[2]
12
12
  comments = CommentRipper.new(code).parse
13
13
  [node, comments]
14
14
  rescue ::SyntaxError => e
@@ -20,7 +20,7 @@ module Solargraph
20
20
  # @param line [Integer]
21
21
  # @return [Parser::AST::Node]
22
22
  def parse code, filename = nil, line = 0
23
- RubyVM::AbstractSyntaxTree.parse(code)
23
+ RubyVM::AbstractSyntaxTree.parse(code).children[2]
24
24
  rescue ::SyntaxError => e
25
25
  raise Parser::SyntaxError, e.message
26
26
  end
@@ -83,6 +83,10 @@ module Solargraph
83
83
  NodeChainer.chain *args
84
84
  end
85
85
 
86
+ def chain_string *args
87
+ NodeChainer.load_string *args
88
+ end
89
+
86
90
  def process_node *args
87
91
  Solargraph::Parser::NodeProcessor.process *args
88
92
  end
@@ -69,8 +69,10 @@ module Solargraph
69
69
  result.push Chain::Call.new(n.children[0].to_s, node_to_argchains(n.children[1]), @in_block || block_passed?(n))
70
70
  elsif n.type == :SELF
71
71
  result.push Chain::Head.new('self')
72
- elsif [:SUPER, :ZSUPER].include?(n.type)
73
- result.push Chain::Head.new('super')
72
+ elsif n.type == :ZSUPER
73
+ result.push Chain::ZSuper.new('super', @in_block || block_passed?(n))
74
+ elsif n.type == :SUPER
75
+ result.push Chain::Call.new('super', node_to_argchains(n.children.last), @in_block || block_passed?(n))
74
76
  elsif [:COLON2, :COLON3, :CONST].include?(n.type)
75
77
  const = unpack_name(n)
76
78
  result.push Chain::Constant.new(const)
@@ -20,6 +20,7 @@ module Solargraph
20
20
  autoload :Head, 'solargraph/source/chain/head'
21
21
  autoload :Or, 'solargraph/source/chain/or'
22
22
  autoload :BlockVariable, 'solargraph/source/chain/block_variable'
23
+ autoload :ZSuper, 'solargraph/source/chain/z_super'
23
24
 
24
25
  @@inference_stack = []
25
26
  @@inference_depth = 0
@@ -28,6 +28,7 @@ module Solargraph
28
28
  # @param name_pin [Pin::Base]
29
29
  # @param locals [Array<Pin::Base>]
30
30
  def resolve api_map, name_pin, locals
31
+ return super_pins(api_map, name_pin) if word == 'super'
31
32
  found = if head?
32
33
  locals.select { |p| p.name == word }
33
34
  else
@@ -188,6 +189,14 @@ module Solargraph
188
189
  return false if argcount < parcount && !(argcount == parcount - 1 && parameters.last.first.start_with?('*'))
189
190
  true
190
191
  end
192
+
193
+ # @param api_map [ApiMap]
194
+ # @param name_pin [Pin::Base]
195
+ # @return [Array<Pin::Base>]
196
+ def super_pins api_map, name_pin
197
+ pins = api_map.get_method_stack(name_pin.namespace, name_pin.name, scope: name_pin.scope)
198
+ pins.reject{|p| p.path == name_pin.path}
199
+ end
191
200
  end
192
201
  end
193
202
  end
@@ -10,19 +10,25 @@ module Solargraph
10
10
  class Head < Link
11
11
  def resolve api_map, name_pin, locals
12
12
  return [Pin::ProxyType.anonymous(name_pin.binder)] if word == 'self'
13
- return super_pins(api_map, name_pin) if word == 'super'
13
+ # return super_pins(api_map, name_pin) if word == 'super'
14
14
  []
15
15
  end
16
16
 
17
+ # @todo This is temporary. Chain heads need to handle arguments to
18
+ # `super`.
19
+ # def arguments
20
+ # []
21
+ # end
22
+
17
23
  private
18
24
 
19
- # @param api_map [ApiMap]
20
- # @param name_pin [Pin::Base]
21
- # @return [Array<Pin::Base>]
22
- def super_pins api_map, name_pin
23
- pins = api_map.get_method_stack(name_pin.namespace, name_pin.name, scope: name_pin.scope)
24
- pins.reject{|p| p.path == name_pin.path}
25
- end
25
+ # # @param api_map [ApiMap]
26
+ # # @param name_pin [Pin::Base]
27
+ # # @return [Array<Pin::Base>]
28
+ # def super_pins api_map, name_pin
29
+ # pins = api_map.get_method_stack(name_pin.namespace, name_pin.name, scope: name_pin.scope)
30
+ # pins.reject{|p| p.path == name_pin.path}
31
+ # end
26
32
  end
27
33
  end
28
34
  end
@@ -0,0 +1,184 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solargraph
4
+ class Source
5
+ class Chain
6
+ class ZSuper < Call
7
+ # @return [String]
8
+ attr_reader :word
9
+
10
+ # @return [Array<Chain>]
11
+ attr_reader :arguments
12
+
13
+ # @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, with_block = false
18
+ super(word, [], with_block)
19
+ end
20
+
21
+ def with_block?
22
+ @with_block
23
+ end
24
+
25
+ # @param api_map [ApiMap]
26
+ # @param name_pin [Pin::Base]
27
+ # @param locals [Array<Pin::Base>]
28
+ def resolve api_map, name_pin, locals
29
+ return super_pins(api_map, name_pin)
30
+ end
31
+
32
+ private
33
+
34
+ # @param pins [Array<Pin::Base>]
35
+ # @param api_map [ApiMap]
36
+ # @param context [ComplexType]
37
+ # @param locals [Pin::LocalVariable]
38
+ # @return [Array<Pin::Base>]
39
+ def inferred_pins pins, api_map, context, locals
40
+ result = pins.map do |p|
41
+ overloads = p.docstring.tags(:overload)
42
+ # next p if overloads.empty?
43
+ type = ComplexType::UNDEFINED
44
+ # @param [YARD::Tags::OverloadTag]
45
+ overloads.each do |ol|
46
+ next unless arguments_match(arguments, ol.parameters)
47
+ next if ol.parameters.last && ol.parameters.last.first.start_with?('&') && ol.parameters.last.last.nil? && !with_block?
48
+ match = true
49
+ arguments.each_with_index do |arg, idx|
50
+ achain = arguments[idx]
51
+ next if achain.nil?
52
+ param = ol.parameters[idx]
53
+ if param.nil?
54
+ match = false unless ol.parameters.last && ol.parameters.last.first.start_with?('*')
55
+ break
56
+ end
57
+ par = ol.tags(:param).select { |pp| pp.name == param.first }.first
58
+ next if par.nil? || par.types.nil? || par.types.empty?
59
+ atype = achain.infer(api_map, Pin::ProxyType.anonymous(context), locals)
60
+ other = ComplexType.try_parse(*par.types)
61
+ # @todo Weak type comparison
62
+ unless atype.tag == other.tag || api_map.super_and_sub?(other.tag, atype.tag)
63
+ match = false
64
+ break
65
+ end
66
+ end
67
+ if match
68
+ type = extra_return_type(ol, context)
69
+ type = ComplexType.try_parse(*ol.tag(:return).types).self_to(context.to_s).qualify(api_map, context.namespace) if ol.has_tag?(:return) && ol.tag(:return).types && !ol.tag(:return).types.empty? && (type.nil? || type.undefined?)
70
+ type ||= ComplexType::UNDEFINED
71
+ end
72
+ break if type.defined?
73
+ end
74
+ next p.proxy(type) if type.defined?
75
+ type = extra_return_type(p.docstring, context)
76
+ if type
77
+ next Solargraph::Pin::Method.new(
78
+ location: p.location,
79
+ closure: p.closure,
80
+ name: p.name,
81
+ comments: "@return [#{context.subtypes.first.to_s}]",
82
+ scope: p.scope,
83
+ visibility: p.visibility,
84
+ parameters: p.parameters,
85
+ node: p.node
86
+ )
87
+ end
88
+ if p.is_a?(Pin::Method) && !p.macros.empty?
89
+ result = process_macro(p, api_map, context, locals)
90
+ next result unless result.return_type.undefined?
91
+ elsif !p.directives.empty?
92
+ result = process_directive(p, api_map, context, locals)
93
+ next result unless result.return_type.undefined?
94
+ end
95
+ p
96
+ end
97
+ result.map do |pin|
98
+ next pin if pin.return_type.undefined?
99
+ selfy = pin.return_type.self_to(context.tag)
100
+ selfy == pin.return_type ? pin : pin.proxy(selfy)
101
+ end
102
+ end
103
+
104
+ # @param pin [Pin::Method]
105
+ # @param api_map [ApiMap]
106
+ # @param context [ComplexType]
107
+ # @param locals [Pin::Base]
108
+ # @return [Pin::Base]
109
+ def process_macro pin, api_map, context, locals
110
+ pin.macros.each do |macro|
111
+ result = inner_process_macro(pin, macro, api_map, context, locals)
112
+ return result unless result.return_type.undefined?
113
+ end
114
+ Pin::ProxyType.anonymous(ComplexType::UNDEFINED)
115
+ end
116
+
117
+ # @param pin [Pin::Method]
118
+ # @param api_map [ApiMap]
119
+ # @param context [ComplexType]
120
+ # @param locals [Pin::Base]
121
+ # @return [Pin::ProxyType]
122
+ def process_directive pin, api_map, context, locals
123
+ pin.directives.each do |dir|
124
+ macro = api_map.named_macro(dir.tag.name)
125
+ next if macro.nil?
126
+ result = inner_process_macro(pin, macro, api_map, context, locals)
127
+ return result unless result.return_type.undefined?
128
+ end
129
+ Pin::ProxyType.anonymous ComplexType::UNDEFINED
130
+ end
131
+
132
+ # @param pin [Pin]
133
+ # @param macro [YARD::Tags::MacroDirective]
134
+ # @param api_map [ApiMap]
135
+ # @param context [ComplexType]
136
+ # @param locals [Array<Pin::Base>]
137
+ # @return [Pin::ProxyType]
138
+ def inner_process_macro pin, macro, api_map, context, locals
139
+ vals = arguments.map{ |c| Pin::ProxyType.anonymous(c.infer(api_map, pin, locals)) }
140
+ txt = macro.tag.text.clone
141
+ if txt.empty? && macro.tag.name
142
+ named = api_map.named_macro(macro.tag.name)
143
+ txt = named.tag.text.clone if named
144
+ end
145
+ i = 1
146
+ vals.each do |v|
147
+ txt.gsub!(/\$#{i}/, v.context.namespace)
148
+ i += 1
149
+ end
150
+ docstring = Solargraph::Source.parse_docstring(txt).to_docstring
151
+ tag = docstring.tag(:return)
152
+ unless tag.nil? || tag.types.nil?
153
+ return Pin::ProxyType.anonymous(ComplexType.try_parse(*tag.types))
154
+ end
155
+ Pin::ProxyType.anonymous(ComplexType::UNDEFINED)
156
+ end
157
+
158
+ # @param docstring [YARD::Docstring]
159
+ # @param context [ComplexType]
160
+ # @return [ComplexType]
161
+ def extra_return_type docstring, context
162
+ if docstring.has_tag?(:return_single_parameter) && context.subtypes.one?
163
+ return context.subtypes.first
164
+ elsif docstring.has_tag?(:return_value_parameter) && context.value_types.one?
165
+ return context.value_types.first
166
+ end
167
+ nil
168
+ end
169
+
170
+ # @param arguments [Array<Chain>]
171
+ # @param parameters [Array<String>]
172
+ # @return [Boolean]
173
+ def arguments_match arguments, parameters
174
+ argcount = arguments.length
175
+ # argcount -= 1 if !arguments.empty? && arguments.last.links.first.word.start_with?('&')
176
+ parcount = parameters.length
177
+ parcount -= 1 if !parameters.empty? && parameters.last.first.start_with?('&')
178
+ return false if argcount < parcount && !(argcount == parcount - 1 && parameters.last.first.start_with?('*'))
179
+ true
180
+ end
181
+ end
182
+ end
183
+ end
184
+ end
@@ -248,7 +248,11 @@ module Solargraph
248
248
  if pins.first.is_a?(Pin::BaseMethod)
249
249
  # @type [Pin::BaseMethod]
250
250
  pin = pins.first
251
- ap = arity_problems_for(pin, base.links.last.arguments, location)
251
+ if base.links.last.is_a?(Solargraph::Source::Chain::ZSuper)
252
+ ap = arity_problems_for(pin, fake_args_for(block_pin), location)
253
+ else
254
+ ap = arity_problems_for(pin, base.links.last.arguments, location)
255
+ end
252
256
  unless ap.empty?
253
257
  result.concat ap
254
258
  break
@@ -470,5 +474,25 @@ module Solargraph
470
474
  pin.docstring.has_tag?(:abstract) ||
471
475
  (pin.closure && pin.closure.docstring.has_tag?(:abstract))
472
476
  end
477
+
478
+ def fake_args_for(pin)
479
+ args = []
480
+ with_opts = false
481
+ with_block = false
482
+ pin.parameters.each do |pin|
483
+ if [:kwarg, :kwoptarg, :kwrestarg].include?(pin.decl)
484
+ with_opts = true
485
+ elsif pin.decl == :block
486
+ with_block = true
487
+ elsif pin.decl == :restarg
488
+ args.push Solargraph::Source::Chain.new([Solargraph::Source::Chain::Variable.new(pin.name)], nil, true)
489
+ else
490
+ args.push Solargraph::Source::Chain.new([Solargraph::Source::Chain::Variable.new(pin.name)])
491
+ end
492
+ end
493
+ args.push Solargraph::Parser.chain_string('{}') if with_opts
494
+ args.push Solargraph::Parser.chain_string('&') if with_block
495
+ args
496
+ end
473
497
  end
474
498
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Solargraph
4
- VERSION = '0.39.0'
4
+ VERSION = '0.39.1'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solargraph
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.39.0
4
+ version: 0.39.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fred Snyder
@@ -513,6 +513,7 @@ files:
513
513
  - lib/solargraph/source/chain/literal.rb
514
514
  - lib/solargraph/source/chain/or.rb
515
515
  - lib/solargraph/source/chain/variable.rb
516
+ - lib/solargraph/source/chain/z_super.rb
516
517
  - lib/solargraph/source/change.rb
517
518
  - lib/solargraph/source/cursor.rb
518
519
  - lib/solargraph/source/encoding_fixes.rb