solargraph 0.34.2 → 0.34.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e432b35fd7f9c1466edf9d2f3ae54bcf210ebfaaa79473458b33ba700c6bf902
4
- data.tar.gz: a4bb6dbe4b7e6ce15bf1177c75ecce9fe13fc10a499527622b5675893bdb0053
3
+ metadata.gz: 19d601d06fae9aedf33e93d09172bb9257757aaf7323f6f6a355c82fc7b67223
4
+ data.tar.gz: 5a5d073284cd8034b710dbb22169a30478e490e8561b4e2be56b59a52c79b757
5
5
  SHA512:
6
- metadata.gz: d05491b24576660461f939eb763d10b6247ec47140ecceef8e0c4f1387074a427850c0d25c0a3624641b42e66e4964782e369c89738aec2ee067d9d2c9aafdb4
7
- data.tar.gz: b0f8d060d9f19810789f1b4190758afe45b608cc4da25e92eed3797550f096f9fa2352723a9c3954e2b3b3bcc3368ca505903476cb36991c337b654fd1fd2ce4
6
+ metadata.gz: 0071a0c809fae4043ea2ffa35ef811f575d1c9027f199c47d344692ce0e7a641a10f94af240220959a5ef924f92985511afebd8b502cc35ed023bbffe2b27a62
7
+ data.tar.gz: 0076f43c9ae828ead40ec6d64a6409fa96d3631a290673baf026aa65e8f72fbdc8103cd073a7f5919945cd8a7f598f233889ef38ea173f3e58cd27cbb03f8812
data/.travis.yml CHANGED
@@ -6,11 +6,15 @@ rvm:
6
6
  - 2.4
7
7
  - 2.5
8
8
  - 2.6
9
- - jruby-9.2
9
+ - jruby-head
10
10
  matrix:
11
11
  include:
12
12
  - rvm: 2.5
13
13
  os: osx
14
+ - rvm: 2.6
15
+ os: osx
16
+ allow_failures:
17
+ - rvm: jruby-head
14
18
  # Update RubyGems and Bundler due to error with Bundler 1.16.1 and RubyGems 2.7.3
15
19
  # See https://github.com/travis-ci/travis-ci/issues/8978
16
20
  before_install:
@@ -121,8 +121,8 @@ module Solargraph
121
121
  point_stack = 0
122
122
  curly_stack = 0
123
123
  paren_stack = 0
124
- base = ''
125
- subtype_string = ''
124
+ base = String.new
125
+ subtype_string = String.new
126
126
  type_string.each_char do |char|
127
127
  if char == '='
128
128
  #raise ComplexTypeError, "Invalid = in type #{type_string}" unless curly_stack > 0
@@ -137,8 +137,8 @@ module Solargraph
137
137
  types.push UniqueType.new(base[0..-2].strip)
138
138
  key_types = types
139
139
  types = []
140
- base = ''
141
- subtype_string = ''
140
+ base.clear
141
+ subtype_string.clear
142
142
  next
143
143
  else
144
144
  point_stack -= 1
@@ -163,14 +163,14 @@ module Solargraph
163
163
  elsif char == ',' && point_stack == 0 && curly_stack == 0 && paren_stack == 0
164
164
  # types.push ComplexType.new([UniqueType.new(base.strip, subtype_string.strip)])
165
165
  types.push UniqueType.new(base.strip, subtype_string.strip)
166
- base = ''
167
- subtype_string = ''
166
+ base.clear
167
+ subtype_string.clear
168
168
  next
169
169
  end
170
170
  if point_stack == 0 && curly_stack == 0 && paren_stack == 0
171
- base += char
171
+ base.concat char
172
172
  else
173
- subtype_string += char
173
+ subtype_string.concat char
174
174
  end
175
175
  end
176
176
  raise ComplexTypeError, "Unclosed subtype in #{type_string}" if point_stack != 0 || curly_stack != 0 || paren_stack != 0
@@ -24,7 +24,8 @@ module Solargraph
24
24
 
25
25
  # @return [Boolean]
26
26
  def nil_type?
