solargraph 0.13.0 → 0.13.1
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/source.rb +55 -13
- data/lib/solargraph/api_map.rb +159 -106
- data/lib/solargraph/code_map.rb +120 -191
- data/lib/solargraph/node_methods.rb +5 -1
- data/lib/solargraph/pin/attribute.rb +14 -1
- data/lib/solargraph/pin/base.rb +18 -0
- data/lib/solargraph/pin/global_variable.rb +6 -0
- data/lib/solargraph/pin/local_variable.rb +25 -0
- data/lib/solargraph/pin/method.rb +2 -0
- data/lib/solargraph/pin.rb +2 -0
- data/lib/solargraph/server.rb +11 -7
- data/lib/solargraph/shell.rb +17 -2
- data/lib/solargraph/suggestion.rb +48 -36
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/yard_map/cache.rb +2 -2
- data/lib/solargraph/yard_map.rb +146 -91
- data/lib/yard-solargraph.rb +0 -23
- metadata +32 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a515f53b1eebf187bf4108abdba6c591f438cdb6
|
4
|
+
data.tar.gz: 832c13c89dcdf1bae7cb69aa3433d73346b86bec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 74f08e71b1c0834aa6b18f4dcb0e176f91d0a40ac6f8a3fe3c76ad95081096eec4cb2ed904aaa7586433d05f8520214b9d1185755a549a2045870ba661acfd6e
|
7
|
+
data.tar.gz: 7ddcdf66369a65533d14e3c13763dad0ecb3f306b4b0ce7ef707802a61ae5b6c6d13a979b48bdd64c76b823064d32d9d1dd57dbd917d60e50dca018db1ab6799
|
@@ -3,16 +3,23 @@ require 'parser/current'
|
|
3
3
|
module Solargraph
|
4
4
|
class ApiMap
|
5
5
|
class Source
|
6
|
+
# @return [String]
|
6
7
|
attr_reader :code
|
8
|
+
|
9
|
+
# @return [Parser::AST::Node]
|
7
10
|
attr_reader :node
|
11
|
+
|
12
|
+
# @return [Array]
|
8
13
|
attr_reader :comments
|
14
|
+
|
15
|
+
# @return [String]
|
9
16
|
attr_reader :filename
|
10
17
|
|
11
18
|
include NodeMethods
|
12
19
|
|
13
20
|
def initialize code, node, comments, filename
|
14
21
|
@code = code
|
15
|
-
root = AST::Node.new(:
|
22
|
+
root = AST::Node.new(:source, [filename])
|
16
23
|
root = root.append node
|
17
24
|
@node = root
|
18
25
|
@comments = comments
|
@@ -20,6 +27,8 @@ module Solargraph
|
|
20
27
|
@filename = filename
|
21
28
|
@namespace_nodes = {}
|
22
29
|
@all_nodes = []
|
30
|
+
@node_stack = []
|
31
|
+
@node_tree = {}
|
23
32
|
inner_map_node @node
|
24
33
|
end
|
25
34
|
|
@@ -55,6 +64,14 @@ module Solargraph
|
|
55
64
|
@class_variable_pins ||= []
|
56
65
|
end
|
57
66
|
|
67
|
+
def local_variable_pins
|
68
|
+
@local_variable_pins ||= []
|
69
|
+
end
|
70
|
+
|
71
|
+
def global_variable_pins
|
72
|
+
@global_variable_pins ||= []
|
73
|
+
end
|
74
|
+
|
58
75
|
def constant_pins
|
59
76
|
@constant_pins ||= []
|
60
77
|
end
|
@@ -78,6 +95,10 @@ module Solargraph
|
|
78
95
|
frag.strip.gsub(/,$/, '')
|
79
96
|
end
|
80
97
|
|
98
|
+
def tree_for node
|
99
|
+
@node_tree[node] || []
|
100
|
+
end
|
101
|
+
|
81
102
|
def include? node
|
82
103
|
@all_nodes.include? node
|
83
104
|
end
|
@@ -115,7 +136,11 @@ module Solargraph
|
|
115
136
|
source = self
|
116
137
|
if node.kind_of?(AST::Node)
|
117
138
|
@all_nodes.push node
|
118
|
-
|
139
|
+
if node.type == :str or node.type == :dstr
|
140
|
+
stack.pop
|
141
|
+
return
|
142
|
+
end
|
143
|
+
@node_stack.unshift node
|
119
144
|
if node.type == :class or node.type == :module
|
120
145
|
visibility = :public
|
121
146
|
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
|
@@ -134,6 +159,7 @@ module Solargraph
|
|
134
159
|
file = source.filename
|
135
160
|
node.children.each do |c|
|
136
161
|
if c.kind_of?(AST::Node)
|
162
|
+
@node_tree[c] = @node_stack.clone
|
137
163
|
if c.type == :ivasgn
|
138
164
|
par = find_parent(stack, :class, :module, :def, :defs)
|
139
165
|
local_scope = ( (par.kind_of?(AST::Node) and par.type == :def) ? :instance : :class )
|
@@ -141,6 +167,7 @@ module Solargraph
|
|
141
167
|
ora = find_parent(stack, :or_asgn)
|
142
168
|
unless ora.nil?
|
143
169
|
u = c.updated(:ivasgn, c.children + ora.children[1..-1], nil)
|
170
|
+
@node_tree[u] = @node_stack.clone
|
144
171
|
instance_variable_pins.push Solargraph::Pin::InstanceVariable.new(self, u, fqn || '', local_scope)
|
145
172
|
end
|
146
173
|
else
|
@@ -151,11 +178,27 @@ module Solargraph
|
|
151
178
|
ora = find_parent(stack, :or_asgn)
|
152
179
|
unless ora.nil?
|
153
180
|
u = c.updated(:cvasgn, c.children + ora.children[1..-1], nil)
|
181
|
+
@node_tree[u] = @node_stack.clone
|
154
182
|
class_variable_pins.push Solargraph::Pin::ClassVariable.new(self, u, fqn || '')
|
155
183
|
end
|
156
184
|
else
|
157
185
|
class_variable_pins.push Solargraph::Pin::ClassVariable.new(self, c, fqn || '')
|
158
186
|
end
|
187
|
+
elsif c.type == :lvasgn
|
188
|
+
if c.children[1].nil?
|
189
|
+
ora = find_parent(stack, :or_asgn)
|
190
|
+
unless ora.nil?
|
191
|
+
u = c.updated(:lvasgn, c.children + ora.children[1..-1], nil)
|
192
|
+
@node_tree[u] = @node_stack.clone
|
193
|
+
@docstring_hash[u.loc] = docstring_for(ora)
|
194
|
+
local_variable_pins.push Solargraph::Pin::LocalVariable.new(self, u, fqn || '', @node_stack.clone)
|
195
|
+
end
|
196
|
+
else
|
197
|
+
@node_tree[c] = @node_stack.clone
|
198
|
+
local_variable_pins.push Solargraph::Pin::LocalVariable.new(self, c, fqn || '', @node_stack.clone)
|
199
|
+
end
|
200
|
+
elsif c.type == :gvasgn
|
201
|
+
global_variable_pins.push Solargraph::Pin::GlobalVariable.new(self, c, fqn || '')
|
159
202
|
elsif c.type == :sym
|
160
203
|
symbol_pins.push Solargraph::Pin::Symbol.new(self, c, fqn)
|
161
204
|
elsif c.type == :casgn
|
@@ -165,8 +208,8 @@ module Solargraph
|
|
165
208
|
if c.kind_of?(AST::Node)
|
166
209
|
if c.type == :def and c.children[0].to_s[0].match(/[a-z]/i)
|
167
210
|
method_pins.push Solargraph::Pin::Method.new(source, c, fqn, scope, visibility)
|
168
|
-
inner_map_node c, tree, visibility, scope, fqn, stack
|
169
|
-
next
|
211
|
+
#inner_map_node c, tree, visibility, scope, fqn, stack
|
212
|
+
#next
|
170
213
|
elsif c.type == :defs
|
171
214
|
method_pins.push Solargraph::Pin::Method.new(source, c, fqn, :class, :public)
|
172
215
|
inner_map_node c, tree, :public, :class, fqn, stack
|
@@ -181,10 +224,10 @@ module Solargraph
|
|
181
224
|
elsif c.type == :send and [:attr_reader, :attr_writer, :attr_accessor].include?(c.children[1])
|
182
225
|
c.children[2..-1].each do |a|
|
183
226
|
if c.children[1] == :attr_reader or c.children[1] == :attr_accessor
|
184
|
-
attribute_pins.push Solargraph::Pin::Attribute.new(self, a, fqn, :reader) #AttrPin.new(c)
|
227
|
+
attribute_pins.push Solargraph::Pin::Attribute.new(self, a, fqn, :reader, docstring_for(c)) #AttrPin.new(c)
|
185
228
|
end
|
186
229
|
if c.children[1] == :attr_writer or c.children[1] == :attr_accessor
|
187
|
-
attribute_pins.push Solargraph::Pin::Attribute.new(self, a, fqn, :writer) #AttrPin.new(c)
|
230
|
+
attribute_pins.push Solargraph::Pin::Attribute.new(self, a, fqn, :writer, docstring_for(c)) #AttrPin.new(c)
|
188
231
|
end
|
189
232
|
end
|
190
233
|
elsif c.type == :sclass and c.children[0].type == :self
|
@@ -198,10 +241,11 @@ module Solargraph
|
|
198
241
|
required.push c.children[2].children[0].to_s
|
199
242
|
end
|
200
243
|
end
|
201
|
-
inner_map_node c, tree, visibility, scope, fqn, stack
|
202
244
|
end
|
245
|
+
inner_map_node c, tree, visibility, scope, fqn, stack
|
203
246
|
end
|
204
247
|
end
|
248
|
+
@node_stack.shift
|
205
249
|
end
|
206
250
|
stack.pop
|
207
251
|
end
|
@@ -220,11 +264,13 @@ module Solargraph
|
|
220
264
|
Source.virtual(filename, code)
|
221
265
|
end
|
222
266
|
|
267
|
+
# @return [Solargraph::ApiMap::Source]
|
223
268
|
def virtual filename, code
|
224
269
|
node, comments = Parser::CurrentRuby.parse_with_comments(code)
|
225
270
|
Source.new(code, node, comments, filename)
|
226
271
|
end
|
227
272
|
|
273
|
+
# @return [Solargraph::ApiMap::Source]
|
228
274
|
def fix filename, code, cursor = nil
|
229
275
|
tries = 0
|
230
276
|
code.gsub!(/\r/, '')
|
@@ -236,10 +282,6 @@ module Solargraph
|
|
236
282
|
# incomplete trees resulting from short scripts (e.g., a lone variable
|
237
283
|
# assignment).
|
238
284
|
node, comments = Parser::CurrentRuby.parse_with_comments(tmp + "\n_")
|
239
|
-
#@node = self.api_map.append_node(node, @comments, filename)
|
240
|
-
#@parsed = tmp
|
241
|
-
#@code.freeze
|
242
|
-
#@parsed.freeze
|
243
285
|
Source.new(code, node, comments, filename)
|
244
286
|
rescue Parser::SyntaxError => e
|
245
287
|
if tries < 10
|
@@ -247,10 +289,10 @@ module Solargraph
|
|
247
289
|
if tries == 10 and e.message.include?('token $end')
|
248
290
|
tmp += "\nend"
|
249
291
|
else
|
250
|
-
if !fixed_cursor and !cursor.nil? and e.message.include?('token $end')
|
292
|
+
if !fixed_cursor and !cursor.nil? and cursor >= 2 and (e.message.include?('token $end') or tmp[cursor - 1] == '$')
|
251
293
|
fixed_cursor = true
|
252
294
|
spot = cursor - 2
|
253
|
-
if tmp[cursor - 1] == '.'
|
295
|
+
if tmp[cursor - 1] == '.' or tmp[cursor - 1] == '$'
|
254
296
|
repl = ';'
|
255
297
|
else
|
256
298
|
repl = '#'
|
data/lib/solargraph/api_map.rb
CHANGED
@@ -9,8 +9,6 @@ module Solargraph
|
|
9
9
|
autoload :Cache, 'solargraph/api_map/cache'
|
10
10
|
|
11
11
|
@@source_cache = {}
|
12
|
-
@@yard_map_cache = {}
|
13
|
-
@@semaphore = Mutex.new
|
14
12
|
|
15
13
|
KEYWORDS = [
|
16
14
|
'__ENCODING__', '__LINE__', '__FILE__', 'BEGIN', 'END', 'alias', 'and',
|
@@ -27,10 +25,6 @@ module Solargraph
|
|
27
25
|
include NodeMethods
|
28
26
|
include YardMethods
|
29
27
|
|
30
|
-
# @todo Temp for testing
|
31
|
-
attr_reader :new_method_pins
|
32
|
-
attr_reader :new_ivar_pins
|
33
|
-
|
34
28
|
# The root directory of the project. The ApiMap will search here for
|
35
29
|
# additional files to parse and analyze.
|
36
30
|
#
|
@@ -49,30 +43,42 @@ module Solargraph
|
|
49
43
|
config = ApiMap::Config.new(@workspace)
|
50
44
|
@workspace_files.concat (config.included - config.excluded)
|
51
45
|
@workspace_files.each do |wf|
|
52
|
-
|
46
|
+
begin
|
47
|
+
@@source_cache[wf] ||= Source.load(wf)
|
48
|
+
rescue
|
49
|
+
STDERR.puts "Failed to load #{wf}"
|
50
|
+
end
|
53
51
|
end
|
54
52
|
end
|
55
53
|
@sources = {}
|
56
54
|
@virtual_source = nil
|
57
55
|
@virtual_filename = nil
|
58
|
-
@stale =
|
59
|
-
|
60
|
-
@new_ivar_pins = []
|
56
|
+
@stale = true
|
57
|
+
refresh
|
61
58
|
end
|
62
59
|
|
63
60
|
# @return [Solargraph::YardMap]
|
64
61
|
def yard_map
|
65
|
-
|
66
|
-
|
67
|
-
|
62
|
+
refresh
|
63
|
+
if @yard_map.nil? || @yard_map.required != required
|
64
|
+
@yard_map = Solargraph::YardMap.new(required: required, workspace: workspace)
|
65
|
+
end
|
66
|
+
@yard_map
|
68
67
|
end
|
69
68
|
|
69
|
+
# @return [Solargraph::ApiMap::Source]
|
70
70
|
def virtualize filename, code, cursor = nil
|
71
|
-
@
|
71
|
+
unless @virtual_source.nil? or @virtual_filename == filename or @workspace_files.include?(@virtual_filename)
|
72
|
+
eliminate @virtual_filename
|
73
|
+
end
|
74
|
+
refresh
|
72
75
|
@virtual_filename = filename
|
73
76
|
@virtual_source = Source.fix(filename, code, cursor)
|
77
|
+
process_virtual
|
78
|
+
@virtual_source
|
74
79
|
end
|
75
80
|
|
81
|
+
# @return [Solargraph::ApiMap::Source]
|
76
82
|
def append_source code, filename
|
77
83
|
virtualize filename, code
|
78
84
|
end
|
@@ -115,18 +121,26 @@ module Solargraph
|
|
115
121
|
result
|
116
122
|
end
|
117
123
|
|
124
|
+
# @return [Array<Solargraph::Pin::Constant>]
|
125
|
+
def get_constant_pins namespace, root
|
126
|
+
fqns = find_fully_qualified_namespace(namespace, root)
|
127
|
+
@const_pins[fqns] || []
|
128
|
+
end
|
129
|
+
|
130
|
+
# @return [Array<Solargraph::Suggestion>]
|
118
131
|
def get_constants namespace, root
|
119
132
|
result = []
|
120
133
|
fqns = find_fully_qualified_namespace(namespace, root)
|
121
134
|
cp = @const_pins[fqns]
|
122
135
|
unless cp.nil?
|
123
136
|
cp.each do |pin|
|
124
|
-
result.push
|
137
|
+
result.push pin_to_suggestion(pin)
|
125
138
|
end
|
126
139
|
end
|
127
140
|
result.concat yard_map.get_constants(namespace, root)
|
128
141
|
end
|
129
142
|
|
143
|
+
# @return [String]
|
130
144
|
def find_fully_qualified_namespace name, root = '', skip = []
|
131
145
|
refresh
|
132
146
|
return nil if skip.include?(root)
|
@@ -168,40 +182,51 @@ module Solargraph
|
|
168
182
|
@namespace_map[fqns] || []
|
169
183
|
end
|
170
184
|
|
185
|
+
# @return [Array<Solargraph::Pin::InstanceVariable>]
|
186
|
+
def get_instance_variable_pins(namespace, scope = :instance)
|
187
|
+
refresh
|
188
|
+
(@ivar_pins[namespace] || []).select{ |pin| pin.scope == scope }
|
189
|
+
end
|
190
|
+
|
191
|
+
# @return [Array<Solargraph::Suggestion>]
|
171
192
|
def get_instance_variables(namespace, scope = :instance)
|
172
193
|
refresh
|
173
194
|
result = []
|
174
195
|
ip = @ivar_pins[namespace]
|
175
196
|
unless ip.nil?
|
176
197
|
ip.select{ |pin| pin.scope == scope }.each do |pin|
|
177
|
-
|
178
|
-
result.push Suggestion.pull(pin, resolve_pin_return_type(pin))
|
198
|
+
result.push pin_to_suggestion(pin)
|
179
199
|
end
|
180
200
|
end
|
181
201
|
result
|
182
202
|
end
|
183
203
|
|
204
|
+
# @return [Array<Solargraph::Pin::ClassVariable>]
|
205
|
+
def get_class_variable_pins(namespace)
|
206
|
+
refresh
|
207
|
+
@cvar_pins[namespace] || []
|
208
|
+
end
|
209
|
+
|
210
|
+
# @return [Array<Solargraph::Suggestion>]
|
184
211
|
def get_class_variables(namespace)
|
185
212
|
refresh
|
186
213
|
result = []
|
187
214
|
ip = @cvar_pins[namespace]
|
188
215
|
unless ip.nil?
|
189
216
|
ip.each do |pin|
|
190
|
-
result.push
|
217
|
+
result.push pin_to_suggestion(pin)
|
191
218
|
end
|
192
219
|
end
|
193
220
|
result
|
194
221
|
end
|
195
222
|
|
223
|
+
# @return [Array<Solargraph::Pin::Symbol>]
|
196
224
|
def get_symbols
|
197
225
|
refresh
|
198
|
-
|
199
|
-
@symbol_pins.each do |s|
|
200
|
-
result.push s
|
201
|
-
end
|
202
|
-
result
|
226
|
+
@symbol_pins.uniq(&:label)
|
203
227
|
end
|
204
228
|
|
229
|
+
# @return [String]
|
205
230
|
def get_filename_for(node)
|
206
231
|
@sources.each do |filename, source|
|
207
232
|
return source.filename if source.include?(node)
|
@@ -209,6 +234,7 @@ module Solargraph
|
|
209
234
|
nil
|
210
235
|
end
|
211
236
|
|
237
|
+
# @return [String]
|
212
238
|
def infer_instance_variable(var, namespace, scope)
|
213
239
|
refresh
|
214
240
|
pins = @ivar_pins[namespace]
|
@@ -218,6 +244,7 @@ module Solargraph
|
|
218
244
|
pin.return_type
|
219
245
|
end
|
220
246
|
|
247
|
+
# @return [String]
|
221
248
|
def infer_class_variable(var, namespace)
|
222
249
|
refresh
|
223
250
|
fqns = find_fully_qualified_namespace(namespace)
|
@@ -228,11 +255,18 @@ module Solargraph
|
|
228
255
|
pin.return_type
|
229
256
|
end
|
230
257
|
|
258
|
+
# @return [Array<Solargraph::Suggestion>]
|
231
259
|
def get_global_variables
|
232
|
-
|
233
|
-
|
260
|
+
result = []
|
261
|
+
@sources.values.each do |s|
|
262
|
+
s.global_variable_pins.each do |p|
|
263
|
+
result.push pin_to_suggestion(p)
|
264
|
+
end
|
265
|
+
end
|
266
|
+
result
|
234
267
|
end
|
235
268
|
|
269
|
+
# @return [String]
|
236
270
|
def infer_assignment_node_type node, namespace
|
237
271
|
type = cache.get_assignment_node_type(node, namespace)
|
238
272
|
if type.nil?
|
@@ -261,6 +295,7 @@ module Solargraph
|
|
261
295
|
type
|
262
296
|
end
|
263
297
|
|
298
|
+
# @return [String]
|
264
299
|
def infer_signature_type signature, namespace, scope: :class
|
265
300
|
if cache.has_signature_type?(signature, namespace, scope)
|
266
301
|
return cache.get_signature_type(signature, namespace, scope)
|
@@ -322,16 +357,16 @@ module Solargraph
|
|
322
357
|
refresh
|
323
358
|
namespace = clean_namespace_string(namespace)
|
324
359
|
meths = []
|
325
|
-
meths
|
360
|
+
meths.concat inner_get_methods(namespace, root, []) #unless has_yardoc?
|
326
361
|
yard_meths = yard_map.get_methods(namespace, root, visibility: visibility)
|
327
362
|
if yard_meths.any?
|
328
363
|
meths.concat yard_meths
|
329
364
|
else
|
330
365
|
type = get_namespace_type(namespace, root)
|
331
366
|
if type == :class
|
332
|
-
meths
|
367
|
+
meths.concat yard_map.get_instance_methods('Class')
|
333
368
|
elsif type == :module
|
334
|
-
meths
|
369
|
+
meths.concat yard_map.get_methods('Module')
|
335
370
|
end
|
336
371
|
end
|
337
372
|
news = meths.select{|s| s.label == 'new'}
|
@@ -341,7 +376,7 @@ module Solargraph
|
|
341
376
|
inits = @method_pins[fqns].select{|p| p.name == 'initialize'}
|
342
377
|
meths -= news unless inits.empty?
|
343
378
|
inits.each do |pin|
|
344
|
-
meths.push Suggestion.new('new', kind: pin.kind,
|
379
|
+
meths.push Suggestion.new('new', kind: pin.kind, docstring: pin.docstring, detail: pin.namespace, arguments: pin.parameters, path: pin.path)
|
345
380
|
end
|
346
381
|
end
|
347
382
|
end
|
@@ -396,6 +431,27 @@ module Solargraph
|
|
396
431
|
@sources.values
|
397
432
|
end
|
398
433
|
|
434
|
+
def get_path_suggestions path
|
435
|
+
result = []
|
436
|
+
if path.include?('#')
|
437
|
+
# It's an instance method
|
438
|
+
parts = path.split('#')
|
439
|
+
result = get_instance_methods(parts[0], '', visibility: [:public, :private, :protected]).select{|s| s.label == parts[1]}
|
440
|
+
elsif path.include?('.')
|
441
|
+
# It's a class method
|
442
|
+
parts = path.split('.')
|
443
|
+
result = get_instance_methods(parts[0], '', visibility: [:public, :private, :protected]).select{|s| s.label == parts[1]}
|
444
|
+
else
|
445
|
+
# It's a class or module
|
446
|
+
get_namespace_nodes(path).each do |node|
|
447
|
+
# TODO This is way underimplemented
|
448
|
+
result.push Suggestion.new(path, kind: Suggestion::CLASS)
|
449
|
+
end
|
450
|
+
result.concat yard_map.objects(path)
|
451
|
+
end
|
452
|
+
result
|
453
|
+
end
|
454
|
+
|
399
455
|
private
|
400
456
|
|
401
457
|
def clear
|
@@ -409,8 +465,12 @@ module Solargraph
|
|
409
465
|
def process_maps
|
410
466
|
@sources.clear
|
411
467
|
@workspace_files.each do |f|
|
412
|
-
|
413
|
-
|
468
|
+
begin
|
469
|
+
@@source_cache[f] ||= Source.load(f)
|
470
|
+
@sources[f] = @@source_cache[f]
|
471
|
+
rescue
|
472
|
+
STDERR.puts "Failed to load #{f}"
|
473
|
+
end
|
414
474
|
end
|
415
475
|
cache.clear
|
416
476
|
@ivar_pins = {}
|
@@ -425,6 +485,7 @@ module Solargraph
|
|
425
485
|
@namespace_map = {}
|
426
486
|
@namespace_tree = {}
|
427
487
|
@required = []
|
488
|
+
@pin_suggestions = {}
|
428
489
|
unless @virtual_source.nil?
|
429
490
|
@sources[@virtual_filename] = @virtual_source
|
430
491
|
end
|
@@ -442,6 +503,31 @@ module Solargraph
|
|
442
503
|
@stale = false
|
443
504
|
end
|
444
505
|
|
506
|
+
def process_virtual
|
507
|
+
unless @virtual_source.nil?
|
508
|
+
cache.clear
|
509
|
+
@sources[@virtual_filename] = @virtual_source
|
510
|
+
@sources.values.each do |s|
|
511
|
+
s.namespace_nodes.each_pair do |k, v|
|
512
|
+
@namespace_map[k] ||= []
|
513
|
+
@namespace_map[k].concat v
|
514
|
+
add_to_namespace_tree k.split('::')
|
515
|
+
end
|
516
|
+
end
|
517
|
+
eliminate @virtual_filename
|
518
|
+
map_source @virtual_source
|
519
|
+
end
|
520
|
+
end
|
521
|
+
|
522
|
+
def eliminate filename
|
523
|
+
[@ivar_pins.values, @cvar_pins.values, @const_pins.values, @method_pins.values, @attr_pins.values].each do |pinsets|
|
524
|
+
pinsets.each do |pins|
|
525
|
+
pins.delete_if{|pin| pin.filename == filename}
|
526
|
+
end
|
527
|
+
end
|
528
|
+
#@symbol_pins.delete_if{|pin| pin.filename == filename}
|
529
|
+
end
|
530
|
+
|
445
531
|
# @param [Solargraph::ApiMap::Source]
|
446
532
|
def map_source source
|
447
533
|
source.method_pins.each do |pin|
|
@@ -484,7 +570,7 @@ module Solargraph
|
|
484
570
|
@cache ||= Cache.new
|
485
571
|
end
|
486
572
|
|
487
|
-
def inner_get_methods(namespace, root = '', skip = [])
|
573
|
+
def inner_get_methods(namespace, root = '', skip = [], visibility = [:public])
|
488
574
|
meths = []
|
489
575
|
return meths if skip.include?(namespace)
|
490
576
|
skip.push namespace
|
@@ -493,7 +579,14 @@ module Solargraph
|
|
493
579
|
mn = @method_pins[fqns]
|
494
580
|
unless mn.nil?
|
495
581
|
mn.select{ |pin| pin.scope == :class }.each do |pin|
|
496
|
-
meths.push
|
582
|
+
meths.push pin_to_suggestion(pin)
|
583
|
+
end
|
584
|
+
end
|
585
|
+
if visibility.include?(:public) or visibility.include?(:protected)
|
586
|
+
sc = @superclasses[fqns]
|
587
|
+
unless sc.nil?
|
588
|
+
meths.concat inner_get_methods(sc, fqns, skip, visibility - [:private])
|
589
|
+
meths.concat yard_map.get_methods(sc, fqns, visibility: visibility - [:private])
|
497
590
|
end
|
498
591
|
end
|
499
592
|
meths.uniq
|
@@ -507,13 +600,13 @@ module Solargraph
|
|
507
600
|
an = @attr_pins[fqns]
|
508
601
|
unless an.nil?
|
509
602
|
an.each do |pin|
|
510
|
-
meths.push
|
603
|
+
meths.push pin_to_suggestion(pin)
|
511
604
|
end
|
512
605
|
end
|
513
606
|
mn = @method_pins[fqns]
|
514
607
|
unless mn.nil?
|
515
608
|
mn.select{|pin| visibility.include?(pin.visibility) and pin.scope == :instance }.each do |pin|
|
516
|
-
meths.push
|
609
|
+
meths.push pin_to_suggestion(pin)
|
517
610
|
end
|
518
611
|
end
|
519
612
|
if visibility.include?(:public) or visibility.include?(:protected)
|
@@ -561,7 +654,7 @@ module Solargraph
|
|
561
654
|
cp = @const_pins[fqns]
|
562
655
|
unless cp.nil?
|
563
656
|
cp.each do |pin|
|
564
|
-
result.push
|
657
|
+
result.push pin_to_suggestion(pin)
|
565
658
|
end
|
566
659
|
end
|
567
660
|
inc = @namespace_includes[fqns]
|
@@ -582,85 +675,48 @@ module Solargraph
|
|
582
675
|
#
|
583
676
|
# @return [String] The fully qualified namespace for the signature's type
|
584
677
|
# or nil if a type could not be determined
|
585
|
-
def inner_infer_signature_type signature, namespace, scope: :instance
|
586
|
-
orig = namespace
|
587
|
-
namespace = clean_namespace_string(namespace)
|
678
|
+
def inner_infer_signature_type signature, namespace, scope: :instance, top: true
|
588
679
|
return nil if signature.nil?
|
589
680
|
signature.gsub!(/\.$/, '')
|
590
|
-
if signature.
|
681
|
+
if signature.empty?
|
591
682
|
if scope == :class
|
592
|
-
return "
|
683
|
+
return "Class<#{namespace}>"
|
593
684
|
else
|
594
685
|
return "#{namespace}"
|
595
686
|
end
|
596
687
|
end
|
597
|
-
if !namespace.nil? and namespace.end_with?('#class')
|
598
|
-
return inner_infer_signature_type signature, namespace[0..-7], scope: (scope == :class ? :instance : :class)
|
599
|
-
end
|
600
688
|
parts = signature.split('.')
|
601
|
-
type =
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
next if !type.nil? and !type.empty? and METHODS_RETURNING_SELF.include?(p)
|
608
|
-
if top and scope == :class
|
609
|
-
if p == 'self'
|
610
|
-
top = false
|
611
|
-
return "Class<#{type}>" if parts.empty?
|
612
|
-
sub = inner_infer_signature_type(parts.join('.'), type, scope: :class)
|
613
|
-
return sub unless sub.to_s == ''
|
614
|
-
next
|
615
|
-
end
|
616
|
-
if p == 'new'
|
617
|
-
scope = :instance
|
618
|
-
type = namespace
|
619
|
-
top = false
|
620
|
-
next
|
621
|
-
end
|
622
|
-
first_class = find_fully_qualified_namespace(p, namespace)
|
623
|
-
sub = nil
|
624
|
-
sub = inner_infer_signature_type(parts.join('.'), first_class, scope: :class) unless first_class.nil?
|
625
|
-
return sub unless sub.to_s == ''
|
689
|
+
type = namespace || ''
|
690
|
+
while (parts.length > 0)
|
691
|
+
part = parts.shift
|
692
|
+
if top == true and part == 'self'
|
693
|
+
top = false
|
694
|
+
next
|
626
695
|
end
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
696
|
+
cls_match = type.match(/^Class<([A-Za-z0-9_:]*?)>$/)
|
697
|
+
if cls_match
|
698
|
+
type = cls_match[1]
|
699
|
+
scope = :class
|
631
700
|
end
|
632
|
-
if
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
end
|
638
|
-
end
|
639
|
-
unless p == 'new' and scope != :instance
|
701
|
+
if scope == :class and part == 'new'
|
702
|
+
scope = :instance
|
703
|
+
elsif !METHODS_RETURNING_SELF.include?(part)
|
704
|
+
visibility = [:public]
|
705
|
+
visibility.concat [:private, :protected] if top
|
640
706
|
if scope == :instance
|
641
|
-
|
642
|
-
visibility.push :private, :protected if top
|
643
|
-
meths = get_instance_methods(type, visibility: visibility)
|
644
|
-
meths += get_methods('') if top or type.to_s == ''
|
707
|
+
meth = get_instance_methods(namespace, visibility: visibility).select{|s| s.label == part}.first
|
645
708
|
else
|
646
|
-
|
647
|
-
end
|
648
|
-
meths.delete_if{ |m| m.insert != p }
|
649
|
-
return nil if meths.empty?
|
650
|
-
type = nil
|
651
|
-
match = meths[0].return_type
|
652
|
-
unless match.nil?
|
653
|
-
cleaned = clean_namespace_string(match)
|
654
|
-
if cleaned.end_with?('#class')
|
655
|
-
return inner_infer_signature_type(parts.join('.'), cleaned.split('#').first, scope: :class)
|
656
|
-
else
|
657
|
-
type = find_fully_qualified_namespace(cleaned)
|
658
|
-
end
|
709
|
+
meth = get_methods(namespace, visibility: visibility).select{|s| s.label == part}.first
|
659
710
|
end
|
711
|
+
return nil if meth.nil? or meth.return_type.nil?
|
712
|
+
type = meth.return_type
|
713
|
+
scope = :instance
|
660
714
|
end
|
661
|
-
scope = :instance
|
662
715
|
top = false
|
663
716
|
end
|
717
|
+
if scope == :class
|
718
|
+
type = "Class<#{type}>"
|
719
|
+
end
|
664
720
|
type
|
665
721
|
end
|
666
722
|
|
@@ -685,13 +741,10 @@ module Solargraph
|
|
685
741
|
result
|
686
742
|
end
|
687
743
|
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
return nil if pin.name == pin.signature.split('.').first
|
693
|
-
infer_signature_type(pin.signature, pin.namespace)
|
744
|
+
# @param pin [Solargraph::Pin::Base]
|
745
|
+
# @return [Solargraph::Suggestion]
|
746
|
+
def pin_to_suggestion pin
|
747
|
+
@pin_suggestions[pin] ||= Suggestion.pull(pin)
|
694
748
|
end
|
695
|
-
|
696
749
|
end
|
697
750
|
end
|