solargraph 0.56.1 → 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 +148 -6
- data/.github/workflows/rspec.yml +39 -4
- data/.github/workflows/typecheck.yml +5 -2
- data/.gitignore +5 -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 +50 -0
- data/README.md +8 -4
- 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 +20 -26
- data/lib/solargraph/api_map/source_to_yard.rb +10 -4
- data/lib/solargraph/api_map/store.rb +126 -18
- data/lib/solargraph/api_map.rb +212 -234
- data/lib/solargraph/bench.rb +1 -0
- data/lib/solargraph/complex_type/type_methods.rb +1 -0
- data/lib/solargraph/complex_type/unique_type.rb +7 -7
- data/lib/solargraph/complex_type.rb +5 -1
- 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 +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 +2 -1
- data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +4 -2
- data/lib/solargraph/convention/struct_definition.rb +87 -24
- data/lib/solargraph/convention.rb +32 -2
- data/lib/solargraph/diagnostics/rubocop.rb +6 -1
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +1 -1
- data/lib/solargraph/doc_map.rb +40 -12
- data/lib/solargraph/environ.rb +9 -2
- data/lib/solargraph/gem_pins.rb +17 -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 +2 -1
- 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 +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 +17 -24
- data/lib/solargraph/location.rb +2 -0
- data/lib/solargraph/logging.rb +11 -2
- data/lib/solargraph/page.rb +4 -0
- data/lib/solargraph/parser/comment_ripper.rb +8 -1
- data/lib/solargraph/parser/flow_sensitive_typing.rb +32 -4
- data/lib/solargraph/parser/node_methods.rb +2 -2
- data/lib/solargraph/parser/node_processor/base.rb +10 -5
- data/lib/solargraph/parser/node_processor.rb +24 -8
- data/lib/solargraph/parser/parser_gem/class_methods.rb +1 -1
- 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 +4 -2
- data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +3 -2
- data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +1 -21
- data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +2 -0
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +7 -1
- data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +0 -22
- data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +1 -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 +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +35 -14
- data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
- data/lib/solargraph/parser/region.rb +3 -0
- data/lib/solargraph/parser/snippet.rb +2 -0
- data/lib/solargraph/pin/base.rb +65 -8
- data/lib/solargraph/pin/base_variable.rb +1 -2
- data/lib/solargraph/pin/callable.rb +9 -0
- data/lib/solargraph/pin/closure.rb +2 -0
- data/lib/solargraph/pin/common.rb +6 -2
- data/lib/solargraph/pin/constant.rb +2 -0
- data/lib/solargraph/pin/delegated_method.rb +1 -0
- data/lib/solargraph/pin/local_variable.rb +4 -1
- data/lib/solargraph/pin/method.rb +12 -7
- data/lib/solargraph/pin/method_alias.rb +3 -0
- data/lib/solargraph/pin/parameter.rb +18 -8
- data/lib/solargraph/pin/proxy_type.rb +1 -0
- data/lib/solargraph/pin/reference/override.rb +15 -1
- 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 +2 -0
- data/lib/solargraph/pin/symbol.rb +5 -0
- data/lib/solargraph/pin_cache.rb +64 -4
- data/lib/solargraph/position.rb +2 -0
- data/lib/solargraph/range.rb +1 -0
- data/lib/solargraph/rbs_map/conversions.rb +47 -18
- data/lib/solargraph/rbs_map/core_map.rb +3 -0
- data/lib/solargraph/rbs_map.rb +15 -2
- data/lib/solargraph/shell.rb +3 -0
- data/lib/solargraph/source/chain/link.rb +10 -1
- data/lib/solargraph/source/chain.rb +9 -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 +5 -2
- data/lib/solargraph/source_map/clip.rb +1 -1
- data/lib/solargraph/source_map/data.rb +4 -0
- data/lib/solargraph/source_map/mapper.rb +4 -2
- data/lib/solargraph/source_map.rb +21 -14
- 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 +173 -120
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace/config.rb +1 -3
- data/lib/solargraph/workspace/require_paths.rb +98 -0
- data/lib/solargraph/workspace.rb +16 -48
- data/lib/solargraph/yard_map/helpers.rb +29 -1
- data/lib/solargraph/yard_map/mapper/to_constant.rb +5 -5
- data/lib/solargraph/yard_map/mapper/to_method.rb +3 -8
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +7 -7
- data/lib/solargraph/yardoc.rb +16 -3
- data/lib/solargraph.rb +15 -0
- data/rbs/fills/tuple.rbs +2 -3
- 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 +14 -4
- metadata +126 -9
- data/lib/.rubocop.yml +0 -22
@@ -19,8 +19,14 @@ module Solargraph
|
|
19
19
|
require_rubocop(config['version'])
|
20
20
|
options, paths = ::RuboCop::Options.new.parse(args)
|
21
21
|
options[:stdin] = original
|
22
|
-
|
23
|
-
|
22
|
+
|
23
|
+
# Ensure only one instance of RuboCop::Runner is running at
|
24
|
+
# a time - it uses 'chdir' to read config files with ERB,
|
25
|
+
# which can conflict with other chdirs.
|
26
|
+
corrections = Solargraph::CHDIR_MUTEX.synchronize do
|
27
|
+
redirect_stdout do
|
28
|
+
::RuboCop::Runner.new(options, ::RuboCop::ConfigStore.new).run(paths)
|
29
|
+
end
|
24
30
|
end
|
25
31
|
result = options[:stdin]
|
26
32
|
|
@@ -34,6 +40,7 @@ module Solargraph
|
|
34
40
|
private
|
35
41
|
|
36
42
|
# @param corrections [String]
|
43
|
+
# @return [void]
|
37
44
|
def log_corrections(corrections)
|
38
45
|
corrections = corrections&.strip
|
39
46
|
return if corrections&.empty?
|
@@ -45,6 +52,8 @@ module Solargraph
|
|
45
52
|
end
|
46
53
|
end
|
47
54
|
|
55
|
+
# @param file_uri [String]
|
56
|
+
# @return [Hash{String => undefined}]
|
48
57
|
def config_for(file_uri)
|
49
58
|
conf = host.formatter_config(file_uri)
|
50
59
|
return {} unless conf.is_a?(Hash)
|
@@ -52,7 +61,9 @@ module Solargraph
|
|
52
61
|
conf['rubocop'] || {}
|
53
62
|
end
|
54
63
|
|
64
|
+
# @param file_uri [String]
|
55
65
|
# @param config [Hash{String => String}]
|
66
|
+
# @return [Array<String>]
|
56
67
|
def cli_args file_uri, config
|
57
68
|
file = UriHelpers.uri_to_file(file_uri)
|
58
69
|
args = [
|
@@ -71,6 +82,8 @@ module Solargraph
|
|
71
82
|
end
|
72
83
|
|
73
84
|
# @param config [Hash{String => String}]
|
85
|
+
# @sg-ignore
|
86
|
+
# @return [Class<RuboCop::Formatter::BaseFormatter>]
|
74
87
|
def formatter_class(config)
|
75
88
|
if self.class.const_defined?('BlankRubocopFormatter')
|
76
89
|
# @sg-ignore
|
@@ -83,6 +96,7 @@ module Solargraph
|
|
83
96
|
end
|
84
97
|
|
85
98
|
# @param value [Array, String]
|
99
|
+
# @return [String]
|
86
100
|
def cop_list(value)
|
87
101
|
value = value.join(',') if value.respond_to?(:join)
|
88
102
|
return nil if value == '' || !value.is_a?(String)
|
@@ -9,11 +9,13 @@ module Solargraph::LanguageServer::Message::Workspace
|
|
9
9
|
|
10
10
|
private
|
11
11
|
|
12
|
+
# @return [void]
|
12
13
|
def add_folders
|
13
14
|
return unless params['event'] && params['event']['added']
|
14
15
|
host.prepare_folders params['event']['added']
|
15
16
|
end
|
16
17
|
|
18
|
+
# @return [void]
|
17
19
|
def remove_folders
|
18
20
|
return unless params['event'] && params['event']['removed']
|
19
21
|
params['event']['removed'].each do |folder|
|
@@ -39,6 +39,7 @@ module Solargraph
|
|
39
39
|
|
40
40
|
# @param message [String]
|
41
41
|
# @param percentage [Integer]
|
42
|
+
# @return [void]
|
42
43
|
def begin message, percentage
|
43
44
|
@kind = 'begin'
|
44
45
|
@message = message
|
@@ -47,6 +48,7 @@ module Solargraph
|
|
47
48
|
|
48
49
|
# @param message [String]
|
49
50
|
# @param percentage [Integer]
|
51
|
+
# @return [void]
|
50
52
|
def report message, percentage
|
51
53
|
@kind = 'report'
|
52
54
|
@message = message
|
@@ -54,6 +56,7 @@ module Solargraph
|
|
54
56
|
end
|
55
57
|
|
56
58
|
# @param message [String]
|
59
|
+
# @return [void]
|
57
60
|
def finish message
|
58
61
|
@kind = 'end'
|
59
62
|
@message = message
|
@@ -62,6 +65,7 @@ module Solargraph
|
|
62
65
|
end
|
63
66
|
|
64
67
|
# @param host [Solargraph::LanguageServer::Host]
|
68
|
+
# @return [void]
|
65
69
|
def send host
|
66
70
|
return unless host.client_supports_progress? && !finished?
|
67
71
|
|
@@ -91,6 +95,7 @@ module Solargraph
|
|
91
95
|
@status = CREATED
|
92
96
|
end
|
93
97
|
|
98
|
+
# @return [Hash]
|
94
99
|
def build
|
95
100
|
{
|
96
101
|
token: uuid,
|
@@ -101,6 +106,7 @@ module Solargraph
|
|
101
106
|
}
|
102
107
|
end
|
103
108
|
|
109
|
+
# @return [Hash]
|
104
110
|
def build_value
|
105
111
|
case kind
|
106
112
|
when 'begin'
|
@@ -115,6 +121,7 @@ module Solargraph
|
|
115
121
|
end
|
116
122
|
|
117
123
|
# @param host [Host]
|
124
|
+
# @return [void]
|
118
125
|
def keep_alive host
|
119
126
|
mutex.synchronize { @last = Time.now }
|
120
127
|
@keep_alive ||= Thread.new do
|
@@ -127,6 +134,7 @@ module Solargraph
|
|
127
134
|
end
|
128
135
|
end
|
129
136
|
|
137
|
+
# @return [Mutex]
|
130
138
|
def mutex
|
131
139
|
@mutex ||= Mutex.new
|
132
140
|
end
|
data/lib/solargraph/library.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'pathname'
|
4
4
|
require 'observer'
|
5
|
+
require 'open3'
|
5
6
|
|
6
7
|
module Solargraph
|
7
8
|
# A Library handles coordination between a Workspace and an ApiMap.
|
@@ -401,8 +402,8 @@ module Solargraph
|
|
401
402
|
repargs = {}
|
402
403
|
workspace.config.reporters.each do |line|
|
403
404
|
if line == 'all!'
|
404
|
-
Diagnostics.reporters.each do |
|
405
|
-
repargs[reporter] ||= []
|
405
|
+
Diagnostics.reporters.each do |reporter_name|
|
406
|
+
repargs[Diagnostics.reporter(reporter_name)] ||= []
|
406
407
|
end
|
407
408
|
else
|
408
409
|
args = line.split(':').map(&:strip)
|
@@ -436,17 +437,6 @@ module Solargraph
|
|
436
437
|
)
|
437
438
|
end
|
438
439
|
|
439
|
-
# Get an array of foldable ranges for the specified file.
|
440
|
-
#
|
441
|
-
# @deprecated The library should not need to handle folding ranges. The
|
442
|
-
# source itself has all the information it needs.
|
443
|
-
#
|
444
|
-
# @param filename [String]
|
445
|
-
# @return [Array<Range>]
|
446
|
-
def folding_ranges filename
|
447
|
-
read(filename).folding_ranges
|
448
|
-
end
|
449
|
-
|
450
440
|
# Create a library from a directory.
|
451
441
|
#
|
452
442
|
# @param directory [String] The path to be used for the workspace
|
@@ -510,7 +500,7 @@ module Solargraph
|
|
510
500
|
|
511
501
|
private
|
512
502
|
|
513
|
-
# @return [Hash{String =>
|
503
|
+
# @return [Hash{String => Array<String>}]
|
514
504
|
def source_map_external_require_hash
|
515
505
|
@source_map_external_require_hash ||= {}
|
516
506
|
end
|
@@ -518,6 +508,7 @@ module Solargraph
|
|
518
508
|
# @param source_map [SourceMap]
|
519
509
|
# @return [void]
|
520
510
|
def find_external_requires source_map
|
511
|
+
# @type [Set<String>]
|
521
512
|
new_set = source_map.requires.map(&:name).to_set
|
522
513
|
# return if new_set == source_map_external_require_hash[source_map.filename]
|
523
514
|
_filenames = nil
|
@@ -604,16 +595,15 @@ module Solargraph
|
|
604
595
|
else
|
605
596
|
logger.info "Caching #{spec.name} #{spec.version}"
|
606
597
|
Thread.new do
|
607
|
-
cache_pid = Process.spawn(workspace.command_path, 'cache', spec.name, spec.version.to_s)
|
608
598
|
report_cache_progress spec.name, pending
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
599
|
+
_o, e, s = Open3.capture3(workspace.command_path, 'cache', spec.name, spec.version.to_s)
|
600
|
+
if s.success?
|
601
|
+
logger.info "Cached #{spec.name} #{spec.version}"
|
602
|
+
else
|
603
|
+
cache_errors.add spec
|
604
|
+
logger.warn "Error caching gemspec #{spec.name} #{spec.version}"
|
605
|
+
logger.warn e
|
606
|
+
end
|
617
607
|
end_cache_progress
|
618
608
|
catalog
|
619
609
|
sync_catalog
|
@@ -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)
|
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
@@ -27,8 +27,10 @@ module Solargraph
|
|
27
27
|
end
|
28
28
|
|
29
29
|
# @param text [String]
|
30
|
+
# @sg-ignore https://github.com/lsegal/yard/pull/1615
|
30
31
|
# @return [String]
|
31
32
|
def htmlify text
|
33
|
+
# @type [String]
|
32
34
|
YARD::Templates::Helpers::Markup::RDocMarkup.new(text).to_html
|
33
35
|
end
|
34
36
|
|
@@ -70,8 +72,10 @@ module Solargraph
|
|
70
72
|
# @param template [String]
|
71
73
|
# @param layout [Boolean]
|
72
74
|
# @param locals [Hash]
|
75
|
+
# @sg-ignore
|
73
76
|
# @return [String]
|
74
77
|
def render template, layout: true, locals: {}
|
78
|
+
# @type [String]
|
75
79
|
@render_method.call(template, layout: layout, locals: locals)
|
76
80
|
end
|
77
81
|
|
@@ -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)
|
@@ -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
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Solargraph
|
2
2
|
module Parser
|
3
|
-
|
3
|
+
module NodeMethods
|
4
4
|
module_function
|
5
5
|
|
6
6
|
# @abstract
|
@@ -74,7 +74,7 @@ module Solargraph
|
|
74
74
|
|
75
75
|
# @abstract
|
76
76
|
# @param node [Parser::AST::Node]
|
77
|
-
# @return [Hash{
|
77
|
+
# @return [Hash{Symbol => Source::Chain}]
|
78
78
|
def convert_hash node
|
79
79
|
raise NotImplementedError
|
80
80
|
end
|
@@ -13,7 +13,7 @@ module Solargraph
|
|
13
13
|
# @return [Array<Pin::Base>]
|
14
14
|
attr_reader :pins
|
15
15
|
|
16
|
-
# @return [Array<Pin::
|
16
|
+
# @return [Array<Pin::LocalVariable>]
|
17
17
|
attr_reader :locals
|
18
18
|
|
19
19
|
# @param node [Parser::AST::Node]
|
@@ -30,9 +30,12 @@ module Solargraph
|
|
30
30
|
|
31
31
|
# Subclasses should override this method to generate new pins.
|
32
32
|
#
|
33
|
-
# @return [
|
33
|
+
# @return [Boolean] continue processing the next processor of the same node type.
|
34
|
+
# @return [void] In case there is only one processor registered for the node type, it can be void.
|
34
35
|
def process
|
35
36
|
process_children
|
37
|
+
|
38
|
+
true
|
36
39
|
end
|
37
40
|
|
38
41
|
private
|
@@ -64,7 +67,9 @@ module Solargraph
|
|
64
67
|
# @param position [Solargraph::Position]
|
65
68
|
# @return [Pin::Closure, nil]
|
66
69
|
def named_path_pin position
|
67
|
-
pins.select
|
70
|
+
pins.select do |pin|
|
71
|
+
pin.is_a?(Pin::Closure) && pin.path && !pin.path.empty? && pin.location.range.contain?(position)
|
72
|
+
end.last
|
68
73
|
end
|
69
74
|
|
70
75
|
# @todo Candidate for deprecation
|
@@ -72,14 +77,14 @@ module Solargraph
|
|
72
77
|
# @return [Pin::Closure, nil]
|
73
78
|
def block_pin position
|
74
79
|
# @todo determine if this can return a Pin::Block
|
75
|
-
pins.select{|pin| pin.is_a?(Pin::Closure) && pin.location.range.contain?(position)}.last
|
80
|
+
pins.select { |pin| pin.is_a?(Pin::Closure) && pin.location.range.contain?(position) }.last
|
76
81
|
end
|
77
82
|
|
78
83
|
# @todo Candidate for deprecation
|
79
84
|
# @param position [Solargraph::Position]
|
80
85
|
# @return [Pin::Closure, nil]
|
81
86
|
def closure_pin position
|
82
|
-
pins.select{|pin| pin.is_a?(Pin::Closure) && pin.location.range.contain?(position)}.last
|
87
|
+
pins.select { |pin| pin.is_a?(Pin::Closure) && pin.location.range.contain?(position) }.last
|
83
88
|
end
|
84
89
|
end
|
85
90
|
end
|
@@ -9,16 +9,26 @@ module Solargraph
|
|
9
9
|
autoload :Base, 'solargraph/parser/node_processor/base'
|
10
10
|
|
11
11
|
class << self
|
12
|
-
# @type [Hash{Symbol => Class<NodeProcessor::Base
|
12
|
+
# @type [Hash{Symbol => Array<Class<NodeProcessor::Base>>}]
|
13
13
|
@@processors ||= {}
|
14
14
|
|
15
|
-
# Register a processor for a node type.
|
15
|
+
# Register a processor for a node type. You can register multiple processors for the same type.
|
16
|
+
# If a node processor returns true, it will skip the next processor of the same node type.
|
16
17
|
#
|
17
18
|
# @param type [Symbol]
|
18
19
|
# @param cls [Class<NodeProcessor::Base>]
|
19
|
-
# @return [Class<NodeProcessor::Base
|
20
|
+
# @return [Array<Class<NodeProcessor::Base>>]
|
20
21
|
def register type, cls
|
21
|
-
@@processors[type]
|
22
|
+
@@processors[type] ||= []
|
23
|
+
@@processors[type] << cls
|
24
|
+
end
|
25
|
+
|
26
|
+
# @param type [Symbol]
|
27
|
+
# @param cls [Class<NodeProcessor::Base>]
|
28
|
+
#
|
29
|
+
# @return [void]
|
30
|
+
def deregister type, cls
|
31
|
+
@@processors[type].delete(cls)
|
22
32
|
end
|
23
33
|
end
|
24
34
|
|
@@ -36,10 +46,16 @@ module Solargraph
|
|
36
46
|
)
|
37
47
|
end
|
38
48
|
return [pins, locals] unless Parser.is_ast_node?(node)
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
49
|
+
node_processor_classes = @@processors[node.type] || [NodeProcessor::Base]
|
50
|
+
|
51
|
+
node_processor_classes.each do |klass|
|
52
|
+
processor = klass.new(node, region, pins, locals)
|
53
|
+
process_next = processor.process
|
54
|
+
|
55
|
+
break unless process_next
|
56
|
+
end
|
57
|
+
|
58
|
+
[pins, locals]
|
43
59
|
end
|
44
60
|
end
|
45
61
|
end
|
@@ -17,7 +17,7 @@ module Solargraph
|
|
17
17
|
module ClassMethods
|
18
18
|
# @param code [String]
|
19
19
|
# @param filename [String, nil]
|
20
|
-
# @return [Array(Parser::AST::Node, Hash{Integer =>
|
20
|
+
# @return [Array(Parser::AST::Node, Hash{Integer => Solargraph::Parser::Snippet})]
|
21
21
|
def parse_with_comments code, filename = nil
|
22
22
|
node = parse(code, filename)
|
23
23
|
comments = CommentRipper.new(code, filename, 0).parse
|
@@ -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
|
@@ -120,7 +120,7 @@ module Solargraph
|
|
120
120
|
end
|
121
121
|
|
122
122
|
# @param node [Parser::AST::Node]
|
123
|
-
# @return [Hash{
|
123
|
+
# @return [Hash{Symbol => Chain}]
|
124
124
|
def convert_hash node
|
125
125
|
return {} unless Parser.is_ast_node?(node)
|
126
126
|
return convert_hash(node.children[0]) if node.type == :kwsplat
|
@@ -179,6 +179,7 @@ module Solargraph
|
|
179
179
|
node.children[1..-1].each { |child| result.concat call_nodes_from(child) }
|
180
180
|
elsif node.type == :send
|
181
181
|
result.push node
|
182
|
+
result.concat call_nodes_from(node.children.first)
|
182
183
|
node.children[2..-1].each { |child| result.concat call_nodes_from(child) }
|
183
184
|
elsif [:super, :zsuper].include?(node.type)
|
184
185
|
result.push node
|
@@ -232,6 +233,7 @@ module Solargraph
|
|
232
233
|
else
|
233
234
|
source.tree_at(position.line, position.column - 1)
|
234
235
|
end
|
236
|
+
# @type [AST::Node, nil]
|
235
237
|
prev = nil
|
236
238
|
tree.each do |node|
|
237
239
|
if node.type == :send
|
@@ -242,7 +244,7 @@ module Solargraph
|
|
242
244
|
if source.synchronized?
|
243
245
|
return node if source.code[0..offset-1] =~ /\(\s*\z/ && source.code[offset..-1] =~ /^\s*\)/
|
244
246
|
else
|
245
|
-
return node if source.code[0..offset-1] =~ /\([
|
247
|
+
return node if source.code[0..offset-1] =~ /\([^(]*\z/
|
246
248
|
end
|
247
249
|
end
|
248
250
|
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
|