solargraph 0.56.2 → 0.58.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 +127 -0
- data/.github/workflows/plugins.yml +183 -7
- data/.github/workflows/rspec.yml +55 -5
- data/.github/workflows/typecheck.yml +6 -3
- data/.gitignore +5 -0
- data/.overcommit.yml +72 -0
- data/.rspec +1 -0
- data/.rubocop.yml +66 -0
- data/.rubocop_todo.yml +1279 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +69 -0
- data/README.md +8 -4
- data/Rakefile +125 -13
- data/bin/solargraph +8 -5
- data/lib/solargraph/api_map/cache.rb +3 -2
- data/lib/solargraph/api_map/constants.rb +279 -0
- data/lib/solargraph/api_map/index.rb +49 -31
- data/lib/solargraph/api_map/source_to_yard.rb +13 -4
- data/lib/solargraph/api_map/store.rb +144 -26
- data/lib/solargraph/api_map.rb +217 -245
- data/lib/solargraph/bench.rb +1 -0
- data/lib/solargraph/complex_type/type_methods.rb +6 -0
- data/lib/solargraph/complex_type/unique_type.rb +19 -12
- data/lib/solargraph/complex_type.rb +24 -3
- data/lib/solargraph/convention/active_support_concern.rb +111 -0
- data/lib/solargraph/convention/base.rb +17 -0
- data/lib/solargraph/convention/data_definition/data_assignment_node.rb +1 -0
- data/lib/solargraph/convention/data_definition/data_definition_node.rb +4 -2
- data/lib/solargraph/convention/data_definition.rb +2 -1
- data/lib/solargraph/convention/gemspec.rb +1 -1
- data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +1 -0
- data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +3 -1
- data/lib/solargraph/convention/struct_definition.rb +36 -13
- data/lib/solargraph/convention.rb +31 -2
- data/lib/solargraph/diagnostics/rubocop.rb +6 -1
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
- data/lib/solargraph/doc_map.rb +44 -13
- data/lib/solargraph/environ.rb +9 -2
- data/lib/solargraph/equality.rb +1 -0
- data/lib/solargraph/gem_pins.rb +21 -11
- data/lib/solargraph/language_server/host/dispatch.rb +2 -0
- data/lib/solargraph/language_server/host/message_worker.rb +3 -0
- data/lib/solargraph/language_server/host.rb +12 -5
- data/lib/solargraph/language_server/message/base.rb +2 -1
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +1 -1
- data/lib/solargraph/language_server/message/text_document/definition.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/formatting.rb +19 -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 +4 -1
- data/lib/solargraph/library.rb +11 -18
- data/lib/solargraph/location.rb +3 -0
- data/lib/solargraph/logging.rb +11 -2
- data/lib/solargraph/page.rb +3 -0
- data/lib/solargraph/parser/comment_ripper.rb +8 -1
- data/lib/solargraph/parser/flow_sensitive_typing.rb +33 -5
- data/lib/solargraph/parser/node_processor/base.rb +1 -1
- data/lib/solargraph/parser/node_processor.rb +6 -2
- data/lib/solargraph/parser/parser_gem/class_methods.rb +3 -13
- data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +3 -1
- data/lib/solargraph/parser/parser_gem/node_methods.rb +5 -16
- data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +3 -2
- data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +2 -0
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -0
- data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +64 -8
- data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +12 -3
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +36 -16
- data/lib/solargraph/parser/region.rb +3 -0
- data/lib/solargraph/parser/snippet.rb +2 -0
- data/lib/solargraph/pin/base.rb +77 -14
- data/lib/solargraph/pin/base_variable.rb +6 -5
- data/lib/solargraph/pin/block.rb +3 -2
- data/lib/solargraph/pin/callable.rb +14 -1
- data/lib/solargraph/pin/closure.rb +5 -7
- data/lib/solargraph/pin/common.rb +6 -2
- data/lib/solargraph/pin/constant.rb +2 -0
- data/lib/solargraph/pin/local_variable.rb +1 -2
- data/lib/solargraph/pin/method.rb +28 -9
- data/lib/solargraph/pin/method_alias.rb +3 -0
- data/lib/solargraph/pin/parameter.rb +24 -10
- data/lib/solargraph/pin/proxy_type.rb +5 -1
- data/lib/solargraph/pin/reference/override.rb +15 -1
- data/lib/solargraph/pin/reference/superclass.rb +5 -0
- data/lib/solargraph/pin/reference.rb +17 -0
- data/lib/solargraph/pin/search.rb +6 -1
- data/lib/solargraph/pin/signature.rb +2 -0
- data/lib/solargraph/pin/symbol.rb +5 -0
- data/lib/solargraph/pin_cache.rb +64 -4
- data/lib/solargraph/position.rb +3 -0
- data/lib/solargraph/range.rb +5 -0
- data/lib/solargraph/rbs_map/conversions.rb +29 -6
- data/lib/solargraph/rbs_map/core_fills.rb +18 -0
- data/lib/solargraph/rbs_map/core_map.rb +14 -7
- data/lib/solargraph/rbs_map.rb +14 -1
- data/lib/solargraph/shell.rb +85 -1
- data/lib/solargraph/source/chain/call.rb +7 -3
- data/lib/solargraph/source/chain/constant.rb +3 -66
- data/lib/solargraph/source/chain/if.rb +1 -1
- data/lib/solargraph/source/chain/link.rb +11 -2
- data/lib/solargraph/source/chain/or.rb +1 -1
- data/lib/solargraph/source/chain.rb +11 -2
- data/lib/solargraph/source/change.rb +2 -2
- data/lib/solargraph/source/cursor.rb +2 -3
- data/lib/solargraph/source/source_chainer.rb +1 -1
- data/lib/solargraph/source.rb +6 -3
- data/lib/solargraph/source_map/clip.rb +18 -26
- data/lib/solargraph/source_map/data.rb +4 -0
- data/lib/solargraph/source_map/mapper.rb +2 -2
- data/lib/solargraph/source_map.rb +28 -16
- data/lib/solargraph/type_checker/param_def.rb +2 -0
- data/lib/solargraph/type_checker/rules.rb +30 -8
- data/lib/solargraph/type_checker.rb +301 -186
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace/config.rb +21 -5
- data/lib/solargraph/workspace/require_paths.rb +97 -0
- data/lib/solargraph/workspace.rb +30 -67
- data/lib/solargraph/yard_map/mapper/to_method.rb +4 -3
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -0
- data/lib/solargraph/yard_map/to_method.rb +2 -1
- data/lib/solargraph/yardoc.rb +39 -3
- data/lib/solargraph.rb +2 -0
- data/rbs/fills/bundler/0/bundler.rbs +4271 -0
- data/rbs/fills/open3/0/open3.rbs +172 -0
- data/rbs/fills/rubygems/0/basic_specification.rbs +326 -0
- data/rbs/fills/rubygems/0/errors.rbs +364 -0
- data/rbs/fills/rubygems/0/spec_fetcher.rbs +107 -0
- data/rbs/fills/rubygems/0/specification.rbs +1753 -0
- data/rbs/fills/{tuple.rbs → tuple/tuple.rbs} +2 -3
- data/rbs_collection.yaml +4 -4
- data/sig/shims/ast/0/node.rbs +5 -0
- data/sig/shims/ast/2.4/.rbs_meta.yaml +9 -0
- data/sig/shims/ast/2.4/ast.rbs +73 -0
- data/sig/shims/parser/3.2.0.1/builders/default.rbs +195 -0
- data/sig/shims/parser/3.2.0.1/manifest.yaml +7 -0
- data/sig/shims/parser/3.2.0.1/parser.rbs +201 -0
- data/sig/shims/parser/3.2.0.1/polyfill.rbs +4 -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 +26 -5
- metadata +181 -13
- data/lib/.rubocop.yml +0 -22
- data/lib/solargraph/parser/node_methods.rb +0 -97
data/lib/solargraph/library.rb
CHANGED
|
@@ -259,11 +259,11 @@ module Solargraph
|
|
|
259
259
|
referenced&.path == pin.path
|
|
260
260
|
end
|
|
261
261
|
if pin.path == 'Class#new'
|
|
262
|
-
caller = cursor.chain.base.infer(api_map, clip.send(:
|
|
262
|
+
caller = cursor.chain.base.infer(api_map, clip.send(:closure), clip.locals).first
|
|
263
263
|
if caller.defined?
|
|
264
264
|
found.select! do |loc|
|
|
265
265
|
clip = api_map.clip_at(loc.filename, loc.range.start)
|
|
266
|
-
other = clip.send(:cursor).chain.base.infer(api_map, clip.send(:
|
|
266
|
+
other = clip.send(:cursor).chain.base.infer(api_map, clip.send(:closure), clip.locals).first
|
|
267
267
|
caller == other
|
|
268
268
|
end
|
|
269
269
|
else
|
|
@@ -402,8 +402,8 @@ module Solargraph
|
|
|
402
402
|
repargs = {}
|
|
403
403
|
workspace.config.reporters.each do |line|
|
|
404
404
|
if line == 'all!'
|
|
405
|
-
Diagnostics.reporters.each do |
|
|
406
|
-
repargs[reporter] ||= []
|
|
405
|
+
Diagnostics.reporters.each do |reporter_name|
|
|
406
|
+
repargs[Diagnostics.reporter(reporter_name)] ||= []
|
|
407
407
|
end
|
|
408
408
|
else
|
|
409
409
|
args = line.split(':').map(&:strip)
|
|
@@ -437,17 +437,6 @@ module Solargraph
|
|
|
437
437
|
)
|
|
438
438
|
end
|
|
439
439
|
|
|
440
|
-
# Get an array of foldable ranges for the specified file.
|
|
441
|
-
#
|
|
442
|
-
# @deprecated The library should not need to handle folding ranges. The
|
|
443
|
-
# source itself has all the information it needs.
|
|
444
|
-
#
|
|
445
|
-
# @param filename [String]
|
|
446
|
-
# @return [Array<Range>]
|
|
447
|
-
def folding_ranges filename
|
|
448
|
-
read(filename).folding_ranges
|
|
449
|
-
end
|
|
450
|
-
|
|
451
440
|
# Create a library from a directory.
|
|
452
441
|
#
|
|
453
442
|
# @param directory [String] The path to be used for the workspace
|
|
@@ -511,7 +500,7 @@ module Solargraph
|
|
|
511
500
|
|
|
512
501
|
private
|
|
513
502
|
|
|
514
|
-
# @return [Hash{String =>
|
|
503
|
+
# @return [Hash{String => Array<String>}]
|
|
515
504
|
def source_map_external_require_hash
|
|
516
505
|
@source_map_external_require_hash ||= {}
|
|
517
506
|
end
|
|
@@ -519,6 +508,7 @@ module Solargraph
|
|
|
519
508
|
# @param source_map [SourceMap]
|
|
520
509
|
# @return [void]
|
|
521
510
|
def find_external_requires source_map
|
|
511
|
+
# @type [Set<String>]
|
|
522
512
|
new_set = source_map.requires.map(&:name).to_set
|
|
523
513
|
# return if new_set == source_map_external_require_hash[source_map.filename]
|
|
524
514
|
_filenames = nil
|
|
@@ -532,7 +522,7 @@ module Solargraph
|
|
|
532
522
|
@external_requires = nil
|
|
533
523
|
end
|
|
534
524
|
|
|
535
|
-
# @return [Mutex]
|
|
525
|
+
# @return [Thread::Mutex]
|
|
536
526
|
def mutex
|
|
537
527
|
@mutex ||= Mutex.new
|
|
538
528
|
end
|
|
@@ -621,6 +611,7 @@ module Solargraph
|
|
|
621
611
|
end
|
|
622
612
|
end
|
|
623
613
|
|
|
614
|
+
# @return [Array<Gem::Specification>]
|
|
624
615
|
def cacheable_specs
|
|
625
616
|
cacheable = api_map.uncached_yard_gemspecs +
|
|
626
617
|
api_map.uncached_rbs_collection_gemspecs -
|
|
@@ -631,6 +622,7 @@ module Solargraph
|
|
|
631
622
|
queued_gemspec_cache
|
|
632
623
|
end
|
|
633
624
|
|
|
625
|
+
# @return [Array<Gem::Specification>]
|
|
634
626
|
def queued_gemspec_cache
|
|
635
627
|
@queued_gemspec_cache ||= []
|
|
636
628
|
end
|
|
@@ -672,13 +664,14 @@ module Solargraph
|
|
|
672
664
|
@total = nil
|
|
673
665
|
end
|
|
674
666
|
|
|
667
|
+
# @return [void]
|
|
675
668
|
def sync_catalog
|
|
676
669
|
return if @sync_count == 0
|
|
677
670
|
|
|
678
671
|
mutex.synchronize do
|
|
679
672
|
logger.info "Cataloging #{workspace.directory.empty? ? 'generic workspace' : workspace.directory}"
|
|
680
|
-
api_map.catalog bench
|
|
681
673
|
source_map_hash.values.each { |map| find_external_requires(map) }
|
|
674
|
+
api_map.catalog bench
|
|
682
675
|
logger.info "Catalog complete (#{api_map.source_maps.length} files, #{api_map.pins.length} pins)"
|
|
683
676
|
logger.info "#{api_map.uncached_yard_gemspecs.length} uncached YARD gemspecs"
|
|
684
677
|
logger.info "#{api_map.uncached_rbs_collection_gemspecs.length} uncached RBS collection gemspecs"
|
data/lib/solargraph/location.rb
CHANGED
|
@@ -25,6 +25,7 @@ module Solargraph
|
|
|
25
25
|
[filename, range]
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
+
# @param other [self]
|
|
28
29
|
def <=>(other)
|
|
29
30
|
return nil unless other.is_a?(Location)
|
|
30
31
|
if filename == other.filename
|
|
@@ -60,6 +61,7 @@ module Solargraph
|
|
|
60
61
|
end
|
|
61
62
|
|
|
62
63
|
# @param node [Parser::AST::Node, nil]
|
|
64
|
+
# @return [Location, nil]
|
|
63
65
|
def self.from_node(node)
|
|
64
66
|
return nil if node.nil? || node.loc.nil?
|
|
65
67
|
range = Range.from_node(node)
|
|
@@ -69,6 +71,7 @@ module Solargraph
|
|
|
69
71
|
# @param other [BasicObject]
|
|
70
72
|
def == other
|
|
71
73
|
return false unless other.is_a?(Location)
|
|
74
|
+
# @sg-ignore https://github.com/castwide/solargraph/pull/1114
|
|
72
75
|
filename == other.filename and range == other.range
|
|
73
76
|
end
|
|
74
77
|
|
data/lib/solargraph/logging.rb
CHANGED
|
@@ -11,8 +11,17 @@ module Solargraph
|
|
|
11
11
|
'info' => Logger::INFO,
|
|
12
12
|
'debug' => Logger::DEBUG
|
|
13
13
|
}
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
configured_level = ENV.fetch('SOLARGRAPH_LOG', nil)
|
|
15
|
+
level = if LOG_LEVELS.keys.include?(configured_level)
|
|
16
|
+
LOG_LEVELS.fetch(configured_level)
|
|
17
|
+
else
|
|
18
|
+
if configured_level
|
|
19
|
+
warn "Invalid value for SOLARGRAPH_LOG: #{configured_level.inspect} - " \
|
|
20
|
+
"valid values are #{LOG_LEVELS.keys}"
|
|
21
|
+
end
|
|
22
|
+
DEFAULT_LOG_LEVEL
|
|
23
|
+
end
|
|
24
|
+
@@logger = Logger.new(STDERR, level: level)
|
|
16
25
|
# @sg-ignore Fix cvar issue
|
|
17
26
|
@@logger.formatter = proc do |severity, datetime, progname, msg|
|
|
18
27
|
"[#{severity}] #{msg}\n"
|
data/lib/solargraph/page.rb
CHANGED
|
@@ -29,6 +29,7 @@ module Solargraph
|
|
|
29
29
|
# @param text [String]
|
|
30
30
|
# @return [String]
|
|
31
31
|
def htmlify text
|
|
32
|
+
# @type [String]
|
|
32
33
|
YARD::Templates::Helpers::Markup::RDocMarkup.new(text).to_html
|
|
33
34
|
end
|
|
34
35
|
|
|
@@ -70,8 +71,10 @@ module Solargraph
|
|
|
70
71
|
# @param template [String]
|
|
71
72
|
# @param layout [Boolean]
|
|
72
73
|
# @param locals [Hash]
|
|
74
|
+
# @sg-ignore
|
|
73
75
|
# @return [String]
|
|
74
76
|
def render template, layout: true, locals: {}
|
|
77
|
+
# @type [String]
|
|
75
78
|
@render_method.call(template, layout: layout, locals: locals)
|
|
76
79
|
end
|
|
77
80
|
|
|
@@ -3,6 +3,13 @@ require 'ripper'
|
|
|
3
3
|
module Solargraph
|
|
4
4
|
module Parser
|
|
5
5
|
class CommentRipper < Ripper::SexpBuilderPP
|
|
6
|
+
# @!override Ripper::SexpBuilder#on_embdoc_beg
|
|
7
|
+
# @return [Array(Symbol, String, Array)]
|
|
8
|
+
# @!override Ripper::SexpBuilder#on_embdoc
|
|
9
|
+
# @return [Array(Symbol, String, Array)]
|
|
10
|
+
# @!override Ripper::SexpBuilder#on_embdoc_end
|
|
11
|
+
# @return [Array(Symbol, String, Array)]
|
|
12
|
+
|
|
6
13
|
# @param src [String]
|
|
7
14
|
# @param filename [String]
|
|
8
15
|
# @param lineno [Integer]
|
|
@@ -51,7 +58,7 @@ module Solargraph
|
|
|
51
58
|
result
|
|
52
59
|
end
|
|
53
60
|
|
|
54
|
-
# @return [Hash{Integer =>
|
|
61
|
+
# @return [Hash{Integer => Solargraph::Parser::Snippet}]
|
|
55
62
|
def parse
|
|
56
63
|
@comments = {}
|
|
57
64
|
super
|
|
@@ -4,14 +4,20 @@ module Solargraph
|
|
|
4
4
|
include Solargraph::Parser::NodeMethods
|
|
5
5
|
|
|
6
6
|
# @param locals [Array<Solargraph::Pin::LocalVariable, Solargraph::Pin::Parameter>]
|
|
7
|
+
# @param enclosing_breakable_pin [Solargraph::Pin::Breakable, nil]
|
|
7
8
|
def initialize(locals, enclosing_breakable_pin = nil)
|
|
8
9
|
@locals = locals
|
|
9
10
|
@enclosing_breakable_pin = enclosing_breakable_pin
|
|
10
11
|
end
|
|
11
12
|
|
|
12
13
|
# @param and_node [Parser::AST::Node]
|
|
14
|
+
# @param true_ranges [Array<Range>]
|
|
15
|
+
#
|
|
16
|
+
# @return [void]
|
|
13
17
|
def process_and(and_node, true_ranges = [])
|
|
18
|
+
# @type [Parser::AST::Node]
|
|
14
19
|
lhs = and_node.children[0]
|
|
20
|
+
# @type [Parser::AST::Node]
|
|
15
21
|
rhs = and_node.children[1]
|
|
16
22
|
|
|
17
23
|
before_rhs_loc = rhs.location.expression.adjust(begin_pos: -1)
|
|
@@ -23,6 +29,8 @@ module Solargraph
|
|
|
23
29
|
end
|
|
24
30
|
|
|
25
31
|
# @param if_node [Parser::AST::Node]
|
|
32
|
+
#
|
|
33
|
+
# @return [void]
|
|
26
34
|
def process_if(if_node)
|
|
27
35
|
#
|
|
28
36
|
# See if we can refine a type based on the result of 'if foo.nil?'
|
|
@@ -36,7 +44,9 @@ module Solargraph
|
|
|
36
44
|
# s(:send, nil, :bar))
|
|
37
45
|
# [4] pry(main)>
|
|
38
46
|
conditional_node = if_node.children[0]
|
|
47
|
+
# @type [Parser::AST::Node]
|
|
39
48
|
then_clause = if_node.children[1]
|
|
49
|
+
# @type [Parser::AST::Node]
|
|
40
50
|
else_clause = if_node.children[2]
|
|
41
51
|
|
|
42
52
|
true_ranges = []
|
|
@@ -72,8 +82,11 @@ module Solargraph
|
|
|
72
82
|
# them based on the Closure and Location.
|
|
73
83
|
#
|
|
74
84
|
# @param pins [Array<Pin::LocalVariable>]
|
|
85
|
+
# @param name [String]
|
|
75
86
|
# @param closure [Pin::Closure]
|
|
76
87
|
# @param location [Location]
|
|
88
|
+
#
|
|
89
|
+
# @return [Array<Pin::LocalVariable>]
|
|
77
90
|
def self.visible_pins(pins, name, closure, location)
|
|
78
91
|
logger.debug { "FlowSensitiveTyping#visible_pins(name=#{name}, closure=#{closure}, location=#{location})" }
|
|
79
92
|
pins_with_name = pins.select { |p| p.name == name }
|
|
@@ -107,7 +120,10 @@ module Solargraph
|
|
|
107
120
|
private
|
|
108
121
|
|
|
109
122
|
# @param pin [Pin::LocalVariable]
|
|
110
|
-
# @param
|
|
123
|
+
# @param downcast_type_name [String]
|
|
124
|
+
# @param presence [Range]
|
|
125
|
+
#
|
|
126
|
+
# @return [void]
|
|
111
127
|
def add_downcast_local(pin, downcast_type_name, presence)
|
|
112
128
|
# @todo Create pin#update method
|
|
113
129
|
new_pin = Solargraph::Pin::LocalVariable.new(
|
|
@@ -126,6 +142,7 @@ module Solargraph
|
|
|
126
142
|
|
|
127
143
|
# @param facts_by_pin [Hash{Pin::LocalVariable => Array<Hash{Symbol => String}>}]
|
|
128
144
|
# @param presences [Array<Range>]
|
|
145
|
+
#
|
|
129
146
|
# @return [void]
|
|
130
147
|
def process_facts(facts_by_pin, presences)
|
|
131
148
|
#
|
|
@@ -142,6 +159,9 @@ module Solargraph
|
|
|
142
159
|
end
|
|
143
160
|
|
|
144
161
|
# @param conditional_node [Parser::AST::Node]
|
|
162
|
+
# @param true_ranges [Array<Range>]
|
|
163
|
+
#
|
|
164
|
+
# @return [void]
|
|
145
165
|
def process_conditional(conditional_node, true_ranges)
|
|
146
166
|
if conditional_node.type == :send
|
|
147
167
|
process_isa(conditional_node, true_ranges)
|
|
@@ -151,7 +171,7 @@ module Solargraph
|
|
|
151
171
|
end
|
|
152
172
|
|
|
153
173
|
# @param isa_node [Parser::AST::Node]
|
|
154
|
-
# @return [Array(String, String)]
|
|
174
|
+
# @return [Array(String, String), nil]
|
|
155
175
|
def parse_isa(isa_node)
|
|
156
176
|
return unless isa_node&.type == :send && isa_node.children[1] == :is_a?
|
|
157
177
|
# Check if conditional node follows this pattern:
|
|
@@ -176,12 +196,20 @@ module Solargraph
|
|
|
176
196
|
[isa_type_name, variable_name]
|
|
177
197
|
end
|
|
178
198
|
|
|
199
|
+
# @param variable_name [String]
|
|
200
|
+
# @param position [Position]
|
|
201
|
+
#
|
|
202
|
+
# @return [Solargraph::Pin::LocalVariable, nil]
|
|
179
203
|
def find_local(variable_name, position)
|
|
180
204
|
pins = locals.select { |pin| pin.name == variable_name && pin.presence.include?(position) }
|
|
181
205
|
return unless pins.length == 1
|
|
182
206
|
pins.first
|
|
183
207
|
end
|
|
184
208
|
|
|
209
|
+
# @param isa_node [Parser::AST::Node]
|
|
210
|
+
# @param true_presences [Array<Range>]
|
|
211
|
+
#
|
|
212
|
+
# @return [void]
|
|
185
213
|
def process_isa(isa_node, true_presences)
|
|
186
214
|
isa_type_name, variable_name = parse_isa(isa_node)
|
|
187
215
|
return if variable_name.nil? || variable_name.empty?
|
|
@@ -197,10 +225,12 @@ module Solargraph
|
|
|
197
225
|
end
|
|
198
226
|
|
|
199
227
|
# @param node [Parser::AST::Node]
|
|
228
|
+
#
|
|
229
|
+
# @return [String, nil]
|
|
200
230
|
def type_name(node)
|
|
201
231
|
# e.g.,
|
|
202
232
|
# s(:const, nil, :Baz)
|
|
203
|
-
return unless node
|
|
233
|
+
return unless node&.type == :const
|
|
204
234
|
module_node = node.children[0]
|
|
205
235
|
class_node = node.children[1]
|
|
206
236
|
|
|
@@ -212,8 +242,6 @@ module Solargraph
|
|
|
212
242
|
"#{module_type_name}::#{class_node}"
|
|
213
243
|
end
|
|
214
244
|
|
|
215
|
-
# @todo "return type could not be inferred" should not trigger here
|
|
216
|
-
# @sg-ignore
|
|
217
245
|
# @param clause_node [Parser::AST::Node]
|
|
218
246
|
def always_breaks?(clause_node)
|
|
219
247
|
clause_node&.type == :break
|
|
@@ -9,7 +9,7 @@ module Solargraph
|
|
|
9
9
|
autoload :Base, 'solargraph/parser/node_processor/base'
|
|
10
10
|
|
|
11
11
|
class << self
|
|
12
|
-
# @type [Hash
|
|
12
|
+
# @type [Hash{Symbol => Array<Class<NodeProcessor::Base>>}]
|
|
13
13
|
@@processors ||= {}
|
|
14
14
|
|
|
15
15
|
# Register a processor for a node type. You can register multiple processors for the same type.
|
|
@@ -17,12 +17,16 @@ module Solargraph
|
|
|
17
17
|
#
|
|
18
18
|
# @param type [Symbol]
|
|
19
19
|
# @param cls [Class<NodeProcessor::Base>]
|
|
20
|
-
# @return [Class<NodeProcessor::Base
|
|
20
|
+
# @return [Array<Class<NodeProcessor::Base>>]
|
|
21
21
|
def register type, cls
|
|
22
22
|
@@processors[type] ||= []
|
|
23
23
|
@@processors[type] << cls
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
+
# @param type [Symbol]
|
|
27
|
+
# @param cls [Class<NodeProcessor::Base>]
|
|
28
|
+
#
|
|
29
|
+
# @return [void]
|
|
26
30
|
def deregister type, cls
|
|
27
31
|
@@processors[type].delete(cls)
|
|
28
32
|
end
|
|
@@ -2,22 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
require 'prism'
|
|
4
4
|
|
|
5
|
-
# Awaiting ability to use a version containing https://github.com/whitequark/parser/pull/1076
|
|
6
|
-
#
|
|
7
|
-
# @!parse
|
|
8
|
-
# class ::Parser::Base < ::Parser::Builder
|
|
9
|
-
# # @return [Integer]
|
|
10
|
-
# def version; end
|
|
11
|
-
# end
|
|
12
|
-
# class ::Parser::CurrentRuby < ::Parser::Base; end
|
|
13
|
-
|
|
14
5
|
module Solargraph
|
|
15
6
|
module Parser
|
|
16
7
|
module ParserGem
|
|
17
8
|
module ClassMethods
|
|
18
9
|
# @param code [String]
|
|
19
10
|
# @param filename [String, nil]
|
|
20
|
-
# @return [Array(Parser::AST::Node, Hash{Integer =>
|
|
11
|
+
# @return [Array(Parser::AST::Node, Hash{Integer => Solargraph::Parser::Snippet})]
|
|
21
12
|
def parse_with_comments code, filename = nil
|
|
22
13
|
node = parse(code, filename)
|
|
23
14
|
comments = CommentRipper.new(code, filename, 0).parse
|
|
@@ -84,6 +75,7 @@ module Solargraph
|
|
|
84
75
|
# @param top [AST::Node]
|
|
85
76
|
# @return [Array<AST::Node>]
|
|
86
77
|
def inner_node_references name, top
|
|
78
|
+
# @type [Array<AST::Node>]
|
|
87
79
|
result = []
|
|
88
80
|
if top.is_a?(AST::Node) && top.to_s.include?(":#{name}")
|
|
89
81
|
result.push top if top.children.any? { |c| c.to_s == name }
|
|
@@ -137,9 +129,7 @@ module Solargraph
|
|
|
137
129
|
def string_ranges node
|
|
138
130
|
return [] unless is_ast_node?(node)
|
|
139
131
|
result = []
|
|
140
|
-
if node.type == :str
|
|
141
|
-
result.push Range.from_node(node)
|
|
142
|
-
end
|
|
132
|
+
result.push Range.from_node(node) if node.type == :str
|
|
143
133
|
node.children.each do |child|
|
|
144
134
|
result.concat string_ranges(child)
|
|
145
135
|
end
|
|
@@ -7,6 +7,7 @@ module Solargraph
|
|
|
7
7
|
#
|
|
8
8
|
class NodeChainer
|
|
9
9
|
include NodeMethods
|
|
10
|
+
|
|
10
11
|
Chain = Source::Chain
|
|
11
12
|
|
|
12
13
|
# @param node [Parser::AST::Node]
|
|
@@ -98,7 +99,8 @@ module Solargraph
|
|
|
98
99
|
elsif [:gvar, :gvasgn].include?(n.type)
|
|
99
100
|
result.push Chain::GlobalVariable.new(n.children[0].to_s)
|
|
100
101
|
elsif n.type == :or_asgn
|
|
101
|
-
|
|
102
|
+
new_node = n.updated(n.children[0].type, n.children[0].children + [n.children[1]])
|
|
103
|
+
result.concat generate_links new_node
|
|
102
104
|
elsif [:class, :module, :def, :defs].include?(n.type)
|
|
103
105
|
# @todo Undefined or what?
|
|
104
106
|
result.push Chain::UNDEFINED_CALL
|
|
@@ -3,20 +3,6 @@
|
|
|
3
3
|
require 'parser'
|
|
4
4
|
require 'ast'
|
|
5
5
|
|
|
6
|
-
# Teach AST::Node#children about its generic type
|
|
7
|
-
#
|
|
8
|
-
# @todo contribute back to https://github.com/ruby/gem_rbs_collection/blob/main/gems/ast/2.4/ast.rbs
|
|
9
|
-
#
|
|
10
|
-
# @!parse
|
|
11
|
-
# module ::AST
|
|
12
|
-
# class Node
|
|
13
|
-
# # New children
|
|
14
|
-
#
|
|
15
|
-
# # @return [Array<self, Integer, String, Symbol, nil>]
|
|
16
|
-
# attr_reader :children
|
|
17
|
-
# end
|
|
18
|
-
# end
|
|
19
|
-
|
|
20
6
|
# https://github.com/whitequark/parser
|
|
21
7
|
module Solargraph
|
|
22
8
|
module Parser
|
|
@@ -120,7 +106,7 @@ module Solargraph
|
|
|
120
106
|
end
|
|
121
107
|
|
|
122
108
|
# @param node [Parser::AST::Node]
|
|
123
|
-
# @return [Hash{
|
|
109
|
+
# @return [Hash{Symbol => Chain}]
|
|
124
110
|
def convert_hash node
|
|
125
111
|
return {} unless Parser.is_ast_node?(node)
|
|
126
112
|
return convert_hash(node.children[0]) if node.type == :kwsplat
|
|
@@ -133,6 +119,7 @@ module Solargraph
|
|
|
133
119
|
result
|
|
134
120
|
end
|
|
135
121
|
|
|
122
|
+
# @sg-ignore Wrong argument type for AST::Node.new: type expected AST::_ToSym, received :nil
|
|
136
123
|
NIL_NODE = ::Parser::AST::Node.new(:nil)
|
|
137
124
|
|
|
138
125
|
# @param node [Parser::AST::Node]
|
|
@@ -179,6 +166,7 @@ module Solargraph
|
|
|
179
166
|
node.children[1..-1].each { |child| result.concat call_nodes_from(child) }
|
|
180
167
|
elsif node.type == :send
|
|
181
168
|
result.push node
|
|
169
|
+
result.concat call_nodes_from(node.children.first)
|
|
182
170
|
node.children[2..-1].each { |child| result.concat call_nodes_from(child) }
|
|
183
171
|
elsif [:super, :zsuper].include?(node.type)
|
|
184
172
|
result.push node
|
|
@@ -232,6 +220,7 @@ module Solargraph
|
|
|
232
220
|
else
|
|
233
221
|
source.tree_at(position.line, position.column - 1)
|
|
234
222
|
end
|
|
223
|
+
# @type [AST::Node, nil]
|
|
235
224
|
prev = nil
|
|
236
225
|
tree.each do |node|
|
|
237
226
|
if node.type == :send
|
|
@@ -242,7 +231,7 @@ module Solargraph
|
|
|
242
231
|
if source.synchronized?
|
|
243
232
|
return node if source.code[0..offset-1] =~ /\(\s*\z/ && source.code[offset..-1] =~ /^\s*\)/
|
|
244
233
|
else
|
|
245
|
-
return node if source.code[0..offset-1] =~ /\([
|
|
234
|
+
return node if source.code[0..offset-1] =~ /\([^(]*\z/
|
|
246
235
|
end
|
|
247
236
|
end
|
|
248
237
|
end
|
|
@@ -11,6 +11,7 @@ module Solargraph
|
|
|
11
11
|
process_children
|
|
12
12
|
|
|
13
13
|
position = get_node_start_position(node)
|
|
14
|
+
# @sg-ignore https://github.com/castwide/solargraph/pull/1114
|
|
14
15
|
enclosing_breakable_pin = pins.select{|pin| pin.is_a?(Pin::Breakable) && pin.location.range.contain?(position)}.last
|
|
15
16
|
FlowSensitiveTyping.new(locals, enclosing_breakable_pin).process_and(node)
|
|
16
17
|
end
|
|
@@ -19,7 +19,7 @@ module Solargraph
|
|
|
19
19
|
else
|
|
20
20
|
region.closure
|
|
21
21
|
end
|
|
22
|
-
|
|
22
|
+
block_pin = Solargraph::Pin::Block.new(
|
|
23
23
|
location: location,
|
|
24
24
|
closure: parent,
|
|
25
25
|
node: node,
|
|
@@ -28,7 +28,8 @@ module Solargraph
|
|
|
28
28
|
scope: region.scope || region.closure.context.scope,
|
|
29
29
|
source: :parser
|
|
30
30
|
)
|
|
31
|
-
|
|
31
|
+
pins.push block_pin
|
|
32
|
+
process_children region.update(closure: block_pin)
|
|
32
33
|
end
|
|
33
34
|
|
|
34
35
|
private
|
|
@@ -11,6 +11,8 @@ module Solargraph
|
|
|
11
11
|
process_children
|
|
12
12
|
|
|
13
13
|
position = get_node_start_position(node)
|
|
14
|
+
# @sg-ignore
|
|
15
|
+
# @type [Solargraph::Pin::Breakable, nil]
|
|
14
16
|
enclosing_breakable_pin = pins.select{|pin| pin.is_a?(Pin::Breakable) && pin.location.range.contain?(position)}.last
|
|
15
17
|
FlowSensitiveTyping.new(locals, enclosing_breakable_pin).process_if(node)
|
|
16
18
|
end
|
|
@@ -22,8 +22,11 @@ module Solargraph
|
|
|
22
22
|
# s(:int, 2),
|
|
23
23
|
# s(:int, 3)))
|
|
24
24
|
masgn = node
|
|
25
|
+
# @type [Parser::AST::Node]
|
|
25
26
|
mlhs = masgn.children.fetch(0)
|
|
27
|
+
# @type [Array<Parser::AST::Node>]
|
|
26
28
|
lhs_arr = mlhs.children
|
|
29
|
+
# @type [Parser::AST::Node]
|
|
27
30
|
mass_rhs = node.children.fetch(1)
|
|
28
31
|
|
|
29
32
|
# Get pins created for the mlhs node
|
|
@@ -9,14 +9,70 @@ module Solargraph
|
|
|
9
9
|
class OpasgnNode < Parser::NodeProcessor::Base
|
|
10
10
|
# @return [void]
|
|
11
11
|
def process
|
|
12
|
-
|
|
13
|
-
# => s(:op_asgn,
|
|
14
|
-
# s(:lvasgn, :a), :+,
|
|
15
|
-
# s(:int, 2))
|
|
16
|
-
asgn = node.children[0]
|
|
17
|
-
variable_name = asgn.children[0]
|
|
12
|
+
target = node.children[0]
|
|
18
13
|
operator = node.children[1]
|
|
19
14
|
argument = node.children[2]
|
|
15
|
+
if target.type == :send
|
|
16
|
+
# @sg-ignore Need a downcast here
|
|
17
|
+
process_send_target(target, operator, argument)
|
|
18
|
+
elsif target.type.to_s.end_with?('vasgn')
|
|
19
|
+
# @sg-ignore Need a downcast here
|
|
20
|
+
process_vasgn_target(target, operator, argument)
|
|
21
|
+
else
|
|
22
|
+
Solargraph.assert_or_log(:opasgn_unknown_target,
|
|
23
|
+
"Unexpected op_asgn target type: #{target.type}")
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# @param call [Parser::AST::Node] the target of the assignment
|
|
28
|
+
# @param operator [Symbol] the operator, e.g. :+
|
|
29
|
+
# @param argument [Parser::AST::Node] the argument of the operation
|
|
30
|
+
#
|
|
31
|
+
# @return [void]
|
|
32
|
+
def process_send_target call, operator, argument
|
|
33
|
+
# if target is a call:
|
|
34
|
+
# [10] pry(main)> Parser::CurrentRuby.parse("Foo.bar += baz")
|
|
35
|
+
# => s(:op_asgn,
|
|
36
|
+
# s(:send, # call
|
|
37
|
+
# s(:const, nil, :Foo), # calee
|
|
38
|
+
# :bar), # call_method
|
|
39
|
+
# :+, # operator
|
|
40
|
+
# s(:send, nil, :baz)) # argument
|
|
41
|
+
# [11] pry(main)>
|
|
42
|
+
callee = call.children[0]
|
|
43
|
+
call_method = call.children[1]
|
|
44
|
+
asgn_method = :"#{call_method}="
|
|
45
|
+
|
|
46
|
+
# [8] pry(main)> Parser::CurrentRuby.parse("Foo.bar = Foo.bar + baz")
|
|
47
|
+
# => s(:send,
|
|
48
|
+
# s(:const, nil, :Foo), # callee
|
|
49
|
+
# :bar=, # asgn_method
|
|
50
|
+
# s(:send,
|
|
51
|
+
# s(:send,
|
|
52
|
+
# s(:const, nil, :Foo), # callee
|
|
53
|
+
# :bar), # call_method
|
|
54
|
+
# :+, # operator
|
|
55
|
+
# s(:send, nil, :baz))) # argument
|
|
56
|
+
new_send = node.updated(:send,
|
|
57
|
+
[callee,
|
|
58
|
+
asgn_method,
|
|
59
|
+
node.updated(:send, [call, operator, argument])])
|
|
60
|
+
NodeProcessor.process(new_send, region, pins, locals)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# @param asgn [Parser::AST::Node] the target of the assignment
|
|
64
|
+
# @param operator [Symbol] the operator, e.g. :+
|
|
65
|
+
# @param argument [Parser::AST::Node] the argument of the operation
|
|
66
|
+
#
|
|
67
|
+
# @return [void]
|
|
68
|
+
def process_vasgn_target asgn, operator, argument
|
|
69
|
+
# => s(:op_asgn,
|
|
70
|
+
# s(:lvasgn, :a), # asgn
|
|
71
|
+
# :+, # operator
|
|
72
|
+
# s(:int, 2)) # argument
|
|
73
|
+
|
|
74
|
+
# @type [Parser::AST::Node]
|
|
75
|
+
variable_name = asgn.children[0]
|
|
20
76
|
# for lvasgn, gvasgn, cvasgn, convert to lvar, gvar, cvar
|
|
21
77
|
# [6] pry(main)> Parser::CurrentRuby.parse("a = a + 1")
|
|
22
78
|
# => s(:lvasgn, :a,
|
|
@@ -25,9 +81,9 @@ module Solargraph
|
|
|
25
81
|
# s(:int, 1)))
|
|
26
82
|
# [7] pry(main)>
|
|
27
83
|
variable_reference_type = asgn.type.to_s.sub(/vasgn$/, 'var').to_sym
|
|
28
|
-
|
|
84
|
+
target_reference = node.updated(variable_reference_type, asgn.children)
|
|
29
85
|
send_children = [
|
|
30
|
-
|
|
86
|
+
target_reference,
|
|
31
87
|
operator,
|
|
32
88
|
argument
|
|
33
89
|
]
|
|
@@ -7,9 +7,18 @@ module Solargraph
|
|
|
7
7
|
class SclassNode < Parser::NodeProcessor::Base
|
|
8
8
|
def process
|
|
9
9
|
sclass = node.children[0]
|
|
10
|
-
|
|
10
|
+
# @todo Changing Parser::AST::Node to AST::Node below will
|
|
11
|
+
# cause type errors at strong level because the combined
|
|
12
|
+
# pin for AST::Node#children has return type
|
|
13
|
+
# "Array<AST::Node>, Array". YARD annotations in AST
|
|
14
|
+
# provided the Array, RBS for Array<AST::Node>. We
|
|
15
|
+
# should probably have a rule to combine "A, A<T>""
|
|
16
|
+
# types to "A<T>" if the "A" comes from YARD, with the
|
|
17
|
+
# rationale that folks tend to be less formal with types in
|
|
18
|
+
# YARD.
|
|
19
|
+
if sclass.is_a?(::Parser::AST::Node) && sclass.type == :self
|
|
11
20
|
closure = region.closure
|
|
12
|
-
elsif sclass.is_a?(AST::Node) && sclass.type == :casgn
|
|
21
|
+
elsif sclass.is_a?(::Parser::AST::Node) && sclass.type == :casgn
|
|
13
22
|
names = [region.closure.namespace, region.closure.name]
|
|
14
23
|
if sclass.children[0].nil? && names.last != sclass.children[1].to_s
|
|
15
24
|
names << sclass.children[1].to_s
|
|
@@ -18,7 +27,7 @@ module Solargraph
|
|
|
18
27
|
end
|
|
19
28
|
name = names.reject(&:empty?).join('::')
|
|
20
29
|
closure = Solargraph::Pin::Namespace.new(name: name, location: region.closure.location, source: :parser)
|
|
21
|
-
elsif sclass.is_a?(AST::Node) && sclass.type == :const
|
|
30
|
+
elsif sclass.is_a?(::Parser::AST::Node) && sclass.type == :const
|
|
22
31
|
names = [region.closure.namespace, region.closure.name]
|
|
23
32
|
also = NodeMethods.unpack_name(sclass)
|
|
24
33
|
if also != region.closure.name
|