solargraph 0.21.1 → 0.22.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 +0 -1
- data/lib/solargraph/api_map.rb +40 -23
- data/lib/solargraph/api_map/completion.rb +3 -0
- data/lib/solargraph/api_map/probe.rb +16 -19
- data/lib/solargraph/api_map/store.rb +6 -2
- data/lib/solargraph/diagnostics/rubocop.rb +6 -0
- data/lib/solargraph/language_server/host.rb +9 -1
- data/lib/solargraph/language_server/message.rb +3 -0
- data/lib/solargraph/language_server/message/extended.rb +1 -0
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +1 -1
- data/lib/solargraph/language_server/message/extended/download_core.rb +25 -0
- data/lib/solargraph/language_server/message/initialize.rb +3 -1
- data/lib/solargraph/language_server/message/text_document.rb +13 -11
- data/lib/solargraph/language_server/message/text_document/definition.rb +1 -1
- data/lib/solargraph/language_server/message/text_document/hover.rb +1 -1
- data/lib/solargraph/language_server/message/text_document/references.rb +14 -0
- data/lib/solargraph/language_server/message/text_document/rename.rb +17 -0
- data/lib/solargraph/language_server/uri_helpers.rb +2 -0
- data/lib/solargraph/library.rb +37 -0
- data/lib/solargraph/live_map.rb +8 -2
- data/lib/solargraph/live_map/cache.rb +7 -0
- data/lib/solargraph/pin.rb +1 -0
- data/lib/solargraph/pin/attribute.rb +5 -1
- data/lib/solargraph/pin/namespace.rb +0 -2
- data/lib/solargraph/pin/proxy_method.rb +31 -0
- data/lib/solargraph/plugin/process.rb +1 -1
- data/lib/solargraph/plugin/runtime.rb +0 -1
- data/lib/solargraph/shell.rb +0 -1
- data/lib/solargraph/source.rb +31 -1
- data/lib/solargraph/source/fragment.rb +12 -15
- data/lib/solargraph/source/location.rb +3 -0
- data/lib/solargraph/source/mapper.rb +20 -10
- data/lib/solargraph/source/node_methods.rb +111 -0
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace.rb +7 -1
- data/lib/solargraph/workspace/config.rb +6 -2
- data/lib/solargraph/yard_map.rb +12 -1
- metadata +25 -7
- data/lib/solargraph/node_methods.rb +0 -101
@@ -0,0 +1,14 @@
|
|
1
|
+
module Solargraph::LanguageServer::Message::TextDocument
|
2
|
+
class References < Base
|
3
|
+
def process
|
4
|
+
locs = host.references_from(uri_to_file(params['textDocument']['uri']), params['position']['line'], params['position']['character'])
|
5
|
+
result = locs.map do |loc|
|
6
|
+
{
|
7
|
+
uri: file_to_uri(loc.filename),
|
8
|
+
range: loc.range.to_hash
|
9
|
+
}
|
10
|
+
end
|
11
|
+
set_result result
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Solargraph::LanguageServer::Message::TextDocument
|
2
|
+
class Rename < Base
|
3
|
+
def process
|
4
|
+
locs = host.references_from(uri_to_file(params['textDocument']['uri']), params['position']['line'], params['position']['character'])
|
5
|
+
changes = {}
|
6
|
+
locs.each do |loc|
|
7
|
+
uri = file_to_uri(loc.filename)
|
8
|
+
changes[uri] ||= []
|
9
|
+
changes[uri].push({
|
10
|
+
range: loc.range.to_hash,
|
11
|
+
newText: params['newName']
|
12
|
+
})
|
13
|
+
end
|
14
|
+
set_result changes: changes
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/solargraph/library.rb
CHANGED
@@ -141,6 +141,30 @@ module Solargraph
|
|
141
141
|
api_map.signify(fragment)
|
142
142
|
end
|
143
143
|
|
144
|
+
def references_from filename, line, column
|
145
|
+
source = read(filename)
|
146
|
+
api_map.virtualize source
|
147
|
+
fragment = source.fragment_at(line, column)
|
148
|
+
pins = api_map.define(fragment)
|
149
|
+
return [] if pins.empty?
|
150
|
+
result = []
|
151
|
+
# @param pin [Solargraph::Pin::Base]
|
152
|
+
pins.uniq.each do |pin|
|
153
|
+
if pin.kind != Solargraph::Pin::NAMESPACE and !pin.location.nil?
|
154
|
+
mn_loc = get_symbol_name_location(pin)
|
155
|
+
result.push mn_loc unless mn_loc.nil?
|
156
|
+
end
|
157
|
+
(workspace.sources + source_hash.values).uniq(&:filename).each do |source|
|
158
|
+
found = source.references(pin.name).select do |loc|
|
159
|
+
referenced = definitions_at(loc.filename, loc.range.ending.line, loc.range.ending.character).first
|
160
|
+
!referenced.nil? and referenced.path == pin.path
|
161
|
+
end
|
162
|
+
result.concat found.sort{|a, b| a.range.start.line <=> b.range.start.line}
|
163
|
+
end
|
164
|
+
end
|
165
|
+
result
|
166
|
+
end
|
167
|
+
|
144
168
|
# Get the pin at the specified location or nil if the pin does not exist.
|
145
169
|
#
|
146
170
|
# @return [Solargraph::Pin::Base]
|
@@ -270,5 +294,18 @@ module Solargraph
|
|
270
294
|
raise FileNotFoundError, "File not found: #{filename}" unless File.file?(filename)
|
271
295
|
Solargraph::Source.load(filename)
|
272
296
|
end
|
297
|
+
|
298
|
+
def get_symbol_name_location pin
|
299
|
+
decsrc = read(pin.location.filename)
|
300
|
+
offset = Solargraph::Source::Position.to_offset(decsrc.code, pin.location.range.start)
|
301
|
+
soff = decsrc.code.index(pin.name, offset)
|
302
|
+
eoff = soff + pin.name.length
|
303
|
+
Solargraph::Source::Location.new(
|
304
|
+
pin.location.filename, Solargraph::Source::Range.new(
|
305
|
+
Solargraph::Source::Position.from_offset(decsrc.code, soff),
|
306
|
+
Solargraph::Source::Position.from_offset(decsrc.code, eoff)
|
307
|
+
)
|
308
|
+
)
|
309
|
+
end
|
273
310
|
end
|
274
311
|
end
|
data/lib/solargraph/live_map.rb
CHANGED
@@ -9,11 +9,17 @@ module Solargraph
|
|
9
9
|
# @return [Solargraph::ApiMap]
|
10
10
|
attr_reader :api_map
|
11
11
|
|
12
|
+
# @param api_map [Solargraph::ApiMap]
|
12
13
|
def initialize api_map
|
13
14
|
@api_map = api_map
|
14
15
|
runners
|
15
16
|
end
|
16
17
|
|
18
|
+
def get_path_pin path
|
19
|
+
cache.get_path_pin(path)
|
20
|
+
end
|
21
|
+
|
22
|
+
# @return [Array<Solargraph::Pin::Base>]
|
17
23
|
def get_methods(namespace, root = '', scope = 'instance', with_private = false)
|
18
24
|
fqns = api_map.find_fully_qualified_namespace(namespace, root)
|
19
25
|
params = {
|
@@ -26,7 +32,7 @@ module Solargraph
|
|
26
32
|
runners.each do |p|
|
27
33
|
next if did_runtime and p.runtime?
|
28
34
|
p.get_methods(namespace: namespace, root: root, scope: scope, with_private: with_private).each do |m|
|
29
|
-
result.push
|
35
|
+
result.push Solargraph::Pin::Method.new(nil, namespace, m['name'], YARD::Docstring.new('(defined at runtime)'), scope.to_sym, nil, [])
|
30
36
|
end
|
31
37
|
did_runtime = true if p.runtime?
|
32
38
|
end
|
@@ -34,7 +40,7 @@ module Solargraph
|
|
34
40
|
result
|
35
41
|
end
|
36
42
|
|
37
|
-
# @return [Array<Solargraph::
|
43
|
+
# @return [Array<Solargraph::Pin::Base>]
|
38
44
|
def get_constants(namespace, root = '')
|
39
45
|
cached = cache.get_constants(namespace, root)
|
40
46
|
return cached unless cached.nil?
|
@@ -4,6 +4,7 @@ module Solargraph
|
|
4
4
|
def initialize
|
5
5
|
@method_cache = {}
|
6
6
|
@constant_cache = {}
|
7
|
+
@path_cache = {}
|
7
8
|
end
|
8
9
|
|
9
10
|
def get_methods options
|
@@ -12,6 +13,7 @@ module Solargraph
|
|
12
13
|
|
13
14
|
def set_methods options, values
|
14
15
|
@method_cache[options] = values
|
16
|
+
values.each { |pin| @path_cache[pin.path] = pin }
|
15
17
|
end
|
16
18
|
|
17
19
|
def get_constants namespace, root
|
@@ -22,9 +24,14 @@ module Solargraph
|
|
22
24
|
@constant_cache[[namespace, root]] = values
|
23
25
|
end
|
24
26
|
|
27
|
+
def get_path_pin path
|
28
|
+
@path_cache[path]
|
29
|
+
end
|
30
|
+
|
25
31
|
def clear
|
26
32
|
@method_cache.clear
|
27
33
|
@constant_cache.clear
|
34
|
+
@path_cache.clear
|
28
35
|
end
|
29
36
|
end
|
30
37
|
end
|
data/lib/solargraph/pin.rb
CHANGED
@@ -21,6 +21,7 @@ module Solargraph
|
|
21
21
|
autoload :Documenting, 'solargraph/pin/documenting'
|
22
22
|
autoload :Block, 'solargraph/pin/block'
|
23
23
|
autoload :Localized, 'solargraph/pin/localized'
|
24
|
+
autoload :ProxyMethod, 'solargraph/pin/proxy_method'
|
24
25
|
|
25
26
|
ATTRIBUTE = 1
|
26
27
|
CLASS_VARIABLE = 2
|
@@ -4,10 +4,14 @@ module Solargraph
|
|
4
4
|
# @return [Symbol] :reader or :writer
|
5
5
|
attr_reader :access
|
6
6
|
|
7
|
-
|
7
|
+
# @return [Symbol] :class or :instance
|
8
|
+
attr_reader :scope
|
9
|
+
|
10
|
+
def initialize location, namespace, name, docstring, access, scope
|
8
11
|
super(location, namespace, name, docstring)
|
9
12
|
@access = access
|
10
13
|
@docstring = docstring
|
14
|
+
@scope = scope
|
11
15
|
end
|
12
16
|
|
13
17
|
def kind
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Solargraph
|
2
|
+
module Pin
|
3
|
+
# ProxyMethod serves as a quick, disposable shortcut for providing context
|
4
|
+
# to type inference methods. ApiMap::Probe can treat it as an anonymous
|
5
|
+
# method while analyzing signatures.
|
6
|
+
#
|
7
|
+
class ProxyMethod
|
8
|
+
# @return [String]
|
9
|
+
attr_reader :return_type
|
10
|
+
|
11
|
+
def initialize return_type
|
12
|
+
@return_type = return_type
|
13
|
+
end
|
14
|
+
|
15
|
+
# @return [String]
|
16
|
+
def namespace
|
17
|
+
@namespace ||= ApiMap::TypeMethods.extract_namespace(@return_type)
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [Integer]
|
21
|
+
def kind
|
22
|
+
Pin::METHOD
|
23
|
+
end
|
24
|
+
|
25
|
+
# @return [Symbol]
|
26
|
+
def scope
|
27
|
+
:instance
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -33,7 +33,7 @@ module Solargraph
|
|
33
33
|
rescue JSON::ParserError => e
|
34
34
|
STDOUT.puts respond_err "Error parsing input: #{e.message}"
|
35
35
|
rescue Exception => e
|
36
|
-
STDOUT.puts respond_err "Error processing input: #{e.message}"
|
36
|
+
STDOUT.puts respond_err "Error processing input: #{e.message}\n#{e.backtrace}"
|
37
37
|
end
|
38
38
|
STDOUT.flush
|
39
39
|
end
|
data/lib/solargraph/shell.rb
CHANGED
data/lib/solargraph/source.rb
CHANGED
@@ -11,6 +11,7 @@ module Solargraph
|
|
11
11
|
autoload :Updater, 'solargraph/source/updater'
|
12
12
|
autoload :Change, 'solargraph/source/change'
|
13
13
|
autoload :Mapper, 'solargraph/source/mapper'
|
14
|
+
autoload :NodeMethods, 'solargraph/source/node_methods'
|
14
15
|
|
15
16
|
# @return [String]
|
16
17
|
attr_reader :code
|
@@ -40,6 +41,7 @@ module Solargraph
|
|
40
41
|
# @return [Time]
|
41
42
|
attr_reader :stime
|
42
43
|
|
44
|
+
# @return [Array<Solargraph::Pin::Base>]
|
43
45
|
attr_reader :pins
|
44
46
|
|
45
47
|
attr_reader :requires
|
@@ -132,6 +134,22 @@ module Solargraph
|
|
132
134
|
symbol_pins
|
133
135
|
end
|
134
136
|
|
137
|
+
# @return [Array<Source::Location>]
|
138
|
+
def references name
|
139
|
+
inner_node_references(name, node).map do |n|
|
140
|
+
offset = Position.to_offset(code, get_node_start_position(n))
|
141
|
+
soff = code.index(name, offset)
|
142
|
+
eoff = soff + name.length
|
143
|
+
Location.new(
|
144
|
+
filename,
|
145
|
+
Solargraph::Source::Range.new(
|
146
|
+
Position.from_offset(code, soff),
|
147
|
+
Position.from_offset(code, eoff)
|
148
|
+
)
|
149
|
+
)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
135
153
|
def locate_named_path_pin line, character
|
136
154
|
_locate_pin line, character, Pin::NAMESPACE, Pin::METHOD
|
137
155
|
end
|
@@ -157,7 +175,8 @@ module Solargraph
|
|
157
175
|
|
158
176
|
# Get the nearest node that contains the specified index.
|
159
177
|
#
|
160
|
-
# @param
|
178
|
+
# @param line [Integer]
|
179
|
+
# @param column [Integer]
|
161
180
|
# @return [AST::Node]
|
162
181
|
def node_at(line, column)
|
163
182
|
tree_at(line, column).first
|
@@ -246,6 +265,17 @@ module Solargraph
|
|
246
265
|
|
247
266
|
private
|
248
267
|
|
268
|
+
def inner_node_references name, top
|
269
|
+
result = []
|
270
|
+
if top.kind_of?(AST::Node)
|
271
|
+
if (top.type == :const and top.children[1].to_s == name) or (top.type == :send and top.children[1].to_s == name)
|
272
|
+
result.push top
|
273
|
+
end
|
274
|
+
top.children.each { |c| result.concat inner_node_references(name, c) }
|
275
|
+
end
|
276
|
+
result
|
277
|
+
end
|
278
|
+
|
249
279
|
def parse
|
250
280
|
node, comments = inner_parse(@fixed, filename)
|
251
281
|
@node = node
|
@@ -3,12 +3,11 @@ module Solargraph
|
|
3
3
|
class Fragment
|
4
4
|
include NodeMethods
|
5
5
|
|
6
|
-
attr_reader :tree
|
7
|
-
|
8
6
|
attr_reader :line
|
9
7
|
|
10
8
|
attr_reader :column
|
11
9
|
|
10
|
+
# @return [Solargraph::Source]
|
12
11
|
attr_reader :source
|
13
12
|
|
14
13
|
# @param source [Solargraph::Source]
|
@@ -46,17 +45,6 @@ module Solargraph
|
|
46
45
|
@argument ||= !signature_position.nil?
|
47
46
|
end
|
48
47
|
|
49
|
-
def chained?
|
50
|
-
if @chained.nil?
|
51
|
-
@chained = false
|
52
|
-
@tree.each do |n|
|
53
|
-
@chained = true if n.type == :send
|
54
|
-
break
|
55
|
-
end
|
56
|
-
end
|
57
|
-
@chained
|
58
|
-
end
|
59
|
-
|
60
48
|
# @return [Fragment]
|
61
49
|
def recipient
|
62
50
|
return nil if signature_position.nil?
|
@@ -319,9 +307,18 @@ module Solargraph
|
|
319
307
|
@base_literal = 'Integer'
|
320
308
|
# @todo Smelly exceptional case for array literals
|
321
309
|
elsif signature.start_with?('.[]')
|
322
|
-
index +=
|
323
|
-
signature = signature[
|
310
|
+
index += 2
|
311
|
+
signature = signature[3..-1].to_s
|
324
312
|
@base_literal = 'Array'
|
313
|
+
elsif signature.start_with?('.')
|
314
|
+
pos = Position.from_offset(source.code, index)
|
315
|
+
node = source.node_at(pos.line, pos.character)
|
316
|
+
lit = infer_literal_node_type(node)
|
317
|
+
unless lit.nil?
|
318
|
+
signature = signature[1..-1].to_s
|
319
|
+
index += 1
|
320
|
+
@base_literal = lit
|
321
|
+
end
|
325
322
|
end
|
326
323
|
[index + 1, signature]
|
327
324
|
end
|
@@ -106,9 +106,17 @@ module Solargraph
|
|
106
106
|
u = c.updated(:ivasgn, c.children + ora.children[1..-1], nil)
|
107
107
|
@docstring_hash[u.loc] = docstring_for(ora)
|
108
108
|
pins.push Solargraph::Pin::InstanceVariable.new(get_node_location(u), fqn || '', c.children[0].to_s, docstring_for(u), resolve_node_signature(u.children[1]), infer_literal_node_type(u.children[1]), context)
|
109
|
+
if visibility == :module_function and context.kind == Pin::METHOD
|
110
|
+
other = pins.select{|pin| pin.path == "#{context.namespace}.#{context.name}"}.first
|
111
|
+
pins.push Solargraph::Pin::InstanceVariable.new(get_node_location(u), fqn || '', c.children[0].to_s, docstring_for(u), resolve_node_signature(u.children[1]), infer_literal_node_type(u.children[1]), other) unless other.nil?
|
112
|
+
end
|
109
113
|
end
|
110
114
|
else
|
111
115
|
pins.push Solargraph::Pin::InstanceVariable.new(get_node_location(c), fqn || '',c.children[0].to_s, docstring_for(c), resolve_node_signature(c.children[1]), infer_literal_node_type(c.children[1]), context)
|
116
|
+
if visibility == :module_function and context.kind == Pin::METHOD
|
117
|
+
other = pins.select{|pin| pin.path == "#{context.namespace}.#{context.name}"}.first
|
118
|
+
pins.push Solargraph::Pin::InstanceVariable.new(get_node_location(c), fqn || '',c.children[0].to_s, docstring_for(c), resolve_node_signature(c.children[1]), infer_literal_node_type(c.children[1]), other)
|
119
|
+
end
|
112
120
|
end
|
113
121
|
elsif c.type == :cvasgn
|
114
122
|
here = get_node_start_position(c)
|
@@ -212,8 +220,14 @@ module Solargraph
|
|
212
220
|
ref = pins.select{|p| p.namespace == (fqn || '') and p.name == cn}.first
|
213
221
|
unless ref.nil?
|
214
222
|
pins.delete ref
|
215
|
-
|
216
|
-
|
223
|
+
mm = Solargraph::Pin::Method.new(ref.location, ref.namespace, ref.name, ref.docstring, :class, :public, ref.parameters)
|
224
|
+
cm = Solargraph::Pin::Method.new(ref.location, ref.namespace, ref.name, ref.docstring, :instance, :private, ref.parameters)
|
225
|
+
pins.push mm, cm
|
226
|
+
pins.select{|pin| pin.kind == Pin::INSTANCE_VARIABLE and pin.context == ref}.each do |ivar|
|
227
|
+
pins.delete ivar
|
228
|
+
pins.push Solargraph::Pin::InstanceVariable.new(ivar.location, ivar.namespace, ivar.name, ivar.docstring, ivar.signature, ivar.instance_variable_get(:@literal), mm)
|
229
|
+
pins.push Solargraph::Pin::InstanceVariable.new(ivar.location, ivar.namespace, ivar.name, ivar.docstring, ivar.signature, ivar.instance_variable_get(:@literal), cm)
|
230
|
+
end
|
217
231
|
end
|
218
232
|
end
|
219
233
|
elsif c.children[2].type == :def
|
@@ -253,10 +267,10 @@ module Solargraph
|
|
253
267
|
elsif c.type == :send and [:attr_reader, :attr_writer, :attr_accessor].include?(c.children[1])
|
254
268
|
c.children[2..-1].each do |a|
|
255
269
|
if c.children[1] == :attr_reader or c.children[1] == :attr_accessor
|
256
|
-
pins.push Solargraph::Pin::Attribute.new(get_node_location(c), fqn || '', "#{a.children[0]}", docstring_for(c), :reader
|
270
|
+
pins.push Solargraph::Pin::Attribute.new(get_node_location(c), fqn || '', "#{a.children[0]}", docstring_for(c), :reader, scope)
|
257
271
|
end
|
258
272
|
if c.children[1] == :attr_writer or c.children[1] == :attr_accessor
|
259
|
-
pins.push Solargraph::Pin::Attribute.new(get_node_location(c), fqn || '', "#{a.children[0]}=", docstring_for(c), :writer
|
273
|
+
pins.push Solargraph::Pin::Attribute.new(get_node_location(c), fqn || '', "#{a.children[0]}=", docstring_for(c), :writer, scope)
|
260
274
|
end
|
261
275
|
end
|
262
276
|
elsif c.type == :sclass and c.children[0].type == :self
|
@@ -330,10 +344,6 @@ module Solargraph
|
|
330
344
|
nil
|
331
345
|
end
|
332
346
|
|
333
|
-
def get_node_start_position(node)
|
334
|
-
Position.new(node.loc.line - 1, node.loc.column)
|
335
|
-
end
|
336
|
-
|
337
347
|
def get_node_location(node)
|
338
348
|
if node.nil?
|
339
349
|
st = Position.new(0, 0)
|
@@ -392,10 +402,10 @@ module Solargraph
|
|
392
402
|
t = (d.tag.types.nil? || d.tag.types.empty?) ? nil : d.tag.types.flatten.join('')
|
393
403
|
if t.nil? or t.include?('r')
|
394
404
|
# location, namespace, name, docstring, access
|
395
|
-
pins.push Solargraph::Pin::Attribute.new(get_node_location(k.node), namespace_for(k.node).path, d.tag.name, docstring, :reader)
|
405
|
+
pins.push Solargraph::Pin::Attribute.new(get_node_location(k.node), namespace_for(k.node).path, d.tag.name, docstring, :reader, :instance)
|
396
406
|
end
|
397
407
|
if t.nil? or t.include?('w')
|
398
|
-
pins.push Solargraph::Pin::Attribute.new(get_node_location(k.node), namespace_for(k.node).path, "#{d.tag.name}=", docstring, :
|
408
|
+
pins.push Solargraph::Pin::Attribute.new(get_node_location(k.node), namespace_for(k.node).path, "#{d.tag.name}=", docstring, :writer, :instance)
|
399
409
|
end
|
400
410
|
elsif d.tag.tag_name == 'method'
|
401
411
|
gen_src = Source.new("def #{d.tag.name};end", filename)
|