27
- @nil_type ||= (name.downcase == 'nil')
27
+ @nil_type = (name.casecmp('nil') == 0) if @nil_type.nil?
28
+ @nil_type
28
29
  end
29
30
 
30
31
  # @return [Boolean]
@@ -25,6 +25,13 @@ module Solargraph
25
25
  Override.method_return('Array#reject', 'self'),
26
26
  Override.method_return('Array#keep_if', 'self'),
27
27
  Override.method_return('Array#delete_if', 'self'),
28
+ Override.method_return('Array#reverse', 'self', delete: ['overload']),
29
+ Override.from_comment('Array#select', %(
30
+ @overload select(&block)
31
+ @return [self]
32
+ @overload select()
33
+ @return [Enumerator]
34
+ )),
28
35
  Override.from_comment('Array#[]', %(
29
36
  @overload [](range)
30
37
  @param range [Range]
@@ -50,7 +57,7 @@ module Solargraph
50
57
  @return [self]
51
58
  @return_single_parameter
52
59
  )),
53
-
60
+
54
61
  Override.method_return('Class#new', 'self'),
55
62
  Override.method_return('Class.new', 'Class<Object>'),
56
63
  Override.method_return('Class#allocate', 'self'),
@@ -63,7 +70,7 @@ module Solargraph
63
70
  Override.from_comment('Hash#[]', %(
64
71
  @return_value_parameter
65
72
  )),
66
-
73
+
67
74
  Override.method_return('Object#!', 'Boolean'),
68
75
  Override.method_return('Object#clone', 'self', delete: [:overload]),
69
76
  Override.method_return('Object#dup', 'self'),
@@ -20,6 +20,8 @@ module Solargraph
20
20
  include Dispatch
21
21
  include Observable
22
22
 
23
+ attr_writer :client_capabilities
24
+
23
25
  def initialize
24
26
  @cancel_semaphore = Mutex.new
25
27
  @buffer_semaphore = Mutex.new
@@ -362,16 +364,18 @@ module Solargraph
362
364
  # @return [void]
363
365
  def register_capabilities methods
364
366
  logger.debug "Registering capabilities: #{methods}"
367
+ registrations = methods.select{|m| can_register?(m) and !registered?(m)}.map { |m|
368
+ @registered_capabilities.add m
369
+ {
370
+ id: m,
371
+ method: m,
372
+ registerOptions: dynamic_capability_options[m]
373
+ }
374
+ }
375
+ return if registrations.empty?
365
376
  @register_semaphore.synchronize do
366
377
  send_request 'client/registerCapability', {
367
- registrations: methods.select{|m| can_register?(m) and !registered?(m)}.map { |m|
368
- @registered_capabilities.add m
369
- {
370
- id: m,
371
- method: m,
372
- registerOptions: dynamic_capability_options[m]
373
- }
374
- }
378
+ registrations: registrations
375
379
  }
376
380
  end
377
381
  end
@@ -384,15 +388,17 @@ module Solargraph
384
388
  # @return [void]
385
389
  def unregister_capabilities methods
386
390
  logger.debug "Unregistering capabilities: #{methods}"
391
+ unregisterations = methods.select{|m| registered?(m)}.map{ |m|
392
+ @registered_capabilities.delete m
393
+ {
394
+ id: m,
395
+ method: m
396
+ }
397
+ }
398
+ return if unregisterations.empty?
387
399
  @register_semaphore.synchronize do
388
400
  send_request 'client/unregisterCapability', {
389
- unregisterations: methods.select{|m| registered?(m)}.map{ |m|
390
- @registered_capabilities.delete m
391
- {
392
- id: m,
393
- method: m
394
- }
395
- }
401
+ unregisterations: unregisterations
396
402
  }
397
403
  end
398
404
  end
@@ -613,6 +619,10 @@ module Solargraph
613
619
  libraries.each(&:catalog)
614
620
  end
615
621
 
622
+ def client_capabilities
623
+ @client_capabilities ||= {}
624
+ end
625
+
616
626
  private
617
627
 
618
628
  # @return [Diagnoser]
@@ -693,7 +703,7 @@ module Solargraph
693
703
  referencesProvider: true
694
704
  },
