solargraph 0.38.0 → 0.38.1
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/.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
|