solargraph 0.11.2 → 0.12.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/attr_pin.rb +37 -0
- data/lib/solargraph/api_map/config.rb +1 -1
- data/lib/solargraph/api_map/cvar_pin.rb +26 -0
- data/lib/solargraph/api_map/ivar_pin.rb +28 -0
- data/lib/solargraph/api_map/method_pin.rb +56 -0
- data/lib/solargraph/api_map.rb +145 -186
- data/lib/solargraph/code_map.rb +116 -87
- data/lib/solargraph/node_methods.rb +1 -1
- data/lib/solargraph/server.rb +15 -8
- data/lib/solargraph/shell.rb +2 -1
- data/lib/solargraph/suggestion.rb +5 -10
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/yard_map.rb +1 -20
- metadata +14 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9a0cb900eab77f94ad22582f22dc8ea75c249485
|
4
|
+
data.tar.gz: 478c5f05faf26850590f928060b35e61903cb807
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: afcd662f413015ece4a315039be1837a8f95b1a10806d75e6ac2ce8d08fa91d3e0720cd67aa1c383f34c6800f5d2c9a3a722c199a093663f6aefec0e93d92480
|
7
|
+
data.tar.gz: 9d9dacf3f53e4a53f69f325e9bd56d42d252cba529a91766515c2e3b9080403bd20f8dbdc801168a5b72164e12f02700b4bdc960845abb2706456391c9214e6a
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Solargraph
|
2
|
+
class ApiMap
|
3
|
+
class AttrPin
|
4
|
+
attr_reader :node
|
5
|
+
|
6
|
+
def initialize node
|
7
|
+
@node = node
|
8
|
+
end
|
9
|
+
|
10
|
+
def suggestions
|
11
|
+
@suggestions ||= generate_suggestions
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def generate_suggestions
|
17
|
+
suggestions = []
|
18
|
+
c = node
|
19
|
+
if c.kind_of?(AST::Node) and c.type == :send and c.children[1] == :attr_reader
|
20
|
+
c.children[2..-1].each { |x|
|
21
|
+
suggestions.push Suggestion.new(x.children[0], kind: Suggestion::FIELD) if x.type == :sym
|
22
|
+
}
|
23
|
+
elsif c.kind_of?(AST::Node) and c.type == :send and c.children[1] == :attr_writer
|
24
|
+
c.children[2..-1].each { |x|
|
25
|
+
suggestions.push Suggestion.new("#{x.children[0]}=", kind: Suggestion::FIELD) if x.type == :sym
|
26
|
+
}
|
27
|
+
elsif c.kind_of?(AST::Node) and c.type == :send and c.children[1] == :attr_accessor
|
28
|
+
c.children[2..-1].each { |x|
|
29
|
+
suggestions.push Suggestion.new(x.children[0], kind: Suggestion::FIELD) if x.type == :sym
|
30
|
+
suggestions.push Suggestion.new("#{x.children[0]}=", insert: "#{x.children[0]} = ", kind: Suggestion::FIELD) if x.type == :sym
|
31
|
+
}
|
32
|
+
end
|
33
|
+
suggestions
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -12,7 +12,7 @@ module Solargraph
|
|
12
12
|
@included = []
|
13
13
|
@excluded = []
|
14
14
|
include_globs = ['**/*.rb']
|
15
|
-
exclude_globs = ['spec/**/*']
|
15
|
+
exclude_globs = ['spec/**/*', 'test/**/*']
|
16
16
|
unless @workspace.nil?
|
17
17
|
sfile = File.join(@workspace, '.solargraph.yml')
|
18
18
|
if File.file?(sfile)
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Solargraph
|
2
|
+
class ApiMap
|
3
|
+
class CvarPin
|
4
|
+
attr_reader :node
|
5
|
+
attr_reader :namespace
|
6
|
+
attr_reader :docstring
|
7
|
+
|
8
|
+
def initialize node, namespace, docstring
|
9
|
+
@node = node
|
10
|
+
@namespace = namespace
|
11
|
+
@docstring = docstring
|
12
|
+
end
|
13
|
+
|
14
|
+
def suggestion(api_map)
|
15
|
+
@suggestion ||= generate_suggestion(api_map)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def generate_suggestion(api_map)
|
21
|
+
type = api_map.infer_assignment_node_type(node, namespace)
|
22
|
+
Suggestion.new(node.children[0], kind: Suggestion::VARIABLE, documentation: docstring, return_type: type)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Solargraph
|
2
|
+
class ApiMap
|
3
|
+
class IvarPin
|
4
|
+
attr_reader :node
|
5
|
+
attr_reader :namespace
|
6
|
+
attr_reader :scope
|
7
|
+
attr_reader :docstring
|
8
|
+
|
9
|
+
def initialize node, namespace, scope, docstring
|
10
|
+
@node = node
|
11
|
+
@namespace = namespace
|
12
|
+
@scope = scope
|
13
|
+
@docstring = docstring
|
14
|
+
end
|
15
|
+
|
16
|
+
def suggestion(api_map)
|
17
|
+
@suggestion ||= generate_suggestion(api_map)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def generate_suggestion(api_map)
|
23
|
+
type = api_map.infer_assignment_node_type(node, namespace)
|
24
|
+
Suggestion.new(node.children[0], kind: Suggestion::VARIABLE, documentation: docstring, return_type: type)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Solargraph
|
2
|
+
class ApiMap
|
3
|
+
class MethodPin
|
4
|
+
attr_reader :node
|
5
|
+
attr_reader :namespace
|
6
|
+
attr_reader :scope
|
7
|
+
attr_reader :visibility
|
8
|
+
attr_reader :docstring
|
9
|
+
|
10
|
+
def initialize node, namespace, scope, visibility, docstring
|
11
|
+
@node = node
|
12
|
+
@namespace = namespace
|
13
|
+
@scope = scope
|
14
|
+
@visibility = visibility
|
15
|
+
@docstring = docstring
|
16
|
+
end
|
17
|
+
|
18
|
+
def suggestion(api_map)
|
19
|
+
@suggestion ||= generate_suggestion(api_map)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def generate_suggestion(api_map)
|
25
|
+
i = node.type == :def ? 0 : 1
|
26
|
+
label = "#{node.children[i]}"
|
27
|
+
Suggestion.new(label, insert: node.children[i].to_s.gsub(/=/, ' = '), kind: Suggestion::METHOD, documentation: docstring, detail: namespace, arguments: get_method_args(api_map))
|
28
|
+
end
|
29
|
+
|
30
|
+
# @return [Array<String>]
|
31
|
+
def get_method_args(api_map)
|
32
|
+
list = nil
|
33
|
+
args = []
|
34
|
+
node.children.each { |c|
|
35
|
+
if c.kind_of?(AST::Node) and c.type == :args
|
36
|
+
list = c
|
37
|
+
break
|
38
|
+
end
|
39
|
+
}
|
40
|
+
return args if list.nil?
|
41
|
+
list.children.each { |c|
|
42
|
+
if c.type == :arg
|
43
|
+
args.push c.children[0].to_s
|
44
|
+
elsif c.type == :optarg
|
45
|
+
args.push "#{c.children[0]} = #{api_map.code_for(c.children[1])}"
|
46
|
+
elsif c.type == :kwarg
|
47
|
+
args.push "#{c.children[0]}:"
|
48
|
+
elsif c.type == :kwoptarg
|
49
|
+
args.push "#{c.children[0]}: #{api_map.code_for(c.children[1])}"
|
50
|
+
end
|
51
|
+
}
|
52
|
+
args
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/solargraph/api_map.rb
CHANGED
@@ -1,10 +1,18 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'parser/current'
|
3
|
+
require 'thread'
|
3
4
|
|
4
5
|
module Solargraph
|
5
6
|
class ApiMap
|
6
7
|
autoload :Config, 'solargraph/api_map/config'
|
7
8
|
autoload :Cache, 'solargraph/api_map/cache'
|
9
|
+
autoload :MethodPin, 'solargraph/api_map/method_pin'
|
10
|
+
autoload :AttrPin, 'solargraph/api_map/attr_pin'
|
11
|
+
autoload :IvarPin, 'solargraph/api_map/ivar_pin'
|
12
|
+
autoload :CvarPin, 'solargraph/api_map/cvar_pin'
|
13
|
+
|
14
|
+
@@yard_map_cache = {}
|
15
|
+
@@semaphore = Mutex.new
|
8
16
|
|
9
17
|
KEYWORDS = [
|
10
18
|
'__ENCODING__', '__LINE__', '__FILE__', 'BEGIN', 'END', 'alias', 'and',
|
@@ -15,9 +23,9 @@ module Solargraph
|
|
15
23
|
].freeze
|
16
24
|
|
17
25
|
MAPPABLE_NODES = [
|
18
|
-
:array, :hash, :str, :int, :float, :block, :class, :sclass,
|
19
|
-
:def, :defs, :ivasgn, :gvasgn, :lvasgn, :cvasgn, :casgn,
|
20
|
-
:const, :lvar, :args, :kwargs
|
26
|
+
:array, :hash, :str, :dstr, :int, :float, :block, :class, :sclass,
|
27
|
+
:module, :def, :defs, :ivasgn, :gvasgn, :lvasgn, :cvasgn, :casgn,
|
28
|
+
:or_asgn, :const, :lvar, :args, :kwargs
|
21
29
|
].freeze
|
22
30
|
|
23
31
|
MAPPABLE_METHODS = [
|
@@ -57,7 +65,10 @@ module Solargraph
|
|
57
65
|
|
58
66
|
# @return [Solargraph::YardMap]
|
59
67
|
def yard_map
|
60
|
-
|
68
|
+
@@semaphore.synchronize {
|
69
|
+
@yard_map ||= @@yard_map_cache[[required, workspace]] || Solargraph::YardMap.new(required: required, workspace: workspace)
|
70
|
+
@@yard_map_cache[[required, workspace]] ||= @yard_map
|
71
|
+
}
|
61
72
|
end
|
62
73
|
|
63
74
|
# Add a file to the map.
|
@@ -88,16 +99,21 @@ module Solargraph
|
|
88
99
|
#
|
89
100
|
# @return [AST::Node]
|
90
101
|
def append_node node, comments, filename = nil
|
102
|
+
@stale = true
|
91
103
|
@file_comments[filename] = associate_comments(node, comments)
|
92
104
|
mapified = reduce(node, @file_comments[filename])
|
93
105
|
root = AST::Node.new(:begin, [filename])
|
94
106
|
root = root.append mapified
|
95
107
|
@file_nodes[filename] = root
|
96
108
|
@required.uniq!
|
97
|
-
process_maps
|
109
|
+
#process_maps
|
98
110
|
root
|
99
111
|
end
|
100
112
|
|
113
|
+
def refresh force = false
|
114
|
+
process_maps if @stale or force
|
115
|
+
end
|
116
|
+
|
101
117
|
# Get the docstring associated with a node.
|
102
118
|
#
|
103
119
|
# @param node [AST::Node]
|
@@ -116,6 +132,7 @@ module Solargraph
|
|
116
132
|
end
|
117
133
|
|
118
134
|
def namespaces
|
135
|
+
refresh
|
119
136
|
@namespace_map.keys
|
120
137
|
end
|
121
138
|
|
@@ -124,6 +141,7 @@ module Solargraph
|
|
124
141
|
end
|
125
142
|
|
126
143
|
def namespaces_in name, root = ''
|
144
|
+
refresh
|
127
145
|
result = []
|
128
146
|
result += inner_namespaces_in(name, root, [])
|
129
147
|
result += yard_map.get_constants name, root
|
@@ -138,6 +156,7 @@ module Solargraph
|
|
138
156
|
end
|
139
157
|
|
140
158
|
def find_fully_qualified_namespace name, root = '', skip = []
|
159
|
+
refresh
|
141
160
|
return nil if skip.include?(root)
|
142
161
|
skip.push root
|
143
162
|
if name == ''
|
@@ -173,25 +192,32 @@ module Solargraph
|
|
173
192
|
|
174
193
|
def get_namespace_nodes(fqns)
|
175
194
|
return @file_nodes.values if fqns == '' or fqns.nil?
|
195
|
+
refresh
|
176
196
|
@namespace_map[fqns] || []
|
177
197
|
end
|
178
198
|
|
179
199
|
def get_instance_variables(namespace, scope = :instance)
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
200
|
+
refresh
|
201
|
+
result = []
|
202
|
+
ip = @ivar_pins[namespace]
|
203
|
+
unless ip.nil?
|
204
|
+
ip.select{ |pin| pin.scope == scope }.each do |pin|
|
205
|
+
result.push pin.suggestion(self)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
result
|
186
209
|
end
|
187
210
|
|
188
211
|
def get_class_variables(namespace)
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
212
|
+
refresh
|
213
|
+
result = []
|
214
|
+
ip = @cvar_pins[namespace]
|
215
|
+
unless ip.nil?
|
216
|
+
ip.each do |pin|
|
217
|
+
result.push pin.suggestion(self)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
result
|
195
221
|
end
|
196
222
|
|
197
223
|
def find_parent(node, *types)
|
@@ -388,6 +414,7 @@ module Solargraph
|
|
388
414
|
#
|
389
415
|
# @return [Array<Solargraph::Suggestion>]
|
390
416
|
def get_methods(namespace, root = '', visibility: [:public])
|
417
|
+
refresh
|
391
418
|
namespace = clean_namespace_string(namespace)
|
392
419
|
meths = []
|
393
420
|
meths += inner_get_methods(namespace, root, []) #unless has_yardoc?
|
@@ -405,36 +432,12 @@ module Solargraph
|
|
405
432
|
end
|
406
433
|
end
|
407
434
|
|
408
|
-
# @return [Array<String>]
|
409
|
-
def get_method_args node
|
410
|
-
list = nil
|
411
|
-
args = []
|
412
|
-
node.children.each { |c|
|
413
|
-
if c.kind_of?(AST::Node) and c.type == :args
|
414
|
-
list = c
|
415
|
-
break
|
416
|
-
end
|
417
|
-
}
|
418
|
-
return args if list.nil?
|
419
|
-
list.children.each { |c|
|
420
|
-
if c.type == :arg
|
421
|
-
args.push c.children[0]
|
422
|
-
elsif c.type == :optarg
|
423
|
-
args.push "#{c.children[0]} = #{code_for(c.children[1])}"
|
424
|
-
elsif c.type == :kwarg
|
425
|
-
args.push "#{c.children[0]}:"
|
426
|
-
elsif c.type == :kwoptarg
|
427
|
-
args.push "#{c.children[0]}: #{code_for(c.children[1])}"
|
428
|
-
end
|
429
|
-
}
|
430
|
-
args
|
431
|
-
end
|
432
|
-
|
433
435
|
# Get an array of instance methods that are available in the specified
|
434
436
|
# namespace.
|
435
437
|
#
|
436
438
|
# @return [Array<Solargraph::Suggestion>]
|
437
439
|
def get_instance_methods(namespace, root = '', visibility: [:public])
|
440
|
+
refresh
|
438
441
|
namespace = clean_namespace_string(namespace)
|
439
442
|
if namespace.end_with?('#class')
|
440
443
|
return get_methods(namespace.split('#').first, root, visibility: visibility)
|
@@ -468,7 +471,7 @@ module Solargraph
|
|
468
471
|
}
|
469
472
|
return nil
|
470
473
|
end
|
471
|
-
|
474
|
+
|
472
475
|
def self.current
|
473
476
|
if @current.nil?
|
474
477
|
@current = ApiMap.new
|
@@ -476,7 +479,7 @@ module Solargraph
|
|
476
479
|
end
|
477
480
|
@current
|
478
481
|
end
|
479
|
-
|
482
|
+
|
480
483
|
def get_include_strings_from *nodes
|
481
484
|
arr = []
|
482
485
|
nodes.each { |node|
|
@@ -488,7 +491,15 @@ module Solargraph
|
|
488
491
|
}
|
489
492
|
arr
|
490
493
|
end
|
491
|
-
|
494
|
+
|
495
|
+
def code_for node
|
496
|
+
src = @file_source[get_filename_for(node)]
|
497
|
+
return nil if src.nil?
|
498
|
+
b = node.location.expression.begin.begin_pos
|
499
|
+
e = node.location.expression.end.end_pos
|
500
|
+
src[b..e].strip.gsub(/,$/, '')
|
501
|
+
end
|
502
|
+
|
492
503
|
# Update the YARD documentation for the current workspace.
|
493
504
|
#
|
494
505
|
def update_yardoc
|
@@ -504,12 +515,16 @@ module Solargraph
|
|
504
515
|
STDERR.puts "There was an error processing the workspace yardoc."
|
505
516
|
end
|
506
517
|
end
|
507
|
-
|
518
|
+
@@semaphore.synchronize {
|
519
|
+
@@yard_map_cache.clear
|
520
|
+
}
|
521
|
+
end
|
508
522
|
end
|
509
523
|
|
510
524
|
private
|
511
525
|
|
512
526
|
def clear
|
527
|
+
@stale = false
|
513
528
|
@file_source = {}
|
514
529
|
@file_nodes = {}
|
515
530
|
@file_comments = {}
|
@@ -517,6 +532,12 @@ module Solargraph
|
|
517
532
|
@namespace_map = {}
|
518
533
|
@namespace_tree = {}
|
519
534
|
@required = []
|
535
|
+
@ivar_pins = {}
|
536
|
+
@cvar_pins = {}
|
537
|
+
@method_pins = {}
|
538
|
+
@attr_nodes = {}
|
539
|
+
@namespace_includes = {}
|
540
|
+
@superclasses = {}
|
520
541
|
end
|
521
542
|
|
522
543
|
def process_maps
|
@@ -527,6 +548,7 @@ module Solargraph
|
|
527
548
|
map_parents f
|
528
549
|
map_namespaces f
|
529
550
|
}
|
551
|
+
@stale = false
|
530
552
|
end
|
531
553
|
|
532
554
|
# @return [Solargraph::ApiMap::Cache]
|
@@ -566,109 +588,42 @@ module Solargraph
|
|
566
588
|
skip.push namespace
|
567
589
|
fqns = find_fully_qualified_namespace(namespace, root)
|
568
590
|
return meths if fqns.nil?
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
if n.type == :class and !n.children[1].nil?
|
574
|
-
s = unpack_name(n.children[1])
|
575
|
-
meths += inner_get_methods(s, root, skip)
|
576
|
-
end
|
577
|
-
vis = [:public]
|
578
|
-
vis.push :private, :protected if namespace == root
|
579
|
-
meths += inner_get_methods_from_node(n, root, :class, skip, vis)
|
580
|
-
end
|
591
|
+
mn = @method_pins[fqns]
|
592
|
+
unless mn.nil?
|
593
|
+
mn.select{ |pin| pin.scope == :class }.each do |pin|
|
594
|
+
meths.push pin.suggestion(self)
|
581
595
|
end
|
582
|
-
|
596
|
+
end
|
583
597
|
meths.uniq
|
584
598
|
end
|
585
599
|
|
586
|
-
def inner_get_methods_from_node node, root, scope, skip, visibility, current_visibility = :public
|
587
|
-
meths = []
|
588
|
-
node.children.each { |c|
|
589
|
-
if c.kind_of?(AST::Node)
|
590
|
-
if c.kind_of?(AST::Node) and c.type == :send and [:public, :protected, :private].include?(c.children[1])
|
591
|
-
current_visibility = c.children[1]
|
592
|
-
elsif (c.type == :defs and scope == :class) or (c.type == :def and scope == :instance)
|
593
|
-
next unless visibility.include?(current_visibility)
|
594
|
-
docstring = get_comment_for(c)
|
595
|
-
child_index = (scope == :class ? 1 : 0)
|
596
|
-
label = "#{c.children[child_index]}"
|
597
|
-
args = get_method_args(c)
|
598
|
-
if (c.children[child_index].to_s[0].match(/[a-z_]/i) and c.children[child_index] != :def)
|
599
|
-
meths.push Suggestion.new(label, insert: c.children[child_index].to_s.gsub(/=/, ' = '), kind: Suggestion::METHOD, detail: 'Method', documentation: docstring, arguments: args)
|
600
|
-
end
|
601
|
-
elsif c.type == :sclass and scope == :class and c.children[0].type == :self
|
602
|
-
meths.concat inner_get_methods_from_node c, root, :instance, skip, visibility
|
603
|
-
elsif c.type == :send and c.children[1] == :include
|
604
|
-
# TODO: This might not be right. Should we be getting singleton methods
|
605
|
-
# from an include, or only from an extend?
|
606
|
-
i = unpack_name(c.children[2])
|
607
|
-
meths.concat inner_get_methods(i, root, skip) unless i == 'Kernel'
|
608
|
-
else
|
609
|
-
meths.concat inner_get_methods_from_node(c, root, scope, skip, visibility, current_visibility)
|
610
|
-
end
|
611
|
-
end
|
612
|
-
}
|
613
|
-
meths
|
614
|
-
end
|
615
|
-
|
616
600
|
def inner_get_instance_methods(namespace, root, skip, visibility = [:public])
|
617
601
|
fqns = find_fully_qualified_namespace(namespace, root)
|
618
602
|
meths = []
|
619
603
|
return meths if skip.include?(fqns)
|
620
604
|
skip.push fqns
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
unless yardoc_has_file?(get_filename_for(n))
|
626
|
-
if n.kind_of?(AST::Node)
|
627
|
-
if n.type == :class and !n.children[1].nil?
|
628
|
-
s = unpack_name(n.children[1])
|
629
|
-
# @todo This skip might not work properly. We might need to get a
|
630
|
-
# fully qualified namespace from it first
|
631
|
-
meths += get_instance_methods(s, namespace, visibility: visibility - [:private]) unless skip.include?(s)
|
632
|
-
end
|
633
|
-
n.children.each { |c|
|
634
|
-
if c.kind_of?(AST::Node) and c.type == :send and [:public, :protected, :private].include?(c.children[1])
|
635
|
-
current_scope = c.children[1]
|
636
|
-
elsif c.kind_of?(AST::Node) and c.type == :send and c.children[1] == :include and n.type == :class
|
637
|
-
fqmod = find_fully_qualified_namespace(const_from(c.children[2]), root)
|
638
|
-
meths += get_instance_methods(fqmod) unless fqmod.nil? or skip.include?(fqmod)
|
639
|
-
else
|
640
|
-
if c.kind_of?(AST::Node) and c.type == :def
|
641
|
-
if visibility.include?(current_scope)
|
642
|
-
cmnt = get_comment_for(c)
|
643
|
-
label = "#{c.children[0]}"
|
644
|
-
args = get_method_args(c)
|
645
|
-
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)
|
646
|
-
end
|
647
|
-
elsif c.kind_of?(AST::Node) and c.type == :send and c.children[1] == :attr_reader
|
648
|
-
c.children[2..-1].each { |x|
|
649
|
-
meths.push Suggestion.new(x.children[0], kind: Suggestion::FIELD) if x.type == :sym
|
650
|
-
}
|
651
|
-
elsif c.kind_of?(AST::Node) and c.type == :send and c.children[1] == :attr_writer
|
652
|
-
c.children[2..-1].each { |x|
|
653
|
-
meths.push Suggestion.new("#{x.children[0]}=", kind: Suggestion::FIELD) if x.type == :sym
|
654
|
-
}
|
655
|
-
elsif c.kind_of?(AST::Node) and c.type == :send and c.children[1] == :attr_accessor
|
656
|
-
c.children[2..-1].each { |x|
|
657
|
-
meths.push Suggestion.new(x.children[0], kind: Suggestion::FIELD) if x.type == :sym
|
658
|
-
meths.push Suggestion.new("#{x.children[0]}=", insert: "#{x.children[0]} = ", kind: Suggestion::FIELD) if x.type == :sym
|
659
|
-
}
|
660
|
-
end
|
661
|
-
end
|
662
|
-
}
|
663
|
-
end
|
605
|
+
an = @attr_nodes[fqns]
|
606
|
+
unless an.nil?
|
607
|
+
an.each do |pin|
|
608
|
+
meths.concat pin.suggestions
|
664
609
|
end
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
610
|
+
end
|
611
|
+
mn = @method_pins[fqns]
|
612
|
+
unless mn.nil?
|
613
|
+
mn.select{|pin| visibility.include?(pin.visibility) and pin.scope == :instance }.each do |pin|
|
614
|
+
meths.push pin.suggestion(self)
|
670
615
|
end
|
671
|
-
|
616
|
+
end
|
617
|
+
if visibility.include?(:public) or visibility.include?(:protected)
|
618
|
+
sc = @superclasses[fqns]
|
619
|
+
meths.concat inner_get_instance_methods(sc, fqns, skip, visibility - [:private]) unless sc.nil?
|
620
|
+
end
|
621
|
+
im = @namespace_includes[fqns]
|
622
|
+
unless im.nil?
|
623
|
+
im.each do |i|
|
624
|
+
meths.concat inner_get_instance_methods(i, fqns, skip, visibility)
|
625
|
+
end
|
626
|
+
end
|
672
627
|
meths.uniq
|
673
628
|
end
|
674
629
|
|
@@ -728,38 +683,6 @@ module Solargraph
|
|
728
683
|
result
|
729
684
|
end
|
730
685
|
|
731
|
-
def inner_get_instance_variables(node, namespace, scope)
|
732
|
-
arr = []
|
733
|
-
if node.kind_of?(AST::Node)
|
734
|
-
node.children.each { |c|
|
735
|
-
if c.kind_of?(AST::Node)
|
736
|
-
is_inst = !find_parent(c, :def).nil?
|
737
|
-
if c.type == :ivasgn and c.children[0] and ( (scope == :instance and is_inst) or (scope != :instance and !is_inst) )
|
738
|
-
type = infer_assignment_node_type(c, namespace)
|
739
|
-
arr.push Suggestion.new(c.children[0], kind: Suggestion::VARIABLE, documentation: get_comment_for(c), return_type: type)
|
740
|
-
end
|
741
|
-
arr += inner_get_instance_variables(c, namespace, scope) unless [:class, :module].include?(c.type)
|
742
|
-
end
|
743
|
-
}
|
744
|
-
end
|
745
|
-
arr
|
746
|
-
end
|
747
|
-
|
748
|
-
def inner_get_class_variables(node, namespace)
|
749
|
-
arr = []
|
750
|
-
if node.kind_of?(AST::Node)
|
751
|
-
node.children.each { |c|
|
752
|
-
next unless c.kind_of?(AST::Node)
|
753
|
-
if c.type == :cvasgn
|
754
|
-
type = infer_assignment_node_type(c, namespace)
|
755
|
-
arr.push Suggestion.new(c.children[0], kind: Suggestion::VARIABLE, documentation: get_comment_for(c), return_type: type)
|
756
|
-
end
|
757
|
-
arr += inner_get_class_variables(c, namespace) unless [:class, :module].include?(c.type)
|
758
|
-
}
|
759
|
-
end
|
760
|
-
arr
|
761
|
-
end
|
762
|
-
|
763
686
|
# Get a fully qualified namespace for the given signature.
|
764
687
|
# The signature should be in the form of a method chain, e.g.,
|
765
688
|
# method1.method2
|
@@ -864,7 +787,7 @@ module Solargraph
|
|
864
787
|
result = node.updated nil, mappable
|
865
788
|
result
|
866
789
|
end
|
867
|
-
|
790
|
+
|
868
791
|
def get_mappable_nodes arr, comment_hash
|
869
792
|
result = []
|
870
793
|
arr.each { |n|
|
@@ -878,7 +801,7 @@ module Solargraph
|
|
878
801
|
}
|
879
802
|
result
|
880
803
|
end
|
881
|
-
|
804
|
+
|
882
805
|
def minify node, comment_hash
|
883
806
|
return node if node.type == :args
|
884
807
|
type = node.type
|
@@ -917,7 +840,7 @@ module Solargraph
|
|
917
840
|
# TODO: The api_map should ignore local variables.
|
918
841
|
type = node.children[0].type
|
919
842
|
children.push node.children[0].children[0], node.children[1]
|
920
|
-
elsif [:array, :hash, :str, :int, :float].include?(node.type)
|
843
|
+
elsif [:array, :hash, :str, :dstr, :int, :float].include?(node.type)
|
921
844
|
# @todo Do we really care about the details?
|
922
845
|
end
|
923
846
|
result = node.updated(type, children)
|
@@ -939,7 +862,7 @@ module Solargraph
|
|
939
862
|
}
|
940
863
|
end
|
941
864
|
end
|
942
|
-
|
865
|
+
|
943
866
|
def add_to_namespace_tree tree
|
944
867
|
cursor = @namespace_tree
|
945
868
|
tree.each { |t|
|
@@ -948,9 +871,11 @@ module Solargraph
|
|
948
871
|
}
|
949
872
|
end
|
950
873
|
|
951
|
-
def map_namespaces node, tree = []
|
874
|
+
def map_namespaces node, tree = [], visibility = :public, scope = :instance, fqn = nil, local_scope = :class
|
952
875
|
if node.kind_of?(AST::Node)
|
876
|
+
return if node.type == :str or node.type == :dstr
|
953
877
|
if node.type == :class or node.type == :module
|
878
|
+
visibility = :public
|
954
879
|
if node.children[0].kind_of?(AST::Node) and node.children[0].children[0].kind_of?(AST::Node) and node.children[0].children[0].type == :cbase
|
955
880
|
tree = pack_name(node.children[0])
|
956
881
|
else
|
@@ -960,21 +885,55 @@ module Solargraph
|
|
960
885
|
fqn = tree.join('::')
|
961
886
|
@namespace_map[fqn] ||= []
|
962
887
|
@namespace_map[fqn].push node
|
888
|
+
if node.type == :class and !node.children[1].nil?
|
889
|
+
sc = unpack_name(node.children[1])
|
890
|
+
@superclasses[fqn] = sc
|
891
|
+
end
|
892
|
+
end
|
893
|
+
file = get_filename_for(node)
|
894
|
+
in_yardoc = yardoc_has_file?(file)
|
895
|
+
node.children.each do |c|
|
896
|
+
if c.kind_of?(AST::Node)
|
897
|
+
if c.type == :ivasgn
|
898
|
+
@ivar_pins[fqn] ||= []
|
899
|
+
@ivar_pins[fqn].push IvarPin.new(c, fqn, local_scope, get_comment_for(c))
|
900
|
+
elsif c.type == :cvasgn
|
901
|
+
@cvar_pins[fqn] ||= []
|
902
|
+
@cvar_pins[fqn].push CvarPin.new(c, fqn, get_comment_for(c))
|
903
|
+
else
|
904
|
+
unless fqn.nil? or in_yardoc
|
905
|
+
if c.kind_of?(AST::Node)
|
906
|
+
if c.type == :def and c.children[0].to_s[0].match(/[a-z]/i)
|
907
|
+
@method_pins[fqn] ||= []
|
908
|
+
@method_pins[fqn].push MethodPin.new(c, fqn, scope, visibility, get_comment_for(c))
|
909
|
+
map_namespaces c, tree, visibility, scope, fqn, :instance
|
910
|
+
next
|
911
|
+
elsif c.type == :defs
|
912
|
+
@method_pins[fqn] ||= []
|
913
|
+
@method_pins[fqn].push MethodPin.new(c, fqn, :class, :public, get_comment_for(c))
|
914
|
+
map_namespaces c, tree, :public, :class, fqn
|
915
|
+
next
|
916
|
+
elsif c.type == :send and [:public, :protected, :private].include?(c.children[1])
|
917
|
+
visibility = c.children[1]
|
918
|
+
elsif c.type == :send and c.children[1] == :include and node.type == :class
|
919
|
+
@namespace_includes[fqn] ||= []
|
920
|
+
@namespace_includes[fqn].push unpack_name(c.children[2])
|
921
|
+
elsif c.type == :send and [:attr_reader, :attr_writer, :attr_accessor].include?(c.children[1])
|
922
|
+
@attr_nodes[fqn] ||= []
|
923
|
+
@attr_nodes[fqn].push AttrPin.new(c)
|
924
|
+
elsif c.type == :sclass and c.children[0].type == :self
|
925
|
+
map_namespaces c, tree, :public, :class, fqn
|
926
|
+
next
|
927
|
+
end
|
928
|
+
end
|
929
|
+
end
|
930
|
+
map_namespaces c, tree, visibility, scope, fqn
|
931
|
+
end
|
932
|
+
end
|
963
933
|
end
|
964
|
-
node.children.each { |c|
|
965
|
-
map_namespaces c, tree
|
966
|
-
}
|
967
934
|
end
|
968
935
|
end
|
969
936
|
|
970
|
-
def code_for node
|
971
|
-
src = @file_source[get_filename_for(node)]
|
972
|
-
return nil if src.nil?
|
973
|
-
b = node.location.expression.begin.begin_pos
|
974
|
-
e = node.location.expression.end.end_pos
|
975
|
-
src[b..e].strip.gsub(/,$/, '')
|
976
|
-
end
|
977
|
-
|
978
937
|
def clean_namespace_string namespace
|
979
938
|
result = namespace.to_s.gsub(/<.*$/, '')
|
980
939
|
if result == 'Class' and namespace.include?('<')
|
data/lib/solargraph/code_map.rb
CHANGED
@@ -263,74 +263,65 @@ module Solargraph
|
|
263
263
|
def suggest_at index, filtered: false, with_snippets: false
|
264
264
|
return [] if string_at?(index) or string_at?(index - 1) or comment_at?(index)
|
265
265
|
result = []
|
266
|
-
phrase = phrase_at(index)
|
267
266
|
signature = get_signature_at(index)
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
literal = node_at(cursed - 1)
|
279
|
-
else
|
280
|
-
literal = node_at(cursed + 1)
|
281
|
-
end
|
282
|
-
type = infer_literal_node_type(literal)
|
283
|
-
if type.nil?
|
284
|
-
type = infer_signature_at(nearest) unless revised.empty?
|
285
|
-
if !type.nil?
|
286
|
-
result.concat api_map.get_instance_methods(type) unless type.nil?
|
287
|
-
elsif !revised.include?('.')
|
288
|
-
fqns = api_map.find_fully_qualified_namespace(revised, namespace)
|
289
|
-
result.concat api_map.get_methods(fqns) unless fqns.nil?
|
290
|
-
end
|
267
|
+
if index == 0 or @code[index - 1].match(/[\.\s]/)
|
268
|
+
type = infer_signature_at(index)
|
269
|
+
else
|
270
|
+
if signature.include?('.')
|
271
|
+
last_period = @code[0..index].rindex('.')
|
272
|
+
if last_period.nil?
|
273
|
+
type = infer_signature_at(index)
|
274
|
+
else
|
275
|
+
type = infer_signature_at(last_period)
|
276
|
+
end
|
291
277
|
else
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
278
|
+
if signature.start_with?('@@')
|
279
|
+
return get_class_variables_at(index)
|
280
|
+
elsif signature.start_with?('@')
|
281
|
+
return get_instance_variables_at(index)
|
282
|
+
elsif signature.start_with?('$')
|
283
|
+
return api_map.get_global_variables
|
296
284
|
else
|
297
|
-
|
298
|
-
result.concat api_map.get_instance_methods(intype)
|
285
|
+
type = infer_signature_at(index)
|
299
286
|
end
|
300
287
|
end
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
288
|
+
end
|
289
|
+
if type.nil?
|
290
|
+
unless signature.include?('.')
|
291
|
+
phrase = phrase_at(index)
|
292
|
+
signature = get_signature_at(index)
|
293
|
+
namespace = namespace_at(index)
|
294
|
+
if phrase.include?('::')
|
295
|
+
parts = phrase.split('::', -1)
|
296
|
+
ns = parts[0..-2].join('::')
|
297
|
+
if parts.last.include?('.')
|
298
|
+
ns = parts[0..-2].join('::') + '::' + parts.last[0..parts.last.index('.')-1]
|
299
|
+
result = api_map.get_methods(ns)
|
300
|
+
else
|
301
|
+
result = api_map.namespaces_in(ns, namespace)
|
302
|
+
end
|
303
|
+
else
|
304
|
+
type = infer_literal_node_type(node_at(index - 2))
|
305
|
+
if type.nil?
|
306
|
+
current_namespace = namespace_at(index)
|
307
|
+
parts = current_namespace.to_s.split('::')
|
308
|
+
result += get_snippets_at(index) if with_snippets
|
309
|
+
result += get_local_variables_and_methods_at(index)
|
310
|
+
result += ApiMap.get_keywords
|
311
|
+
while parts.length > 0
|
312
|
+
ns = parts.join('::')
|
313
|
+
result += api_map.namespaces_in(ns, namespace)
|
314
|
+
parts.pop
|
315
|
+
end
|
316
|
+
result += api_map.namespaces_in('')
|
317
|
+
result += api_map.get_instance_methods('Kernel')
|
318
|
+
else
|
319
|
+
result.concat api_map.get_instance_methods(type)
|
320
|
+
end
|
328
321
|
end
|
329
|
-
result += api_map.namespaces_in('')
|
330
|
-
result += api_map.get_instance_methods('Kernel')
|
331
|
-
else
|
332
|
-
result.concat api_map.get_instance_methods(type)
|
333
322
|
end
|
323
|
+
else
|
324
|
+
result.concat api_map.get_instance_methods(type)
|
334
325
|
end
|
335
326
|
result = reduce_starting_with(result, word_at(index)) if filtered
|
336
327
|
result.uniq{|s| s.path}.sort{|a,b| a.label <=> b.label}
|
@@ -375,7 +366,10 @@ module Solargraph
|
|
375
366
|
end
|
376
367
|
end
|
377
368
|
return [] if path.nil?
|
378
|
-
|
369
|
+
if path.start_with?('Class<')
|
370
|
+
path.gsub!(/^Class<([a-z0-9_:]*)>#([a-z0-9_]*)$/i, '\\1.\\2')
|
371
|
+
end
|
372
|
+
api_map.yard_map.objects(path, ns_here)
|
379
373
|
end
|
380
374
|
|
381
375
|
# Infer the type of the signature located at the specified index.
|
@@ -392,36 +386,67 @@ module Solargraph
|
|
392
386
|
# @return [String]
|
393
387
|
def infer_signature_at index
|
394
388
|
signature = get_signature_at(index)
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
389
|
+
# Check for literals first
|
390
|
+
return 'Integer' if signature.match(/^[0-9]+?\.?$/)
|
391
|
+
literal = nil
|
392
|
+
if (signature.empty? and @code[index - 1] == '.') or signature == '[].'
|
393
|
+
literal = node_at(index - 2)
|
394
|
+
elsif signature.start_with?('.')
|
395
|
+
literal = node_at(index - 1)
|
396
|
+
else
|
397
|
+
beg_sig = get_signature_index_at(index)
|
398
|
+
literal = node_at(1 + beg_sig)
|
399
|
+
end
|
400
|
+
type = infer_literal_node_type(literal)
|
401
|
+
if type.nil?
|
402
|
+
node = parent_node_from(index, :class, :module, :def, :defs) || @node
|
403
|
+
result = infer_signature_from_node signature, node
|
404
|
+
if result.nil? or result.empty?
|
405
|
+
arg = nil
|
406
|
+
if node.type == :def or node.type == :defs or node.type == :block
|
407
|
+
# Check for method arguments
|
408
|
+
parts = signature.split('.', 2)
|
409
|
+
# @type [Solargraph::Suggestion]
|
410
|
+
arg = get_method_arguments_from(node).keep_if{|s| s.to_s == parts[0] }.first
|
411
|
+
unless arg.nil?
|
412
|
+
if parts[1].nil?
|
413
|
+
result = arg.return_type
|
414
|
+
else
|
415
|
+
result = api_map.infer_signature_type(parts[1], parts[0], scope: :instance)
|
416
|
+
end
|
409
417
|
end
|
410
418
|
end
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
419
|
+
if arg.nil?
|
420
|
+
# Check for yieldparams
|
421
|
+
parts = signature.split('.', 2)
|
422
|
+
yp = get_yieldparams_at(index).keep_if{|s| s.to_s == parts[0]}.first
|
423
|
+
unless yp.nil?
|
424
|
+
if parts[1].nil? or parts[1].empty?
|
425
|
+
result = yp.return_type
|
426
|
+
else
|
427
|
+
newsig = parts[1..-1].join('.')
|
428
|
+
result = api_map.infer_signature_type(newsig, yp.return_type, scope: :instance)
|
429
|
+
end
|
422
430
|
end
|
423
431
|
end
|
424
432
|
end
|
433
|
+
else
|
434
|
+
if signature.empty?
|
435
|
+
result = type
|
436
|
+
else
|
437
|
+
cursed = get_signature_index_at(index)
|
438
|
+
rest = signature[literal.loc.expression.end_pos+(cursed-literal.loc.expression.end_pos)..-1]
|
439
|
+
return type if rest.nil?
|
440
|
+
lit_code = @code[literal.loc.expression.begin_pos..literal.loc.expression.end_pos]
|
441
|
+
rest = rest[lit_code.length..-1] if rest.start_with?(lit_code)
|
442
|
+
rest = rest[1..-1] if rest.start_with?('.')
|
443
|
+
rest = rest[0..-2] if rest.end_with?('.')
|
444
|
+
if rest.empty?
|
445
|
+
result = type
|
446
|
+
else
|
447
|
+
result = api_map.infer_signature_type(rest, type, scope: :instance)
|
448
|
+
end
|
449
|
+
end
|
425
450
|
end
|
426
451
|
result
|
427
452
|
end
|
@@ -439,6 +464,10 @@ module Solargraph
|
|
439
464
|
inferred = nil
|
440
465
|
parts = signature.split('.')
|
441
466
|
ns_here = namespace_from(node)
|
467
|
+
unless signature.include?('.')
|
468
|
+
fqns = api_map.find_fully_qualified_namespace(signature, ns_here)
|
469
|
+
return "Class<#{fqns}>" unless fqns.nil?
|
470
|
+
end
|
442
471
|
start = parts[0]
|
443
472
|
return nil if start.nil?
|
444
473
|
remainder = parts[1..-1]
|
data/lib/solargraph/server.rb
CHANGED
@@ -15,6 +15,11 @@ module Solargraph
|
|
15
15
|
GC.start
|
16
16
|
end
|
17
17
|
|
18
|
+
def self.wait
|
19
|
+
@@semaphore.lock
|
20
|
+
@@semaphore.unlock
|
21
|
+
end
|
22
|
+
|
18
23
|
post '/prepare' do
|
19
24
|
STDERR.puts "Preparing #{params['workspace']}"
|
20
25
|
Server.prepare_workspace params['workspace']
|
@@ -44,7 +49,7 @@ module Solargraph
|
|
44
49
|
begin
|
45
50
|
sugg = []
|
46
51
|
workspace = params['workspace'] || nil
|
47
|
-
Server.prepare_workspace workspace unless @@api_hash.has_key?(workspace)
|
52
|
+
#Server.prepare_workspace workspace unless @@api_hash.has_key?(workspace)
|
48
53
|
@@semaphore.synchronize {
|
49
54
|
code_map = CodeMap.new(code: params['text'], filename: params['filename'], api_map: @@api_hash[workspace], cursor: [params['line'].to_i, params['column'].to_i])
|
50
55
|
offset = code_map.get_offset(params['line'].to_i, params['column'].to_i)
|
@@ -63,7 +68,7 @@ module Solargraph
|
|
63
68
|
begin
|
64
69
|
sugg = []
|
65
70
|
workspace = params['workspace'] || nil
|
66
|
-
Server.prepare_workspace workspace unless @@api_hash.has_key?(workspace)
|
71
|
+
#Server.prepare_workspace workspace unless @@api_hash.has_key?(workspace)
|
67
72
|
@@semaphore.synchronize {
|
68
73
|
code_map = CodeMap.new(code: params['text'], filename: params['filename'], api_map: @@api_hash[workspace], cursor: [params['line'].to_i, params['column'].to_i])
|
69
74
|
offset = code_map.get_offset(params['line'].to_i, params['column'].to_i)
|
@@ -121,12 +126,14 @@ module Solargraph
|
|
121
126
|
end
|
122
127
|
|
123
128
|
def prepare_workspace directory
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
129
|
+
Thread.new do
|
130
|
+
@@semaphore.synchronize {
|
131
|
+
api_map = Solargraph::ApiMap.new(directory)
|
132
|
+
api_map.update_yardoc
|
133
|
+
@@api_hash[directory] = api_map
|
134
|
+
}
|
135
|
+
end
|
136
|
+
end
|
130
137
|
end
|
131
138
|
|
132
139
|
class Helpers
|
data/lib/solargraph/shell.rb
CHANGED
@@ -39,14 +39,9 @@ module Solargraph
|
|
39
39
|
def return_type
|
40
40
|
if @return_type.nil?
|
41
41
|
if code_object.nil?
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
@return_type = t.types[0] unless t.nil? or t.types.nil?
|
46
|
-
else
|
47
|
-
match = documentation.match(/@return \[([a-z0-9:_]*)/i)
|
48
|
-
@return_type = match[1] unless match.nil?
|
49
|
-
end
|
42
|
+
if documentation.kind_of?(YARD::Docstring)
|
43
|
+
t = documentation.tag(:return)
|
44
|
+
@return_type = t.types[0] unless t.nil? or t.types.nil?
|
50
45
|
end
|
51
46
|
else
|
52
47
|
o = code_object.tag(:overload)
|
@@ -63,8 +58,8 @@ module Solargraph
|
|
63
58
|
|
64
59
|
def documentation
|
65
60
|
if @documentation.nil?
|
66
|
-
unless @code_object.nil?
|
67
|
-
@documentation = @code_object.docstring
|
61
|
+
unless @code_object.nil? or @code_object.docstring.nil?
|
62
|
+
@documentation = @code_object.docstring
|
68
63
|
end
|
69
64
|
end
|
70
65
|
@documentation
|
data/lib/solargraph/version.rb
CHANGED
data/lib/solargraph/yard_map.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
|
-
require 'rubygems'
|
2
1
|
require 'parser/current'
|
3
2
|
require 'yard'
|
4
|
-
require 'bundler'
|
5
3
|
|
6
4
|
module Solargraph
|
7
5
|
|
@@ -10,7 +8,7 @@ module Solargraph
|
|
10
8
|
|
11
9
|
attr_reader :workspace
|
12
10
|
|
13
|
-
def initialize required: [], workspace: nil
|
11
|
+
def initialize required: [], workspace: nil
|
14
12
|
@workspace = workspace
|
15
13
|
unless workspace.nil?
|
16
14
|
wsy = File.join(workspace, '.yardoc')
|
@@ -34,26 +32,9 @@ module Solargraph
|
|
34
32
|
}
|
35
33
|
yardocs.push File.join(Dir.home, '.solargraph', 'cache', '2.0.0', 'yardoc')
|
36
34
|
yardocs.uniq!
|
37
|
-
include_bundled_gems if with_bundled
|
38
35
|
cache_core
|
39
36
|
end
|
40
37
|
|
41
|
-
def include_bundled_gems
|
42
|
-
return if workspace.nil?
|
43
|
-
lockfile = File.join(workspace, 'Gemfile.lock')
|
44
|
-
return unless File.file?(lockfile)
|
45
|
-
parser = Bundler::LockfileParser.new(Bundler.read_file(lockfile))
|
46
|
-
parser.specs.each do |s|
|
47
|
-
STDERR.puts "Specs include #{s.name}"
|
48
|
-
gy = YARD::Registry.yardoc_file_for_gem(s.name)
|
49
|
-
if gy.nil?
|
50
|
-
STDERR.puts "Bundled gem not found: #{s.name}"
|
51
|
-
else
|
52
|
-
yardocs.unshift gy unless yardocs.include?(gy)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
38
|
# @return [Array<String>]
|
58
39
|
def yardocs
|
59
40
|
@yardocs ||= []
|
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.12.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-09-
|
11
|
+
date: 2017-09-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: parser
|
@@ -124,30 +124,30 @@ dependencies:
|
|
124
124
|
name: debase
|
125
125
|
requirement: !ruby/object:Gem::Requirement
|
126
126
|
requirements:
|
127
|
-
- - "
|
127
|
+
- - "~>"
|
128
128
|
- !ruby/object:Gem::Version
|
129
|
-
version: '0'
|
129
|
+
version: '0.2'
|
130
130
|
type: :development
|
131
131
|
prerelease: false
|
132
132
|
version_requirements: !ruby/object:Gem::Requirement
|
133
133
|
requirements:
|
134
|
-
- - "
|
134
|
+
- - "~>"
|
135
135
|
- !ruby/object:Gem::Version
|
136
|
-
version: '0'
|
136
|
+
version: '0.2'
|
137
137
|
- !ruby/object:Gem::Dependency
|
138
138
|
name: ruby-debug-ide
|
139
139
|
requirement: !ruby/object:Gem::Requirement
|
140
140
|
requirements:
|
141
|
-
- - "
|
141
|
+
- - "~>"
|
142
142
|
- !ruby/object:Gem::Version
|
143
|
-
version: '0'
|
143
|
+
version: '0.6'
|
144
144
|
type: :development
|
145
145
|
prerelease: false
|
146
146
|
version_requirements: !ruby/object:Gem::Requirement
|
147
147
|
requirements:
|
148
|
-
- - "
|
148
|
+
- - "~>"
|
149
149
|
- !ruby/object:Gem::Version
|
150
|
-
version: '0'
|
150
|
+
version: '0.6'
|
151
151
|
description: IDE tools for code completion and inline documentation
|
152
152
|
email: admin@castwide.com
|
153
153
|
executables:
|
@@ -158,8 +158,12 @@ files:
|
|
158
158
|
- bin/solargraph
|
159
159
|
- lib/solargraph.rb
|
160
160
|
- lib/solargraph/api_map.rb
|
161
|
+
- lib/solargraph/api_map/attr_pin.rb
|
161
162
|
- lib/solargraph/api_map/cache.rb
|
162
163
|
- lib/solargraph/api_map/config.rb
|
164
|
+
- lib/solargraph/api_map/cvar_pin.rb
|
165
|
+
- lib/solargraph/api_map/ivar_pin.rb
|
166
|
+
- lib/solargraph/api_map/method_pin.rb
|
163
167
|
- lib/solargraph/code_map.rb
|
164
168
|
- lib/solargraph/node_methods.rb
|
165
169
|
- lib/solargraph/server.rb
|