695
705
  'textDocument/rename' => {
696
- renameProvider: {prepareProvider: true}
706
+ renameProvider: prepare_rename? ? { prepareProvider: true } : true
697
707
  },
698
708
  'textDocument/documentSymbol' => {
699
709
  documentSymbolProvider: true
@@ -712,6 +722,10 @@ module Solargraph
712
722
  }
713
723
  }
714
724
  end
725
+
726
+ def prepare_rename?
727
+ client_capabilities['rename'] && client_capabilities['rename']['prepareSupport']
728
+ end
715
729
  end
716
730
  end
717
731
  end
@@ -85,8 +85,10 @@ module Solargraph
85
85
  # @return [void]
86
86
  def async_update uri, updater
87
87
  src = find(uri)
88
- mutex.synchronize { open_source_hash[uri] = src.start_synchronize(updater) }
89
- mutex.synchronize { queue.push uri }
88
+ mutex.synchronize do
89
+ open_source_hash[uri] = src.start_synchronize(updater)
90
+ queue.push uri
91
+ end
90
92
  changed
91
93
  notify_observers uri
92
94
  end
@@ -9,6 +9,7 @@ module Solargraph
9
9
  def process
10
10
  bm = Benchmark.measure {
11
11
  host.configure params['initializationOptions']
12
+ host.client_capabilities = params['capabilities']
12
13
  if support_workspace_folders?
13
14
  host.prepare_folders params['workspaceFolders']
14
15
  elsif params['rootUri']
@@ -213,6 +213,10 @@ module Solargraph
213
213
  result
214
214
  end
215
215
 
216
+ def identity
217
+ @identity ||= "#{closure.context.namespace}|#{name}"
218
+ end
219
+
216
220
  def inspect
217
221
  "#<#{self.class} at #{self.location.inspect}>"
218
222
  end
@@ -19,7 +19,7 @@ module Solargraph
19
19
  end
20
20
 
21
21
  def path
22
- @path ||= namespace.to_s + (scope == :instance ? '#' : '.') + name.to_s
22
+ @path ||= "#{namespace}#{(scope == :instance ? '#' : '.')}#{name}"
23
23
  end
24
24
 
25
25
  def typify api_map
@@ -20,8 +20,7 @@ module Solargraph
20
20
  end
21
21
 
22
22
  def path
23
- return name if context.namespace.to_s.empty?
24
- "#{context.namespace}::#{name}"
23
+ @path ||= context.namespace.to_s.empty? ? name : "#{context.namespace}::#{name}"
25
24
  end
26
25
  end
27
26
  end
@@ -112,8 +112,7 @@ module Solargraph
112
112
  location.filename,
113
113
  [n.loc.expression.last_line, n.loc.expression.last_column]
114
114
  )
115
- chain = Solargraph::Source::NodeChainer.chain(n, location.filename)
116
- type = chain.infer(api_map, self, clip.locals)
115
+ type = clip.infer
117
116
  result.push type unless type.undefined?
118
117
  end
119
118
  end
@@ -44,6 +44,10 @@ module Solargraph
44
44
  true
45
45
  end
46
46
 
47
+ def probe api_map
48
+ typify api_map
49
+ end
50
+
47
51
  private
48
52
 
49
53
  # @return [YARD::Tags::Tag]
@@ -71,9 +75,11 @@ module Solargraph
71
75
  meths = chain.define(api_map, closure, locals)
72
76
  meths.each do |meth|
73
77
  if meth.docstring.has_tag?(:yieldparam_single_parameter)
74
- bmeth = chain.base.define(api_map, closure, locals).first
75
- return ComplexType::UNDEFINED if bmeth.nil? || bmeth.return_type.undefined? || bmeth.return_type.subtypes.empty?
76
- return bmeth.return_type.subtypes.first.qualify(api_map, bmeth.context.namespace)
78
+ type = chain.base.infer(api_map, closure, locals)
79
+ if type.defined? && !type.subtypes.empty?
80
+ bmeth = chain.base.define(api_map, closure, locals).first
81
+ return type.subtypes.first.qualify(api_map, bmeth.context.namespace)
82
+ end
77
83
  else
78
84
  yps = meth.docstring.tags(:yieldparam)
