solargraph 0.4.2 → 0.5.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.rb +4 -0
- data/lib/solargraph/api_map.rb +142 -55
- data/lib/solargraph/code_map.rb +73 -82
- data/lib/solargraph/node_methods.rb +25 -9
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/yard_map.rb +15 -9
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7d08698f9e91d4e08d2826494bb69eeb81fd8675
|
4
|
+
data.tar.gz: 4fb6952fdc4c54106ffdefa2d596ad764cc6d0c9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 336d028676662a1315d4c9686c8c09a052618cf2ac0156a9fcf89e376ffcbec53b32c819ac5c9c77291c20eb88c63ed0fa3f1e19e185e5a1924e34e68651d045
|
7
|
+
data.tar.gz: 73d41b0eee445ad355d675ab4cff779330053130dd6fe1e85f5da21a1cd4a8373d707e60401675c8855002809bad34b1bfb8b04ff134717296120cfe9a166934
|
data/lib/solargraph.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'solargraph/version'
|
2
2
|
require 'rubygems/package'
|
3
|
+
require 'yard'
|
3
4
|
|
4
5
|
module Solargraph
|
5
6
|
autoload :Analyzer, 'solargraph/analyzer'
|
@@ -38,3 +39,6 @@ unless File.exist?(version_dir)
|
|
38
39
|
tar_extract.close
|
39
40
|
#FileUtils.rm File.join(cache_dir, '2.0.0.tar.gz')
|
40
41
|
end
|
42
|
+
|
43
|
+
# Define a @type tag to be used for documenting variables
|
44
|
+
YARD::Tags::Library.define_tag("Type", :type, :with_types_and_name)
|
data/lib/solargraph/api_map.rb
CHANGED
@@ -12,20 +12,25 @@ module Solargraph
|
|
12
12
|
'nil', 'not', 'or', 'redo', 'rescue', 'retry', 'return', 'self', 'super',
|
13
13
|
'then', 'true', 'undef', 'unless', 'until', 'when', 'while', 'yield'
|
14
14
|
]
|
15
|
-
|
15
|
+
|
16
16
|
MAPPABLE_METHODS = [
|
17
|
-
:include, :require, :autoload, :attr_reader, :attr_writer, :attr_accessor, :private, :public, :protected
|
17
|
+
:include, :extend, :require, :autoload, :attr_reader, :attr_writer, :attr_accessor, :private, :public, :protected,
|
18
|
+
:solargraph_include_public_methods
|
18
19
|
]
|
19
20
|
|
20
21
|
include NodeMethods
|
21
|
-
|
22
|
+
|
22
23
|
attr_reader :workspace
|
23
24
|
attr_reader :required
|
24
|
-
|
25
|
+
|
25
26
|
def initialize workspace = nil
|
26
27
|
@workspace = workspace
|
27
28
|
clear
|
28
29
|
unless @workspace.nil?
|
30
|
+
extra = File.join(workspace, '.solargraph')
|
31
|
+
if File.exist?(extra)
|
32
|
+
append_file(extra)
|
33
|
+
end
|
29
34
|
files = []
|
30
35
|
opts = options
|
31
36
|
(opts[:include] - opts[:exclude]).each { |glob|
|
@@ -51,18 +56,29 @@ module Solargraph
|
|
51
56
|
|
52
57
|
def options
|
53
58
|
o = {
|
54
|
-
include: [
|
59
|
+
include: [],
|
55
60
|
exclude: []
|
56
61
|
}
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
+
unless workspace.nil?
|
63
|
+
yardopts_file = File.join(workspace, '.yardopts')
|
64
|
+
if File.exist?(yardopts_file)
|
65
|
+
yardopts = File.read(yardopts_file)
|
66
|
+
yardopts.lines.each { |line|
|
67
|
+
arg = line.strip
|
68
|
+
if !arg.start_with?('-')
|
69
|
+
o[:include].push arg
|
70
|
+
end
|
71
|
+
}
|
72
|
+
end
|
62
73
|
end
|
74
|
+
o[:include].concat ['app/**/*.rb', 'lib/**/*.rb'] if o[:include].empty?
|
63
75
|
o
|
64
76
|
end
|
65
77
|
|
78
|
+
def yard_map
|
79
|
+
@yard_map ||= YardMap.new(required: required, workspace: workspace)
|
80
|
+
end
|
81
|
+
|
66
82
|
def append_file filename
|
67
83
|
append_source File.read(filename), filename
|
68
84
|
end
|
@@ -80,6 +96,7 @@ module Solargraph
|
|
80
96
|
@file_nodes[filename] = root
|
81
97
|
@required.uniq!
|
82
98
|
process_maps
|
99
|
+
root
|
83
100
|
end
|
84
101
|
|
85
102
|
def associate_comments node, comments
|
@@ -88,7 +105,7 @@ module Solargraph
|
|
88
105
|
comment_hash.each_pair { |k, v|
|
89
106
|
ctxt = ''
|
90
107
|
v.each { |l|
|
91
|
-
ctxt += l.text.gsub(
|
108
|
+
ctxt += l.text.gsub(/^# /, '') + "\n"
|
92
109
|
}
|
93
110
|
parser = YARD::DocstringParser.new
|
94
111
|
yard_hash[k] = parser.parse(ctxt).to_docstring
|
@@ -133,13 +150,12 @@ module Solargraph
|
|
133
150
|
def namespaces_in name, root = ''
|
134
151
|
result = []
|
135
152
|
result += inner_namespaces_in(name, root, [])
|
136
|
-
|
137
|
-
result += yard.get_constants name, root
|
153
|
+
result += yard_map.get_constants name, root
|
138
154
|
fqns = find_fully_qualified_namespace(name, root)
|
139
155
|
unless fqns.nil?
|
140
156
|
nodes = get_namespace_nodes(fqns)
|
141
157
|
get_include_strings_from(*nodes).each { |i|
|
142
|
-
result +=
|
158
|
+
result += yard_map.get_constants(i, root)
|
143
159
|
}
|
144
160
|
end
|
145
161
|
result
|
@@ -198,7 +214,7 @@ module Solargraph
|
|
198
214
|
return name unless @namespace_map[name].nil?
|
199
215
|
get_include_strings_from(*@file_nodes.values).each { |i|
|
200
216
|
reroot = "#{root == '' ? '' : root + '::'}#{i}"
|
201
|
-
recname = find_fully_qualified_namespace name, reroot, skip
|
217
|
+
recname = find_fully_qualified_namespace name.to_s, reroot, skip
|
202
218
|
return recname unless recname.nil?
|
203
219
|
}
|
204
220
|
else
|
@@ -215,11 +231,11 @@ module Solargraph
|
|
215
231
|
}
|
216
232
|
end
|
217
233
|
end
|
218
|
-
|
234
|
+
yard_map.find_fully_qualified_namespace(name, root)
|
219
235
|
end
|
220
236
|
|
221
237
|
def get_namespace_nodes(fqns)
|
222
|
-
return @file_nodes.values if fqns == ''
|
238
|
+
return @file_nodes.values if fqns == '' or fqns.nil?
|
223
239
|
@namespace_map[fqns] || []
|
224
240
|
end
|
225
241
|
|
@@ -259,7 +275,7 @@ module Solargraph
|
|
259
275
|
if c.kind_of?(AST::Node)
|
260
276
|
is_inst = !find_parent(c, :def).nil?
|
261
277
|
if c.type == :ivasgn and c.children[0] and ( (scope == :instance and is_inst) or (scope != :instance and !is_inst) )
|
262
|
-
arr.push Suggestion.new(c.children[0], kind: Suggestion::VARIABLE)
|
278
|
+
arr.push Suggestion.new(c.children[0], kind: Suggestion::VARIABLE, documentation: get_comment_for(c))
|
263
279
|
end
|
264
280
|
arr += inner_get_instance_variables(c, scope) unless [:class, :module].include?(c.type)
|
265
281
|
end
|
@@ -269,14 +285,28 @@ module Solargraph
|
|
269
285
|
end
|
270
286
|
|
271
287
|
def infer_instance_variable(var, namespace, scope = :instance)
|
288
|
+
result = nil
|
272
289
|
vn = nil
|
273
|
-
|
274
|
-
|
290
|
+
fqns = find_fully_qualified_namespace(namespace)
|
291
|
+
unless fqns.nil?
|
292
|
+
get_namespace_nodes(fqns).each { |node|
|
275
293
|
vn = find_instance_variable_assignment(var, node, scope)
|
276
294
|
break unless vn.nil?
|
277
295
|
}
|
278
296
|
end
|
279
|
-
|
297
|
+
unless vn.nil?
|
298
|
+
cmnt = get_comment_for(vn)
|
299
|
+
unless cmnt.nil?
|
300
|
+
tag = cmnt.tag(:type)
|
301
|
+
result = tag.types[0] unless tag.nil? or tag.types.empty?
|
302
|
+
end
|
303
|
+
result = infer(vn.children[1]) if result.nil?
|
304
|
+
if result.nil?
|
305
|
+
signature = resolve_node_signature(vn.children[1])
|
306
|
+
result = infer_signature_type(signature, namespace || '', scope: scope)
|
307
|
+
end
|
308
|
+
end
|
309
|
+
result
|
280
310
|
end
|
281
311
|
|
282
312
|
def find_instance_variable_assignment(var, node, scope)
|
@@ -295,12 +325,56 @@ module Solargraph
|
|
295
325
|
}
|
296
326
|
nil
|
297
327
|
end
|
298
|
-
|
328
|
+
|
299
329
|
def get_global_variables
|
300
330
|
# TODO: Get them
|
301
331
|
[]
|
302
332
|
end
|
303
|
-
|
333
|
+
|
334
|
+
# Get a fully qualified namespace for the given signature.
|
335
|
+
# The signature should be in the form of a method chain, e.g.,
|
336
|
+
# method1.method2
|
337
|
+
#
|
338
|
+
# @return [String] The fully qualified namespace for the signature's type
|
339
|
+
# or nil if a type could not be determined
|
340
|
+
def infer_signature_type signature, namespace, scope: :instance
|
341
|
+
parts = signature.split('.')
|
342
|
+
type = find_fully_qualified_namespace(namespace)
|
343
|
+
type ||= ''
|
344
|
+
top = true
|
345
|
+
while parts.length > 0 and !type.nil?
|
346
|
+
p = parts.shift
|
347
|
+
unless p == 'new' and scope != :instance
|
348
|
+
if scope == :instance
|
349
|
+
meths = get_instance_methods(type)
|
350
|
+
meths += get_methods('') if top
|
351
|
+
else
|
352
|
+
meths = get_methods(type)
|
353
|
+
#meths += get_methods('') if top
|
354
|
+
end
|
355
|
+
meths.delete_if{ |m| m.insert != p }
|
356
|
+
return nil if meths.empty?
|
357
|
+
type = nil
|
358
|
+
unless meths[0].documentation.nil?
|
359
|
+
match = meths[0].documentation.all.match(/@return \[([a-z0-9:_]*)/i)
|
360
|
+
type = find_fully_qualified_namespace(match[1]) unless match.nil?
|
361
|
+
end
|
362
|
+
end
|
363
|
+
scope = :instance
|
364
|
+
top = false
|
365
|
+
end
|
366
|
+
type
|
367
|
+
end
|
368
|
+
|
369
|
+
def get_method_return_value namespace, root, method, scope = :instance
|
370
|
+
meths = get_methods(namespace, root).delete_if{ |m| m.insert != method }
|
371
|
+
meths.each { |m|
|
372
|
+
r = get_return_tag(m)
|
373
|
+
return r unless r.nil?
|
374
|
+
}
|
375
|
+
nil
|
376
|
+
end
|
377
|
+
|
304
378
|
def get_namespace_type namespace, root = ''
|
305
379
|
type = nil
|
306
380
|
fqns = find_fully_qualified_namespace(namespace, root)
|
@@ -314,16 +388,15 @@ module Solargraph
|
|
314
388
|
def get_methods(namespace, root = '', visibility: [:public])
|
315
389
|
meths = []
|
316
390
|
meths += inner_get_methods(namespace, root, []) #unless has_yardoc?
|
317
|
-
|
318
|
-
yard_meths = yard.get_methods(namespace, root, visibility: visibility)
|
391
|
+
yard_meths = yard_map.get_methods(namespace, root, visibility: visibility)
|
319
392
|
if yard_meths.any?
|
320
393
|
meths.concat yard_meths
|
321
394
|
else
|
322
395
|
type = get_namespace_type(namespace, root)
|
323
396
|
if type == :class
|
324
|
-
meths +=
|
397
|
+
meths += yard_map.get_instance_methods('Class')
|
325
398
|
elsif type == :module
|
326
|
-
meths +=
|
399
|
+
meths += yard_map.get_methods('Module')
|
327
400
|
end
|
328
401
|
meths
|
329
402
|
end
|
@@ -350,23 +423,23 @@ module Solargraph
|
|
350
423
|
def get_instance_methods(namespace, root = '', visibility: [:public])
|
351
424
|
meths = []
|
352
425
|
meths += inner_get_instance_methods(namespace, root, []) #unless has_yardoc?
|
353
|
-
|
354
|
-
yard_meths =
|
426
|
+
fqns = find_fully_qualified_namespace(namespace, root)
|
427
|
+
yard_meths = yard_map.get_instance_methods(fqns, '', visibility: visibility)
|
355
428
|
if yard_meths.any?
|
356
429
|
meths.concat yard_meths
|
357
430
|
else
|
358
431
|
type = get_namespace_type(namespace, root)
|
359
432
|
if type == :class
|
360
|
-
meths +=
|
433
|
+
meths += yard_map.get_instance_methods('Object')
|
361
434
|
elsif type == :module
|
362
|
-
meths +=
|
435
|
+
meths += yard_map.get_instance_methods('Module')
|
363
436
|
end
|
364
437
|
# TODO: Look out for repeats. Consider not doing this at all.
|
365
|
-
sc = get_superclass(namespace, root)
|
366
|
-
until sc.nil?
|
367
|
-
|
368
|
-
|
369
|
-
end
|
438
|
+
#sc = get_superclass(namespace, root)
|
439
|
+
#until sc.nil?
|
440
|
+
# meths += yard.get_instance_methods(sc, root)
|
441
|
+
# sc = get_superclass(sc)
|
442
|
+
#end
|
370
443
|
end
|
371
444
|
meths
|
372
445
|
end
|
@@ -420,26 +493,39 @@ module Solargraph
|
|
420
493
|
s = unpack_name(n.children[1])
|
421
494
|
meths += inner_get_methods(s, root, skip)
|
422
495
|
end
|
423
|
-
n
|
424
|
-
if c.kind_of?(AST::Node) and c.type == :defs
|
425
|
-
docstring = get_comment_for(c)
|
426
|
-
label = "#{c.children[1]}"
|
427
|
-
args = get_method_args(c)
|
428
|
-
label += " #{args.join(', ')}" unless args.empty?
|
429
|
-
meths.push Suggestion.new(label, insert: c.children[1].to_s, kind: Suggestion::METHOD, detail: 'Method', documentation: docstring) if c.children[1].to_s[0].match(/[a-z_]/i) and c.children[1] != :def
|
430
|
-
elsif c.kind_of?(AST::Node) and c.type == :send and c.children[1] == :include
|
431
|
-
# TODO: This might not be right. Should we be getting singleton methods
|
432
|
-
# from an include, or only from an extend?
|
433
|
-
i = unpack_name(c.children[2])
|
434
|
-
meths += inner_get_methods(i, root, skip) unless i == 'Kernel'
|
435
|
-
end
|
436
|
-
}
|
496
|
+
meths += inner_get_methods_from_node(n, root, skip)
|
437
497
|
end
|
438
498
|
#end
|
439
499
|
}
|
440
500
|
meths.uniq
|
441
501
|
end
|
442
502
|
|
503
|
+
def inner_get_methods_from_node node, root, skip
|
504
|
+
meths = []
|
505
|
+
node.children.each { |c|
|
506
|
+
if c.kind_of?(AST::Node)
|
507
|
+
if c.type == :defs
|
508
|
+
docstring = get_comment_for(c)
|
509
|
+
label = "#{c.children[1]}"
|
510
|
+
args = get_method_args(c)
|
511
|
+
label += " #{args.join(', ')}" unless args.empty?
|
512
|
+
meths.push Suggestion.new(label, insert: c.children[1].to_s, kind: Suggestion::METHOD, detail: 'Method', documentation: docstring) if c.children[1].to_s[0].match(/[a-z_]/i) and c.children[1] != :def
|
513
|
+
elsif c.type == :send and c.children[1] == :include
|
514
|
+
# TODO: This might not be right. Should we be getting singleton methods
|
515
|
+
# from an include, or only from an extend?
|
516
|
+
i = unpack_name(c.children[2])
|
517
|
+
meths += inner_get_methods(i, root, skip) unless i == 'Kernel'
|
518
|
+
elsif c.type == :send and c.children[1] == :solargraph_include_public_methods
|
519
|
+
i = unpack_name(c.children[2])
|
520
|
+
meths += get_instance_methods(i, root, visibility: [:public])
|
521
|
+
else
|
522
|
+
meths += inner_get_methods_from_node(c, root, skip)
|
523
|
+
end
|
524
|
+
end
|
525
|
+
}
|
526
|
+
meths
|
527
|
+
end
|
528
|
+
|
443
529
|
def inner_get_instance_methods(namespace, root, skip)
|
444
530
|
fqns = find_fully_qualified_namespace(namespace, root)
|
445
531
|
meths = []
|
@@ -481,19 +567,20 @@ module Solargraph
|
|
481
567
|
}
|
482
568
|
end
|
483
569
|
end
|
484
|
-
get_include_strings_from(n).each { |i|
|
485
|
-
meths += inner_get_instance_methods(i, fqns, skip)
|
486
|
-
}
|
487
570
|
}
|
488
571
|
end
|
489
572
|
#end
|
573
|
+
# This is necessary to get included modules from workspace definitions
|
574
|
+
get_include_strings_from(n).each { |i|
|
575
|
+
meths += inner_get_instance_methods(i, fqns, skip)
|
576
|
+
}
|
490
577
|
}
|
491
578
|
meths.uniq
|
492
579
|
end
|
493
580
|
|
494
581
|
def mappable?(node)
|
495
582
|
# TODO Add node.type :casgn (constant assignment)
|
496
|
-
if node.kind_of?(AST::Node) and (node.type == :class or node.type == :module or node.type == :def or node.type == :defs or node.type == :ivasgn or node.type == :gvasgn or node.type == :or_asgn)
|
583
|
+
if node.kind_of?(AST::Node) and (node.type == :class or node.type == :module or node.type == :def or node.type == :defs or node.type == :ivasgn or node.type == :gvasgn or node.type == :lvasgn or node.type == :or_asgn)
|
497
584
|
true
|
498
585
|
elsif node.kind_of?(AST::Node) and node.type == :send and node.children[0] == nil and MAPPABLE_METHODS.include?(node.children[1])
|
499
586
|
true
|
@@ -539,7 +626,7 @@ module Solargraph
|
|
539
626
|
elsif node.type == :module
|
540
627
|
children += node.children[0, 1]
|
541
628
|
children += get_mappable_nodes(node.children[1..-1], comment_hash)
|
542
|
-
elsif node.type == :ivasgn or node.type == :gvasgn
|
629
|
+
elsif node.type == :ivasgn or node.type == :gvasgn or node.type == :lvasgn
|
543
630
|
children += node.children
|
544
631
|
elsif node.type == :send and node.children[1] == :include
|
545
632
|
children += node.children[0,3]
|
data/lib/solargraph/code_map.rb
CHANGED
@@ -4,9 +4,9 @@ module Solargraph
|
|
4
4
|
class CodeMap
|
5
5
|
attr_accessor :node
|
6
6
|
attr_accessor :api_map
|
7
|
-
|
7
|
+
|
8
8
|
include NodeMethods
|
9
|
-
|
9
|
+
|
10
10
|
def initialize code: '', filename: nil, workspace: nil, api_map: nil
|
11
11
|
unless workspace.nil?
|
12
12
|
workspace = workspace.gsub(File::ALT_SEPARATOR, File::SEPARATOR) unless File::ALT_SEPARATOR.nil?
|
@@ -17,11 +17,7 @@ module Solargraph
|
|
17
17
|
end
|
18
18
|
@api_map = api_map
|
19
19
|
if @api_map.nil?
|
20
|
-
|
21
|
-
@api_map = ApiMap.new(workspace)
|
22
|
-
else
|
23
|
-
@api_map = ApiMap.new(workspace)
|
24
|
-
end
|
20
|
+
@api_map = ApiMap.new(workspace)
|
25
21
|
end
|
26
22
|
|
27
23
|
@code = code.gsub(/\r/, '')
|
@@ -29,8 +25,8 @@ module Solargraph
|
|
29
25
|
# Hide incomplete code to avoid syntax errors
|
30
26
|
tmp = "#{@code}\nX".gsub(/[\.@]([\s])/, '#\1').gsub(/([\A\s]?)def([\s]*?[\n\Z])/, '\1#ef\2')
|
31
27
|
begin
|
32
|
-
|
33
|
-
@api_map.append_node(
|
28
|
+
node, comments = Parser::CurrentRuby.parse_with_comments(tmp)
|
29
|
+
@node = @api_map.append_node(node, comments, filename)
|
34
30
|
rescue Parser::SyntaxError => e
|
35
31
|
if tries < 10
|
36
32
|
tries += 1
|
@@ -154,14 +150,19 @@ module Solargraph
|
|
154
150
|
return [] if string_at?(index)
|
155
151
|
result = []
|
156
152
|
phrase = phrase_at(index)
|
157
|
-
|
158
|
-
|
153
|
+
signature = get_signature_at(index)
|
154
|
+
if signature.start_with?('@')
|
155
|
+
parts = signature.split('.')
|
156
|
+
var = parts.shift
|
157
|
+
if parts.length > 0 or signature.end_with?('.')
|
159
158
|
result = []
|
160
|
-
# TODO: Temporarily assuming one period
|
161
|
-
var = phrase[0..phrase.index('.')-1]
|
162
159
|
ns = namespace_at(index)
|
163
|
-
|
164
|
-
|
160
|
+
scope = :class
|
161
|
+
node = parent_node_from(index, :def, :defs, :class, :module)
|
162
|
+
scope = :instance if !node.nil? and node.type == :def
|
163
|
+
obj = @api_map.infer_instance_variable(var, ns, scope)
|
164
|
+
type = @api_map.infer_signature_type(parts.join('.'), obj, scope: :instance)
|
165
|
+
result = @api_map.get_instance_methods(type) unless type.nil?
|
165
166
|
else
|
166
167
|
result = get_instance_variables_at(index)
|
167
168
|
end
|
@@ -179,7 +180,7 @@ module Solargraph
|
|
179
180
|
else
|
180
181
|
result = @api_map.namespaces_in(ns)
|
181
182
|
end
|
182
|
-
elsif
|
183
|
+
elsif signature.include?('.')
|
183
184
|
result = resolve_signature_at @code[0, index].rindex('.')
|
184
185
|
else
|
185
186
|
current_namespace = namespace_at(index)
|
@@ -198,74 +199,70 @@ module Solargraph
|
|
198
199
|
result = reduce_starting_with(result, word_at(index)) if filtered
|
199
200
|
result
|
200
201
|
end
|
201
|
-
|
202
|
+
|
203
|
+
# Find the signature at the specified index and get suggestions based
|
204
|
+
# on its inferred type.
|
205
|
+
#
|
206
|
+
# @return [Array<Solargraph::Suggestion>]
|
202
207
|
def resolve_signature_at index
|
208
|
+
result = []
|
203
209
|
signature = get_signature_at(index)
|
204
210
|
ns_here = namespace_at(index)
|
205
|
-
parts = signature.split('.')
|
206
|
-
first = parts.shift
|
207
211
|
scope = parent_node_from(index, :class, :module, :def, :defs) || @node
|
208
|
-
|
212
|
+
parts = signature.split('.')
|
213
|
+
var = find_local_variable_node(parts[0], scope)
|
209
214
|
if var.nil?
|
210
|
-
# It's not a
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
215
|
+
# It's not a local variable
|
216
|
+
fqns = @api_map.find_fully_qualified_namespace(signature, ns_here)
|
217
|
+
if fqns.nil?
|
218
|
+
# It's a method call
|
219
|
+
type = @api_map.infer_signature_type(signature, ns_here, scope: :class)
|
220
|
+
result.concat @api_map.get_instance_methods(type) unless type.nil?
|
216
221
|
else
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
else
|
230
|
-
meths = @api_map.get_methods(ns_here).delete_if{|m| m.insert != first}
|
231
|
-
return [] if meths.empty?
|
232
|
-
return [] if meths[0].documentation.nil?
|
233
|
-
match = meths[0].documentation.all.match(/@return \[([a-z0-9:_]*)/i)
|
234
|
-
return [] if match[1].nil?
|
235
|
-
return @api_map.get_instance_methods(match[1], ns_here)
|
236
|
-
end
|
237
|
-
end
|
238
|
-
end
|
239
|
-
meth = parts.shift
|
240
|
-
if meth == 'new'
|
241
|
-
obj = first
|
222
|
+
result.concat @api_map.get_methods(fqns)
|
223
|
+
end
|
224
|
+
else
|
225
|
+
# It's a local variable. Get the type from the node
|
226
|
+
type = get_type_comment(var)
|
227
|
+
type = infer(var.children[1]) if type.nil?
|
228
|
+
if type.nil?
|
229
|
+
vsig = resolve_node_signature(var.children[1])
|
230
|
+
vparts = vsig.split('.')
|
231
|
+
fqns = @api_map.find_fully_qualified_namespace(vparts[0], ns_here)
|
232
|
+
if fqns.nil?
|
233
|
+
vtype = @api_map.infer_signature_type(vsig, ns_here, scope: :instance)
|
242
234
|
else
|
243
|
-
|
235
|
+
vtype = @api_map.infer_signature_type(vparts[1..-1].join('.'), fqns, scope: :class)
|
244
236
|
end
|
237
|
+
fqns = @api_map.find_fully_qualified_namespace(vtype, ns_here)
|
238
|
+
signature = parts[1..-1].join('.')
|
239
|
+
type = @api_map.infer_signature_type(signature, fqns, scope: :instance)
|
245
240
|
end
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
241
|
+
unless type.nil?
|
242
|
+
lparts = signature.split('.')
|
243
|
+
if lparts.length > 1
|
244
|
+
lsig = lparts[1..-1].join('.')
|
245
|
+
ltype = @api_map.infer_signature_type(lsig, type, scope: :instance)
|
246
|
+
result.concat @api_map.get_instance_methods(ltype) unless ltype.nil?
|
247
|
+
else
|
248
|
+
result.concat @api_map.get_instance_methods(type)
|
249
|
+
end
|
255
250
|
end
|
256
|
-
return @api_map.get_instance_methods(obj) unless obj.nil?
|
257
251
|
end
|
252
|
+
result
|
258
253
|
end
|
259
254
|
|
260
|
-
def
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
255
|
+
def get_type_comment node
|
256
|
+
obj = nil
|
257
|
+
cmnt = @api_map.get_comment_for(node)
|
258
|
+
unless cmnt.nil?
|
259
|
+
tag = cmnt.tag(:type)
|
260
|
+
obj = tag.types[0] unless tag.nil? or tag.types.empty?
|
261
|
+
end
|
262
|
+
obj
|
267
263
|
end
|
268
264
|
|
265
|
+
# @todo Candidate for deprecation
|
269
266
|
def get_instance_method_return_value namespace, root, method
|
270
267
|
meths = @api_map.get_instance_methods(namespace, root).delete_if{ |m| m.insert != method }
|
271
268
|
meths.each { |m|
|
@@ -284,13 +281,6 @@ module Solargraph
|
|
284
281
|
end
|
285
282
|
|
286
283
|
def get_signature_at index
|
287
|
-
#node = node_at(index - 1)
|
288
|
-
#return '' unless node.type == :send
|
289
|
-
#parts = []
|
290
|
-
#build_signature(node, parts)
|
291
|
-
#return parts.join('.')
|
292
|
-
|
293
|
-
# TODO: Alternate rough version
|
294
284
|
brackets = 0
|
295
285
|
squares = 0
|
296
286
|
parens = 0
|
@@ -314,7 +304,8 @@ module Solargraph
|
|
314
304
|
end
|
315
305
|
if brackets == 0 and parens == 0 and squares == 0
|
316
306
|
break if ['"', "'", ',', ' ', "\t", "\n"].include?(char)
|
317
|
-
signature = char + signature if char.match(/[a-z0-9:\._]/i)
|
307
|
+
signature = char + signature if char.match(/[a-z0-9:\._@]/i)
|
308
|
+
break if char == '@'
|
318
309
|
end
|
319
310
|
index -= 1
|
320
311
|
end
|
@@ -364,7 +355,7 @@ module Solargraph
|
|
364
355
|
result += @api_map.get_methods('Kernel')
|
365
356
|
result
|
366
357
|
end
|
367
|
-
|
358
|
+
|
368
359
|
private
|
369
360
|
|
370
361
|
def reduce_starting_with(suggestions, word)
|
@@ -379,7 +370,7 @@ module Solargraph
|
|
379
370
|
node.children.each { |c|
|
380
371
|
if c.kind_of?(AST::Node)
|
381
372
|
if c.type == :lvasgn
|
382
|
-
arr.push Suggestion.new(c.children[0], kind: Suggestion::VARIABLE)
|
373
|
+
arr.push Suggestion.new(c.children[0], kind: Suggestion::VARIABLE, documentation: @api_map.get_comment_for(c))
|
383
374
|
else
|
384
375
|
arr += get_local_variables_from(c) unless [:class, :module, :def, :defs].include?(c.type)
|
385
376
|
end
|
@@ -387,7 +378,7 @@ module Solargraph
|
|
387
378
|
}
|
388
379
|
arr
|
389
380
|
end
|
390
|
-
|
381
|
+
|
391
382
|
def inner_node_at(index, node, arr)
|
392
383
|
node.children.each { |c|
|
393
384
|
if c.kind_of?(AST::Node)
|
@@ -406,7 +397,7 @@ module Solargraph
|
|
406
397
|
end
|
407
398
|
}
|
408
399
|
end
|
409
|
-
|
400
|
+
|
410
401
|
def find_local_variable_node name, scope
|
411
402
|
scope.children.each { |c|
|
412
403
|
if c.kind_of?(AST::Node)
|
@@ -422,6 +413,6 @@ module Solargraph
|
|
422
413
|
}
|
423
414
|
nil
|
424
415
|
end
|
425
|
-
|
416
|
+
|
426
417
|
end
|
427
418
|
end
|
@@ -33,18 +33,34 @@ module Solargraph
|
|
33
33
|
return 'Integer'
|
34
34
|
elsif node.type == :float
|
35
35
|
return 'Float'
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
36
|
+
end
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
|
40
|
+
# Get a call signature from a node.
|
41
|
+
# The result should be a string in the form of a method path, e.g.,
|
42
|
+
# String.new or variable.method.
|
43
|
+
#
|
44
|
+
# @return [String]
|
45
|
+
def resolve_node_signature node
|
46
|
+
stack_node_signature(node).join('.')
|
47
|
+
end
|
48
|
+
|
49
|
+
def stack_node_signature node
|
50
|
+
parts = []
|
51
|
+
if node.kind_of?(AST::Node)
|
52
|
+
if node.type == :send
|
53
|
+
unless node.children[0].nil?
|
54
|
+
parts = [unpack_name(node.children[0])] + parts
|
43
55
|
end
|
56
|
+
parts += stack_node_signature(node.children[1])
|
57
|
+
else
|
58
|
+
parts = [unpack_name(node)] + stack_node_signature(node.children[1])
|
44
59
|
end
|
45
|
-
|
46
|
-
|
60
|
+
else
|
61
|
+
parts.push node.to_s
|
47
62
|
end
|
63
|
+
parts
|
48
64
|
end
|
49
65
|
end
|
50
66
|
end
|
data/lib/solargraph/version.rb
CHANGED
data/lib/solargraph/yard_map.rb
CHANGED
@@ -126,11 +126,11 @@ module Solargraph
|
|
126
126
|
yard = YARD::Registry.load! y
|
127
127
|
unless yard.nil?
|
128
128
|
ns = nil
|
129
|
-
if scope == ''
|
130
|
-
|
131
|
-
else
|
129
|
+
#if scope == ''
|
130
|
+
# ns = yard.at(namespace)
|
131
|
+
#else
|
132
132
|
ns = find_first_resolved_namespace(yard, namespace, scope)
|
133
|
-
end
|
133
|
+
#end
|
134
134
|
unless ns.nil? or !ns.kind_of?(YARD::CodeObjects::NamespaceObject)
|
135
135
|
ns.meths(scope: :class, visibility: visibility).each { |m|
|
136
136
|
# HACK: Fix return tags in core documentation
|
@@ -156,11 +156,11 @@ module Solargraph
|
|
156
156
|
yard = YARD::Registry.load! y
|
157
157
|
unless yard.nil?
|
158
158
|
ns = nil
|
159
|
-
if scope == ''
|
160
|
-
|
161
|
-
else
|
159
|
+
#if scope == ''
|
160
|
+
# ns = yard.at(namespace)
|
161
|
+
#else
|
162
162
|
ns = find_first_resolved_namespace(yard, namespace, scope)
|
163
|
-
end
|
163
|
+
#end
|
164
164
|
unless ns.nil?
|
165
165
|
ns.meths(scope: :instance, visibility: visibility).each { |m|
|
166
166
|
# HACK: Fix return tags in core documentation
|
@@ -186,6 +186,11 @@ module Solargraph
|
|
186
186
|
Gem::Specification.map{ |s| s.name }.uniq
|
187
187
|
end
|
188
188
|
|
189
|
+
def find_fully_qualified_namespace namespace, scope
|
190
|
+
obj = resolve(namespace, scope)
|
191
|
+
return obj.path unless obj.nil?
|
192
|
+
end
|
193
|
+
|
189
194
|
private
|
190
195
|
|
191
196
|
def get_method_args meth
|
@@ -215,7 +220,8 @@ module Solargraph
|
|
215
220
|
def find_first_resolved_namespace yard, namespace, scope
|
216
221
|
parts = scope.split('::')
|
217
222
|
while parts.length > 0
|
218
|
-
|
223
|
+
puts "Looking for #{namespace} in #{parts.join('::')}"
|
224
|
+
ns = yard.resolve(P(parts.join('::')), namespace, true)
|
219
225
|
return ns unless ns.nil?
|
220
226
|
parts.pop
|
221
227
|
end
|
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.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fred Snyder
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-04-
|
11
|
+
date: 2017-04-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parser
|