solargraph 0.11.2 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/solargraph/api_map/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
|