79
85
  unless yps[index].nil? or yps[index].types.nil? or yps[index].types.empty?
@@ -18,16 +18,15 @@ module Solargraph
18
18
  location: location,
19
19
  name: code_object.name.to_s,
20
20
  comments: nil,
21
- type: namespace_type(code_object),
21
+ type: namespace_type,
22
22
  visibility: code_object.visibility,
23
- closure: closure,
24
- gates: split_to_gates(code_object.path)
23
+ closure: closure
25
24
  )
26
25
  end
27
26
 
28
27
  private
29
28
 
30
- def namespace_type code_object
29
+ def namespace_type
31
30
  code_object.is_a?(YARD::CodeObjects::ClassObject) ? :class : :module
32
31
  end
33
32
  end
@@ -15,25 +15,19 @@ module Solargraph
15
15
  end
16
16
 
17
17
  def location
18
+ # Guarding with @located because nil locations are valid
18
19
  return @location if @located
19
20
  @located = true
20
- @location = Solargraph::YardMap::Mapper.object_location(code_object, spec)
21
+ @location = object_location
21
22
  end
22
23
 
23
24
  private
24
25
 
25
- def split_to_gates namespace
26
- @@gate_cache[namespace] || begin
27
- parts = namespace.split('::')
28
- result = []
29
- until parts.empty?
30
- result.push parts.join('::')
31
- parts.pop
32
- end
33
- result.push ''
34
- @@gate_cache[namespace] = result.freeze
35
- result
36
- end
26
+ # @return [Solargraph::Location, nil]
27
+ def object_location
28
+ return nil if spec.nil? || code_object.nil? || code_object.file.nil? || code_object.line.nil?
29
+ file = File.join(spec.full_gem_path, code_object.file)
30
+ Solargraph::Location.new(file, Solargraph::Range.from_to(code_object.line - 1, 0, code_object.line - 1, 0))
37
31
  end
38
32
  end
39
33
  end
@@ -198,7 +198,7 @@ module Solargraph
198
198
  # @param pin [Solargraph::Pin::Base]
199
199
  # @return [String]
200
200
  def pin_description pin
201
- if pin.path.nil? || pin.path.empty?
201
+ desc = if pin.path.nil? || pin.path.empty?
202
202
  if pin.closure
203
203
  "#{pin.closure.path} | #{pin.name}"
204
204
  else
@@ -207,6 +207,8 @@ module Solargraph
207
207
  else
208
208
  pin.path
209
209
  end
210
+ desc += " (#{pin.location.filename} #{pin.location.range.start.line})" if pin.location
211
+ desc
210
212
  end
211
213
  end
212
214
  end
@@ -22,6 +22,8 @@ module Solargraph
22
22
 
23
23
  @@inference_stack = []
24
24
  @@inference_depth = 0
25
+ @@last_api_map = nil
26
+ @@pin_cache = {}
25
27
 
26
28
  UNDEFINED_CALL = Chain::Call.new('<undefined>')
27
29
  UNDEFINED_CONSTANT = Chain::Constant.new('<undefined>')
@@ -105,11 +107,18 @@ module Solargraph
105
107
  # Limit method inference recursion
106
108
  return type if @@inference_depth >= 2 && pins.first.is_a?(Pin::BaseMethod)
107
109
  @@inference_depth += 1
110
+ name_count = {}
108
111
  pins.each do |pin|
112
+ # Limit pin name hits for, e.g., variables with insane amounts of definitions
113
+ name_count[pin.identity] ||= 0
114
+ name_count[pin.identity] += 1
115
+ next if name_count[pin.identity] >= 10
109
116
  # Avoid infinite recursion
110
117
  next if @@inference_stack.include?(pin)
111
118
  @@inference_stack.push pin
112
- type = pin.probe(api_map)
119
+ # puts " Inferring #{pin.class} | #{pin.path} | #{pin.name} | #{pin.location ? pin.location.to_hash : pin.location}"
120
+ # type = pin.probe(api_map)
121
+ type = remember_or_probe(pin, api_map)
113
122
  @@inference_stack.pop
114
123
  break if type.defined?
115
124
  end
