solargraph 0.17.4 → 0.18.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.rb +16 -12
- data/lib/solargraph/api_map.rb +516 -588
- data/lib/solargraph/api_map/completion.rb +16 -0
- data/lib/solargraph/api_map/source_to_yard.rb +2 -2
- data/lib/solargraph/language_server.rb +12 -0
- data/lib/solargraph/language_server/completion_item_kinds.rb +31 -0
- data/lib/solargraph/language_server/error_codes.rb +16 -0
- data/lib/solargraph/language_server/host.rb +305 -0
- data/lib/solargraph/language_server/message.rb +70 -0
- data/lib/solargraph/language_server/message/base.rb +64 -0
- data/lib/solargraph/language_server/message/cancel_request.rb +11 -0
- data/lib/solargraph/language_server/message/client.rb +5 -0
- data/lib/solargraph/language_server/message/client/register_capability.rb +13 -0
- data/lib/solargraph/language_server/message/completion_item.rb +9 -0
- data/lib/solargraph/language_server/message/completion_item/resolve.rb +23 -0
- data/lib/solargraph/language_server/message/exit_notification.rb +12 -0
- data/lib/solargraph/language_server/message/extended.rb +15 -0
- data/lib/solargraph/language_server/message/extended/document.rb +18 -0
- data/lib/solargraph/language_server/message/extended/search.rb +18 -0
- data/lib/solargraph/language_server/message/initialize.rb +39 -0
- data/lib/solargraph/language_server/message/initialized.rb +10 -0
- data/lib/solargraph/language_server/message/method_not_found.rb +14 -0
- data/lib/solargraph/language_server/message/method_not_implemented.rb +12 -0
- data/lib/solargraph/language_server/message/shutdown.rb +11 -0
- data/lib/solargraph/language_server/message/text_document.rb +21 -0
- data/lib/solargraph/language_server/message/text_document/base.rb +17 -0
- data/lib/solargraph/language_server/message/text_document/completion.rb +69 -0
- data/lib/solargraph/language_server/message/text_document/definition.rb +38 -0
- data/lib/solargraph/language_server/message/text_document/did_change.rb +15 -0
- data/lib/solargraph/language_server/message/text_document/did_close.rb +12 -0
- data/lib/solargraph/language_server/message/text_document/did_open.rb +13 -0
- data/lib/solargraph/language_server/message/text_document/did_save.rb +15 -0
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +31 -0
- data/lib/solargraph/language_server/message/text_document/formatting.rb +36 -0
- data/lib/solargraph/language_server/message/text_document/hover.rb +19 -0
- data/lib/solargraph/language_server/message/text_document/on_type_formatting.rb +29 -0
- data/lib/solargraph/language_server/message/text_document/signature_help.rb +23 -0
- data/lib/solargraph/language_server/message/workspace.rb +11 -0
- data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +9 -0
- data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +30 -0
- data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +31 -0
- data/lib/solargraph/language_server/symbol_kinds.rb +32 -0
- data/lib/solargraph/language_server/transport.rb +7 -0
- data/lib/solargraph/language_server/transport/socket.rb +66 -0
- data/lib/solargraph/language_server/uri_helpers.rb +21 -0
- data/lib/solargraph/library.rb +225 -0
- data/lib/solargraph/live_map.rb +1 -1
- data/lib/solargraph/page.rb +61 -0
- data/lib/solargraph/pin.rb +7 -0
- data/lib/solargraph/pin/attribute.rb +9 -0
- data/lib/solargraph/pin/base.rb +76 -6
- data/lib/solargraph/pin/base_variable.rb +29 -7
- data/lib/solargraph/pin/block_parameter.rb +53 -0
- data/lib/solargraph/pin/constant.rb +6 -2
- data/lib/solargraph/pin/conversions.rb +65 -0
- data/lib/solargraph/pin/directed/attribute.rb +4 -0
- data/lib/solargraph/pin/directed/method.rb +6 -1
- data/lib/solargraph/pin/helper.rb +35 -0
- data/lib/solargraph/pin/keyword.rb +22 -0
- data/lib/solargraph/pin/local_variable.rb +0 -1
- data/lib/solargraph/pin/method.rb +55 -2
- data/lib/solargraph/pin/method_parameter.rb +19 -0
- data/lib/solargraph/pin/namespace.rb +7 -2
- data/lib/solargraph/pin/parameter.rb +23 -0
- data/lib/solargraph/pin/plugin/method.rb +3 -2
- data/lib/solargraph/pin/yard_object.rb +101 -0
- data/lib/solargraph/server.rb +82 -135
- data/lib/solargraph/shell.rb +20 -1
- data/lib/solargraph/source.rb +709 -0
- data/lib/solargraph/source/flawed_builder.rb +10 -0
- data/lib/solargraph/source/fragment.rb +319 -0
- data/lib/solargraph/source/position.rb +26 -0
- data/lib/solargraph/source/range.rb +39 -0
- data/lib/solargraph/suggestion.rb +29 -4
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace.rb +105 -0
- data/lib/solargraph/{api_map → workspace}/config.rb +1 -1
- data/lib/solargraph/yard_map.rb +59 -37
- metadata +168 -5
- data/lib/solargraph/api_map/source.rb +0 -470
- data/lib/solargraph/code_map.rb +0 -868
@@ -1,470 +0,0 @@
|
|
1
|
-
require 'parser/current'
|
2
|
-
|
3
|
-
module Solargraph
|
4
|
-
class ApiMap
|
5
|
-
class Source
|
6
|
-
class FlawedBuilder < Parser::Builders::Default
|
7
|
-
def string_value(token)
|
8
|
-
value(token)
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
# @return [String]
|
13
|
-
attr_reader :code
|
14
|
-
|
15
|
-
# @return [Parser::AST::Node]
|
16
|
-
attr_reader :node
|
17
|
-
|
18
|
-
# @return [Array]
|
19
|
-
attr_reader :comments
|
20
|
-
|
21
|
-
# @return [String]
|
22
|
-
attr_reader :filename
|
23
|
-
|
24
|
-
attr_reader :mtime
|
25
|
-
|
26
|
-
# @return [Array<Integer>]
|
27
|
-
attr_reader :stubbed_lines
|
28
|
-
|
29
|
-
attr_reader :directives
|
30
|
-
|
31
|
-
attr_reader :path_macros
|
32
|
-
|
33
|
-
include NodeMethods
|
34
|
-
|
35
|
-
def initialize code, node, comments, filename, stubbed_lines = []
|
36
|
-
@code = code
|
37
|
-
root = AST::Node.new(:source, [filename])
|
38
|
-
root = root.append node
|
39
|
-
@node = root
|
40
|
-
@comments = comments
|
41
|
-
@directives = {}
|
42
|
-
@path_macros = {}
|
43
|
-
@docstring_hash = associate_comments(node, comments) || {}
|
44
|
-
@filename = filename
|
45
|
-
@mtime = (!filename.nil? and File.exist?(filename) ? File.mtime(filename) : nil)
|
46
|
-
@namespace_nodes = {}
|
47
|
-
@all_nodes = []
|
48
|
-
@node_stack = []
|
49
|
-
@node_tree = {}
|
50
|
-
@stubbed_lines = stubbed_lines
|
51
|
-
inner_map_node @node
|
52
|
-
@directives.each_pair do |k, v|
|
53
|
-
v.each do |d|
|
54
|
-
ns = namespace_for(k.node)
|
55
|
-
docstring = YARD::Docstring.parser.parse(d.tag.text).to_docstring
|
56
|
-
if d.tag.tag_name == 'attribute'
|
57
|
-
t = (d.tag.types.nil? || d.tag.types.empty?) ? nil : d.tag.types.flatten.join('')
|
58
|
-
if t.nil? or t.include?('r')
|
59
|
-
attribute_pins.push Solargraph::Pin::Directed::Attribute.new(self, k.node, ns, :reader, docstring, d.tag.name)
|
60
|
-
end
|
61
|
-
if t.nil? or t.include?('w')
|
62
|
-
attribute_pins.push Solargraph::Pin::Directed::Attribute.new(self, k.node, ns, :writer, docstring, "#{d.tag.name}=")
|
63
|
-
end
|
64
|
-
elsif d.tag.tag_name == 'method'
|
65
|
-
gen_src = Source.virtual("def #{d.tag.name};end", filename)
|
66
|
-
gen_pin = gen_src.method_pins.first
|
67
|
-
method_pins.push Solargraph::Pin::Directed::Method.new(gen_src, gen_pin.node, ns, :instance, :public, docstring, gen_pin.name)
|
68
|
-
elsif d.tag.tag_name == 'macro'
|
69
|
-
# @todo Handle various types of macros (attach, new, whatever)
|
70
|
-
path = path_for(k.node)
|
71
|
-
@path_macros[path] = v
|
72
|
-
else
|
73
|
-
STDERR.puts "Nothing to do for directive: #{d}"
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
def macro path
|
80
|
-
@path_macros[path]
|
81
|
-
end
|
82
|
-
|
83
|
-
def namespaces
|
84
|
-
@namespace_nodes.keys
|
85
|
-
end
|
86
|
-
|
87
|
-
def namespace_nodes
|
88
|
-
@namespace_nodes
|
89
|
-
end
|
90
|
-
|
91
|
-
def namespace_includes
|
92
|
-
@namespace_includes ||= {}
|
93
|
-
end
|
94
|
-
|
95
|
-
def namespace_extends
|
96
|
-
@namespaces_extends ||= {}
|
97
|
-
end
|
98
|
-
|
99
|
-
def superclasses
|
100
|
-
@superclasses ||= {}
|
101
|
-
end
|
102
|
-
|
103
|
-
# @return [Array<Solargraph::Pin::Method>]
|
104
|
-
def method_pins
|
105
|
-
@method_pins ||= []
|
106
|
-
end
|
107
|
-
|
108
|
-
# @return [Array<Solargraph::Pin::Attribute>]
|
109
|
-
def attribute_pins
|
110
|
-
@attribute_pins ||= []
|
111
|
-
end
|
112
|
-
|
113
|
-
# @return [Array<Solargraph::Pin::InstanceVariable>]
|
114
|
-
def instance_variable_pins
|
115
|
-
@instance_variable_pins ||= []
|
116
|
-
end
|
117
|
-
|
118
|
-
# @return [Array<Solargraph::Pin::ClassVariable>]
|
119
|
-
def class_variable_pins
|
120
|
-
@class_variable_pins ||= []
|
121
|
-
end
|
122
|
-
|
123
|
-
# @return [Array<Solargraph::Pin::LocalVariable>]
|
124
|
-
def local_variable_pins
|
125
|
-
@local_variable_pins ||= []
|
126
|
-
end
|
127
|
-
|
128
|
-
# @return [Array<Solargraph::Pin::GlobalVariable>]
|
129
|
-
def global_variable_pins
|
130
|
-
@global_variable_pins ||= []
|
131
|
-
end
|
132
|
-
|
133
|
-
# @return [Array<Solargraph::Pin::Constant>]
|
134
|
-
def constant_pins
|
135
|
-
@constant_pins ||= []
|
136
|
-
end
|
137
|
-
|
138
|
-
# @return [Array<Solargraph::Pin::Symbol>]
|
139
|
-
def symbol_pins
|
140
|
-
@symbol_pins ||= []
|
141
|
-
end
|
142
|
-
|
143
|
-
# @return [Array<Solargraph::Pin::Namespace>]
|
144
|
-
def namespace_pins
|
145
|
-
@namespace_pins ||= []
|
146
|
-
end
|
147
|
-
|
148
|
-
# @return [Array<String>]
|
149
|
-
def required
|
150
|
-
@required ||= []
|
151
|
-
end
|
152
|
-
|
153
|
-
# @return [YARD::Docstring]
|
154
|
-
def docstring_for node
|
155
|
-
return @docstring_hash[node.loc] if node.respond_to?(:loc)
|
156
|
-
nil
|
157
|
-
end
|
158
|
-
|
159
|
-
# @return [String]
|
160
|
-
def code_for node
|
161
|
-
b = node.location.expression.begin.begin_pos
|
162
|
-
e = node.location.expression.end.end_pos
|
163
|
-
frag = code[b..e-1].to_s
|
164
|
-
frag.strip.gsub(/,$/, '')
|
165
|
-
end
|
166
|
-
|
167
|
-
def tree_for node
|
168
|
-
@node_tree[node] || []
|
169
|
-
end
|
170
|
-
|
171
|
-
# @return [String]
|
172
|
-
def namespace_for node
|
173
|
-
parts = []
|
174
|
-
([node] + (@node_tree[node] || [])).each do |n|
|
175
|
-
if n.type == :class or n.type == :module
|
176
|
-
parts.unshift unpack_name(n.children[0])
|
177
|
-
end
|
178
|
-
end
|
179
|
-
parts.join('::')
|
180
|
-
end
|
181
|
-
|
182
|
-
def path_for node
|
183
|
-
path = namespace_for(node) || ''
|
184
|
-
mp = (method_pins + attribute_pins).select{|p| p.node == node}.first
|
185
|
-
unless mp.nil?
|
186
|
-
path += (mp.scope == :instance ? '#' : '.') + mp.name
|
187
|
-
end
|
188
|
-
path
|
189
|
-
end
|
190
|
-
|
191
|
-
def include? node
|
192
|
-
@all_nodes.include? node
|
193
|
-
end
|
194
|
-
|
195
|
-
private
|
196
|
-
|
197
|
-
def associate_comments node, comments
|
198
|
-
return nil if comments.nil?
|
199
|
-
comment_hash = Parser::Source::Comment.associate_locations(node, comments)
|
200
|
-
yard_hash = {}
|
201
|
-
comment_hash.each_pair { |k, v|
|
202
|
-
ctxt = ''
|
203
|
-
num = nil
|
204
|
-
started = false
|
205
|
-
v.each { |l|
|
206
|
-
# Trim the comment and minimum leading whitespace
|
207
|
-
p = l.text.gsub(/^#/, '')
|
208
|
-
if num.nil? and !p.strip.empty?
|
209
|
-
num = p.index(/[^ ]/)
|
210
|
-
started = true
|
211
|
-
elsif started and !p.strip.empty?
|
212
|
-
cur = p.index(/[^ ]/)
|
213
|
-
num = cur if cur < num
|
214
|
-
end
|
215
|
-
if started
|
216
|
-
ctxt += "#{p[num..-1]}\n"
|
217
|
-
end
|
218
|
-
}
|
219
|
-
parse = YARD::Docstring.parser.parse(ctxt)
|
220
|
-
unless parse.directives.empty?
|
221
|
-
@directives[k] ||= []
|
222
|
-
@directives[k].concat parse.directives
|
223
|
-
end
|
224
|
-
yard_hash[k] = parse.to_docstring
|
225
|
-
}
|
226
|
-
yard_hash
|
227
|
-
end
|
228
|
-
|
229
|
-
def inner_map_node node, tree = [], visibility = :public, scope = :instance, fqn = nil, stack = []
|
230
|
-
stack.push node
|
231
|
-
source = self
|
232
|
-
if node.kind_of?(AST::Node)
|
233
|
-
@all_nodes.push node
|
234
|
-
if node.type == :str or node.type == :dstr
|
235
|
-
stack.pop
|
236
|
-
return
|
237
|
-
end
|
238
|
-
@node_stack.unshift node
|
239
|
-
if node.type == :class or node.type == :module
|
240
|
-
visibility = :public
|
241
|
-
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
|
242
|
-
tree = pack_name(node.children[0])
|
243
|
-
else
|
244
|
-
tree = tree + pack_name(node.children[0])
|
245
|
-
end
|
246
|
-
fqn = tree.join('::')
|
247
|
-
@namespace_nodes[fqn] ||= []
|
248
|
-
@namespace_nodes[fqn].push node
|
249
|
-
namespace_pins.push Solargraph::Pin::Namespace.new(self, node, tree[0..-2].join('::') || '', :public)
|
250
|
-
if node.type == :class and !node.children[1].nil?
|
251
|
-
sc = unpack_name(node.children[1])
|
252
|
-
superclasses[fqn] = sc
|
253
|
-
end
|
254
|
-
end
|
255
|
-
file = source.filename
|
256
|
-
node.children.each do |c|
|
257
|
-
if c.kind_of?(AST::Node)
|
258
|
-
@node_tree[c] = @node_stack.clone
|
259
|
-
if c.type == :ivasgn
|
260
|
-
par = find_parent(stack, :class, :module, :def, :defs)
|
261
|
-
local_scope = ( (par.kind_of?(AST::Node) and par.type == :def) ? :instance : :class )
|
262
|
-
if c.children[1].nil?
|
263
|
-
ora = find_parent(stack, :or_asgn)
|
264
|
-
unless ora.nil?
|
265
|
-
u = c.updated(:ivasgn, c.children + ora.children[1..-1], nil)
|
266
|
-
@node_tree[u] = @node_stack.clone
|
267
|
-
@docstring_hash[u.loc] = docstring_for(ora)
|
268
|
-
instance_variable_pins.push Solargraph::Pin::InstanceVariable.new(self, u, fqn || '', local_scope)
|
269
|
-
end
|
270
|
-
else
|
271
|
-
instance_variable_pins.push Solargraph::Pin::InstanceVariable.new(self, c, fqn || '', local_scope)
|
272
|
-
end
|
273
|
-
elsif c.type == :cvasgn
|
274
|
-
if c.children[1].nil?
|
275
|
-
ora = find_parent(stack, :or_asgn)
|
276
|
-
unless ora.nil?
|
277
|
-
u = c.updated(:cvasgn, c.children + ora.children[1..-1], nil)
|
278
|
-
@node_tree[u] = @node_stack.clone
|
279
|
-
@docstring_hash[u.loc] = docstring_for(ora)
|
280
|
-
class_variable_pins.push Solargraph::Pin::ClassVariable.new(self, u, fqn || '')
|
281
|
-
end
|
282
|
-
else
|
283
|
-
class_variable_pins.push Solargraph::Pin::ClassVariable.new(self, c, fqn || '')
|
284
|
-
end
|
285
|
-
elsif c.type == :lvasgn
|
286
|
-
if c.children[1].nil?
|
287
|
-
ora = find_parent(stack, :or_asgn)
|
288
|
-
unless ora.nil?
|
289
|
-
u = c.updated(:lvasgn, c.children + ora.children[1..-1], nil)
|
290
|
-
@node_tree[u] = @node_stack.clone
|
291
|
-
@docstring_hash[u.loc] = docstring_for(ora)
|
292
|
-
local_variable_pins.push Solargraph::Pin::LocalVariable.new(self, u, fqn || '', @node_stack.clone)
|
293
|
-
end
|
294
|
-
else
|
295
|
-
@node_tree[c] = @node_stack.clone
|
296
|
-
local_variable_pins.push Solargraph::Pin::LocalVariable.new(self, c, fqn || '', @node_stack.clone)
|
297
|
-
end
|
298
|
-
elsif c.type == :gvasgn
|
299
|
-
global_variable_pins.push Solargraph::Pin::GlobalVariable.new(self, c, fqn || '')
|
300
|
-
elsif c.type == :sym
|
301
|
-
symbol_pins.push Solargraph::Pin::Symbol.new(self, c, fqn)
|
302
|
-
elsif c.type == :casgn
|
303
|
-
constant_pins.push Solargraph::Pin::Constant.new(self, c, fqn, :public)
|
304
|
-
else
|
305
|
-
if c.kind_of?(AST::Node)
|
306
|
-
if c.type == :def and c.children[0].to_s[0].match(/[a-z]/i)
|
307
|
-
method_pins.push Solargraph::Pin::Method.new(source, c, fqn || '', scope, visibility)
|
308
|
-
elsif c.type == :defs
|
309
|
-
s_visi = visibility
|
310
|
-
s_visi = :public if scope != :class
|
311
|
-
method_pins.push Solargraph::Pin::Method.new(source, c, fqn || '', :class, s_visi)
|
312
|
-
inner_map_node c, tree, scope, :class, fqn, stack
|
313
|
-
next
|
314
|
-
elsif c.type == :send and [:public, :protected, :private].include?(c.children[1])
|
315
|
-
visibility = c.children[1]
|
316
|
-
elsif c.type == :send and [:private_class_method].include?(c.children[1]) and c.children[2].kind_of?(AST::Node)
|
317
|
-
if c.children[2].type == :sym or c.children[2].type == :str
|
318
|
-
ref = method_pins.select{|p| p.name == c.children[2].children[0].to_s}.first
|
319
|
-
unless ref.nil?
|
320
|
-
source.method_pins.delete ref
|
321
|
-
source.method_pins.push Solargraph::Pin::Method.new(ref.source, ref.node, ref.namespace, ref.scope, :private)
|
322
|
-
end
|
323
|
-
else
|
324
|
-
inner_map_node c, tree, :private, :class, fqn, stack
|
325
|
-
next
|
326
|
-
end
|
327
|
-
elsif c.type == :send and [:private_constant].include?(c.children[1]) and c.children[2].kind_of?(AST::Node)
|
328
|
-
if c.children[2].type == :sym or c.children[2].type == :str
|
329
|
-
cn = c.children[2].children[0].to_s
|
330
|
-
ref = constant_pins.select{|p| p.name == cn}.first
|
331
|
-
if ref.nil?
|
332
|
-
ref = namespace_pins.select{|p| p.name == cn}.first
|
333
|
-
unless ref.nil?
|
334
|
-
source.namespace_pins.delete ref
|
335
|
-
source.namespace_pins.push Solargraph::Pin::Namespace.new(ref.source, ref.node, ref.namespace, :private)
|
336
|
-
end
|
337
|
-
else
|
338
|
-
source.constant_pins.delete ref
|
339
|
-
source.constant_pins.push Solargraph::Pin::Constant.new(ref.source, ref.node, ref.namespace, :private)
|
340
|
-
end
|
341
|
-
end
|
342
|
-
next
|
343
|
-
elsif c.type == :send and c.children[1] == :include
|
344
|
-
namespace_includes[fqn] ||= []
|
345
|
-
c.children[2..-1].each do |i|
|
346
|
-
namespace_includes[fqn].push unpack_name(i)
|
347
|
-
end
|
348
|
-
elsif c.type == :send and c.children[1] == :extend
|
349
|
-
namespace_extends[fqn] ||= []
|
350
|
-
c.children[2..-1].each do |i|
|
351
|
-
namespace_extends[fqn].push unpack_name(i)
|
352
|
-
end
|
353
|
-
elsif c.type == :send and [:attr_reader, :attr_writer, :attr_accessor].include?(c.children[1])
|
354
|
-
c.children[2..-1].each do |a|
|
355
|
-
if c.children[1] == :attr_reader or c.children[1] == :attr_accessor
|
356
|
-
attribute_pins.push Solargraph::Pin::Attribute.new(self, a, fqn || '', :reader, docstring_for(c)) #AttrPin.new(c)
|
357
|
-
end
|
358
|
-
if c.children[1] == :attr_writer or c.children[1] == :attr_accessor
|
359
|
-
attribute_pins.push Solargraph::Pin::Attribute.new(self, a, fqn || '', :writer, docstring_for(c)) #AttrPin.new(c)
|
360
|
-
end
|
361
|
-
end
|
362
|
-
elsif c.type == :sclass and c.children[0].type == :self
|
363
|
-
inner_map_node c, tree, :public, :class, fqn || '', stack
|
364
|
-
next
|
365
|
-
end
|
366
|
-
end
|
367
|
-
if c.type == :send and c.children[1] == :require
|
368
|
-
if c.children[2].kind_of?(AST::Node) and c.children[2].type == :str
|
369
|
-
required.push c.children[2].children[0].to_s
|
370
|
-
end
|
371
|
-
end
|
372
|
-
end
|
373
|
-
inner_map_node c, tree, visibility, scope, fqn, stack
|
374
|
-
end
|
375
|
-
end
|
376
|
-
@node_stack.shift
|
377
|
-
end
|
378
|
-
stack.pop
|
379
|
-
end
|
380
|
-
|
381
|
-
def find_parent(stack, *types)
|
382
|
-
stack.reverse.each { |p|
|
383
|
-
return p if types.include?(p.type)
|
384
|
-
}
|
385
|
-
nil
|
386
|
-
end
|
387
|
-
|
388
|
-
class << self
|
389
|
-
# @return [Solargraph::ApiMap::Source]
|
390
|
-
def load filename
|
391
|
-
Source.virtual(File.read(filename), filename)
|
392
|
-
end
|
393
|
-
|
394
|
-
# @return [Solargraph::ApiMap::Source]
|
395
|
-
def virtual code, filename = nil
|
396
|
-
node, comments = Source.parse(code, filename)
|
397
|
-
Source.new(code, node, comments, filename)
|
398
|
-
end
|
399
|
-
|
400
|
-
def get_position_at(code, offset)
|
401
|
-
cursor = 0
|
402
|
-
line = 0
|
403
|
-
col = nil
|
404
|
-
code.each_line do |l|
|
405
|
-
if cursor + l.length >= offset
|
406
|
-
col = offset - cursor
|
407
|
-
break
|
408
|
-
end
|
409
|
-
cursor += l.length
|
410
|
-
line += 1
|
411
|
-
end
|
412
|
-
raise "Invalid offset" if col.nil?
|
413
|
-
[line, col]
|
414
|
-
end
|
415
|
-
|
416
|
-
def parse code, filename = nil
|
417
|
-
parser = Parser::CurrentRuby.new(FlawedBuilder.new)
|
418
|
-
parser.diagnostics.all_errors_are_fatal = true
|
419
|
-
parser.diagnostics.ignore_warnings = true
|
420
|
-
buffer = Parser::Source::Buffer.new(filename, 1)
|
421
|
-
buffer.source = code
|
422
|
-
parser.parse_with_comments(buffer)
|
423
|
-
end
|
424
|
-
|
425
|
-
def fix code, filename = nil, offset = nil
|
426
|
-
tries = 0
|
427
|
-
code.gsub!(/\r/, '')
|
428
|
-
offset = CodeMap.get_offset(code, offset[0], offset[1]) if offset.kind_of?(Array)
|
429
|
-
pos = nil
|
430
|
-
pos = get_position_at(code, offset) unless offset.nil?
|
431
|
-
stubs = []
|
432
|
-
fixed_position = false
|
433
|
-
tmp = code
|
434
|
-
begin
|
435
|
-
node, comments = parse(tmp, filename)
|
436
|
-
Source.new(code, node, comments, filename, stubs)
|
437
|
-
rescue Parser::SyntaxError => e
|
438
|
-
if tries < 10
|
439
|
-
tries += 1
|
440
|
-
# Stub periods before the offset to retain the expected node tree
|
441
|
-
if !offset.nil? and tmp[offset-1] == '.'
|
442
|
-
tmp = tmp[0, offset-1] + ';' + tmp[offset..-1]
|
443
|
-
elsif !fixed_position and !offset.nil?
|
444
|
-
fixed_position = true
|
445
|
-
beg = beginning_of_line_from(tmp, offset)
|
446
|
-
tmp = "#{tmp[0, beg]}##{tmp[beg+1..-1]}"
|
447
|
-
stubs.push(pos[0])
|
448
|
-
elsif e.message.include?('token $end')
|
449
|
-
tmp += "\nend"
|
450
|
-
elsif e.message.include?("unexpected `@'")
|
451
|
-
tmp = tmp[0, e.diagnostic.location.begin_pos] + '_' + tmp[e.diagnostic.location.begin_pos+1..-1]
|
452
|
-
end
|
453
|
-
retry
|
454
|
-
end
|
455
|
-
STDERR.puts "Unable to parse file #{filename.nil? ? 'undefined' : filename}: #{e.message}"
|
456
|
-
node, comments = parse(code.gsub(/[^\s]/, ' '), filename)
|
457
|
-
Source.new(code, node, comments, filename)
|
458
|
-
end
|
459
|
-
end
|
460
|
-
|
461
|
-
def beginning_of_line_from str, i
|
462
|
-
while i > 0 and str[i-1] != "\n"
|
463
|
-
i -= 1
|
464
|
-
end
|
465
|
-
i
|
466
|
-
end
|
467
|
-
end
|
468
|
-
end
|
469
|
-
end
|
470
|
-
end
|