solargraph 0.52.0 → 0.53.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/plugins.yml +40 -0
- data/.github/workflows/rspec.yml +1 -3
- data/.github/workflows/typecheck.yml +34 -0
- data/CHANGELOG.md +30 -0
- data/README.md +13 -16
- data/SPONSORS.md +1 -7
- data/lib/solargraph/api_map/cache.rb +59 -21
- data/lib/solargraph/api_map/store.rb +45 -9
- data/lib/solargraph/api_map.rb +152 -93
- data/lib/solargraph/bench.rb +2 -2
- data/lib/solargraph/cache.rb +29 -5
- data/lib/solargraph/complex_type/type_methods.rb +53 -8
- data/lib/solargraph/complex_type/unique_type.rb +149 -59
- data/lib/solargraph/complex_type.rb +62 -9
- data/lib/solargraph/convention.rb +0 -1
- data/lib/solargraph/converters/dd.rb +5 -0
- data/lib/solargraph/converters/dl.rb +3 -0
- data/lib/solargraph/converters/dt.rb +3 -0
- data/lib/solargraph/diagnostics/rubocop.rb +8 -7
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +1 -0
- data/lib/solargraph/diagnostics/type_check.rb +1 -0
- data/lib/solargraph/diagnostics.rb +2 -2
- data/lib/solargraph/doc_map.rb +146 -0
- data/lib/solargraph/gem_pins.rb +64 -0
- data/lib/solargraph/language_server/host/cataloger.rb +1 -0
- data/lib/solargraph/language_server/host/diagnoser.rb +2 -2
- data/lib/solargraph/language_server/host/dispatch.rb +10 -4
- data/lib/solargraph/language_server/host/message_worker.rb +4 -0
- data/lib/solargraph/language_server/host/sources.rb +7 -4
- data/lib/solargraph/language_server/host.rb +15 -6
- data/lib/solargraph/language_server/message/completion_item/resolve.rb +3 -1
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +13 -1
- data/lib/solargraph/language_server/message/initialize.rb +5 -2
- data/lib/solargraph/language_server/message/text_document/hover.rb +2 -0
- data/lib/solargraph/language_server/message/text_document.rb +0 -1
- data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +5 -0
- data/lib/solargraph/language_server/transport/adapter.rb +16 -1
- data/lib/solargraph/language_server/transport/data_reader.rb +2 -0
- data/lib/solargraph/library.rb +58 -11
- data/lib/solargraph/location.rb +1 -0
- data/lib/solargraph/parser/comment_ripper.rb +3 -0
- data/lib/solargraph/parser/node_methods.rb +47 -8
- data/lib/solargraph/parser/node_processor/base.rb +9 -0
- data/lib/solargraph/parser/{legacy → parser_gem}/class_methods.rb +29 -3
- data/lib/solargraph/parser/{legacy → parser_gem}/flawed_builder.rb +3 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_chainer.rb +42 -34
- data/lib/solargraph/parser/{legacy → parser_gem}/node_methods.rb +201 -29
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/alias_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/args_node.rb +4 -1
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/begin_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/block_node.rb +3 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/casgn_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/cvasgn_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/def_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/defs_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/gvasgn_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/ivasgn_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/lvasgn_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/namespace_node.rb +2 -2
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/orasgn_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/resbody_node.rb +3 -3
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/sclass_node.rb +1 -1
- data/lib/solargraph/parser/{legacy → parser_gem}/node_processors/send_node.rb +2 -2
- data/lib/solargraph/parser/{rubyvm → parser_gem}/node_processors/sym_node.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors.rb +54 -0
- data/lib/solargraph/parser/parser_gem.rb +12 -0
- data/lib/solargraph/parser/snippet.rb +2 -0
- data/lib/solargraph/parser.rb +8 -11
- data/lib/solargraph/pin/base.rb +63 -8
- data/lib/solargraph/pin/base_variable.rb +6 -2
- data/lib/solargraph/pin/block.rb +11 -6
- data/lib/solargraph/pin/closure.rb +17 -2
- data/lib/solargraph/pin/common.rb +7 -3
- data/lib/solargraph/pin/conversions.rb +33 -3
- data/lib/solargraph/pin/documenting.rb +25 -34
- data/lib/solargraph/pin/instance_variable.rb +4 -0
- data/lib/solargraph/pin/local_variable.rb +13 -1
- data/lib/solargraph/pin/method.rb +109 -15
- data/lib/solargraph/pin/namespace.rb +16 -10
- data/lib/solargraph/pin/parameter.rb +41 -10
- data/lib/solargraph/pin/reference/override.rb +2 -2
- data/lib/solargraph/pin/reference.rb +8 -0
- data/lib/solargraph/pin/search.rb +3 -3
- data/lib/solargraph/pin/signature.rb +114 -2
- data/lib/solargraph/pin.rb +0 -1
- data/lib/solargraph/range.rb +2 -2
- data/lib/solargraph/rbs_map/conversions.rb +212 -25
- data/lib/solargraph/rbs_map/core_fills.rb +4 -26
- data/lib/solargraph/rbs_map/core_map.rb +1 -0
- data/lib/solargraph/rbs_map/core_signs.rb +2 -0
- data/lib/solargraph/rbs_map/stdlib_map.rb +2 -8
- data/lib/solargraph/rbs_map.rb +19 -9
- data/lib/solargraph/shell.rb +62 -59
- data/lib/solargraph/source/chain/array.rb +4 -1
- data/lib/solargraph/source/chain/block_symbol.rb +13 -0
- data/lib/solargraph/source/chain/call.rb +95 -26
- data/lib/solargraph/source/chain/constant.rb +15 -1
- data/lib/solargraph/source/chain/if.rb +23 -0
- data/lib/solargraph/source/chain/link.rb +7 -1
- data/lib/solargraph/source/chain/or.rb +1 -1
- data/lib/solargraph/source/chain/z_super.rb +2 -2
- data/lib/solargraph/source/chain.rb +20 -4
- data/lib/solargraph/source/change.rb +3 -0
- data/lib/solargraph/source/cursor.rb +2 -0
- data/lib/solargraph/source/source_chainer.rb +6 -5
- data/lib/solargraph/source.rb +15 -16
- data/lib/solargraph/source_map/clip.rb +11 -7
- data/lib/solargraph/source_map/mapper.rb +10 -0
- data/lib/solargraph/source_map.rb +13 -3
- data/lib/solargraph/type_checker/checks.rb +10 -2
- data/lib/solargraph/type_checker.rb +74 -19
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace/config.rb +8 -6
- data/lib/solargraph/workspace.rb +1 -1
- data/lib/solargraph/yard_map/cache.rb +6 -0
- data/lib/solargraph/yard_map/helpers.rb +1 -1
- data/lib/solargraph/yard_map/mapper/to_method.rb +11 -1
- data/lib/solargraph/yard_map/to_method.rb +11 -4
- data/lib/solargraph/yard_map.rb +0 -292
- data/lib/solargraph/yardoc.rb +52 -0
- data/lib/solargraph.rb +4 -1
- data/solargraph.gemspec +2 -2
- metadata +35 -57
- data/lib/solargraph/api_map/bundler_methods.rb +0 -22
- data/lib/solargraph/documentor.rb +0 -76
- data/lib/solargraph/parser/legacy/node_processors/alias_node.rb +0 -23
- data/lib/solargraph/parser/legacy/node_processors/begin_node.rb +0 -15
- data/lib/solargraph/parser/legacy/node_processors/sym_node.rb +0 -18
- data/lib/solargraph/parser/legacy/node_processors.rb +0 -55
- data/lib/solargraph/parser/legacy.rb +0 -12
- data/lib/solargraph/parser/rubyvm/class_methods.rb +0 -151
- data/lib/solargraph/parser/rubyvm/node_chainer.rb +0 -163
- data/lib/solargraph/parser/rubyvm/node_methods.rb +0 -317
- data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +0 -85
- data/lib/solargraph/parser/rubyvm/node_processors/block_node.rb +0 -42
- data/lib/solargraph/parser/rubyvm/node_processors/casgn_node.rb +0 -33
- data/lib/solargraph/parser/rubyvm/node_processors/cvasgn_node.rb +0 -23
- data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +0 -75
- data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +0 -68
- data/lib/solargraph/parser/rubyvm/node_processors/gvasgn_node.rb +0 -23
- data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +0 -38
- data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +0 -39
- data/lib/solargraph/parser/rubyvm/node_processors/lit_node.rb +0 -20
- data/lib/solargraph/parser/rubyvm/node_processors/lvasgn_node.rb +0 -27
- data/lib/solargraph/parser/rubyvm/node_processors/namespace_node.rb +0 -39
- data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +0 -26
- data/lib/solargraph/parser/rubyvm/node_processors/orasgn_node.rb +0 -15
- data/lib/solargraph/parser/rubyvm/node_processors/resbody_node.rb +0 -51
- data/lib/solargraph/parser/rubyvm/node_processors/sclass_node.rb +0 -32
- data/lib/solargraph/parser/rubyvm/node_processors/scope_node.rb +0 -15
- data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +0 -279
- data/lib/solargraph/parser/rubyvm/node_processors.rb +0 -64
- data/lib/solargraph/parser/rubyvm/node_wrapper.rb +0 -47
- data/lib/solargraph/parser/rubyvm.rb +0 -40
data/lib/solargraph/library.rb
CHANGED
@@ -159,7 +159,7 @@ module Solargraph
|
|
159
159
|
# @param filename [String] The file to analyze
|
160
160
|
# @param line [Integer] The zero-based line number
|
161
161
|
# @param column [Integer] The zero-based column number
|
162
|
-
# @return [SourceMap::Completion]
|
162
|
+
# @return [SourceMap::Completion, nil]
|
163
163
|
# @todo Take a Location instead of filename/line/column
|
164
164
|
def completions_at filename, line, column
|
165
165
|
position = Position.new(line, column)
|
@@ -175,7 +175,7 @@ module Solargraph
|
|
175
175
|
# @param filename [String] The file to analyze
|
176
176
|
# @param line [Integer] The zero-based line number
|
177
177
|
# @param column [Integer] The zero-based column number
|
178
|
-
# @return [Array<Solargraph::Pin::Base
|
178
|
+
# @return [Array<Solargraph::Pin::Base>, nil]
|
179
179
|
# @todo Take filename/position instead of filename/line/column
|
180
180
|
def definitions_at filename, line, column
|
181
181
|
position = Position.new(line, column)
|
@@ -205,7 +205,7 @@ module Solargraph
|
|
205
205
|
# @param filename [String] The file to analyze
|
206
206
|
# @param line [Integer] The zero-based line number
|
207
207
|
# @param column [Integer] The zero-based column number
|
208
|
-
# @return [Array<Solargraph::Pin::Base
|
208
|
+
# @return [Array<Solargraph::Pin::Base>, nil]
|
209
209
|
# @todo Take filename/position instead of filename/line/column
|
210
210
|
def type_definitions_at filename, line, column
|
211
211
|
position = Position.new(line, column)
|
@@ -283,6 +283,7 @@ module Solargraph
|
|
283
283
|
return if map.nil?
|
284
284
|
pin = map.requires.select { |p| p.location.range.contain?(location.range.start) }.first
|
285
285
|
return nil if pin.nil?
|
286
|
+
# @param full [String]
|
286
287
|
return_if_match = proc do |full|
|
287
288
|
if source_map_hash.key?(full)
|
288
289
|
return Location.new(full, Solargraph::Range.from_to(0, 0, 0, 0))
|
@@ -301,13 +302,13 @@ module Solargraph
|
|
301
302
|
# Get an array of pins that match a path.
|
302
303
|
#
|
303
304
|
# @param path [String]
|
304
|
-
# @return [
|
305
|
+
# @return [Enumerable<Solargraph::Pin::Base>]
|
305
306
|
def get_path_pins path
|
306
307
|
api_map.get_path_suggestions(path)
|
307
308
|
end
|
308
309
|
|
309
310
|
# @param query [String]
|
310
|
-
# @return [
|
311
|
+
# @return [Enumerable<YARD::CodeObjects::Base>]
|
311
312
|
def document query
|
312
313
|
api_map.document query
|
313
314
|
end
|
@@ -339,11 +340,12 @@ module Solargraph
|
|
339
340
|
end
|
340
341
|
|
341
342
|
# @param path [String]
|
342
|
-
# @return [
|
343
|
+
# @return [Enumerable<Solargraph::Pin::Base>]
|
343
344
|
def path_pins path
|
344
345
|
api_map.get_path_suggestions(path)
|
345
346
|
end
|
346
347
|
|
348
|
+
# @return [Array<SourceMap>]
|
347
349
|
def source_maps
|
348
350
|
source_map_hash.values
|
349
351
|
end
|
@@ -400,14 +402,19 @@ module Solargraph
|
|
400
402
|
end
|
401
403
|
end
|
402
404
|
|
405
|
+
# @return [void]
|
403
406
|
private def catalog_inlock
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
407
|
+
return if synchronized?
|
408
|
+
|
409
|
+
logger.info "Cataloging #{workspace.directory.empty? ? 'generic workspace' : workspace.directory}"
|
410
|
+
api_map.catalog bench
|
411
|
+
@synchronized = true
|
412
|
+
logger.info "Catalog complete (#{api_map.source_maps.length} files, #{api_map.pins.length} pins)"
|
413
|
+
logger.info "#{api_map.uncached_gemspecs.length} uncached gemspecs"
|
414
|
+
cache_next_gemspec
|
409
415
|
end
|
410
416
|
|
417
|
+
# @return [Bench]
|
411
418
|
def bench
|
412
419
|
Bench.new(
|
413
420
|
source_maps: source_map_hash.values,
|
@@ -452,6 +459,7 @@ module Solargraph
|
|
452
459
|
result
|
453
460
|
end
|
454
461
|
|
462
|
+
# @return [Hash{String => SourceMap}]
|
455
463
|
def source_map_hash
|
456
464
|
@source_map_hash ||= {}
|
457
465
|
end
|
@@ -460,6 +468,7 @@ module Solargraph
|
|
460
468
|
(workspace.filenames - source_map_hash.keys).empty?
|
461
469
|
end
|
462
470
|
|
471
|
+
# @return [SourceMap, Boolean]
|
463
472
|
def next_map
|
464
473
|
return false if mapped?
|
465
474
|
mutex.synchronize do
|
@@ -476,6 +485,7 @@ module Solargraph
|
|
476
485
|
end
|
477
486
|
end
|
478
487
|
|
488
|
+
# @return [self]
|
479
489
|
def map!
|
480
490
|
workspace.sources.each do |src|
|
481
491
|
source_map_hash[src.filename] = Solargraph::SourceMap.map(src)
|
@@ -484,21 +494,25 @@ module Solargraph
|
|
484
494
|
self
|
485
495
|
end
|
486
496
|
|
497
|
+
# @return [Array<Solargraph::Pin::Base>]
|
487
498
|
def pins
|
488
499
|
@pins ||= []
|
489
500
|
end
|
490
501
|
|
502
|
+
# @return [Set<String>]
|
491
503
|
def external_requires
|
492
504
|
@external_requires ||= source_map_external_require_hash.values.flatten.to_set
|
493
505
|
end
|
494
506
|
|
495
507
|
private
|
496
508
|
|
509
|
+
# @return [Hash{String => Set<String>}]
|
497
510
|
def source_map_external_require_hash
|
498
511
|
@source_map_external_require_hash ||= {}
|
499
512
|
end
|
500
513
|
|
501
514
|
# @param source_map [SourceMap]
|
515
|
+
# @return [void]
|
502
516
|
def find_external_requires source_map
|
503
517
|
new_set = source_map.requires.map(&:name).to_set
|
504
518
|
# return if new_set == source_map_external_require_hash[source_map.filename]
|
@@ -537,6 +551,9 @@ module Solargraph
|
|
537
551
|
workspace.source(filename)
|
538
552
|
end
|
539
553
|
|
554
|
+
# @param filename [String]
|
555
|
+
# @param error [FileNotFoundError]
|
556
|
+
# @return [nil]
|
540
557
|
def handle_file_not_found filename, error
|
541
558
|
if workspace.source(filename)
|
542
559
|
Solargraph.logger.debug "#{filename} is not cataloged in the ApiMap"
|
@@ -546,6 +563,8 @@ module Solargraph
|
|
546
563
|
end
|
547
564
|
end
|
548
565
|
|
566
|
+
# @param source [Source]
|
567
|
+
# @return [void]
|
549
568
|
def maybe_map source
|
550
569
|
return unless source
|
551
570
|
return unless @current == source || workspace.has_file?(source.filename)
|
@@ -570,5 +589,33 @@ module Solargraph
|
|
570
589
|
@synchronized = false
|
571
590
|
end
|
572
591
|
end
|
592
|
+
|
593
|
+
# @return [Set<Gem::Specification>]
|
594
|
+
def cache_errors
|
595
|
+
@cache_errors ||= Set.new
|
596
|
+
end
|
597
|
+
|
598
|
+
# @return [void]
|
599
|
+
def cache_next_gemspec
|
600
|
+
return if @cache_pid
|
601
|
+
spec = api_map.uncached_gemspecs.find { |spec| !cache_errors.include?(spec)}
|
602
|
+
return unless spec
|
603
|
+
|
604
|
+
logger.info "Caching #{spec.name} #{spec.version}"
|
605
|
+
Thread.new do
|
606
|
+
@cache_pid = Process.spawn('solargraph', 'cache', spec.name, spec.version.to_s)
|
607
|
+
Process.wait(@cache_pid)
|
608
|
+
logger.info "Cached #{spec.name} #{spec.version}"
|
609
|
+
@synchronized = false
|
610
|
+
rescue Errno::EINVAL => e
|
611
|
+
logger.info "Cached #{spec.name} #{spec.version} with EINVAL"
|
612
|
+
@synchronized = false
|
613
|
+
rescue StandardError => e
|
614
|
+
cache_errors.add spec
|
615
|
+
Solargraph.logger.warn "Error caching gemspec #{spec.name} #{spec.version}: [#{e.class}] #{e.message}"
|
616
|
+
ensure
|
617
|
+
@cache_pid = nil
|
618
|
+
end
|
619
|
+
end
|
573
620
|
end
|
574
621
|
end
|
data/lib/solargraph/location.rb
CHANGED
@@ -3,39 +3,78 @@ module Solargraph
|
|
3
3
|
class NodeMethods
|
4
4
|
module_function
|
5
5
|
|
6
|
+
# @abstract
|
7
|
+
# @param node [Parser::AST::Node]
|
8
|
+
# @return [String]
|
6
9
|
def unpack_name node
|
7
10
|
raise NotImplementedError
|
8
11
|
end
|
9
12
|
|
10
|
-
|
13
|
+
# @abstract
|
14
|
+
# @todo Temporarily here for testing. Move to Solargraph::Parser.
|
15
|
+
# @param node [Parser::AST::Node]
|
16
|
+
# @return [Array<Parser::AST::Node>]
|
17
|
+
def call_nodes_from node
|
11
18
|
raise NotImplementedError
|
12
19
|
end
|
13
20
|
|
14
|
-
|
21
|
+
# Find all the nodes within the provided node that potentially return a
|
22
|
+
# value.
|
23
|
+
#
|
24
|
+
# The node parameter typically represents a method's logic, e.g., the
|
25
|
+
# second child (after the :args node) of a :def node. A simple one-line
|
26
|
+
# method would typically return itself, while a node with conditions
|
27
|
+
# would return the resulting node from each conditional branch. Nodes
|
28
|
+
# that follow a :return node are assumed to be unreachable. Nil values
|
29
|
+
# are converted to nil node types.
|
30
|
+
#
|
31
|
+
# @abstract
|
32
|
+
# @param node [Parser::AST::Node]
|
33
|
+
# @return [Array<Parser::AST::Node>]
|
34
|
+
def returns_from_method_body node
|
15
35
|
raise NotImplementedError
|
16
36
|
end
|
17
37
|
|
18
|
-
|
38
|
+
# @abstract
|
39
|
+
# @param node [Parser::AST::Node]
|
40
|
+
#
|
41
|
+
# @return [Array<Parser::AST::Node>]
|
42
|
+
def const_nodes_from node
|
19
43
|
raise NotImplementedError
|
20
44
|
end
|
21
45
|
|
22
|
-
|
46
|
+
# @abstract
|
47
|
+
# @param cursor [Solargraph::Source::Cursor]
|
48
|
+
# @return [Parser::AST::Node, nil]
|
49
|
+
def find_recipient_node cursor
|
23
50
|
raise NotImplementedError
|
24
51
|
end
|
25
52
|
|
26
|
-
|
53
|
+
# @abstract
|
54
|
+
# @param node [Parser::AST::Node]
|
55
|
+
# @return [Array<AST::Node>] low-level value nodes in
|
56
|
+
# value position. Does not include explicit return
|
57
|
+
# statements
|
58
|
+
def value_position_nodes_only(node)
|
27
59
|
raise NotImplementedError
|
28
60
|
end
|
29
61
|
|
30
|
-
# @
|
31
|
-
|
62
|
+
# @abstract
|
63
|
+
# @param nodes [Enumerable<Parser::AST::Node>]
|
64
|
+
def any_splatted_call?(nodes)
|
32
65
|
raise NotImplementedError
|
33
66
|
end
|
34
67
|
|
35
|
-
|
68
|
+
# @abstract
|
69
|
+
# @param node [Parser::AST::Node]
|
70
|
+
# @return [void]
|
71
|
+
def process node
|
36
72
|
raise NotImplementedError
|
37
73
|
end
|
38
74
|
|
75
|
+
# @abstract
|
76
|
+
# @param node [Parser::AST::Node]
|
77
|
+
# @return [Hash{Parser::AST::Node => Chain}]
|
39
78
|
def convert_hash node
|
40
79
|
raise NotImplementedError
|
41
80
|
end
|
@@ -19,6 +19,7 @@ module Solargraph
|
|
19
19
|
# @param node [Parser::AST::Node]
|
20
20
|
# @param region [Region]
|
21
21
|
# @param pins [Array<Pin::Base>]
|
22
|
+
# @param locals [Array<Pin::LocalVariable>]
|
22
23
|
def initialize node, region, pins, locals
|
23
24
|
@node = node
|
24
25
|
@region = region
|
@@ -54,20 +55,28 @@ module Solargraph
|
|
54
55
|
Location.new(region.filename, range)
|
55
56
|
end
|
56
57
|
|
58
|
+
# @param node [Parser::AST::Node]
|
59
|
+
# @return [String, nil]
|
57
60
|
def comments_for(node)
|
58
61
|
region.source.comments_for(node)
|
59
62
|
end
|
60
63
|
|
64
|
+
# @param position [Solargraph::Position]
|
65
|
+
# @return [Pin::Base, nil]
|
61
66
|
def named_path_pin position
|
62
67
|
pins.select{|pin| pin.is_a?(Pin::Closure) && pin.path && !pin.path.empty? && pin.location.range.contain?(position)}.last
|
63
68
|
end
|
64
69
|
|
65
70
|
# @todo Candidate for deprecation
|
71
|
+
# @param position [Solargraph::Position]
|
72
|
+
# @return [Pin::Closure, nil]
|
66
73
|
def block_pin position
|
67
74
|
pins.select{|pin| pin.is_a?(Pin::Closure) && pin.location.range.contain?(position)}.last
|
68
75
|
end
|
69
76
|
|
70
77
|
# @todo Candidate for deprecation
|
78
|
+
# @param position [Solargraph::Position]
|
79
|
+
# @return [Pin::Closure, nil]
|
71
80
|
def closure_pin position
|
72
81
|
pins.select{|pin| pin.is_a?(Pin::Closure) && pin.location.range.contain?(position)}.last
|
73
82
|
end
|
@@ -1,12 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'parser/current'
|
4
|
+
require 'parser/source/buffer'
|
2
5
|
|
3
6
|
module Solargraph
|
4
7
|
module Parser
|
5
|
-
module
|
8
|
+
module ParserGem
|
6
9
|
module ClassMethods
|
7
10
|
# @param code [String]
|
8
11
|
# @param filename [String, nil]
|
9
|
-
# @return [Array(Parser::AST::Node,
|
12
|
+
# @return [Array(Parser::AST::Node, Hash{Integer => String})]
|
10
13
|
def parse_with_comments code, filename = nil
|
11
14
|
buffer = ::Parser::Source::Buffer.new(filename, 0)
|
12
15
|
buffer.source = code
|
@@ -29,7 +32,7 @@ module Solargraph
|
|
29
32
|
raise Parser::SyntaxError, e.message
|
30
33
|
end
|
31
34
|
|
32
|
-
# @return [Parser::Base]
|
35
|
+
# @return [::Parser::Base]
|
33
36
|
def parser
|
34
37
|
# @todo Consider setting an instance variable. We might not need to
|
35
38
|
# recreate the parser every time we use it.
|
@@ -39,19 +42,30 @@ module Solargraph
|
|
39
42
|
parser
|
40
43
|
end
|
41
44
|
|
45
|
+
# @param source [Source]
|
46
|
+
# @return [Array(Array<Pin::Base>, Array<Pin::Base>)]
|
42
47
|
def map source
|
43
48
|
NodeProcessor.process(source.node, Region.new(source: source))
|
44
49
|
end
|
45
50
|
|
51
|
+
# @param node [Parser::AST::Node]
|
52
|
+
# @return [Array<Parser::AST::Node>]
|
46
53
|
def returns_from node
|
47
54
|
NodeMethods.returns_from(node)
|
48
55
|
end
|
49
56
|
|
57
|
+
# @param source [Source]
|
58
|
+
# @param name [String]
|
59
|
+
# @return [Array<Location>]
|
50
60
|
def references source, name
|
51
61
|
if name.end_with?("=")
|
52
62
|
reg = /#{Regexp.escape name[0..-2]}\s*=/
|
63
|
+
# @param code [String]
|
64
|
+
# @param offset [Integer]
|
53
65
|
extract_offset = ->(code, offset) { reg.match(code, offset).offset(0) }
|
54
66
|
else
|
67
|
+
# @param code [String]
|
68
|
+
# @param offset [Integer]
|
55
69
|
extract_offset = ->(code, offset) { [soff = code.index(name, offset), soff + name.length] }
|
56
70
|
end
|
57
71
|
inner_node_references(name, source.node).map do |n|
|
@@ -80,36 +94,48 @@ module Solargraph
|
|
80
94
|
result
|
81
95
|
end
|
82
96
|
|
97
|
+
# @return [Source::Chain]
|
83
98
|
def chain *args
|
84
99
|
NodeChainer.chain *args
|
85
100
|
end
|
86
101
|
|
102
|
+
# @return [Source::Chain]
|
87
103
|
def chain_string *args
|
88
104
|
NodeChainer.load_string *args
|
89
105
|
end
|
90
106
|
|
107
|
+
# @return [Array(Array<Pin::Base>, Array<Pin::Base>)]
|
91
108
|
def process_node *args
|
92
109
|
Solargraph::Parser::NodeProcessor.process *args
|
93
110
|
end
|
94
111
|
|
112
|
+
# @param node [Parser::AST::Node]
|
113
|
+
# @return [String, nil]
|
95
114
|
def infer_literal_node_type node
|
96
115
|
NodeMethods.infer_literal_node_type node
|
97
116
|
end
|
98
117
|
|
118
|
+
# @return [void]
|
99
119
|
def version
|
100
120
|
parser.version
|
101
121
|
end
|
102
122
|
|
123
|
+
# @param node [BasicObject]
|
124
|
+
# @return [Boolean]
|
103
125
|
def is_ast_node? node
|
104
126
|
node.is_a?(::Parser::AST::Node)
|
105
127
|
end
|
106
128
|
|
129
|
+
# @param node [Parser::AST::Node]
|
130
|
+
# @return [Range]
|
107
131
|
def node_range node
|
108
132
|
st = Position.new(node.loc.line, node.loc.column)
|
109
133
|
en = Position.new(node.loc.last_line, node.loc.last_column)
|
110
134
|
Range.new(st, en)
|
111
135
|
end
|
112
136
|
|
137
|
+
# @param node [Parser::AST::Node]
|
138
|
+
# @return [Array<Range>]
|
113
139
|
def string_ranges node
|
114
140
|
return [] unless is_ast_node?(node)
|
115
141
|
result = []
|
@@ -2,11 +2,13 @@
|
|
2
2
|
|
3
3
|
module Solargraph
|
4
4
|
module Parser
|
5
|
-
module
|
5
|
+
module ParserGem
|
6
6
|
# A custom builder for source parsers that ignores character encoding
|
7
7
|
# issues in literal strings.
|
8
8
|
#
|
9
9
|
class FlawedBuilder < ::Parser::Builders::Default
|
10
|
+
# @param token [::Parser::AST::Node]
|
11
|
+
# @return [String]
|
10
12
|
def string_value(token)
|
11
13
|
value(token)
|
12
14
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Solargraph
|
4
4
|
module Parser
|
5
|
-
module
|
5
|
+
module ParserGem
|
6
6
|
# A factory for generating chains from nodes.
|
7
7
|
#
|
8
8
|
class NodeChainer
|
@@ -11,10 +11,11 @@ module Solargraph
|
|
11
11
|
|
12
12
|
# @param node [Parser::AST::Node]
|
13
13
|
# @param filename [String, nil]
|
14
|
-
|
14
|
+
# @param parent [Parser::AST::Node, nil]
|
15
|
+
def initialize node, filename = nil, parent = nil
|
15
16
|
@node = node
|
16
17
|
@filename = filename
|
17
|
-
@
|
18
|
+
@parent = parent
|
18
19
|
end
|
19
20
|
|
20
21
|
# @return [Source::Chain]
|
@@ -26,9 +27,10 @@ module Solargraph
|
|
26
27
|
class << self
|
27
28
|
# @param node [Parser::AST::Node]
|
28
29
|
# @param filename [String, nil]
|
30
|
+
# @param parent [Parser::AST::Node, nil]
|
29
31
|
# @return [Source::Chain]
|
30
|
-
def chain node, filename = nil,
|
31
|
-
NodeChainer.new(node, filename,
|
32
|
+
def chain node, filename = nil, parent = nil
|
33
|
+
NodeChainer.new(node, filename, parent).chain
|
32
34
|
end
|
33
35
|
|
34
36
|
# @param code [String]
|
@@ -48,55 +50,42 @@ module Solargraph
|
|
48
50
|
def generate_links n
|
49
51
|
return [] unless n.is_a?(::Parser::AST::Node)
|
50
52
|
return generate_links(n.children[0]) if n.type == :splat
|
53
|
+
# @type [Array<Chain::Link>]
|
51
54
|
result = []
|
52
55
|
if n.type == :block
|
53
|
-
@
|
54
|
-
result.concat generate_links(n.children[0])
|
55
|
-
@in_block -= 1
|
56
|
+
result.concat NodeChainer.chain(n.children[0], @filename, n).links
|
56
57
|
elsif n.type == :send
|
57
58
|
if n.children[0].is_a?(::Parser::AST::Node)
|
58
59
|
result.concat generate_links(n.children[0])
|
59
|
-
|
60
|
-
n.children[2..-1].each do |c|
|
61
|
-
args.push NodeChainer.chain(c)
|
62
|
-
end
|
63
|
-
result.push Chain::Call.new(n.children[1].to_s, args, @in_block > 0 || block_passed?(n))
|
60
|
+
result.push Chain::Call.new(n.children[1].to_s, node_args(n), passed_block(n))
|
64
61
|
elsif n.children[0].nil?
|
65
62
|
args = []
|
66
63
|
n.children[2..-1].each do |c|
|
67
|
-
args.push NodeChainer.chain(c)
|
64
|
+
args.push NodeChainer.chain(c, @filename, n)
|
68
65
|
end
|
69
|
-
result.push Chain::Call.new(n.children[1].to_s,
|
66
|
+
result.push Chain::Call.new(n.children[1].to_s, node_args(n), passed_block(n))
|
70
67
|
else
|
71
68
|
raise "No idea what to do with #{n}"
|
72
69
|
end
|
73
70
|
elsif n.type == :csend
|
74
71
|
if n.children[0].is_a?(::Parser::AST::Node)
|
75
72
|
result.concat generate_links(n.children[0])
|
76
|
-
|
77
|
-
n.children[2..-1].each do |c|
|
78
|
-
args.push NodeChainer.chain(c)
|
79
|
-
end
|
80
|
-
result.push Chain::QCall.new(n.children[1].to_s, args, @in_block > 0 || block_passed?(n))
|
73
|
+
result.push Chain::QCall.new(n.children[1].to_s, node_args(n))
|
81
74
|
elsif n.children[0].nil?
|
82
|
-
|
83
|
-
n.children[2..-1].each do |c|
|
84
|
-
args.push NodeChainer.chain(c)
|
85
|
-
end
|
86
|
-
result.push Chain::QCall.new(n.children[1].to_s, args, @in_block > 0 || block_passed?(n))
|
75
|
+
result.push Chain::QCall.new(n.children[1].to_s, node_args(n))
|
87
76
|
else
|
88
77
|
raise "No idea what to do with #{n}"
|
89
78
|
end
|
90
79
|
elsif n.type == :self
|
91
80
|
result.push Chain::Head.new('self')
|
92
81
|
elsif n.type == :zsuper
|
93
|
-
result.push Chain::ZSuper.new('super'
|
82
|
+
result.push Chain::ZSuper.new('super')
|
94
83
|
elsif n.type == :super
|
95
|
-
args = n.children.map { |c| NodeChainer.chain(c) }
|
96
|
-
result.push Chain::Call.new('super', args
|
84
|
+
args = n.children.map { |c| NodeChainer.chain(c, @filename, n) }
|
85
|
+
result.push Chain::Call.new('super', args)
|
97
86
|
elsif n.type == :yield
|
98
|
-
args = n.children.map { |c| NodeChainer.chain(c) }
|
99
|
-
result.push Chain::Call.new('yield', args
|
87
|
+
args = n.children.map { |c| NodeChainer.chain(c, @filename, n) }
|
88
|
+
result.push Chain::Call.new('yield', args)
|
100
89
|
elsif n.type == :const
|
101
90
|
const = unpack_name(n)
|
102
91
|
result.push Chain::Constant.new(const)
|
@@ -116,7 +105,9 @@ module Solargraph
|
|
116
105
|
elsif n.type == :and
|
117
106
|
result.concat generate_links(n.children.last)
|
118
107
|
elsif n.type == :or
|
119
|
-
result.push Chain::Or.new([NodeChainer.chain(n.children[0], @filename), NodeChainer.chain(n.children[1], @filename)])
|
108
|
+
result.push Chain::Or.new([NodeChainer.chain(n.children[0], @filename), NodeChainer.chain(n.children[1], @filename, n)])
|
109
|
+
elsif n.type == :if
|
110
|
+
result.push Chain::If.new([NodeChainer.chain(n.children[1], @filename), NodeChainer.chain(n.children[2], @filename, n)])
|
120
111
|
elsif [:begin, :kwbegin].include?(n.type)
|
121
112
|
result.concat generate_links(n.children.last)
|
122
113
|
elsif n.type == :block_pass
|
@@ -126,7 +117,11 @@ module Solargraph
|
|
126
117
|
# added in Ruby 3.1 - https://bugs.ruby-lang.org/issues/11256
|
127
118
|
result.push Chain::BlockVariable.new(nil)
|
128
119
|
else
|
129
|
-
|
120
|
+
if block_variable_name_node.type == :sym
|
121
|
+
result.push Chain::BlockSymbol.new("#{block_variable_name_node.children[0].to_s}")
|
122
|
+
else
|
123
|
+
result.push Chain::BlockVariable.new("&#{block_variable_name_node.children[0].to_s}")
|
124
|
+
end
|
130
125
|
end
|
131
126
|
elsif n.type == :hash
|
132
127
|
result.push Chain::Hash.new('::Hash', hash_is_splatted?(n))
|
@@ -140,6 +135,7 @@ module Solargraph
|
|
140
135
|
result
|
141
136
|
end
|
142
137
|
|
138
|
+
# @param node [Parser::AST::Node]
|
143
139
|
def hash_is_splatted? node
|
144
140
|
return false unless Parser.is_ast_node?(node) && node.type == :hash
|
145
141
|
return false unless Parser.is_ast_node?(node.children.last) && node.children.last.type == :kwsplat
|
@@ -147,8 +143,20 @@ module Solargraph
|
|
147
143
|
true
|
148
144
|
end
|
149
145
|
|
150
|
-
|
151
|
-
|
146
|
+
# @param node [Parser::AST::Node]
|
147
|
+
# @return [Source::Chain, nil]
|
148
|
+
def passed_block node
|
149
|
+
return unless node == @node && @parent&.type == :block
|
150
|
+
|
151
|
+
NodeChainer.chain(@parent.children[2], @filename)
|
152
|
+
end
|
153
|
+
|
154
|
+
# @param node [Parser::AST::Node]
|
155
|
+
# @return [Array<Source::Chain>]
|
156
|
+
def node_args node
|
157
|
+
node.children[2..-1].map do |child|
|
158
|
+
NodeChainer.chain(child, @filename, node)
|
159
|
+
end
|
152
160
|
end
|
153
161
|
end
|
154
162
|
end
|