@@ -147,6 +156,12 @@ module Solargraph
147
156
  end
148
157
  end
149
158
  end
159
+
160
+ def remember_or_probe pin, api_map
161
+ @@pin_cache.clear if @@last_api_map != api_map
162
+ @@last_api_map = api_map
163
+ @@pin_cache[pin] ||= pin.probe(api_map)
164
+ end
150
165
  end
151
166
  end
152
167
  end
@@ -12,9 +12,14 @@ module Solargraph
12
12
 
13
13
  # @param word [String]
14
14
  # @param arguments [Array<Chain>]
15
- def initialize word, arguments = []
15
+ def initialize word, arguments = [], with_block = false
16
16
  @word = word
17
17
  @arguments = arguments
18
+ @with_block = with_block
19
+ end
20
+
21
+ def with_block?
22
+ @with_block
18
23
  end
19
24
 
20
25
  # @param api_map [ApiMap]
@@ -42,8 +47,8 @@ module Solargraph
42
47
  type = ComplexType::UNDEFINED
43
48
  # @param [YARD::Tags::OverloadTag]
44
49
  overloads.each do |ol|
45
- next if arguments.length < ol.parameters.length &&
46
- !(arguments.length == ol.parameters.length - 1 && ol.parameters.last.first.start_with?('*'))
50
+ next unless arguments_match(arguments, ol.parameters)
51
+ next if ol.parameters.last && ol.parameters.last.first.start_with?('&') && ol.parameters.last.last.nil? && !with_block?
47
52
  match = true
48
53
  arguments.each_with_index do |arg, idx|
49
54
  achain = arguments[idx]
@@ -95,7 +100,7 @@ module Solargraph
95
100
  end
96
101
  result.map do |pin|
97
102
  next pin if pin.return_type.undefined?
98
- selfy = pin.return_type.self_to(context.namespace)
103
+ selfy = pin.return_type.self_to(context.tag)
99
104
  selfy == pin.return_type ? pin : pin.proxy(selfy)
100
105
  end
101
106
  end
@@ -156,6 +161,15 @@ module Solargraph
156
161
  end
157
162
  nil
158
163
  end
164
+
165
+ def arguments_match arguments, parameters
166
+ argcount = arguments.length
167
+ # argcount -= 1 if !arguments.empty? && arguments.last.links.first.word.start_with?('&')
168
+ parcount = parameters.length
169
+ parcount -= 1 if !parameters.empty? && parameters.last.first.start_with?('&')
170
+ return false if argcount < parcount && !(argcount == parcount - 1 && parameters.last.first.start_with?('*'))
171
+ true
172
+ end
159
173
  end
160
174
  end
161
175
  end
@@ -9,9 +9,10 @@ module Solargraph
9
9
 
10
10
  # @param node [Parser::AST::Node]
11
11
  # @param filename [String]
12
- def initialize node, filename = nil
12
+ def initialize node, filename = nil, in_block = false
13
13
  @node = node
14
14
  @filename = filename
15
+ @in_block = in_block
15
16
  end
16
17
 
17
18
  # @return [Source::Chain]
@@ -24,8 +25,8 @@ module Solargraph
24
25
  # @param node [Parser::AST::Node]
25
26
  # @param filename [String]
26
27
  # @return [Chain]
27
- def chain node, filename = nil
28
- NodeChainer.new(node, filename).chain
28
+ def chain node, filename = nil, in_block = false
29
+ NodeChainer.new(node, filename, in_block).chain
29
30
  end
30
31
 
31
32
  # @param code [String]
@@ -55,13 +56,13 @@ module Solargraph
55
56
  n.children[2..-1].each do |c|
56
57
  args.push NodeChainer.chain(c)
57
58
  end
58
- result.push Chain::Call.new(n.children[1].to_s, args)
59
+ result.push Chain::Call.new(n.children[1].to_s, args, @in_block)
59
60
  elsif n.children[0].nil?
60
61
  args = []
61
62
  n.children[2..-1].each do |c|
62
63
  args.push NodeChainer.chain(c)
63
64
  end
64
- result.push Chain::Call.new(n.children[1].to_s, args)
65
+ result.push Chain::Call.new(n.children[1].to_s, args, @in_block)
65
66
  else
