solargraph 0.60.4 → 0.61.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 +1 -1
- data/.github/workflows/rspec.yml +3 -1
- data/CHANGELOG.md +16 -0
- data/Gemfile +0 -3
- data/lib/solargraph/api_map/index.rb +15 -2
- data/lib/solargraph/api_map/store.rb +13 -0
- data/lib/solargraph/api_map.rb +60 -81
- data/lib/solargraph/cache_dir.rb +58 -0
- data/lib/solargraph/collection/base.rb +50 -0
- data/lib/solargraph/collection/core.rb +17 -0
- data/lib/solargraph/collection/gem.rb +57 -0
- data/lib/solargraph/collection/rbs.rb +49 -0
- data/lib/solargraph/collection/stdlib.rb +25 -0
- data/lib/solargraph/collection.rb +31 -0
- data/lib/solargraph/convention.rb +5 -3
- data/lib/solargraph/diagnostics/require_not_found.rb +0 -4
- data/lib/solargraph/external.rb +159 -0
- data/lib/solargraph/language_server/message/text_document/definition.rb +4 -1
- data/lib/solargraph/language_server/message/text_document/hover.rb +1 -2
- data/lib/solargraph/library.rb +11 -24
- data/lib/solargraph/metagem.rb +80 -0
- data/lib/solargraph/parser/parser_gem/node_chainer.rb +22 -3
- data/lib/solargraph/pin/closure.rb +17 -0
- data/lib/solargraph/pin/factory_parameter.rb +84 -0
- data/lib/solargraph/pin.rb +1 -0
- data/lib/solargraph/rbs_map/base.rb +31 -0
- data/lib/solargraph/rbs_map/conversions.rb +3 -1
- data/lib/solargraph/rbs_map/{core_map.rb → core.rb} +18 -39
- data/lib/solargraph/rbs_map/core_fills.rb +1 -1
- data/lib/solargraph/rbs_map/gem.rb +13 -0
- data/lib/solargraph/rbs_map/helpers.rb +60 -0
- data/lib/solargraph/rbs_map/path.rb +19 -0
- data/lib/solargraph/rbs_map/stdlib.rb +24 -0
- data/lib/solargraph/rbs_map.rb +7 -198
- data/lib/solargraph/repo.rb +177 -0
- data/lib/solargraph/shell.rb +49 -99
- data/lib/solargraph/source/chain/call.rb +29 -4
- data/lib/solargraph/source/chain/literal.rb +17 -17
- data/lib/solargraph/source/chain/parameter.rb +79 -0
- data/lib/solargraph/source/chain.rb +8 -0
- data/lib/solargraph/source/source_chainer.rb +40 -44
- data/lib/solargraph/source_map/clip.rb +5 -3
- data/lib/solargraph/source_map/mapper.rb +6 -2
- data/lib/solargraph/source_map.rb +10 -5
- data/lib/solargraph/type_checker/rules.rb +2 -1
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace.rb +0 -1
- data/lib/solargraph/yard_map/cache.rb +1 -1
- data/lib/solargraph/yard_map/directives/attribute_directive.rb +1 -1
- data/lib/solargraph/yard_map/directives/domain_directive.rb +1 -1
- data/lib/solargraph/yard_map/directives/method_directive.rb +1 -1
- data/lib/solargraph/yard_map/directives/override_directive.rb +1 -1
- data/lib/solargraph/yard_map/directives/parse_directive.rb +1 -1
- data/lib/solargraph/yard_map/directives/scope_directive.rb +178 -0
- data/lib/solargraph/yard_map/directives/visibility_directive.rb +1 -1
- data/lib/solargraph/yard_map/directives.rb +5 -2
- data/lib/solargraph/yard_map/helpers.rb +1 -1
- data/lib/solargraph/yard_map/macro.rb +34 -5
- data/lib/solargraph/yard_map/mapper/to_constant.rb +1 -1
- data/lib/solargraph/yard_map/mapper/to_method.rb +1 -1
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -1
- data/lib/solargraph/yard_map/mapper.rb +2 -2
- data/lib/solargraph/yard_map.rb +1 -1
- data/lib/solargraph/yardoc.rb +43 -60
- data/lib/solargraph.rb +6 -3
- data/solargraph.gemspec +1 -1
- metadata +22 -9
- data/lib/solargraph/doc_map.rb +0 -439
- data/lib/solargraph/gem_pins.rb +0 -87
- data/lib/solargraph/pin_cache.rb +0 -248
- data/lib/solargraph/rbs_map/stdlib_map.rb +0 -71
- data/lib/solargraph/workspace/gemspecs.rb +0 -373
|
@@ -38,12 +38,14 @@ module Solargraph
|
|
|
38
38
|
result
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
# @
|
|
41
|
+
# @todo Determine what argument needs to be passed here
|
|
42
|
+
#
|
|
43
|
+
# @param object [Object]
|
|
42
44
|
# @return [Environ]
|
|
43
|
-
def self.for_global
|
|
45
|
+
def self.for_global object
|
|
44
46
|
result = Environ.new
|
|
45
47
|
@@conventions.each do |conv|
|
|
46
|
-
result.merge conv.global(
|
|
48
|
+
result.merge conv.global(object)
|
|
47
49
|
end
|
|
48
50
|
result
|
|
49
51
|
end
|
|
@@ -13,10 +13,6 @@ module Solargraph
|
|
|
13
13
|
# @sg-ignore Need to add nil check here
|
|
14
14
|
map = api_map.source_map(source.filename)
|
|
15
15
|
map.requires.each { |ref| refs[ref.name] = ref }
|
|
16
|
-
api_map.missing_docs.each do |r|
|
|
17
|
-
next unless refs.key?(r)
|
|
18
|
-
result.push docs_error(r, refs[r].location)
|
|
19
|
-
end
|
|
20
16
|
api_map.unresolved_requires.each do |r|
|
|
21
17
|
next unless refs.key?(r)
|
|
22
18
|
result.push require_error(r, refs[r].location)
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'set'
|
|
4
|
+
|
|
5
|
+
module Solargraph
|
|
6
|
+
# @todo This class might need a way to track changes to the repo, e.g.,
|
|
7
|
+
# bundle or dependency updates
|
|
8
|
+
#
|
|
9
|
+
class External
|
|
10
|
+
# @return [String]
|
|
11
|
+
attr_reader :directory
|
|
12
|
+
|
|
13
|
+
# @return [Array<String>]
|
|
14
|
+
attr_reader :requires
|
|
15
|
+
|
|
16
|
+
# @param directory [String]
|
|
17
|
+
# @param requires [Array<String>]
|
|
18
|
+
def initialize directory, requires
|
|
19
|
+
@repo = Repo.new(directory)
|
|
20
|
+
@directory = directory
|
|
21
|
+
@requires = requires
|
|
22
|
+
update!
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def unresolved_requires
|
|
26
|
+
@unresolved_requires ||= []
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def unresolved_dependencies
|
|
30
|
+
@unresolved_dependencies ||= []
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def loaded_gems
|
|
34
|
+
@loaded_gems ||= Set.new
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def unloaded_gems
|
|
38
|
+
@unloaded_gems ||= Set.new
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def pins
|
|
42
|
+
@pins ||= []
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# @return [Integer] incremented whenever the external pin set is rebuilt
|
|
46
|
+
def generation
|
|
47
|
+
@generation ||= 0
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# @param new_requires [Array<String>]
|
|
51
|
+
# @return [Boolean]
|
|
52
|
+
def update new_requires
|
|
53
|
+
return false if requires == new_requires && !cache_changed?
|
|
54
|
+
|
|
55
|
+
requires.replace new_requires
|
|
56
|
+
update!
|
|
57
|
+
true
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# @return [Array<String>]
|
|
61
|
+
def rbs_collection_paths
|
|
62
|
+
@rbs_collection_paths ||= read_rbs_collection_paths
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# @return [String, nil]
|
|
66
|
+
def rbs_collection_config_path
|
|
67
|
+
# @todo Get rid of the '*' case
|
|
68
|
+
@rbs_collection_config_path ||= unless directory.nil? || directory.empty? || directory == '*'
|
|
69
|
+
yaml_file = File.join(directory, 'rbs_collection.yaml')
|
|
70
|
+
yaml_file if File.file?(yaml_file)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
private
|
|
75
|
+
|
|
76
|
+
def update!
|
|
77
|
+
@generation = generation + 1
|
|
78
|
+
clear_all
|
|
79
|
+
load_requires
|
|
80
|
+
load_rbs_collection
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def cache_changed?
|
|
84
|
+
unloaded_gems.any? { |gem| Collection::Gem.cached?(gem) }
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def load_requires
|
|
88
|
+
bundler_require = false
|
|
89
|
+
|
|
90
|
+
requires.uniq.each do |path|
|
|
91
|
+
if path == 'bundler/require'
|
|
92
|
+
bundler_require = true
|
|
93
|
+
end
|
|
94
|
+
if RbsMap::Stdlib.has?(path)
|
|
95
|
+
pins.concat Collection::Stdlib.load(path)
|
|
96
|
+
else
|
|
97
|
+
metagem = @repo.find_by_path(path)
|
|
98
|
+
next unresolved_requires.push(path) unless metagem
|
|
99
|
+
process_gem metagem
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
return unless bundler_require
|
|
104
|
+
|
|
105
|
+
@repo.find_by_group(:default).each { |metagem| process_gem metagem }
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def load_rbs_collection
|
|
109
|
+
rbs_collection_pins = rbs_collection_paths.flat_map { |path| Collection::Rbs.load(path) }
|
|
110
|
+
pins.replace RbsMap::Helpers.combine(pins, rbs_collection_pins)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def clear_all
|
|
114
|
+
pins.clear
|
|
115
|
+
unresolved_requires.clear
|
|
116
|
+
unresolved_dependencies.clear
|
|
117
|
+
loaded_gems.clear
|
|
118
|
+
unloaded_gems.clear
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def process_gem metagem
|
|
122
|
+
return if loaded_gems.include?(metagem) || unloaded_gems.include?(metagem)
|
|
123
|
+
|
|
124
|
+
if metagem.cacheable?
|
|
125
|
+
if Collection::Gem.cached?(metagem)
|
|
126
|
+
loaded_gems.add metagem
|
|
127
|
+
pins.concat Collection::Gem.load(metagem)
|
|
128
|
+
else
|
|
129
|
+
unloaded_gems.add metagem
|
|
130
|
+
end
|
|
131
|
+
else
|
|
132
|
+
loaded_gems.add metagem
|
|
133
|
+
pins.concat Collection::Gem.load(metagem)
|
|
134
|
+
end
|
|
135
|
+
load_dependencies metagem
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def load_dependencies parent
|
|
139
|
+
parent.dependencies.each do |name|
|
|
140
|
+
next if loaded_gems.map(&:name).include?(name) || unloaded_gems.map(&:name).include?(name)
|
|
141
|
+
metagem = @repo.find_by_name(name)
|
|
142
|
+
next unresolved_dependencies.push(name) unless metagem
|
|
143
|
+
process_gem metagem
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# @return [Array<String>]
|
|
148
|
+
def read_rbs_collection_paths
|
|
149
|
+
return [] unless rbs_collection_config_path
|
|
150
|
+
|
|
151
|
+
yaml = YAML.load_file(rbs_collection_config_path)
|
|
152
|
+
[File.expand_path(yaml.fetch('path'), directory)].concat(
|
|
153
|
+
yaml.fetch('sources', [])
|
|
154
|
+
.select { |source| source['type'] == 'local' && source['path'] }
|
|
155
|
+
.map { |source| File.expand_path(source['path'], directory) }
|
|
156
|
+
).compact
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
@@ -29,7 +29,10 @@ module Solargraph
|
|
|
29
29
|
|
|
30
30
|
# @return [Array<Hash>, nil]
|
|
31
31
|
def require_location
|
|
32
|
-
# @todo Terrible hack
|
|
32
|
+
# @todo Terrible hack - move this logic to [Solargraph::Source::Chain::Parameter]
|
|
33
|
+
# @example
|
|
34
|
+
# require 'click_me'
|
|
35
|
+
# ^^^^^^^^^^
|
|
33
36
|
lib = host.library_for(params['textDocument']['uri'])
|
|
34
37
|
rloc = Solargraph::Location.new(uri_to_file(params['textDocument']['uri']),
|
|
35
38
|
Solargraph::Range.from_to(@line, @column, @line, @column))
|
|
@@ -11,8 +11,7 @@ module Solargraph
|
|
|
11
11
|
contents = []
|
|
12
12
|
suggestions = host.definitions_at(params['textDocument']['uri'], line, col)
|
|
13
13
|
last_link = nil
|
|
14
|
-
|
|
15
|
-
suggestions.each do |pin|
|
|
14
|
+
suggestions&.each do |pin|
|
|
16
15
|
parts = []
|
|
17
16
|
this_link = host.options['enablePages'] ? pin.link_documentation : pin.text_documentation
|
|
18
17
|
parts.push this_link if !this_link.nil? && this_link != last_link
|
data/lib/solargraph/library.rb
CHANGED
|
@@ -576,14 +576,8 @@ module Solargraph
|
|
|
576
576
|
return unless source
|
|
577
577
|
# @sg-ignore Wrong argument type for Solargraph::Workspace#has_file?: filename expected String, received String, nil
|
|
578
578
|
return unless @current == source || workspace.has_file?(source.filename)
|
|
579
|
-
if
|
|
580
|
-
|
|
581
|
-
# @sg-ignore OK if source.filename is nil
|
|
582
|
-
source_map_hash[source.filename] = new_map
|
|
583
|
-
else
|
|
584
|
-
# @sg-ignore OK if source.filename is nil
|
|
585
|
-
source_map_hash[source.filename] = Solargraph::SourceMap.map(source)
|
|
586
|
-
end
|
|
579
|
+
# @sg-ignore OK if source.filename is nil
|
|
580
|
+
source_map_hash[source.filename] = Solargraph::SourceMap.map(source)
|
|
587
581
|
end
|
|
588
582
|
|
|
589
583
|
# @return [Set<Gem::Specification>]
|
|
@@ -595,10 +589,10 @@ module Solargraph
|
|
|
595
589
|
def cache_next_gemspec
|
|
596
590
|
return if @cache_progress
|
|
597
591
|
|
|
598
|
-
spec =
|
|
592
|
+
spec = api_map.unloaded_gems.first
|
|
599
593
|
return end_cache_progress unless spec
|
|
600
594
|
|
|
601
|
-
pending = api_map.
|
|
595
|
+
pending = api_map.unloaded_gems.length - cache_errors.length - 1
|
|
602
596
|
|
|
603
597
|
if Yardoc.processing?(spec)
|
|
604
598
|
logger.info "Enqueuing cache of #{spec.name} #{spec.version} (already being processed)"
|
|
@@ -615,7 +609,10 @@ module Solargraph
|
|
|
615
609
|
logger.info "Caching #{spec.name} #{spec.version}"
|
|
616
610
|
Thread.new do
|
|
617
611
|
report_cache_progress spec.name, pending
|
|
618
|
-
|
|
612
|
+
|
|
613
|
+
cmd = [workspace.command_path, 'cache', spec.name]
|
|
614
|
+
cmd.push('--directory', workspace.directory) if workspace.directory
|
|
615
|
+
_o, e, s = Open3.capture3(*cmd)
|
|
619
616
|
if s.success?
|
|
620
617
|
logger.info "Cached #{spec.name} #{spec.version}"
|
|
621
618
|
else
|
|
@@ -630,17 +627,6 @@ module Solargraph
|
|
|
630
627
|
end
|
|
631
628
|
end
|
|
632
629
|
|
|
633
|
-
# @return [Array<Gem::Specification>]
|
|
634
|
-
def cacheable_specs
|
|
635
|
-
cacheable = api_map.uncached_yard_gemspecs +
|
|
636
|
-
api_map.uncached_rbs_collection_gemspecs -
|
|
637
|
-
queued_gemspec_cache -
|
|
638
|
-
cache_errors.to_a
|
|
639
|
-
return cacheable unless cacheable.empty?
|
|
640
|
-
|
|
641
|
-
queued_gemspec_cache
|
|
642
|
-
end
|
|
643
|
-
|
|
644
630
|
# @return [Array<Gem::Specification>]
|
|
645
631
|
def queued_gemspec_cache
|
|
646
632
|
@queued_gemspec_cache ||= []
|
|
@@ -696,8 +682,9 @@ module Solargraph
|
|
|
696
682
|
source_map_hash.each_value { |map| find_external_requires(map) }
|
|
697
683
|
api_map.catalog bench
|
|
698
684
|
logger.info "Catalog complete (#{api_map.source_maps.length} files, #{api_map.pins.length} pins)"
|
|
699
|
-
|
|
700
|
-
logger.info "#{api_map.
|
|
685
|
+
# @todo This needs work
|
|
686
|
+
# logger.info "#{api_map.uncached_yard_gemspecs.length} uncached YARD gemspecs"
|
|
687
|
+
# logger.info "#{api_map.uncached_rbs_collection_gemspecs.length} uncached RBS collection gemspecs"
|
|
701
688
|
cache_next_gemspec
|
|
702
689
|
@sync_count = 0
|
|
703
690
|
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
class Metagem
|
|
5
|
+
include Equality
|
|
6
|
+
|
|
7
|
+
# @return [String]
|
|
8
|
+
attr_reader :name
|
|
9
|
+
|
|
10
|
+
# @return [String]
|
|
11
|
+
attr_reader :full_path
|
|
12
|
+
|
|
13
|
+
# @return [String]
|
|
14
|
+
attr_reader :spec_file
|
|
15
|
+
|
|
16
|
+
# @return [String]
|
|
17
|
+
attr_reader :source
|
|
18
|
+
|
|
19
|
+
# @return [String]
|
|
20
|
+
attr_reader :version
|
|
21
|
+
|
|
22
|
+
# @return [Array<String>]
|
|
23
|
+
attr_reader :require_paths
|
|
24
|
+
|
|
25
|
+
# @return [Array<String>]
|
|
26
|
+
attr_reader :dependencies
|
|
27
|
+
|
|
28
|
+
# @return [String]
|
|
29
|
+
attr_reader :cache_name
|
|
30
|
+
|
|
31
|
+
def initialize name:, full_path:, spec_file:, source:, version:, require_paths:, dependencies:
|
|
32
|
+
@name = name
|
|
33
|
+
@full_path = full_path
|
|
34
|
+
@spec_file = spec_file
|
|
35
|
+
@source = source
|
|
36
|
+
@version = version
|
|
37
|
+
@require_paths = require_paths
|
|
38
|
+
@dependencies = dependencies
|
|
39
|
+
# @todo Possible change to cache names to make them more specific to sources
|
|
40
|
+
# @cache_name = "#{File.basename(full_path)}__#{source.gsub(/[^a-z0-9\-_]/i, '_')}" unless source.end_with?('Path')
|
|
41
|
+
# @todo Better path source detection
|
|
42
|
+
@cache_name = File.basename(full_path) unless source.start_with?('source at') || source.to_s.end_with?('::Path')
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def cacheable?
|
|
46
|
+
!!@cache_name
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def require? path
|
|
50
|
+
require_paths.any? do |req|
|
|
51
|
+
File.file?(File.join(full_path, req, "#{path}.rb"))
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def to_specification
|
|
56
|
+
Gem::Specification.load(spec_file)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
alias full_gem_path full_path
|
|
60
|
+
|
|
61
|
+
# @return [Array]
|
|
62
|
+
def equality_fields
|
|
63
|
+
# A version arrives as a String from a bundle definition and as a
|
|
64
|
+
# Gem::Version from a specification, so compare its string form.
|
|
65
|
+
[name, version.to_s, full_path, source]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# @param gem [Gem::Specification]
|
|
69
|
+
# @return [Metagem]
|
|
70
|
+
def self.from_specification gem
|
|
71
|
+
Metagem.new(name: gem.name,
|
|
72
|
+
full_path: gem.full_gem_path,
|
|
73
|
+
spec_file: gem.spec_file,
|
|
74
|
+
source: gem.source.to_s,
|
|
75
|
+
version: gem.version,
|
|
76
|
+
require_paths: gem.require_paths,
|
|
77
|
+
dependencies: gem.runtime_dependencies.map(&:name))
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -13,10 +13,12 @@ module Solargraph
|
|
|
13
13
|
# @param node [Parser::AST::Node]
|
|
14
14
|
# @param filename [String, nil]
|
|
15
15
|
# @param parent [Parser::AST::Node, nil]
|
|
16
|
-
|
|
16
|
+
# @param tree [Array<Parser::AST::Node>, nil]
|
|
17
|
+
def initialize node, filename = nil, parent = nil, tree = nil
|
|
17
18
|
@node = node
|
|
18
19
|
@filename = filename
|
|
19
20
|
@parent = parent
|
|
21
|
+
@tree = tree
|
|
20
22
|
end
|
|
21
23
|
|
|
22
24
|
# @return [Source::Chain]
|
|
@@ -29,9 +31,10 @@ module Solargraph
|
|
|
29
31
|
# @param node [Parser::AST::Node]
|
|
30
32
|
# @param filename [String, nil]
|
|
31
33
|
# @param parent [Parser::AST::Node, nil]
|
|
34
|
+
# @param tree [Parser::AST::Node, nil]
|
|
32
35
|
# @return [Source::Chain]
|
|
33
|
-
def chain node, filename = nil, parent = nil
|
|
34
|
-
NodeChainer.new(node, filename, parent).chain
|
|
36
|
+
def chain node, filename = nil, parent = nil, tree = nil
|
|
37
|
+
NodeChainer.new(node, filename, parent, tree).chain
|
|
35
38
|
end
|
|
36
39
|
|
|
37
40
|
# @param code [String]
|
|
@@ -150,6 +153,13 @@ module Solargraph
|
|
|
150
153
|
elsif n.type == :array
|
|
151
154
|
chained_children = n.children.map { |c| NodeChainer.chain(c) }
|
|
152
155
|
result.push Source::Chain::Array.new(chained_children, n)
|
|
156
|
+
elsif inside_method_call? # If the node is inside a method call, it may be a parameter.
|
|
157
|
+
lit = infer_literal_node_type(n)
|
|
158
|
+
if lit
|
|
159
|
+
method_call_chain = NodeChainer.chain(send_node, @filename, nil, [])
|
|
160
|
+
literal = Chain::Literal.new(lit, n)
|
|
161
|
+
result.push Chain::Parameter.new(literal, method_call_chain)
|
|
162
|
+
end
|
|
153
163
|
else
|
|
154
164
|
lit = infer_literal_node_type(n)
|
|
155
165
|
result.push(lit ? Chain::Literal.new(lit, n) : Chain::Link.new)
|
|
@@ -158,6 +168,15 @@ module Solargraph
|
|
|
158
168
|
result
|
|
159
169
|
end
|
|
160
170
|
|
|
171
|
+
def inside_method_call?
|
|
172
|
+
!send_node.nil? && send_node != @node
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# @return [Parser::AST::Node, nil]
|
|
176
|
+
def send_node
|
|
177
|
+
@send_node ||= @tree&.find { |n| n.type == :send }
|
|
178
|
+
end
|
|
179
|
+
|
|
161
180
|
# @param node [Parser::AST::Node]
|
|
162
181
|
def hash_is_splatted? node
|
|
163
182
|
return false unless Parser.is_ast_node?(node) && node.type == :hash
|
|
@@ -6,6 +6,23 @@ module Solargraph
|
|
|
6
6
|
# @return [::Symbol] :class or :instance
|
|
7
7
|
attr_reader :scope
|
|
8
8
|
|
|
9
|
+
# Override the pin's scope.
|
|
10
|
+
#
|
|
11
|
+
# Scope is normally determined by the syntax that declared the pin, but
|
|
12
|
+
# YARD's `@!scope` directive can change it after the fact. Any values
|
|
13
|
+
# derived from the scope, such as the pin's path and context, are
|
|
14
|
+
# recalculated.
|
|
15
|
+
#
|
|
16
|
+
# @param scope [::Symbol] :class or :instance
|
|
17
|
+
# @return [void]
|
|
18
|
+
def scope= scope
|
|
19
|
+
return if @scope == scope
|
|
20
|
+
|
|
21
|
+
@scope = scope
|
|
22
|
+
# remove cached values generated from scope
|
|
23
|
+
reset_generated!
|
|
24
|
+
end
|
|
25
|
+
|
|
9
26
|
# @param scope [::Symbol] :class or :instance
|
|
10
27
|
# @param generics [::Array<Pin::String>, nil]
|
|
11
28
|
# @param generic_defaults [Hash{String => ComplexType}]
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
module Pin
|
|
5
|
+
# A method parameter with a literal value used in a factory method.
|
|
6
|
+
#
|
|
7
|
+
# @example
|
|
8
|
+
# RSpec.shared_examples 'some examples'
|
|
9
|
+
#
|
|
10
|
+
# FactoryParameter.new(
|
|
11
|
+
# method_name: 'shared_examples',
|
|
12
|
+
# method_namespace: 'RSpec',
|
|
13
|
+
# method_scope: :class,
|
|
14
|
+
# param_name: 'name',
|
|
15
|
+
# value: 'some examples',
|
|
16
|
+
# decl: :arg,
|
|
17
|
+
# return_type: 'void'
|
|
18
|
+
# )
|
|
19
|
+
class FactoryParameter < Base
|
|
20
|
+
# @return [String]
|
|
21
|
+
attr_reader :method_name
|
|
22
|
+
# @return [String]
|
|
23
|
+
attr_reader :method_namespace
|
|
24
|
+
# @return [Symbol] :class or :instance
|
|
25
|
+
attr_reader :method_scope
|
|
26
|
+
# @return [String, nil]
|
|
27
|
+
attr_reader :param_name
|
|
28
|
+
# @return [::String, ::Symbol] The literal value
|
|
29
|
+
attr_reader :value
|
|
30
|
+
# @return [::Symbol] :arg, :optarg, :kwarg, :kwoptarg, :restarg, :kwrestarg, :block, :blockarg
|
|
31
|
+
attr_reader :decl
|
|
32
|
+
# @return [Location, nil]
|
|
33
|
+
attr_reader :location
|
|
34
|
+
|
|
35
|
+
# @param method_name [String] The name of the method that this parameter belongs to
|
|
36
|
+
# @param method_namespace [String] The class of the method that this parameter belongs to
|
|
37
|
+
# @param method_scope [Symbol] The scope of the method, either :class or :instance
|
|
38
|
+
# @param param_name [String, nil] The name of the parameter
|
|
39
|
+
# @param value [String, Symbol] The value of the parameter
|
|
40
|
+
# @param decl [::Symbol] :arg, :kwarg
|
|
41
|
+
# @param location [Location, nil] The location of the parameter in the source code
|
|
42
|
+
# @param return_type [String, nil] The return type of the method that this parameter belongs to
|
|
43
|
+
def initialize method_name:,
|
|
44
|
+
method_namespace:,
|
|
45
|
+
method_scope:,
|
|
46
|
+
param_name:,
|
|
47
|
+
value:,
|
|
48
|
+
return_type:,
|
|
49
|
+
decl: :arg,
|
|
50
|
+
location: nil
|
|
51
|
+
super(location: location)
|
|
52
|
+
@method_name = method_name
|
|
53
|
+
@method_namespace = method_namespace
|
|
54
|
+
@method_scope = method_scope
|
|
55
|
+
@param_name = param_name
|
|
56
|
+
@value = value
|
|
57
|
+
@decl = decl
|
|
58
|
+
@return_type = return_type
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def name
|
|
62
|
+
param_name
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def text_documentation
|
|
66
|
+
"#{method_path}(#{param_name}) = #{value.inspect}"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# @return [String]
|
|
70
|
+
def method_path
|
|
71
|
+
# @sg-ignore false failure on method_scope "Wrong argument type for Solargraph::Pin::Base#==: other expected
|
|
72
|
+
# Solargraph::Pin::Base, received :instance"
|
|
73
|
+
@method_path ||= "#{method_namespace}#{method_scope == :instance ? '#' : '.'}#{method_name}"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
def inner_desc
|
|
79
|
+
"method_path=#{method_path}, value=#{value.inspect}, decl=#{decl.inspect}, " \
|
|
80
|
+
"return_type=#{return_type&.to_s || 'nil'}"
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
data/lib/solargraph/pin.rb
CHANGED
|
@@ -38,6 +38,7 @@ module Solargraph
|
|
|
38
38
|
autoload :Until, 'solargraph/pin/until'
|
|
39
39
|
autoload :While, 'solargraph/pin/while'
|
|
40
40
|
autoload :Callable, 'solargraph/pin/callable'
|
|
41
|
+
autoload :FactoryParameter, 'solargraph/pin/factory_parameter'
|
|
41
42
|
autoload :CompoundStatement,
|
|
42
43
|
'solargraph/pin/compound_statement'
|
|
43
44
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
module RbsMap
|
|
5
|
+
class Base
|
|
6
|
+
def pins
|
|
7
|
+
@pins ||= RbsMap::Conversions.new(loader: loader).pins
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# @return [RBS::Repository]
|
|
11
|
+
def repository
|
|
12
|
+
@repository ||= RBS::Repository.new(no_stdlib: true)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# @return [RBS::EnvironmentLoader]
|
|
16
|
+
def loader
|
|
17
|
+
@loader ||= RBS::EnvironmentLoader.new(core_root: nil, repository: repository)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# @param path [String]
|
|
21
|
+
# @return [Array<Pin::Base>]
|
|
22
|
+
def path_pins path
|
|
23
|
+
pins.select { |p| p.path == path }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.pins(...)
|
|
27
|
+
new(...).pins
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
require 'rbs'
|
|
4
4
|
|
|
5
5
|
module Solargraph
|
|
6
|
-
|
|
6
|
+
module RbsMap
|
|
7
7
|
# Functions for converting RBS declarations to Solargraph pins
|
|
8
8
|
#
|
|
9
9
|
class Conversions
|
|
@@ -49,6 +49,8 @@ module Solargraph
|
|
|
49
49
|
return
|
|
50
50
|
end
|
|
51
51
|
environment.declarations.each { |decl| convert_decl_to_pin(decl, Solargraph::Pin::ROOT_PIN) }
|
|
52
|
+
rescue RBS::DuplicatedDeclarationError => e
|
|
53
|
+
Solargraph.logger.warn "RBS conversion failed due to duplicate declarations: [#{e.class}] #{e.message}"
|
|
52
54
|
end
|
|
53
55
|
|
|
54
56
|
# @param decl [RBS::AST::Declarations::Base]
|
|
@@ -1,39 +1,32 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Solargraph
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class CoreMap
|
|
8
|
-
include Logging
|
|
4
|
+
module RbsMap
|
|
5
|
+
class Core < Base
|
|
6
|
+
FILLS_DIRECTORY = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'rbs', 'fills'))
|
|
9
7
|
|
|
10
|
-
def
|
|
11
|
-
|
|
8
|
+
def pins
|
|
9
|
+
@pins ||= generate_pins
|
|
12
10
|
end
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
# @return [RBS::EnvironmentLoader]
|
|
13
|
+
def loader
|
|
14
|
+
@loader ||= RBS::EnvironmentLoader.new(repository: repository)
|
|
15
|
+
end
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def pins out: $stderr
|
|
21
|
-
return @pins if @pins
|
|
22
|
-
@pins = cache_core(out: out)
|
|
17
|
+
def repository
|
|
18
|
+
@repository ||= RBS::Repository.new(no_stdlib: false)
|
|
23
19
|
end
|
|
24
20
|
|
|
25
|
-
|
|
21
|
+
private
|
|
22
|
+
|
|
26
23
|
# @return [Array<Pin::Base>]
|
|
27
|
-
def
|
|
28
|
-
new_pins =
|
|
29
|
-
cache = PinCache.deserialize_core
|
|
30
|
-
return cache if cache
|
|
31
|
-
new_pins.concat conversions.pins
|
|
24
|
+
def generate_pins
|
|
25
|
+
new_pins = RbsMap::Conversions.new(loader: loader).pins
|
|
32
26
|
|
|
33
27
|
# Avoid RBS::DuplicatedDeclarationError by loading in a different EnvironmentLoader
|
|
34
28
|
fill_loader = RBS::EnvironmentLoader.new(core_root: nil, repository: RBS::Repository.new(no_stdlib: false))
|
|
35
29
|
fill_loader.add(path: Pathname(FILLS_DIRECTORY))
|
|
36
|
-
out&.puts 'Caching RBS pins for Ruby core'
|
|
37
30
|
fill_conversions = Conversions.new(loader: fill_loader)
|
|
38
31
|
new_pins.concat fill_conversions.pins
|
|
39
32
|
|
|
@@ -42,23 +35,9 @@ module Solargraph
|
|
|
42
35
|
|
|
43
36
|
# process overrides, then remove any which couldn't be resolved
|
|
44
37
|
processed = ApiMap::Store.new(new_pins).pins.reject { |p| p.is_a?(Solargraph::Pin::Reference::Override) }
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
new_pins
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
private
|
|
53
|
-
|
|
54
|
-
# @return [RBS::EnvironmentLoader]
|
|
55
|
-
def loader
|
|
56
|
-
@loader ||= RBS::EnvironmentLoader.new(repository: RBS::Repository.new(no_stdlib: false))
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
# @return [Conversions]
|
|
60
|
-
def conversions
|
|
61
|
-
@conversions ||= Conversions.new(loader: loader)
|
|
38
|
+
# serial = Marshal.dump(processed)
|
|
39
|
+
# File.write cache_file, serial, mode: 'wb'
|
|
40
|
+
processed
|
|
62
41
|
end
|
|
63
42
|
end
|
|
64
43
|
end
|