solargraph 0.7.5 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/solargraph/api_map.rb +10 -17
- data/lib/solargraph/code_map.rb +128 -27
- data/lib/solargraph/node_methods.rb +40 -1
- data/lib/solargraph/server.rb +51 -20
- data/lib/solargraph/shell.rb +0 -1
- data/lib/solargraph/suggestion.rb +7 -5
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/yard_map.rb +51 -19
- 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: a80ad72c101042120c5ec349dd3fb19a98e794e7
|
4
|
+
data.tar.gz: 99d562e48985d5fa6e3d8dbaf93edafd165490c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ee8a6a7d1d7cc1ec77727a81e7cd4db7e3da8c0d03baee7424ac2063d281bbc1ceb1863c37c489219f65735cc3adbb64f78b05b7a1ed29a9dfc2b73eb776c6ee
|
7
|
+
data.tar.gz: 34a309dcdb41c54a99ced46a8c51fe3b4372d8dc51a2620647f0b7d3f4331662f7fd3a263f4a99d6e45f3bfe899b965212e38adfb1e578daa89667914be50b98
|
data/lib/solargraph/api_map.rb
CHANGED
@@ -15,7 +15,7 @@ module Solargraph
|
|
15
15
|
|
16
16
|
MAPPABLE_METHODS = [
|
17
17
|
:include, :extend, :require, :autoload, :attr_reader, :attr_writer, :attr_accessor, :private, :public, :protected
|
18
|
-
]
|
18
|
+
]
|
19
19
|
|
20
20
|
include NodeMethods
|
21
21
|
|
@@ -99,7 +99,7 @@ module Solargraph
|
|
99
99
|
|
100
100
|
def self.get_keywords
|
101
101
|
result = []
|
102
|
-
keywords = KEYWORDS +
|
102
|
+
keywords = KEYWORDS + ['attr_reader', 'attr_writer', 'attr_accessor', 'private', 'public', 'protected']
|
103
103
|
keywords.each { |k|
|
104
104
|
result.push Suggestion.new(k, kind: Suggestion::KEYWORD, detail: 'Keyword')
|
105
105
|
}
|
@@ -250,7 +250,6 @@ module Solargraph
|
|
250
250
|
if @yardoc_files.nil?
|
251
251
|
@yardoc_files = []
|
252
252
|
yard_options[:include].each { |glob|
|
253
|
-
#@yardoc_files.concat Dir[File.join workspace, glob]
|
254
253
|
Dir[File.join workspace, glob].each { |f|
|
255
254
|
@yardoc_files.push File.absolute_path(f)
|
256
255
|
}
|
@@ -349,7 +348,6 @@ module Solargraph
|
|
349
348
|
meths += get_methods('') if top or type.to_s == ''
|
350
349
|
else
|
351
350
|
meths = get_methods(type)
|
352
|
-
#meths += get_methods('') if top
|
353
351
|
end
|
354
352
|
meths.delete_if{ |m| m.insert != p }
|
355
353
|
return nil if meths.empty?
|
@@ -389,7 +387,7 @@ module Solargraph
|
|
389
387
|
meths
|
390
388
|
end
|
391
389
|
end
|
392
|
-
|
390
|
+
|
393
391
|
def get_method_args node
|
394
392
|
list = nil
|
395
393
|
args = []
|
@@ -466,12 +464,9 @@ module Solargraph
|
|
466
464
|
STDERR.puts "No workspace specified for yardoc update."
|
467
465
|
else
|
468
466
|
Dir.chdir(workspace) do
|
469
|
-
#YARD::Registry.load(yard_options[:include] - yard_options[:exclude], true)
|
470
|
-
#YARD::Registry.save
|
471
467
|
Thread.new {
|
472
468
|
STDERR.puts "Updating the yardoc..."
|
473
469
|
globs = yard_options[:include] - yard_options[:exclude]
|
474
|
-
#cmd = "yardoc #{globs.join(' ')} -e #{Solargraph::YARD_EXTENSION_FILE} #{yard_options[:flags].join(' ')}"
|
475
470
|
cmd = "yardoc -e #{Solargraph::YARD_EXTENSION_FILE}"
|
476
471
|
STDERR.puts "Update yardoc with #{cmd}"
|
477
472
|
STDERR.puts `#{cmd}`
|
@@ -514,16 +509,12 @@ module Solargraph
|
|
514
509
|
docstring = get_comment_for(c)
|
515
510
|
label = "#{c.children[1]}"
|
516
511
|
args = get_method_args(c)
|
517
|
-
label
|
518
|
-
meths.push Suggestion.new(label, insert: c.children[1].to_s.gsub(/=/, ' = '), kind: Suggestion::METHOD, detail: 'Method', documentation: docstring) if c.children[1].to_s[0].match(/[a-z_]/i) and c.children[1] != :def
|
512
|
+
meths.push Suggestion.new(label, insert: c.children[1].to_s.gsub(/=/, ' = '), kind: Suggestion::METHOD, detail: 'Method', documentation: docstring, arguments: args) if c.children[1].to_s[0].match(/[a-z_]/i) and c.children[1] != :def
|
519
513
|
elsif c.type == :send and c.children[1] == :include
|
520
514
|
# TODO: This might not be right. Should we be getting singleton methods
|
521
515
|
# from an include, or only from an extend?
|
522
516
|
i = unpack_name(c.children[2])
|
523
517
|
meths += inner_get_methods(i, root, skip) unless i == 'Kernel'
|
524
|
-
#elsif c.type == :send and c.children[1] == :solargraph_include_public_methods
|
525
|
-
# i = unpack_name(c.children[2])
|
526
|
-
# meths += get_instance_methods(i, root, visibility: [:public])
|
527
518
|
else
|
528
519
|
meths += inner_get_methods_from_node(c, root, skip)
|
529
520
|
end
|
@@ -559,8 +550,7 @@ module Solargraph
|
|
559
550
|
cmnt = get_comment_for(c)
|
560
551
|
label = "#{c.children[0]}"
|
561
552
|
args = get_method_args(c)
|
562
|
-
label
|
563
|
-
meths.push Suggestion.new(label, insert: c.children[0].to_s.gsub(/=/, ' = '), kind: Suggestion::METHOD, documentation: cmnt, detail: fqns) if c.children[0].to_s[0].match(/[a-z]/i)
|
553
|
+
meths.push Suggestion.new(label, insert: c.children[0].to_s.gsub(/=/, ' = '), kind: Suggestion::METHOD, documentation: cmnt, detail: fqns, arguments: args) if c.children[0].to_s[0].match(/[a-z]/i)
|
564
554
|
elsif c.kind_of?(AST::Node) and c.type == :send and c.children[1] == :attr_reader
|
565
555
|
c.children[2..-1].each { |x|
|
566
556
|
meths.push Suggestion.new(x.children[0], kind: Suggestion::METHOD) if x.type == :sym
|
@@ -590,7 +580,7 @@ module Solargraph
|
|
590
580
|
def mappable?(node)
|
591
581
|
return true if node.kind_of?(AST::Node) and [:array, :hash, :str, :int, :float].include?(node.type)
|
592
582
|
# TODO Add node.type :casgn (constant assignment)
|
593
|
-
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)
|
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 or node.type == :const or node.type == :lvar)
|
594
584
|
true
|
595
585
|
elsif node.kind_of?(AST::Node) and node.type == :send and node.children[0] == nil and MAPPABLE_METHODS.include?(node.children[1])
|
596
586
|
true
|
@@ -627,6 +617,9 @@ module Solargraph
|
|
627
617
|
if node.type == :class
|
628
618
|
children += node.children[0, 2]
|
629
619
|
children += get_mappable_nodes(node.children[2..-1], comment_hash)
|
620
|
+
#children += get_mappable_nodes(node.children, comment_hash)
|
621
|
+
elsif node.type == :const
|
622
|
+
children += node.children
|
630
623
|
elsif node.type == :def
|
631
624
|
children += node.children[0, 2]
|
632
625
|
children += get_mappable_nodes(node.children[2..-1], comment_hash)
|
@@ -647,7 +640,7 @@ module Solargraph
|
|
647
640
|
@required.push(node.children[3].children[0]) if node.children[3].children[0].kind_of?(String)
|
648
641
|
type = :require
|
649
642
|
children += node.children[1, 3]
|
650
|
-
elsif node.type == :send
|
643
|
+
elsif node.type == :send or node.type == :lvar
|
651
644
|
children += node.children
|
652
645
|
elsif node.type == :or_asgn
|
653
646
|
# TODO: The api_map should ignore local variables.
|
data/lib/solargraph/code_map.rb
CHANGED
@@ -24,10 +24,6 @@ module Solargraph
|
|
24
24
|
end
|
25
25
|
@code = code.gsub(/\r/, '')
|
26
26
|
tries = 0
|
27
|
-
# Hide incomplete code to avoid syntax errors
|
28
|
-
# @todo This might not be necessary given the corrected character
|
29
|
-
# replacement in retries.
|
30
|
-
#tmp = "#{@code}\nX".gsub(/[\.@]([\s])/, '#\1').gsub(/([\A\s]?)def([\s]*?[\n\Z])/, '\1#ef\2')
|
31
27
|
tmp = @code
|
32
28
|
begin
|
33
29
|
node, comments = Parser::CurrentRuby.parse_with_comments(tmp)
|
@@ -41,10 +37,6 @@ module Solargraph
|
|
41
37
|
STDERR.puts "Retrying..."
|
42
38
|
tries += 1
|
43
39
|
spot = e.diagnostic.location.begin_pos
|
44
|
-
#STDERR.puts "CODE>>>>"
|
45
|
-
#STDERR.puts tmp
|
46
|
-
#STDERR.puts "<<<<CODE"
|
47
|
-
#STDERR.puts "Spot #{spot}: #{tmp[spot]}"
|
48
40
|
repl = '_'
|
49
41
|
if tmp[spot] == '@' or tmp[spot] == ':'
|
50
42
|
# Stub unfinished instance variables and symbols
|
@@ -61,14 +53,7 @@ module Solargraph
|
|
61
53
|
repl= 'end;end'
|
62
54
|
end
|
63
55
|
end
|
64
|
-
|
65
|
-
# tmp = '#' + tmp[1..-1]
|
66
|
-
#else
|
67
|
-
tmp = tmp[0..spot] + repl + tmp[spot+repl.length+1..-1].to_s
|
68
|
-
#end
|
69
|
-
#STDERR.puts "CHNG>>>>"
|
70
|
-
#STDERR.puts tmp
|
71
|
-
#STDERR.puts "<<<<CHNG"
|
56
|
+
tmp = tmp[0..spot] + repl + tmp[spot+repl.length+1..-1].to_s
|
72
57
|
retry
|
73
58
|
end
|
74
59
|
raise e
|
@@ -136,12 +121,12 @@ module Solargraph
|
|
136
121
|
def namespace_at(index)
|
137
122
|
tree = tree_at(index)
|
138
123
|
return nil if tree.length == 0
|
139
|
-
|
140
|
-
slice = tree[(tree.index(node) || 0)..-1]
|
124
|
+
slice = tree
|
141
125
|
parts = []
|
142
126
|
slice.reverse.each { |n|
|
143
127
|
if n.type == :class or n.type == :module
|
144
|
-
|
128
|
+
c = const_from(n.children[0])
|
129
|
+
parts.push c
|
145
130
|
end
|
146
131
|
}
|
147
132
|
parts.join("::")
|
@@ -179,7 +164,7 @@ module Solargraph
|
|
179
164
|
@api_map.get_instance_variables(ns, (node.type == :def ? :instance : :class))
|
180
165
|
end
|
181
166
|
|
182
|
-
def suggest_at index, filtered:
|
167
|
+
def suggest_at index, filtered: false, with_snippets: false
|
183
168
|
node = node_at(index - 2)
|
184
169
|
return [] if string_at?(index)
|
185
170
|
result = []
|
@@ -240,10 +225,88 @@ module Solargraph
|
|
240
225
|
end
|
241
226
|
end
|
242
227
|
end
|
243
|
-
|
228
|
+
result = reduce_starting_with(result, word_at(index)) if filtered
|
244
229
|
result.uniq{|s| s.path}
|
245
230
|
end
|
246
231
|
|
232
|
+
def signatures_at index
|
233
|
+
sig = signature_index_before(index)
|
234
|
+
return [] if sig.nil?
|
235
|
+
word = word_at(sig)
|
236
|
+
suggest_at(sig).reject{|s| s.label != word}
|
237
|
+
end
|
238
|
+
|
239
|
+
def resolve_object_at index
|
240
|
+
signature = get_signature_at(index)
|
241
|
+
cursor = index
|
242
|
+
while @code[cursor] =~ /[a-z0-9_\?]/i
|
243
|
+
signature += @code[cursor]
|
244
|
+
cursor += 1
|
245
|
+
break if cursor >= @code.length
|
246
|
+
end
|
247
|
+
return [] if signature.to_s == ''
|
248
|
+
ns_here = namespace_at(index)
|
249
|
+
scope = parent_node_from(index, :class, :module, :def, :defs) || @node
|
250
|
+
parts = signature.split('.')
|
251
|
+
if parts.length > 1
|
252
|
+
beginner = parts[0..-2].join('.')
|
253
|
+
ender = parts.last
|
254
|
+
else
|
255
|
+
beginner = signature
|
256
|
+
ender = nil
|
257
|
+
end
|
258
|
+
var = find_local_variable_node(parts[0], scope)
|
259
|
+
if var.nil?
|
260
|
+
# It's not a local variable
|
261
|
+
fqns = @api_map.find_fully_qualified_namespace(beginner, ns_here)
|
262
|
+
if fqns.nil?
|
263
|
+
# It's a method call
|
264
|
+
if ender.nil?
|
265
|
+
return @api_map.yard_map.objects(beginner, ns_here)
|
266
|
+
else
|
267
|
+
sig_scope = (scope.type == :def ? :instance : :class)
|
268
|
+
type = @api_map.infer_signature_type(beginner, ns_here, scope: sig_scope)
|
269
|
+
return [] if type.nil?
|
270
|
+
path = type
|
271
|
+
path += "##{ender}" unless ender.nil?
|
272
|
+
return @api_map.yard_map.objects(path, ns_here)
|
273
|
+
end
|
274
|
+
else
|
275
|
+
path = beginner
|
276
|
+
path += "##{ender}" unless ender.nil?
|
277
|
+
return @api_map.yard_map.objects(path, ns_here)
|
278
|
+
end
|
279
|
+
else
|
280
|
+
# It's a local variable. Get the type from the node
|
281
|
+
type = get_type_comment(var)
|
282
|
+
type = infer(var.children[1]) if type.nil?
|
283
|
+
if type.nil?
|
284
|
+
vsig = resolve_node_signature(var.children[1])
|
285
|
+
vparts = vsig.split('.')
|
286
|
+
fqns = @api_map.find_fully_qualified_namespace(vparts[0], ns_here)
|
287
|
+
if fqns.nil?
|
288
|
+
vtype = @api_map.infer_signature_type(vsig, ns_here, scope: :instance)
|
289
|
+
else
|
290
|
+
vtype = @api_map.infer_signature_type(vparts[1..-1].join('.'), fqns, scope: :class)
|
291
|
+
end
|
292
|
+
return [] if vtype.nil?
|
293
|
+
fqns = @api_map.find_fully_qualified_namespace(vtype, ns_here)
|
294
|
+
if ender.nil?
|
295
|
+
signature = parts[1..-1].join('.')
|
296
|
+
else
|
297
|
+
signature = parts[1..-2].join('.')
|
298
|
+
end
|
299
|
+
type = @api_map.infer_signature_type(signature, fqns, scope: :instance)
|
300
|
+
end
|
301
|
+
unless type.nil?
|
302
|
+
path = type
|
303
|
+
path += "##{ender}" unless ender.nil?
|
304
|
+
return @api_map.yard_map.objects(path, ns_here)
|
305
|
+
end
|
306
|
+
end
|
307
|
+
return []
|
308
|
+
end
|
309
|
+
|
247
310
|
# Find the signature at the specified index and get suggestions based
|
248
311
|
# on its inferred type.
|
249
312
|
#
|
@@ -274,23 +337,44 @@ module Solargraph
|
|
274
337
|
# It's a local variable. Get the type from the node
|
275
338
|
type = get_type_comment(var)
|
276
339
|
type = infer(var.children[1]) if type.nil?
|
340
|
+
skipdat = false
|
277
341
|
if type.nil?
|
278
342
|
vsig = resolve_node_signature(var.children[1])
|
279
343
|
vparts = vsig.split('.')
|
280
344
|
fqns = @api_map.find_fully_qualified_namespace(vparts[0], ns_here)
|
281
345
|
if fqns.nil?
|
282
|
-
|
346
|
+
lvar = find_local_variable_node(vparts[0], scope)
|
347
|
+
if lvar.nil?
|
348
|
+
vtype = @api_map.infer_signature_type(vsig, ns_here, scope: :instance)
|
349
|
+
else
|
350
|
+
type = get_type_comment(lvar)
|
351
|
+
type = infer(lvar.children[1]) if type.nil?
|
352
|
+
if type.nil?
|
353
|
+
type = @api_map.infer_signature_type(resolve_node_signature(lvar.children[1]), ns_here, scope: :class)
|
354
|
+
end
|
355
|
+
unless type.nil?
|
356
|
+
signature = "#{vparts[1..-1].join('.')}"
|
357
|
+
skipdat = true
|
358
|
+
end
|
359
|
+
end
|
283
360
|
else
|
284
361
|
vtype = @api_map.infer_signature_type(vparts[1..-1].join('.'), fqns, scope: :class)
|
362
|
+
type = fqns
|
363
|
+
signature = parts[1..-1].join('.')
|
364
|
+
skipdat = true
|
285
365
|
end
|
286
|
-
|
287
|
-
|
288
|
-
|
366
|
+
unless skipdat
|
367
|
+
fqns = @api_map.find_fully_qualified_namespace(vtype, ns_here)
|
368
|
+
signature = parts[1..-1].join('.')
|
369
|
+
type = @api_map.infer_signature_type(signature, fqns, scope: :instance)
|
370
|
+
end
|
371
|
+
else
|
372
|
+
signature = signature.split('.')[1..-1].join('.')
|
289
373
|
end
|
290
374
|
unless type.nil?
|
291
375
|
lparts = signature.split('.')
|
292
|
-
if lparts.length
|
293
|
-
lsig =
|
376
|
+
if lparts.length >= 1
|
377
|
+
lsig = signature
|
294
378
|
ltype = @api_map.infer_signature_type(lsig, type, scope: :instance)
|
295
379
|
result.concat @api_map.get_instance_methods(ltype) unless ltype.nil?
|
296
380
|
else
|
@@ -454,5 +538,22 @@ module Solargraph
|
|
454
538
|
end
|
455
539
|
i
|
456
540
|
end
|
541
|
+
|
542
|
+
def signature_index_before index
|
543
|
+
open_parens = 0
|
544
|
+
cursor = index - 1
|
545
|
+
while cursor >= 0
|
546
|
+
break if cursor < 0
|
547
|
+
if @code[cursor] == ')'
|
548
|
+
open_parens -= 1
|
549
|
+
elsif @code[cursor] == '('
|
550
|
+
open_parens += 1
|
551
|
+
end
|
552
|
+
break if open_parens == 1
|
553
|
+
cursor -= 1
|
554
|
+
end
|
555
|
+
cursor = nil if cursor < 0
|
556
|
+
cursor
|
557
|
+
end
|
457
558
|
end
|
458
559
|
end
|
@@ -22,6 +22,44 @@ module Solargraph
|
|
22
22
|
parts
|
23
23
|
end
|
24
24
|
|
25
|
+
def const_from node
|
26
|
+
if node.kind_of?(AST::Node) and node.type == :const
|
27
|
+
result = ''
|
28
|
+
unless node.children[0].nil?
|
29
|
+
result = const_from(node.children[0])
|
30
|
+
end
|
31
|
+
if result == ''
|
32
|
+
result = node.children[1].to_s
|
33
|
+
else
|
34
|
+
result = result + '::' + node.children[1].to_s
|
35
|
+
end
|
36
|
+
result
|
37
|
+
else
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def drill_signature node, signature
|
43
|
+
return signature unless node.kind_of?(AST::Node)
|
44
|
+
if node.type == :const or node.type == :cbase
|
45
|
+
unless node.children[0].nil?
|
46
|
+
signature += drill_signature(node.children[0], signature)
|
47
|
+
end
|
48
|
+
signature += '::' unless signature.empty?
|
49
|
+
signature += node.children[1].to_s
|
50
|
+
elsif node.type == :lvar
|
51
|
+
signature += '.' unless signature.empty?
|
52
|
+
signature += node.children[0].to_s
|
53
|
+
elsif node.type == :send
|
54
|
+
unless node.children[0].nil?
|
55
|
+
signature += drill_signature(node.children[0], signature)
|
56
|
+
end
|
57
|
+
signature += '.' unless signature.empty?
|
58
|
+
signature += node.children[1].to_s
|
59
|
+
end
|
60
|
+
signature
|
61
|
+
end
|
62
|
+
|
25
63
|
def infer node
|
26
64
|
if node.type == :str
|
27
65
|
return 'String'
|
@@ -43,7 +81,8 @@ module Solargraph
|
|
43
81
|
#
|
44
82
|
# @return [String]
|
45
83
|
def resolve_node_signature node
|
46
|
-
stack_node_signature(node).join('.')
|
84
|
+
#stack_node_signature(node).join('.')
|
85
|
+
drill_signature node, ''
|
47
86
|
end
|
48
87
|
|
49
88
|
def stack_node_signature node
|
data/lib/solargraph/server.rb
CHANGED
@@ -24,7 +24,45 @@ module Solargraph
|
|
24
24
|
@@semaphore.synchronize {
|
25
25
|
code_map = CodeMap.new(code: params['text'], filename: params['filename'], api_map: @@api_hash[workspace])
|
26
26
|
offset = code_map.get_offset(params['line'].to_i, params['column'].to_i)
|
27
|
-
sugg = code_map.suggest_at(offset, with_snippets: params['with_snippets'] == '1' ? true : false
|
27
|
+
sugg = code_map.suggest_at(offset, with_snippets: params['with_snippets'] == '1' ? true : false)
|
28
|
+
}
|
29
|
+
{ "status" => "ok", "suggestions" => sugg }.to_json
|
30
|
+
rescue Exception => e
|
31
|
+
STDERR.puts e
|
32
|
+
STDERR.puts e.backtrace.join("\n")
|
33
|
+
{ "status" => "err", "message" => e.message + "\n" + e.backtrace.join("\n") }.to_json
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
post '/signify' do
|
38
|
+
content_type :json
|
39
|
+
begin
|
40
|
+
sugg = []
|
41
|
+
workspace = params['workspace'] || CodeMap.find_workspace(params['filename'])
|
42
|
+
Server.prepare_workspace workspace unless @@api_hash.has_key?(workspace)
|
43
|
+
@@semaphore.synchronize {
|
44
|
+
code_map = CodeMap.new(code: params['text'], filename: params['filename'], api_map: @@api_hash[workspace])
|
45
|
+
offset = code_map.get_offset(params['line'].to_i, params['column'].to_i)
|
46
|
+
sugg = code_map.signatures_at(offset)
|
47
|
+
}
|
48
|
+
{ "status" => "ok", "suggestions" => sugg }.to_json
|
49
|
+
rescue Exception => e
|
50
|
+
STDERR.puts e
|
51
|
+
STDERR.puts e.backtrace.join("\n")
|
52
|
+
{ "status" => "err", "message" => e.message + "\n" + e.backtrace.join("\n") }.to_json
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
post '/hover' do
|
57
|
+
content_type :json
|
58
|
+
begin
|
59
|
+
sugg = []
|
60
|
+
workspace = params['workspace'] || CodeMap.find_workspace(params['filename'])
|
61
|
+
Server.prepare_workspace workspace unless @@api_hash.has_key?(workspace)
|
62
|
+
@@semaphore.synchronize {
|
63
|
+
code_map = CodeMap.new(code: params['text'], filename: params['filename'], api_map: @@api_hash[workspace])
|
64
|
+
offset = code_map.get_offset(params['line'].to_i, params['column'].to_i)
|
65
|
+
sugg = code_map.resolve_object_at(offset)
|
28
66
|
}
|
29
67
|
{ "status" => "ok", "suggestions" => sugg }.to_json
|
30
68
|
rescue Exception => e
|
@@ -58,15 +96,22 @@ module Solargraph
|
|
58
96
|
erb :document
|
59
97
|
end
|
60
98
|
|
61
|
-
def htmlify
|
99
|
+
def htmlify text
|
100
|
+
rdoc_to_html text
|
101
|
+
end
|
102
|
+
|
103
|
+
def rdoc_to_html text
|
104
|
+
h = Helpers.new
|
105
|
+
h.html_markup_rdoc(text)
|
106
|
+
end
|
107
|
+
|
108
|
+
def ruby_to_html code
|
62
109
|
h = Helpers.new
|
63
|
-
h.
|
64
|
-
h.htmlify object.docstring.all, :rdoc
|
110
|
+
h.html_markup_ruby(code)
|
65
111
|
end
|
66
112
|
|
67
113
|
class << self
|
68
114
|
def run!
|
69
|
-
#constant_updates
|
70
115
|
super
|
71
116
|
end
|
72
117
|
|
@@ -75,22 +120,8 @@ module Solargraph
|
|
75
120
|
@@semaphore.synchronize {
|
76
121
|
@@api_hash[directory] = api_map
|
77
122
|
}
|
78
|
-
#Thread.new {
|
79
|
-
api_map.update_yardoc
|
80
|
-
#}
|
81
|
-
end
|
82
|
-
|
83
|
-
def constant_updates
|
84
123
|
Thread.new {
|
85
|
-
|
86
|
-
@@api_hash.keys.each { |k|
|
87
|
-
update = Solargraph::ApiMap.new(k)
|
88
|
-
@@semaphore.synchronize {
|
89
|
-
@@api_hash[k] = update
|
90
|
-
}
|
91
|
-
}
|
92
|
-
sleep 10
|
93
|
-
end
|
124
|
+
api_map.update_yardoc
|
94
125
|
}
|
95
126
|
end
|
96
127
|
end
|
data/lib/solargraph/shell.rb
CHANGED
@@ -75,7 +75,6 @@ module Solargraph
|
|
75
75
|
rescue Exception => e
|
76
76
|
STDERR.puts e
|
77
77
|
STDERR.puts e.backtrace.join("\n")
|
78
|
-
#result = { "status" => "err", "message" => e.message }.to_json
|
79
78
|
result = { "status" => "err", "message" => e.message + "\n" + e.backtrace.join("\n") }.to_json
|
80
79
|
STDOUT.puts result
|
81
80
|
end
|
@@ -10,9 +10,9 @@ module Solargraph
|
|
10
10
|
VARIABLE = 'Variable'
|
11
11
|
SNIPPET = 'Snippet'
|
12
12
|
|
13
|
-
attr_reader :label, :kind, :insert, :detail, :documentation, :code_object, :location
|
13
|
+
attr_reader :label, :kind, :insert, :detail, :documentation, :code_object, :location, :arguments
|
14
14
|
|
15
|
-
def initialize label, kind: KEYWORD, insert: nil, detail: nil, documentation: nil, code_object: nil, location: nil
|
15
|
+
def initialize label, kind: KEYWORD, insert: nil, detail: nil, documentation: nil, code_object: nil, location: nil, arguments: []
|
16
16
|
@label = label.to_s
|
17
17
|
@kind = kind
|
18
18
|
@insert = insert || @label
|
@@ -20,6 +20,7 @@ module Solargraph
|
|
20
20
|
@code_object = code_object
|
21
21
|
@documentation = documentation
|
22
22
|
@location = location
|
23
|
+
@arguments = arguments
|
23
24
|
end
|
24
25
|
|
25
26
|
def path
|
@@ -55,12 +56,13 @@ module Solargraph
|
|
55
56
|
insert: @insert,
|
56
57
|
detail: @detail,
|
57
58
|
path: path,
|
58
|
-
location: (@location.nil? ? nil : @location.to_s)
|
59
|
+
location: (@location.nil? ? nil : @location.to_s),
|
60
|
+
arguments: @arguments
|
59
61
|
}
|
60
62
|
if @code_object.nil?
|
61
|
-
obj[:documentation] = @documentation.
|
63
|
+
obj[:documentation] = @documentation.to_s unless @documentation.nil?
|
62
64
|
else
|
63
|
-
obj[:documentation] = @code_object.docstring.
|
65
|
+
obj[:documentation] = @code_object.docstring.to_s unless @code_object.docstring.nil?
|
64
66
|
end
|
65
67
|
obj.to_json(args)
|
66
68
|
end
|
data/lib/solargraph/version.rb
CHANGED
data/lib/solargraph/yard_map.rb
CHANGED
@@ -11,8 +11,6 @@ module Solargraph
|
|
11
11
|
unless workspace.nil?
|
12
12
|
wsy = File.join(workspace, '.yardoc')
|
13
13
|
yardocs.push wsy if File.exist?(wsy)
|
14
|
-
#wsy = Dir[File.join workspace, '**/*.rb']
|
15
|
-
#yardocs.push(wsy)
|
16
14
|
end
|
17
15
|
used = []
|
18
16
|
required.each { |r|
|
@@ -29,16 +27,7 @@ module Solargraph
|
|
29
27
|
end
|
30
28
|
end
|
31
29
|
}
|
32
|
-
# TODO: Experimental loading of all gems
|
33
|
-
#Bundler.load.specs.each { |s|
|
34
|
-
# unless used.include?(s.name)
|
35
|
-
# used.push s.name
|
36
|
-
# gy = YARD::Registry.yardoc_file_for_gem(s.name)
|
37
|
-
# yardocs.push gy unless gy.nil?
|
38
|
-
# end
|
39
|
-
#}
|
40
30
|
yardocs.push File.join(Dir.home, '.solargraph', 'cache', '2.0.0', 'yardoc')
|
41
|
-
#yardocs.push File.join(Dir.home, '.solargraph', 'cache', '2.0.0', 'yardoc-stdlib')
|
42
31
|
yardocs.uniq!
|
43
32
|
cache_core
|
44
33
|
end
|
@@ -159,8 +148,7 @@ module Solargraph
|
|
159
148
|
n = m.to_s.split(/[\.#]/).last.gsub(/=/, ' = ')
|
160
149
|
label = "#{n}"
|
161
150
|
args = get_method_args(m)
|
162
|
-
label
|
163
|
-
meths.push Suggestion.new(label, insert: "#{n.gsub(/=/, ' = ')}", kind: Suggestion::METHOD, documentation: m.docstring, code_object: m, detail: "#{ns}", location: "#{m.file}:#{m.line}")
|
151
|
+
meths.push Suggestion.new(label, insert: "#{n.gsub(/=/, ' = ')}", kind: Suggestion::METHOD, documentation: m.docstring, code_object: m, detail: "#{ns}", location: "#{m.file}:#{m.line}", arguments: args)
|
164
152
|
}
|
165
153
|
# Collect superclass methods
|
166
154
|
if ns.kind_of?(YARD::CodeObjects::ClassObject) and !ns.superclass.nil?
|
@@ -168,6 +156,14 @@ module Solargraph
|
|
168
156
|
end
|
169
157
|
if ns.kind_of?(YARD::CodeObjects::ClassObject) and namespace != 'Class'
|
170
158
|
meths += get_instance_methods('Class')
|
159
|
+
yard = load_yardoc(y)
|
160
|
+
i = yard.at("#{ns}#initialize")
|
161
|
+
unless i.nil?
|
162
|
+
meths.delete_if{|m| m.label == 'new'}
|
163
|
+
label = "#{i}"
|
164
|
+
args = get_method_args(i)
|
165
|
+
meths.push Suggestion.new('new', kind: Suggestion::METHOD, documentation: i.docstring, code_object: i, detail: "#{ns}", location: "#{i.file}:#{i.line}", arguments: args)
|
166
|
+
end
|
171
167
|
end
|
172
168
|
end
|
173
169
|
end
|
@@ -195,8 +191,7 @@ module Solargraph
|
|
195
191
|
if n.to_s.match(/^[a-z]/i) and (namespace == 'Kernel' or !m.to_s.start_with?('Kernel#')) and !m.docstring.to_s.include?(':nodoc:')
|
196
192
|
label = "#{n}"
|
197
193
|
args = get_method_args(m)
|
198
|
-
label
|
199
|
-
meths.push Suggestion.new(label, insert: "#{n.gsub(/=/, ' = ')}", kind: Suggestion::METHOD, documentation: m.docstring, code_object: m, detail: "#{ns}", location: "#{m.file}:#{m.line}")
|
194
|
+
meths.push Suggestion.new(label, insert: "#{n.gsub(/=/, ' = ')}", kind: Suggestion::METHOD, documentation: m.docstring, code_object: m, detail: m.namespace, location: "#{m.file}:#{m.line}", arguments: args)
|
200
195
|
end
|
201
196
|
}
|
202
197
|
if ns.kind_of?(YARD::CodeObjects::ClassObject) and namespace != 'Object'
|
@@ -226,6 +221,35 @@ module Solargraph
|
|
226
221
|
nil
|
227
222
|
end
|
228
223
|
|
224
|
+
def objects path, space = ''
|
225
|
+
result = []
|
226
|
+
yardocs.each { |y|
|
227
|
+
yard = load_yardoc(y)
|
228
|
+
unless yard.nil?
|
229
|
+
obj = find_first_resolved_namespace(yard, path, space)
|
230
|
+
if obj.nil? and path.include?('#')
|
231
|
+
parts = path.split('#')
|
232
|
+
obj = yard.at(parts[0])
|
233
|
+
unless obj.nil?
|
234
|
+
meths = obj.meths(scope: [:instance]).keep_if{|m| m.name.to_s == parts[1]}
|
235
|
+
meths.each { |m|
|
236
|
+
args = get_method_args(m)
|
237
|
+
result.push Solargraph::Suggestion.new(m.name, kind: 'Method', detail: m.path, code_object: m, arguments: args)
|
238
|
+
}
|
239
|
+
end
|
240
|
+
else
|
241
|
+
unless obj.nil?
|
242
|
+
args = []
|
243
|
+
args = get_method_args(obj) if obj.kind_of?(YARD::CodeObjects::MethodObject)
|
244
|
+
kind = kind_of_object(obj)
|
245
|
+
result.push Solargraph::Suggestion.new(obj.name, kind: kind, detail: obj.path, code_object: obj, arguments: args)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
}
|
250
|
+
result
|
251
|
+
end
|
252
|
+
|
229
253
|
private
|
230
254
|
|
231
255
|
def cache
|
@@ -257,10 +281,18 @@ module Solargraph
|
|
257
281
|
|
258
282
|
def cache_core
|
259
283
|
c = get_constants '', ''
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
284
|
+
end
|
285
|
+
|
286
|
+
def kind_of_object obj
|
287
|
+
if obj.kind_of?(YARD::CodeObjects::MethodObject)
|
288
|
+
'Method'
|
289
|
+
elsif obj.kind_of?(YARD::CodeObjects::ClassObject)
|
290
|
+
'Class'
|
291
|
+
elsif obj.kind_of?(YARD::CodeObjects::ModuleObject)
|
292
|
+
'Module'
|
293
|
+
else
|
294
|
+
nil
|
295
|
+
end
|
264
296
|
end
|
265
297
|
end
|
266
298
|
|
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.8.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-05-
|
11
|
+
date: 2017-05-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parser
|