66
67
  raise "No idea what to do with #{n}"
67
68
  end
@@ -35,13 +35,14 @@ module Solargraph
35
35
  return Chain.new([Chain::Literal.new('Symbol')]) if phrase.start_with?(':') && !phrase.start_with?('::')
36
36
  begin
37
37
  return Chain.new([]) if phrase.end_with?('..')
38
+ node = nil
39
+ parent = nil
38
40
  if !source.repaired? && source.parsed? && source.synchronized?
39
- node = source.node_at(position.line, position.column)
41
+ node, parent = source.tree_at(position.line, position.column)[0..2]
40
42
  elsif source.parsed? && source.repaired? && end_of_phrase == '.'
41
- node = source.node_at(fixed_position.line, fixed_position.column)
43
+ node, parent = source.tree_at(fixed_position.line, fixed_position.column)[0..2]
42
44
  else
43
- node = nil
44
- node = source.node_at(fixed_position.line, fixed_position.column) unless source.error_ranges.any?{|r| r.nil? || r.include?(fixed_position)}
45
+ node, parent = source.tree_at(fixed_position.line, fixed_position.column)[0..2] unless source.error_ranges.any?{|r| r.nil? || r.include?(fixed_position)}
45
46
  # Exception for positions that chain literal nodes in unsynchronized sources
46
47
  node = nil unless source.synchronized? || !infer_literal_node_type(node).nil?
47
48
  node = Source.parse(fixed_phrase) if node.nil?
@@ -50,7 +51,7 @@ module Solargraph
50
51
  return Chain.new([Chain::UNDEFINED_CALL])
51
52
  end
52
53
  return Chain.new([Chain::UNDEFINED_CALL]) if node.nil? || (node.type == :sym && !phrase.start_with?(':'))
53
- chain = NodeChainer.chain(node, source.filename)
54
+ chain = NodeChainer.chain(node, source.filename, parent && parent.type == :block)
54
55
  if source.repaired? || !source.parsed? || !source.synchronized?
55
56
  if end_of_phrase.strip == '.'
56
57
  chain.links.push Chain::UNDEFINED_CALL
@@ -12,7 +12,7 @@ module Solargraph
12
12
 
13
13
  private_class_method :new
14
14
 
15
- MACRO_REGEXP = /(@\!method|@\!attribute|@\!domain|@\!macro|@\!parse)/.freeze
15
+ MACRO_REGEXP = /(@\!method|@\!attribute|@\!domain|@\!macro|@\!parse|@\!override)/.freeze
16
16
 
17
17
  # Generate the data.
18
18
  #
@@ -67,14 +67,27 @@ module Solargraph
67
67
  last_line = 0
68
68
  # @param d [YARD::Tags::Directive]
69
69
  parse.directives.each do |d|
70
- line_num = cmnt.lines[last_line..-1].find_index { |l| l.include?("@!#{d.tag.tag_name}") }
71
- line_num += last_line
70
+ line_num = find_directive_line_number(cmnt, d.tag.tag_name, last_line)
72
71
  pos = Solargraph::Position.new(comment_position.line + line_num, comment_position.column)
73
72
  process_directive(source_position, pos, d)
74
73
  last_line = line_num + 1
74
+ # @todo The below call assumes the topmost comment line. The above
75
+ # process occasionally emits incorrect comment positions due to
76
+ # blank lines in comment blocks, but at least it processes all the
77
+ # directives.
78
+ # process_directive(source_position, comment_position, d)
75
79
  end
76
80
  end
77
81
 
82
+ def find_directive_line_number comment, tag, start
83
+ num = comment.lines[start..-1].find_index do |line|
84
+ # Legacy method directives might be `@method` instead of `@!method`
85
+ # @todo Legacy syntax should probably emit a warning
86
+ line.include?("@!#{tag}") || (tag == 'method' && line.include?("@#{tag}"))
87
+ end
88
+ num.to_i + start
89
+ end
90
+
78
91
  # @param position [Position]
79
92
  # @param directive [YARD::Tags::Directive]
80
93
  def process_directive source_position, comment_position, directive
