solargraph 0.34.2 → 0.34.3

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: 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