solargraph 0.29.4 → 0.29.5
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.rb +5 -2
- data/lib/solargraph/api_map/source_to_yard.rb +32 -29
- data/lib/solargraph/api_map/store.rb +4 -6
- data/lib/solargraph/complex_type/type_methods.rb +5 -1
- data/lib/solargraph/diagnostics/type_not_defined.rb +1 -1
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +64 -32
- data/lib/solargraph/library.rb +28 -28
- data/lib/solargraph/pin.rb +1 -0
- data/lib/solargraph/pin/attribute.rb +1 -31
- data/lib/solargraph/pin/base.rb +38 -17
- data/lib/solargraph/pin/base_method.rb +64 -0
- data/lib/solargraph/pin/base_variable.rb +2 -4
- data/lib/solargraph/pin/block.rb +1 -3
- data/lib/solargraph/pin/block_parameter.rb +4 -3
- data/lib/solargraph/pin/keyword.rb +0 -4
- data/lib/solargraph/pin/localized.rb +2 -1
- data/lib/solargraph/pin/method.rb +24 -59
- data/lib/solargraph/pin/namespace.rb +1 -2
- data/lib/solargraph/range.rb +4 -2
- data/lib/solargraph/source.rb +18 -0
- data/lib/solargraph/source/chain.rb +5 -2
- data/lib/solargraph/source/chain/call.rb +3 -1
- data/lib/solargraph/source/change.rb +2 -2
- data/lib/solargraph/source/node_chainer.rb +2 -0
- data/lib/solargraph/source/node_methods.rb +15 -0
- data/lib/solargraph/source/source_chainer.rb +0 -22
- data/lib/solargraph/source_map.rb +11 -3
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace.rb +3 -3
- metadata +10 -9
data/lib/solargraph/pin.rb
CHANGED
@@ -4,6 +4,7 @@ module Solargraph
|
|
4
4
|
module Pin
|
5
5
|
autoload :Conversions, 'solargraph/pin/conversions'
|
6
6
|
autoload :Base, 'solargraph/pin/base'
|
7
|
+
autoload :BaseMethod, 'solargraph/pin/base_method'
|
7
8
|
autoload :Method, 'solargraph/pin/method'
|
8
9
|
autoload :MethodAlias, 'solargraph/pin/method_alias'
|
9
10
|
autoload :Attribute, 'solargraph/pin/attribute'
|
@@ -1,15 +1,9 @@
|
|
1
1
|
module Solargraph
|
2
2
|
module Pin
|
3
|
-
class Attribute <
|
3
|
+
class Attribute < BaseMethod
|
4
4
|
# @return [Symbol] :reader or :writer
|
5
5
|
attr_reader :access
|
6
6
|
|
7
|
-
# @return [Symbol] :class or :instance
|
8
|
-
attr_reader :scope
|
9
|
-
|
10
|
-
# @return [Symbol] :public, :protected, or :private
|
11
|
-
attr_reader :visibility
|
12
|
-
|
13
7
|
def initialize location, namespace, name, comments, access, scope, visibility
|
14
8
|
super(location, namespace, name, comments)
|
15
9
|
@access = access
|
@@ -33,10 +27,6 @@ module Solargraph
|
|
33
27
|
@path ||= namespace + (scope == :instance ? '#' : '.') + name
|
34
28
|
end
|
35
29
|
|
36
|
-
def return_complex_type
|
37
|
-
@return_complex_type ||= generate_complex_type
|
38
|
-
end
|
39
|
-
|
40
30
|
def parameters
|
41
31
|
# Since attributes are generally equivalent to methods, treat
|
42
32
|
# them as methods without parameters
|
@@ -46,26 +36,6 @@ module Solargraph
|
|
46
36
|
def parameter_names
|
47
37
|
[]
|
48
38
|
end
|
49
|
-
|
50
|
-
private
|
51
|
-
|
52
|
-
# @todo DRY this method. It also exists in Pin::Method.
|
53
|
-
#
|
54
|
-
# @return [ComplexType]
|
55
|
-
def generate_complex_type
|
56
|
-
tag = docstring.tag(:return)
|
57
|
-
if tag.nil?
|
58
|
-
ol = docstring.tag(:overload)
|
59
|
-
tag = ol.tag(:return) unless ol.nil?
|
60
|
-
end
|
61
|
-
return ComplexType::UNDEFINED if tag.nil? or tag.types.nil? or tag.types.empty?
|
62
|
-
begin
|
63
|
-
ComplexType.parse *tag.types
|
64
|
-
rescue Solargraph::ComplexTypeError => e
|
65
|
-
STDERR.puts e.message
|
66
|
-
ComplexType::UNDEFINED
|
67
|
-
end
|
68
|
-
end
|
69
39
|
end
|
70
40
|
end
|
71
41
|
end
|
data/lib/solargraph/pin/base.rb
CHANGED
@@ -85,14 +85,12 @@ module Solargraph
|
|
85
85
|
# @param other [Solargraph::Pin::Base, Object]
|
86
86
|
# @return [Boolean]
|
87
87
|
def nearly? other
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
( ((maybe_directives? == false and other.maybe_directives? == false) or compare_directives(directives, other.directives)) and
|
95
|
-
compare_docstring_tags(docstring, other.docstring) )
|
88
|
+
self.class == other.class &&
|
89
|
+
namespace == other.namespace &&
|
90
|
+
name == other.name &&
|
91
|
+
(comments == other.comments ||
|
92
|
+
(((maybe_directives? == false && other.maybe_directives? == false) || compare_directives(directives, other.directives)) &&
|
93
|
+
compare_docstring_tags(docstring, other.docstring))
|
96
94
|
)
|
97
95
|
end
|
98
96
|
|
@@ -145,12 +143,36 @@ module Solargraph
|
|
145
143
|
@deprecated ||= docstring.has_tag?('deprecated')
|
146
144
|
end
|
147
145
|
|
146
|
+
# Get a fully qualified type from the pin's return type.
|
147
|
+
#
|
148
|
+
# The relative type is determined from YARD documentation (@return,
|
149
|
+
# @param, @type, etc.) and its namespaces are fully qualified using the
|
150
|
+
# provided ApiMap.
|
151
|
+
#
|
148
152
|
# @param api_map [ApiMap]
|
149
153
|
# @return [ComplexType]
|
150
|
-
def
|
154
|
+
def typify api_map
|
151
155
|
return_complex_type.qualify(api_map, namespace)
|
152
156
|
end
|
153
157
|
|
158
|
+
# Infer the pin's return type via static code analysis.
|
159
|
+
#
|
160
|
+
# @param api_map [ApiMap]
|
161
|
+
# @return [ComplexType]
|
162
|
+
def probe api_map
|
163
|
+
typify api_map
|
164
|
+
end
|
165
|
+
|
166
|
+
# @deprecated Use #typify and/or #probe instead
|
167
|
+
# @param api_map [ApiMap]
|
168
|
+
# @return [ComplexType]
|
169
|
+
def infer api_map
|
170
|
+
STDERR.puts "WARNING: Pin #infer methods are deprecated. Use #typify or #probe instead."
|
171
|
+
type = typify(api_map)
|
172
|
+
return type unless type.undefined?
|
173
|
+
probe api_map
|
174
|
+
end
|
175
|
+
|
154
176
|
# Try to merge data from another pin. Merges are only possible if the
|
155
177
|
# pins are near matches (see the #nearly? method). The changes should
|
156
178
|
# not have any side effects on the API surface.
|
@@ -160,14 +182,13 @@ module Solargraph
|
|
160
182
|
def try_merge! pin
|
161
183
|
return false unless nearly?(pin)
|
162
184
|
@location = pin.location
|
163
|
-
if comments
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
end
|
185
|
+
return true if comments == pin.comments
|
186
|
+
@comments = pin.comments
|
187
|
+
@docstring = pin.docstring
|
188
|
+
@return_complex_type = pin.return_complex_type
|
189
|
+
@documentation = nil
|
190
|
+
@deprecated = nil
|
191
|
+
reset_conversions
|
171
192
|
true
|
172
193
|
end
|
173
194
|
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Solargraph
|
2
|
+
module Pin
|
3
|
+
# The base class for method and attribute pins.
|
4
|
+
#
|
5
|
+
class BaseMethod < Base
|
6
|
+
# @return [Symbol] :instance or :class
|
7
|
+
attr_reader :scope
|
8
|
+
|
9
|
+
# @return [Symbol] :public, :private, or :protected
|
10
|
+
attr_reader :visibility
|
11
|
+
|
12
|
+
def return_complex_type
|
13
|
+
@return_complex_type ||= generate_complex_type
|
14
|
+
end
|
15
|
+
|
16
|
+
def typify api_map
|
17
|
+
decl = super
|
18
|
+
return decl unless decl.undefined?
|
19
|
+
type = see_reference(api_map)
|
20
|
+
return type unless type.nil?
|
21
|
+
ComplexType::UNDEFINED
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
# @return [ComplexType]
|
27
|
+
def generate_complex_type
|
28
|
+
tag = docstring.tag(:return)
|
29
|
+
if tag.nil?
|
30
|
+
ol = docstring.tag(:overload)
|
31
|
+
tag = ol.tag(:return) unless ol.nil?
|
32
|
+
end
|
33
|
+
return ComplexType::UNDEFINED if tag.nil? or tag.types.nil? or tag.types.empty?
|
34
|
+
begin
|
35
|
+
ComplexType.parse *tag.types
|
36
|
+
rescue Solargraph::ComplexTypeError => e
|
37
|
+
STDERR.puts e.message
|
38
|
+
ComplexType::UNDEFINED
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# @param [ApiMap]
|
43
|
+
def see_reference api_map
|
44
|
+
docstring.ref_tags.each do |ref|
|
45
|
+
next unless ref.tag_name == 'return' && ref.owner
|
46
|
+
parts = ref.owner.to_s.split(/[\.#]/)
|
47
|
+
if parts.first.empty?
|
48
|
+
path = "#{namespace}#{ref.owner.to_s}"
|
49
|
+
else
|
50
|
+
fqns = api_map.qualify(parts.first, namespace)
|
51
|
+
return ComplexType::UNDEFINED if fqns.nil?
|
52
|
+
path = fqns + ref.owner.to_s[parts.first.length] + parts.last
|
53
|
+
end
|
54
|
+
pins = api_map.get_path_pins(path)
|
55
|
+
pins.each do |pin|
|
56
|
+
type = pin.typify(api_map)
|
57
|
+
return type unless type.undefined?
|
58
|
+
end
|
59
|
+
end
|
60
|
+
nil
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -39,10 +39,8 @@ module Solargraph
|
|
39
39
|
true
|
40
40
|
end
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
result = super
|
45
|
-
return result if result.defined? or @assignment.nil?
|
42
|
+
def probe api_map
|
43
|
+
return ComplexType::UNDEFINED if @assignment.nil?
|
46
44
|
chain = Source::NodeChainer.chain(@assignment, filename)
|
47
45
|
clip = api_map.clip_at(location.filename, location.range.start)
|
48
46
|
locals = clip.locals - [self]
|
data/lib/solargraph/pin/block.rb
CHANGED
@@ -6,9 +6,6 @@ module Solargraph
|
|
6
6
|
# @return [Parser::AST::Node]
|
7
7
|
attr_reader :receiver
|
8
8
|
|
9
|
-
# @return [Array<String>]
|
10
|
-
attr_reader :parameters
|
11
|
-
|
12
9
|
def initialize location, namespace, name, comments, receiver, context
|
13
10
|
super(location, namespace, name, comments)
|
14
11
|
@receiver = receiver
|
@@ -19,6 +16,7 @@ module Solargraph
|
|
19
16
|
Pin::BLOCK
|
20
17
|
end
|
21
18
|
|
19
|
+
# @return [Array<String>]
|
22
20
|
def parameters
|
23
21
|
@parameters ||= []
|
24
22
|
end
|
@@ -71,9 +71,10 @@ module Solargraph
|
|
71
71
|
block
|
72
72
|
end
|
73
73
|
|
74
|
-
|
75
|
-
|
76
|
-
|
74
|
+
def typify api_map
|
75
|
+
# @todo Does anything need to be eliminated because it's more accurately a probe?
|
76
|
+
type = super
|
77
|
+
return type unless type.undefined?
|
77
78
|
chain = Source::NodeChainer.chain(block.receiver, filename)
|
78
79
|
clip = api_map.clip_at(location.filename, location.range.start)
|
79
80
|
locals = clip.locals - [self]
|
@@ -7,9 +7,10 @@ module Solargraph
|
|
7
7
|
attr_reader :presence
|
8
8
|
|
9
9
|
# @param other [Pin::Base] The caller's block
|
10
|
-
# @param position [Position] The caller's position
|
10
|
+
# @param position [Position, Array(Integer, Integer)] The caller's position
|
11
11
|
# @return [Boolean]
|
12
12
|
def visible_from?(other, position)
|
13
|
+
position = Position.normalize(position)
|
13
14
|
other.filename == filename and
|
14
15
|
( other == block or
|
15
16
|
(block.location.range.contain?(other.location.range.start) and block.location.range.contain?(other.location.range.ending))
|
@@ -1,14 +1,8 @@
|
|
1
1
|
module Solargraph
|
2
2
|
module Pin
|
3
|
-
class Method <
|
3
|
+
class Method < BaseMethod
|
4
4
|
include Source::NodeMethods
|
5
5
|
|
6
|
-
# @return [Symbol] :instance or :class
|
7
|
-
attr_reader :scope
|
8
|
-
|
9
|
-
# @return [Symbol] :public, :private, or :protected
|
10
|
-
attr_reader :visibility
|
11
|
-
|
12
6
|
# @return [Array<String>]
|
13
7
|
attr_reader :parameters
|
14
8
|
|
@@ -51,15 +45,10 @@ module Solargraph
|
|
51
45
|
Solargraph::LanguageServer::CompletionItemKinds::METHOD
|
52
46
|
end
|
53
47
|
|
54
|
-
# @return [Integer]
|
55
48
|
def symbol_kind
|
56
49
|
LanguageServer::SymbolKinds::METHOD
|
57
50
|
end
|
58
51
|
|
59
|
-
def return_complex_type
|
60
|
-
@return_complex_type ||= generate_complex_type
|
61
|
-
end
|
62
|
-
|
63
52
|
def documentation
|
64
53
|
if @documentation.nil?
|
65
54
|
@documentation ||= super || ''
|
@@ -87,14 +76,18 @@ module Solargraph
|
|
87
76
|
visibility == other.visibility
|
88
77
|
end
|
89
78
|
|
90
|
-
def
|
91
|
-
decl = super
|
92
|
-
return decl unless decl.undefined?
|
93
|
-
type = see_reference(api_map)
|
94
|
-
return type unless type.nil?
|
79
|
+
def probe api_map
|
95
80
|
infer_from_return_nodes(api_map)
|
96
81
|
end
|
97
82
|
|
83
|
+
# @deprecated Use #typify and/or #probe instead
|
84
|
+
def infer api_map
|
85
|
+
STDERR.puts 'WARNING: Pin #infer methods are deprecated. Use #typify or #probe instead.'
|
86
|
+
type = typify(api_map)
|
87
|
+
return type unless type.undefined?
|
88
|
+
probe api_map
|
89
|
+
end
|
90
|
+
|
98
91
|
def try_merge! pin
|
99
92
|
return false unless super
|
100
93
|
@node = pin.node
|
@@ -103,59 +96,31 @@ module Solargraph
|
|
103
96
|
|
104
97
|
private
|
105
98
|
|
106
|
-
# @return [
|
107
|
-
def
|
108
|
-
|
109
|
-
if
|
110
|
-
|
111
|
-
|
112
|
-
end
|
113
|
-
return ComplexType::UNDEFINED if tag.nil? or tag.types.nil? or tag.types.empty?
|
114
|
-
begin
|
115
|
-
ComplexType.parse *tag.types
|
116
|
-
rescue Solargraph::ComplexTypeError => e
|
117
|
-
STDERR.puts e.message
|
118
|
-
ComplexType::UNDEFINED
|
119
|
-
end
|
99
|
+
# @return [Parser::AST:Node, nil]
|
100
|
+
def method_body_node
|
101
|
+
return nil if node.nil?
|
102
|
+
return node.children[2] if node.type == :def
|
103
|
+
return node.children[3] if node.type == :defs
|
104
|
+
nil
|
120
105
|
end
|
121
106
|
|
122
107
|
# @param api_map [ApiMap]
|
108
|
+
# @return [ComplexType]
|
123
109
|
def infer_from_return_nodes api_map
|
124
|
-
return ComplexType::UNDEFINED if node.nil? ||
|
125
|
-
(node.type == :def && node.children[2].nil?) ||
|
126
|
-
(node.type == :defs && node.children[3].nil?)
|
127
110
|
result = []
|
128
|
-
|
129
|
-
nodes.each do |n|
|
111
|
+
returns_from(method_body_node).each do |n|
|
130
112
|
next if n.loc.nil?
|
131
|
-
clip = api_map.clip_at(
|
132
|
-
|
113
|
+
clip = api_map.clip_at(
|
114
|
+
location.filename,
|
115
|
+
[n.loc.expression.last_line, n.loc.expression.last_column]
|
116
|
+
)
|
117
|
+
chain = Solargraph::Source::NodeChainer.chain(n, location.filename)
|
118
|
+
type = chain.infer(api_map, self, clip.locals)
|
133
119
|
result.push type unless type.undefined?
|
134
120
|
end
|
135
121
|
return ComplexType::UNDEFINED if result.empty?
|
136
122
|
ComplexType.parse(*result.map(&:tag))
|
137
123
|
end
|
138
|
-
|
139
|
-
# @param [ApiMap]
|
140
|
-
def see_reference api_map
|
141
|
-
docstring.ref_tags.each do |ref|
|
142
|
-
next unless ref.tag_name == 'return' && ref.owner
|
143
|
-
parts = ref.owner.to_s.split(/[\.#]/)
|
144
|
-
if parts.first.empty?
|
145
|
-
path = "#{namespace}#{ref.owner.to_s}"
|
146
|
-
else
|
147
|
-
fqns = api_map.qualify(parts.first, namespace)
|
148
|
-
return ComplexType::UNDEFINED if fqns.nil?
|
149
|
-
path = fqns + ref.owner.to_s[parts.first.length] + parts.last
|
150
|
-
end
|
151
|
-
pins = api_map.get_path_pins(path)
|
152
|
-
pins.each do |pin|
|
153
|
-
type = pin.infer(api_map)
|
154
|
-
return type unless type.undefined?
|
155
|
-
end
|
156
|
-
end
|
157
|
-
nil
|
158
|
-
end
|
159
124
|
end
|
160
125
|
end
|
161
126
|
end
|
data/lib/solargraph/range.rb
CHANGED
@@ -28,9 +28,10 @@ module Solargraph
|
|
28
28
|
|
29
29
|
# True if the specified position is inside the range.
|
30
30
|
#
|
31
|
-
# @param position [
|
31
|
+
# @param position [Position, Array(Integer, Integer)]
|
32
32
|
# @return [Boolean]
|
33
33
|
def contain? position
|
34
|
+
position = Position.normalize(position)
|
34
35
|
return false if position.line < start.line || position.line > ending.line
|
35
36
|
return false if position.line == start.line && position.character < start.character
|
36
37
|
return false if position.line == ending.line && position.character > ending.character
|
@@ -39,9 +40,10 @@ module Solargraph
|
|
39
40
|
|
40
41
|
# True if the range contains the specified position and the position does not precede it.
|
41
42
|
#
|
42
|
-
# @param position [Position]
|
43
|
+
# @param position [Position, Array(Integer, Integer)]
|
43
44
|
# @return [Boolean]
|
44
45
|
def include? position
|
46
|
+
position = Position.normalize(position)
|
45
47
|
contain?(position) && !(position.line == start.line && position.character == start.character)
|
46
48
|
end
|
47
49
|
|
data/lib/solargraph/source.rb
CHANGED
@@ -24,6 +24,7 @@ module Solargraph
|
|
24
24
|
# @return [Parser::AST::Node]
|
25
25
|
attr_reader :node
|
26
26
|
|
27
|
+
# @return [Array<Parser::Source::Comment>]
|
27
28
|
attr_reader :comments
|
28
29
|
|
29
30
|
# @return [String]
|
@@ -194,6 +195,9 @@ module Solargraph
|
|
194
195
|
arr ? stringify_comment_array(arr) : nil
|
195
196
|
end
|
196
197
|
|
198
|
+
# A location representing the file in its entirety.
|
199
|
+
#
|
200
|
+
# @return [Location]
|
197
201
|
def location
|
198
202
|
st = Position.new(0, 0)
|
199
203
|
en = Position.from_offset(code, code.length)
|
@@ -203,6 +207,9 @@ module Solargraph
|
|
203
207
|
|
204
208
|
private
|
205
209
|
|
210
|
+
# Get a hash of comments grouped by the line numbers of the associated code.
|
211
|
+
#
|
212
|
+
# @return [Hash{Integer => Array<Parser::Source::Comment>}]
|
206
213
|
def associated_comments
|
207
214
|
@associated_comments ||= begin
|
208
215
|
result = {}
|
@@ -216,6 +223,10 @@ module Solargraph
|
|
216
223
|
end
|
217
224
|
end
|
218
225
|
|
226
|
+
# Get a string representation of an array of comments.
|
227
|
+
#
|
228
|
+
# @param comments [Array<Parser::Source::Comment>]
|
229
|
+
# @return [String]
|
219
230
|
def stringify_comment_array comments
|
220
231
|
ctxt = ''
|
221
232
|
num = nil
|
@@ -309,17 +320,24 @@ module Solargraph
|
|
309
320
|
|
310
321
|
# @param code [String]
|
311
322
|
# @param filename [String]
|
323
|
+
# @param version [Integer]
|
312
324
|
# @return [Solargraph::Source]
|
313
325
|
def load_string code, filename = nil, version = 0
|
314
326
|
Source.new code, filename, version
|
315
327
|
end
|
316
328
|
|
329
|
+
# @param code [String]
|
330
|
+
# @param filename [String]
|
331
|
+
# @return [Array(Parser::AST::Node, Array<Parser::Source::Comment>)]
|
317
332
|
def parse_with_comments code, filename = nil
|
318
333
|
buffer = Parser::Source::Buffer.new(filename, 0)
|
319
334
|
buffer.source = code.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '_')
|
320
335
|
parser.parse_with_comments(buffer)
|
321
336
|
end
|
322
337
|
|
338
|
+
# @param code [String]
|
339
|
+
# @param filename [String]
|
340
|
+
# @return [Parser::AST::Node]
|
323
341
|
def parse code, filename = nil
|
324
342
|
buffer = Parser::Source::Buffer.new(filename, 0)
|
325
343
|
buffer.source = code.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '_')
|