@@ -192,12 +192,21 @@ module Solargraph
192
192
  break
193
193
  end
194
194
  else
195
- # @todo Break here? Not sure about that
196
- break if curtype.type == :restarg || curtype.type == :kwrestarg
195
+ # @todo This should also detect when the last parameter is a hash
196
+ if curtype.type == :kwrestarg
197
+ if arg.type != :hash
198
+ result.push Problem.new(Solargraph::Location.new(filename, Solargraph::Range.from_node(node)), "Wrong parameter type for #{pin.path}: expected hash or keyword")
199
+ else
200
+ result.concat check_hash_params arg, params
201
+ end
202
+ # @todo Break here? Not sure about that
203
+ break
204
+ end
205
+ break if curtype.type == :restarg
197
206
  if arg.is_a?(Parser::AST::Node) && arg.type == :hash
198
207
  arg.children.each do |pair|
199
208
  sym = pair.children[0].children[0].to_s
200
- partype = params[pin.parameter_names[index]]
209
+ partype = params[sym]
201
210
  if partype
202
211
  chain = Solargraph::Source::NodeChainer.chain(pair.children[1], filename)
203
212
  argtype = chain.infer(api_map, block, locals)
@@ -242,6 +251,24 @@ module Solargraph
242
251
  result
243
252
  end
244
253
 
254
+ def check_hash_params arg, params
255
+ result = []
256
+ keys = arg.children.map do |child|
257
+ child.children[0].children[0].to_s
258
+ end
259
+ keys.each do |key|
260
+ param = params[key]
261
+ if param
262
+ # @todo typecheck
263
+ else
264
+ # @todo This error might not be valid. If there's a splat in the
265
+ # method parameters, should the type checker let it pass?
266
+ result.push Problem.new(nil, "Keyword argument #{key} does not have a @param tag")
267
+ end
268
+ end
269
+ result
270
+ end
271
+
245
272
  def arg_to_duck arg, par
246
273
  return false unless par.duck_type?
247
274
  meths = api_map.get_complex_type_methods(arg).map(&:name)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Solargraph
4
- VERSION = '0.34.2'
4
+ VERSION = '0.34.3'
5
5
  end
@@ -171,8 +171,6 @@ module Solargraph
171
171
  result = []
172
172
  begin
173
173
  spec = spec_for_require(r)
174
- ver = spec.version.to_s
175
- ver = ">= 0" if ver.empty?
176
174
  yd = yardoc_file_for_spec(spec)
177
175
  # YARD detects gems for certain libraries that do not have a yardoc
178
176
  # but exist in the stdlib. `fileutils` is an example. Treat those
@@ -5,7 +5,7 @@ module Solargraph
5
5
  class Mapper
6
6
  @@object_file_cache = {}
7
7
 
8
- # @param code_objects [Array<YARD::CodeObject::Base>]
8
+ # @param code_objects [Array<YARD::CodeObjects::Base>]
9
9
  # @param spec [Gem::Specification]
10
10
  def initialize code_objects, spec = nil
11
11
  @code_objects = code_objects
@@ -65,22 +65,6 @@ module Solargraph
65
65
  end
66
66
  result
67
67
  end
68
-
69
- # @param obj [YARD::CodeObjects::Base]
70
- # @return [Solargraph::Location, nil]
71
- def self.object_location obj, spec = nil
72
- return nil if spec.nil? || obj.file.nil? || obj.line.nil?
73
- file = nil
74
- if @@object_file_cache.key?(obj.file)
75
- file = @@object_file_cache[obj.file]
76
- else
77
- tmp = File.join(spec.full_gem_path, obj.file)
78
- file = tmp if File.exist?(tmp)
79
- @@object_file_cache[obj.file] = file
80
- end
81
- return nil if file.nil?
82
- Solargraph::Location.new(file, Solargraph::Range.from_to(obj.line - 1, 0, obj.line - 1, 0))
83
- end
84
68
  end
85
69
  end
86
70
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solargraph
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.34.2
4
+ version: 0.34.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fred Snyder
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-07-03 00:00:00.000000000 Z
11
+ date: 2019-07-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: backport