solargraph 0.55.3 → 0.55.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/.github/workflows/plugins.yml +2 -0
- data/.github/workflows/typecheck.yml +3 -1
- data/.gitignore +2 -0
- data/CHANGELOG.md +7 -1
- data/README.md +13 -3
- data/lib/solargraph/api_map/index.rb +23 -15
- data/lib/solargraph/api_map/store.rb +8 -4
- data/lib/solargraph/api_map.rb +150 -57
- data/lib/solargraph/complex_type/type_methods.rb +6 -1
- data/lib/solargraph/complex_type/unique_type.rb +10 -2
- data/lib/solargraph/convention/base.rb +3 -3
- data/lib/solargraph/convention.rb +3 -3
- data/lib/solargraph/doc_map.rb +192 -46
- data/lib/solargraph/gem_pins.rb +53 -37
- data/lib/solargraph/language_server/host.rb +11 -2
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +2 -0
- data/lib/solargraph/language_server/message/extended/document.rb +5 -2
- data/lib/solargraph/language_server/message/extended/document_gems.rb +3 -3
- data/lib/solargraph/library.rb +7 -4
- data/lib/solargraph/location.rb +13 -0
- data/lib/solargraph/logging.rb +1 -0
- data/lib/solargraph/parser/comment_ripper.rb +1 -0
- data/lib/solargraph/parser/flow_sensitive_typing.rb +2 -1
- data/lib/solargraph/parser/node_processor.rb +3 -1
- data/lib/solargraph/parser/parser_gem/class_methods.rb +5 -8
- data/lib/solargraph/parser/parser_gem/node_methods.rb +1 -1
- data/lib/solargraph/parser/parser_gem/node_processors/alias_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +4 -2
- data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +4 -2
- data/lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb +4 -3
- data/lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +6 -3
- data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +4 -2
- data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb +6 -4
- data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +4 -3
- data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +28 -16
- data/lib/solargraph/parser/parser_gem/node_processors/sym_node.rb +2 -1
- data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +1 -0
- data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +1 -0
- data/lib/solargraph/parser/region.rb +1 -1
- data/lib/solargraph/pin/base.rb +295 -28
- data/lib/solargraph/pin/base_variable.rb +9 -8
- data/lib/solargraph/pin/callable.rb +74 -3
- data/lib/solargraph/pin/closure.rb +18 -1
- data/lib/solargraph/pin/common.rb +5 -0
- data/lib/solargraph/pin/delegated_method.rb +2 -0
- data/lib/solargraph/pin/documenting.rb +16 -0
- data/lib/solargraph/pin/keyword.rb +7 -2
- data/lib/solargraph/pin/local_variable.rb +8 -5
- data/lib/solargraph/pin/method.rb +147 -25
- data/lib/solargraph/pin/namespace.rb +7 -2
- data/lib/solargraph/pin/parameter.rb +47 -6
- data/lib/solargraph/pin/proxy_type.rb +3 -3
- data/lib/solargraph/pin/reference/override.rb +10 -6
- data/lib/solargraph/pin/reference/require.rb +2 -2
- data/lib/solargraph/pin/signature.rb +42 -0
- data/lib/solargraph/pin/singleton.rb +1 -1
- data/lib/solargraph/pin/symbol.rb +3 -2
- data/lib/solargraph/pin.rb +1 -1
- data/lib/solargraph/pin_cache.rb +185 -0
- data/lib/solargraph/position.rb +9 -0
- data/lib/solargraph/range.rb +9 -0
- data/lib/solargraph/rbs_map/conversions.rb +183 -56
- data/lib/solargraph/rbs_map/core_fills.rb +24 -15
- data/lib/solargraph/rbs_map/core_map.rb +34 -11
- data/lib/solargraph/rbs_map/stdlib_map.rb +15 -5
- data/lib/solargraph/rbs_map.rb +74 -17
- data/lib/solargraph/shell.rb +12 -15
- data/lib/solargraph/source/chain/array.rb +7 -4
- 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 +8 -7
- data/lib/solargraph/source/chain/hash.rb +1 -1
- data/lib/solargraph/source/chain/head.rb +1 -1
- data/lib/solargraph/source/chain/if.rb +1 -1
- data/lib/solargraph/source/chain/literal.rb +2 -2
- data/lib/solargraph/source/chain/or.rb +1 -1
- data/lib/solargraph/source/chain.rb +2 -2
- data/lib/solargraph/source_map/mapper.rb +9 -5
- data/lib/solargraph/source_map.rb +0 -17
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/views/_method.erb +10 -10
- data/lib/solargraph/views/_namespace.erb +3 -3
- data/lib/solargraph/views/document.erb +10 -10
- data/lib/solargraph/workspace.rb +15 -5
- data/lib/solargraph/yard_map/mapper/to_constant.rb +4 -2
- data/lib/solargraph/yard_map/mapper/to_method.rb +14 -1
- data/lib/solargraph/yard_map/mapper/to_namespace.rb +4 -2
- data/lib/solargraph/yard_map/mapper.rb +4 -3
- data/lib/solargraph/yard_map/to_method.rb +4 -2
- data/lib/solargraph/yardoc.rb +3 -11
- data/lib/solargraph.rb +18 -1
- data/rbs/fills/tuple.rbs +150 -0
- data/rbs_collection.yaml +19 -0
- data/solargraph.gemspec +1 -0
- metadata +20 -7
- data/lib/solargraph/cache.rb +0 -77
data/lib/solargraph/doc_map.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'pathname'
|
4
|
+
require 'benchmark'
|
5
|
+
|
3
6
|
module Solargraph
|
4
7
|
# A collection of pins generated from required gems.
|
5
8
|
#
|
@@ -8,6 +11,7 @@ module Solargraph
|
|
8
11
|
|
9
12
|
# @return [Array<String>]
|
10
13
|
attr_reader :requires
|
14
|
+
alias required requires
|
11
15
|
|
12
16
|
# @return [Array<Gem::Specification>]
|
13
17
|
attr_reader :preferences
|
@@ -16,11 +20,27 @@ module Solargraph
|
|
16
20
|
attr_reader :pins
|
17
21
|
|
18
22
|
# @return [Array<Gem::Specification>]
|
19
|
-
|
23
|
+
def uncached_gemspecs
|
24
|
+
(uncached_yard_gemspecs + uncached_rbs_collection_gemspecs).sort.
|
25
|
+
uniq { |gemspec| "#{gemspec.name}:#{gemspec.version}" }
|
26
|
+
end
|
27
|
+
|
28
|
+
# @return [Array<Gem::Specification>]
|
29
|
+
attr_reader :uncached_yard_gemspecs
|
30
|
+
|
31
|
+
# @return [Array<Gem::Specification>]
|
32
|
+
attr_reader :uncached_rbs_collection_gemspecs
|
33
|
+
|
34
|
+
attr_reader :rbs_collection_path
|
35
|
+
|
36
|
+
attr_reader :rbs_collection_config_path
|
20
37
|
|
21
38
|
# @return [Workspace, nil]
|
22
39
|
attr_reader :workspace
|
23
40
|
|
41
|
+
# @return [Environ]
|
42
|
+
attr_reader :environ
|
43
|
+
|
24
44
|
# @param requires [Array<String>]
|
25
45
|
# @param preferences [Array<Gem::Specification>]
|
26
46
|
# @param workspace [Workspace, nil]
|
@@ -28,7 +48,51 @@ module Solargraph
|
|
28
48
|
@requires = requires.compact
|
29
49
|
@preferences = preferences.compact
|
30
50
|
@workspace = workspace
|
31
|
-
|
51
|
+
@rbs_collection_path = workspace&.rbs_collection_path
|
52
|
+
@rbs_collection_config_path = workspace&.rbs_collection_config_path
|
53
|
+
@environ = Convention.for_global(self)
|
54
|
+
load_serialized_gem_pins
|
55
|
+
pins.concat @environ.pins
|
56
|
+
end
|
57
|
+
|
58
|
+
def cache_all!(out)
|
59
|
+
# if we log at debug level:
|
60
|
+
if logger.info?
|
61
|
+
gem_desc = uncached_gemspecs.map { |gemspec| "#{gemspec.name}:#{gemspec.version}" }.join(', ')
|
62
|
+
logger.info "Caching pins for gems: #{gem_desc}" unless uncached_gemspecs.empty?
|
63
|
+
end
|
64
|
+
logger.debug { "Caching for YARD: #{uncached_yard_gemspecs.map(&:name)}" }
|
65
|
+
logger.debug { "Caching for RBS collection: #{uncached_rbs_collection_gemspecs.map(&:name)}" }
|
66
|
+
load_serialized_gem_pins
|
67
|
+
uncached_gemspecs.each do |gemspec|
|
68
|
+
cache(gemspec, out: out)
|
69
|
+
end
|
70
|
+
load_serialized_gem_pins
|
71
|
+
@uncached_rbs_collection_gemspecs = []
|
72
|
+
@uncached_yard_gemspecs = []
|
73
|
+
end
|
74
|
+
|
75
|
+
def cache_yard_pins(gemspec, out)
|
76
|
+
pins = GemPins.build_yard_pins(gemspec)
|
77
|
+
PinCache.serialize_yard_gem(gemspec, pins)
|
78
|
+
logger.info { "Cached #{pins.length} YARD pins for gem #{gemspec.name}:#{gemspec.version}" } unless pins.empty?
|
79
|
+
end
|
80
|
+
|
81
|
+
def cache_rbs_collection_pins(gemspec, out)
|
82
|
+
rbs_map = RbsMap.from_gemspec(gemspec, rbs_collection_path, rbs_collection_config_path)
|
83
|
+
pins = rbs_map.pins
|
84
|
+
rbs_version_cache_key = rbs_map.cache_key
|
85
|
+
# cache pins even if result is zero, so we don't retry building pins
|
86
|
+
pins ||= []
|
87
|
+
PinCache.serialize_rbs_collection_gem(gemspec, rbs_version_cache_key, pins)
|
88
|
+
logger.info { "Cached #{pins.length} RBS collection pins for gem #{gemspec.name} #{gemspec.version} with cache_key #{rbs_version_cache_key.inspect}" unless pins.empty? }
|
89
|
+
end
|
90
|
+
|
91
|
+
# @param gemspec [Gem::Specification]
|
92
|
+
def cache(gemspec, rebuild: false, out: nil)
|
93
|
+
out.puts("Caching pins for gem #{gemspec.name}:#{gemspec.version}") if out
|
94
|
+
cache_yard_pins(gemspec, out) if uncached_yard_gemspecs.include?(gemspec) || rebuild
|
95
|
+
cache_rbs_collection_pins(gemspec, out) if uncached_rbs_collection_gemspecs.include?(gemspec) || rebuild
|
32
96
|
end
|
33
97
|
|
34
98
|
# @return [Array<Gem::Specification>]
|
@@ -41,9 +105,24 @@ module Solargraph
|
|
41
105
|
@unresolved_requires ||= required_gems_map.select { |_, gemspecs| gemspecs.nil? }.keys
|
42
106
|
end
|
43
107
|
|
44
|
-
|
45
|
-
|
46
|
-
|
108
|
+
def self.all_yard_gems_in_memory
|
109
|
+
@yard_gems_in_memory ||= {}
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.all_rbs_collection_gems_in_memory
|
113
|
+
@rbs_collection_gems_in_memory ||= {}
|
114
|
+
end
|
115
|
+
|
116
|
+
def yard_pins_in_memory
|
117
|
+
self.class.all_yard_gems_in_memory
|
118
|
+
end
|
119
|
+
|
120
|
+
def rbs_collection_pins_in_memory
|
121
|
+
self.class.all_rbs_collection_gems_in_memory[rbs_collection_path] ||= {}
|
122
|
+
end
|
123
|
+
|
124
|
+
def combined_pins_in_memory
|
125
|
+
@combined_pins_in_memory ||= {}
|
47
126
|
end
|
48
127
|
|
49
128
|
# @return [Set<Gem::Specification>]
|
@@ -54,20 +133,29 @@ module Solargraph
|
|
54
133
|
private
|
55
134
|
|
56
135
|
# @return [void]
|
57
|
-
def
|
136
|
+
def load_serialized_gem_pins
|
58
137
|
@pins = []
|
59
|
-
@
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
138
|
+
@uncached_yard_gemspecs = []
|
139
|
+
@uncached_rbs_collection_gemspecs = []
|
140
|
+
with_gemspecs, without_gemspecs = required_gems_map.partition { |_, v| v }
|
141
|
+
paths = Hash[without_gemspecs].keys
|
142
|
+
gemspecs = Hash[with_gemspecs].values.flatten.compact + dependencies.to_a
|
143
|
+
|
144
|
+
paths.each do |path|
|
145
|
+
rbs_pins = deserialize_stdlib_rbs_map path
|
146
|
+
end
|
147
|
+
|
148
|
+
logger.debug { "DocMap#load_serialized_gem_pins: Combining pins..." }
|
149
|
+
time = Benchmark.measure do
|
150
|
+
gemspecs.each do |gemspec|
|
151
|
+
pins = deserialize_combined_pin_cache gemspec
|
152
|
+
@pins.concat pins if pins
|
67
153
|
end
|
68
154
|
end
|
69
|
-
|
70
|
-
@
|
155
|
+
logger.info { "DocMap#load_serialized_gem_pins: Loaded and processed serialized pins together in #{time.real} seconds" }
|
156
|
+
@uncached_yard_gemspecs.uniq!
|
157
|
+
@uncached_rbs_collection_gemspecs.uniq!
|
158
|
+
nil
|
71
159
|
end
|
72
160
|
|
73
161
|
# @return [Hash{String => Array<Gem::Specification>}]
|
@@ -80,32 +168,97 @@ module Solargraph
|
|
80
168
|
@preference_map ||= preferences.to_h { |gemspec| [gemspec.name, gemspec] }
|
81
169
|
end
|
82
170
|
|
171
|
+
# @param gemspec [Gem::Specification]
|
172
|
+
# @return [Array<Pin::Base>]
|
173
|
+
def deserialize_yard_pin_cache gemspec
|
174
|
+
if yard_pins_in_memory.key?([gemspec.name, gemspec.version])
|
175
|
+
return yard_pins_in_memory[[gemspec.name, gemspec.version]]
|
176
|
+
end
|
177
|
+
|
178
|
+
cached = PinCache.deserialize_yard_gem(gemspec)
|
179
|
+
if cached
|
180
|
+
logger.info { "Loaded #{cached.length} cached YARD pins from #{gemspec.name}:#{gemspec.version}" }
|
181
|
+
yard_pins_in_memory[[gemspec.name, gemspec.version]] = cached
|
182
|
+
cached
|
183
|
+
else
|
184
|
+
logger.debug "No YARD pin cache for #{gemspec.name}:#{gemspec.version}"
|
185
|
+
@uncached_yard_gemspecs.push gemspec
|
186
|
+
nil
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
83
190
|
# @param gemspec [Gem::Specification]
|
84
191
|
# @return [void]
|
85
|
-
def
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
192
|
+
def deserialize_combined_pin_cache(gemspec)
|
193
|
+
unless combined_pins_in_memory[[gemspec.name, gemspec.version]].nil?
|
194
|
+
return combined_pins_in_memory[[gemspec.name, gemspec.version]]
|
195
|
+
end
|
196
|
+
|
197
|
+
rbs_map = RbsMap.from_gemspec(gemspec, rbs_collection_path, rbs_collection_config_path)
|
198
|
+
rbs_version_cache_key = rbs_map.cache_key
|
199
|
+
|
200
|
+
cached = PinCache.deserialize_combined_gem(gemspec, rbs_version_cache_key)
|
201
|
+
if cached
|
202
|
+
logger.info { "Loaded #{cached.length} cached YARD pins from #{gemspec.name}:#{gemspec.version}" }
|
203
|
+
combined_pins_in_memory[[gemspec.name, gemspec.version]] = cached
|
204
|
+
return combined_pins_in_memory[[gemspec.name, gemspec.version]]
|
205
|
+
end
|
206
|
+
|
207
|
+
rbs_collection_pins = deserialize_rbs_collection_cache gemspec, rbs_version_cache_key
|
208
|
+
|
209
|
+
yard_pins = deserialize_yard_pin_cache gemspec
|
210
|
+
|
211
|
+
if !rbs_collection_pins.nil? && !yard_pins.nil?
|
212
|
+
logger.debug { "Combining pins for #{gemspec.name}:#{gemspec.version}" }
|
213
|
+
combined_pins = GemPins.combine(yard_pins, rbs_collection_pins)
|
214
|
+
PinCache.serialize_combined_gem(gemspec, rbs_version_cache_key, combined_pins)
|
215
|
+
combined_pins_in_memory[[gemspec.name, gemspec.version]] = combined_pins
|
216
|
+
logger.info { "Generated #{combined_pins_in_memory[[gemspec.name, gemspec.version]].length} combined pins for #{gemspec.name} #{gemspec.version}" }
|
217
|
+
return combined_pins
|
218
|
+
end
|
219
|
+
|
220
|
+
if !yard_pins.nil?
|
221
|
+
logger.debug { "Using only YARD pins for #{gemspec.name}:#{gemspec.version}" }
|
222
|
+
combined_pins_in_memory[[gemspec.name, gemspec.version]] = yard_pins
|
223
|
+
return combined_pins_in_memory[[gemspec.name, gemspec.version]]
|
224
|
+
elsif !rbs_collection_pins.nil?
|
225
|
+
logger.debug { "Using only RBS collection pins for #{gemspec.name}:#{gemspec.version}" }
|
226
|
+
combined_pins_in_memory[[gemspec.name, gemspec.version]] = rbs_collection_pins
|
227
|
+
return combined_pins_in_memory[[gemspec.name, gemspec.version]]
|
93
228
|
else
|
94
|
-
|
95
|
-
|
229
|
+
logger.debug { "Pins not yet cached for #{gemspec.name}:#{gemspec.version}" }
|
230
|
+
return nil
|
96
231
|
end
|
97
232
|
end
|
98
233
|
|
99
234
|
# @param path [String] require path that might be in the RBS stdlib collection
|
100
235
|
# @return [void]
|
101
|
-
def
|
236
|
+
def deserialize_stdlib_rbs_map path
|
102
237
|
map = RbsMap::StdlibMap.load(path)
|
103
238
|
if map.resolved?
|
104
|
-
|
239
|
+
logger.debug { "Loading stdlib pins for #{path}" }
|
105
240
|
@pins.concat map.pins
|
241
|
+
logger.debug { "Loaded #{map.pins.length} stdlib pins for #{path}" }
|
242
|
+
map.pins
|
106
243
|
else
|
107
244
|
# @todo Temporarily ignoring unresolved `require 'set'`
|
108
|
-
|
245
|
+
logger.debug { "Require path #{path} could not be resolved in RBS" } unless path == 'set'
|
246
|
+
nil
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
# @return [Array<Pin::Base>, nil]
|
251
|
+
def deserialize_rbs_collection_cache gemspec, rbs_version_cache_key
|
252
|
+
return if rbs_collection_pins_in_memory.key?([gemspec, rbs_version_cache_key])
|
253
|
+
cached = PinCache.deserialize_rbs_collection_gem(gemspec, rbs_version_cache_key)
|
254
|
+
if cached
|
255
|
+
logger.info { "Loaded #{cached.length} pins from RBS collection cache for #{gemspec.name}:#{gemspec.version}" } unless cached.empty?
|
256
|
+
rbs_collection_pins_in_memory[[gemspec, rbs_version_cache_key]] = cached
|
257
|
+
cached
|
258
|
+
else
|
259
|
+
logger.debug "No RBS collection pin cache for #{gemspec.name} #{gemspec.version}"
|
260
|
+
@uncached_rbs_collection_gemspecs.push gemspec
|
261
|
+
nil
|
109
262
|
end
|
110
263
|
end
|
111
264
|
|
@@ -119,18 +272,6 @@ module Solargraph
|
|
119
272
|
true
|
120
273
|
end
|
121
274
|
|
122
|
-
# @param gemspec [Gem::Specification]
|
123
|
-
def update_from_collection gemspec, gempins
|
124
|
-
return gempins unless workspace&.rbs_collection_path && File.directory?(workspace&.rbs_collection_path)
|
125
|
-
return gempins if RbsMap.new(gemspec.name, gemspec.version).resolved?
|
126
|
-
|
127
|
-
rbs_map = RbsMap.new(gemspec.name, gemspec.version, directories: [workspace&.rbs_collection_path])
|
128
|
-
return gempins unless rbs_map.resolved?
|
129
|
-
|
130
|
-
Solargraph.logger.info "Updating #{gemspec.name} #{gemspec.version} from collection"
|
131
|
-
GemPins.combine(gempins, rbs_map)
|
132
|
-
end
|
133
|
-
|
134
275
|
# @param path [String]
|
135
276
|
# @return [::Array<Gem::Specification>, nil]
|
136
277
|
def resolve_path_to_gemspecs path
|
@@ -149,7 +290,7 @@ module Solargraph
|
|
149
290
|
file = "lib/#{path}.rb"
|
150
291
|
gemspec = potential_gemspec if potential_gemspec.files.any? { |gemspec_file| file == gemspec_file }
|
151
292
|
rescue Gem::MissingSpecError
|
152
|
-
|
293
|
+
logger.debug { "Require path #{path} could not be resolved to a gem via find_by_path or guess of #{gem_name_guess}" }
|
153
294
|
[]
|
154
295
|
end
|
155
296
|
end
|
@@ -187,7 +328,7 @@ module Solargraph
|
|
187
328
|
dep ||= Gem::Specification.find_by_name(spec.name, spec.requirement)
|
188
329
|
deps.merge fetch_dependencies(dep) if deps.add?(dep)
|
189
330
|
rescue Gem::MissingSpecError
|
190
|
-
Solargraph.logger.warn "Gem dependency #{spec.name} #{spec.requirement} for #{gemspec.name} not found."
|
331
|
+
Solargraph.logger.warn "Gem dependency #{spec.name} #{spec.requirement} for #{gemspec.name} not found in RubyGems."
|
191
332
|
end.to_a
|
192
333
|
end
|
193
334
|
|
@@ -197,6 +338,11 @@ module Solargraph
|
|
197
338
|
gemspec.dependencies - gemspec.development_dependencies
|
198
339
|
end
|
199
340
|
|
341
|
+
|
342
|
+
def inspect
|
343
|
+
self.class.inspect
|
344
|
+
end
|
345
|
+
|
200
346
|
def gemspecs_required_from_bundler
|
201
347
|
if workspace&.directory && Bundler.definition&.lockfile&.to_s&.start_with?(workspace.directory)
|
202
348
|
# Find only the gems bundler is now using
|
@@ -207,7 +353,7 @@ module Solargraph
|
|
207
353
|
logger.info("Could not find #{lazy_spec.name}:#{lazy_spec.version} with find_by_name, falling back to guess")
|
208
354
|
# can happen in local filesystem references
|
209
355
|
specs = resolve_path_to_gemspecs lazy_spec.name
|
210
|
-
logger.
|
356
|
+
logger.warn "Gem #{lazy_spec.name} #{lazy_spec.version} from bundle not found: #{e}" if specs.nil?
|
211
357
|
next specs
|
212
358
|
end.compact
|
213
359
|
else
|
@@ -229,13 +375,13 @@ module Solargraph
|
|
229
375
|
if s.success?
|
230
376
|
Solargraph.logger.debug "External bundle: #{o}"
|
231
377
|
hash = o && !o.empty? ? JSON.parse(o.split("\n").last) : {}
|
232
|
-
hash.
|
378
|
+
hash.flat_map do |name, version|
|
233
379
|
Gem::Specification.find_by_name(name, version)
|
234
380
|
rescue Gem::MissingSpecError => e
|
235
381
|
logger.info("Could not find #{name}:#{version} with find_by_name, falling back to guess")
|
236
382
|
# can happen in local filesystem references
|
237
383
|
specs = resolve_path_to_gemspecs name
|
238
|
-
logger.
|
384
|
+
logger.warn "Gem #{name} #{version} from bundle not found: #{e}" if specs.nil?
|
239
385
|
next specs
|
240
386
|
end.compact
|
241
387
|
else
|
data/lib/solargraph/gem_pins.rb
CHANGED
@@ -7,59 +7,75 @@ module Solargraph
|
|
7
7
|
# documentation.
|
8
8
|
#
|
9
9
|
module GemPins
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
class << self
|
11
|
+
include Logging
|
12
|
+
end
|
13
|
+
|
14
14
|
# @param gemspec [Gem::Specification]
|
15
15
|
# @return [Array<Pin::Base>]
|
16
|
-
def self.
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
def self.build_yard_pins(gemspec)
|
17
|
+
Yardoc.cache(gemspec) unless Yardoc.cached?(gemspec)
|
18
|
+
yardoc = Yardoc.load!(gemspec)
|
19
|
+
YardMap::Mapper.new(yardoc, gemspec).map
|
20
|
+
end
|
21
|
+
|
22
|
+
# @param pins [Array<Pin::Base>]
|
23
|
+
def self.combine_method_pins_by_path(pins)
|
24
|
+
# bad_pins = pins.select { |pin| pin.is_a?(Pin::Method) && pin.path == 'StringIO.open' && pin.source == :rbs }; raise "wtf: #{bad_pins}" if bad_pins.length > 1
|
25
|
+
method_pins, alias_pins = pins.partition { |pin| pin.class == Pin::Method }
|
26
|
+
by_path = method_pins.group_by(&:path)
|
27
|
+
by_path.transform_values! do |pins|
|
28
|
+
GemPins.combine_method_pins(*pins)
|
29
|
+
end
|
30
|
+
by_path.values + alias_pins
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.combine_method_pins(*pins)
|
34
|
+
out = pins.reduce(nil) do |memo, pin|
|
35
|
+
next pin if memo.nil?
|
36
|
+
if memo == pin && memo.source != :combined
|
37
|
+
# @todo we should track down situations where we are handled
|
38
|
+
# the same pin from the same source here and eliminate them -
|
39
|
+
# this is an efficiency workaround for now
|
40
|
+
next memo
|
41
|
+
end
|
42
|
+
memo.combine_with(pin)
|
43
|
+
end
|
44
|
+
logger.debug { "GemPins.combine_method_pins(pins.length=#{pins.length}, pins=#{pins}) => #{out.inspect}" }
|
45
|
+
out
|
20
46
|
end
|
21
47
|
|
22
48
|
# @param yard_pins [Array<Pin::Base>]
|
23
49
|
# @param rbs_map [RbsMap]
|
24
50
|
# @return [Array<Pin::Base>]
|
25
|
-
def self.combine(yard_pins,
|
51
|
+
def self.combine(yard_pins, rbs_pins)
|
26
52
|
in_yard = Set.new
|
27
|
-
|
28
|
-
|
29
|
-
|
53
|
+
rbs_api_map = Solargraph::ApiMap.new(pins: rbs_pins)
|
54
|
+
combined = yard_pins.map do |yard_pin|
|
55
|
+
in_yard.add yard_pin.path
|
56
|
+
rbs_pin = rbs_api_map.get_path_pins(yard_pin.path).filter { |pin| pin.is_a? Pin::Method }.first
|
57
|
+
next yard_pin unless rbs_pin && yard_pin.class == Pin::Method
|
30
58
|
|
31
|
-
|
32
|
-
|
59
|
+
unless rbs_pin
|
60
|
+
logger.debug { "GemPins.combine: No rbs pin for #{yard_pin.path} - using YARD's '#{yard_pin.inspect} (return_type=#{yard_pin.return_type}; signatures=#{yard_pin.signatures})" }
|
61
|
+
next yard_pin
|
62
|
+
end
|
33
63
|
|
34
|
-
|
35
|
-
yard.
|
36
|
-
|
37
|
-
closure: yard.closure,
|
38
|
-
name: yard.name,
|
39
|
-
comments: yard.comments,
|
40
|
-
scope: yard.scope,
|
41
|
-
parameters: rbs.parameters,
|
42
|
-
generics: rbs.generics,
|
43
|
-
node: yard.node,
|
44
|
-
signatures: yard.signatures,
|
45
|
-
return_type: best_return_type(rbs.return_type, yard.return_type)
|
46
|
-
)
|
64
|
+
out = combine_method_pins(rbs_pin, yard_pin)
|
65
|
+
logger.debug { "GemPins.combine: Combining yard.path=#{yard_pin.path} - rbs=#{rbs_pin.inspect} with yard=#{yard_pin.inspect} into #{out}" }
|
66
|
+
out
|
47
67
|
end
|
48
|
-
|
49
|
-
|
68
|
+
in_rbs_only = rbs_pins.select do |pin|
|
69
|
+
pin.path.nil? || !in_yard.include?(pin.path)
|
70
|
+
end
|
71
|
+
out = combined + in_rbs_only
|
72
|
+
logger.debug { "GemPins#combine: Returning #{out.length} combined pins" }
|
73
|
+
out
|
50
74
|
end
|
51
75
|
|
52
76
|
class << self
|
53
77
|
private
|
54
78
|
|
55
|
-
# @param gemspec [Gem::Specification]
|
56
|
-
# @return [Array<Pin::Base>]
|
57
|
-
def build_yard_pins(gemspec)
|
58
|
-
Yardoc.cache(gemspec) unless Yardoc.cached?(gemspec)
|
59
|
-
yardoc = Yardoc.load!(gemspec)
|
60
|
-
YardMap::Mapper.new(yardoc, gemspec).map
|
61
|
-
end
|
62
|
-
|
63
79
|
# Select the first defined type.
|
64
80
|
#
|
65
81
|
# @param choices [Array<ComplexType>]
|
@@ -299,6 +299,10 @@ module Solargraph
|
|
299
299
|
end
|
300
300
|
end
|
301
301
|
|
302
|
+
def command_path
|
303
|
+
options['commandPath'] || 'solargraph'
|
304
|
+
end
|
305
|
+
|
302
306
|
# Prepare multiple folders.
|
303
307
|
#
|
304
308
|
# @param array [Array<Hash{String => String}>]
|
@@ -501,7 +505,8 @@ module Solargraph
|
|
501
505
|
parameters: pin.parameters,
|
502
506
|
return_type: ComplexType.try_parse(params['data']['path']),
|
503
507
|
comments: pin.comments,
|
504
|
-
closure: pin.closure
|
508
|
+
closure: pin.closure,
|
509
|
+
source: :solargraph
|
505
510
|
)
|
506
511
|
end)
|
507
512
|
end
|
@@ -597,7 +602,11 @@ module Solargraph
|
|
597
602
|
# @return [Array]
|
598
603
|
def document query
|
599
604
|
result = []
|
600
|
-
libraries.
|
605
|
+
if libraries.empty?
|
606
|
+
result.concat generic_library.document(query)
|
607
|
+
else
|
608
|
+
libraries.each { |lib| result.concat lib.document(query) }
|
609
|
+
end
|
601
610
|
result
|
602
611
|
end
|
603
612
|
|
@@ -83,6 +83,8 @@ module Solargraph
|
|
83
83
|
@fetched = true
|
84
84
|
begin
|
85
85
|
@available ||= begin
|
86
|
+
# @sg-ignore
|
87
|
+
# @type [Gem::Dependency, nil]
|
86
88
|
tuple = CheckGemVersion.fetcher.search_for_dependency(Gem::Dependency.new('solargraph')).flatten.first
|
87
89
|
if tuple.nil?
|
88
90
|
@error = 'An error occurred fetching the gem data'
|
@@ -6,12 +6,15 @@ module Solargraph
|
|
6
6
|
module Extended
|
7
7
|
class Document < Base
|
8
8
|
def process
|
9
|
-
|
9
|
+
api_map, pins = host.document(params['query'])
|
10
10
|
page = Solargraph::Page.new(host.options['viewsPath'])
|
11
|
-
content = page.render('document', layout: true, locals: {
|
11
|
+
content = page.render('document', layout: true, locals: { api_map: api_map, pins: pins })
|
12
12
|
set_result(
|
13
13
|
content: content
|
14
14
|
)
|
15
|
+
rescue StandardError => e
|
16
|
+
Solargraph.logger.warn "Error processing document: [#{e.class}] #{e.message}"
|
17
|
+
Solargraph.logger.debug e.backtrace.join("\n")
|
15
18
|
end
|
16
19
|
end
|
17
20
|
end
|
@@ -11,9 +11,9 @@ module Solargraph
|
|
11
11
|
#
|
12
12
|
class DocumentGems < Base
|
13
13
|
def process
|
14
|
-
cmd =
|
15
|
-
cmd
|
16
|
-
o, s = Open3.capture2(cmd)
|
14
|
+
cmd = [host.command_path, 'gems']
|
15
|
+
cmd.push '--rebuild' if params['rebuild']
|
16
|
+
o, s = Open3.capture2(*cmd)
|
17
17
|
if s != 0
|
18
18
|
host.show_message "An error occurred while building gem documentation.", LanguageServer::MessageTypes::ERROR
|
19
19
|
set_result({
|
data/lib/solargraph/library.rb
CHANGED
@@ -327,9 +327,10 @@ module Solargraph
|
|
327
327
|
|
328
328
|
# @param query [String]
|
329
329
|
# @return [Enumerable<YARD::CodeObjects::Base>]
|
330
|
+
# @return [Array(ApiMap, Enumerable<Pin::Base>)]
|
330
331
|
def document query
|
331
332
|
sync_catalog
|
332
|
-
mutex.synchronize { api_map.
|
333
|
+
mutex.synchronize { [api_map, api_map.get_path_pins(query)] }
|
333
334
|
end
|
334
335
|
|
335
336
|
# @param query [String]
|
@@ -586,8 +587,9 @@ module Solargraph
|
|
586
587
|
|
587
588
|
# @return [void]
|
588
589
|
def cache_next_gemspec
|
589
|
-
return if @
|
590
|
-
spec = api_map.
|
590
|
+
return if @cache_progres
|
591
|
+
spec = (api_map.uncached_yard_gemspecs + api_map.uncached_rbs_collection_gemspecs).
|
592
|
+
find { |spec| !cache_errors.include?(spec) }
|
591
593
|
return end_cache_progress unless spec
|
592
594
|
|
593
595
|
pending = api_map.uncached_gemspecs.length - cache_errors.length - 1
|
@@ -654,7 +656,8 @@ module Solargraph
|
|
654
656
|
api_map.catalog bench
|
655
657
|
source_map_hash.values.each { |map| find_external_requires(map) }
|
656
658
|
logger.info "Catalog complete (#{api_map.source_maps.length} files, #{api_map.pins.length} pins)"
|
657
|
-
logger.info "#{api_map.
|
659
|
+
logger.info "#{api_map.uncached_yard_gemspecs.length} uncached YARD gemspecs"
|
660
|
+
logger.info "#{api_map.uncached_rbs_collection_gemspecs.length} uncached RBS collection gemspecs"
|
658
661
|
cache_next_gemspec
|
659
662
|
@sync_count = 0
|
660
663
|
end
|
data/lib/solargraph/location.rb
CHANGED
@@ -25,6 +25,19 @@ module Solargraph
|
|
25
25
|
[filename, range]
|
26
26
|
end
|
27
27
|
|
28
|
+
def <=>(other)
|
29
|
+
return nil unless other.is_a?(Location)
|
30
|
+
if filename == other.filename
|
31
|
+
range <=> other.range
|
32
|
+
else
|
33
|
+
filename <=> other.filename
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def rbs?
|
38
|
+
filename.end_with?('.rbs')
|
39
|
+
end
|
40
|
+
|
28
41
|
# @param location [self]
|
29
42
|
def contain? location
|
30
43
|
range.contain?(location.range.start) && range.contain?(location.range.ending) && filename == location.filename
|
data/lib/solargraph/logging.rb
CHANGED
@@ -118,7 +118,8 @@ module Solargraph
|
|
118
118
|
comments: pin.comments,
|
119
119
|
presence: presence,
|
120
120
|
return_type: ComplexType.try_parse(downcast_type_name),
|
121
|
-
presence_certain: true
|
121
|
+
presence_certain: true,
|
122
|
+
source: :flow_sensitive_typing
|
122
123
|
)
|
123
124
|
locals.push(new_pin)
|
124
125
|
end
|
@@ -9,6 +9,7 @@ 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
13
|
@@processors ||= {}
|
13
14
|
|
14
15
|
# Register a processor for a node type.
|
@@ -30,7 +31,8 @@ module Solargraph
|
|
30
31
|
if pins.empty?
|
31
32
|
pins.push Pin::Namespace.new(
|
32
33
|
location: region.source.location,
|
33
|
-
name: ''
|
34
|
+
name: '',
|
35
|
+
source: :parser,
|
34
36
|
)
|
35
37
|
end
|
36
38
|
return [pins, locals] unless Parser.is_ast_node?(node)
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
4
|
-
require 'parser/source/buffer'
|
3
|
+
require 'prism'
|
5
4
|
|
6
5
|
# Awaiting ability to use a version containing https://github.com/whitequark/parser/pull/1076
|
7
6
|
#
|
@@ -39,12 +38,10 @@ module Solargraph
|
|
39
38
|
|
40
39
|
# @return [::Parser::Base]
|
41
40
|
def parser
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
parser.diagnostics.ignore_warnings = true
|
47
|
-
parser
|
41
|
+
@parser ||= Prism::Translation::Parser.new(FlawedBuilder.new).tap do |parser|
|
42
|
+
parser.diagnostics.all_errors_are_fatal = true
|
43
|
+
parser.diagnostics.ignore_warnings = true
|
44
|
+
end
|
48
45
|
end
|
49
46
|
|
50
47
|
# @param source [Source]
|