solargraph 0.54.0 → 0.54.5
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/CHANGELOG.md +45 -0
- data/lib/solargraph/api_map/cache.rb +10 -1
- data/lib/solargraph/api_map/index.rb +167 -0
- data/lib/solargraph/api_map/store.rb +72 -121
- data/lib/solargraph/api_map.rb +94 -36
- data/lib/solargraph/bench.rb +17 -1
- data/lib/solargraph/complex_type/type_methods.rb +17 -11
- data/lib/solargraph/complex_type/unique_type.rb +93 -10
- data/lib/solargraph/complex_type.rb +68 -18
- data/lib/solargraph/convention.rb +1 -0
- data/lib/solargraph/doc_map.rb +1 -0
- data/lib/solargraph/equality.rb +33 -0
- data/lib/solargraph/language_server/host/message_worker.rb +48 -5
- data/lib/solargraph/language_server/host.rb +12 -11
- data/lib/solargraph/language_server/message/base.rb +19 -12
- data/lib/solargraph/language_server/message/initialize.rb +3 -1
- data/lib/solargraph/language_server/message/text_document/completion.rb +0 -3
- data/lib/solargraph/language_server/message/text_document/definition.rb +3 -3
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +3 -3
- data/lib/solargraph/language_server/message/text_document/formatting.rb +4 -0
- data/lib/solargraph/language_server/message/text_document/hover.rb +1 -1
- data/lib/solargraph/language_server/message/text_document/type_definition.rb +3 -3
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +2 -2
- data/lib/solargraph/language_server/progress.rb +19 -2
- data/lib/solargraph/library.rb +31 -41
- data/lib/solargraph/location.rb +21 -1
- data/lib/solargraph/parser/node_methods.rb +1 -1
- data/lib/solargraph/parser/node_processor.rb +1 -0
- data/lib/solargraph/parser/parser_gem/class_methods.rb +2 -6
- data/lib/solargraph/parser/parser_gem/node_methods.rb +3 -3
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +23 -19
- data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +8 -2
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +1 -1
- data/lib/solargraph/parser.rb +2 -5
- data/lib/solargraph/pin/base.rb +41 -17
- data/lib/solargraph/pin/base_variable.rb +4 -3
- data/lib/solargraph/pin/block.rb +6 -26
- data/lib/solargraph/pin/callable.rb +147 -0
- data/lib/solargraph/pin/closure.rb +8 -3
- data/lib/solargraph/pin/common.rb +2 -6
- data/lib/solargraph/pin/conversions.rb +3 -2
- data/lib/solargraph/pin/instance_variable.rb +2 -2
- data/lib/solargraph/pin/method.rb +57 -31
- data/lib/solargraph/pin/namespace.rb +5 -5
- data/lib/solargraph/pin/parameter.rb +11 -12
- data/lib/solargraph/pin/proxy_type.rb +1 -1
- data/lib/solargraph/pin/signature.rb +3 -129
- data/lib/solargraph/pin.rb +4 -1
- data/lib/solargraph/position.rb +7 -0
- data/lib/solargraph/range.rb +9 -4
- data/lib/solargraph/rbs_map/conversions.rb +77 -38
- data/lib/solargraph/rbs_map/core_fills.rb +6 -6
- data/lib/solargraph/rbs_map.rb +1 -0
- data/lib/solargraph/shell.rb +19 -2
- data/lib/solargraph/source/chain/array.rb +7 -6
- data/lib/solargraph/source/chain/block_symbol.rb +1 -1
- data/lib/solargraph/source/chain/block_variable.rb +1 -1
- data/lib/solargraph/source/chain/call.rb +90 -55
- data/lib/solargraph/source/chain/hash.rb +5 -0
- data/lib/solargraph/source/chain/if.rb +5 -0
- data/lib/solargraph/source/chain/link.rb +26 -5
- data/lib/solargraph/source/chain/literal.rb +5 -0
- data/lib/solargraph/source/chain/or.rb +1 -1
- data/lib/solargraph/source/chain.rb +68 -30
- data/lib/solargraph/source/cursor.rb +3 -2
- data/lib/solargraph/source.rb +104 -86
- data/lib/solargraph/source_map/clip.rb +5 -5
- data/lib/solargraph/source_map/data.rb +30 -0
- data/lib/solargraph/source_map.rb +28 -16
- data/lib/solargraph/type_checker/rules.rb +6 -1
- data/lib/solargraph/type_checker.rb +15 -15
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/views/environment.erb +3 -5
- data/lib/solargraph/workspace/config.rb +7 -3
- data/lib/solargraph/workspace.rb +1 -1
- data/lib/solargraph/yard_map/mapper/to_constant.rb +1 -0
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -0
- data/lib/solargraph/yard_map/mapper.rb +1 -0
- data/lib/solargraph/yardoc.rb +1 -1
- data/lib/solargraph.rb +1 -0
- data/solargraph.gemspec +5 -5
- metadata +29 -25
data/lib/solargraph/library.rb
CHANGED
@@ -27,11 +27,11 @@ module Solargraph
|
|
27
27
|
def initialize workspace = Solargraph::Workspace.new, name = nil
|
28
28
|
@workspace = workspace
|
29
29
|
@name = name
|
30
|
-
@threads = []
|
31
30
|
# @type [Integer, nil]
|
32
31
|
@total = nil
|
33
32
|
# @type [Source, nil]
|
34
33
|
@current = nil
|
34
|
+
@sync_count = 0
|
35
35
|
end
|
36
36
|
|
37
37
|
def inspect
|
@@ -44,7 +44,7 @@ module Solargraph
|
|
44
44
|
#
|
45
45
|
# @return [Boolean]
|
46
46
|
def synchronized?
|
47
|
-
|
47
|
+
@sync_count < 2
|
48
48
|
end
|
49
49
|
|
50
50
|
# Attach a source to the library.
|
@@ -132,6 +132,7 @@ module Solargraph
|
|
132
132
|
result = false
|
133
133
|
filenames.each do |filename|
|
134
134
|
detach filename
|
135
|
+
source_map_hash.delete(filename)
|
135
136
|
result ||= workspace.remove(filename)
|
136
137
|
end
|
137
138
|
result
|
@@ -174,9 +175,9 @@ module Solargraph
|
|
174
175
|
# @return [Array<Solargraph::Pin::Base>, nil]
|
175
176
|
# @todo Take filename/position instead of filename/line/column
|
176
177
|
def definitions_at filename, line, column
|
178
|
+
sync_catalog
|
177
179
|
position = Position.new(line, column)
|
178
180
|
cursor = Source::Cursor.new(read(filename), position)
|
179
|
-
sync_catalog
|
180
181
|
if cursor.comment?
|
181
182
|
source = read(filename)
|
182
183
|
offset = Solargraph::Position.to_offset(source.code, Solargraph::Position.new(line, column))
|
@@ -190,7 +191,10 @@ module Solargraph
|
|
190
191
|
[]
|
191
192
|
end
|
192
193
|
else
|
193
|
-
mutex.synchronize
|
194
|
+
mutex.synchronize do
|
195
|
+
clip = api_map.clip(cursor)
|
196
|
+
clip.define.map { |pin| pin.realize(api_map) }
|
197
|
+
end
|
194
198
|
end
|
195
199
|
rescue FileNotFoundError => e
|
196
200
|
handle_file_not_found(filename, e)
|
@@ -205,9 +209,9 @@ module Solargraph
|
|
205
209
|
# @return [Array<Solargraph::Pin::Base>, nil]
|
206
210
|
# @todo Take filename/position instead of filename/line/column
|
207
211
|
def type_definitions_at filename, line, column
|
212
|
+
sync_catalog
|
208
213
|
position = Position.new(line, column)
|
209
214
|
cursor = Source::Cursor.new(read(filename), position)
|
210
|
-
sync_catalog
|
211
215
|
mutex.synchronize { api_map.clip(cursor).types }
|
212
216
|
rescue FileNotFoundError => e
|
213
217
|
handle_file_not_found filename, e
|
@@ -222,9 +226,9 @@ module Solargraph
|
|
222
226
|
# @return [Array<Solargraph::Pin::Base>]
|
223
227
|
# @todo Take filename/position instead of filename/line/column
|
224
228
|
def signatures_at filename, line, column
|
229
|
+
sync_catalog
|
225
230
|
position = Position.new(line, column)
|
226
231
|
cursor = Source::Cursor.new(read(filename), position)
|
227
|
-
sync_catalog
|
228
232
|
mutex.synchronize { api_map.clip(cursor).signify }
|
229
233
|
end
|
230
234
|
|
@@ -233,7 +237,7 @@ module Solargraph
|
|
233
237
|
# @param column [Integer]
|
234
238
|
# @param strip [Boolean] Strip special characters from variable names
|
235
239
|
# @param only [Boolean] Search for references in the current file only
|
236
|
-
# @return [Array<Solargraph::
|
240
|
+
# @return [Array<Solargraph::Location>]
|
237
241
|
# @todo Take a Location instead of filename/line/column
|
238
242
|
def references_from filename, line, column, strip: false, only: false
|
239
243
|
sync_catalog
|
@@ -391,6 +395,8 @@ module Solargraph
|
|
391
395
|
return [] unless open?(filename)
|
392
396
|
result = []
|
393
397
|
source = read(filename)
|
398
|
+
|
399
|
+
# @type [Hash{Class<Solargraph::Diagnostics::Base> => Array<String>}]
|
394
400
|
repargs = {}
|
395
401
|
workspace.config.reporters.each do |line|
|
396
402
|
if line == 'all!'
|
@@ -416,20 +422,7 @@ module Solargraph
|
|
416
422
|
#
|
417
423
|
# @return [void]
|
418
424
|
def catalog
|
419
|
-
@
|
420
|
-
@threads.push(Thread.new do
|
421
|
-
sleep 0.05 if RUBY_PLATFORM =~ /mingw/
|
422
|
-
next unless @threads.last == Thread.current
|
423
|
-
|
424
|
-
mutex.synchronize do
|
425
|
-
logger.info "Cataloging #{workspace.directory.empty? ? 'generic workspace' : workspace.directory}"
|
426
|
-
api_map.catalog bench
|
427
|
-
logger.info "Catalog complete (#{api_map.source_maps.length} files, #{api_map.pins.length} pins)"
|
428
|
-
logger.info "#{api_map.uncached_gemspecs.length} uncached gemspecs"
|
429
|
-
cache_next_gemspec
|
430
|
-
end
|
431
|
-
end)
|
432
|
-
@threads.last.run if RUBY_PLATFORM =~ /mingw/
|
425
|
+
@sync_count += 1
|
433
426
|
end
|
434
427
|
|
435
428
|
# @return [Bench]
|
@@ -437,7 +430,8 @@ module Solargraph
|
|
437
430
|
Bench.new(
|
438
431
|
source_maps: source_map_hash.values,
|
439
432
|
workspace: workspace,
|
440
|
-
external_requires: external_requires
|
433
|
+
external_requires: external_requires,
|
434
|
+
live_map: @current ? source_map_hash[@current.filename] : nil
|
441
435
|
)
|
442
436
|
end
|
443
437
|
|
@@ -467,7 +461,6 @@ module Solargraph
|
|
467
461
|
# @param source [Source]
|
468
462
|
# @return [Boolean] True if the source was merged into the workspace.
|
469
463
|
def merge source
|
470
|
-
Logging.logger.debug "Merging source: #{source.filename}"
|
471
464
|
result = workspace.merge(source)
|
472
465
|
maybe_map source
|
473
466
|
result
|
@@ -489,7 +482,6 @@ module Solargraph
|
|
489
482
|
if src
|
490
483
|
Logging.logger.debug "Mapping #{src.filename}"
|
491
484
|
source_map_hash[src.filename] = Solargraph::SourceMap.map(src)
|
492
|
-
find_external_requires(source_map_hash[src.filename])
|
493
485
|
source_map_hash[src.filename]
|
494
486
|
else
|
495
487
|
false
|
@@ -500,7 +492,7 @@ module Solargraph
|
|
500
492
|
def map!
|
501
493
|
workspace.sources.each do |src|
|
502
494
|
source_map_hash[src.filename] = Solargraph::SourceMap.map(src)
|
503
|
-
find_external_requires
|
495
|
+
find_external_requires source_map_hash[src.filename]
|
504
496
|
end
|
505
497
|
self
|
506
498
|
end
|
@@ -580,22 +572,10 @@ module Solargraph
|
|
580
572
|
return unless source
|
581
573
|
return unless @current == source || workspace.has_file?(source.filename)
|
582
574
|
if source_map_hash.key?(source.filename)
|
583
|
-
|
584
|
-
|
585
|
-
source.synchronized?
|
586
|
-
if source.synchronized?
|
587
|
-
new_map = Solargraph::SourceMap.map(source)
|
588
|
-
unless source_map_hash[source.filename].try_merge!(new_map)
|
589
|
-
source_map_hash[source.filename] = new_map
|
590
|
-
find_external_requires(source_map_hash[source.filename])
|
591
|
-
end
|
592
|
-
else
|
593
|
-
# @todo Smelly instance variable access
|
594
|
-
source_map_hash[source.filename].instance_variable_set(:@source, source)
|
595
|
-
end
|
575
|
+
new_map = Solargraph::SourceMap.map(source)
|
576
|
+
source_map_hash[source.filename] = new_map
|
596
577
|
else
|
597
578
|
source_map_hash[source.filename] = Solargraph::SourceMap.map(source)
|
598
|
-
find_external_requires(source_map_hash[source.filename])
|
599
579
|
end
|
600
580
|
end
|
601
581
|
|
@@ -625,6 +605,7 @@ module Solargraph
|
|
625
605
|
ensure
|
626
606
|
end_cache_progress
|
627
607
|
catalog
|
608
|
+
sync_catalog
|
628
609
|
end
|
629
610
|
end
|
630
611
|
|
@@ -666,8 +647,17 @@ module Solargraph
|
|
666
647
|
end
|
667
648
|
|
668
649
|
def sync_catalog
|
669
|
-
@
|
670
|
-
|
650
|
+
return if @sync_count == 0
|
651
|
+
|
652
|
+
mutex.synchronize do
|
653
|
+
logger.info "Cataloging #{workspace.directory.empty? ? 'generic workspace' : workspace.directory}"
|
654
|
+
api_map.catalog bench
|
655
|
+
source_map_hash.values.each { |map| find_external_requires(map) }
|
656
|
+
logger.info "Catalog complete (#{api_map.source_maps.length} files, #{api_map.pins.length} pins)"
|
657
|
+
logger.info "#{api_map.uncached_gemspecs.length} uncached gemspecs"
|
658
|
+
cache_next_gemspec
|
659
|
+
@sync_count = 0
|
660
|
+
end
|
671
661
|
end
|
672
662
|
end
|
673
663
|
end
|
data/lib/solargraph/location.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Solargraph
|
4
|
-
# A section of text identified by its filename
|
4
|
+
# A pointer to a section of source text identified by its filename
|
5
|
+
# and Range.
|
5
6
|
#
|
6
7
|
class Location
|
8
|
+
include Equality
|
9
|
+
|
7
10
|
# @return [String]
|
8
11
|
attr_reader :filename
|
9
12
|
|
@@ -17,6 +20,16 @@ module Solargraph
|
|
17
20
|
@range = range
|
18
21
|
end
|
19
22
|
|
23
|
+
# @sg-ignore Fix "Not enough arguments to Module#protected"
|
24
|
+
protected def equality_fields
|
25
|
+
[filename, range]
|
26
|
+
end
|
27
|
+
|
28
|
+
# @param location [self]
|
29
|
+
def contain? location
|
30
|
+
range.contain?(location.range.start) && range.contain?(location.range.ending) && filename == location.filename
|
31
|
+
end
|
32
|
+
|
20
33
|
# @return [Hash]
|
21
34
|
def to_hash
|
22
35
|
{
|
@@ -25,6 +38,13 @@ module Solargraph
|
|
25
38
|
}
|
26
39
|
end
|
27
40
|
|
41
|
+
# @param node [Parser::AST::Node, nil]
|
42
|
+
def self.from_node(node)
|
43
|
+
return nil if node.nil? || node.loc.nil?
|
44
|
+
range = Range.from_node(node)
|
45
|
+
self.new(node.loc.expression.source_buffer.name, range)
|
46
|
+
end
|
47
|
+
|
28
48
|
# @param other [BasicObject]
|
29
49
|
def == other
|
30
50
|
return false unless other.is_a?(Location)
|
@@ -11,13 +11,9 @@ module Solargraph
|
|
11
11
|
# @param filename [String, nil]
|
12
12
|
# @return [Array(Parser::AST::Node, Hash{Integer => String})]
|
13
13
|
def parse_with_comments code, filename = nil
|
14
|
-
|
15
|
-
buffer.source = code
|
16
|
-
node = parser.parse(buffer)
|
14
|
+
node = parse(code, filename)
|
17
15
|
comments = CommentRipper.new(code, filename, 0).parse
|
18
16
|
[node, comments]
|
19
|
-
rescue ::Parser::SyntaxError => e
|
20
|
-
raise Parser::SyntaxError, e.message
|
21
17
|
end
|
22
18
|
|
23
19
|
# @param code [String]
|
@@ -28,7 +24,7 @@ module Solargraph
|
|
28
24
|
buffer = ::Parser::Source::Buffer.new(filename, line)
|
29
25
|
buffer.source = code
|
30
26
|
parser.parse(buffer)
|
31
|
-
rescue ::Parser::SyntaxError => e
|
27
|
+
rescue ::Parser::SyntaxError, ::Parser::UnknownEncodingInMagicComment => e
|
32
28
|
raise Parser::SyntaxError, e.message
|
33
29
|
end
|
34
30
|
|
@@ -12,7 +12,7 @@ require 'ast'
|
|
12
12
|
# class Node
|
13
13
|
# # New children
|
14
14
|
#
|
15
|
-
# # @return [Array<
|
15
|
+
# # @return [Array<self>]
|
16
16
|
# attr_reader :children
|
17
17
|
# end
|
18
18
|
# end
|
@@ -311,7 +311,7 @@ module Solargraph
|
|
311
311
|
# statements in value positions.
|
312
312
|
module DeepInference
|
313
313
|
class << self
|
314
|
-
CONDITIONAL_ALL_BUT_FIRST = [:if, :unless
|
314
|
+
CONDITIONAL_ALL_BUT_FIRST = [:if, :unless]
|
315
315
|
CONDITIONAL_ALL = [:or]
|
316
316
|
ONLY_ONE_CHILD = [:return]
|
317
317
|
FIRST_TWO_CHILDREN = [:rescue]
|
@@ -462,7 +462,7 @@ module Solargraph
|
|
462
462
|
result
|
463
463
|
end
|
464
464
|
|
465
|
-
# @param nodes [Enumerable<Parser::AST::Node,
|
465
|
+
# @param nodes [Enumerable<Parser::AST::Node, BasicObject>]
|
466
466
|
# @return [Array<Parser::AST::Node, nil>]
|
467
467
|
def reduce_to_value_nodes nodes
|
468
468
|
result = []
|
@@ -6,22 +6,25 @@ module Solargraph
|
|
6
6
|
module NodeProcessors
|
7
7
|
class ArgsNode < Parser::NodeProcessor::Base
|
8
8
|
def process
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
9
|
+
callable = region.closure
|
10
|
+
if callable.is_a? Pin::Callable
|
11
|
+
if node.type == :forward_args
|
12
|
+
forward(callable)
|
13
|
+
else
|
14
|
+
node.children.each do |u|
|
15
|
+
loc = get_node_location(u)
|
16
|
+
locals.push Solargraph::Pin::Parameter.new(
|
17
|
+
location: loc,
|
18
|
+
closure: callable,
|
19
|
+
comments: comments_for(node),
|
20
|
+
name: u.children[0].to_s,
|
21
|
+
assignment: u.children[1],
|
22
|
+
asgn_code: u.children[1] ? region.code_for(u.children[1]) : nil,
|
23
|
+
presence: callable.location.range,
|
24
|
+
decl: get_decl(u)
|
25
|
+
)
|
26
|
+
callable.parameters.push locals.last
|
27
|
+
end
|
25
28
|
end
|
26
29
|
end
|
27
30
|
process_children
|
@@ -29,16 +32,17 @@ module Solargraph
|
|
29
32
|
|
30
33
|
private
|
31
34
|
|
35
|
+
# @param callable [Pin::Callable]
|
32
36
|
# @return [void]
|
33
|
-
def forward
|
37
|
+
def forward(callable)
|
34
38
|
loc = get_node_location(node)
|
35
39
|
locals.push Solargraph::Pin::Parameter.new(
|
36
40
|
location: loc,
|
37
|
-
closure:
|
41
|
+
closure: callable,
|
38
42
|
presence: region.closure.location.range,
|
39
43
|
decl: get_decl(node)
|
40
44
|
)
|
41
|
-
|
45
|
+
callable.parameters.push locals.last
|
42
46
|
end
|
43
47
|
|
44
48
|
# @param node [AST::Node]
|
@@ -30,11 +30,17 @@ module Solargraph
|
|
30
30
|
|
31
31
|
lhs_arr.each_with_index do |lhs, i|
|
32
32
|
location = get_node_location(lhs)
|
33
|
+
pin = if lhs.type == :lvasgn
|
34
|
+
# lvasgn is a local variable
|
35
|
+
locals.find { |l| l.location == location }
|
36
|
+
else
|
37
|
+
# e.g., ivasgn is an instance variable, etc
|
38
|
+
pins.find { |iv| iv.location == location && iv.is_a?(Pin::BaseVariable) }
|
39
|
+
end
|
33
40
|
# @todo in line below, nothing in typechecking alerts
|
34
41
|
# when a non-existant method is called on 'l'
|
35
|
-
pin = locals.find { |l| l.location == location }
|
36
42
|
if pin.nil?
|
37
|
-
Solargraph.logger.debug "Could not find
|
43
|
+
Solargraph.logger.debug { "Could not find local for masgn= value in location #{location.inspect} in #{lhs_arr} - masgn = #{masgn}, lhs.type = #{lhs.type}" }
|
38
44
|
next
|
39
45
|
end
|
40
46
|
pin.mass_assignment = [mass_rhs, i]
|
@@ -92,7 +92,7 @@ module Solargraph
|
|
92
92
|
pins.push method_pin
|
93
93
|
method_pin.parameters.push Pin::Parameter.new(name: 'value', decl: :arg, closure: pins.last)
|
94
94
|
if method_pin.return_type.defined?
|
95
|
-
pins.last.docstring.add_tag YARD::Tags::Tag.new(:param, '', pins.last.return_type.
|
95
|
+
pins.last.docstring.add_tag YARD::Tags::Tag.new(:param, '', pins.last.return_type.items.map(&:rooted_tags), 'value')
|
96
96
|
end
|
97
97
|
end
|
98
98
|
end
|
data/lib/solargraph/parser.rb
CHANGED
@@ -9,15 +9,12 @@ module Solargraph
|
|
9
9
|
class SyntaxError < StandardError
|
10
10
|
end
|
11
11
|
|
12
|
-
def self.rubyvm?
|
13
|
-
false
|
14
|
-
end
|
15
|
-
|
16
12
|
# @deprecated
|
17
13
|
Legacy = ParserGem
|
18
14
|
|
19
15
|
ClassMethods = ParserGem::ClassMethods
|
20
|
-
|
16
|
+
# @todo should be able to just 'extend ClassMethods' here and
|
17
|
+
# typecheck things off it in strict mode
|
21
18
|
extend ParserGem::ClassMethods
|
22
19
|
|
23
20
|
NodeMethods = ParserGem::NodeMethods
|
data/lib/solargraph/pin/base.rb
CHANGED
@@ -15,6 +15,9 @@ module Solargraph
|
|
15
15
|
# @return [Solargraph::Location]
|
16
16
|
attr_reader :location
|
17
17
|
|
18
|
+
# @return [Solargraph::Location]
|
19
|
+
attr_reader :type_location
|
20
|
+
|
18
21
|
# @return [String]
|
19
22
|
attr_reader :name
|
20
23
|
|
@@ -25,11 +28,13 @@ module Solargraph
|
|
25
28
|
attr_accessor :source
|
26
29
|
|
27
30
|
# @param location [Solargraph::Location, nil]
|
31
|
+
# @param type_location [Solargraph::Location, nil]
|
28
32
|
# @param closure [Solargraph::Pin::Closure, nil]
|
29
33
|
# @param name [String]
|
30
34
|
# @param comments [String]
|
31
|
-
def initialize location: nil, closure: nil, name: '', comments: ''
|
35
|
+
def initialize location: nil, type_location: nil, closure: nil, name: '', comments: ''
|
32
36
|
@location = location
|
37
|
+
@type_location = type_location
|
33
38
|
@closure = closure
|
34
39
|
@name = name
|
35
40
|
@comments = comments
|
@@ -66,11 +71,14 @@ module Solargraph
|
|
66
71
|
# @param context_type [ComplexType] The receiver type
|
67
72
|
# @return [self]
|
68
73
|
def resolve_generics definitions, context_type
|
69
|
-
|
70
|
-
|
74
|
+
transform_types { |t| t.resolve_generics(definitions, context_type) if t }
|
75
|
+
end
|
76
|
+
|
77
|
+
def all_rooted?
|
78
|
+
!return_type || return_type.all_rooted?
|
71
79
|
end
|
72
80
|
|
73
|
-
# @param generics_to_erase [
|
81
|
+
# @param generics_to_erase [::Array<String>]
|
74
82
|
# @return [self]
|
75
83
|
def erase_generics(generics_to_erase)
|
76
84
|
return self if generics_to_erase.empty?
|
@@ -94,7 +102,7 @@ module Solargraph
|
|
94
102
|
end
|
95
103
|
|
96
104
|
def to_s
|
97
|
-
|
105
|
+
desc
|
98
106
|
end
|
99
107
|
|
100
108
|
# @return [Boolean]
|
@@ -102,12 +110,9 @@ module Solargraph
|
|
102
110
|
false
|
103
111
|
end
|
104
112
|
|
105
|
-
#
|
106
|
-
|
107
|
-
|
108
|
-
def == other
|
109
|
-
return false unless nearly? other
|
110
|
-
comments == other.comments and location == other.location
|
113
|
+
# @return [Location, nil]
|
114
|
+
def best_location
|
115
|
+
location || type_location
|
111
116
|
end
|
112
117
|
|
113
118
|
# True if the specified pin is a near match to this one. A near match
|
@@ -126,6 +131,14 @@ module Solargraph
|
|
126
131
|
)
|
127
132
|
end
|
128
133
|
|
134
|
+
# Pin equality is determined using the #nearly? method and also
|
135
|
+
# requiring both pins to have the same location.
|
136
|
+
#
|
137
|
+
def == other
|
138
|
+
return false unless nearly? other
|
139
|
+
comments == other.comments && location == other.location
|
140
|
+
end
|
141
|
+
|
129
142
|
# The pin's return type.
|
130
143
|
#
|
131
144
|
# @return [ComplexType]
|
@@ -252,9 +265,10 @@ module Solargraph
|
|
252
265
|
result
|
253
266
|
end
|
254
267
|
|
268
|
+
# @deprecated
|
255
269
|
# @return [String]
|
256
270
|
def identity
|
257
|
-
@identity ||= "#{closure
|
271
|
+
@identity ||= "#{closure&.path}|#{name}"
|
258
272
|
end
|
259
273
|
|
260
274
|
# @return [String, nil]
|
@@ -262,19 +276,29 @@ module Solargraph
|
|
262
276
|
return_type.to_rbs
|
263
277
|
end
|
264
278
|
|
265
|
-
# @return [String
|
266
|
-
def
|
279
|
+
# @return [String]
|
280
|
+
def type_desc
|
281
|
+
rbs = to_rbs
|
282
|
+
# RBS doesn't have a way to represent a Class<x> type
|
283
|
+
rbs = return_type.rooted_tags if return_type.name == 'Class'
|
267
284
|
if path
|
268
|
-
if
|
269
|
-
path + ' ' +
|
285
|
+
if rbs
|
286
|
+
path + ' ' + rbs
|
270
287
|
else
|
271
288
|
path
|
272
289
|
end
|
273
290
|
else
|
274
|
-
|
291
|
+
rbs
|
275
292
|
end
|
276
293
|
end
|
277
294
|
|
295
|
+
# @return [String]
|
296
|
+
def desc
|
297
|
+
closure_info = closure&.desc
|
298
|
+
binder_info = binder&.desc
|
299
|
+
"[#{type_desc}, closure=#{closure_info}, binder=#{binder}"
|
300
|
+
end
|
301
|
+
|
278
302
|
def inspect
|
279
303
|
"#<#{self.class} `#{self.desc}` at #{self.location.inspect}>"
|
280
304
|
end
|
@@ -57,7 +57,7 @@ module Solargraph
|
|
57
57
|
# Use the return node for inference. The clip might infer from the
|
58
58
|
# first node in a method call instead of the entire call.
|
59
59
|
chain = Parser.chain(node, nil, nil)
|
60
|
-
result = chain.infer(api_map, closure, clip.locals).
|
60
|
+
result = chain.infer(api_map, closure, clip.locals).self_to_type(closure.context)
|
61
61
|
types.push result unless result.undefined?
|
62
62
|
end
|
63
63
|
end
|
@@ -93,6 +93,7 @@ module Solargraph
|
|
93
93
|
assignment == other.assignment
|
94
94
|
end
|
95
95
|
|
96
|
+
# @param pin [self]
|
96
97
|
def try_merge! pin
|
97
98
|
return false unless super
|
98
99
|
@assignment = pin.assignment
|
@@ -100,8 +101,8 @@ module Solargraph
|
|
100
101
|
true
|
101
102
|
end
|
102
103
|
|
103
|
-
def
|
104
|
-
"#{
|
104
|
+
def type_desc
|
105
|
+
"#{super} = #{assignment&.type.inspect}"
|
105
106
|
end
|
106
107
|
|
107
108
|
private
|
data/lib/solargraph/pin/block.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Solargraph
|
4
4
|
module Pin
|
5
|
-
class Block <
|
5
|
+
class Block < Callable
|
6
6
|
# @return [Parser::AST::Node]
|
7
7
|
attr_reader :receiver
|
8
8
|
|
@@ -14,10 +14,9 @@ module Solargraph
|
|
14
14
|
# @param context [ComplexType, nil]
|
15
15
|
# @param args [::Array<Parameter>]
|
16
16
|
def initialize receiver: nil, args: [], context: nil, node: nil, **splat
|
17
|
-
super(**splat)
|
17
|
+
super(**splat, parameters: args)
|
18
18
|
@receiver = receiver
|
19
19
|
@context = context
|
20
|
-
@parameters = args
|
21
20
|
@return_type = ComplexType.parse('::Proc')
|
22
21
|
@node = node
|
23
22
|
end
|
@@ -32,38 +31,19 @@ module Solargraph
|
|
32
31
|
@rebind&.defined? ? @rebind : closure.binder
|
33
32
|
end
|
34
33
|
|
35
|
-
# @return [::Array<Parameter>]
|
36
|
-
def parameters
|
37
|
-
@parameters ||= []
|
38
|
-
end
|
39
|
-
|
40
|
-
# @return [::Array<String>]
|
41
|
-
def parameter_names
|
42
|
-
@parameter_names ||= parameters.map(&:name)
|
43
|
-
end
|
44
|
-
|
45
34
|
# @param yield_types [::Array<ComplexType>]
|
46
35
|
# @param parameters [::Array<Parameter>]
|
47
36
|
#
|
48
37
|
# @return [::Array<ComplexType>]
|
49
38
|
def destructure_yield_types(yield_types, parameters)
|
50
|
-
return yield_types if yield_types.length == parameters.length
|
51
|
-
|
52
39
|
# yielding a tuple into a block will destructure the tuple
|
53
40
|
if yield_types.length == 1
|
54
41
|
yield_type = yield_types.first
|
55
42
|
return yield_type.all_params if yield_type.tuple? && yield_type.all_params.length == parameters.length
|
56
43
|
end
|
57
|
-
parameters.map { ComplexType::UNDEFINED }
|
44
|
+
parameters.map.with_index { |_, idx| yield_types[idx] || ComplexType::UNDEFINED }
|
58
45
|
end
|
59
46
|
|
60
|
-
# @todo the next step with parameters, arguments, destructuring,
|
61
|
-
# kwargs, etc logic is probably either creating a Parameters
|
62
|
-
# or Callable pin that encapsulates and shares the logic
|
63
|
-
# between methods, blocks and signatures. It could live in
|
64
|
-
# Signature if Method didn't also own potentially different
|
65
|
-
# set of parameters, generics and return types.
|
66
|
-
|
67
47
|
# @param api_map [ApiMap]
|
68
48
|
# @return [::Array<ComplexType>]
|
69
49
|
def typify_parameters(api_map)
|
@@ -87,7 +67,7 @@ module Solargraph
|
|
87
67
|
namespace_pin = api_map.get_namespace_pins(meth.namespace, closure.namespace).first
|
88
68
|
arg_type.resolve_generics(namespace_pin, param_type)
|
89
69
|
else
|
90
|
-
arg_type.
|
70
|
+
arg_type.self_to_type(chain.base.infer(api_map, self, locals)).qualify(api_map, meth.context.namespace)
|
91
71
|
end
|
92
72
|
end
|
93
73
|
end
|
@@ -105,7 +85,7 @@ module Solargraph
|
|
105
85
|
|
106
86
|
chain = Parser.chain(receiver, location.filename)
|
107
87
|
locals = api_map.source_map(location.filename).locals_at(location)
|
108
|
-
receiver_pin = chain.define(api_map,
|
88
|
+
receiver_pin = chain.define(api_map, closure, locals).first
|
109
89
|
return ComplexType::UNDEFINED unless receiver_pin
|
110
90
|
|
111
91
|
types = receiver_pin.docstring.tag(:yieldreceiver)&.types
|
@@ -114,7 +94,7 @@ module Solargraph
|
|
114
94
|
target = chain.base.infer(api_map, receiver_pin, locals)
|
115
95
|
target = full_context unless target.defined?
|
116
96
|
|
117
|
-
ComplexType.try_parse(*types).qualify(api_map, receiver_pin.context.namespace).
|
97
|
+
ComplexType.try_parse(*types).qualify(api_map, receiver_pin.context.namespace).self_to_type(target)
|
118
98
|
end
|
119
99
|
end
|
120
100
|
end
|