solargraph 0.48.0 → 0.50.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/FUNDING.yml +1 -0
- data/.github/workflows/rspec.yml +1 -1
- data/CHANGELOG.md +29 -0
- data/LICENSE +1 -1
- data/README.md +2 -4
- data/SPONSORS.md +4 -4
- data/lib/solargraph/api_map/store.rb +13 -1
- data/lib/solargraph/api_map.rb +30 -12
- data/lib/solargraph/cache.rb +53 -0
- data/lib/solargraph/complex_type/type_methods.rb +3 -6
- data/lib/solargraph/complex_type/unique_type.rb +57 -0
- data/lib/solargraph/complex_type.rb +22 -3
- data/lib/solargraph/convention/rakefile.rb +17 -0
- data/lib/solargraph/convention.rb +2 -0
- data/lib/solargraph/diagnostics/rubocop.rb +15 -2
- data/lib/solargraph/diagnostics/rubocop_helpers.rb +3 -1
- data/lib/solargraph/language_server/host/cataloger.rb +1 -1
- data/lib/solargraph/language_server/host.rb +22 -18
- data/lib/solargraph/language_server/message/extended/download_core.rb +1 -5
- data/lib/solargraph/language_server/message/initialize.rb +2 -0
- data/lib/solargraph/language_server/message/text_document/formatting.rb +1 -1
- data/lib/solargraph/language_server/message/text_document/signature_help.rb +1 -6
- data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +10 -3
- data/lib/solargraph/library.rb +25 -20
- data/lib/solargraph/parser/rubyvm/class_methods.rb +6 -1
- data/lib/solargraph/parser/rubyvm/node_processors/def_node.rb +20 -8
- data/lib/solargraph/parser/rubyvm/node_processors/defs_node.rb +14 -3
- data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +4 -2
- data/lib/solargraph/parser/rubyvm/node_wrapper.rb +47 -0
- data/lib/solargraph/pin/base.rb +5 -2
- data/lib/solargraph/pin/base_variable.rb +1 -1
- data/lib/solargraph/pin/conversions.rb +2 -6
- data/lib/solargraph/pin/method.rb +84 -10
- data/lib/solargraph/pin/namespace.rb +4 -1
- data/lib/solargraph/pin/parameter.rb +8 -3
- data/lib/solargraph/pin/signature.rb +23 -0
- data/lib/solargraph/pin.rb +1 -0
- data/lib/solargraph/rbs_map/conversions.rb +394 -0
- data/lib/solargraph/rbs_map/core_fills.rb +61 -0
- data/lib/solargraph/rbs_map/core_map.rb +38 -0
- data/lib/solargraph/rbs_map/core_signs.rb +33 -0
- data/lib/solargraph/rbs_map/stdlib_map.rb +36 -0
- data/lib/solargraph/rbs_map.rb +73 -0
- data/lib/solargraph/shell.rb +50 -32
- data/lib/solargraph/source/chain/call.rb +31 -23
- data/lib/solargraph/source/chain.rb +22 -7
- data/lib/solargraph/source_map/clip.rb +5 -0
- data/lib/solargraph/source_map/mapper.rb +8 -4
- data/lib/solargraph/type_checker.rb +71 -65
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/views/environment.erb +2 -2
- data/lib/solargraph/workspace.rb +11 -14
- data/lib/solargraph/yard_map/mapper/to_method.rb +7 -4
- data/lib/solargraph/yard_map.rb +10 -151
- data/lib/solargraph.rb +2 -2
- data/solargraph.gemspec +11 -6
- metadata +46 -37
- data/.travis.yml +0 -19
- data/lib/solargraph/compat.rb +0 -37
- data/lib/solargraph/yard_map/core_docs.rb +0 -170
- data/lib/solargraph/yard_map/core_fills.rb +0 -208
- data/lib/solargraph/yard_map/core_gen.rb +0 -76
- data/lib/solargraph/yard_map/rdoc_to_yard.rb +0 -143
- data/lib/solargraph/yard_map/stdlib_fills.rb +0 -43
- data/yardoc/2.2.2.tar.gz +0 -0
data/lib/solargraph/shell.rb
CHANGED
@@ -71,43 +71,46 @@ module Solargraph
|
|
71
71
|
STDOUT.puts "Configuration file initialized."
|
72
72
|
end
|
73
73
|
|
74
|
-
desc 'download-core [VERSION]', 'Download core documentation'
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
desc 'list-cores', 'List the local documentation versions'
|
74
|
+
desc 'download-core [VERSION]', 'Download core documentation [deprecated]', hide: true
|
75
|
+
long_desc %(
|
76
|
+
The `download-core` command is deprecated. Current versions of Solargraph
|
77
|
+
use RBS for core and stdlib documentation.
|
78
|
+
)
|
79
|
+
# @deprecated
|
80
|
+
def download_core _version = nil
|
81
|
+
puts 'The `download-core` command is deprecated.'
|
82
|
+
puts 'Current versions of Solargraph use RBS for core and stdlib documentation.'
|
83
|
+
end
|
84
|
+
|
85
|
+
desc 'list-cores', 'List the local documentation versions [deprecated]', hide: true
|
86
|
+
long_desc %(
|
87
|
+
The `list-cores` command is deprecated. Current versions of Solargraph use
|
88
|
+
RBS for core and stdlib documentation.
|
89
|
+
)
|
90
|
+
# @deprecated
|
92
91
|
def list_cores
|
93
|
-
puts
|
92
|
+
puts 'The `list-cores` command is deprecated.'
|
93
|
+
puts 'Current versions of Solargraph use RBS for core and stdlib documentation.'
|
94
94
|
end
|
95
95
|
|
96
|
-
desc 'available-cores', 'List available documentation versions'
|
96
|
+
desc 'available-cores', 'List available documentation versions [deprecated]', hide: true
|
97
|
+
long_desc %(
|
98
|
+
The `available-cores` command is deprecated. Current versions of Solargraph
|
99
|
+
use RBS for core and stdlib documentation.
|
100
|
+
)
|
101
|
+
# @deprecated
|
97
102
|
def available_cores
|
98
|
-
puts
|
103
|
+
puts 'The `available-cores` command is deprecated.'
|
104
|
+
puts 'Current versions of Solargraph use RBS for core and stdlib documentation.'
|
99
105
|
end
|
100
106
|
|
101
107
|
desc 'clear', 'Delete all cached documentation'
|
102
108
|
long_desc %(
|
103
109
|
This command will delete all core and gem documentation from the cache.
|
104
|
-
You can also delete specific gem caches with the `uncache` command or
|
105
|
-
update documentation for specific Ruby versions with the `download-core`
|
106
|
-
command.
|
107
110
|
)
|
108
111
|
def clear
|
109
112
|
puts "Deleting the cached documentation"
|
110
|
-
Solargraph::
|
113
|
+
Solargraph::Cache.clear
|
111
114
|
end
|
112
115
|
map 'clear-cache' => :clear
|
113
116
|
map 'clear-cores' => :clear
|
@@ -191,18 +194,33 @@ module Solargraph
|
|
191
194
|
puts "Scanned #{directory} (#{api_map.pins.length} pins) in #{time.real} seconds."
|
192
195
|
end
|
193
196
|
|
194
|
-
desc '
|
197
|
+
desc 'list', 'List the files in the workspace and the total count'
|
198
|
+
option :count, type: :boolean, aliases: :c, desc: 'Display the file count only', default: false
|
199
|
+
option :directory, type: :string, aliases: :d, desc: 'The directory to read', default: '.'
|
200
|
+
def list
|
201
|
+
workspace = Solargraph::Workspace.new(options[:directory])
|
202
|
+
unless options[:count]
|
203
|
+
workspace.filenames.each { |f| puts f }
|
204
|
+
end
|
205
|
+
puts "#{workspace.filenames.length} files total."
|
206
|
+
end
|
207
|
+
|
208
|
+
desc 'bundle', 'Generate documentation for bundled gems [deprecated]', hide: true
|
209
|
+
long_desc %(
|
210
|
+
The `bundle` command is deprecated. Solargraph currently uses RBS instead.
|
211
|
+
)
|
195
212
|
option :directory, type: :string, aliases: :d, desc: 'The workspace directory', default: '.'
|
196
213
|
option :rebuild, type: :boolean, aliases: :r, desc: 'Rebuild existing documentation', default: false
|
197
214
|
def bundle
|
198
|
-
|
215
|
+
puts 'The `bundle` command is deprecated. Solargraph currently uses RBS instead.'
|
199
216
|
end
|
200
217
|
|
201
|
-
desc 'rdoc GEM [VERSION]', 'Use RDoc to cache documentation'
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
218
|
+
desc 'rdoc GEM [VERSION]', 'Use RDoc to cache documentation [deprecated]', hide: true
|
219
|
+
long_desc %(
|
220
|
+
The `rdoc` command is deprecated. Solargraph currently uses RBS instead.
|
221
|
+
)
|
222
|
+
def rdoc _gem, _version = '>= 0'
|
223
|
+
puts 'The `rdoc` command is deprecated. Solargraph currently uses RBS instead.'
|
206
224
|
end
|
207
225
|
|
208
226
|
private
|
@@ -52,36 +52,32 @@ module Solargraph
|
|
52
52
|
# @return [Array<Pin::Base>]
|
53
53
|
def inferred_pins pins, api_map, context, locals
|
54
54
|
result = pins.map do |p|
|
55
|
-
|
55
|
+
next p unless p.is_a?(Pin::Method)
|
56
|
+
overloads = p.signatures
|
56
57
|
# next p if overloads.empty?
|
57
58
|
type = ComplexType::UNDEFINED
|
58
|
-
# @param [YARD::Tags::OverloadTag]
|
59
59
|
overloads.each do |ol|
|
60
|
-
next unless arguments_match(arguments, ol
|
61
|
-
next if ol.parameters.last && ol.parameters.last.first.start_with?('&') && ol.parameters.last.last.nil? && !with_block?
|
60
|
+
next unless arguments_match(arguments, ol)
|
61
|
+
# next if ol.parameters.last && ol.parameters.last.first.start_with?('&') && ol.parameters.last.last.nil? && !with_block?
|
62
62
|
match = true
|
63
63
|
arguments.each_with_index do |arg, idx|
|
64
|
-
achain = arguments[idx]
|
65
|
-
next if achain.nil?
|
66
64
|
param = ol.parameters[idx]
|
67
65
|
if param.nil?
|
68
|
-
match = false unless ol.parameters.
|
66
|
+
match = false unless ol.parameters.any?(&:restarg?)
|
69
67
|
break
|
70
68
|
end
|
71
|
-
|
72
|
-
next if par.nil? || par.types.nil? || par.types.empty?
|
73
|
-
atype = achain.infer(api_map, Pin::ProxyType.anonymous(context), locals)
|
74
|
-
other = ComplexType.try_parse(*par.types)
|
69
|
+
atype = arg.infer(api_map, Pin::ProxyType.anonymous(context), locals)
|
75
70
|
# @todo Weak type comparison
|
76
|
-
unless atype.tag ==
|
71
|
+
# unless atype.tag == param.return_type.tag || api_map.super_and_sub?(param.return_type.tag, atype.tag)
|
72
|
+
unless param.return_type.undefined? || atype.name == param.return_type.name || api_map.super_and_sub?(param.return_type.name, atype.name)
|
77
73
|
match = false
|
78
74
|
break
|
79
75
|
end
|
80
76
|
end
|
81
77
|
if match
|
82
|
-
type = extra_return_type(
|
78
|
+
type = extra_return_type(p.docstring, context)
|
83
79
|
break if type
|
84
|
-
type =
|
80
|
+
type = with_params(ol.return_type.self_to(context.to_s), context).qualify(api_map, context.namespace) if ol.return_type.defined?
|
85
81
|
type ||= ComplexType::UNDEFINED
|
86
82
|
end
|
87
83
|
break if type.defined?
|
@@ -110,9 +106,13 @@ module Solargraph
|
|
110
106
|
p
|
111
107
|
end
|
112
108
|
result.map do |pin|
|
113
|
-
|
114
|
-
|
115
|
-
|
109
|
+
if pin.path == 'Class#new' && context.tag != 'Class'
|
110
|
+
pin.proxy(ComplexType.try_parse(context.namespace))
|
111
|
+
else
|
112
|
+
next pin if pin.return_type.undefined?
|
113
|
+
selfy = pin.return_type.self_to(context.tag)
|
114
|
+
selfy == pin.return_type ? pin : pin.proxy(selfy)
|
115
|
+
end
|
116
116
|
end
|
117
117
|
end
|
118
118
|
|
@@ -183,14 +183,15 @@ module Solargraph
|
|
183
183
|
end
|
184
184
|
|
185
185
|
# @param arguments [Array<Chain>]
|
186
|
-
# @param
|
186
|
+
# @param signature [Pin::Signature]
|
187
187
|
# @return [Boolean]
|
188
|
-
def arguments_match arguments,
|
188
|
+
def arguments_match arguments, signature
|
189
|
+
parameters = signature.parameters
|
189
190
|
argcount = arguments.length
|
190
|
-
# argcount -= 1 if !arguments.empty? && arguments.last.links.first.word.start_with?('&')
|
191
191
|
parcount = parameters.length
|
192
|
-
parcount -= 1 if !parameters.empty? && parameters.last.
|
193
|
-
return false if
|
192
|
+
parcount -= 1 if !parameters.empty? && parameters.last.block?
|
193
|
+
return false if signature.block? && !with_block?
|
194
|
+
return false if argcount < parcount && !(argcount == parcount - 1 && parameters.last.restarg?)
|
194
195
|
true
|
195
196
|
end
|
196
197
|
|
@@ -198,9 +199,16 @@ module Solargraph
|
|
198
199
|
# @param name_pin [Pin::Base]
|
199
200
|
# @return [Array<Pin::Base>]
|
200
201
|
def super_pins api_map, name_pin
|
201
|
-
pins = api_map.get_method_stack(name_pin.namespace, name_pin.name, scope: name_pin.scope)
|
202
|
+
pins = api_map.get_method_stack(name_pin.namespace, name_pin.name, scope: name_pin.context.scope)
|
202
203
|
pins.reject{|p| p.path == name_pin.path}
|
203
204
|
end
|
205
|
+
|
206
|
+
# @param type [ComplexType]
|
207
|
+
# @param context [ComplexType]
|
208
|
+
def with_params type, context
|
209
|
+
return type unless type.to_s.include?('$')
|
210
|
+
ComplexType.try_parse(type.to_s.gsub('$', context.value_types.map(&:tag).join(', ')).gsub('<>', ''))
|
211
|
+
end
|
204
212
|
end
|
205
213
|
end
|
206
214
|
end
|
@@ -63,11 +63,11 @@ module Solargraph
|
|
63
63
|
working_pin = name_pin
|
64
64
|
links[0..-2].each do |link|
|
65
65
|
pins = link.resolve(api_map, working_pin, locals)
|
66
|
-
type = infer_first_defined(pins, working_pin, api_map)
|
66
|
+
type = infer_first_defined(pins, working_pin, api_map, locals)
|
67
67
|
return [] if type.undefined?
|
68
68
|
working_pin = Pin::ProxyType.anonymous(type)
|
69
69
|
end
|
70
|
-
links.last.last_context =
|
70
|
+
links.last.last_context = name_pin
|
71
71
|
links.last.resolve(api_map, working_pin, locals)
|
72
72
|
end
|
73
73
|
|
@@ -76,8 +76,12 @@ module Solargraph
|
|
76
76
|
# @param locals [Array<Pin::Base>]
|
77
77
|
# @return [ComplexType]
|
78
78
|
def infer api_map, name_pin, locals
|
79
|
+
from_here = base.infer(api_map, name_pin, locals) unless links.length == 1
|
80
|
+
if from_here
|
81
|
+
name_pin = name_pin.proxy(from_here)
|
82
|
+
end
|
79
83
|
pins = define(api_map, name_pin, locals)
|
80
|
-
type = infer_first_defined(pins, links.last.last_context, api_map)
|
84
|
+
type = infer_first_defined(pins, links.last.last_context, api_map, locals)
|
81
85
|
maybe_nil(type)
|
82
86
|
end
|
83
87
|
|
@@ -110,9 +114,10 @@ module Solargraph
|
|
110
114
|
private
|
111
115
|
|
112
116
|
# @param pins [Array<Pin::Base>]
|
117
|
+
# @param context [Pin::Base]
|
113
118
|
# @param api_map [ApiMap]
|
114
119
|
# @return [ComplexType]
|
115
|
-
def infer_first_defined pins, context, api_map
|
120
|
+
def infer_first_defined pins, context, api_map, locals
|
116
121
|
possibles = []
|
117
122
|
pins.each do |pin|
|
118
123
|
# Avoid infinite recursion
|
@@ -121,8 +126,18 @@ module Solargraph
|
|
121
126
|
type = pin.typify(api_map)
|
122
127
|
@@inference_stack.pop
|
123
128
|
if type.defined?
|
124
|
-
|
125
|
-
|
129
|
+
if type.parameterized?
|
130
|
+
type = type.resolve_parameters(pin.closure, context)
|
131
|
+
# idx = pin.closure.parameters.index(type.subtypes.first.name)
|
132
|
+
# next if idx.nil?
|
133
|
+
# param_type = context.return_type.all_params[idx]
|
134
|
+
# next unless param_type
|
135
|
+
# type = ComplexType.try_parse(param_type.to_s)
|
136
|
+
end
|
137
|
+
if type.defined?
|
138
|
+
possibles.push type
|
139
|
+
break if pin.is_a?(Pin::Method)
|
140
|
+
end
|
126
141
|
end
|
127
142
|
end
|
128
143
|
if possibles.empty?
|
@@ -147,7 +162,7 @@ module Solargraph
|
|
147
162
|
sorted = possibles.map { |t| t.rooted? ? "::#{t}" : t.to_s }.sort { |a, _| a == 'nil' ? 1 : 0 }
|
148
163
|
ComplexType.parse(*sorted)
|
149
164
|
else
|
150
|
-
possibles.
|
165
|
+
ComplexType.parse(possibles.map(&:to_s).join(', '))
|
151
166
|
end
|
152
167
|
return type if context.nil? || context.return_type.undefined?
|
153
168
|
type.self_to(context.return_type.namespace)
|
@@ -43,6 +43,11 @@ module Solargraph
|
|
43
43
|
# @return [ComplexType]
|
44
44
|
def infer
|
45
45
|
result = cursor.chain.infer(api_map, block, locals)
|
46
|
+
if result.tag == 'Class'
|
47
|
+
# HACK: Exception to return Object from Class#new
|
48
|
+
dfn = cursor.chain.define(api_map, block, locals).first
|
49
|
+
return ComplexType.try_parse('Object') if dfn && dfn.path == 'Class#new'
|
50
|
+
end
|
46
51
|
return result unless result.tag == 'self'
|
47
52
|
ComplexType.try_parse(cursor.chain.base.infer(api_map, block, locals).namespace)
|
48
53
|
end
|
@@ -12,7 +12,7 @@ module Solargraph
|
|
12
12
|
|
13
13
|
private_class_method :new
|
14
14
|
|
15
|
-
|
15
|
+
DIRECTIVE_REGEXP = /(@\!method|@\!attribute|@\!visibility|@\!domain|@\!macro|@\!parse|@\!override)/.freeze
|
16
16
|
|
17
17
|
# Generate the data.
|
18
18
|
#
|
@@ -24,6 +24,8 @@ module Solargraph
|
|
24
24
|
@code = source.code
|
25
25
|
@comments = source.comments
|
26
26
|
@pins, @locals = Parser.map(source)
|
27
|
+
@pins.each { |p| p.source = :code }
|
28
|
+
@locals.each { |l| l.source = :code }
|
27
29
|
process_comment_directives
|
28
30
|
[@pins, @locals]
|
29
31
|
# rescue Exception => e
|
@@ -63,7 +65,7 @@ module Solargraph
|
|
63
65
|
end
|
64
66
|
|
65
67
|
def process_comment source_position, comment_position, comment
|
66
|
-
return unless comment.encode('UTF-8', invalid: :replace, replace: '?') =~
|
68
|
+
return unless comment.encode('UTF-8', invalid: :replace, replace: '?') =~ DIRECTIVE_REGEXP
|
67
69
|
cmnt = remove_inline_comment_hashes(comment)
|
68
70
|
parse = Solargraph::Source.parse_docstring(cmnt)
|
69
71
|
last_line = 0
|
@@ -196,6 +198,8 @@ module Solargraph
|
|
196
198
|
namespace.domains.concat directive.tag.types unless directive.tag.types.nil?
|
197
199
|
when 'override'
|
198
200
|
pins.push Pin::Reference::Override.new(location, directive.tag.name, docstring.tags)
|
201
|
+
when 'macro'
|
202
|
+
# @todo Handle macros
|
199
203
|
end
|
200
204
|
end
|
201
205
|
|
@@ -209,7 +213,7 @@ module Solargraph
|
|
209
213
|
started = false
|
210
214
|
comment.lines.each { |l|
|
211
215
|
# Trim the comment and minimum leading whitespace
|
212
|
-
p = l.encode('UTF-8', invalid: :replace, replace: '?').gsub(
|
216
|
+
p = l.encode('UTF-8', invalid: :replace, replace: '?').gsub(/^#+/, '')
|
213
217
|
if num.nil? && !p.strip.empty?
|
214
218
|
num = p.index(/[^ ]/)
|
215
219
|
started = true
|
@@ -224,7 +228,7 @@ module Solargraph
|
|
224
228
|
|
225
229
|
# @return [void]
|
226
230
|
def process_comment_directives
|
227
|
-
return unless @code.encode('UTF-8', invalid: :replace, replace: '?') =~
|
231
|
+
return unless @code.encode('UTF-8', invalid: :replace, replace: '?') =~ DIRECTIVE_REGEXP
|
228
232
|
code_lines = @code.lines
|
229
233
|
@source.associated_comments.each do |line, comments|
|
230
234
|
src_pos = line ? Position.new(line, code_lines[line].to_s.chomp.index(/[^\s]/) || 0) : Position.new(code_lines.length, 0)
|
@@ -120,12 +120,10 @@ module Solargraph
|
|
120
120
|
# @param pin [Pin::Base]
|
121
121
|
# @return [Boolean]
|
122
122
|
def resolved_constant? pin
|
123
|
-
|
123
|
+
return true if pin.typify(api_map).defined?
|
124
|
+
api_map.get_constants('', *pin.closure.gates)
|
124
125
|
.select { |p| p.name == pin.return_type.namespace }
|
125
|
-
.any?
|
126
|
-
inferred = p.infer(api_map)
|
127
|
-
['Class', 'Module'].include?(inferred.name)
|
128
|
-
end
|
126
|
+
.any? { |p| p.infer(api_map).defined? }
|
129
127
|
end
|
130
128
|
|
131
129
|
def virtual_pin? pin
|
@@ -139,10 +137,12 @@ module Solargraph
|
|
139
137
|
params = first_param_hash(stack)
|
140
138
|
result = []
|
141
139
|
if rules.require_type_tags?
|
142
|
-
pin.
|
143
|
-
|
144
|
-
|
145
|
-
|
140
|
+
pin.signatures.each do |sig|
|
141
|
+
sig.parameters.each do |par|
|
142
|
+
break if par.decl == :restarg || par.decl == :kwrestarg || par.decl == :blockarg
|
143
|
+
unless params[par.name]
|
144
|
+
result.push Problem.new(pin.location, "Missing @param tag for #{par.name} on #{pin.path}", pin: pin)
|
145
|
+
end
|
146
146
|
end
|
147
147
|
end
|
148
148
|
end
|
@@ -184,7 +184,7 @@ module Solargraph
|
|
184
184
|
elsif declared_externally?(pin)
|
185
185
|
ignored_pins.push pin
|
186
186
|
end
|
187
|
-
elsif !pin.is_a?(Pin::Parameter)
|
187
|
+
elsif !pin.is_a?(Pin::Parameter) && !resolved_constant?(pin)
|
188
188
|
result.push Problem.new(pin.location, "Unresolved type #{pin.return_type} for variable #{pin.name}", pin: pin)
|
189
189
|
end
|
190
190
|
else
|
@@ -243,7 +243,7 @@ module Solargraph
|
|
243
243
|
end
|
244
244
|
closest = found.typify(api_map) if found
|
245
245
|
if !found || found.is_a?(Pin::BaseVariable) || (closest.defined? && internal_or_core?(found))
|
246
|
-
unless ignored_pins.include?(found)
|
246
|
+
unless closest.parameterized? || ignored_pins.include?(found)
|
247
247
|
result.push Problem.new(location, "Unresolved call to #{missing.links.last.word}")
|
248
248
|
@marked_ranges.push rng
|
249
249
|
end
|
@@ -273,34 +273,44 @@ module Solargraph
|
|
273
273
|
end
|
274
274
|
break unless rules.validate_calls?
|
275
275
|
params = first_param_hash(pins)
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
276
|
+
|
277
|
+
all_errors = []
|
278
|
+
pin.signatures.sort { |sig| sig.parameters.length }.each do |sig|
|
279
|
+
errors = []
|
280
|
+
sig.parameters.each_with_index do |par, idx|
|
281
|
+
argchain = base.links.last.arguments[idx]
|
282
|
+
if argchain.nil? && par.decl == :arg
|
283
|
+
errors.push Problem.new(location, "Not enough arguments to #{pin.path}")
|
284
|
+
next
|
285
|
+
end
|
286
|
+
if argchain
|
287
|
+
if par.decl != :arg
|
288
|
+
errors.concat kwarg_problems_for argchain, api_map, block_pin, locals, location, pin, params, idx
|
289
|
+
next
|
290
290
|
else
|
291
|
-
|
292
|
-
if
|
293
|
-
|
291
|
+
ptype = params.key?(par.name) ? params[par.name][:qualified] : ComplexType::UNDEFINED
|
292
|
+
if ptype.nil?
|
293
|
+
# @todo Some level (strong, I guess) should require the param here
|
294
|
+
else
|
295
|
+
argtype = argchain.infer(api_map, block_pin, locals)
|
296
|
+
if argtype.defined? && ptype.defined? && !any_types_match?(api_map, ptype, argtype)
|
297
|
+
errors.push Problem.new(location, "Wrong argument type for #{pin.path}: #{par.name} expected #{ptype}, received #{argtype}")
|
298
|
+
next
|
299
|
+
end
|
294
300
|
end
|
295
301
|
end
|
302
|
+
elsif par.decl == :kwarg
|
303
|
+
errors.push Problem.new(location, "Call to #{pin.path} is missing keyword argument #{par.name}")
|
304
|
+
next
|
296
305
|
end
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
result.push Problem.new(location, "Call to #{pin.path} is missing keyword argument #{par.name}")
|
306
|
+
end
|
307
|
+
if errors.empty?
|
308
|
+
all_errors.clear
|
301
309
|
break
|
302
310
|
end
|
311
|
+
all_errors.concat errors
|
303
312
|
end
|
313
|
+
result.concat all_errors
|
304
314
|
end
|
305
315
|
base = base.base
|
306
316
|
end
|
@@ -310,7 +320,7 @@ module Solargraph
|
|
310
320
|
def kwarg_problems_for argchain, api_map, block_pin, locals, location, pin, params, first
|
311
321
|
result = []
|
312
322
|
kwargs = convert_hash(argchain.node)
|
313
|
-
pin.parameters[first..-1].each_with_index do |par, cur|
|
323
|
+
pin.signatures.first.parameters[first..-1].each_with_index do |par, cur|
|
314
324
|
idx = first + cur
|
315
325
|
argchain = kwargs[par.name.to_sym]
|
316
326
|
if par.decl == :kwrestarg || (par.decl == :optarg && idx == pin.parameters.length - 1 && par.asgn_code == '{}')
|
@@ -381,8 +391,10 @@ module Solargraph
|
|
381
391
|
pin.location && api_map.bundled?(pin.location.filename)
|
382
392
|
end
|
383
393
|
|
394
|
+
# True if the pin is either internal (part of the workspace) or from the core/stdlib
|
384
395
|
def internal_or_core? pin
|
385
|
-
|
396
|
+
# @todo RBS pins are not necessarily core/stdlib pins
|
397
|
+
internal?(pin) || pin.source == :rbs
|
386
398
|
end
|
387
399
|
|
388
400
|
# @param pin [Pin::Base]
|
@@ -417,20 +429,20 @@ module Solargraph
|
|
417
429
|
true
|
418
430
|
end
|
419
431
|
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
432
|
+
def arity_problems_for pin, arguments, location
|
433
|
+
results = pin.signatures.map do |sig|
|
434
|
+
r = parameterized_arity_problems_for(pin, sig.parameters, arguments, location)
|
435
|
+
return [] if r.empty?
|
436
|
+
r
|
437
|
+
end
|
438
|
+
results.first
|
427
439
|
end
|
428
440
|
|
429
|
-
|
430
|
-
def pin_arity_problems_for(pin, arguments, location)
|
441
|
+
def parameterized_arity_problems_for(pin, parameters, arguments, location)
|
431
442
|
return [] unless pin.explicit?
|
432
|
-
return [] if
|
433
|
-
if pin.
|
443
|
+
return [] if parameters.empty? && arguments.empty?
|
444
|
+
return [] if pin.anon_splat?
|
445
|
+
if parameters.empty?
|
434
446
|
# Functions tagged param_tuple accepts two arguments (e.g., Hash#[]=)
|
435
447
|
return [] if pin.docstring.tag(:param_tuple) && arguments.length == 2
|
436
448
|
return [] if arguments.length == 1 && arguments.last.links.last.is_a?(Source::Chain::BlockVariable)
|
@@ -438,21 +450,21 @@ module Solargraph
|
|
438
450
|
end
|
439
451
|
unchecked = arguments.clone
|
440
452
|
add_params = 0
|
441
|
-
if unchecked.empty? &&
|
453
|
+
if unchecked.empty? && parameters.any? { |param| param.decl == :kwarg }
|
442
454
|
return [Problem.new(location, "Missing keyword arguments to #{pin.path}")]
|
443
455
|
end
|
444
456
|
settled_kwargs = 0
|
445
457
|
unless unchecked.empty?
|
446
458
|
if any_splatted_call?(unchecked.map(&:node))
|
447
|
-
settled_kwargs =
|
459
|
+
settled_kwargs = parameters.count(&:keyword?)
|
448
460
|
else
|
449
461
|
kwargs = convert_hash(unchecked.last.node)
|
450
|
-
if
|
462
|
+
if parameters.any? { |param| [:kwarg, :kwoptarg].include?(param.decl) || param.kwrestarg? }
|
451
463
|
if kwargs.empty?
|
452
464
|
add_params += 1
|
453
465
|
else
|
454
466
|
unchecked.pop
|
455
|
-
|
467
|
+
parameters.each do |param|
|
456
468
|
next unless param.keyword?
|
457
469
|
if kwargs.key?(param.name.to_sym)
|
458
470
|
kwargs.delete param.name.to_sym
|
@@ -462,7 +474,7 @@ module Solargraph
|
|
462
474
|
return [Problem.new(location, "Missing keyword argument #{param.name} to #{pin.path}")]
|
463
475
|
end
|
464
476
|
end
|
465
|
-
kwargs.clear if
|
477
|
+
kwargs.clear if parameters.any?(&:kwrestarg?)
|
466
478
|
unless kwargs.empty?
|
467
479
|
return [Problem.new(location, "Unrecognized keyword argument #{kwargs.keys.first} to #{pin.path}")]
|
468
480
|
end
|
@@ -470,18 +482,18 @@ module Solargraph
|
|
470
482
|
end
|
471
483
|
end
|
472
484
|
end
|
473
|
-
req = required_param_count(
|
485
|
+
req = required_param_count(parameters)
|
474
486
|
if req + add_params < unchecked.length
|
475
|
-
return [] if
|
476
|
-
opt = optional_param_count(
|
487
|
+
return [] if parameters.any?(&:rest?)
|
488
|
+
opt = optional_param_count(parameters)
|
477
489
|
return [] if unchecked.length <= req + opt
|
478
490
|
if unchecked.length == req + opt + 1 && unchecked.last.links.last.is_a?(Source::Chain::BlockVariable)
|
479
491
|
return []
|
480
492
|
end
|
481
|
-
if req + add_params + 1 == unchecked.length && any_splatted_call?(unchecked.map(&:node)) && (
|
493
|
+
if req + add_params + 1 == unchecked.length && any_splatted_call?(unchecked.map(&:node)) && (parameters.map(&:decl) & [:kwarg, :kwoptarg, :kwrestarg]).any?
|
482
494
|
return []
|
483
495
|
end
|
484
|
-
return [] if arguments.length - req ==
|
496
|
+
return [] if arguments.length - req == parameters.select { |p| [:optarg, :kwoptarg].include?(p.decl) }.length
|
485
497
|
return [Problem.new(location, "Too many arguments to #{pin.path}")]
|
486
498
|
elsif unchecked.length < req - settled_kwargs && (arguments.empty? || (!arguments.last.splat? && !arguments.last.links.last.is_a?(Solargraph::Source::Chain::Hash)))
|
487
499
|
# HACK: Kernel#raise signature is incorrect in Ruby 2.7 core docs.
|
@@ -493,19 +505,13 @@ module Solargraph
|
|
493
505
|
[]
|
494
506
|
end
|
495
507
|
|
496
|
-
|
497
|
-
|
498
|
-
pin.parameters.sum { |param| %i[arg kwarg].include?(param.decl) ? 1 : 0 }
|
508
|
+
def required_param_count(parameters)
|
509
|
+
parameters.sum { |param| %i[arg kwarg].include?(param.decl) ? 1 : 0 }
|
499
510
|
end
|
500
511
|
|
501
512
|
# @param pin [Pin::Method]
|
502
|
-
def optional_param_count(
|
503
|
-
|
504
|
-
pin.parameters.each do |param|
|
505
|
-
next unless param.decl == :optarg
|
506
|
-
count += 1
|
507
|
-
end
|
508
|
-
count
|
513
|
+
def optional_param_count(parameters)
|
514
|
+
parameters.select { |p| p.decl == :optarg }.length
|
509
515
|
end
|
510
516
|
|
511
517
|
def abstract? pin
|
data/lib/solargraph/version.rb
CHANGED
@@ -30,10 +30,10 @@
|
|
30
30
|
Solargraph Version: <%= Solargraph::VERSION %>
|
31
31
|
</li>
|
32
32
|
<li>
|
33
|
-
Core Documentation Version:
|
33
|
+
Core Documentation Version: N/A <%# @todo Fix %>
|
34
34
|
</li>
|
35
35
|
<li>
|
36
|
-
Core Cache Directory:
|
36
|
+
Core Cache Directory: N/A <%# @todo Fix %>
|
37
37
|
</li>
|
38
38
|
<% unless Solargraph::Parser.rubyvm? %>
|
39
39
|
<li>
|