solargraph 0.39.7 → 0.39.12
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/SPONSORS.md +1 -0
- data/lib/solargraph.rb +3 -0
- data/lib/solargraph/api_map.rb +27 -21
- data/lib/solargraph/api_map/cache.rb +4 -0
- data/lib/solargraph/api_map/store.rb +35 -47
- data/lib/solargraph/compat.rb +9 -0
- data/lib/solargraph/language_server/message/text_document/formatting.rb +1 -1
- data/lib/solargraph/library.rb +16 -2
- data/lib/solargraph/parser/legacy/node_methods.rb +3 -1
- data/lib/solargraph/parser/legacy/node_processors/send_node.rb +10 -0
- data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +11 -0
- data/lib/solargraph/pin/base.rb +2 -2
- data/lib/solargraph/pin/block.rb +27 -13
- data/lib/solargraph/pin/documenting.rb +3 -2
- data/lib/solargraph/pin/method.rb +1 -1
- data/lib/solargraph/source/chain.rb +0 -31
- data/lib/solargraph/source/chain/z_super.rb +0 -154
- data/lib/solargraph/source/source_chainer.rb +2 -1
- data/lib/solargraph/source_map.rb +16 -1
- data/lib/solargraph/source_map/clip.rb +76 -43
- data/lib/solargraph/source_map/mapper.rb +20 -8
- data/lib/solargraph/stdlib_fills.rb +8 -0
- data/lib/solargraph/type_checker.rb +2 -3
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/yard_map.rb +22 -0
- data/lib/solargraph/yard_map/rdoc_to_yard.rb +14 -10
- data/solargraph.gemspec +1 -1
- data/yardoc/2.2.2.tar.gz +0 -0
- metadata +9 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 94e2150b6575ab34c7a13a51616cdbce7e21e13bff1b6cc2e6f4307960501acb
|
|
4
|
+
data.tar.gz: 474e22c2f716481a1410a8ba5199ce94b9d912573a29e077c29cea075fb8fd3d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ded8a57414921d2fc45616d9f8d10c8c6581d1769657968bd3b40e3b59d199f4090e9e086319cbea26dd9f4cab0d7231ebfd2b58b7f8f15524de745fc351ea88
|
|
7
|
+
data.tar.gz: f6fabb492847eb4091b0d642d9b41a28abb1b39e983f338828b17baf3a79aad1006244ef2dafbbd51757e11e4ac91eb721431151afe0e61ee11dc792e3d045f5
|
data/SPONSORS.md
CHANGED
data/lib/solargraph.rb
CHANGED
data/lib/solargraph/api_map.rb
CHANGED
|
@@ -26,7 +26,6 @@ module Solargraph
|
|
|
26
26
|
def initialize pins: []
|
|
27
27
|
@source_map_hash = {}
|
|
28
28
|
@cache = Cache.new
|
|
29
|
-
@mutex = Mutex.new
|
|
30
29
|
@method_alias_stack = []
|
|
31
30
|
index pins
|
|
32
31
|
end
|
|
@@ -34,13 +33,11 @@ module Solargraph
|
|
|
34
33
|
# @param pins [Array<Pin::Base>]
|
|
35
34
|
# @return [self]
|
|
36
35
|
def index pins
|
|
37
|
-
@
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
workspace_filenames.clear
|
|
43
|
-
}
|
|
36
|
+
@source_map_hash.clear
|
|
37
|
+
@cache.clear
|
|
38
|
+
@store = Store.new(pins + YardMap.new.pins)
|
|
39
|
+
@unresolved_requires = []
|
|
40
|
+
workspace_filenames.clear
|
|
44
41
|
self
|
|
45
42
|
end
|
|
46
43
|
|
|
@@ -123,14 +120,14 @@ module Solargraph
|
|
|
123
120
|
reqs.merge br.keys
|
|
124
121
|
yard_map.change(reqs.to_a, br, bundle.workspace.gemnames)
|
|
125
122
|
new_store = Store.new(pins + yard_map.pins)
|
|
126
|
-
@
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
123
|
+
@cache.clear
|
|
124
|
+
@source_map_hash = new_map_hash
|
|
125
|
+
@store = new_store
|
|
126
|
+
@unresolved_requires = yard_map.unresolved_requires
|
|
127
|
+
workspace_filenames.clear
|
|
128
|
+
workspace_filenames.concat bundle.workspace.filenames
|
|
129
|
+
@rebindable_method_names = nil
|
|
130
|
+
store.block_pins.each { |blk| blk.rebind(self) }
|
|
134
131
|
self
|
|
135
132
|
end
|
|
136
133
|
|
|
@@ -179,6 +176,16 @@ module Solargraph
|
|
|
179
176
|
store.pins
|
|
180
177
|
end
|
|
181
178
|
|
|
179
|
+
def rebindable_method_names
|
|
180
|
+
@rebindable_method_names ||= begin
|
|
181
|
+
result = yard_map.rebindable_method_names
|
|
182
|
+
source_maps.each do |map|
|
|
183
|
+
result.merge map.rebindable_method_names
|
|
184
|
+
end
|
|
185
|
+
result
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
182
189
|
# An array of pins based on Ruby keywords (`if`, `end`, etc.).
|
|
183
190
|
#
|
|
184
191
|
# @return [Array<Solargraph::Pin::Keyword>]
|
|
@@ -280,8 +287,7 @@ module Solargraph
|
|
|
280
287
|
|
|
281
288
|
# @return [Array<Solargraph::Pin::GlobalVariable>]
|
|
282
289
|
def get_global_variable_pins
|
|
283
|
-
|
|
284
|
-
pins.select{ |p| p.is_a?(Pin::GlobalVariable) }
|
|
290
|
+
store.pins_by_class(Pin::GlobalVariable)
|
|
285
291
|
end
|
|
286
292
|
|
|
287
293
|
# Get an array of methods available in a particular context.
|
|
@@ -535,17 +541,17 @@ module Solargraph
|
|
|
535
541
|
#
|
|
536
542
|
# @return [Hash{String => SourceMap}]
|
|
537
543
|
def source_map_hash
|
|
538
|
-
@
|
|
544
|
+
@source_map_hash
|
|
539
545
|
end
|
|
540
546
|
|
|
541
547
|
# @return [ApiMap::Store]
|
|
542
548
|
def store
|
|
543
|
-
@
|
|
549
|
+
@store
|
|
544
550
|
end
|
|
545
551
|
|
|
546
552
|
# @return [Solargraph::ApiMap::Cache]
|
|
547
553
|
def cache
|
|
548
|
-
@
|
|
554
|
+
@cache
|
|
549
555
|
end
|
|
550
556
|
|
|
551
557
|
# @param fqns [String] A fully qualified namespace
|
|
@@ -10,6 +10,7 @@ module Solargraph
|
|
|
10
10
|
@receiver_definitions = {}
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
+
# @return [Array<Pin::BaseMethod>]
|
|
13
14
|
def get_methods fqns, scope, visibility, deep
|
|
14
15
|
@methods[[fqns, scope, visibility.sort, deep]]
|
|
15
16
|
end
|
|
@@ -18,6 +19,7 @@ module Solargraph
|
|
|
18
19
|
@methods[[fqns, scope, visibility.sort, deep]] = value
|
|
19
20
|
end
|
|
20
21
|
|
|
22
|
+
# @return [Array<Pin::Base>]
|
|
21
23
|
def get_constants namespace, context
|
|
22
24
|
@constants[[namespace, context]]
|
|
23
25
|
end
|
|
@@ -26,6 +28,7 @@ module Solargraph
|
|
|
26
28
|
@constants[[namespace, context]] = value
|
|
27
29
|
end
|
|
28
30
|
|
|
31
|
+
# @return [String]
|
|
29
32
|
def get_qualified_namespace name, context
|
|
30
33
|
@qualified_namespaces[[name, context]]
|
|
31
34
|
end
|
|
@@ -38,6 +41,7 @@ module Solargraph
|
|
|
38
41
|
@receiver_definitions.key? path
|
|
39
42
|
end
|
|
40
43
|
|
|
44
|
+
# @return [Pin::BaseMethod]
|
|
41
45
|
def get_receiver_definition path
|
|
42
46
|
@receiver_definitions[path]
|
|
43
47
|
end
|
|
@@ -99,12 +99,12 @@ module Solargraph
|
|
|
99
99
|
|
|
100
100
|
# @return [Array<Solargraph::Pin::Base>]
|
|
101
101
|
def namespace_pins
|
|
102
|
-
|
|
102
|
+
pins_by_class(Solargraph::Pin::Namespace)
|
|
103
103
|
end
|
|
104
104
|
|
|
105
|
-
# @return [Array<Solargraph::Pin::
|
|
105
|
+
# @return [Array<Solargraph::Pin::BaseMethod>]
|
|
106
106
|
def method_pins
|
|
107
|
-
|
|
107
|
+
pins_by_class(Solargraph::Pin::BaseMethod)
|
|
108
108
|
end
|
|
109
109
|
|
|
110
110
|
# @param fqns [String]
|
|
@@ -133,7 +133,7 @@ module Solargraph
|
|
|
133
133
|
|
|
134
134
|
# @return [Array<Pin::Block>]
|
|
135
135
|
def block_pins
|
|
136
|
-
|
|
136
|
+
pins_by_class(Pin::Block)
|
|
137
137
|
end
|
|
138
138
|
|
|
139
139
|
def inspect
|
|
@@ -141,6 +141,12 @@ module Solargraph
|
|
|
141
141
|
to_s
|
|
142
142
|
end
|
|
143
143
|
|
|
144
|
+
# @param klass [Class]
|
|
145
|
+
# @return [Array<Solargraph::Pin::Base>]
|
|
146
|
+
def pins_by_class klass
|
|
147
|
+
@pin_select_cache[klass] ||= @pin_class_hash.select { |key, _| key <= klass }.values.flatten
|
|
148
|
+
end
|
|
149
|
+
|
|
144
150
|
private
|
|
145
151
|
|
|
146
152
|
# @param fqns [String]
|
|
@@ -167,7 +173,7 @@ module Solargraph
|
|
|
167
173
|
|
|
168
174
|
# @return [Array<Solargraph::Pin::Symbol>]
|
|
169
175
|
def symbols
|
|
170
|
-
|
|
176
|
+
pins_by_class(Pin::Symbol)
|
|
171
177
|
end
|
|
172
178
|
|
|
173
179
|
def superclass_references
|
|
@@ -198,7 +204,7 @@ module Solargraph
|
|
|
198
204
|
end
|
|
199
205
|
|
|
200
206
|
def all_instance_variables
|
|
201
|
-
|
|
207
|
+
pins_by_class(Pin::InstanceVariable)
|
|
202
208
|
end
|
|
203
209
|
|
|
204
210
|
def path_pin_hash
|
|
@@ -207,48 +213,29 @@ module Solargraph
|
|
|
207
213
|
|
|
208
214
|
# @return [void]
|
|
209
215
|
def index
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
prepend_references[pin.namespace] ||= []
|
|
232
|
-
prepend_references[pin.namespace].push pin.name
|
|
233
|
-
elsif pin.is_a?(Pin::Reference::Extend)
|
|
234
|
-
extend_references[pin.namespace] ||= []
|
|
235
|
-
extend_references[pin.namespace].push pin.name
|
|
236
|
-
elsif pin.is_a?(Pin::Reference::Superclass)
|
|
237
|
-
superclass_references[pin.namespace] ||= []
|
|
238
|
-
superclass_references[pin.namespace].push pin.name
|
|
239
|
-
elsif pin.is_a?(Pin::Block)
|
|
240
|
-
block_pins.push pin
|
|
241
|
-
elsif pin.is_a?(Pin::InstanceVariable)
|
|
242
|
-
all_instance_variables.push pin
|
|
243
|
-
elsif pin.is_a?(Pin::Reference::Override)
|
|
244
|
-
override_pins.push pin
|
|
245
|
-
end
|
|
246
|
-
if pin.path
|
|
247
|
-
path_pin_hash[pin.path] ||= []
|
|
248
|
-
path_pin_hash[pin.path].push pin
|
|
249
|
-
end
|
|
216
|
+
set = pins.to_set
|
|
217
|
+
@pin_class_hash = set.classify(&:class).transform_values(&:to_a)
|
|
218
|
+
@pin_select_cache = {}
|
|
219
|
+
@namespace_map = set.classify(&:namespace).transform_values(&:to_a)
|
|
220
|
+
@path_pin_hash = set.classify(&:path).transform_values(&:to_a)
|
|
221
|
+
@namespaces = @path_pin_hash.keys.compact
|
|
222
|
+
pins_by_class(Pin::Reference::Include).each do |pin|
|
|
223
|
+
include_references[pin.namespace] ||= []
|
|
224
|
+
include_references[pin.namespace].push pin.name
|
|
225
|
+
end
|
|
226
|
+
pins_by_class(Pin::Reference::Prepend).each do |pin|
|
|
227
|
+
prepend_references[pin.namespace] ||= []
|
|
228
|
+
prepend_references[pin.namespace].push pin.name
|
|
229
|
+
end
|
|
230
|
+
pins_by_class(Pin::Reference::Extend).each do |pin|
|
|
231
|
+
extend_references[pin.namespace] ||= []
|
|
232
|
+
extend_references[pin.namespace].push pin.name
|
|
233
|
+
end
|
|
234
|
+
pins_by_class(Pin::Reference::Superclass).each do |pin|
|
|
235
|
+
superclass_references[pin.namespace] ||= []
|
|
236
|
+
superclass_references[pin.namespace].push pin.name
|
|
250
237
|
end
|
|
251
|
-
|
|
238
|
+
pins_by_class(Pin::Reference::Override).each do |ovr|
|
|
252
239
|
pin = get_path_pins(ovr.name).first
|
|
253
240
|
next if pin.nil?
|
|
254
241
|
(ovr.tags.map(&:tag_name) + ovr.delete).uniq.each do |tag|
|
|
@@ -261,6 +248,7 @@ module Solargraph
|
|
|
261
248
|
# @todo This is probably not the best place for these overrides
|
|
262
249
|
superclass_references['Integer'] = ['Numeric']
|
|
263
250
|
superclass_references['Float'] = ['Numeric']
|
|
251
|
+
superclass_references['File'] = ['IO']
|
|
264
252
|
end
|
|
265
253
|
end
|
|
266
254
|
end
|
|
@@ -26,10 +26,10 @@ module Solargraph
|
|
|
26
26
|
store = RuboCop::ConfigStore.new
|
|
27
27
|
redirect_stdout { RuboCop::Runner.new(options, store).run(paths) }
|
|
28
28
|
result = File.read(tempfile)
|
|
29
|
-
File.unlink tempfile
|
|
30
29
|
format original, result
|
|
31
30
|
rescue RuboCop::ValidationError, RuboCop::ConfigNotFoundError => e
|
|
32
31
|
set_error(Solargraph::LanguageServer::ErrorCodes::INTERNAL_ERROR, "[#{e.class}] #{e.message}")
|
|
32
|
+
ensure
|
|
33
33
|
File.unlink tempfile
|
|
34
34
|
end
|
|
35
35
|
end
|
data/lib/solargraph/library.rb
CHANGED
|
@@ -171,7 +171,21 @@ module Solargraph
|
|
|
171
171
|
def definitions_at filename, line, column
|
|
172
172
|
position = Position.new(line, column)
|
|
173
173
|
cursor = Source::Cursor.new(read(filename), position)
|
|
174
|
-
|
|
174
|
+
if cursor.comment?
|
|
175
|
+
source = read(filename)
|
|
176
|
+
offset = Solargraph::Position.to_offset(source.code, Solargraph::Position.new(line, column))
|
|
177
|
+
lft = source.code[0..offset-1].match(/\[([a-z0-9_:]*)\z/i)
|
|
178
|
+
rgt = source.code[offset..-1].match(/^([a-z0-9_]*)(:[a-z0-9_:]*)?\]/i)
|
|
179
|
+
if lft && rgt
|
|
180
|
+
tag = lft[1] + rgt[1]
|
|
181
|
+
clip = api_map.clip(cursor)
|
|
182
|
+
clip.translate tag
|
|
183
|
+
else
|
|
184
|
+
[]
|
|
185
|
+
end
|
|
186
|
+
else
|
|
187
|
+
api_map.clip(cursor).define.map { |pin| pin.realize(api_map) }
|
|
188
|
+
end
|
|
175
189
|
end
|
|
176
190
|
|
|
177
191
|
# Get signature suggestions for the method at the specified file and
|
|
@@ -339,7 +353,7 @@ module Solargraph
|
|
|
339
353
|
logger.info "Cataloging #{workspace.directory.empty? ? 'generic workspace' : workspace.directory}"
|
|
340
354
|
api_map.catalog bundle
|
|
341
355
|
@synchronized = true
|
|
342
|
-
logger.info "Catalog complete (#{api_map.pins.length} pins)"
|
|
356
|
+
logger.info "Catalog complete (#{api_map.source_maps.length} files, #{api_map.pins.length} pins)" if logger.info?
|
|
343
357
|
end
|
|
344
358
|
end
|
|
345
359
|
|
|
@@ -124,7 +124,9 @@ module Solargraph
|
|
|
124
124
|
result = []
|
|
125
125
|
if node.type == :block
|
|
126
126
|
result.push node
|
|
127
|
-
node.children[0].children[
|
|
127
|
+
if Parser.is_ast_node?(node.children[0]) && node.children[0].children.length > 2
|
|
128
|
+
node.children[0].children[2..-1].each { |child| result.concat call_nodes_from(child) }
|
|
129
|
+
end
|
|
128
130
|
node.children[1..-1].each { |child| result.concat call_nodes_from(child) }
|
|
129
131
|
elsif node.type == :send
|
|
130
132
|
result.push node
|
|
@@ -36,6 +36,8 @@ module Solargraph
|
|
|
36
36
|
process_prepend
|
|
37
37
|
elsif node.children[1] == :require
|
|
38
38
|
process_require
|
|
39
|
+
elsif node.children[1] == :autoload
|
|
40
|
+
process_autoload
|
|
39
41
|
elsif node.children[1] == :private_constant
|
|
40
42
|
process_private_constant
|
|
41
43
|
elsif node.children[1] == :alias_method && node.children[2] && node.children[2] && node.children[2].type == :sym && node.children[3] && node.children[3].type == :sym
|
|
@@ -138,6 +140,14 @@ module Solargraph
|
|
|
138
140
|
end
|
|
139
141
|
end
|
|
140
142
|
|
|
143
|
+
# @return [void]
|
|
144
|
+
def process_autoload
|
|
145
|
+
if node.children[3].is_a?(AST::Node) && node.children[3].type == :str
|
|
146
|
+
path = node.children[3].children[0].to_s
|
|
147
|
+
pins.push Pin::Reference::Require.new(get_node_location(node), path)
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
141
151
|
# @return [void]
|
|
142
152
|
def process_module_function
|
|
143
153
|
if node.children[2].nil?
|
|
@@ -28,6 +28,8 @@ module Solargraph
|
|
|
28
28
|
process_module_function
|
|
29
29
|
elsif node.children[0] == :require
|
|
30
30
|
process_require
|
|
31
|
+
elsif node.children[0] == :autoload
|
|
32
|
+
process_autoload
|
|
31
33
|
elsif node.children[0] == :alias_method
|
|
32
34
|
process_alias_method
|
|
33
35
|
elsif node.children[0] == :private_class_method
|
|
@@ -143,6 +145,15 @@ module Solargraph
|
|
|
143
145
|
end
|
|
144
146
|
end
|
|
145
147
|
|
|
148
|
+
# @return [void]
|
|
149
|
+
def process_autoload
|
|
150
|
+
return unless Parser.is_ast_node?(node.children[1]) && Parser.is_ast_node?(node.children[1].children[1])
|
|
151
|
+
arg = node.children[1].children[1]
|
|
152
|
+
if arg.type == :STR
|
|
153
|
+
pins.push Pin::Reference::Require.new(get_node_location(arg), arg.children[0])
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
146
157
|
# @return [void]
|
|
147
158
|
def process_module_function
|
|
148
159
|
if node.type == :VCALL
|
data/lib/solargraph/pin/base.rb
CHANGED
|
@@ -23,7 +23,7 @@ module Solargraph
|
|
|
23
23
|
|
|
24
24
|
# @param location [Solargraph::Location]
|
|
25
25
|
# @param kind [Integer]
|
|
26
|
-
# @param closure [
|
|
26
|
+
# @param closure [Solargraph::Pin::Closure]
|
|
27
27
|
# @param name [String]
|
|
28
28
|
# @param comments [String]
|
|
29
29
|
def initialize location: nil, closure: nil, name: '', comments: ''
|
|
@@ -38,7 +38,7 @@ module Solargraph
|
|
|
38
38
|
@comments ||= ''
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
# @return [String]
|
|
41
|
+
# @return [String, nil]
|
|
42
42
|
def filename
|
|
43
43
|
return nil if location.nil?
|
|
44
44
|
location.filename
|
data/lib/solargraph/pin/block.rb
CHANGED
|
@@ -14,17 +14,14 @@ module Solargraph
|
|
|
14
14
|
@parameters = args
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def rebound?
|
|
23
|
-
@rebound ||= false
|
|
17
|
+
# @param api_map [ApiMap]
|
|
18
|
+
# @return [void]
|
|
19
|
+
def rebind api_map
|
|
20
|
+
@binder ||= binder_or_nil(api_map)
|
|
24
21
|
end
|
|
25
22
|
|
|
26
23
|
def binder
|
|
27
|
-
@binder ||
|
|
24
|
+
@binder || closure.binder
|
|
28
25
|
end
|
|
29
26
|
|
|
30
27
|
# @return [Array<String>]
|
|
@@ -37,11 +34,28 @@ module Solargraph
|
|
|
37
34
|
@parameter_names ||= parameters.map(&:name)
|
|
38
35
|
end
|
|
39
36
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
# @param api_map [ApiMap]
|
|
40
|
+
# @return [ComplexType, nil]
|
|
41
|
+
def binder_or_nil api_map
|
|
42
|
+
return nil unless receiver
|
|
43
|
+
word = receiver.children.find { |c| c.is_a?(::Symbol) }.to_s
|
|
44
|
+
return nil unless api_map.rebindable_method_names.include?(word)
|
|
45
|
+
chain = Parser.chain(receiver, location.filename)
|
|
46
|
+
locals = api_map.source_map(location.filename).locals_at(location)
|
|
47
|
+
if ['instance_eval', 'instance_exec', 'class_eval', 'class_exec', 'module_eval', 'module_exec'].include?(chain.links.last.word)
|
|
48
|
+
return chain.base.infer(api_map, self, locals)
|
|
49
|
+
else
|
|
50
|
+
receiver_pin = chain.define(api_map, self, locals).first
|
|
51
|
+
if receiver_pin && receiver_pin.docstring
|
|
52
|
+
ys = receiver_pin.docstring.tag(:yieldself)
|
|
53
|
+
if ys && ys.types && !ys.types.empty?
|
|
54
|
+
return ComplexType.try_parse(*ys.types).qualify(api_map, receiver_pin.context.namespace)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
nil
|
|
45
59
|
end
|
|
46
60
|
end
|
|
47
61
|
end
|
|
@@ -53,13 +53,14 @@ module Solargraph
|
|
|
53
53
|
# @param text [String]
|
|
54
54
|
# @return [String]
|
|
55
55
|
def escape_brackets text
|
|
56
|
-
text.gsub(/(\[[^\]]*\])([^\(]|\z)/, '
|
|
56
|
+
# text.gsub(/(\[[^\]]*\])([^\(]|\z)/, '!!!^\1^!!!\2')
|
|
57
|
+
text.gsub('[', '!!!!b').gsub(']', 'e!!!!')
|
|
57
58
|
end
|
|
58
59
|
|
|
59
60
|
# @param text [String]
|
|
60
61
|
# @return [String]
|
|
61
62
|
def unescape_brackets text
|
|
62
|
-
text.gsub('
|
|
63
|
+
text.gsub('!!!!b', '[').gsub('e!!!!', ']')
|
|
63
64
|
end
|
|
64
65
|
end
|
|
65
66
|
|
|
@@ -57,7 +57,6 @@ module Solargraph
|
|
|
57
57
|
# @param locals [Array<Pin::Base>]
|
|
58
58
|
# @return [Array<Pin::Base>]
|
|
59
59
|
def define api_map, name_pin, locals
|
|
60
|
-
rebind_block name_pin, api_map, locals
|
|
61
60
|
return [] if undefined?
|
|
62
61
|
working_pin = name_pin
|
|
63
62
|
links[0..-2].each do |link|
|
|
@@ -79,7 +78,6 @@ module Solargraph
|
|
|
79
78
|
# @param locals [Array<Pin::Base>]
|
|
80
79
|
# @return [ComplexType]
|
|
81
80
|
def infer api_map, name_pin, locals
|
|
82
|
-
rebind_block name_pin, api_map, locals
|
|
83
81
|
pins = define(api_map, name_pin, locals)
|
|
84
82
|
infer_first_defined(pins, links.last.last_context, api_map)
|
|
85
83
|
end
|
|
@@ -138,35 +136,6 @@ module Solargraph
|
|
|
138
136
|
return type if context.nil? || context.return_type.undefined?
|
|
139
137
|
type.self_to(context.return_type.namespace)
|
|
140
138
|
end
|
|
141
|
-
|
|
142
|
-
def skippable_block_receivers api_map
|
|
143
|
-
@@skippable_block_receivers ||= (
|
|
144
|
-
api_map.get_methods('Array', deep: false).map(&:name) +
|
|
145
|
-
api_map.get_methods('Enumerable', deep: false).map(&:name) +
|
|
146
|
-
api_map.get_methods('Hash', deep: false).map(&:name) +
|
|
147
|
-
['new']
|
|
148
|
-
).to_set
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
def rebind_block pin, api_map, locals
|
|
152
|
-
return unless pin.is_a?(Pin::Block) && pin.receiver && !pin.rebound?
|
|
153
|
-
# This first rebind just sets the block pin's rebound state
|
|
154
|
-
pin.rebind ComplexType::UNDEFINED
|
|
155
|
-
chain = Parser.chain(pin.receiver, pin.location.filename)
|
|
156
|
-
return if skippable_block_receivers(api_map).include?(chain.links.last.word)
|
|
157
|
-
if ['instance_eval', 'instance_exec', 'class_eval', 'class_exec', 'module_eval', 'module_exec'].include?(chain.links.last.word)
|
|
158
|
-
type = chain.base.infer(api_map, pin, locals)
|
|
159
|
-
pin.rebind type
|
|
160
|
-
else
|
|
161
|
-
receiver_pin = chain.define(api_map, pin, locals).first
|
|
162
|
-
return if receiver_pin.nil? || receiver_pin.docstring.nil?
|
|
163
|
-
ys = receiver_pin.docstring.tag(:yieldself)
|
|
164
|
-
unless ys.nil? || ys.types.nil? || ys.types.empty?
|
|
165
|
-
ysct = ComplexType.try_parse(*ys.types).qualify(api_map, receiver_pin.context.namespace)
|
|
166
|
-
pin.rebind ysct
|
|
167
|
-
end
|
|
168
|
-
end
|
|
169
|
-
end
|
|
170
139
|
end
|
|
171
140
|
end
|
|
172
141
|
end
|
|
@@ -18,166 +18,12 @@ module Solargraph
|
|
|
18
18
|
super(word, [], with_block)
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
def with_block?
|
|
22
|
-
@with_block
|
|
23
|
-
end
|
|
24
|
-
|
|
25
21
|
# @param api_map [ApiMap]
|
|
26
22
|
# @param name_pin [Pin::Base]
|
|
27
23
|
# @param locals [Array<Pin::Base>]
|
|
28
24
|
def resolve api_map, name_pin, locals
|
|
29
25
|
return super_pins(api_map, name_pin)
|
|
30
26
|
end
|
|
31
|
-
|
|
32
|
-
private
|
|
33
|
-
|
|
34
|
-
# @param pins [Array<Pin::Base>]
|
|
35
|
-
# @param api_map [ApiMap]
|
|
36
|
-
# @param context [ComplexType]
|
|
37
|
-
# @param locals [Pin::LocalVariable]
|
|
38
|
-
# @return [Array<Pin::Base>]
|
|
39
|
-
def inferred_pins pins, api_map, context, locals
|
|
40
|
-
result = pins.map do |p|
|
|
41
|
-
overloads = p.docstring.tags(:overload)
|
|
42
|
-
# next p if overloads.empty?
|
|
43
|
-
type = ComplexType::UNDEFINED
|
|
44
|
-
# @param [YARD::Tags::OverloadTag]
|
|
45
|
-
overloads.each do |ol|
|
|
46
|
-
next unless arguments_match(arguments, ol.parameters)
|
|
47
|
-
next if ol.parameters.last && ol.parameters.last.first.start_with?('&') && ol.parameters.last.last.nil? && !with_block?
|
|
48
|
-
match = true
|
|
49
|
-
arguments.each_with_index do |arg, idx|
|
|
50
|
-
achain = arguments[idx]
|
|
51
|
-
next if achain.nil?
|
|
52
|
-
param = ol.parameters[idx]
|
|
53
|
-
if param.nil?
|
|
54
|
-
match = false unless ol.parameters.last && ol.parameters.last.first.start_with?('*')
|
|
55
|
-
break
|
|
56
|
-
end
|
|
57
|
-
par = ol.tags(:param).select { |pp| pp.name == param.first }.first
|
|
58
|
-
next if par.nil? || par.types.nil? || par.types.empty?
|
|
59
|
-
atype = achain.infer(api_map, Pin::ProxyType.anonymous(context), locals)
|
|
60
|
-
other = ComplexType.try_parse(*par.types)
|
|
61
|
-
# @todo Weak type comparison
|
|
62
|
-
unless atype.tag == other.tag || api_map.super_and_sub?(other.tag, atype.tag)
|
|
63
|
-
match = false
|
|
64
|
-
break
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
if match
|
|
68
|
-
type = extra_return_type(ol, context)
|
|
69
|
-
type = ComplexType.try_parse(*ol.tag(:return).types).self_to(context.to_s).qualify(api_map, context.namespace) if ol.has_tag?(:return) && ol.tag(:return).types && !ol.tag(:return).types.empty? && (type.nil? || type.undefined?)
|
|
70
|
-
type ||= ComplexType::UNDEFINED
|
|
71
|
-
end
|
|
72
|
-
break if type.defined?
|
|
73
|
-
end
|
|
74
|
-
next p.proxy(type) if type.defined?
|
|
75
|
-
type = extra_return_type(p.docstring, context)
|
|
76
|
-
if type
|
|
77
|
-
next Solargraph::Pin::Method.new(
|
|
78
|
-
location: p.location,
|
|
79
|
-
closure: p.closure,
|
|
80
|
-
name: p.name,
|
|
81
|
-
comments: "@return [#{context.subtypes.first.to_s}]",
|
|
82
|
-
scope: p.scope,
|
|
83
|
-
visibility: p.visibility,
|
|
84
|
-
parameters: p.parameters,
|
|
85
|
-
node: p.node
|
|
86
|
-
)
|
|
87
|
-
end
|
|
88
|
-
if p.is_a?(Pin::Method) && !p.macros.empty?
|
|
89
|
-
result = process_macro(p, api_map, context, locals)
|
|
90
|
-
next result unless result.return_type.undefined?
|
|
91
|
-
elsif !p.directives.empty?
|
|
92
|
-
result = process_directive(p, api_map, context, locals)
|
|
93
|
-
next result unless result.return_type.undefined?
|
|
94
|
-
end
|
|
95
|
-
p
|
|
96
|
-
end
|
|
97
|
-
result.map do |pin|
|
|
98
|
-
next pin if pin.return_type.undefined?
|
|
99
|
-
selfy = pin.return_type.self_to(context.tag)
|
|
100
|
-
selfy == pin.return_type ? pin : pin.proxy(selfy)
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
# @param pin [Pin::Method]
|
|
105
|
-
# @param api_map [ApiMap]
|
|
106
|
-
# @param context [ComplexType]
|
|
107
|
-
# @param locals [Pin::Base]
|
|
108
|
-
# @return [Pin::Base]
|
|
109
|
-
def process_macro pin, api_map, context, locals
|
|
110
|
-
pin.macros.each do |macro|
|
|
111
|
-
result = inner_process_macro(pin, macro, api_map, context, locals)
|
|
112
|
-
return result unless result.return_type.undefined?
|
|
113
|
-
end
|
|
114
|
-
Pin::ProxyType.anonymous(ComplexType::UNDEFINED)
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
# @param pin [Pin::Method]
|
|
118
|
-
# @param api_map [ApiMap]
|
|
119
|
-
# @param context [ComplexType]
|
|
120
|
-
# @param locals [Pin::Base]
|
|
121
|
-
# @return [Pin::ProxyType]
|
|
122
|
-
def process_directive pin, api_map, context, locals
|
|
123
|
-
pin.directives.each do |dir|
|
|
124
|
-
macro = api_map.named_macro(dir.tag.name)
|
|
125
|
-
next if macro.nil?
|
|
126
|
-
result = inner_process_macro(pin, macro, api_map, context, locals)
|
|
127
|
-
return result unless result.return_type.undefined?
|
|
128
|
-
end
|
|
129
|
-
Pin::ProxyType.anonymous ComplexType::UNDEFINED
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
# @param pin [Pin]
|
|
133
|
-
# @param macro [YARD::Tags::MacroDirective]
|
|
134
|
-
# @param api_map [ApiMap]
|
|
135
|
-
# @param context [ComplexType]
|
|
136
|
-
# @param locals [Array<Pin::Base>]
|
|
137
|
-
# @return [Pin::ProxyType]
|
|
138
|
-
def inner_process_macro pin, macro, api_map, context, locals
|
|
139
|
-
vals = arguments.map{ |c| Pin::ProxyType.anonymous(c.infer(api_map, pin, locals)) }
|
|
140
|
-
txt = macro.tag.text.clone
|
|
141
|
-
if txt.empty? && macro.tag.name
|
|
142
|
-
named = api_map.named_macro(macro.tag.name)
|
|
143
|
-
txt = named.tag.text.clone if named
|
|
144
|
-
end
|
|
145
|
-
i = 1
|
|
146
|
-
vals.each do |v|
|
|
147
|
-
txt.gsub!(/\$#{i}/, v.context.namespace)
|
|
148
|
-
i += 1
|
|
149
|
-
end
|
|
150
|
-
docstring = Solargraph::Source.parse_docstring(txt).to_docstring
|
|
151
|
-
tag = docstring.tag(:return)
|
|
152
|
-
unless tag.nil? || tag.types.nil?
|
|
153
|
-
return Pin::ProxyType.anonymous(ComplexType.try_parse(*tag.types))
|
|
154
|
-
end
|
|
155
|
-
Pin::ProxyType.anonymous(ComplexType::UNDEFINED)
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
# @param docstring [YARD::Docstring]
|
|
159
|
-
# @param context [ComplexType]
|
|
160
|
-
# @return [ComplexType]
|
|
161
|
-
def extra_return_type docstring, context
|
|
162
|
-
if docstring.has_tag?(:return_single_parameter) && context.subtypes.one?
|
|
163
|
-
return context.subtypes.first
|
|
164
|
-
elsif docstring.has_tag?(:return_value_parameter) && context.value_types.one?
|
|
165
|
-
return context.value_types.first
|
|
166
|
-
end
|
|
167
|
-
nil
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
# @param arguments [Array<Chain>]
|
|
171
|
-
# @param parameters [Array<String>]
|
|
172
|
-
# @return [Boolean]
|
|
173
|
-
def arguments_match arguments, parameters
|
|
174
|
-
argcount = arguments.length
|
|
175
|
-
# argcount -= 1 if !arguments.empty? && arguments.last.links.first.word.start_with?('&')
|
|
176
|
-
parcount = parameters.length
|
|
177
|
-
parcount -= 1 if !parameters.empty? && parameters.last.first.start_with?('&')
|
|
178
|
-
return false if argcount < parcount && !(argcount == parcount - 1 && parameters.last.first.start_with?('*'))
|
|
179
|
-
true
|
|
180
|
-
end
|
|
181
27
|
end
|
|
182
28
|
end
|
|
183
29
|
end
|
|
@@ -17,7 +17,6 @@ module Solargraph
|
|
|
17
17
|
# @param position [Position]
|
|
18
18
|
# @return [Source::Chain]
|
|
19
19
|
def chain source, position
|
|
20
|
-
# raise "Not a source" unless source.is_a?(Source)
|
|
21
20
|
new(source, position).chain
|
|
22
21
|
end
|
|
23
22
|
end
|
|
@@ -32,6 +31,8 @@ module Solargraph
|
|
|
32
31
|
|
|
33
32
|
# @return [Source::Chain]
|
|
34
33
|
def chain
|
|
34
|
+
# Special handling for files that end with an integer and a period
|
|
35
|
+
return Chain.new([Chain::Literal.new('Integer'), Chain::UNDEFINED_CALL]) if phrase =~ /^[0-9]+\.$/
|
|
35
36
|
return Chain.new([Chain::Literal.new('Symbol')]) if phrase.start_with?(':') && !phrase.start_with?('::')
|
|
36
37
|
begin
|
|
37
38
|
return Chain.new([]) if phrase.end_with?('..')
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require 'jaro_winkler'
|
|
4
4
|
require 'yard'
|
|
5
5
|
require 'yard-solargraph'
|
|
6
|
+
require 'set'
|
|
6
7
|
|
|
7
8
|
module Solargraph
|
|
8
9
|
# An index of pins and other ApiMap-related data for a Source.
|
|
@@ -30,6 +31,19 @@ module Solargraph
|
|
|
30
31
|
@pins = pins
|
|
31
32
|
@locals = locals
|
|
32
33
|
environ.merge Convention.for(source)
|
|
34
|
+
@pin_class_hash = pins.to_set.classify(&:class).transform_values(&:to_a)
|
|
35
|
+
@pin_select_cache = {}
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def pins_by_class klass
|
|
39
|
+
@pin_select_cache[klass] ||= @pin_class_hash.select { |key, _| key <= klass }.values.flatten
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def rebindable_method_names
|
|
43
|
+
@rebindable_method_names ||= pins_by_class(Pin::Method)
|
|
44
|
+
.select { |pin| pin.comments && pin.comments.include?('@yieldself') }
|
|
45
|
+
.map(&:name)
|
|
46
|
+
.to_set
|
|
33
47
|
end
|
|
34
48
|
|
|
35
49
|
# @return [String]
|
|
@@ -44,7 +58,7 @@ module Solargraph
|
|
|
44
58
|
|
|
45
59
|
# @return [Array<Pin::Reference::Require>]
|
|
46
60
|
def requires
|
|
47
|
-
|
|
61
|
+
pins_by_class(Pin::Reference::Require)
|
|
48
62
|
end
|
|
49
63
|
|
|
50
64
|
# @return [Environ]
|
|
@@ -62,6 +76,7 @@ module Solargraph
|
|
|
62
76
|
# @param query [String]
|
|
63
77
|
# @return [Array<Pin::Base>]
|
|
64
78
|
def query_symbols query
|
|
79
|
+
return document_symbols if query && query.empty?
|
|
65
80
|
document_symbols.select{ |pin| fuzzy_string_match(pin.path, query) || fuzzy_string_match(pin.name, query) }
|
|
66
81
|
end
|
|
67
82
|
|
|
@@ -25,51 +25,12 @@ module Solargraph
|
|
|
25
25
|
def complete
|
|
26
26
|
return package_completions([]) if !source_map.source.parsed? || cursor.string?
|
|
27
27
|
return package_completions(api_map.get_symbols) if cursor.chain.literal? && cursor.chain.links.last.word == '<Symbol>'
|
|
28
|
-
return Completion.new([], cursor.range) if cursor.chain.literal?
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if cursor.chain.constant? || cursor.start_of_constant?
|
|
32
|
-
full = cursor.chain.links.first.word
|
|
33
|
-
type = if cursor.chain.undefined?
|
|
34
|
-
cursor.chain.base.infer(api_map, context_pin, locals)
|
|
35
|
-
else
|
|
36
|
-
if full.include?('::') && cursor.chain.links.length == 1
|
|
37
|
-
ComplexType.try_parse(full.split('::')[0..-2].join('::'))
|
|
38
|
-
elsif cursor.chain.links.length > 1
|
|
39
|
-
ComplexType.try_parse(full)
|
|
40
|
-
else
|
|
41
|
-
ComplexType::UNDEFINED
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
if type.undefined?
|
|
45
|
-
if full.include?('::')
|
|
46
|
-
result.concat api_map.get_constants(full, *gates)
|
|
47
|
-
else
|
|
48
|
-
result.concat api_map.get_constants('', cursor.start_of_constant? ? '' : context_pin.full_context.namespace, *gates) #.select { |pin| pin.name.start_with?(full) }
|
|
49
|
-
end
|
|
50
|
-
else
|
|
51
|
-
result.concat api_map.get_constants(type.namespace, cursor.start_of_constant? ? '' : context_pin.full_context.namespace, *gates)
|
|
52
|
-
end
|
|
28
|
+
return Completion.new([], cursor.range) if cursor.chain.literal?
|
|
29
|
+
if cursor.comment?
|
|
30
|
+
tag_complete
|
|
53
31
|
else
|
|
54
|
-
|
|
55
|
-
result.concat api_map.get_complex_type_methods(type, block.binder.namespace, cursor.chain.links.length == 1)
|
|
56
|
-
if cursor.chain.links.length == 1
|
|
57
|
-
if cursor.word.start_with?('@@')
|
|
58
|
-
return package_completions(api_map.get_class_variable_pins(context_pin.full_context.namespace))
|
|
59
|
-
elsif cursor.word.start_with?('@')
|
|
60
|
-
return package_completions(api_map.get_instance_variable_pins(block.binder.namespace, block.binder.scope))
|
|
61
|
-
elsif cursor.word.start_with?('$')
|
|
62
|
-
return package_completions(api_map.get_global_variable_pins)
|
|
63
|
-
end
|
|
64
|
-
result.concat locals
|
|
65
|
-
result.concat api_map.get_constants(context_pin.context.namespace, *gates)
|
|
66
|
-
result.concat api_map.get_methods(block.binder.namespace, scope: block.binder.scope, visibility: [:public, :private, :protected])
|
|
67
|
-
result.concat api_map.get_methods('Kernel')
|
|
68
|
-
result.concat ApiMap.keywords
|
|
69
|
-
result.concat yielded_self_pins
|
|
70
|
-
end
|
|
32
|
+
code_complete
|
|
71
33
|
end
|
|
72
|
-
package_completions(result)
|
|
73
34
|
end
|
|
74
35
|
|
|
75
36
|
# @return [Array<Pin::Base>]
|
|
@@ -111,6 +72,13 @@ module Solargraph
|
|
|
111
72
|
end
|
|
112
73
|
end
|
|
113
74
|
|
|
75
|
+
# @param phrase [String]
|
|
76
|
+
# @return [Array<Solargraph::Pin::Base>]
|
|
77
|
+
def translate phrase
|
|
78
|
+
chain = Parser.chain(Parser.parse(phrase))
|
|
79
|
+
chain.define(api_map, block, locals)
|
|
80
|
+
end
|
|
81
|
+
|
|
114
82
|
private
|
|
115
83
|
|
|
116
84
|
# @return [ApiMap]
|
|
@@ -185,6 +153,71 @@ module Solargraph
|
|
|
185
153
|
}
|
|
186
154
|
Completion.new(filtered, cursor.range)
|
|
187
155
|
end
|
|
156
|
+
|
|
157
|
+
def tag_complete
|
|
158
|
+
result = []
|
|
159
|
+
match = source_map.code[0..cursor.offset-1].match(/\[([a-z0-9_:]*)\z/i)
|
|
160
|
+
if match
|
|
161
|
+
full = match[1]
|
|
162
|
+
if full.include?('::')
|
|
163
|
+
if full.end_with?('::')
|
|
164
|
+
result.concat api_map.get_constants(full[0..-3], *gates)
|
|
165
|
+
else
|
|
166
|
+
result.concat api_map.get_constants(full.split('::')[0..-2].join('::'), *gates)
|
|
167
|
+
end
|
|
168
|
+
else
|
|
169
|
+
result.concat api_map.get_constants('', full.end_with?('::') ? '' : context_pin.full_context.namespace, *gates) #.select { |pin| pin.name.start_with?(full) }
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
package_completions(result)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def code_complete
|
|
176
|
+
result = []
|
|
177
|
+
result.concat complete_keyword_parameters
|
|
178
|
+
if cursor.chain.constant? || cursor.start_of_constant?
|
|
179
|
+
full = cursor.chain.links.first.word
|
|
180
|
+
type = if cursor.chain.undefined?
|
|
181
|
+
cursor.chain.base.infer(api_map, context_pin, locals)
|
|
182
|
+
else
|
|
183
|
+
if full.include?('::') && cursor.chain.links.length == 1
|
|
184
|
+
ComplexType.try_parse(full.split('::')[0..-2].join('::'))
|
|
185
|
+
elsif cursor.chain.links.length > 1
|
|
186
|
+
ComplexType.try_parse(full)
|
|
187
|
+
else
|
|
188
|
+
ComplexType::UNDEFINED
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
if type.undefined?
|
|
192
|
+
if full.include?('::')
|
|
193
|
+
result.concat api_map.get_constants(full, *gates)
|
|
194
|
+
else
|
|
195
|
+
result.concat api_map.get_constants('', cursor.start_of_constant? ? '' : context_pin.full_context.namespace, *gates) #.select { |pin| pin.name.start_with?(full) }
|
|
196
|
+
end
|
|
197
|
+
else
|
|
198
|
+
result.concat api_map.get_constants(type.namespace, cursor.start_of_constant? ? '' : context_pin.full_context.namespace, *gates)
|
|
199
|
+
end
|
|
200
|
+
else
|
|
201
|
+
type = cursor.chain.base.infer(api_map, block, locals)
|
|
202
|
+
result.concat api_map.get_complex_type_methods(type, block.binder.namespace, cursor.chain.links.length == 1)
|
|
203
|
+
if cursor.chain.links.length == 1
|
|
204
|
+
if cursor.word.start_with?('@@')
|
|
205
|
+
return package_completions(api_map.get_class_variable_pins(context_pin.full_context.namespace))
|
|
206
|
+
elsif cursor.word.start_with?('@')
|
|
207
|
+
return package_completions(api_map.get_instance_variable_pins(block.binder.namespace, block.binder.scope))
|
|
208
|
+
elsif cursor.word.start_with?('$')
|
|
209
|
+
return package_completions(api_map.get_global_variable_pins)
|
|
210
|
+
end
|
|
211
|
+
result.concat locals
|
|
212
|
+
result.concat api_map.get_constants(context_pin.context.namespace, *gates)
|
|
213
|
+
result.concat api_map.get_methods(block.binder.namespace, scope: block.binder.scope, visibility: [:public, :private, :protected])
|
|
214
|
+
result.concat api_map.get_methods('Kernel')
|
|
215
|
+
result.concat ApiMap.keywords
|
|
216
|
+
result.concat yielded_self_pins
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
package_completions(result)
|
|
220
|
+
end
|
|
188
221
|
end
|
|
189
222
|
end
|
|
190
223
|
end
|
|
@@ -95,6 +95,7 @@ module Solargraph
|
|
|
95
95
|
# @param source_position [Position]
|
|
96
96
|
# @param comment_position [Position]
|
|
97
97
|
# @param directive [YARD::Tags::Directive]
|
|
98
|
+
# @return [void]
|
|
98
99
|
def process_directive source_position, comment_position, directive
|
|
99
100
|
docstring = Solargraph::Source.parse_docstring(directive.tag.text).to_docstring
|
|
100
101
|
location = Location.new(@filename, Range.new(comment_position, comment_position))
|
|
@@ -104,10 +105,10 @@ module Solargraph
|
|
|
104
105
|
if namespace.location.range.start.line < comment_position.line
|
|
105
106
|
namespace = closure_at(comment_position)
|
|
106
107
|
end
|
|
107
|
-
region = Parser::Region.new(source: @source, closure: namespace)
|
|
108
108
|
begin
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
src = Solargraph::Source.load_string("def #{directive.tag.name};end", @source.filename)
|
|
110
|
+
region = Parser::Region.new(source: src, closure: namespace)
|
|
111
|
+
gen_pin = Parser.process_node(src.node, region).first.last
|
|
111
112
|
return if gen_pin.nil?
|
|
112
113
|
# Move the location to the end of the line so it gets recognized
|
|
113
114
|
# as originating from a comment
|
|
@@ -148,12 +149,23 @@ module Solargraph
|
|
|
148
149
|
)
|
|
149
150
|
end
|
|
150
151
|
when 'parse'
|
|
151
|
-
ns = closure_at(source_position)
|
|
152
|
-
region = Parser::Region.new(source: @source, closure: ns)
|
|
153
152
|
begin
|
|
154
|
-
|
|
153
|
+
ns = closure_at(source_position)
|
|
154
|
+
src = Solargraph::Source.load_string(directive.tag.text, @source.filename)
|
|
155
|
+
region = Parser::Region.new(source: src, closure: ns)
|
|
155
156
|
# @todo These pins may need to be marked not explicit
|
|
156
|
-
|
|
157
|
+
index = @pins.length
|
|
158
|
+
loff = if @code.lines[comment_position.line].strip.end_with?('@!parse')
|
|
159
|
+
comment_position.line + 1
|
|
160
|
+
else
|
|
161
|
+
comment_position.line
|
|
162
|
+
end
|
|
163
|
+
Parser.process_node(src.node, region, @pins)
|
|
164
|
+
@pins[index..-1].each do |p|
|
|
165
|
+
# @todo Smelly instance variable access
|
|
166
|
+
p.location.range.start.instance_variable_set(:@line, p.location.range.start.line + loff)
|
|
167
|
+
p.location.range.ending.instance_variable_set(:@line, p.location.range.ending.line + loff)
|
|
168
|
+
end
|
|
157
169
|
rescue Parser::SyntaxError => e
|
|
158
170
|
# @todo Handle parser errors in !parse directives
|
|
159
171
|
end
|
|
@@ -190,7 +202,7 @@ module Solargraph
|
|
|
190
202
|
code_lines = @code.lines
|
|
191
203
|
@source.associated_comments.each do |line, comments|
|
|
192
204
|
src_pos = line ? Position.new(line, code_lines[line].to_s.chomp.index(/[^\s]/) || 0) : Position.new(code_lines.length, 0)
|
|
193
|
-
com_pos = Position.new(line -
|
|
205
|
+
com_pos = Position.new(line + 1 - comments.lines.length, 0)
|
|
194
206
|
process_comment(src_pos, com_pos, comments)
|
|
195
207
|
end
|
|
196
208
|
end
|
|
@@ -20,6 +20,14 @@ module Solargraph
|
|
|
20
20
|
Override.method_return('Pathname#cleanpath', 'Pathname'),
|
|
21
21
|
Override.method_return('Pathname#children', 'Array<Pathname>'),
|
|
22
22
|
Override.method_return('Pathname#entries', 'Array<Pathname>')
|
|
23
|
+
],
|
|
24
|
+
|
|
25
|
+
'set' => [
|
|
26
|
+
Override.method_return('Enumerable#to_set', 'Set'),
|
|
27
|
+
Override.method_return('Set#add', 'self'),
|
|
28
|
+
Override.method_return('Set#add?', 'self, nil'),
|
|
29
|
+
Override.method_return('Set#classify', 'Hash'),
|
|
30
|
+
Override.from_comment('Set#each', '@yieldparam_single_parameter')
|
|
23
31
|
]
|
|
24
32
|
}
|
|
25
33
|
|
|
@@ -74,7 +74,7 @@ module Solargraph
|
|
|
74
74
|
def method_tag_problems
|
|
75
75
|
result = []
|
|
76
76
|
# @param pin [Pin::BaseMethod]
|
|
77
|
-
source_map.
|
|
77
|
+
source_map.pins_by_class(Pin::BaseMethod).each do |pin|
|
|
78
78
|
result.concat method_return_type_problems_for(pin)
|
|
79
79
|
result.concat method_param_type_problems_for(pin)
|
|
80
80
|
end
|
|
@@ -184,8 +184,7 @@ module Solargraph
|
|
|
184
184
|
|
|
185
185
|
# @return [Array<Pin::BaseVariable>]
|
|
186
186
|
def all_variables
|
|
187
|
-
source_map.
|
|
188
|
-
source_map.locals.select { |pin| pin.is_a?(Pin::LocalVariable) }
|
|
187
|
+
source_map.pins_by_class(Pin::BaseVariable) + source_map.locals.select { |pin| pin.is_a?(Pin::LocalVariable) }
|
|
189
188
|
end
|
|
190
189
|
|
|
191
190
|
def const_problems
|
data/lib/solargraph/version.rb
CHANGED
data/lib/solargraph/yard_map.rb
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require 'yard'
|
|
4
4
|
require 'yard-solargraph'
|
|
5
5
|
require 'rubygems/package'
|
|
6
|
+
require 'set'
|
|
6
7
|
|
|
7
8
|
module Solargraph
|
|
8
9
|
# The YardMap provides access to YARD documentation for the Ruby core, the
|
|
@@ -56,6 +57,7 @@ module Solargraph
|
|
|
56
57
|
@source_gems = []
|
|
57
58
|
process_requires
|
|
58
59
|
yardocs.uniq!
|
|
60
|
+
@pin_select_cache = {}
|
|
59
61
|
end
|
|
60
62
|
|
|
61
63
|
# @return [Array<Solargraph::Pin::Base>]
|
|
@@ -80,10 +82,22 @@ module Solargraph
|
|
|
80
82
|
@gemset = new_gemset
|
|
81
83
|
@source_gems = source_gems
|
|
82
84
|
process_requires
|
|
85
|
+
@rebindable_method_names = nil
|
|
86
|
+
@pin_class_hash = nil
|
|
87
|
+
@pin_select_cache = {}
|
|
83
88
|
true
|
|
84
89
|
end
|
|
85
90
|
end
|
|
86
91
|
|
|
92
|
+
# @return [Set<String>]
|
|
93
|
+
def rebindable_method_names
|
|
94
|
+
@rebindable_method_names ||= pins_by_class(Pin::Method)
|
|
95
|
+
.select { |pin| pin.comments && pin.comments.include?('@yieldself') }
|
|
96
|
+
.map(&:name)
|
|
97
|
+
.concat(['instance_eval', 'instance_exec', 'class_eval', 'class_exec', 'module_eval', 'module_exec'])
|
|
98
|
+
.to_set
|
|
99
|
+
end
|
|
100
|
+
|
|
87
101
|
# @return [Array<String>]
|
|
88
102
|
def yardocs
|
|
89
103
|
@yardocs ||= []
|
|
@@ -144,6 +158,14 @@ module Solargraph
|
|
|
144
158
|
@cache ||= YardMap::Cache.new
|
|
145
159
|
end
|
|
146
160
|
|
|
161
|
+
def pin_class_hash
|
|
162
|
+
@pin_class_hash ||= pins.to_set.classify(&:class).transform_values(&:to_a)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def pins_by_class klass
|
|
166
|
+
@pin_select_cache[klass] ||= pin_class_hash.select { |key, _| key <= klass }.values.flatten
|
|
167
|
+
end
|
|
168
|
+
|
|
147
169
|
# @param ns [YARD::CodeObjects::NamespaceObject]
|
|
148
170
|
# @return [Array<YARD::CodeObjects::Base>]
|
|
149
171
|
def recurse_namespace_object ns
|
|
@@ -15,23 +15,23 @@ module Solargraph
|
|
|
15
15
|
# @return [void]
|
|
16
16
|
def self.run spec, cache_dir: nil
|
|
17
17
|
Dir.mktmpdir do |tmpdir|
|
|
18
|
-
rdir = File.join(tmpdir, '
|
|
19
|
-
Dir.
|
|
18
|
+
rdir = File.join(tmpdir, 'sg_tmp_rdoc')
|
|
19
|
+
FileUtils.cp_r Dir.glob(File.join(spec.full_gem_path, '*')), tmpdir
|
|
20
|
+
Dir.chdir tmpdir do
|
|
20
21
|
pins = []
|
|
21
22
|
pins.push Solargraph::Pin::ROOT_PIN
|
|
22
23
|
name_hash = {}
|
|
23
24
|
|
|
24
|
-
argv = ['-q', '-
|
|
25
|
+
argv = ['-q', '-r', '-N', '-o', rdir]
|
|
25
26
|
spec.load_paths.each do |path|
|
|
26
27
|
argv.concat ['-i', path]
|
|
27
28
|
end
|
|
28
29
|
rdoc = RDoc::RDoc.new
|
|
29
30
|
rdoc.document argv
|
|
30
|
-
|
|
31
|
-
store =
|
|
32
|
-
store.
|
|
31
|
+
# @type [RDoc::Store]
|
|
32
|
+
store = rdoc.store
|
|
33
|
+
store.path = rdir
|
|
33
34
|
store.cache[:modules].each do |mod|
|
|
34
|
-
# store.load_class(mod)
|
|
35
35
|
# @type [RDoc::NormalClass]
|
|
36
36
|
mod = store.find_class_or_module(mod)
|
|
37
37
|
closure = pins.select { |pin| pin.path == mod.full_name.split('::')[0..-2].join('::') }.first || pins.first
|
|
@@ -51,7 +51,7 @@ module Solargraph
|
|
|
51
51
|
closure: namepin
|
|
52
52
|
)
|
|
53
53
|
end
|
|
54
|
-
# @param
|
|
54
|
+
# @param ext [RDoc::Extend]
|
|
55
55
|
mod.extends.each do |ext|
|
|
56
56
|
pins.push Solargraph::Pin::Reference::Extend.new(
|
|
57
57
|
location: locate(ext),
|
|
@@ -105,7 +105,11 @@ module Solargraph
|
|
|
105
105
|
mod.full_name.split('::')[0..-2].join('::')
|
|
106
106
|
end
|
|
107
107
|
|
|
108
|
+
# @param cmnt [RDoc::Comment]
|
|
109
|
+
# @return [String]
|
|
108
110
|
def self.commentary cmnt
|
|
111
|
+
return cmnt if cmnt.is_a?(String)
|
|
112
|
+
return cmnt.text if cmnt.is_a?(RDoc::Comment)
|
|
109
113
|
result = []
|
|
110
114
|
cmnt.parts.each do |part|
|
|
111
115
|
result.push RDoc::Markup::ToHtml.new({}).to_html(part.text) if part.respond_to?(:text)
|
|
@@ -126,9 +130,9 @@ module Solargraph
|
|
|
126
130
|
|
|
127
131
|
def self.find_file obj
|
|
128
132
|
if obj.respond_to?(:in_files) && !obj.in_files.empty?
|
|
129
|
-
[obj.in_files.first.to_s.sub(/^file /, ''), obj.
|
|
133
|
+
[obj.in_files.first.to_s.sub(/^file /, ''), obj.line]
|
|
130
134
|
else
|
|
131
|
-
[obj.
|
|
135
|
+
[obj.file, obj.line]
|
|
132
136
|
end
|
|
133
137
|
end
|
|
134
138
|
end
|
data/solargraph.gemspec
CHANGED
|
@@ -27,7 +27,7 @@ Gem::Specification.new do |s|
|
|
|
27
27
|
s.add_runtime_dependency 'maruku', '~> 0.7', '>= 0.7.3'
|
|
28
28
|
s.add_runtime_dependency 'nokogiri', '~> 1.9', '>= 1.9.1'
|
|
29
29
|
s.add_runtime_dependency 'parser', '~> 2.3'
|
|
30
|
-
s.add_runtime_dependency 'reverse_markdown', '
|
|
30
|
+
s.add_runtime_dependency 'reverse_markdown', '>= 1.0.5', '< 3'
|
|
31
31
|
s.add_runtime_dependency 'rubocop', '~> 0.52'
|
|
32
32
|
s.add_runtime_dependency 'thor', '~> 1.0'
|
|
33
33
|
s.add_runtime_dependency 'tilt', '~> 2.0'
|
data/yardoc/2.2.2.tar.gz
CHANGED
|
Binary file
|
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.39.
|
|
4
|
+
version: 0.39.12
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Fred Snyder
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2020-
|
|
11
|
+
date: 2020-07-18 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: backport
|
|
@@ -138,22 +138,22 @@ dependencies:
|
|
|
138
138
|
name: reverse_markdown
|
|
139
139
|
requirement: !ruby/object:Gem::Requirement
|
|
140
140
|
requirements:
|
|
141
|
-
- - "~>"
|
|
142
|
-
- !ruby/object:Gem::Version
|
|
143
|
-
version: '1.0'
|
|
144
141
|
- - ">="
|
|
145
142
|
- !ruby/object:Gem::Version
|
|
146
143
|
version: 1.0.5
|
|
144
|
+
- - "<"
|
|
145
|
+
- !ruby/object:Gem::Version
|
|
146
|
+
version: '3'
|
|
147
147
|
type: :runtime
|
|
148
148
|
prerelease: false
|
|
149
149
|
version_requirements: !ruby/object:Gem::Requirement
|
|
150
150
|
requirements:
|
|
151
|
-
- - "~>"
|
|
152
|
-
- !ruby/object:Gem::Version
|
|
153
|
-
version: '1.0'
|
|
154
151
|
- - ">="
|
|
155
152
|
- !ruby/object:Gem::Version
|
|
156
153
|
version: 1.0.5
|
|
154
|
+
- - "<"
|
|
155
|
+
- !ruby/object:Gem::Version
|
|
156
|
+
version: '3'
|
|
157
157
|
- !ruby/object:Gem::Dependency
|
|
158
158
|
name: rubocop
|
|
159
159
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -317,6 +317,7 @@ files:
|
|
|
317
317
|
- lib/solargraph/api_map/source_to_yard.rb
|
|
318
318
|
- lib/solargraph/api_map/store.rb
|
|
319
319
|
- lib/solargraph/bundle.rb
|
|
320
|
+
- lib/solargraph/compat.rb
|
|
320
321
|
- lib/solargraph/complex_type.rb
|
|
321
322
|
- lib/solargraph/complex_type/type_methods.rb
|
|
322
323
|
- lib/solargraph/complex_type/unique_type.rb
|