solargraph 0.54.4 → 0.57.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/workflows/linting.yml +125 -0
- data/.github/workflows/plugins.yml +149 -5
- data/.github/workflows/rspec.yml +39 -4
- data/.github/workflows/typecheck.yml +8 -3
- data/.gitignore +7 -0
- data/.overcommit.yml +72 -0
- data/.rspec +1 -0
- data/.rubocop.yml +66 -0
- data/.rubocop_todo.yml +2627 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +104 -0
- data/README.md +20 -6
- data/Rakefile +125 -13
- data/lib/solargraph/api_map/cache.rb +3 -2
- data/lib/solargraph/api_map/constants.rb +218 -0
- data/lib/solargraph/api_map/index.rb +44 -42
- data/lib/solargraph/api_map/source_to_yard.rb +10 -4
- data/lib/solargraph/api_map/store.rb +165 -32
- data/lib/solargraph/api_map.rb +319 -243
- data/lib/solargraph/bench.rb +18 -1
- data/lib/solargraph/complex_type/type_methods.rb +7 -1
- data/lib/solargraph/complex_type/unique_type.rb +105 -16
- data/lib/solargraph/complex_type.rb +40 -7
- data/lib/solargraph/convention/active_support_concern.rb +111 -0
- data/lib/solargraph/convention/base.rb +20 -3
- data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -0
- data/lib/solargraph/convention/data_definition/data_definition_node.rb +91 -0
- data/lib/solargraph/convention/data_definition.rb +105 -0
- data/lib/solargraph/convention/gemspec.rb +3 -2
- data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +61 -0
- data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +102 -0
- data/lib/solargraph/convention/struct_definition.rb +164 -0
- data/lib/solargraph/convention.rb +35 -4
- data/lib/solargraph/diagnostics/rubocop.rb +6 -1
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +1 -1
- data/lib/solargraph/doc_map.rb +313 -65
- data/lib/solargraph/environ.rb +9 -2
- data/lib/solargraph/gem_pins.rb +60 -38
- data/lib/solargraph/language_server/host/dispatch.rb +2 -0
- data/lib/solargraph/language_server/host/message_worker.rb +13 -7
- data/lib/solargraph/language_server/host.rb +14 -3
- data/lib/solargraph/language_server/message/base.rb +2 -1
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +2 -0
- data/lib/solargraph/language_server/message/extended/document.rb +5 -2
- data/lib/solargraph/language_server/message/extended/document_gems.rb +3 -3
- data/lib/solargraph/language_server/message/text_document/definition.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/formatting.rb +16 -2
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +1 -0
- data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +2 -0
- data/lib/solargraph/language_server/progress.rb +8 -0
- data/lib/solargraph/language_server/request.rb +1 -0
- data/lib/solargraph/library.rb +53 -32
- data/lib/solargraph/location.rb +23 -0
- data/lib/solargraph/logging.rb +12 -2
- data/lib/solargraph/page.rb +4 -0
- data/lib/solargraph/parser/comment_ripper.rb +20 -7
- data/lib/solargraph/parser/flow_sensitive_typing.rb +255 -0
- data/lib/solargraph/parser/node_methods.rb +16 -2
- data/lib/solargraph/parser/node_processor/base.rb +10 -5
- data/lib/solargraph/parser/node_processor.rb +26 -9
- data/lib/solargraph/parser/parser_gem/class_methods.rb +17 -15
- data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +13 -11
- data/lib/solargraph/parser/parser_gem/node_methods.rb +8 -4
- data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +21 -0
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +4 -2
- data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +7 -4
- data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +6 -3
- data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +23 -0
- data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +4 -2
- data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +7 -1
- data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +8 -7
- data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +42 -0
- data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +3 -1
- data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +4 -3
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +63 -30
- data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +3 -1
- data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -0
- data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +29 -0
- data/lib/solargraph/parser/parser_gem/node_processors.rb +14 -0
- data/lib/solargraph/parser/region.rb +4 -1
- data/lib/solargraph/parser/snippet.rb +2 -0
- data/lib/solargraph/parser.rb +1 -0
- data/lib/solargraph/pin/base.rb +360 -30
- data/lib/solargraph/pin/base_variable.rb +16 -10
- data/lib/solargraph/pin/block.rb +2 -0
- data/lib/solargraph/pin/breakable.rb +9 -0
- data/lib/solargraph/pin/callable.rb +83 -3
- data/lib/solargraph/pin/closure.rb +20 -1
- data/lib/solargraph/pin/common.rb +10 -1
- data/lib/solargraph/pin/constant.rb +2 -0
- data/lib/solargraph/pin/delegated_method.rb +21 -1
- data/lib/solargraph/pin/documenting.rb +16 -0
- data/lib/solargraph/pin/keyword.rb +7 -2
- data/lib/solargraph/pin/local_variable.rb +18 -6
- data/lib/solargraph/pin/method.rb +175 -46
- data/lib/solargraph/pin/method_alias.rb +3 -0
- data/lib/solargraph/pin/namespace.rb +17 -9
- data/lib/solargraph/pin/parameter.rb +78 -19
- data/lib/solargraph/pin/proxy_type.rb +13 -6
- data/lib/solargraph/pin/reference/override.rb +24 -6
- data/lib/solargraph/pin/reference/require.rb +2 -2
- data/lib/solargraph/pin/reference/superclass.rb +5 -0
- data/lib/solargraph/pin/reference.rb +26 -0
- data/lib/solargraph/pin/search.rb +3 -1
- data/lib/solargraph/pin/signature.rb +44 -0
- data/lib/solargraph/pin/singleton.rb +1 -1
- data/lib/solargraph/pin/symbol.rb +8 -2
- data/lib/solargraph/pin/until.rb +18 -0
- data/lib/solargraph/pin/while.rb +18 -0
- data/lib/solargraph/pin.rb +4 -1
- data/lib/solargraph/pin_cache.rb +245 -0
- data/lib/solargraph/position.rb +11 -0
- data/lib/solargraph/range.rb +10 -0
- data/lib/solargraph/rbs_map/conversions.rb +226 -70
- data/lib/solargraph/rbs_map/core_fills.rb +32 -16
- data/lib/solargraph/rbs_map/core_map.rb +37 -11
- data/lib/solargraph/rbs_map/stdlib_map.rb +15 -5
- data/lib/solargraph/rbs_map.rb +88 -18
- data/lib/solargraph/shell.rb +20 -18
- data/lib/solargraph/source/chain/array.rb +11 -7
- data/lib/solargraph/source/chain/block_symbol.rb +1 -1
- data/lib/solargraph/source/chain/block_variable.rb +1 -1
- data/lib/solargraph/source/chain/call.rb +53 -23
- data/lib/solargraph/source/chain/constant.rb +1 -1
- data/lib/solargraph/source/chain/hash.rb +4 -3
- data/lib/solargraph/source/chain/head.rb +1 -1
- data/lib/solargraph/source/chain/if.rb +1 -1
- data/lib/solargraph/source/chain/link.rb +12 -1
- data/lib/solargraph/source/chain/literal.rb +22 -2
- data/lib/solargraph/source/chain/or.rb +1 -1
- data/lib/solargraph/source/chain/z_super.rb +1 -1
- data/lib/solargraph/source/chain.rb +84 -47
- data/lib/solargraph/source/change.rb +2 -2
- data/lib/solargraph/source/cursor.rb +2 -3
- data/lib/solargraph/source/source_chainer.rb +3 -3
- data/lib/solargraph/source.rb +5 -2
- data/lib/solargraph/source_map/clip.rb +4 -2
- data/lib/solargraph/source_map/data.rb +4 -0
- data/lib/solargraph/source_map/mapper.rb +13 -7
- data/lib/solargraph/source_map.rb +21 -31
- data/lib/solargraph/type_checker/checks.rb +4 -0
- data/lib/solargraph/type_checker/param_def.rb +2 -0
- data/lib/solargraph/type_checker/rules.rb +8 -0
- data/lib/solargraph/type_checker.rb +208 -128
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/views/_method.erb +10 -10
- data/lib/solargraph/views/_namespace.erb +3 -3
- data/lib/solargraph/views/document.erb +10 -10
- data/lib/solargraph/workspace/config.rb +1 -3
- data/lib/solargraph/workspace/require_paths.rb +98 -0
- data/lib/solargraph/workspace.rb +38 -52
- data/lib/solargraph/yard_map/helpers.rb +29 -1
- data/lib/solargraph/yard_map/mapper/to_constant.rb +7 -5
- data/lib/solargraph/yard_map/mapper/to_method.rb +53 -18
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +9 -7
- data/lib/solargraph/yard_map/mapper.rb +4 -3
- data/lib/solargraph/yard_map/to_method.rb +4 -2
- data/lib/solargraph/yardoc.rb +22 -10
- data/lib/solargraph.rb +34 -1
- data/rbs/fills/tuple.rbs +149 -0
- data/rbs_collection.yaml +19 -0
- data/sig/shims/parser/3.2.0.1/builders/default.rbs +195 -0
- data/sig/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
- data/sig/shims/thor/1.2.0.1/manifest.yaml +7 -0
- data/sig/shims/thor/1.2.0.1/thor.rbs +17 -0
- data/solargraph.gemspec +15 -4
- metadata +157 -15
- data/lib/.rubocop.yml +0 -22
- data/lib/solargraph/cache.rb +0 -77
@@ -57,6 +57,14 @@ module Solargraph
|
|
57
57
|
def require_all_return_types_match_inferred?
|
58
58
|
rank >= LEVELS[:alpha]
|
59
59
|
end
|
60
|
+
|
61
|
+
# We keep this at strong because if you added an @ sg-ignore to
|
62
|
+
# address a strong-level issue, then ran at a lower level, you'd
|
63
|
+
# get a false positive - we don't run stronger level checks than
|
64
|
+
# requested for performance reasons
|
65
|
+
def validate_sg_ignores?
|
66
|
+
rank >= LEVELS[:strong]
|
67
|
+
end
|
60
68
|
end
|
61
69
|
end
|
62
70
|
end
|
@@ -38,15 +38,20 @@ module Solargraph
|
|
38
38
|
@source_map ||= api_map.source_map(filename)
|
39
39
|
end
|
40
40
|
|
41
|
+
# @return [Source]
|
42
|
+
def source
|
43
|
+
@source_map.source
|
44
|
+
end
|
45
|
+
|
41
46
|
# @return [Array<Problem>]
|
42
47
|
def problems
|
43
48
|
@problems ||= begin
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
49
|
+
all = method_tag_problems
|
50
|
+
.concat(variable_type_tag_problems)
|
51
|
+
.concat(const_problems)
|
52
|
+
.concat(call_problems)
|
53
|
+
unignored = without_ignored(all)
|
54
|
+
unignored.concat(unneeded_sgignore_problems)
|
50
55
|
end
|
51
56
|
end
|
52
57
|
|
@@ -140,7 +145,7 @@ module Solargraph
|
|
140
145
|
|
141
146
|
# @param pin [Pin::Base]
|
142
147
|
def virtual_pin? pin
|
143
|
-
pin.location &&
|
148
|
+
pin.location && source.comment_at?(pin.location.range.ending)
|
144
149
|
end
|
145
150
|
|
146
151
|
# @param pin [Pin::Method]
|
@@ -231,7 +236,7 @@ module Solargraph
|
|
231
236
|
def const_problems
|
232
237
|
return [] unless rules.validate_consts?
|
233
238
|
result = []
|
234
|
-
Solargraph::Parser::NodeMethods.const_nodes_from(
|
239
|
+
Solargraph::Parser::NodeMethods.const_nodes_from(source.node).each do |const|
|
235
240
|
rng = Solargraph::Range.from_node(const)
|
236
241
|
chain = Solargraph::Parser.chain(const, filename)
|
237
242
|
block_pin = source_map.locate_block_pin(rng.start.line, rng.start.column)
|
@@ -249,7 +254,7 @@ module Solargraph
|
|
249
254
|
# @return [Array<Problem>]
|
250
255
|
def call_problems
|
251
256
|
result = []
|
252
|
-
Solargraph::Parser::NodeMethods.call_nodes_from(
|
257
|
+
Solargraph::Parser::NodeMethods.call_nodes_from(source.node).each do |call|
|
253
258
|
rng = Solargraph::Range.from_node(call)
|
254
259
|
next if @marked_ranges.any? { |d| d.contain?(rng.start) }
|
255
260
|
chain = Solargraph::Parser.chain(call, filename)
|
@@ -272,7 +277,11 @@ module Solargraph
|
|
272
277
|
# @todo remove the internal_or_core? check at a higher-than-strict level
|
273
278
|
if !found || found.is_a?(Pin::BaseVariable) || (closest.defined? && internal_or_core?(found))
|
274
279
|
unless closest.generic? || ignored_pins.include?(found)
|
275
|
-
|
280
|
+
if closest.defined?
|
281
|
+
result.push Problem.new(location, "Unresolved call to #{missing.links.last.word} on #{closest}")
|
282
|
+
else
|
283
|
+
result.push Problem.new(location, "Unresolved call to #{missing.links.last.word}")
|
284
|
+
end
|
276
285
|
@marked_ranges.push rng
|
277
286
|
end
|
278
287
|
end
|
@@ -284,127 +293,136 @@ module Solargraph
|
|
284
293
|
|
285
294
|
# @param chain [Solargraph::Source::Chain]
|
286
295
|
# @param api_map [Solargraph::ApiMap]
|
287
|
-
# @param
|
296
|
+
# @param closure_pin [Solargraph::Pin::Closure]
|
288
297
|
# @param locals [Array<Solargraph::Pin::Base>]
|
289
298
|
# @param location [Solargraph::Location]
|
290
299
|
# @return [Array<Problem>]
|
291
|
-
def argument_problems_for chain, api_map,
|
300
|
+
def argument_problems_for chain, api_map, closure_pin, locals, location
|
292
301
|
result = []
|
293
302
|
base = chain
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
303
|
+
# @type last_base_link [Solargraph::Source::Chain::Call]
|
304
|
+
last_base_link = base.links.last
|
305
|
+
return [] unless last_base_link.is_a?(Solargraph::Source::Chain::Call)
|
306
|
+
|
307
|
+
arguments = last_base_link.arguments
|
308
|
+
|
309
|
+
pins = base.define(api_map, closure_pin, locals)
|
310
|
+
|
311
|
+
first_pin = pins.first
|
312
|
+
unresolvable = first_pin.is_a?(Pin::DelegatedMethod) && !first_pin.resolvable?(api_map)
|
313
|
+
if !unresolvable && first_pin.is_a?(Pin::Method)
|
314
|
+
# @type [Pin::Method]
|
315
|
+
pin = first_pin
|
316
|
+
ap = if base.links.last.is_a?(Solargraph::Source::Chain::ZSuper)
|
317
|
+
arity_problems_for(pin, fake_args_for(closure_pin), location)
|
318
|
+
elsif pin.path == 'Class#new'
|
319
|
+
fqns = if base.links.one?
|
320
|
+
closure_pin.namespace
|
321
|
+
else
|
322
|
+
base.base.infer(api_map, closure_pin, locals).namespace
|
323
|
+
end
|
324
|
+
init = api_map.get_method_stack(fqns, 'initialize').first
|
325
|
+
|
326
|
+
init ? arity_problems_for(init, arguments, location) : []
|
327
|
+
else
|
328
|
+
arity_problems_for(pin, arguments, location)
|
329
|
+
end
|
330
|
+
return ap unless ap.empty?
|
331
|
+
return [] if !rules.validate_calls? || base.links.first.is_a?(Solargraph::Source::Chain::ZSuper)
|
332
|
+
|
333
|
+
params = first_param_hash(pins)
|
334
|
+
|
335
|
+
all_errors = []
|
336
|
+
pin.signatures.sort { |sig| sig.parameters.length }.each do |sig|
|
337
|
+
signature_errors = signature_argument_problems_for location, locals, closure_pin, params, arguments, sig, pin
|
338
|
+
if signature_errors.empty?
|
339
|
+
# we found a signature that works - meaning errors from
|
340
|
+
# other signatures don't matter.
|
341
|
+
return []
|
342
|
+
end
|
343
|
+
all_errors.concat signature_errors
|
344
|
+
end
|
345
|
+
result.concat all_errors
|
346
|
+
end
|
347
|
+
result
|
348
|
+
end
|
349
|
+
|
350
|
+
# @param location [Location]
|
351
|
+
# @param locals [Array<Pin::LocalVariable>]
|
352
|
+
# @param closure_pin [Pin::Closure]
|
353
|
+
# @param params [Hash{String => Hash{Symbol => String, Solargraph::ComplexType}}]
|
354
|
+
# @param arguments [Array<Source::Chain>]
|
355
|
+
# @param sig [Pin::Signature]
|
356
|
+
# @param pin [Pin::Method]
|
357
|
+
# @param pins [Array<Pin::Method>]
|
358
|
+
#
|
359
|
+
# @return [Array<Problem>]
|
360
|
+
def signature_argument_problems_for location, locals, closure_pin, params, arguments, sig, pin
|
361
|
+
errors = []
|
362
|
+
# @todo add logic mapping up restarg parameters with
|
363
|
+
# arguments (including restarg arguments). Use tuples
|
364
|
+
# when possible, and when not, ensure provably
|
365
|
+
# incorrect situations are detected.
|
366
|
+
sig.parameters.each_with_index do |par, idx|
|
367
|
+
return errors if par.decl == :restarg # bail out and assume the rest is valid pending better arg processing
|
368
|
+
argchain = arguments[idx]
|
369
|
+
if argchain.nil?
|
370
|
+
if par.decl == :arg
|
371
|
+
final_arg = arguments.last
|
372
|
+
if final_arg && final_arg.node.type == :splat
|
373
|
+
argchain = final_arg
|
374
|
+
return errors
|
313
375
|
else
|
314
|
-
|
376
|
+
errors.push Problem.new(location, "Not enough arguments to #{pin.path}")
|
315
377
|
end
|
316
|
-
init = api_map.get_method_stack(fqns, 'initialize').first
|
317
|
-
init ? arity_problems_for(init, arguments, location) : []
|
318
378
|
else
|
319
|
-
|
320
|
-
|
321
|
-
unless ap.empty?
|
322
|
-
result.concat ap
|
323
|
-
break
|
379
|
+
final_arg = arguments.last
|
380
|
+
argchain = final_arg if final_arg && [:kwsplat, :hash].include?(final_arg.node.type)
|
324
381
|
end
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
#
|
336
|
-
#
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
final_arg = arguments.last
|
351
|
-
argchain = final_arg if final_arg && [:kwsplat, :hash].include?(final_arg.node.type)
|
352
|
-
end
|
353
|
-
end
|
354
|
-
if argchain
|
355
|
-
if par.decl != :arg
|
356
|
-
errors.concat kwarg_problems_for sig, argchain, api_map, block_pin, locals, location, pin, params, idx
|
357
|
-
next
|
358
|
-
else
|
359
|
-
if argchain.node.type == :splat && argchain == arguments.last
|
360
|
-
final_arg = argchain
|
361
|
-
end
|
362
|
-
if (final_arg && final_arg.node.type == :splat)
|
363
|
-
# The final argument given has been seen and was a
|
364
|
-
# splat, which doesn't give us useful types or
|
365
|
-
# arities against positional parameters, so let's
|
366
|
-
# continue on in case there are any required
|
367
|
-
# kwargs we should warn about
|
368
|
-
next
|
369
|
-
end
|
370
|
-
|
371
|
-
if argchain.node.type == :splat && par != sig.parameters.last
|
372
|
-
# we have been given a splat and there are more
|
373
|
-
# arguments to come.
|
374
|
-
|
375
|
-
# @todo Improve this so that we can skip past the
|
376
|
-
# rest of the positional parameters here but still
|
377
|
-
# process the kwargs
|
378
|
-
break
|
379
|
-
end
|
380
|
-
ptype = params.key?(par.name) ? params[par.name][:qualified] : ComplexType::UNDEFINED
|
381
|
-
ptype = ptype.self_to_type(par.context)
|
382
|
-
if ptype.nil?
|
383
|
-
# @todo Some level (strong, I guess) should require the param here
|
384
|
-
else
|
385
|
-
argtype = argchain.infer(api_map, block_pin, locals)
|
386
|
-
if argtype.defined? && ptype.defined? && !any_types_match?(api_map, ptype, argtype)
|
387
|
-
errors.push Problem.new(location, "Wrong argument type for #{pin.path}: #{par.name} expected #{ptype}, received #{argtype}")
|
388
|
-
next
|
389
|
-
end
|
390
|
-
end
|
391
|
-
end
|
392
|
-
elsif par.decl == :kwarg
|
393
|
-
errors.push Problem.new(location, "Call to #{pin.path} is missing keyword argument #{par.name}")
|
394
|
-
next
|
395
|
-
end
|
382
|
+
end
|
383
|
+
if argchain
|
384
|
+
if par.decl != :arg
|
385
|
+
errors.concat kwarg_problems_for sig, argchain, api_map, closure_pin, locals, location, pin, params, idx
|
386
|
+
next
|
387
|
+
else
|
388
|
+
if argchain.node.type == :splat && argchain == arguments.last
|
389
|
+
final_arg = argchain
|
390
|
+
end
|
391
|
+
if (final_arg && final_arg.node.type == :splat)
|
392
|
+
# The final argument given has been seen and was a
|
393
|
+
# splat, which doesn't give us useful types or
|
394
|
+
# arities against positional parameters, so let's
|
395
|
+
# continue on in case there are any required
|
396
|
+
# kwargs we should warn about
|
397
|
+
next
|
398
|
+
end
|
399
|
+
if argchain.node.type == :splat && par != sig.parameters.last
|
400
|
+
# we have been given a splat and there are more
|
401
|
+
# arguments to come.
|
402
|
+
|
403
|
+
# @todo Improve this so that we can skip past the
|
404
|
+
# rest of the positional parameters here but still
|
405
|
+
# process the kwargs
|
406
|
+
return errors
|
396
407
|
end
|
397
|
-
|
398
|
-
|
399
|
-
|
408
|
+
ptype = params.key?(par.name) ? params[par.name][:qualified] : ComplexType::UNDEFINED
|
409
|
+
ptype = ptype.self_to_type(par.context)
|
410
|
+
if ptype.nil?
|
411
|
+
# @todo Some level (strong, I guess) should require the param here
|
412
|
+
else
|
413
|
+
argtype = argchain.infer(api_map, closure_pin, locals)
|
414
|
+
if argtype.defined? && ptype.defined? && !any_types_match?(api_map, ptype, argtype)
|
415
|
+
errors.push Problem.new(location, "Wrong argument type for #{pin.path}: #{par.name} expected #{ptype}, received #{argtype}")
|
416
|
+
return errors
|
417
|
+
end
|
400
418
|
end
|
401
|
-
all_errors.concat errors
|
402
419
|
end
|
403
|
-
|
420
|
+
elsif par.decl == :kwarg
|
421
|
+
errors.push Problem.new(location, "Call to #{pin.path} is missing keyword argument #{par.name}")
|
422
|
+
next
|
404
423
|
end
|
405
|
-
base = base.base
|
406
424
|
end
|
407
|
-
|
425
|
+
errors
|
408
426
|
end
|
409
427
|
|
410
428
|
# @param sig [Pin::Signature]
|
@@ -470,12 +488,22 @@ module Solargraph
|
|
470
488
|
# @param pin [Pin::Method]
|
471
489
|
# @return [Hash{String => Hash{Symbol => String, ComplexType}}]
|
472
490
|
def param_hash(pin)
|
473
|
-
tags = pin.docstring.tags(:param)
|
474
|
-
return {} if tags.empty?
|
475
491
|
# @type [Hash{String => Hash{Symbol => String, ComplexType}}]
|
476
492
|
result = {}
|
493
|
+
pin.parameters.each do |param|
|
494
|
+
type = param.typify(api_map)
|
495
|
+
next if type.nil? || type.undefined?
|
496
|
+
result[param.name.to_s] = {
|
497
|
+
tagged: type.tags,
|
498
|
+
qualified: type
|
499
|
+
}
|
500
|
+
end
|
501
|
+
# see if we have additional tags to pay attention to from YARD -
|
502
|
+
# e.g., kwargs in a **restkwargs splat
|
503
|
+
tags = pin.docstring.tags(:param)
|
477
504
|
tags.each do |tag|
|
478
|
-
next if
|
505
|
+
next if result.key? tag.name.to_s
|
506
|
+
next if tag.types.nil?
|
479
507
|
result[tag.name.to_s] = {
|
480
508
|
tagged: tag.types.join(', '),
|
481
509
|
qualified: Solargraph::ComplexType.try_parse(*tag.types).qualify(api_map, pin.full_context.namespace)
|
@@ -487,11 +515,27 @@ module Solargraph
|
|
487
515
|
# @param pins [Array<Pin::Method>]
|
488
516
|
# @return [Hash{String => Hash{Symbol => String, ComplexType}}]
|
489
517
|
def first_param_hash(pins)
|
490
|
-
pins.
|
491
|
-
|
492
|
-
|
518
|
+
return {} if pins.empty?
|
519
|
+
first_pin_type = pins.first.typify(api_map)
|
520
|
+
first_pin = pins.first.proxy first_pin_type
|
521
|
+
param_names = first_pin.parameter_names
|
522
|
+
results = param_hash(first_pin)
|
523
|
+
pins[1..].each do |pin|
|
524
|
+
# @todo this assignment from parametric use of Hash should not lose its generic
|
525
|
+
# @type [Hash{String => Hash{Symbol => BasicObject}}]
|
526
|
+
|
527
|
+
# documentation of types in superclasses should fail back to
|
528
|
+
# subclasses if the subclass hasn't documented something
|
529
|
+
superclass_results = param_hash(pin)
|
530
|
+
superclass_results.each do |param_name, details|
|
531
|
+
next unless param_names.include?(param_name)
|
532
|
+
|
533
|
+
results[param_name] ||= {}
|
534
|
+
results[param_name][:tagged] ||= details[:tagged]
|
535
|
+
results[param_name][:qualified] ||= details[:qualified]
|
536
|
+
end
|
493
537
|
end
|
494
|
-
|
538
|
+
results
|
495
539
|
end
|
496
540
|
|
497
541
|
# @param pin [Pin::Base]
|
@@ -584,7 +628,8 @@ module Solargraph
|
|
584
628
|
kwargs.delete param.name.to_sym
|
585
629
|
settled_kwargs += 1
|
586
630
|
elsif param.decl == :kwarg
|
587
|
-
|
631
|
+
last_arg_last_link = arguments.last.links.last
|
632
|
+
return [] if last_arg_last_link.is_a?(Solargraph::Source::Chain::Hash) && last_arg_last_link.splatted?
|
588
633
|
return [Problem.new(location, "Missing keyword argument #{param.name} to #{pin.path}")]
|
589
634
|
end
|
590
635
|
end
|
@@ -619,7 +664,6 @@ module Solargraph
|
|
619
664
|
# @param parameters [Enumerable<Pin::Parameter>]
|
620
665
|
# @todo need to use generic types in method to choose correct
|
621
666
|
# signature and generate Integer as return type
|
622
|
-
# @sg-ignore
|
623
667
|
# @return [Integer]
|
624
668
|
def required_param_count(parameters)
|
625
669
|
parameters.sum { |param| %i[arg kwarg].include?(param.decl) ? 1 : 0 }
|
@@ -660,12 +704,48 @@ module Solargraph
|
|
660
704
|
args
|
661
705
|
end
|
662
706
|
|
707
|
+
# @return [Set<Integer>]
|
708
|
+
def sg_ignore_lines_processed
|
709
|
+
@sg_ignore_lines_processed ||= Set.new
|
710
|
+
end
|
711
|
+
|
712
|
+
# @return [Set<Integer>]
|
713
|
+
def all_sg_ignore_lines
|
714
|
+
source.associated_comments.select do |_line, text|
|
715
|
+
text.include?('@sg-ignore')
|
716
|
+
end.keys.to_set
|
717
|
+
end
|
718
|
+
|
719
|
+
# @return [Array<Integer>]
|
720
|
+
def unprocessed_sg_ignore_lines
|
721
|
+
(all_sg_ignore_lines - sg_ignore_lines_processed).to_a.sort
|
722
|
+
end
|
723
|
+
|
724
|
+
# @return [Array<Problem>]
|
725
|
+
def unneeded_sgignore_problems
|
726
|
+
return [] unless rules.validate_sg_ignores?
|
727
|
+
|
728
|
+
unprocessed_sg_ignore_lines.map do |line|
|
729
|
+
Problem.new(
|
730
|
+
Location.new(filename, Range.from_to(line, 0, line, 0)),
|
731
|
+
'Unneeded @sg-ignore comment'
|
732
|
+
)
|
733
|
+
end
|
734
|
+
end
|
735
|
+
|
663
736
|
# @param problems [Array<Problem>]
|
664
737
|
# @return [Array<Problem>]
|
665
738
|
def without_ignored problems
|
666
739
|
problems.reject do |problem|
|
667
|
-
node =
|
668
|
-
node &&
|
740
|
+
node = source.node_at(problem.location.range.start.line, problem.location.range.start.column)
|
741
|
+
ignored = node && source.comments_for(node)&.include?('@sg-ignore')
|
742
|
+
unless !ignored || all_sg_ignore_lines.include?(problem.location.range.start.line)
|
743
|
+
# :nocov:
|
744
|
+
Solargraph.assert_or_log(:sg_ignore) { "@sg-ignore accounting issue - node is #{node}" }
|
745
|
+
# :nocov:
|
746
|
+
end
|
747
|
+
sg_ignore_lines_processed.add problem.location.range.start.line if ignored
|
748
|
+
ignored
|
669
749
|
end
|
670
750
|
end
|
671
751
|
end
|
data/lib/solargraph/version.rb
CHANGED
@@ -2,33 +2,33 @@
|
|
2
2
|
Namespace:
|
3
3
|
</h2>
|
4
4
|
<p>
|
5
|
-
<a href="solargraph:/document?query=<%= CGI.escape
|
5
|
+
<a href="solargraph:/document?query=<%= CGI.escape pin.namespace.path %>"><%= pin.namespace %></a>
|
6
6
|
</p>
|
7
7
|
<h2>
|
8
8
|
Overview:
|
9
9
|
</h2>
|
10
|
-
<%= htmlify
|
10
|
+
<%= htmlify pin.docstring %>
|
11
11
|
<p class="document-section">
|
12
|
-
<big><strong>Visibility:</strong></big> <%=
|
12
|
+
<big><strong>Visibility:</strong></big> <%= pin.visibility %>
|
13
13
|
</p>
|
14
|
-
<% unless
|
14
|
+
<% unless pin.docstring.tags(:param).empty? %>
|
15
15
|
<h2>
|
16
16
|
Parameters:
|
17
17
|
</h2>
|
18
18
|
<ul>
|
19
|
-
<%
|
19
|
+
<% pin.docstring.tags(:param).each do |tag| %>
|
20
20
|
<li>
|
21
21
|
<%= erb :_name_type_tag, layout: false, locals: {tag: tag} %>
|
22
22
|
</li>
|
23
23
|
<% end %>
|
24
24
|
</ul>
|
25
25
|
<% end %>
|
26
|
-
<% unless
|
26
|
+
<% unless pin.docstring.tags(:raise).empty? %>
|
27
27
|
<h2>
|
28
28
|
Raises:
|
29
29
|
</h2>
|
30
30
|
<ul>
|
31
|
-
<%
|
31
|
+
<% pin.docstring.tags(:raise).each do |tag| %>
|
32
32
|
<li>
|
33
33
|
<%= erb :_name_type_tag, layout: false, locals: {tag: tag} %>
|
34
34
|
</li>
|
@@ -38,20 +38,20 @@
|
|
38
38
|
<h2>
|
39
39
|
Returns:
|
40
40
|
</h2>
|
41
|
-
<% if
|
41
|
+
<% if pin.docstring.tag(:return).nil? %>
|
42
42
|
<p>
|
43
43
|
Undefined/unknown
|
44
44
|
</p>
|
45
45
|
<% else %>
|
46
46
|
<ul>
|
47
|
-
<%
|
47
|
+
<% pin.tags(:return).each do |tag| %>
|
48
48
|
<li>
|
49
49
|
<%= erb :_name_type_tag, layout: false, locals: {tag: tag} %>
|
50
50
|
</li>
|
51
51
|
<% end %>
|
52
52
|
</ul>
|
53
53
|
<% end %>
|
54
|
-
<% examples =
|
54
|
+
<% examples = pin.docstring.tags(:example) %>
|
55
55
|
<% unless examples.nil? %>
|
56
56
|
<% examples.each do |example| %>
|
57
57
|
<h2>
|
@@ -1,12 +1,12 @@
|
|
1
1
|
<h2>
|
2
2
|
Overview:
|
3
3
|
</h2>
|
4
|
-
<%= htmlify
|
4
|
+
<%= htmlify pin.docstring %>
|
5
5
|
<h2>
|
6
6
|
Class Methods
|
7
7
|
</h2>
|
8
8
|
<ul class="doc-list">
|
9
|
-
<%
|
9
|
+
<% api_map.get_methods(pin.path, scope: :class, deep: false).sort{|a, b| a.name <=> b.name}.each do |meth| %>
|
10
10
|
<li>
|
11
11
|
<a href="solargraph:/document?query=<%= CGI.escape(meth.path) %>"><%= meth.name %></a>
|
12
12
|
</li>
|
@@ -16,7 +16,7 @@
|
|
16
16
|
Instance Methods
|
17
17
|
</h2>
|
18
18
|
<ul class="doc-list">
|
19
|
-
<%
|
19
|
+
<% api_map.get_methods(pin.path, scope: :instance, deep: false).sort{|a, b| a.name <=> b.name}.each do |meth| %>
|
20
20
|
<li>
|
21
21
|
<a href="solargraph:/document?query=<%= CGI.escape(meth.path) %>"><%= meth.name %></a>
|
22
22
|
</li>
|
@@ -1,23 +1,23 @@
|
|
1
|
-
<%
|
1
|
+
<% pins.each do |pin| %>
|
2
2
|
<h1>
|
3
|
-
<%=
|
4
|
-
<% if
|
5
|
-
<small>(<%=
|
3
|
+
<%= pin.name %>
|
4
|
+
<% if pin.is_a?(Solargraph::Pin::Method) && !pin.parameters.empty? %>
|
5
|
+
<small>(<%= pin.parameters.map {|p| "#{p[0]}#{p[1] and p[0].end_with?(':') ? ' ' : (p[1] ? ' = ' : '')}#{p[1]}"}.join(', ') %>)</small>
|
6
6
|
<% end %>
|
7
7
|
</h1>
|
8
|
-
<% unless
|
8
|
+
<% unless pins.map(&:location).compact.empty? %>
|
9
9
|
<h2>
|
10
10
|
Defined in:
|
11
11
|
</h2>
|
12
12
|
<ul>
|
13
|
-
<%
|
13
|
+
<% pins.map(&:location).compact.map(&:filename).each do |f| %>
|
14
14
|
<li><%= f %></li>
|
15
15
|
<% end %>
|
16
16
|
</ul>
|
17
17
|
<% end %>
|
18
|
-
<% if
|
19
|
-
<%= erb :_namespace, layout: false, locals: {
|
20
|
-
<% elsif
|
21
|
-
<%= erb :_method, layout: false, locals: {
|
18
|
+
<% if pin.is_a?(Solargraph::Pin::Namespace) %>
|
19
|
+
<%= erb :_namespace, layout: false, locals: {api_map: api_map, pin: pin} %>
|
20
|
+
<% elsif pin.is_a?(Solargraph::Pin::Method) %>
|
21
|
+
<%= erb :_method, layout: false, locals: {api_map: api_map, pin: pin} %>
|
22
22
|
<% end %>
|
23
23
|
<% end %>
|
@@ -90,7 +90,6 @@ module Solargraph
|
|
90
90
|
|
91
91
|
# A hash of options supported by the formatter
|
92
92
|
#
|
93
|
-
# @sg-ignore pending https://github.com/castwide/solargraph/pull/905
|
94
93
|
# @return [Hash]
|
95
94
|
def formatter
|
96
95
|
raw_data['formatter']
|
@@ -105,7 +104,6 @@ module Solargraph
|
|
105
104
|
|
106
105
|
# The maximum number of files to parse from the workspace.
|
107
106
|
#
|
108
|
-
# @sg-ignore pending https://github.com/castwide/solargraph/pull/905
|
109
107
|
# @return [Integer]
|
110
108
|
def max_files
|
111
109
|
raw_data['max_files']
|
@@ -151,7 +149,7 @@ module Solargraph
|
|
151
149
|
# @return [Hash{String => Array, Hash, Integer}]
|
152
150
|
def default_config
|
153
151
|
{
|
154
|
-
'include' => ['**/*.rb'],
|
152
|
+
'include' => ['Rakefile', 'Gemfile', '*.gemspec', '**/*.rb'],
|
155
153
|
'exclude' => ['spec/**/*', 'test/**/*', 'vendor/**/*', '.bundle/**/*'],
|
156
154
|
'require' => [],
|
157
155
|
'domains' => [],
|