solargraph 0.13.0 → 0.13.1
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/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
|