solargraph 0.18.3 → 0.19.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/lib/solargraph/api_map/probe.rb +222 -0
- data/lib/solargraph/api_map/source_to_yard.rb +3 -3
- data/lib/solargraph/api_map/store.rb +135 -0
- data/lib/solargraph/api_map.rb +169 -609
- data/lib/solargraph/diagnostics/rubocop.rb +4 -4
- data/lib/solargraph/language_server/host.rb +53 -19
- data/lib/solargraph/language_server/message/extended/document.rb +1 -1
- data/lib/solargraph/language_server/message/extended/search.rb +1 -1
- data/lib/solargraph/language_server/message/method_not_found.rb +1 -1
- data/lib/solargraph/language_server/message/text_document/definition.rb +2 -15
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +2 -15
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +3 -15
- data/lib/solargraph/language_server/message_types.rb +10 -0
- data/lib/solargraph/language_server.rb +1 -0
- data/lib/solargraph/library.rb +8 -0
- data/lib/solargraph/node_methods.rb +6 -1
- data/lib/solargraph/page.rb +2 -1
- data/lib/solargraph/pin/attribute.rb +8 -12
- data/lib/solargraph/pin/base.rb +20 -95
- data/lib/solargraph/pin/base_variable.rb +15 -74
- data/lib/solargraph/pin/block.rb +21 -0
- data/lib/solargraph/pin/block_parameter.rb +30 -44
- data/lib/solargraph/pin/class_variable.rb +3 -0
- data/lib/solargraph/pin/constant.rb +4 -8
- data/lib/solargraph/pin/conversions.rb +4 -3
- data/lib/solargraph/pin/documenting.rb +27 -0
- data/lib/solargraph/pin/global_variable.rb +3 -0
- data/lib/solargraph/pin/instance_variable.rb +5 -4
- data/lib/solargraph/pin/local_variable.rb +8 -15
- data/lib/solargraph/pin/localized.rb +12 -0
- data/lib/solargraph/pin/method.rb +6 -67
- data/lib/solargraph/pin/method_parameter.rb +24 -11
- data/lib/solargraph/pin/namespace.rb +26 -35
- data/lib/solargraph/pin/reference.rb +15 -8
- data/lib/solargraph/pin/symbol.rb +34 -3
- data/lib/solargraph/pin/yard_object.rb +11 -4
- data/lib/solargraph/pin.rb +16 -2
- data/lib/solargraph/server.rb +2 -2
- data/lib/solargraph/source/change.rb +10 -13
- data/lib/solargraph/source/fragment.rb +42 -94
- data/lib/solargraph/source/location.rb +13 -0
- data/lib/solargraph/source/mapper.rb +426 -0
- data/lib/solargraph/source/position.rb +1 -0
- data/lib/solargraph/source/range.rb +11 -3
- data/lib/solargraph/source.rb +93 -284
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/views/_method.erb +59 -60
- data/lib/solargraph/views/_name_type_tag.erb +10 -0
- data/lib/solargraph/views/_namespace.erb +26 -26
- data/lib/solargraph/views/document.erb +23 -16
- data/lib/solargraph/views/layout.erb +38 -10
- data/lib/solargraph/views/search.erb +12 -11
- data/lib/solargraph/workspace/config.rb +27 -6
- data/lib/solargraph/workspace.rb +10 -2
- data/lib/solargraph.rb +10 -2
- data/lib/yard-solargraph.rb +3 -0
- metadata +25 -20
- data/lib/solargraph/pin/directed/attribute.rb +0 -20
- data/lib/solargraph/pin/directed/method.rb +0 -22
- data/lib/solargraph/pin/directed.rb +0 -9
- data/lib/solargraph/pin/parameter.rb +0 -23
data/lib/solargraph/api_map.rb
CHANGED
@@ -7,6 +7,8 @@ module Solargraph
|
|
7
7
|
autoload :Cache, 'solargraph/api_map/cache'
|
8
8
|
autoload :SourceToYard, 'solargraph/api_map/source_to_yard'
|
9
9
|
autoload :Completion, 'solargraph/api_map/completion'
|
10
|
+
autoload :Probe, 'solargraph/api_map/probe'
|
11
|
+
autoload :Store, 'solargraph/api_map/store'
|
10
12
|
|
11
13
|
include Solargraph::ApiMap::SourceToYard
|
12
14
|
include CoreFills
|
@@ -17,27 +19,41 @@ module Solargraph
|
|
17
19
|
attr_reader :workspace
|
18
20
|
|
19
21
|
# @param workspace [Solargraph::Workspace]
|
20
|
-
def initialize workspace = nil
|
21
|
-
# @todo Deprecate strings for the workspace parameter
|
22
|
-
workspace = Solargraph::Workspace.new(workspace) if workspace.kind_of?(String)
|
23
|
-
workspace = Solargraph::Workspace.new(nil) if workspace.nil?
|
22
|
+
def initialize workspace = Solargraph::Workspace.new(nil)
|
24
23
|
@workspace = workspace
|
25
24
|
require_extensions
|
26
25
|
@virtual_source = nil
|
27
26
|
@yard_stale = true
|
28
|
-
process_maps
|
27
|
+
# process_maps
|
28
|
+
@sources = workspace.sources
|
29
29
|
yard_map
|
30
30
|
end
|
31
31
|
|
32
|
+
# Create an ApiMap with a workspace in the specified directory.
|
33
|
+
#
|
34
|
+
# @return [ApiMap]
|
32
35
|
def self.load directory
|
33
36
|
self.new(Solargraph::Workspace.new(directory))
|
34
37
|
end
|
35
38
|
|
39
|
+
# @return [ApiMap::Store]
|
40
|
+
def store
|
41
|
+
@store ||= ApiMap::Store.new(@sources)
|
42
|
+
end
|
43
|
+
|
44
|
+
def pins
|
45
|
+
store.pins
|
46
|
+
end
|
47
|
+
|
36
48
|
# An array of required paths in the workspace.
|
37
49
|
#
|
38
50
|
# @return [Array<String>]
|
39
51
|
def required
|
40
|
-
|
52
|
+
result = []
|
53
|
+
@sources.each do |s|
|
54
|
+
result.concat s.required
|
55
|
+
end
|
56
|
+
result.uniq
|
41
57
|
end
|
42
58
|
|
43
59
|
# Get a YardMap associated with the current workspace.
|
@@ -65,8 +81,9 @@ module Solargraph
|
|
65
81
|
# one source can be virtualized at a time.
|
66
82
|
#
|
67
83
|
# @param source [Solargraph::Source]
|
84
|
+
# @return [Solargraph::Source]
|
68
85
|
def virtualize source
|
69
|
-
|
86
|
+
store.remove @virtual_source unless @virtual_source.nil?
|
70
87
|
if workspace.has_source?(source)
|
71
88
|
@sources = workspace.sources
|
72
89
|
@virtual_source = nil
|
@@ -78,10 +95,18 @@ module Solargraph
|
|
78
95
|
process_virtual
|
79
96
|
end
|
80
97
|
end
|
98
|
+
source
|
81
99
|
end
|
82
100
|
|
83
|
-
#
|
84
|
-
|
101
|
+
# Create a Source from the code and filename, and virtualize the result.
|
102
|
+
# This method can be useful for directly testing the ApiMap. In practice,
|
103
|
+
# applications should use a Library to synchronize the ApiMap to a
|
104
|
+
# workspace.
|
105
|
+
#
|
106
|
+
# @param code [String]
|
107
|
+
# @param filename [String]
|
108
|
+
# @return [Solargraph::Source]
|
109
|
+
def virtualize_string code, filename = nil
|
85
110
|
source = Source.load_string(code, filename)
|
86
111
|
virtualize source
|
87
112
|
end
|
@@ -92,27 +117,12 @@ module Solargraph
|
|
92
117
|
def refresh force = false
|
93
118
|
return unless @force or changed?
|
94
119
|
if force
|
95
|
-
|
120
|
+
@api_map = ApiMap::Store.new(@sources)
|
96
121
|
else
|
97
|
-
current_workspace_sources.reject{|s| workspace.sources.include?(s)}
|
98
|
-
eliminate source
|
99
|
-
end
|
122
|
+
store.remove *(current_workspace_sources.reject{ |s| workspace.sources.include?(s) })
|
100
123
|
@sources = workspace.sources
|
101
124
|
@sources.push @virtual_source unless @virtual_source.nil?
|
102
|
-
|
103
|
-
namespace_map.clear
|
104
|
-
@sources.each do |s|
|
105
|
-
s.namespaces.each do |n|
|
106
|
-
namespace_map[n] ||= []
|
107
|
-
namespace_map[n].concat s.namespace_pins(n)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
@sources.each do |source|
|
111
|
-
if @stime.nil? or source.stime > @stime
|
112
|
-
eliminate source
|
113
|
-
map_source source
|
114
|
-
end
|
115
|
-
end
|
125
|
+
store.update *(@sources.select{ |s| @stime.nil? or s.stime > @stime })
|
116
126
|
end
|
117
127
|
@stime = Time.new
|
118
128
|
end
|
@@ -142,8 +152,7 @@ module Solargraph
|
|
142
152
|
#
|
143
153
|
# @return [Array<String>]
|
144
154
|
def namespaces
|
145
|
-
|
146
|
-
namespace_map.keys
|
155
|
+
store.namespaces
|
147
156
|
end
|
148
157
|
|
149
158
|
# True if the namespace exists.
|
@@ -152,14 +161,14 @@ module Solargraph
|
|
152
161
|
# @param root [String] The context to search
|
153
162
|
# @return [Boolean]
|
154
163
|
def namespace_exists? name, root = ''
|
155
|
-
!
|
164
|
+
!qualify(name, root).nil?
|
156
165
|
end
|
157
166
|
|
158
167
|
# Get suggestions for constants in the specified namespace. The result
|
159
168
|
# may contain both constant and namespace pins.
|
160
169
|
#
|
161
|
-
# @param
|
162
|
-
# @param
|
170
|
+
# @param namespace [String] The namespace
|
171
|
+
# @param context [String] The context
|
163
172
|
# @return [Array<Solargraph::Pin::Base>]
|
164
173
|
def get_constants namespace, context = ''
|
165
174
|
namespace ||= ''
|
@@ -168,13 +177,13 @@ module Solargraph
|
|
168
177
|
bases = context.split('::')
|
169
178
|
while bases.length > 0
|
170
179
|
built = bases.join('::')
|
171
|
-
fqns =
|
180
|
+
fqns = qualify(namespace, built)
|
172
181
|
visibility = [:public]
|
173
182
|
visibility.push :private if fqns == context
|
174
183
|
result.concat inner_get_constants(fqns, visibility, skip)
|
175
184
|
bases.pop
|
176
185
|
end
|
177
|
-
fqns =
|
186
|
+
fqns = qualify(namespace, '')
|
178
187
|
visibility = [:public]
|
179
188
|
visibility.push :private if fqns == context
|
180
189
|
result.concat inner_get_constants(fqns, visibility, skip)
|
@@ -182,54 +191,18 @@ module Solargraph
|
|
182
191
|
end
|
183
192
|
|
184
193
|
# Get a fully qualified namespace name. This method will start the search
|
185
|
-
# in the specified
|
194
|
+
# in the specified context until it finds a match for the name.
|
186
195
|
#
|
187
|
-
# @param
|
188
|
-
# @param
|
196
|
+
# @param namespace [String] The namespace to match
|
197
|
+
# @param context [String] The context to search
|
189
198
|
# @return [String]
|
190
|
-
def
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
return ''
|
198
|
-
else
|
199
|
-
return find_fully_qualified_namespace(root, '', skip)
|
200
|
-
end
|
201
|
-
else
|
202
|
-
if (root == '')
|
203
|
-
return name unless namespace_map[name].nil?
|
204
|
-
im = @namespace_includes['']
|
205
|
-
unless im.nil?
|
206
|
-
im.each do |i|
|
207
|
-
i.resolve self
|
208
|
-
return i.name unless i.name.nil?
|
209
|
-
end
|
210
|
-
end
|
211
|
-
else
|
212
|
-
roots = root.to_s.split('::')
|
213
|
-
while roots.length > 0
|
214
|
-
fqns = roots.join('::') + '::' + name
|
215
|
-
return fqns unless namespace_map[fqns].nil?
|
216
|
-
roots.pop
|
217
|
-
end
|
218
|
-
return name unless namespace_map[name].nil?
|
219
|
-
im = @namespace_includes['']
|
220
|
-
unless im.nil?
|
221
|
-
im.each do |i|
|
222
|
-
i.resolve self
|
223
|
-
return i.name unless i.name.nil?
|
224
|
-
end
|
225
|
-
end
|
226
|
-
end
|
227
|
-
end
|
228
|
-
result = yard_map.find_fully_qualified_namespace(name, root)
|
229
|
-
if result.nil?
|
230
|
-
result = live_map.get_fqns(name, root)
|
231
|
-
end
|
232
|
-
result
|
199
|
+
def qualify namespace, context = ''
|
200
|
+
inner_qualify namespace, context, []
|
201
|
+
end
|
202
|
+
|
203
|
+
# @deprecated Use #qualify instead
|
204
|
+
def find_fully_qualified_namespace namespace, context = ''
|
205
|
+
qualify namespace, context
|
233
206
|
end
|
234
207
|
|
235
208
|
# Get an array of instance variable pins defined in specified namespace
|
@@ -239,13 +212,7 @@ module Solargraph
|
|
239
212
|
# @param scope [Symbol] :instance or :class
|
240
213
|
# @return [Array<Solargraph::Pin::InstanceVariable>]
|
241
214
|
def get_instance_variable_pins(namespace, scope = :instance)
|
242
|
-
|
243
|
-
return [] if raw.nil?
|
244
|
-
# @todo This is a crazy workaround because instance variables in the
|
245
|
-
# global namespace might be in either scope
|
246
|
-
pins = prefer_non_nil_variables(raw)
|
247
|
-
return pins if namespace.empty?
|
248
|
-
pins.select{ |pin| pin.scope == scope }
|
215
|
+
store.get_instance_variables(namespace, scope)
|
249
216
|
end
|
250
217
|
|
251
218
|
# Get an array of class variable pins for a namespace.
|
@@ -258,221 +225,7 @@ module Solargraph
|
|
258
225
|
|
259
226
|
# @return [Array<Solargraph::Pin::Base>]
|
260
227
|
def get_symbols
|
261
|
-
|
262
|
-
@symbol_pins
|
263
|
-
end
|
264
|
-
|
265
|
-
# Find a class, instance, or global variable by name in the provided
|
266
|
-
# namespace and scope.
|
267
|
-
#
|
268
|
-
# @param name [String] The variable name, e.g., `@foo`, `@@bar`, or `$baz`
|
269
|
-
# @param fqns [String] The fully qualified namespace
|
270
|
-
# @param scope [Symbol] :class or :instance
|
271
|
-
# @return [Solargraph::Pin::BaseVariable]
|
272
|
-
def find_variable_pin name, fqns, scope
|
273
|
-
var = nil
|
274
|
-
return nil if name.nil?
|
275
|
-
if name.start_with?('@@')
|
276
|
-
# class variable
|
277
|
-
var = get_class_variable_pins(fqns).select{|pin| pin.name == name}.first
|
278
|
-
return nil if var.nil?
|
279
|
-
elsif name.start_with?('@')
|
280
|
-
# instance variable
|
281
|
-
var = get_instance_variable_pins(fqns, scope).select{|pin| pin.name == name}.first
|
282
|
-
return nil if var.nil?
|
283
|
-
elsif name.start_with?('$')
|
284
|
-
# global variable
|
285
|
-
var = get_global_variable_pins.select{|pin| pin.name == name}.first
|
286
|
-
return nil if var.nil?
|
287
|
-
end
|
288
|
-
var
|
289
|
-
end
|
290
|
-
|
291
|
-
def find_namespace_pin fqns
|
292
|
-
crawl_constants fqns, '', [:public, :private]
|
293
|
-
end
|
294
|
-
|
295
|
-
def crawl_constants name, fqns, visibility
|
296
|
-
return nil if name.nil?
|
297
|
-
chain = name.split('::')
|
298
|
-
cursor = chain.shift
|
299
|
-
return nil if cursor.nil?
|
300
|
-
unless fqns.empty?
|
301
|
-
bases = fqns.split('::')
|
302
|
-
result = nil
|
303
|
-
until bases.empty?
|
304
|
-
built = bases.join('::')
|
305
|
-
result = get_constants(built, '').select{|pin| pin.name == cursor and visibility.include?(pin.visibility)}.first
|
306
|
-
break unless result.nil?
|
307
|
-
bases.pop
|
308
|
-
visibility -= [:private]
|
309
|
-
end
|
310
|
-
return nil if result.nil?
|
311
|
-
end
|
312
|
-
result = get_constants(fqns, '').select{|pin| pin.name == cursor and visibility.include?(pin.visibility)}.first
|
313
|
-
visibility -= [:private]
|
314
|
-
until chain.empty? or result.nil?
|
315
|
-
fqns = result.path
|
316
|
-
cursor = chain.shift
|
317
|
-
result = get_constants(fqns, '').select{|pin| pin.name == cursor and visibility.include?(pin.visibility)}.first
|
318
|
-
end
|
319
|
-
result
|
320
|
-
end
|
321
|
-
|
322
|
-
# This method checks the signature from the namespace's internal context,
|
323
|
-
# i.e., the first word in the signature can be a private or protected
|
324
|
-
# method, a private constant, an instance variable, or a class variable.
|
325
|
-
# Local variables are not accessible.
|
326
|
-
#
|
327
|
-
# @return [String]
|
328
|
-
def infer_type signature, namespace = '', scope: :instance
|
329
|
-
context = combine_type(namespace, scope)
|
330
|
-
parts = signature.split('.')
|
331
|
-
base = parts.shift
|
332
|
-
return nil if base.nil?
|
333
|
-
type = infer_word_type(base, context, true)
|
334
|
-
return nil if type.nil?
|
335
|
-
until parts.empty?
|
336
|
-
word = parts.shift
|
337
|
-
type = infer_method_type(word, type)
|
338
|
-
return nil if type.nil?
|
339
|
-
end
|
340
|
-
type
|
341
|
-
end
|
342
|
-
|
343
|
-
# @return [Solargraph::Pin::Base]
|
344
|
-
def tail_pins signature, fqns, scope, visibility
|
345
|
-
return [] if signature.nil?
|
346
|
-
type = combine_type(fqns, scope)
|
347
|
-
return infer_word_pins(signature, type, true) unless signature.include?('.')
|
348
|
-
parts = signature.split('.')
|
349
|
-
last = parts.pop
|
350
|
-
base = parts.join('.')
|
351
|
-
type = infer_type(base, fqns, scope: scope)
|
352
|
-
return [] if type.nil?
|
353
|
-
infer_word_pins(last, type, true)
|
354
|
-
end
|
355
|
-
|
356
|
-
# @return [Solargraph::Pin::Base]
|
357
|
-
def tail_pin signature, fqns, scope, visibility
|
358
|
-
tail_pins(signature, fqns, scope, visibility).first
|
359
|
-
end
|
360
|
-
|
361
|
-
# Get an array of pins for a word in the provided context. A word can be
|
362
|
-
# a constant, a global variable, or a method name. Private and protected
|
363
|
-
# words are excluded by default. Set the `internal` parameter to `true` to
|
364
|
-
# to include private and protected methods, private constants, instance
|
365
|
-
# variables, and class variables.
|
366
|
-
#
|
367
|
-
# @param word [String]
|
368
|
-
# @param base_type [String]
|
369
|
-
# @param internal [Boolean]
|
370
|
-
# @return [Array<Solargraph::Pin::Base>]
|
371
|
-
def infer_word_pins word, base_type, internal = false
|
372
|
-
pins = []
|
373
|
-
namespace, scope = extract_namespace_and_scope(base_type)
|
374
|
-
if word == 'self' and internal
|
375
|
-
context = (internal ? namespace.split('::')[0..-2].join(';;') : '')
|
376
|
-
fqns = find_fully_qualified_namespace(namespace, context)
|
377
|
-
pins.concat get_path_suggestions(fqns) unless fqns.nil?
|
378
|
-
return pins
|
379
|
-
end
|
380
|
-
fqns = find_fully_qualified_namespace(word, namespace)
|
381
|
-
unless fqns.nil?
|
382
|
-
pins.concat get_path_suggestions(fqns) unless fqns.nil?
|
383
|
-
return pins
|
384
|
-
end
|
385
|
-
if internal
|
386
|
-
if word.start_with?('@@')
|
387
|
-
pins.concat get_class_variable_pins(namespace).select{|pin| pin.name == word}
|
388
|
-
return pins
|
389
|
-
elsif word.start_with?('@')
|
390
|
-
pins.concat get_instance_variable_pins(namespace, scope).select{|pin| pin.name == word}
|
391
|
-
return pins
|
392
|
-
end
|
393
|
-
end
|
394
|
-
if word.start_with?('$')
|
395
|
-
pins.concat get_global_variable_pins.select{|pin| pin.name == word}
|
396
|
-
return pins
|
397
|
-
end
|
398
|
-
pins.concat get_constants(namespace, (internal ? namespace : '')).select{|pin| pin.name == word}
|
399
|
-
if pins.empty?
|
400
|
-
pins.concat get_type_methods(base_type, (internal ? base_type : '')).select{|pin| pin.name == word}
|
401
|
-
pins.concat get_type_methods('Kernel').select{|pin| pin.name == word}
|
402
|
-
end
|
403
|
-
pins
|
404
|
-
end
|
405
|
-
|
406
|
-
# @return [Solargraph::Pin::Base]
|
407
|
-
def infer_word_pin word, base_type, internal = false
|
408
|
-
infer_word_pins(word, base_type, internal).first
|
409
|
-
end
|
410
|
-
|
411
|
-
# @return [String]
|
412
|
-
def infer_word_type word, base_type, internal = false
|
413
|
-
return base_type if word == 'self' and internal
|
414
|
-
if word == 'new'
|
415
|
-
namespace, scope = extract_namespace_and_scope(base_type)
|
416
|
-
return namespace if scope == :class
|
417
|
-
end
|
418
|
-
pin = infer_word_pin(word, base_type, internal)
|
419
|
-
return nil if pin.nil?
|
420
|
-
pin.resolve self
|
421
|
-
pin.return_type
|
422
|
-
end
|
423
|
-
|
424
|
-
# Get an array of pins for a method name in the provided context. Private
|
425
|
-
# and protected methods are excluded by default. Set the `internal`
|
426
|
-
# parameter to `true` to include all methods.
|
427
|
-
#
|
428
|
-
# @param method_name [String] The name of the method
|
429
|
-
# @param base_type [String] The context type (e.g., `String` or `Class<String>`)
|
430
|
-
# @param internal [Boolean] True if the call came from inside the base type
|
431
|
-
# @return [Array<Solargraph::Pin::Base>]
|
432
|
-
def infer_method_pins method_name, base_type, internal = false
|
433
|
-
get_type_methods(base_type, (internal ? base_type : '')).select{|pin| pin.name == method_name}
|
434
|
-
end
|
435
|
-
|
436
|
-
# Get the first pin that matches a method name in the provided context.
|
437
|
-
# Private and protected methods are excluded by default. Set the `internal`
|
438
|
-
# parameter to `true` to include all methods.
|
439
|
-
#
|
440
|
-
# @param method_name [String] The name of the method
|
441
|
-
# @param base_type [String] The context type (e.g., `String` or `Class<String>`)
|
442
|
-
# @param internal [Boolean] True if the call came from inside the base type
|
443
|
-
# @return [Solargraph::Pin::Base]
|
444
|
-
def infer_method_pin method_name, base_type, internal = false
|
445
|
-
infer_method_pins(method_name, base_type, internal).first
|
446
|
-
end
|
447
|
-
|
448
|
-
# Infer the type returned by a method in the provided context. Private and
|
449
|
-
# protected methods are excluded by default. Set the `internal` parameter
|
450
|
-
# to `true` to include all methods.
|
451
|
-
#
|
452
|
-
# @param method_name [String] The name of the method
|
453
|
-
# @param base_type [String] The context type (e.g., `String` or `Class<String>`)
|
454
|
-
# @param internal [Boolean] True if the call came from inside the base type
|
455
|
-
# @return [String]
|
456
|
-
def infer_method_type method_name, base_type, internal = false
|
457
|
-
namespace, scope = extract_namespace_and_scope(base_type)
|
458
|
-
method = infer_method_pin(method_name, base_type, internal)
|
459
|
-
return nil if method.nil?
|
460
|
-
method.resolve self
|
461
|
-
return namespace if method.name == 'new' and scope == :class
|
462
|
-
return base_type if method.return_type == 'self'
|
463
|
-
method.return_type
|
464
|
-
end
|
465
|
-
|
466
|
-
def infer_deep_signature_type chain, base_type
|
467
|
-
return nil if base_type.nil?
|
468
|
-
internal = true
|
469
|
-
until chain.empty?
|
470
|
-
base = chain.shift
|
471
|
-
base_type = infer_method_type(base, base_type, internal)
|
472
|
-
return nil if base_type.nil?
|
473
|
-
internal = false
|
474
|
-
end
|
475
|
-
base_type
|
228
|
+
store.get_symbols
|
476
229
|
end
|
477
230
|
|
478
231
|
# @return [Array<Solargraph::Pin::GlobalVariable>]
|
@@ -484,17 +237,6 @@ module Solargraph
|
|
484
237
|
globals
|
485
238
|
end
|
486
239
|
|
487
|
-
def get_type_methods type, context = ''
|
488
|
-
return [] if type.nil?
|
489
|
-
namespace, scope = extract_namespace_and_scope(type)
|
490
|
-
base = extract_namespace(context)
|
491
|
-
fqns = find_fully_qualified_namespace(namespace, base)
|
492
|
-
return [] if fqns.nil?
|
493
|
-
visibility = [:public]
|
494
|
-
visibility.push :private, :protected if fqns == base
|
495
|
-
get_methods fqns, scope: scope, visibility: visibility
|
496
|
-
end
|
497
|
-
|
498
240
|
def get_methods fqns, scope: :instance, visibility: [:public], deep: true
|
499
241
|
result = []
|
500
242
|
skip = []
|
@@ -511,9 +253,9 @@ module Solargraph
|
|
511
253
|
# @param fragment [Solargraph::Source::Fragment]
|
512
254
|
# @return [ApiMap::Completion]
|
513
255
|
def complete fragment
|
514
|
-
return Completion.new([], fragment.whole_word_range) if fragment.string? or fragment.comment?
|
256
|
+
return Completion.new([], fragment.whole_word_range) if fragment.string? or fragment.comment?
|
515
257
|
result = []
|
516
|
-
if !fragment.signature.include?('.')
|
258
|
+
if !fragment.signature.include?('.') and !fragment.base_literal?
|
517
259
|
if fragment.signature.start_with?('@@')
|
518
260
|
result.concat get_class_variable_pins(fragment.namespace)
|
519
261
|
elsif fragment.signature.start_with?('@')
|
@@ -524,34 +266,38 @@ module Solargraph
|
|
524
266
|
result.concat get_symbols
|
525
267
|
else
|
526
268
|
unless fragment.signature.include?('::')
|
527
|
-
result.concat prefer_non_nil_variables(fragment.
|
528
|
-
result.concat
|
529
|
-
result.concat
|
269
|
+
result.concat prefer_non_nil_variables(fragment.locals)
|
270
|
+
result.concat get_methods(fragment.namespace, scope: fragment.scope, visibility: [:public, :private, :protected])
|
271
|
+
result.concat get_methods('Kernel')
|
530
272
|
result.concat ApiMap.keywords
|
531
273
|
end
|
532
274
|
result.concat get_constants(fragment.base, fragment.namespace)
|
533
275
|
end
|
534
276
|
else
|
535
|
-
if fragment.
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
277
|
+
if fragment.base_literal?
|
278
|
+
pin = get_path_suggestions(fragment.base_literal).select{|pin| pin.kind == Pin::NAMESPACE}.first
|
279
|
+
unless pin.nil?
|
280
|
+
if fragment.base.empty?
|
281
|
+
result.concat get_methods(pin.path)
|
282
|
+
else
|
283
|
+
type = probe.infer_signature_type(fragment.base, pin, fragment.locals)
|
284
|
+
unless type.nil?
|
285
|
+
namespace, scope = extract_namespace_and_scope(type)
|
286
|
+
result.concat get_methods(namespace, scope: scope)
|
287
|
+
end
|
288
|
+
end
|
542
289
|
end
|
543
|
-
|
544
|
-
|
290
|
+
elsif fragment.signature.include?('::') and !fragment.signature.include?('.')
|
291
|
+
result.concat get_constants(fragment.base, fragment.namespace)
|
292
|
+
else
|
293
|
+
type = probe.infer_signature_type(fragment.base, fragment.named_path, fragment.locals)
|
545
294
|
unless type.nil?
|
546
|
-
|
547
|
-
|
548
|
-
next if type.nil?
|
549
|
-
end
|
550
|
-
result.concat get_type_methods(type) unless type.nil?
|
295
|
+
namespace, scope = extract_namespace_and_scope(type)
|
296
|
+
result.concat get_methods(namespace, scope: scope)
|
551
297
|
end
|
552
298
|
end
|
553
299
|
end
|
554
|
-
filtered = result.uniq(&:identifier).select{|s| s.kind !=
|
300
|
+
filtered = result.uniq(&:identifier).select{|s| s.kind != Pin::METHOD or s.name.match(/^[a-z0-9_]*(\!|\?|=)?$/i)}.sort_by.with_index{ |x, idx| [x.name, idx] }
|
555
301
|
Completion.new(filtered, fragment.whole_word_range)
|
556
302
|
end
|
557
303
|
|
@@ -559,74 +305,25 @@ module Solargraph
|
|
559
305
|
# @return [Array<Solargraph::Pin::Base>]
|
560
306
|
def define fragment
|
561
307
|
return [] if fragment.string? or fragment.comment?
|
562
|
-
|
563
|
-
end
|
564
|
-
|
565
|
-
def infer_fragment_type fragment
|
566
|
-
parts = fragment.whole_signature.split('.')
|
567
|
-
base = parts.shift
|
568
|
-
type = nil
|
569
|
-
lvar = prefer_non_nil_variables(fragment.local_variable_pins(base)).first
|
570
|
-
unless lvar.nil?
|
571
|
-
lvar.resolve self
|
572
|
-
type = lvar.return_type
|
573
|
-
return nil if type.nil?
|
574
|
-
end
|
575
|
-
type = infer_word_type(base, fragment.namespace, fragment.scope) if type.nil?
|
576
|
-
return nil if type.nil?
|
577
|
-
until parts.empty?
|
578
|
-
meth = parts.shift
|
579
|
-
type = infer_word_type(meth, type)
|
580
|
-
return nil if type.nil?
|
581
|
-
end
|
582
|
-
type
|
308
|
+
probe.infer_signature_pins fragment.whole_signature, fragment.named_path, fragment.locals
|
583
309
|
end
|
584
310
|
|
311
|
+
# Infer a return type from a fragment. This method will attempt to resolve
|
312
|
+
# signatures.
|
313
|
+
#
|
585
314
|
# @param fragment [Solargraph::Source::Fragment]
|
315
|
+
# @return [String]
|
316
|
+
def infer_type fragment
|
317
|
+
return nil if fragment.string? or fragment.comment?
|
318
|
+
probe.infer_signature_type fragment.whole_signature, fragment.named_path, fragment.locals
|
319
|
+
end
|
320
|
+
|
321
|
+
# @param fragment [Solargraph::Source::Fragment]
|
322
|
+
# @return [Array<Solargraph::Pin::Base>]
|
586
323
|
def signify fragment
|
587
324
|
return [] unless fragment.argument?
|
588
325
|
return [] if fragment.recipient.whole_signature.nil? or fragment.recipient.whole_signature.empty?
|
589
|
-
|
590
|
-
return infer_word_pins(base, fragment.recipient.namespace, true) if rest.nil?
|
591
|
-
type = nil
|
592
|
-
lvar = prefer_non_nil_variables(fragment.local_variable_pins(base)).first
|
593
|
-
unless lvar.nil?
|
594
|
-
lvar.resolve self
|
595
|
-
type = lvar.return_type
|
596
|
-
return [] if type.nil?
|
597
|
-
end
|
598
|
-
type = infer_word_type(base, fragment.namespace, fragment.scope) if type.nil?
|
599
|
-
return [] if type.nil?
|
600
|
-
ns, sc = extract_namespace_and_scope(type)
|
601
|
-
tail_pins(rest, ns, sc, [:public, :private, :protected])
|
602
|
-
end
|
603
|
-
|
604
|
-
# Get the namespace's type (Class or Module).
|
605
|
-
#
|
606
|
-
# @param [String] A fully qualified namespace
|
607
|
-
# @return [Symbol] :class, :module, or nil
|
608
|
-
def get_namespace_type fqns
|
609
|
-
pin = @namespace_path_pins[fqns]
|
610
|
-
return yard_map.get_namespace_type(fqns) if pin.nil?
|
611
|
-
pin.first.type
|
612
|
-
end
|
613
|
-
|
614
|
-
# Convert a namespace and scope into a type.
|
615
|
-
#
|
616
|
-
# @example
|
617
|
-
# combine_type('String', :instance) => 'String'
|
618
|
-
# combine_type('String', :class) => 'Class<String>'
|
619
|
-
#
|
620
|
-
# @param namespace [String]
|
621
|
-
# @param scope [Symbol] :class or :instance
|
622
|
-
def combine_type namespace, scope
|
623
|
-
return '' if namespace.empty?
|
624
|
-
if scope == :instance
|
625
|
-
namespace
|
626
|
-
else
|
627
|
-
type = get_namespace_type(namespace)
|
628
|
-
"#{type == :class ? 'Class' : 'Module'}<#{namespace}>"
|
629
|
-
end
|
326
|
+
probe.infer_signature_pins fragment.recipient.whole_signature, fragment.named_path, fragment.locals
|
630
327
|
end
|
631
328
|
|
632
329
|
# Get an array of all suggestions that match the specified path.
|
@@ -635,28 +332,10 @@ module Solargraph
|
|
635
332
|
# @return [Array<Solargraph::Pin::Base>]
|
636
333
|
def get_path_suggestions path
|
637
334
|
return [] if path.nil?
|
638
|
-
# refresh
|
639
335
|
result = []
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
result = get_methods(parts[0], visibility: [:public, :private, :protected]).select{|s| s.name == parts[1]}
|
644
|
-
elsif path.include?('.')
|
645
|
-
# It's a class method
|
646
|
-
parts = path.split('.')
|
647
|
-
result = get_methods(parts[0], scope: :class, visibility: [:public, :private, :protected]).select{|s| s.name == parts[1]}
|
648
|
-
else
|
649
|
-
# It's a class or module
|
650
|
-
parts = path.split('::')
|
651
|
-
np = @namespace_pins[parts[0..-2].join('::')]
|
652
|
-
unless np.nil?
|
653
|
-
result.concat np.select{|p| p.name == parts.last}
|
654
|
-
end
|
655
|
-
result.concat yard_map.objects(path)
|
656
|
-
end
|
657
|
-
# @todo Resolve the pins?
|
658
|
-
result.map{|pin| pin.resolve(self); pin}
|
659
|
-
# result
|
336
|
+
result.concat store.get_path_pins(path)
|
337
|
+
result.concat yard_map.objects(path)
|
338
|
+
result
|
660
339
|
end
|
661
340
|
|
662
341
|
# Get a list of documented paths that match the query.
|
@@ -702,145 +381,33 @@ module Solargraph
|
|
702
381
|
result
|
703
382
|
end
|
704
383
|
|
705
|
-
def superclass_of fqns
|
706
|
-
found = @superclasses[fqns]
|
707
|
-
return nil if found.nil?
|
708
|
-
found.resolve self
|
709
|
-
found.name
|
710
|
-
end
|
711
|
-
|
712
384
|
def locate_pin location
|
713
385
|
@sources.each do |source|
|
714
386
|
pin = source.locate_pin(location)
|
715
387
|
unless pin.nil?
|
716
|
-
pin.resolve self
|
388
|
+
# pin.resolve self
|
717
389
|
return pin
|
718
390
|
end
|
719
391
|
end
|
720
392
|
nil
|
721
393
|
end
|
722
394
|
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
def namespace_map
|
727
|
-
@namespace_map ||= {}
|
395
|
+
# @return [Probe]
|
396
|
+
def probe
|
397
|
+
@probe ||= Probe.new(self)
|
728
398
|
end
|
729
399
|
|
730
|
-
|
731
|
-
@sources = workspace.sources
|
732
|
-
@sources.push @virtual_source unless @virtual_source.nil?
|
733
|
-
cache.clear
|
734
|
-
@ivar_pins = {}
|
735
|
-
@cvar_pins = {}
|
736
|
-
@const_pins = {}
|
737
|
-
@method_pins = {}
|
738
|
-
@symbol_pins = []
|
739
|
-
@attr_pins = {}
|
740
|
-
@namespace_includes = {}
|
741
|
-
@namespace_extends = {}
|
742
|
-
@superclasses = {}
|
743
|
-
@namespace_pins = {}
|
744
|
-
@namespace_path_pins = {}
|
745
|
-
namespace_map.clear
|
746
|
-
@required = workspace.config.required.clone
|
747
|
-
@sources.each do |s|
|
748
|
-
s.namespaces.each do |n|
|
749
|
-
namespace_map[n] ||= []
|
750
|
-
namespace_map[n].concat s.namespace_pins(n)
|
751
|
-
end
|
752
|
-
end
|
753
|
-
@sources.each do |s|
|
754
|
-
map_source s
|
755
|
-
end
|
756
|
-
@required.uniq!
|
757
|
-
live_map.refresh
|
758
|
-
@yard_stale = true
|
759
|
-
@stime = Time.now
|
760
|
-
end
|
761
|
-
|
762
|
-
def rebuild_local_yardoc
|
763
|
-
return if workspace.nil? or !File.exist?(File.join(workspace, '.yardoc'))
|
764
|
-
STDERR.puts "Rebuilding local yardoc for #{workspace}"
|
765
|
-
Dir.chdir(workspace) { Process.spawn('yardoc') }
|
766
|
-
end
|
400
|
+
private
|
767
401
|
|
768
402
|
def process_virtual
|
769
403
|
unless @virtual_source.nil?
|
770
|
-
cache.clear
|
771
|
-
namespace_map.clear
|
772
|
-
@sources.each do |s|
|
773
|
-
s.namespace_pins.each do |pin|
|
774
|
-
namespace_map[pin.path] ||= []
|
775
|
-
namespace_map[pin.path].push pin
|
776
|
-
end
|
777
|
-
end
|
778
404
|
map_source @virtual_source
|
779
405
|
end
|
780
406
|
end
|
781
407
|
|
782
|
-
def eliminate source
|
783
|
-
[@ivar_pins.values, @cvar_pins.values, @const_pins.values, @method_pins.values, @attr_pins.values, @namespace_pins.values].each do |pinsets|
|
784
|
-
pinsets.each do |pins|
|
785
|
-
pins.delete_if{|pin| pin.filename == source.filename}
|
786
|
-
end
|
787
|
-
end
|
788
|
-
[@namespace_includes.values, @namespace_extends.values].each do |refsets|
|
789
|
-
refsets.each do |refs|
|
790
|
-
refs.delete_if{|ref| ref.pin.filename == source.filename}
|
791
|
-
end
|
792
|
-
end
|
793
|
-
@superclasses.delete_if{|key, ref| ref.pin.filename == source.filename}
|
794
|
-
@symbol_pins.delete_if{|pin| pin.filename == source.filename}
|
795
|
-
end
|
796
|
-
|
797
408
|
# @param [Solargraph::Source]
|
798
409
|
def map_source source
|
799
|
-
|
800
|
-
@method_pins[pin.namespace] ||= []
|
801
|
-
@method_pins[pin.namespace].push pin
|
802
|
-
end
|
803
|
-
source.attribute_pins.each do |pin|
|
804
|
-
@attr_pins[pin.namespace] ||= []
|
805
|
-
@attr_pins[pin.namespace].push pin
|
806
|
-
end
|
807
|
-
source.instance_variable_pins.each do |pin|
|
808
|
-
@ivar_pins[pin.namespace] ||= []
|
809
|
-
@ivar_pins[pin.namespace].push pin
|
810
|
-
end
|
811
|
-
source.class_variable_pins.each do |pin|
|
812
|
-
@cvar_pins[pin.namespace] ||= []
|
813
|
-
@cvar_pins[pin.namespace].push pin
|
814
|
-
end
|
815
|
-
source.constant_pins.each do |pin|
|
816
|
-
@const_pins[pin.namespace] ||= []
|
817
|
-
@const_pins[pin.namespace].push pin
|
818
|
-
end
|
819
|
-
source.symbol_pins.each do |pin|
|
820
|
-
@symbol_pins.push pin
|
821
|
-
end
|
822
|
-
source.namespace_pins.each do |pin|
|
823
|
-
@namespace_path_pins[pin.path] ||= []
|
824
|
-
@namespace_path_pins[pin.path].push pin
|
825
|
-
@namespace_pins[pin.namespace] ||= []
|
826
|
-
@namespace_pins[pin.namespace].push pin
|
827
|
-
# @todo Determine whether references should be resolve here or
|
828
|
-
# dynamically during queries
|
829
|
-
unless pin.superclass_reference.nil?
|
830
|
-
@superclasses[pin.path] = pin.superclass_reference
|
831
|
-
# pin.superclass_reference.resolve self
|
832
|
-
end
|
833
|
-
pin.include_references.each do |ref|
|
834
|
-
@namespace_includes[pin.path] ||= []
|
835
|
-
@namespace_includes[pin.path].push ref
|
836
|
-
# ref.resolve self
|
837
|
-
end
|
838
|
-
pin.extend_references.each do |ref|
|
839
|
-
@namespace_extends[pin.path] ||= []
|
840
|
-
@namespace_extends[pin.path].push ref
|
841
|
-
# ref.resolve self
|
842
|
-
end
|
843
|
-
end
|
410
|
+
store.update source
|
844
411
|
path_macros.merge! source.path_macros
|
845
412
|
source.required.each do |r|
|
846
413
|
required.push r
|
@@ -858,44 +425,28 @@ module Solargraph
|
|
858
425
|
skip.push reqstr
|
859
426
|
result = []
|
860
427
|
if scope == :instance
|
861
|
-
|
862
|
-
result.concat aps unless aps.nil?
|
863
|
-
end
|
864
|
-
mps = @method_pins[fqns]
|
865
|
-
result.concat mps.select{|pin| (pin.scope == scope or fqns == '') and visibility.include?(pin.visibility)} unless mps.nil?
|
866
|
-
if fqns != '' and scope == :class and !result.map(&:path).include?("#{fqns}.new")
|
867
|
-
# Create a [Class].new method pin from [Class]#initialize
|
868
|
-
init = inner_get_methods(fqns, :instance, [:private], deep, skip - [fqns]).select{|pin| pin.name == 'initialize'}.first
|
869
|
-
unless init.nil?
|
870
|
-
result.unshift Solargraph::Pin::Directed::Method.new(init.source, init.node, init.namespace, :class, :public, init.docstring, 'new', init.namespace)
|
871
|
-
end
|
428
|
+
result.concat store.get_attrs(fqns)
|
872
429
|
end
|
430
|
+
result.concat store.get_methods(fqns, scope: scope, visibility: visibility)
|
873
431
|
if deep
|
874
|
-
|
875
|
-
unless
|
432
|
+
sc = store.get_superclass(fqns)
|
433
|
+
unless sc.nil?
|
434
|
+
fqsc = qualify(sc, fqns)
|
876
435
|
sc_visi = [:public]
|
877
436
|
sc_visi.push :protected if visibility.include?(:protected)
|
878
|
-
|
879
|
-
scref.resolve self
|
880
|
-
result.concat inner_get_methods(scref.name, scope, sc_visi, true, skip) unless scref.name.nil?
|
437
|
+
result.concat inner_get_methods(fqsc, scope, sc_visi, true, skip) unless fqsc.nil?
|
881
438
|
end
|
882
439
|
if scope == :instance
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
i.resolve self
|
887
|
-
result.concat inner_get_methods(i.name, scope, visibility, deep, skip) unless i.name.nil?
|
888
|
-
end
|
440
|
+
store.get_includes(fqns).each do |im|
|
441
|
+
fqim = qualify(im, fqns)
|
442
|
+
result.concat inner_get_methods(fqim, scope, visibility, deep, skip) unless fqim.nil?
|
889
443
|
end
|
890
444
|
result.concat yard_map.get_instance_methods(fqns, visibility: visibility)
|
891
445
|
result.concat inner_get_methods('Object', :instance, [:public], deep, skip) unless fqns == 'Object'
|
892
446
|
else
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
e.resolve self
|
897
|
-
result.concat inner_get_methods(e.name, :instance, visibility, deep, skip) unless e.name.nil?
|
898
|
-
end
|
447
|
+
store.get_extends(fqns).each do |em|
|
448
|
+
fqem = qualify(em, fqns)
|
449
|
+
result.concat inner_get_methods(fqem, :instance, visibility, deep, skip) unless fqem.nil?
|
899
450
|
end
|
900
451
|
result.concat yard_map.get_methods(fqns, '', visibility: visibility)
|
901
452
|
type = get_namespace_type(fqns)
|
@@ -913,49 +464,15 @@ module Solargraph
|
|
913
464
|
return [] if skip.include?(fqns)
|
914
465
|
skip.push fqns
|
915
466
|
result = []
|
916
|
-
result.concat
|
917
|
-
result.concat @namespace_pins[fqns] if @namespace_pins.has_key?(fqns)
|
918
|
-
result.keep_if{|pin| !pin.name.empty? and visibility.include?(pin.visibility)}
|
467
|
+
result.concat store.get_constants(fqns, visibility)
|
919
468
|
result.concat yard_map.get_constants(fqns)
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
i.resolve self
|
924
|
-
result.concat inner_get_constants(i.name, [:public], skip) unless i.name.nil?
|
925
|
-
end
|
469
|
+
store.get_includes(fqns).each do |is|
|
470
|
+
fqis = qualify(is, fqns)
|
471
|
+
result.concat inner_get_constants(fqis, [:public], skip) unless fqis.nil?
|
926
472
|
end
|
927
473
|
result
|
928
474
|
end
|
929
475
|
|
930
|
-
# Extract a namespace from a type.
|
931
|
-
#
|
932
|
-
# @example
|
933
|
-
# extract_namespace('String') => 'String'
|
934
|
-
# extract_namespace('Class<String>') => 'String'
|
935
|
-
#
|
936
|
-
# @return [String]
|
937
|
-
def extract_namespace type
|
938
|
-
extract_namespace_and_scope(type)[0]
|
939
|
-
end
|
940
|
-
|
941
|
-
# Extract a namespace and a scope (:instance or :class) from a type.
|
942
|
-
#
|
943
|
-
# @example
|
944
|
-
# extract_namespace('String') #=> ['String', :instance]
|
945
|
-
# extract_namespace('Class<String>') #=> ['String', :class]
|
946
|
-
# extract_namespace('Module<Enumerable') #=> ['Enumberable', :class]
|
947
|
-
#
|
948
|
-
# @return [Array] The namespace (String) and scope (Symbol).
|
949
|
-
def extract_namespace_and_scope type
|
950
|
-
scope = :instance
|
951
|
-
result = type.to_s.gsub(/<.*$/, '')
|
952
|
-
if (result == 'Class' or result == 'Module') and type.include?('<')
|
953
|
-
result = type.match(/<([a-z0-9:_]*)/i)[1]
|
954
|
-
scope = :class
|
955
|
-
end
|
956
|
-
[result, scope]
|
957
|
-
end
|
958
|
-
|
959
476
|
def require_extensions
|
960
477
|
Gem::Specification.all_names.select{|n| n.match(/^solargraph\-[a-z0-9_\-]*?\-ext\-[0-9\.]*$/)}.each do |n|
|
961
478
|
STDERR.puts "Loading extension #{n}"
|
@@ -968,7 +485,7 @@ module Solargraph
|
|
968
485
|
result = []
|
969
486
|
nil_pins = []
|
970
487
|
pins.each do |pin|
|
971
|
-
if pin.
|
488
|
+
if pin.variable? and pin.nil_assignment?
|
972
489
|
nil_pins.push pin
|
973
490
|
else
|
974
491
|
result.push pin
|
@@ -977,14 +494,6 @@ module Solargraph
|
|
977
494
|
result + nil_pins
|
978
495
|
end
|
979
496
|
|
980
|
-
# @todo DRY this method. It's duplicated in CodeMap
|
981
|
-
def get_subtypes type
|
982
|
-
return [] if type.nil?
|
983
|
-
match = type.match(/<([a-z0-9_:, ]*)>/i)
|
984
|
-
return [] if match.nil?
|
985
|
-
match[1].split(',').map(&:strip)
|
986
|
-
end
|
987
|
-
|
988
497
|
# @return [Hash]
|
989
498
|
def path_macros
|
990
499
|
@path_macros ||= {}
|
@@ -993,5 +502,56 @@ module Solargraph
|
|
993
502
|
def current_workspace_sources
|
994
503
|
@sources - [@virtual_source]
|
995
504
|
end
|
505
|
+
|
506
|
+
def inner_qualify name, root, skip
|
507
|
+
return nil if name.nil?
|
508
|
+
return nil if skip.include?(root)
|
509
|
+
skip.push root
|
510
|
+
if name == ''
|
511
|
+
if root == ''
|
512
|
+
return ''
|
513
|
+
else
|
514
|
+
return inner_qualify(root, '', skip)
|
515
|
+
end
|
516
|
+
else
|
517
|
+
if (root == '')
|
518
|
+
return name if store.namespace_exists?(name)
|
519
|
+
# @todo What to do about the @namespace_includes stuff above?
|
520
|
+
else
|
521
|
+
roots = root.to_s.split('::')
|
522
|
+
while roots.length > 0
|
523
|
+
fqns = roots.join('::') + '::' + name
|
524
|
+
return fqns if store.namespace_exists?(fqns)
|
525
|
+
roots.pop
|
526
|
+
end
|
527
|
+
return name if store.namespace_exists?(name)
|
528
|
+
end
|
529
|
+
end
|
530
|
+
result = yard_map.find_fully_qualified_namespace(name, root)
|
531
|
+
if result.nil?
|
532
|
+
result = live_map.get_fqns(name, root)
|
533
|
+
end
|
534
|
+
result
|
535
|
+
end
|
536
|
+
|
537
|
+
# Get the namespace's type (Class or Module).
|
538
|
+
#
|
539
|
+
# @param [String] A fully qualified namespace
|
540
|
+
# @return [Symbol] :class, :module, or nil
|
541
|
+
def get_namespace_type fqns
|
542
|
+
pin = store.get_path_pins(fqns).first
|
543
|
+
return yard_map.get_namespace_type(fqns) if pin.nil?
|
544
|
+
pin.type
|
545
|
+
end
|
546
|
+
|
547
|
+
def extract_namespace_and_scope type
|
548
|
+
scope = :instance
|
549
|
+
result = type.to_s.gsub(/<.*$/, '')
|
550
|
+
if (result == 'Class' or result == 'Module') and type.include?('<')
|
551
|
+
result = type.match(/<([a-z0-9:_]*)/i)[1]
|
552
|
+
scope = :class
|
553
|
+
end
|
554
|
+
[result, scope]
|
555
|
+
end
|
996
556
|
end
|
997
557
|
end
|