solargraph 0.38.0 → 0.38.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/README.md +6 -0
- data/lib/solargraph/api_map.rb +9 -7
- data/lib/solargraph/core_fills.rb +13 -1
- data/lib/solargraph/source/chain/call.rb +24 -4
- data/lib/solargraph/source/node_chainer.rb +2 -2
- data/lib/solargraph/source/node_methods.rb +2 -0
- data/lib/solargraph/type_checker.rb +47 -3
- data/lib/solargraph/version.rb +1 -1
- data/lib/yard-solargraph.rb +2 -0
- data/solargraph.gemspec +4 -1
- metadata +46 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0dbf36f40f7b87b541abe48c7e624999b44730cd5165f53ca8e7878311da7dcd
|
4
|
+
data.tar.gz: 0c12fa0cc1008eaf172fb964e6fac8fbc0b46333247b273b0e4ea9d840a81862
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b7d4bb938698bf682bbb418a6489b4544451ad91039d0fe0e0720339d8b2f9e6c394cc7d8354cc1b2cf6b5505867e93ca26071c177ecae69eab2cf5c1e2e601d
|
7
|
+
data.tar.gz: 368ad36e47cc109a9e3c428a743617771a69e14ce7730e4889bb7bab44c3c3aa13643608d6286497f7ea38b99c1f6da130a3401ae0a167a31cf07fb96197fac0
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -61,6 +61,12 @@ The Solargraph gem ships with documentation for Ruby 2.2.2. You can download doc
|
|
61
61
|
$ solargraph download-core # Install the best match for your Ruby version
|
62
62
|
$ solargraph clear # Reset the documentation cache
|
63
63
|
|
64
|
+
### The Documentation Cache
|
65
|
+
|
66
|
+
Solargraph uses a cache directory to store documentation for the Ruby core and customized documentation for certain gems. The default location is `~/.solargraph/cache`, e.g., `/home/<username>/.solargraph/cache` on Linux or `C:\Users\<username>\.solargraph` on Windows.
|
67
|
+
|
68
|
+
You can change the location of the cache directory with the `SOLARGRAPH_CACHE` environment variable. This can be useful if you want the cache to comply with the XDG Base Directory Specification.
|
69
|
+
|
64
70
|
### Solargraph and Bundler
|
65
71
|
|
66
72
|
If you're using the language server with a project that uses Bundler, the most comprehensive way to use your bundled gems is to bundle Solargraph.
|
data/lib/solargraph/api_map.rb
CHANGED
@@ -138,7 +138,7 @@ module Solargraph
|
|
138
138
|
@implicit ||= Environ.new
|
139
139
|
end
|
140
140
|
|
141
|
-
# @return [Hash]
|
141
|
+
# @return [Hash{String => String}]
|
142
142
|
def local_path_hash
|
143
143
|
@local_paths ||= {}
|
144
144
|
end
|
@@ -189,7 +189,7 @@ module Solargraph
|
|
189
189
|
|
190
190
|
# An array of namespace names defined in the ApiMap.
|
191
191
|
#
|
192
|
-
# @return [
|
192
|
+
# @return [Set<String>]
|
193
193
|
def namespaces
|
194
194
|
store.namespaces
|
195
195
|
end
|
@@ -513,9 +513,11 @@ module Solargraph
|
|
513
513
|
# @return [Boolean]
|
514
514
|
def super_and_sub?(sup, sub)
|
515
515
|
fqsup = qualify(sup)
|
516
|
-
cls = qualify(
|
517
|
-
until cls.nil?
|
518
|
-
|
516
|
+
cls = qualify(sub)
|
517
|
+
until fqsup.nil? || cls.nil?
|
518
|
+
# @todo Classes in the workspace are not detected as subclasses of
|
519
|
+
# Object. The quick and dirty fix is to hardcode it here.
|
520
|
+
return true if fqsup == 'Object' || cls == fqsup
|
519
521
|
cls = qualify(store.get_superclass(cls), cls)
|
520
522
|
end
|
521
523
|
false
|
@@ -627,7 +629,7 @@ module Solargraph
|
|
627
629
|
# @param name [String]
|
628
630
|
# @param root [String]
|
629
631
|
# @param skip [Array<String>]
|
630
|
-
# @return [String]
|
632
|
+
# @return [String, nil]
|
631
633
|
def inner_qualify name, root, skip
|
632
634
|
return nil if name.nil?
|
633
635
|
return nil if skip.include?(root)
|
@@ -663,7 +665,7 @@ module Solargraph
|
|
663
665
|
# Get the namespace's type (Class or Module).
|
664
666
|
#
|
665
667
|
# @param fqns [String] A fully qualified namespace
|
666
|
-
# @return [Symbol] :class, :module, or nil
|
668
|
+
# @return [Symbol, nil] :class, :module, or nil
|
667
669
|
def get_namespace_type fqns
|
668
670
|
return nil if fqns.nil?
|
669
671
|
# @type [Pin::Namespace, nil]
|
@@ -62,6 +62,11 @@ module Solargraph
|
|
62
62
|
@return_single_parameter
|
63
63
|
)),
|
64
64
|
|
65
|
+
Override.from_comment('BasicObject#==', %(
|
66
|
+
@param other [BasicObject]
|
67
|
+
@return [Boolean]
|
68
|
+
)),
|
69
|
+
|
65
70
|
Override.method_return('Class#new', 'self'),
|
66
71
|
Override.method_return('Class.new', 'Class<Object>'),
|
67
72
|
Override.method_return('Class#allocate', 'self'),
|
@@ -75,10 +80,16 @@ module Solargraph
|
|
75
80
|
@return_value_parameter
|
76
81
|
)),
|
77
82
|
|
83
|
+
# @todo This override isn't robust enough. It needs to allow for
|
84
|
+
# parameterized Hash types, e.g., [Hash{Symbol => String}].
|
85
|
+
Override.from_comment('Hash#[]=', %(
|
86
|
+
@param_tuple
|
87
|
+
)),
|
88
|
+
|
78
89
|
Override.method_return('Object#!', 'Boolean'),
|
79
90
|
Override.method_return('Object#clone', 'self', delete: [:overload]),
|
80
91
|
Override.method_return('Object#dup', 'self'),
|
81
|
-
Override.method_return('Object#freeze', 'self'),
|
92
|
+
Override.method_return('Object#freeze', 'self', delete: [:overload]),
|
82
93
|
Override.method_return('Object#taint', 'self'),
|
83
94
|
Override.method_return('Object#to_s', 'String'),
|
84
95
|
Override.method_return('Object#untaint', 'self'),
|
@@ -99,3 +110,4 @@ module Solargraph
|
|
99
110
|
)
|
100
111
|
end
|
101
112
|
end
|
113
|
+
|
@@ -12,16 +12,23 @@ module Solargraph
|
|
12
12
|
|
13
13
|
# @param word [String]
|
14
14
|
# @param arguments [Array<Chain>]
|
15
|
-
|
15
|
+
# @param with_block [Boolean] True if the chain is inside a block
|
16
|
+
# @param head [Boolean] True if the call is the start of its chain
|
17
|
+
def initialize word, arguments = [], with_block = false, head = false
|
16
18
|
@word = word
|
17
19
|
@arguments = arguments
|
18
20
|
@with_block = with_block
|
21
|
+
@head = head
|
19
22
|
end
|
20
23
|
|
21
24
|
def with_block?
|
22
25
|
@with_block
|
23
26
|
end
|
24
27
|
|
28
|
+
def head?
|
29
|
+
@head
|
30
|
+
end
|
31
|
+
|
25
32
|
# @param api_map [ApiMap]
|
26
33
|
# @param name_pin [Pin::Base]
|
27
34
|
# @param locals [Array<Pin::Base>]
|
@@ -29,6 +36,7 @@ module Solargraph
|
|
29
36
|
found = locals.select{|p| p.name == word}
|
30
37
|
return inferred_pins(found, api_map, name_pin.context, locals) unless found.empty?
|
31
38
|
pins = api_map.get_method_stack(name_pin.binder.namespace, word, scope: name_pin.binder.scope)
|
39
|
+
pins.concat api_map.get_method_stack('Kernel', word, scope: :instance) if head?
|
32
40
|
return [] if pins.empty?
|
33
41
|
inferred_pins(pins, api_map, name_pin.context, locals)
|
34
42
|
end
|
@@ -108,6 +116,7 @@ module Solargraph
|
|
108
116
|
# @param pin [Pin::Method]
|
109
117
|
# @param api_map [ApiMap]
|
110
118
|
# @param context [ComplexType]
|
119
|
+
# @param locals [Pin::Base]
|
111
120
|
# @return [Pin::Base]
|
112
121
|
def process_macro pin, api_map, context, locals
|
113
122
|
pin.macros.each do |macro|
|
@@ -117,6 +126,11 @@ module Solargraph
|
|
117
126
|
Pin::ProxyType.anonymous(ComplexType::UNDEFINED)
|
118
127
|
end
|
119
128
|
|
129
|
+
# @param pin [Pin::Method]
|
130
|
+
# @param api_map [ApiMap]
|
131
|
+
# @param context [ComplexType]
|
132
|
+
# @param locals [Pin::Base]
|
133
|
+
# @return [Pin::ProxyType]
|
120
134
|
def process_directive pin, api_map, context, locals
|
121
135
|
pin.directives.each do |dir|
|
122
136
|
macro = api_map.named_macro(dir.tag.name)
|
@@ -127,8 +141,12 @@ module Solargraph
|
|
127
141
|
Pin::ProxyType.anonymous ComplexType::UNDEFINED
|
128
142
|
end
|
129
143
|
|
130
|
-
# @param
|
144
|
+
# @param pin [Pin]
|
131
145
|
# @param macro [YARD::Tags::MacroDirective]
|
146
|
+
# @param api_map [ApiMap]
|
147
|
+
# @param context [ComplexType]
|
148
|
+
# @param locals [Array<Pin::Base>]
|
149
|
+
# @return [Pin::ProxyType]
|
132
150
|
def inner_process_macro pin, macro, api_map, context, locals
|
133
151
|
vals = arguments.map{ |c| Pin::ProxyType.anonymous(c.infer(api_map, pin, locals)) }
|
134
152
|
txt = macro.tag.text.clone
|
@@ -151,17 +169,19 @@ module Solargraph
|
|
151
169
|
|
152
170
|
# @param docstring [YARD::Docstring]
|
153
171
|
# @param context [ComplexType]
|
172
|
+
# @return [ComplexType]
|
154
173
|
def extra_return_type docstring, context
|
155
174
|
if docstring.has_tag?(:return_single_parameter) && context.subtypes.one?
|
156
175
|
return context.subtypes.first
|
157
176
|
elsif docstring.has_tag?(:return_value_parameter) && context.value_types.one?
|
158
177
|
return context.value_types.first
|
159
|
-
# elsif docstring.has_tag?(:return) && docstring.tag(:return).types && !docstring.tag(:return).types.empty?
|
160
|
-
# return ComplexType.try_parse(*docstring.tag(:return).types)
|
161
178
|
end
|
162
179
|
nil
|
163
180
|
end
|
164
181
|
|
182
|
+
# @param arguments [Array<Chain>]
|
183
|
+
# @param parameters [Array<String>]
|
184
|
+
# @return [Boolean]
|
165
185
|
def arguments_match arguments, parameters
|
166
186
|
argcount = arguments.length
|
167
187
|
# argcount -= 1 if !arguments.empty? && arguments.last.links.first.word.start_with?('&')
|
@@ -58,13 +58,13 @@ module Solargraph
|
|
58
58
|
n.children[2..-1].each do |c|
|
59
59
|
args.push NodeChainer.chain(c)
|
60
60
|
end
|
61
|
-
result.push Chain::Call.new(n.children[1].to_s, args, @in_block || block_passed?(n))
|
61
|
+
result.push Chain::Call.new(n.children[1].to_s, args, @in_block || block_passed?(n), result.length.zero?)
|
62
62
|
elsif n.children[0].nil?
|
63
63
|
args = []
|
64
64
|
n.children[2..-1].each do |c|
|
65
65
|
args.push NodeChainer.chain(c)
|
66
66
|
end
|
67
|
-
result.push Chain::Call.new(n.children[1].to_s, args, @in_block || block_passed?(n))
|
67
|
+
result.push Chain::Call.new(n.children[1].to_s, args, @in_block || block_passed?(n), result.length.zero?)
|
68
68
|
else
|
69
69
|
raise "No idea what to do with #{n}"
|
70
70
|
end
|
@@ -177,9 +177,33 @@ module Solargraph
|
|
177
177
|
else
|
178
178
|
pin = pins.first
|
179
179
|
ptypes = ParamDef.from(pin)
|
180
|
-
params =
|
180
|
+
params = first_param_tags_from(pins)
|
181
181
|
cursor = 0
|
182
182
|
curtype = nil
|
183
|
+
# The @param_tuple tag marks exceptional cases for handling, e.g., the Hash#[]= method.
|
184
|
+
if pin.docstring.tag(:param_tuple)
|
185
|
+
if node.children[2..-1].length > 2
|
186
|
+
result.push Problem.new(Solargraph::Location.new(filename, Solargraph::Range.from_node(node)), "Wrong number of arguments to #{pin.path}")
|
187
|
+
else
|
188
|
+
base = chain.base.infer(api_map, block, locals)
|
189
|
+
# @todo Don't just use the first key/value type
|
190
|
+
k = base.key_types.first || ComplexType.parse('Object')
|
191
|
+
v = base.value_types.first || ComplexType.parse('Object')
|
192
|
+
tuple = [
|
193
|
+
ParamDef.new('key', k),
|
194
|
+
ParamDef.new('value', v)
|
195
|
+
]
|
196
|
+
node.children[2..-1].each_with_index do |arg, index|
|
197
|
+
chain = Solargraph::Source::NodeChainer.chain(arg, filename)
|
198
|
+
argtype = chain.infer(api_map, block, locals)
|
199
|
+
partype = tuple[index].type
|
200
|
+
if argtype.tag != partype.tag && !api_map.super_and_sub?(partype.tag.to_s, argtype.tag.to_s)
|
201
|
+
result.push Problem.new(Solargraph::Location.new(filename, Solargraph::Range.from_node(node)), "Wrong parameter type for #{pin.path}: #{tuple[index].name} expected #{partype.tag}, received #{argtype.tag}")
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
return result
|
206
|
+
end
|
183
207
|
node.children[2..-1].each_with_index do |arg, index|
|
184
208
|
if pin.is_a?(Pin::Attribute)
|
185
209
|
curtype = ParamDef.new('value', :arg)
|
@@ -188,8 +212,20 @@ module Solargraph
|
|
188
212
|
end
|
189
213
|
if curtype.nil?
|
190
214
|
if pin.parameters[index].nil?
|
191
|
-
|
192
|
-
|
215
|
+
if params.values[index]
|
216
|
+
# Allow for methods that have named parameters but no
|
217
|
+
# arguments in their definitions. This is common in the Ruby
|
218
|
+
# core, e.g., the Hash#[]= method.
|
219
|
+
chain = Solargraph::Source::NodeChainer.chain(arg, filename)
|
220
|
+
argtype = chain.infer(api_map, block, locals)
|
221
|
+
partype = params.values[index]
|
222
|
+
if argtype.tag != partype.tag && !api_map.super_and_sub?(partype.tag.to_s, argtype.tag.to_s)
|
223
|
+
result.push Problem.new(Solargraph::Location.new(filename, Solargraph::Range.from_node(node)), "Wrong parameter type for #{pin.path}: #{params.keys[index]} expected #{partype.tag}, received #{argtype.tag}")
|
224
|
+
end
|
225
|
+
else
|
226
|
+
result.push Problem.new(Solargraph::Location.new(filename, Solargraph::Range.from_node(node)), "Not enough arguments sent to #{pin.path}")
|
227
|
+
break
|
228
|
+
end
|
193
229
|
end
|
194
230
|
else
|
195
231
|
# @todo This should also detect when the last parameter is a hash
|
@@ -300,6 +336,14 @@ module Solargraph
|
|
300
336
|
result
|
301
337
|
end
|
302
338
|
|
339
|
+
def first_param_tags_from pins
|
340
|
+
pins.each do |pin|
|
341
|
+
result = param_tags_from(pin)
|
342
|
+
return result unless result.empty?
|
343
|
+
end
|
344
|
+
{}
|
345
|
+
end
|
346
|
+
|
303
347
|
# @param location [Location, nil]
|
304
348
|
def report_location? location
|
305
349
|
return false if location.nil?
|
data/lib/solargraph/version.rb
CHANGED
data/lib/yard-solargraph.rb
CHANGED
@@ -22,6 +22,8 @@ YARD::Tags::Library.define_tag('ReturnSingleParameter', :return_single_parameter
|
|
22
22
|
YARD::Tags::Library.define_tag('YieldparamSingleParameter', :yieldparam_single_parameter)
|
23
23
|
# Define a @return_value_parameter tag for returning e.g. Hash values
|
24
24
|
YARD::Tags::Library.define_tag('ReturnValueParameter', :return_value_parameter)
|
25
|
+
# Define a @param_tuple tag for e.g. Hash#[]= parameters
|
26
|
+
YARD::Tags::Library.define_tag('ParamTuple', :param_tuple)
|
25
27
|
# Define a @!domain directive for documenting DSLs
|
26
28
|
YARD::Tags::Library.define_directive("domain", :with_types, Solargraph::DomainDirective)
|
27
29
|
# Define an @!override directive for overriding method tags
|
data/solargraph.gemspec
CHANGED
@@ -27,9 +27,12 @@ Gem::Specification.new do |s|
|
|
27
27
|
s.add_runtime_dependency 'parser', '~> 2.3'
|
28
28
|
s.add_runtime_dependency 'reverse_markdown', '~> 1.0', '>= 1.0.5'
|
29
29
|
s.add_runtime_dependency 'rubocop', '~> 0.52'
|
30
|
-
s.add_runtime_dependency 'thor', '~>
|
30
|
+
s.add_runtime_dependency 'thor', '~> 1.0'
|
31
31
|
s.add_runtime_dependency 'tilt', '~> 2.0'
|
32
32
|
s.add_runtime_dependency 'yard', '~> 0.9'
|
33
|
+
s.add_runtime_dependency 'e2mmap'
|
34
|
+
s.add_runtime_dependency 'irb', '<= 1.1.0'
|
35
|
+
s.add_runtime_dependency 'benchmark'
|
33
36
|
|
34
37
|
s.add_development_dependency 'pry', '~> 0.11.3'
|
35
38
|
s.add_development_dependency 'rspec', '~> 3.5', '>= 3.5.0'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: solargraph
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.38.
|
4
|
+
version: 0.38.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fred Snyder
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-01-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: backport
|
@@ -146,20 +146,14 @@ dependencies:
|
|
146
146
|
requirements:
|
147
147
|
- - "~>"
|
148
148
|
- !ruby/object:Gem::Version
|
149
|
-
version: '0
|
150
|
-
- - ">="
|
151
|
-
- !ruby/object:Gem::Version
|
152
|
-
version: 0.19.4
|
149
|
+
version: '1.0'
|
153
150
|
type: :runtime
|
154
151
|
prerelease: false
|
155
152
|
version_requirements: !ruby/object:Gem::Requirement
|
156
153
|
requirements:
|
157
154
|
- - "~>"
|
158
155
|
- !ruby/object:Gem::Version
|
159
|
-
version: '0
|
160
|
-
- - ">="
|
161
|
-
- !ruby/object:Gem::Version
|
162
|
-
version: 0.19.4
|
156
|
+
version: '1.0'
|
163
157
|
- !ruby/object:Gem::Dependency
|
164
158
|
name: tilt
|
165
159
|
requirement: !ruby/object:Gem::Requirement
|
@@ -188,6 +182,48 @@ dependencies:
|
|
188
182
|
- - "~>"
|
189
183
|
- !ruby/object:Gem::Version
|
190
184
|
version: '0.9'
|
185
|
+
- !ruby/object:Gem::Dependency
|
186
|
+
name: e2mmap
|
187
|
+
requirement: !ruby/object:Gem::Requirement
|
188
|
+
requirements:
|
189
|
+
- - ">="
|
190
|
+
- !ruby/object:Gem::Version
|
191
|
+
version: '0'
|
192
|
+
type: :runtime
|
193
|
+
prerelease: false
|
194
|
+
version_requirements: !ruby/object:Gem::Requirement
|
195
|
+
requirements:
|
196
|
+
- - ">="
|
197
|
+
- !ruby/object:Gem::Version
|
198
|
+
version: '0'
|
199
|
+
- !ruby/object:Gem::Dependency
|
200
|
+
name: irb
|
201
|
+
requirement: !ruby/object:Gem::Requirement
|
202
|
+
requirements:
|
203
|
+
- - "<="
|
204
|
+
- !ruby/object:Gem::Version
|
205
|
+
version: 1.1.0
|
206
|
+
type: :runtime
|
207
|
+
prerelease: false
|
208
|
+
version_requirements: !ruby/object:Gem::Requirement
|
209
|
+
requirements:
|
210
|
+
- - "<="
|
211
|
+
- !ruby/object:Gem::Version
|
212
|
+
version: 1.1.0
|
213
|
+
- !ruby/object:Gem::Dependency
|
214
|
+
name: benchmark
|
215
|
+
requirement: !ruby/object:Gem::Requirement
|
216
|
+
requirements:
|
217
|
+
- - ">="
|
218
|
+
- !ruby/object:Gem::Version
|
219
|
+
version: '0'
|
220
|
+
type: :runtime
|
221
|
+
prerelease: false
|
222
|
+
version_requirements: !ruby/object:Gem::Requirement
|
223
|
+
requirements:
|
224
|
+
- - ">="
|
225
|
+
- !ruby/object:Gem::Version
|
226
|
+
version: '0'
|
191
227
|
- !ruby/object:Gem::Dependency
|
192
228
|
name: pry
|
193
229
|
requirement: !ruby/object:Gem::Requirement
|