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
data/lib/solargraph/shell.rb
CHANGED
|
@@ -98,60 +98,37 @@ module Solargraph
|
|
|
98
98
|
# @return [void]
|
|
99
99
|
def clear
|
|
100
100
|
puts 'Deleting all cached documentation (gems, core and stdlib)'
|
|
101
|
-
Solargraph::
|
|
101
|
+
Solargraph::CacheDir.clear
|
|
102
102
|
end
|
|
103
103
|
map 'clear-cache' => :clear
|
|
104
104
|
map 'clear-cores' => :clear
|
|
105
105
|
|
|
106
|
-
desc 'cache', 'Cache a gem', hide: true
|
|
107
|
-
option :rebuild, type: :boolean, desc: 'Rebuild existing documentation', default: false
|
|
108
|
-
# @return [void]
|
|
109
|
-
# @param gem [String]
|
|
110
|
-
# @param version [String, nil]
|
|
111
|
-
def cache gem, version = nil
|
|
112
|
-
gemspec = Gem::Specification.find_by_name(gem, version)
|
|
113
|
-
|
|
114
|
-
if options[:rebuild] || !PinCache.has_yard?(gemspec)
|
|
115
|
-
pins = GemPins.build_yard_pins(['yard-activesupport-concern'], gemspec)
|
|
116
|
-
PinCache.serialize_yard_gem(gemspec, pins)
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
workspace = Solargraph::Workspace.new(Dir.pwd) if File.exist?('rbs_collection.yaml')
|
|
120
|
-
rbs_map = RbsMap.from_gemspec(gemspec, workspace&.rbs_collection_path, workspace&.rbs_collection_config_path)
|
|
121
|
-
if options[:rebuild] || !PinCache.has_rbs_collection?(gemspec, rbs_map.cache_key)
|
|
122
|
-
PinCache.serialize_rbs_collection_gem(gemspec, rbs_map.cache_key, rbs_map.pins)
|
|
123
|
-
end
|
|
124
|
-
rescue Gem::MissingSpecError
|
|
125
|
-
warn "Gem '#{gem}' not found"
|
|
126
|
-
end
|
|
127
|
-
|
|
128
106
|
desc 'uncache GEM [...GEM]', 'Delete specific cached gem documentation'
|
|
129
107
|
long_desc %(
|
|
130
108
|
Specify one or more gem names to clear. 'core' or 'stdlib' may
|
|
131
109
|
also be specified to clear cached system documentation.
|
|
132
110
|
Documentation will be regenerated as needed.
|
|
133
111
|
)
|
|
112
|
+
option :directory, type: :string, desc: 'Workspace directory', default: Dir.pwd
|
|
134
113
|
# @param gems [Array<String>]
|
|
135
114
|
# @return [void]
|
|
136
115
|
def uncache *gems
|
|
137
116
|
raise ArgumentError, 'No gems specified.' if gems.empty?
|
|
117
|
+
repo = Solargraph::Repo.new(options[:directory])
|
|
118
|
+
|
|
138
119
|
gems.each do |gem|
|
|
139
120
|
if gem == 'core'
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
next
|
|
121
|
+
Solargraph::Collection::Core.uncache
|
|
122
|
+
elsif gem == 'stdlib'
|
|
123
|
+
FileUtils.rm_rf CacheDir.stdlib_dir
|
|
124
|
+
else
|
|
125
|
+
metagem = repo.find_by_name(gem)
|
|
126
|
+
Solargraph::Collection::Gem.uncache(metagem) if metagem
|
|
147
127
|
end
|
|
148
|
-
|
|
149
|
-
spec = Gem::Specification.find_by_name(gem)
|
|
150
|
-
PinCache.uncache_gem(spec, out: $stdout)
|
|
151
128
|
end
|
|
152
129
|
end
|
|
153
130
|
|
|
154
|
-
desc '
|
|
131
|
+
desc 'cache GEM_NAME [...GEM_NAME] [core]', 'Cache documentation for
|
|
155
132
|
installed libraries'
|
|
156
133
|
long_desc %( This command will cache the
|
|
157
134
|
generated type documentation for the specified libraries. While
|
|
@@ -172,56 +149,51 @@ module Solargraph
|
|
|
172
149
|
If the library is already cached, it will be rebuilt if the
|
|
173
150
|
--rebuild option is set.
|
|
174
151
|
|
|
175
|
-
Cached documentation is stored in #{
|
|
152
|
+
Cached documentation is stored in #{CacheDir.base_dir}, which
|
|
176
153
|
can be stored between CI runs.
|
|
177
154
|
)
|
|
155
|
+
option :directory, type: :string, desc: 'Workspace directory', default: Dir.pwd
|
|
178
156
|
option :rebuild, type: :boolean, desc: 'Rebuild existing documentation', default: false
|
|
179
157
|
# @param names [Array<String>]
|
|
180
158
|
# @return [void]
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
warn "Gem '#{name}' not found"
|
|
216
|
-
rescue Gem::Requirement::BadRequirementError => e
|
|
217
|
-
warn "Gem '#{name}' failed while loading"
|
|
218
|
-
warn e.message
|
|
219
|
-
# @sg-ignore Need to add nil check here
|
|
220
|
-
warn e.backtrace.join("\n")
|
|
221
|
-
end
|
|
222
|
-
warn "Documentation cached for #{names.count} gems."
|
|
159
|
+
# @param [Array<Object>] gem_names
|
|
160
|
+
def cache *gem_names
|
|
161
|
+
repo = Solargraph::Repo.new(options[:directory])
|
|
162
|
+
metagems = if gem_names.empty?
|
|
163
|
+
if repo.bundled?
|
|
164
|
+
repo.bundled.select(&:cacheable?)
|
|
165
|
+
else
|
|
166
|
+
Gem::Specification.all_names
|
|
167
|
+
.map { |name| Gem::Specification.find_by_full_name(name) }
|
|
168
|
+
.map { |gemspec| Metagem.from_specification(gemspec) }
|
|
169
|
+
end
|
|
170
|
+
else
|
|
171
|
+
gem_names.each_with_object([]) do |name, result|
|
|
172
|
+
if name == 'core'
|
|
173
|
+
Collection::Core.uncache if options[:rebuild]
|
|
174
|
+
puts 'Caching core'
|
|
175
|
+
Collection::Core.load
|
|
176
|
+
else
|
|
177
|
+
# @todo Quick and dirty hack for solargraph-rspec require bug
|
|
178
|
+
# (see https://github.com/lekemula/solargraph-rspec/pull/38)
|
|
179
|
+
# TL;DR: `repo.find_by_path` should not be necessary
|
|
180
|
+
found = repo.find_by_name(name) || repo.find_by_path(name)
|
|
181
|
+
if found
|
|
182
|
+
result.push found
|
|
183
|
+
else
|
|
184
|
+
warn "Gem #{name} not found"
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
metagems.each do |metagem|
|
|
190
|
+
Collection::Gem.uncache(metagem) if options[:rebuild]
|
|
191
|
+
puts "Caching #{metagem.name} #{metagem.version} (#{metagem.cache_name})"
|
|
192
|
+
Collection::Gem.load(metagem)
|
|
223
193
|
end
|
|
194
|
+
puts "Documentation cached for #{metagems.count} gems."
|
|
224
195
|
end
|
|
196
|
+
map 'gems' => :cache
|
|
225
197
|
|
|
226
198
|
desc 'reporters', 'Get a list of diagnostics reporters'
|
|
227
199
|
# @return [void]
|
|
@@ -596,27 +568,5 @@ module Solargraph
|
|
|
596
568
|
puts pin.inspect
|
|
597
569
|
end
|
|
598
570
|
end
|
|
599
|
-
|
|
600
|
-
# @param gemspec [Gem::Specification, nil]
|
|
601
|
-
# @param rebuild [Boolean]
|
|
602
|
-
# @return [void]
|
|
603
|
-
def do_cache gemspec, rebuild: false
|
|
604
|
-
if gemspec.nil?
|
|
605
|
-
warn "Gem '#{gemspec&.name}' not found"
|
|
606
|
-
else
|
|
607
|
-
if rebuild || !PinCache.has_yard?(gemspec)
|
|
608
|
-
pins = GemPins.build_yard_pins(['yard-activesupport-concern'], gemspec)
|
|
609
|
-
PinCache.serialize_yard_gem(gemspec, pins)
|
|
610
|
-
end
|
|
611
|
-
|
|
612
|
-
workspace = Solargraph::Workspace.new(Dir.pwd)
|
|
613
|
-
rbs_map = RbsMap.from_gemspec(gemspec, workspace.rbs_collection_path, workspace.rbs_collection_config_path)
|
|
614
|
-
if rebuild || !PinCache.has_rbs_collection?(gemspec, rbs_map.cache_key)
|
|
615
|
-
# cache pins even if result is zero, so we don't retry building pins
|
|
616
|
-
pins = rbs_map.pins || []
|
|
617
|
-
PinCache.serialize_rbs_collection_gem(gemspec, rbs_map.cache_key, pins)
|
|
618
|
-
end
|
|
619
|
-
end
|
|
620
|
-
end
|
|
621
571
|
end
|
|
622
572
|
end
|
|
@@ -64,7 +64,9 @@ module Solargraph
|
|
|
64
64
|
[stack.first].compact
|
|
65
65
|
end
|
|
66
66
|
pin_groups = [] if !api_map.loose_unions && pin_groups.any?(&:empty?)
|
|
67
|
-
|
|
67
|
+
# Several union members can end up with the same pin and return type.
|
|
68
|
+
# @sg-ignore Array#flatten returns a bare Array
|
|
69
|
+
pins = pin_groups.flatten.uniq { |p| [p.path, p.return_type.rooted_tags] }
|
|
68
70
|
return [] if pins.empty?
|
|
69
71
|
inferred_pins(pins, api_map, name_pin, locals)
|
|
70
72
|
end
|
|
@@ -153,9 +155,11 @@ module Solargraph
|
|
|
153
155
|
# qualify(), however, happens in the namespace where
|
|
154
156
|
# the docs were written - from the method pin.
|
|
155
157
|
# @todo Need to add nil check here
|
|
156
|
-
if new_return_type.defined?
|
|
157
|
-
|
|
158
|
-
|
|
158
|
+
type = if new_return_type.defined?
|
|
159
|
+
with_params(new_return_type.self_to_type(self_type), self_type).qualify(api_map, *pin.gates)
|
|
160
|
+
else
|
|
161
|
+
inferr_from_factory_parameters(api_map, pin)
|
|
162
|
+
end
|
|
159
163
|
type ||= ComplexType::UNDEFINED
|
|
160
164
|
[type, new_signature_pin]
|
|
161
165
|
end
|
|
@@ -219,6 +223,27 @@ module Solargraph
|
|
|
219
223
|
end
|
|
220
224
|
end
|
|
221
225
|
|
|
226
|
+
# @param api_map [ApiMap]
|
|
227
|
+
# @param method_pin [Pin::Method]
|
|
228
|
+
# @return [ComplexType, nil]
|
|
229
|
+
def inferr_from_factory_parameters api_map, method_pin
|
|
230
|
+
factory_parameter = api_map.factory_parameters_for_method(method_pin).find do |factory_param|
|
|
231
|
+
method_pin.parameters.each_with_index.find do |param, index|
|
|
232
|
+
current_argument = arguments[index]
|
|
233
|
+
next unless current_argument&.literal?
|
|
234
|
+
# @type [Solargraph::Source::Chain::Literal]
|
|
235
|
+
last_link = current_argument.links.last
|
|
236
|
+
argument_value = last_link.value
|
|
237
|
+
|
|
238
|
+
param.name == factory_param.param_name && argument_value == factory_param.value
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
return nil if factory_parameter.nil?
|
|
243
|
+
|
|
244
|
+
factory_parameter.return_type.qualify(api_map, method_pin.namespace)
|
|
245
|
+
end
|
|
246
|
+
|
|
222
247
|
# @param pin [Pin::Base]
|
|
223
248
|
# @param api_map [ApiMap]
|
|
224
249
|
# @param context [ComplexType, ComplexType::UniqueType]
|
|
@@ -6,29 +6,29 @@ module Solargraph
|
|
|
6
6
|
class Source
|
|
7
7
|
class Chain
|
|
8
8
|
class Literal < Link
|
|
9
|
-
attr_reader :word
|
|
9
|
+
attr_reader :word
|
|
10
|
+
|
|
11
|
+
# @return [::String, ::Symbol]
|
|
12
|
+
attr_reader :value
|
|
13
|
+
|
|
14
|
+
# @return [Parser::AST::Node]
|
|
15
|
+
attr_reader :node
|
|
10
16
|
|
|
11
17
|
# @param type [String]
|
|
12
18
|
# @param node [Parser::AST::Node, Object]
|
|
13
19
|
def initialize type, node
|
|
14
20
|
super("<#{type}>")
|
|
21
|
+
@node = node
|
|
15
22
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
# @value = false
|
|
26
|
-
# # @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
|
|
27
|
-
# elsif %i[int sym].include?(node.type)
|
|
28
|
-
# # @sg-ignore flow sensitive typing needs to narrow down type with an if is_a? check
|
|
29
|
-
# @value = node.children.first
|
|
30
|
-
# end
|
|
31
|
-
# end
|
|
23
|
+
if node.is_a?(::Parser::AST::Node)
|
|
24
|
+
if node.type == :true
|
|
25
|
+
@value = true
|
|
26
|
+
elsif node.type == :false
|
|
27
|
+
@value = false
|
|
28
|
+
elsif %i[int sym].include?(node.type)
|
|
29
|
+
@value = node.children.first
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
32
|
@type = type
|
|
33
33
|
# @literal_type = ComplexType.try_parse(@value.inspect)
|
|
34
34
|
@literal_type = ComplexType::UNDEFINED
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Solargraph
|
|
4
|
+
class Source
|
|
5
|
+
class Chain
|
|
6
|
+
# A method parameter represented as a link in a method call chain.
|
|
7
|
+
#
|
|
8
|
+
# @example
|
|
9
|
+
# some_method('literal_value')
|
|
10
|
+
# ^^^^^^^^^^^^^
|
|
11
|
+
class Parameter < Link
|
|
12
|
+
# @param literal [Chain::Literal] - literal argument
|
|
13
|
+
# @param method_call_chain [Chain] method call that contains the argument
|
|
14
|
+
def initialize literal, method_call_chain # rubocop:disable Lint/MissingSuper
|
|
15
|
+
@literal = literal
|
|
16
|
+
@method_call_chain = method_call_chain
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def word
|
|
20
|
+
@word ||= "#{method_name}(.., #{@literal.word}, ..)"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# @param api_map [ApiMap]
|
|
24
|
+
# @param name_pin [Pin::Base]
|
|
25
|
+
# @param locals [::Array<Pin::Parameter, Pin::LocalVariable>]
|
|
26
|
+
# @return [::Array<Pin::Base>]
|
|
27
|
+
def resolve api_map, name_pin, locals
|
|
28
|
+
# @type [Pin::Method]
|
|
29
|
+
method_pin = method_call_chain.define(api_map, name_pin, locals)&.first
|
|
30
|
+
return [] unless method_pin
|
|
31
|
+
|
|
32
|
+
# Use indexed lookup for better performance
|
|
33
|
+
api_map.factory_parameters_for_method(method_pin).select do |fp|
|
|
34
|
+
param_index = method_pin.parameters.find_index { |param| param.name == fp.param_name }
|
|
35
|
+
next if param_index.nil?
|
|
36
|
+
next false unless fp.value == literal_value
|
|
37
|
+
|
|
38
|
+
# a splat takes every argument from its position on
|
|
39
|
+
method_pin.parameters[param_index].restarg? ? current_index >= param_index : current_index == param_index
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# @return [Boolean] true if this is a parameter of Kernel#require
|
|
44
|
+
def require_parameter?
|
|
45
|
+
method_call_chain.links.last.word == 'require'
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
# @return [Chain::Literal]
|
|
51
|
+
attr_reader :literal
|
|
52
|
+
# @ return [Chain]
|
|
53
|
+
attr_reader :method_call_chain
|
|
54
|
+
|
|
55
|
+
# @return [String] The name of the method that this parameter belongs to
|
|
56
|
+
def method_name
|
|
57
|
+
@method_name ||= method_call.word
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# @return [Chain::Call]
|
|
61
|
+
def method_call
|
|
62
|
+
@method_call_chain.links.last
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# The index of the literal in the method call chain.
|
|
66
|
+
# @return [Integer]
|
|
67
|
+
def current_index
|
|
68
|
+
@current_index ||= method_call_chain.node.children[2..].index(literal.node)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# @return [::String, ::Symbol] The literal value of the parameter
|
|
72
|
+
# @sg-ignore false "return type could not be inferred"
|
|
73
|
+
def literal_value
|
|
74
|
+
literal.node.children.first
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -34,6 +34,7 @@ module Solargraph
|
|
|
34
34
|
autoload :ZSuper, 'solargraph/source/chain/z_super'
|
|
35
35
|
autoload :Hash, 'solargraph/source/chain/hash'
|
|
36
36
|
autoload :Array, 'solargraph/source/chain/array'
|
|
37
|
+
autoload :Parameter, 'solargraph/source/chain/parameter'
|
|
37
38
|
|
|
38
39
|
@@inference_stack = []
|
|
39
40
|
@@inference_depth = 0
|
|
@@ -182,6 +183,13 @@ module Solargraph
|
|
|
182
183
|
links.last.is_a?(Chain::Literal)
|
|
183
184
|
end
|
|
184
185
|
|
|
186
|
+
# @return [Boolean]
|
|
187
|
+
# @sg-ignore false "return type could not be inferred"
|
|
188
|
+
def require_parameter?
|
|
189
|
+
# @sg-ignore false "Unresolved call to require_parameter? on Solargraph::Source::Chain::Link"
|
|
190
|
+
links.last.is_a?(Chain::Parameter) && links.last.require_parameter?
|
|
191
|
+
end
|
|
192
|
+
|
|
185
193
|
def undefined?
|
|
186
194
|
links.any?(&:undefined?)
|
|
187
195
|
end
|
|
@@ -31,55 +31,18 @@ module Solargraph
|
|
|
31
31
|
|
|
32
32
|
# @return [Source::Chain]
|
|
33
33
|
def chain
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
# return Chain.new([Chain::Literal.new('Integer', Integer(phrase[0..-2])),
|
|
37
|
-
# Chain::UNDEFINED_CALL])
|
|
38
|
-
# end
|
|
39
|
-
if phrase.start_with?(':') && !phrase.start_with?('::')
|
|
40
|
-
return Chain.new([Chain::Literal.new('Symbol',
|
|
41
|
-
# @sg-ignore Need to add nil check here
|
|
42
|
-
phrase[1..].to_sym)])
|
|
43
|
-
end
|
|
44
|
-
if end_of_phrase.strip == '::' && source.code[Position.to_offset(
|
|
45
|
-
source.code, position
|
|
46
|
-
)].to_s.match?(/[a-z]/i)
|
|
47
|
-
return SourceChainer.chain(source,
|
|
48
|
-
Position.new(position.line,
|
|
49
|
-
position.character + 1))
|
|
50
|
-
end
|
|
34
|
+
return SourceChainer.chain(source, Position.new(position.line, position.character + 1)) if end_of_phrase.strip == '::' && source.code[Position.to_offset(source.code, position)].to_s.match?(/[a-z]/i)
|
|
35
|
+
|
|
51
36
|
begin
|
|
52
|
-
|
|
53
|
-
# @type [::Parser::AST::Node, nil]
|
|
54
|
-
node = nil
|
|
55
|
-
# @type [::Parser::AST::Node, nil]
|
|
56
|
-
parent = nil
|
|
57
|
-
if !source.repaired? && source.parsed? && source.synchronized?
|
|
58
|
-
tree = source.tree_at(position.line, position.column)
|
|
59
|
-
node, parent = tree[0..2]
|
|
60
|
-
elsif source.parsed? && source.repaired? && end_of_phrase == '.'
|
|
61
|
-
node, parent = source.tree_at(fixed_position.line, fixed_position.column)[0..2]
|
|
62
|
-
# provide filename and line so that we can look up local variables there later
|
|
63
|
-
node = Parser.parse(fixed_phrase, source.filename, fixed_position.line) if node.nil?
|
|
64
|
-
elsif source.repaired?
|
|
65
|
-
node = Parser.parse(fixed_phrase, source.filename, fixed_position.line)
|
|
66
|
-
else
|
|
67
|
-
unless source.error_ranges.any? do |r|
|
|
68
|
-
r.nil? || r.include?(fixed_position)
|
|
69
|
-
end
|
|
70
|
-
node, parent = source.tree_at(fixed_position.line,
|
|
71
|
-
fixed_position.column)[0..2]
|
|
72
|
-
end
|
|
73
|
-
# Exception for positions that chain literal nodes in unsynchronized sources
|
|
74
|
-
node = nil unless source.synchronized? || !Parser.infer_literal_node_type(node).nil?
|
|
75
|
-
node = Parser.parse(fixed_phrase, source.filename, fixed_position.line) if node.nil?
|
|
76
|
-
end
|
|
37
|
+
node, parent, tree = node_from_position
|
|
77
38
|
rescue Parser::SyntaxError
|
|
78
39
|
return Chain.new([Chain::UNDEFINED_CALL])
|
|
79
40
|
end
|
|
41
|
+
|
|
80
42
|
return Chain.new([Chain::UNDEFINED_CALL]) if node.nil? || (node.type == :sym && !phrase.start_with?(':'))
|
|
81
|
-
|
|
82
|
-
chain = Parser.chain(node, source.filename, parent)
|
|
43
|
+
|
|
44
|
+
chain = Parser.chain(node, source.filename, parent, tree)
|
|
45
|
+
|
|
83
46
|
if source.repaired? || !source.parsed? || !source.synchronized?
|
|
84
47
|
if end_of_phrase.strip == '.'
|
|
85
48
|
chain.links.push Chain::UNDEFINED_CALL
|
|
@@ -94,6 +57,39 @@ module Solargraph
|
|
|
94
57
|
|
|
95
58
|
private
|
|
96
59
|
|
|
60
|
+
# @return [Array(Parser::AST::Node, Parser::AST::Node, Array<Parser::AST::Node>)]
|
|
61
|
+
# parent node, child node, and the tree at the position
|
|
62
|
+
def node_from_position
|
|
63
|
+
node = nil
|
|
64
|
+
parent = nil
|
|
65
|
+
tree = nil
|
|
66
|
+
|
|
67
|
+
if source.parsed? && !source.repaired? && source.synchronized?
|
|
68
|
+
tree = source.tree_at(position.line, position.column)
|
|
69
|
+
node, parent = tree[0..2]
|
|
70
|
+
elsif source.parsed? && source.repaired? && end_of_phrase == '.'
|
|
71
|
+
tree = source.tree_at(fixed_position.line, fixed_position.column)
|
|
72
|
+
node, parent = tree[0..2]
|
|
73
|
+
# provide filename and line so that we can look up local variables there later
|
|
74
|
+
node = Parser.parse(fixed_phrase, source.filename, fixed_position.line) if node.nil?
|
|
75
|
+
tree = source.tree_at(fixed_position.line, fixed_position.column) if node
|
|
76
|
+
elsif source.repaired?
|
|
77
|
+
node = Parser.parse(fixed_phrase, source.filename, fixed_position.line)
|
|
78
|
+
tree = source.tree_at(fixed_position.line, fixed_position.column) if node
|
|
79
|
+
else
|
|
80
|
+
unless source.error_ranges.any? { |r| r.nil? || r.include?(fixed_position) }
|
|
81
|
+
tree = source.tree_at(fixed_position.line, fixed_position.column)
|
|
82
|
+
node, parent = tree[0..2]
|
|
83
|
+
end
|
|
84
|
+
# Exception for positions that chain literal nodes in unsynchronized sources
|
|
85
|
+
node = nil unless source.synchronized? || !Parser.infer_literal_node_type(node).nil?
|
|
86
|
+
node = Parser.parse(fixed_phrase, source.filename, fixed_position.line) if node.nil?
|
|
87
|
+
tree = source.tree_at(fixed_position.line, fixed_position.column) if node
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
[node, parent, tree]
|
|
91
|
+
end
|
|
92
|
+
|
|
97
93
|
# @return [Position]
|
|
98
94
|
attr_reader :position
|
|
99
95
|
|
|
@@ -13,14 +13,14 @@ module Solargraph
|
|
|
13
13
|
@cursor = cursor
|
|
14
14
|
closure_pin = closure
|
|
15
15
|
# @sg-ignore Need to add nil check here
|
|
16
|
-
if closure_pin.is_a?(Pin::Block) && !Solargraph::Range.from_node(closure_pin.receiver)
|
|
16
|
+
if closure_pin.is_a?(Pin::Block) && !Solargraph::Range.from_node(closure_pin.receiver)&.contain?(cursor.range.start)
|
|
17
17
|
closure_pin.rebind(api_map)
|
|
18
18
|
end
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
# @return [Array<Pin::Base>] Relevant pins for infering the type of the Cursor's position
|
|
22
22
|
def define
|
|
23
|
-
return [] if cursor.comment? || cursor.chain.literal?
|
|
23
|
+
return [] if cursor.comment? || cursor.chain.literal? || cursor.chain.require_parameter?
|
|
24
24
|
result = cursor.chain.define(api_map, closure, locals)
|
|
25
25
|
result.concat file_global_methods
|
|
26
26
|
if result.empty?
|
|
@@ -40,7 +40,8 @@ module Solargraph
|
|
|
40
40
|
# @return [Completion]
|
|
41
41
|
def complete
|
|
42
42
|
return package_completions([]) if !source_map.source.parsed? || cursor.string?
|
|
43
|
-
|
|
43
|
+
# TODO: Improve magic word comparsion == '<::Symbol>', too fragile
|
|
44
|
+
if cursor.chain.literal? && cursor.chain.links.last.word == '<::Symbol>'
|
|
44
45
|
return package_completions(api_map.get_symbols)
|
|
45
46
|
end
|
|
46
47
|
return Completion.new([], cursor.range) if cursor.chain.literal?
|
|
@@ -211,6 +212,7 @@ module Solargraph
|
|
|
211
212
|
result.concat api_map.get_constants('', cursor.start_of_constant? ? '' : context_pin.full_context.namespace, *gates) # .select { |pin| pin.name.start_with?(full) }
|
|
212
213
|
end
|
|
213
214
|
else
|
|
215
|
+
type = type.qualify(api_map, *gates)
|
|
214
216
|
result.concat api_map.get_constants(type.namespace,
|
|
215
217
|
cursor.start_of_constant? ? '' : context_pin.full_context.namespace, *gates)
|
|
216
218
|
end
|
|
@@ -12,7 +12,7 @@ module Solargraph
|
|
|
12
12
|
|
|
13
13
|
private_class_method :new
|
|
14
14
|
|
|
15
|
-
DIRECTIVE_REGEXP = /(@!method|@!attribute|@!visibility|@!domain|@!macro|@!parse|@!override)/
|
|
15
|
+
DIRECTIVE_REGEXP = /(@!method|@!attribute|@!visibility|@!scope|@!domain|@!macro|@!parse|@!override)/
|
|
16
16
|
|
|
17
17
|
# Generate the data.
|
|
18
18
|
#
|
|
@@ -104,9 +104,13 @@ module Solargraph
|
|
|
104
104
|
directive_processor = YardMap::Directives.for(directive)
|
|
105
105
|
return unless directive_processor
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
new_pins = directive_processor.process_directive(
|
|
108
108
|
@source, @pins, source_position, comment_position, directive
|
|
109
109
|
)
|
|
110
|
+
# A @!scope directive in the indented text of another directive applies
|
|
111
|
+
# only to the object that directive defines.
|
|
112
|
+
YardMap::Directives::ScopeDirective.apply_nested directive, new_pins
|
|
113
|
+
@pins += new_pins
|
|
110
114
|
end
|
|
111
115
|
|
|
112
116
|
# @param comment [String]
|
|
@@ -190,10 +190,12 @@ module Solargraph
|
|
|
190
190
|
end
|
|
191
191
|
end
|
|
192
192
|
|
|
193
|
-
private
|
|
194
|
-
|
|
195
193
|
# @return [Array<Pin::Base>]
|
|
196
|
-
|
|
194
|
+
def convention_pins
|
|
195
|
+
@convention_pins || []
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
private
|
|
197
199
|
|
|
198
200
|
# @return [Hash{Class<Pin::Base> => Array<Pin::Base>}]
|
|
199
201
|
def pin_class_hash
|
|
@@ -206,9 +208,12 @@ module Solargraph
|
|
|
206
208
|
@data ||= Data.new(source)
|
|
207
209
|
end
|
|
208
210
|
|
|
211
|
+
# @param pins [Array<Pin::Base>]
|
|
209
212
|
# @return [Array<Pin::Base>]
|
|
210
|
-
def convention_pins
|
|
211
|
-
|
|
213
|
+
def convention_pins= pins
|
|
214
|
+
# unmemoizing the document_symbols in case it was called from any of conventions
|
|
215
|
+
@document_symbols = nil
|
|
216
|
+
@convention_pins = pins
|
|
212
217
|
end
|
|
213
218
|
|
|
214
219
|
# @generic T
|
|
@@ -75,7 +75,7 @@ module Solargraph
|
|
|
75
75
|
# @todo 22: Translate to something flow sensitive typing understands
|
|
76
76
|
# @todo 3: Need a downcast here
|
|
77
77
|
#
|
|
78
|
-
# flow sensitive typing could handle (
|
|
78
|
+
# flow sensitive typing could handle (97):
|
|
79
79
|
#
|
|
80
80
|
# @todo 36: flow sensitive typing needs to handle attrs
|
|
81
81
|
# @todo 29: flow sensitive typing should be able to handle redefinition
|
|
@@ -113,6 +113,7 @@ module Solargraph
|
|
|
113
113
|
# @todo 1: flow sensitive typing needs to create separate ranges for postfix if
|
|
114
114
|
# @todo 1: flow sensitive typing needs to handle constants
|
|
115
115
|
# @todo 1: flow sensitive typing needs to eliminate literal from union with return if foo == :bar
|
|
116
|
+
# @todo 1: Array#flatten returns a bare Array
|
|
116
117
|
def require_all_unique_types_match_expected?
|
|
117
118
|
report?(:require_all_unique_types_match_expected, :strong)
|
|
118
119
|
end
|
data/lib/solargraph/version.rb
CHANGED
data/lib/solargraph/workspace.rb
CHANGED