solargraph 0.45.0 → 0.49.0
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 +4 -4
- data/.github/FUNDING.yml +1 -0
- data/.github/workflows/rspec.yml +1 -1
- data/CHANGELOG.md +41 -0
- data/LICENSE +1 -1
- data/README.md +8 -0
- data/SPONSORS.md +2 -4
- data/lib/solargraph/api_map/store.rb +13 -1
- data/lib/solargraph/api_map.rb +55 -32
- data/lib/solargraph/cache.rb +51 -0
- data/lib/solargraph/complex_type/type_methods.rb +10 -6
- data/lib/solargraph/complex_type/unique_type.rb +57 -0
- data/lib/solargraph/complex_type.rb +35 -2
- data/lib/solargraph/convention/rakefile.rb +17 -0
- data/lib/solargraph/convention.rb +2 -0
- data/lib/solargraph/diagnostics/require_not_found.rb +16 -0
- data/lib/solargraph/diagnostics/rubocop.rb +17 -3
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +3 -1
- data/lib/solargraph/language_server/host.rb +22 -18
- data/lib/solargraph/language_server/message/extended/download_core.rb +1 -5
- data/lib/solargraph/language_server/message/initialize.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/formatting.rb +1 -1
- data/lib/solargraph/language_server/message/text_document/hover.rb +16 -4
- data/lib/solargraph/language_server/message/text_document/signature_help.rb +1 -6
- data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +10 -3
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +1 -1
- data/lib/solargraph/library.rb +21 -20
- data/lib/solargraph/parser/legacy/node_processors/casgn_node.rb +12 -2
- data/lib/solargraph/parser/legacy/node_processors/sclass_node.rb +24 -3
- data/lib/solargraph/parser/rubyvm/class_methods.rb +7 -2
- data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +13 -2
- data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +20 -9
- data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +14 -3
- data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +2 -2
- data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +14 -3
- data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +4 -2
- data/lib/solargraph/parser/rubyvm/node_wrapper.rb +47 -0
- data/lib/solargraph/pin/base.rb +5 -2
- data/lib/solargraph/pin/block.rb +2 -1
- data/lib/solargraph/pin/conversions.rb +2 -6
- data/lib/solargraph/pin/method.rb +100 -10
- data/lib/solargraph/pin/namespace.rb +4 -1
- data/lib/solargraph/pin/parameter.rb +10 -7
- data/lib/solargraph/pin/search.rb +56 -0
- data/lib/solargraph/pin/signature.rb +23 -0
- data/lib/solargraph/pin.rb +2 -0
- data/lib/solargraph/rbs_map/conversions.rb +394 -0
- data/lib/solargraph/rbs_map/core_fills.rb +61 -0
- data/lib/solargraph/rbs_map/core_map.rb +38 -0
- data/lib/solargraph/rbs_map/core_signs.rb +33 -0
- data/lib/solargraph/rbs_map/stdlib_map.rb +36 -0
- data/lib/solargraph/rbs_map.rb +73 -0
- data/lib/solargraph/shell.rb +38 -30
- data/lib/solargraph/source/chain/call.rb +34 -23
- data/lib/solargraph/source/chain.rb +21 -6
- data/lib/solargraph/source.rb +1 -1
- data/lib/solargraph/source_map/clip.rb +5 -0
- data/lib/solargraph/source_map/mapper.rb +31 -2
- data/lib/solargraph/source_map.rb +1 -10
- data/lib/solargraph/type_checker/checks.rb +13 -0
- data/lib/solargraph/type_checker.rb +88 -68
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/views/environment.erb +2 -2
- data/lib/solargraph/workspace.rb +12 -14
- data/lib/solargraph/yard_map/mapper/to_method.rb +7 -4
- data/lib/solargraph/yard_map.rb +51 -195
- data/lib/solargraph.rb +2 -2
- data/solargraph.gemspec +8 -6
- metadata +44 -36
- data/lib/solargraph/compat.rb +0 -37
- data/lib/solargraph/yard_map/core_docs.rb +0 -170
- data/lib/solargraph/yard_map/core_fills.rb +0 -208
- data/lib/solargraph/yard_map/core_gen.rb +0 -76
- data/lib/solargraph/yard_map/rdoc_to_yard.rb +0 -140
- data/lib/solargraph/yard_map/stdlib_fills.rb +0 -43
- data/yardoc/2.2.2.tar.gz +0 -0
@@ -40,10 +40,12 @@ module Solargraph
|
|
40
40
|
# @return [Array<Problem>]
|
41
41
|
def problems
|
42
42
|
@problems ||= begin
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
43
|
+
without_ignored(
|
44
|
+
method_tag_problems
|
45
|
+
.concat variable_type_tag_problems
|
46
|
+
.concat const_problems
|
47
|
+
.concat call_problems
|
48
|
+
)
|
47
49
|
end
|
48
50
|
end
|
49
51
|
|
@@ -103,7 +105,7 @@ module Solargraph
|
|
103
105
|
result.push Problem.new(pin.location, "#{pin.path} return type could not be inferred", pin: pin)
|
104
106
|
end
|
105
107
|
else
|
106
|
-
unless (rules.rank > 1 ?
|
108
|
+
unless (rules.rank > 1 ? all_types_match?(api_map, inferred, declared) : any_types_match?(api_map, declared, inferred))
|
107
109
|
result.push Problem.new(pin.location, "Declared return type #{declared} does not match inferred type #{inferred} for #{pin.path}", pin: pin)
|
108
110
|
end
|
109
111
|
end
|
@@ -118,7 +120,10 @@ module Solargraph
|
|
118
120
|
# @param pin [Pin::Base]
|
119
121
|
# @return [Boolean]
|
120
122
|
def resolved_constant? pin
|
121
|
-
|
123
|
+
return true if pin.typify(api_map).defined?
|
124
|
+
api_map.get_constants('', *pin.closure.gates)
|
125
|
+
.select { |p| p.name == pin.return_type.namespace }
|
126
|
+
.any? { |p| p.infer(api_map).defined? }
|
122
127
|
end
|
123
128
|
|
124
129
|
def virtual_pin? pin
|
@@ -132,10 +137,12 @@ module Solargraph
|
|
132
137
|
params = first_param_hash(stack)
|
133
138
|
result = []
|
134
139
|
if rules.require_type_tags?
|
135
|
-
pin.
|
136
|
-
|
137
|
-
|
138
|
-
|
140
|
+
pin.signatures.each do |sig|
|
141
|
+
sig.parameters.each do |par|
|
142
|
+
break if par.decl == :restarg || par.decl == :kwrestarg || par.decl == :blockarg
|
143
|
+
unless params[par.name]
|
144
|
+
result.push Problem.new(pin.location, "Missing @param tag for #{par.name} on #{pin.path}", pin: pin)
|
145
|
+
end
|
139
146
|
end
|
140
147
|
end
|
141
148
|
end
|
@@ -170,14 +177,14 @@ module Solargraph
|
|
170
177
|
result.push Problem.new(pin.location, "Variable type could not be inferred for #{pin.name}", pin: pin)
|
171
178
|
end
|
172
179
|
else
|
173
|
-
unless
|
180
|
+
unless any_types_match?(api_map, declared, inferred)
|
174
181
|
result.push Problem.new(pin.location, "Declared type #{declared} does not match inferred type #{inferred} for variable #{pin.name}", pin: pin)
|
175
182
|
end
|
176
183
|
end
|
177
184
|
elsif declared_externally?(pin)
|
178
185
|
ignored_pins.push pin
|
179
186
|
end
|
180
|
-
elsif !pin.is_a?(Pin::Parameter)
|
187
|
+
elsif !pin.is_a?(Pin::Parameter) && !resolved_constant?(pin)
|
181
188
|
result.push Problem.new(pin.location, "Unresolved type #{pin.return_type} for variable #{pin.name}", pin: pin)
|
182
189
|
end
|
183
190
|
else
|
@@ -235,8 +242,8 @@ module Solargraph
|
|
235
242
|
base = base.base
|
236
243
|
end
|
237
244
|
closest = found.typify(api_map) if found
|
238
|
-
if !found || (closest.defined? && internal_or_core?(found))
|
239
|
-
unless ignored_pins.include?(found)
|
245
|
+
if !found || found.is_a?(Pin::BaseVariable) || (closest.defined? && internal_or_core?(found))
|
246
|
+
unless closest.parameterized? || ignored_pins.include?(found)
|
240
247
|
result.push Problem.new(location, "Unresolved call to #{missing.links.last.word}")
|
241
248
|
@marked_ranges.push rng
|
242
249
|
end
|
@@ -266,34 +273,44 @@ module Solargraph
|
|
266
273
|
end
|
267
274
|
break unless rules.validate_calls?
|
268
275
|
params = first_param_hash(pins)
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
276
|
+
|
277
|
+
all_errors = []
|
278
|
+
pin.signatures.sort { |sig| sig.parameters.length }.each do |sig|
|
279
|
+
errors = []
|
280
|
+
sig.parameters.each_with_index do |par, idx|
|
281
|
+
argchain = base.links.last.arguments[idx]
|
282
|
+
if argchain.nil? && par.decl == :arg
|
283
|
+
errors.push Problem.new(location, "Not enough arguments to #{pin.path}")
|
284
|
+
next
|
285
|
+
end
|
286
|
+
if argchain
|
287
|
+
if par.decl != :arg
|
288
|
+
errors.concat kwarg_problems_for argchain, api_map, block_pin, locals, location, pin, params, idx
|
289
|
+
next
|
283
290
|
else
|
284
|
-
|
285
|
-
if
|
286
|
-
|
291
|
+
ptype = params.key?(par.name) ? params[par.name][:qualified] : ComplexType::UNDEFINED
|
292
|
+
if ptype.nil?
|
293
|
+
# @todo Some level (strong, I guess) should require the param here
|
294
|
+
else
|
295
|
+
argtype = argchain.infer(api_map, block_pin, locals)
|
296
|
+
if argtype.defined? && ptype.defined? && !any_types_match?(api_map, ptype, argtype)
|
297
|
+
errors.push Problem.new(location, "Wrong argument type for #{pin.path}: #{par.name} expected #{ptype}, received #{argtype}")
|
298
|
+
next
|
299
|
+
end
|
287
300
|
end
|
288
301
|
end
|
302
|
+
elsif par.decl == :kwarg
|
303
|
+
errors.push Problem.new(location, "Call to #{pin.path} is missing keyword argument #{par.name}")
|
304
|
+
next
|
289
305
|
end
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
result.push Problem.new(location, "Call to #{pin.path} is missing keyword argument #{par.name}")
|
306
|
+
end
|
307
|
+
if errors.empty?
|
308
|
+
all_errors.clear
|
294
309
|
break
|
295
310
|
end
|
311
|
+
all_errors.concat errors
|
296
312
|
end
|
313
|
+
result.concat all_errors
|
297
314
|
end
|
298
315
|
base = base.base
|
299
316
|
end
|
@@ -303,7 +320,7 @@ module Solargraph
|
|
303
320
|
def kwarg_problems_for argchain, api_map, block_pin, locals, location, pin, params, first
|
304
321
|
result = []
|
305
322
|
kwargs = convert_hash(argchain.node)
|
306
|
-
pin.parameters[first..-1].each_with_index do |par, cur|
|
323
|
+
pin.signatures.first.parameters[first..-1].each_with_index do |par, cur|
|
307
324
|
idx = first + cur
|
308
325
|
argchain = kwargs[par.name.to_sym]
|
309
326
|
if par.decl == :kwrestarg || (par.decl == :optarg && idx == pin.parameters.length - 1 && par.asgn_code == '{}')
|
@@ -374,8 +391,10 @@ module Solargraph
|
|
374
391
|
pin.location && api_map.bundled?(pin.location.filename)
|
375
392
|
end
|
376
393
|
|
394
|
+
# True if the pin is either internal (part of the workspace) or from the core/stdlib
|
377
395
|
def internal_or_core? pin
|
378
|
-
|
396
|
+
# @todo RBS pins are not necessarily core/stdlib pins
|
397
|
+
internal?(pin) || pin.source == :rbs
|
379
398
|
end
|
380
399
|
|
381
400
|
# @param pin [Pin::Base]
|
@@ -410,20 +429,20 @@ module Solargraph
|
|
410
429
|
true
|
411
430
|
end
|
412
431
|
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
432
|
+
def arity_problems_for pin, arguments, location
|
433
|
+
results = pin.signatures.map do |sig|
|
434
|
+
r = parameterized_arity_problems_for(pin, sig.parameters, arguments, location)
|
435
|
+
return [] if r.empty?
|
436
|
+
r
|
437
|
+
end
|
438
|
+
results.first
|
420
439
|
end
|
421
440
|
|
422
|
-
|
423
|
-
def pin_arity_problems_for(pin, arguments, location)
|
441
|
+
def parameterized_arity_problems_for(pin, parameters, arguments, location)
|
424
442
|
return [] unless pin.explicit?
|
425
|
-
return [] if
|
426
|
-
if pin.
|
443
|
+
return [] if parameters.empty? && arguments.empty?
|
444
|
+
return [] if pin.anon_splat?
|
445
|
+
if parameters.empty?
|
427
446
|
# Functions tagged param_tuple accepts two arguments (e.g., Hash#[]=)
|
428
447
|
return [] if pin.docstring.tag(:param_tuple) && arguments.length == 2
|
429
448
|
return [] if arguments.length == 1 && arguments.last.links.last.is_a?(Source::Chain::BlockVariable)
|
@@ -431,21 +450,21 @@ module Solargraph
|
|
431
450
|
end
|
432
451
|
unchecked = arguments.clone
|
433
452
|
add_params = 0
|
434
|
-
if unchecked.empty? &&
|
453
|
+
if unchecked.empty? && parameters.any? { |param| param.decl == :kwarg }
|
435
454
|
return [Problem.new(location, "Missing keyword arguments to #{pin.path}")]
|
436
455
|
end
|
437
456
|
settled_kwargs = 0
|
438
457
|
unless unchecked.empty?
|
439
458
|
if any_splatted_call?(unchecked.map(&:node))
|
440
|
-
settled_kwargs =
|
459
|
+
settled_kwargs = parameters.count(&:keyword?)
|
441
460
|
else
|
442
461
|
kwargs = convert_hash(unchecked.last.node)
|
443
|
-
if
|
462
|
+
if parameters.any? { |param| [:kwarg, :kwoptarg].include?(param.decl) || param.kwrestarg? }
|
444
463
|
if kwargs.empty?
|
445
464
|
add_params += 1
|
446
465
|
else
|
447
466
|
unchecked.pop
|
448
|
-
|
467
|
+
parameters.each do |param|
|
449
468
|
next unless param.keyword?
|
450
469
|
if kwargs.key?(param.name.to_sym)
|
451
470
|
kwargs.delete param.name.to_sym
|
@@ -455,7 +474,7 @@ module Solargraph
|
|
455
474
|
return [Problem.new(location, "Missing keyword argument #{param.name} to #{pin.path}")]
|
456
475
|
end
|
457
476
|
end
|
458
|
-
kwargs.clear if
|
477
|
+
kwargs.clear if parameters.any?(&:kwrestarg?)
|
459
478
|
unless kwargs.empty?
|
460
479
|
return [Problem.new(location, "Unrecognized keyword argument #{kwargs.keys.first} to #{pin.path}")]
|
461
480
|
end
|
@@ -463,18 +482,18 @@ module Solargraph
|
|
463
482
|
end
|
464
483
|
end
|
465
484
|
end
|
466
|
-
req = required_param_count(
|
485
|
+
req = required_param_count(parameters)
|
467
486
|
if req + add_params < unchecked.length
|
468
|
-
return [] if
|
469
|
-
opt = optional_param_count(
|
487
|
+
return [] if parameters.any?(&:rest?)
|
488
|
+
opt = optional_param_count(parameters)
|
470
489
|
return [] if unchecked.length <= req + opt
|
471
490
|
if unchecked.length == req + opt + 1 && unchecked.last.links.last.is_a?(Source::Chain::BlockVariable)
|
472
491
|
return []
|
473
492
|
end
|
474
|
-
if req + add_params + 1 == unchecked.length && any_splatted_call?(unchecked.map(&:node)) && (
|
493
|
+
if req + add_params + 1 == unchecked.length && any_splatted_call?(unchecked.map(&:node)) && (parameters.map(&:decl) & [:kwarg, :kwoptarg, :kwrestarg]).any?
|
475
494
|
return []
|
476
495
|
end
|
477
|
-
return [] if arguments.length - req ==
|
496
|
+
return [] if arguments.length - req == parameters.select { |p| [:optarg, :kwoptarg].include?(p.decl) }.length
|
478
497
|
return [Problem.new(location, "Too many arguments to #{pin.path}")]
|
479
498
|
elsif unchecked.length < req - settled_kwargs && (arguments.empty? || (!arguments.last.splat? && !arguments.last.links.last.is_a?(Solargraph::Source::Chain::Hash)))
|
480
499
|
# HACK: Kernel#raise signature is incorrect in Ruby 2.7 core docs.
|
@@ -486,19 +505,13 @@ module Solargraph
|
|
486
505
|
[]
|
487
506
|
end
|
488
507
|
|
489
|
-
|
490
|
-
|
491
|
-
pin.parameters.sum { |param| %i[arg kwarg].include?(param.decl) ? 1 : 0 }
|
508
|
+
def required_param_count(parameters)
|
509
|
+
parameters.sum { |param| %i[arg kwarg].include?(param.decl) ? 1 : 0 }
|
492
510
|
end
|
493
511
|
|
494
512
|
# @param pin [Pin::Method]
|
495
|
-
def optional_param_count(
|
496
|
-
|
497
|
-
pin.parameters.each do |param|
|
498
|
-
next unless param.decl == :optarg
|
499
|
-
count += 1
|
500
|
-
end
|
501
|
-
count
|
513
|
+
def optional_param_count(parameters)
|
514
|
+
parameters.select { |p| p.decl == :optarg }.length
|
502
515
|
end
|
503
516
|
|
504
517
|
def abstract? pin
|
@@ -525,5 +538,12 @@ module Solargraph
|
|
525
538
|
args.push Solargraph::Parser.chain_string('&') if with_block
|
526
539
|
args
|
527
540
|
end
|
541
|
+
|
542
|
+
def without_ignored problems
|
543
|
+
problems.reject do |problem|
|
544
|
+
node = source_map.source.node_at(problem.location.range.start.line, problem.location.range.start.column)
|
545
|
+
source_map.source.comments_for(node)&.include?('@sg-ignore')
|
546
|
+
end
|
547
|
+
end
|
528
548
|
end
|
529
549
|
end
|
data/lib/solargraph/version.rb
CHANGED
@@ -30,10 +30,10 @@
|
|
30
30
|
Solargraph Version: <%= Solargraph::VERSION %>
|
31
31
|
</li>
|
32
32
|
<li>
|
33
|
-
Core Documentation Version:
|
33
|
+
Core Documentation Version: N/A <%# @todo Fix %>
|
34
34
|
</li>
|
35
35
|
<li>
|
36
|
-
Core Cache Directory:
|
36
|
+
Core Cache Directory: N/A <%# @todo Fix %>
|
37
37
|
</li>
|
38
38
|
<% unless Solargraph::Parser.rubyvm? %>
|
39
39
|
<li>
|
data/lib/solargraph/workspace.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'open3'
|
4
4
|
require 'rubygems'
|
5
|
+
require 'json'
|
5
6
|
|
6
7
|
module Solargraph
|
7
8
|
# A workspace consists of the files in a project's directory and the
|
@@ -45,24 +46,21 @@ module Solargraph
|
|
45
46
|
#
|
46
47
|
# @param source [Solargraph::Source]
|
47
48
|
# @return [Boolean] True if the source was added to the workspace
|
48
|
-
def merge
|
49
|
-
unless directory == '*' || source_hash.key?(source.filename)
|
49
|
+
def merge *sources
|
50
|
+
unless directory == '*' || sources.all? { |source| source_hash.key?(source.filename) }
|
50
51
|
# Reload the config to determine if a new source should be included
|
51
52
|
@config = Solargraph::Workspace::Config.new(directory)
|
52
|
-
return false unless config.calculated.include?(source.filename)
|
53
53
|
end
|
54
|
-
source_hash[source.filename] = source
|
55
|
-
true
|
56
|
-
end
|
57
54
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
55
|
+
includes_any = false
|
56
|
+
sources.each do |source|
|
57
|
+
if directory == "*" || config.calculated.include?(source.filename)
|
58
|
+
source_hash[source.filename] = source
|
59
|
+
includes_any = true
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
includes_any
|
66
64
|
end
|
67
65
|
|
68
66
|
# Remove a source from the workspace. The source will not be removed if
|
@@ -13,16 +13,19 @@ module Solargraph
|
|
13
13
|
)
|
14
14
|
location = object_location(code_object, spec)
|
15
15
|
comments = code_object.docstring ? code_object.docstring.all.to_s : ''
|
16
|
-
Pin::Method.new(
|
16
|
+
pin = Pin::Method.new(
|
17
17
|
location: location,
|
18
18
|
closure: closure,
|
19
19
|
name: name || code_object.name.to_s,
|
20
20
|
comments: comments,
|
21
21
|
scope: scope || code_object.scope,
|
22
22
|
visibility: visibility || code_object.visibility,
|
23
|
-
|
23
|
+
# @todo Might need to convert overloads to signatures
|
24
|
+
parameters: [],
|
24
25
|
explicit: code_object.is_explicit?
|
25
26
|
)
|
27
|
+
pin.parameters.concat get_parameters(code_object, location, comments, pin)
|
28
|
+
pin
|
26
29
|
end
|
27
30
|
|
28
31
|
class << self
|
@@ -30,7 +33,7 @@ module Solargraph
|
|
30
33
|
|
31
34
|
# @param code_object [YARD::CodeObjects::Base]
|
32
35
|
# @return [Array<Solargraph::Pin::Parameter>]
|
33
|
-
def get_parameters code_object, location, comments
|
36
|
+
def get_parameters code_object, location, comments, pin
|
34
37
|
return [] unless code_object.is_a?(YARD::CodeObjects::MethodObject)
|
35
38
|
# HACK: Skip `nil` and `self` parameters that are sometimes emitted
|
36
39
|
# for methods defined in C
|
@@ -38,7 +41,7 @@ module Solargraph
|
|
38
41
|
code_object.parameters.select { |a| a[0] && a[0] != 'self' }.map do |a|
|
39
42
|
Solargraph::Pin::Parameter.new(
|
40
43
|
location: location,
|
41
|
-
closure:
|
44
|
+
closure: pin,
|
42
45
|
comments: comments,
|
43
46
|
name: arg_name(a),
|
44
47
|
presence: nil,
|