solargraph 0.28.4 → 0.29.0
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.rb +43 -10
- data/lib/solargraph/api_map/store.rb +13 -0
- data/lib/solargraph/bundle.rb +3 -0
- data/lib/solargraph/complex_type.rb +5 -4
- data/lib/solargraph/core_fills.rb +3 -2
- data/lib/solargraph/language_server/host.rb +0 -1
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +4 -3
- data/lib/solargraph/language_server/message/extended/document_gems.rb +7 -0
- data/lib/solargraph/language_server/transport/socket.rb +7 -1
- data/lib/solargraph/library.rb +1 -1
- data/lib/solargraph/page.rb +1 -2
- data/lib/solargraph/pin.rb +1 -0
- data/lib/solargraph/pin/base.rb +8 -1
- data/lib/solargraph/pin/base_variable.rb +1 -1
- data/lib/solargraph/pin/block_parameter.rb +5 -0
- data/lib/solargraph/pin/conversions.rb +1 -1
- data/lib/solargraph/pin/method.rb +59 -1
- data/lib/solargraph/pin/method_alias.rb +19 -0
- data/lib/solargraph/pin/yard_pin/method.rb +2 -2
- data/lib/solargraph/source.rb +63 -1
- data/lib/solargraph/source/chain/call.rb +39 -20
- data/lib/solargraph/source/node_chainer.rb +1 -1
- data/lib/solargraph/source/node_methods.rb +81 -0
- data/lib/solargraph/source_map.rb +15 -0
- data/lib/solargraph/source_map/clip.rb +1 -1
- data/lib/solargraph/source_map/mapper.rb +9 -421
- data/lib/solargraph/source_map/node_processor.rb +75 -0
- data/lib/solargraph/source_map/node_processor/alias_node.rb +21 -0
- data/lib/solargraph/source_map/node_processor/args_node.rb +28 -0
- data/lib/solargraph/source_map/node_processor/base.rb +68 -0
- data/lib/solargraph/source_map/node_processor/begin_node.rb +11 -0
- data/lib/solargraph/source_map/node_processor/block_node.rb +14 -0
- data/lib/solargraph/source_map/node_processor/casgn_node.rb +14 -0
- data/lib/solargraph/source_map/node_processor/cvasgn_node.rb +14 -0
- data/lib/solargraph/source_map/node_processor/def_node.rb +54 -0
- data/lib/solargraph/source_map/node_processor/defs_node.rb +21 -0
- data/lib/solargraph/source_map/node_processor/gvasgn_node.rb +12 -0
- data/lib/solargraph/source_map/node_processor/ivasgn_node.rb +18 -0
- data/lib/solargraph/source_map/node_processor/lvasgn_node.rb +16 -0
- data/lib/solargraph/source_map/node_processor/namespace_node.rb +26 -0
- data/lib/solargraph/source_map/node_processor/orasgn_node.rb +12 -0
- data/lib/solargraph/source_map/node_processor/sclass_node.rb +11 -0
- data/lib/solargraph/source_map/node_processor/send_node.rb +150 -0
- data/lib/solargraph/source_map/node_processor/sym_node.rb +11 -0
- data/lib/solargraph/source_map/region.rb +58 -0
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/yard_map.rb +17 -10
- data/lib/yard-solargraph.rb +0 -2
- metadata +24 -18
@@ -0,0 +1,19 @@
|
|
1
|
+
module Solargraph
|
2
|
+
module Pin
|
3
|
+
# Use this class to track method aliases for later remapping. Common
|
4
|
+
# examples are aliases for superclass methods or methods from included
|
5
|
+
# modules.
|
6
|
+
#
|
7
|
+
class MethodAlias < Method
|
8
|
+
attr_reader :original
|
9
|
+
|
10
|
+
def initialize location, namespace, name, scope, original
|
11
|
+
# @todo Determine how to handle these parameters. Among other things,
|
12
|
+
# determine if the visibility is defined by the location of the
|
13
|
+
# alias call or the original method.
|
14
|
+
super(location, namespace, name, '', scope, :public, [])
|
15
|
+
@original = original
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -6,7 +6,7 @@ module Solargraph
|
|
6
6
|
|
7
7
|
def initialize code_object, location, name = nil, scope = nil, visibility = nil
|
8
8
|
comments = (code_object.docstring ? code_object.docstring.all : nil)
|
9
|
-
super(location, code_object.namespace.to_s, name || code_object.name.to_s, comments, scope || code_object.scope, visibility || code_object.visibility, get_parameters(code_object))
|
9
|
+
super(location, code_object.namespace.to_s, name || code_object.name.to_s, comments, scope || code_object.scope, visibility || code_object.visibility, get_parameters(code_object), nil)
|
10
10
|
end
|
11
11
|
|
12
12
|
def return_complex_type
|
@@ -28,7 +28,7 @@ module Solargraph
|
|
28
28
|
args.push p
|
29
29
|
end
|
30
30
|
args
|
31
|
-
end
|
31
|
+
end
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
data/lib/solargraph/source.rb
CHANGED
@@ -46,7 +46,12 @@ module Solargraph
|
|
46
46
|
@node, @comments = Source.parse_with_comments(@code, filename)
|
47
47
|
@parsed = true
|
48
48
|
rescue Parser::SyntaxError, EncodingError => e
|
49
|
-
@node,
|
49
|
+
# @todo 100% whitespace results in a nil node, so there's no reason to parse it.
|
50
|
+
# We still need to determine whether the resulting node should be nil or a dummy
|
51
|
+
# node with a location that encompasses the range.
|
52
|
+
# @node, @comments = Source.parse_with_comments(@code.gsub(/[^\s]/, ' '), filename)
|
53
|
+
@node = nil
|
54
|
+
@comments = []
|
50
55
|
@parsed = false
|
51
56
|
rescue Exception => e
|
52
57
|
STDERR.puts e.message
|
@@ -171,8 +176,65 @@ module Solargraph
|
|
171
176
|
@error_ranges ||= []
|
172
177
|
end
|
173
178
|
|
179
|
+
def code_for(node)
|
180
|
+
# @todo Using node locations on code with converted EOLs seems
|
181
|
+
# slightly more efficient than calculating offsets.
|
182
|
+
# b = node.location.expression.begin.begin_pos
|
183
|
+
# e = node.location.expression.end.end_pos
|
184
|
+
b = Position.line_char_to_offset(@code, node.location.line, node.location.column)
|
185
|
+
e = Position.line_char_to_offset(@code, node.location.last_line, node.location.last_column)
|
186
|
+
frag = code[b..e-1].to_s
|
187
|
+
frag.strip.gsub(/,$/, '')
|
188
|
+
end
|
189
|
+
|
190
|
+
# @param node [Parser::AST::Node]
|
191
|
+
# @return [String]
|
192
|
+
def comments_for node
|
193
|
+
arr = associated_comments[node.loc.line]
|
194
|
+
arr ? stringify_comment_array(arr) : nil
|
195
|
+
end
|
196
|
+
|
197
|
+
def location
|
198
|
+
st = Position.new(0, 0)
|
199
|
+
en = Position.from_offset(code, code.length)
|
200
|
+
range = Range.new(st, en)
|
201
|
+
Location.new(filename, range)
|
202
|
+
end
|
203
|
+
|
174
204
|
private
|
175
205
|
|
206
|
+
def associated_comments
|
207
|
+
@associated_comments ||= begin
|
208
|
+
result = {}
|
209
|
+
Parser::Source::Comment.associate_locations(node, comments).each_pair do |loc, all|
|
210
|
+
block = all.select{ |l| l.document? || code.lines[l.loc.line].strip.start_with?('#')}
|
211
|
+
next if block.empty?
|
212
|
+
result[loc.line] ||= []
|
213
|
+
result[loc.line].concat block
|
214
|
+
end
|
215
|
+
result
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
def stringify_comment_array comments
|
220
|
+
ctxt = ''
|
221
|
+
num = nil
|
222
|
+
started = false
|
223
|
+
comments.each { |l|
|
224
|
+
# Trim the comment and minimum leading whitespace
|
225
|
+
p = l.text.gsub(/^#/, '')
|
226
|
+
if num.nil? and !p.strip.empty?
|
227
|
+
num = p.index(/[^ ]/)
|
228
|
+
started = true
|
229
|
+
elsif started and !p.strip.empty?
|
230
|
+
cur = p.index(/[^ ]/)
|
231
|
+
num = cur if cur < num
|
232
|
+
end
|
233
|
+
ctxt += "#{p[num..-1]}\n" if started
|
234
|
+
}
|
235
|
+
ctxt
|
236
|
+
end
|
237
|
+
|
176
238
|
# @return [Array<Range>]
|
177
239
|
def string_ranges
|
178
240
|
@string_ranges ||= string_ranges_in(@node)
|
@@ -42,16 +42,18 @@ module Solargraph
|
|
42
42
|
def inferred_pins pins, api_map, context, locals
|
43
43
|
result = pins.map do |p|
|
44
44
|
if CoreFills::METHODS_RETURNING_SELF.include?(p.path)
|
45
|
-
next Solargraph::Pin::Method.new(p.location, p.namespace, p.name, "@return [#{context.tag}]", p.scope, p.visibility, p.parameters)
|
45
|
+
next Solargraph::Pin::Method.new(p.location, p.namespace, p.name, "@return [#{context.tag}]", p.scope, p.visibility, p.parameters, p.node)
|
46
46
|
end
|
47
47
|
if CoreFills::METHODS_RETURNING_SUBTYPES.include?(p.path) && !context.subtypes.empty?
|
48
|
-
next Solargraph::Pin::Method.new(p.location, p.namespace, p.name, "@return [#{context.subtypes.first.tag}]", p.scope, p.visibility, p.parameters)
|
48
|
+
next Solargraph::Pin::Method.new(p.location, p.namespace, p.name, "@return [#{context.subtypes.first.tag}]", p.scope, p.visibility, p.parameters, p.node)
|
49
|
+
end
|
50
|
+
if p.kind == Pin::METHOD && !p.macros.empty?
|
51
|
+
result = process_macro(p, api_map, context, locals)
|
52
|
+
next result unless result.return_type.undefined?
|
53
|
+
elsif !p.directives.empty?
|
54
|
+
result = process_directive(p, api_map, context, locals)
|
55
|
+
next result unless result.return_type.undefined?
|
49
56
|
end
|
50
|
-
# @todo Temporarily disabled macros
|
51
|
-
# if p.kind == Pin::METHOD && !p.macros.empty?
|
52
|
-
# result = process_macro(p, api_map, context, locals)
|
53
|
-
# next result unless result.return_type.undefined?
|
54
|
-
# end
|
55
57
|
next p if p.kind == Pin::METHOD || p.kind == Pin::ATTRIBUTE || p.kind == Pin::NAMESPACE
|
56
58
|
type = p.infer(api_map)
|
57
59
|
next p if p.return_complex_type == type
|
@@ -67,22 +69,39 @@ module Solargraph
|
|
67
69
|
# @param pin [Pin::Method]
|
68
70
|
# @param api_map [ApiMap]
|
69
71
|
# @param context [ComplexType]
|
72
|
+
# @return [Pin::Base]
|
70
73
|
def process_macro pin, api_map, context, locals
|
71
74
|
pin.macros.each do |macro|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
75
|
+
result = inner_process_macro(pin, macro, api_map, context, locals)
|
76
|
+
return result unless result.return_type.undefined?
|
77
|
+
end
|
78
|
+
Pin::ProxyType.new(nil, nil, nil, ComplexType::UNDEFINED)
|
79
|
+
end
|
80
|
+
|
81
|
+
def process_directive pin, api_map, context, locals
|
82
|
+
pin.directives.each do |dir|
|
83
|
+
macro = api_map.named_macro(dir.tag.name)
|
84
|
+
next if macro.nil?
|
85
|
+
result = inner_process_macro(pin, macro, api_map, context, locals)
|
86
|
+
return result unless result.return_type.undefined?
|
87
|
+
end
|
88
|
+
Pin::ProxyType.new(nil, nil, nil, ComplexType::UNDEFINED)
|
89
|
+
end
|
90
|
+
|
91
|
+
def inner_process_macro pin, macro, api_map, context, locals
|
92
|
+
vals = arguments.map{ |c| Pin::ProxyType.anonymous(c.infer(api_map, pin, locals)) }
|
93
|
+
txt = macro.tag.text.clone
|
94
|
+
i = 1
|
95
|
+
vals.each do |v|
|
96
|
+
txt.gsub!(/\$#{i}/, v.context.namespace)
|
97
|
+
i += 1
|
98
|
+
end
|
99
|
+
docstring = YARD::Docstring.parser.parse(txt).to_docstring
|
100
|
+
tag = docstring.tag(:return)
|
101
|
+
unless tag.nil? || tag.types.nil?
|
102
|
+
return Pin::ProxyType.anonymous(ComplexType.parse(*tag.types))
|
84
103
|
end
|
85
|
-
|
104
|
+
Pin::ProxyType.new(nil, nil, nil, ComplexType::UNDEFINED)
|
86
105
|
end
|
87
106
|
end
|
88
107
|
end
|
@@ -41,7 +41,7 @@ module Solargraph
|
|
41
41
|
# @param n [Parser::AST::Node]
|
42
42
|
# @return [Array<Chain::Link>]
|
43
43
|
def generate_links n
|
44
|
-
return []
|
44
|
+
return [] unless n.is_a?(Parser::AST::Node)
|
45
45
|
return generate_links(n.children[0]) if n.type == :begin
|
46
46
|
# @todo This might not be right. It's weird either way.
|
47
47
|
# return generate_links(n.children[2] || n.children[0]) if n.type == :block
|
@@ -60,6 +60,8 @@ module Solargraph
|
|
60
60
|
return 'Float'
|
61
61
|
elsif node.type == :sym
|
62
62
|
return 'Symbol'
|
63
|
+
elsif node.type == :regexp
|
64
|
+
return 'Regexp'
|
63
65
|
# @todo Maybe ignore nils
|
64
66
|
# elsif node.type == :nil
|
65
67
|
# return 'NilClass'
|
@@ -106,6 +108,85 @@ module Solargraph
|
|
106
108
|
end
|
107
109
|
signature
|
108
110
|
end
|
111
|
+
|
112
|
+
def returns_from node
|
113
|
+
DeepInference.get_return_nodes(node)
|
114
|
+
end
|
115
|
+
|
116
|
+
module DeepInference
|
117
|
+
class << self
|
118
|
+
CONDITIONAL = [:if, :unless]
|
119
|
+
REDUCEABLE = [:begin, :kwbegin]
|
120
|
+
SKIPPABLE = [:def, :defs, :class, :sclass, :module]
|
121
|
+
|
122
|
+
def get_return_nodes node
|
123
|
+
result = []
|
124
|
+
if REDUCEABLE.include?(node.type)
|
125
|
+
result.concat get_return_nodes_from_children(node)
|
126
|
+
elsif CONDITIONAL.include?(node.type)
|
127
|
+
result.concat reduce_to_value_nodes(node.children[1..-1])
|
128
|
+
else
|
129
|
+
result.push node
|
130
|
+
end
|
131
|
+
result
|
132
|
+
end
|
133
|
+
|
134
|
+
private
|
135
|
+
|
136
|
+
def get_return_nodes_from_children parent
|
137
|
+
result = []
|
138
|
+
nodes = parent.children.select{|n| n.is_a?(AST::Node)}
|
139
|
+
nodes[0..-2].each do |node|
|
140
|
+
next if SKIPPABLE.include?(node.type)
|
141
|
+
if node.type == :return
|
142
|
+
result.concat reduce_to_value_nodes([node.children[0]])
|
143
|
+
# @todo Maybe return the result here because the rest of the code is
|
144
|
+
# unreachable
|
145
|
+
return result
|
146
|
+
else
|
147
|
+
result.concat get_return_nodes_only(node)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
result.concat reduce_to_value_nodes([nodes.last]) unless nodes.last.nil?
|
151
|
+
result
|
152
|
+
end
|
153
|
+
|
154
|
+
def get_return_nodes_only parent
|
155
|
+
result = []
|
156
|
+
nodes = parent.children.select{|n| n.is_a?(AST::Node)}
|
157
|
+
nodes.each do |node|
|
158
|
+
next if SKIPPABLE.include?(node.type)
|
159
|
+
if node.type == :return
|
160
|
+
result.concat reduce_to_value_nodes([node.children[0]])
|
161
|
+
# @todo Maybe return the result here because the rest of the code is
|
162
|
+
# unreachable
|
163
|
+
else
|
164
|
+
result.concat get_return_nodes_only(node)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
result
|
168
|
+
end
|
169
|
+
|
170
|
+
def reduce_to_value_nodes nodes
|
171
|
+
result = []
|
172
|
+
nodes.each do |node|
|
173
|
+
if REDUCEABLE.include?(node.type)
|
174
|
+
result.concat get_return_nodes_from_children(node)
|
175
|
+
# node.children.each do |child|
|
176
|
+
# result.concat reduce_to_value_nodes(child)
|
177
|
+
# end
|
178
|
+
elsif CONDITIONAL.include?(node.type)
|
179
|
+
result.concat reduce_to_value_nodes(node.children[1..-1])
|
180
|
+
elsif node.type == :return
|
181
|
+
result.concat get_return_nodes(node.children[0])
|
182
|
+
else
|
183
|
+
result.push node
|
184
|
+
end
|
185
|
+
end
|
186
|
+
result
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
109
190
|
end
|
110
191
|
end
|
111
192
|
end
|
@@ -2,9 +2,11 @@ module Solargraph
|
|
2
2
|
# An index of pins and other ApiMap-related data for a Source.
|
3
3
|
#
|
4
4
|
class SourceMap
|
5
|
+
autoload :NodeProcessor, 'solargraph/source_map/node_processor'
|
5
6
|
autoload :Mapper, 'solargraph/source_map/mapper'
|
6
7
|
autoload :Clip, 'solargraph/source_map/clip'
|
7
8
|
autoload :Completion, 'solargraph/source_map/completion'
|
9
|
+
autoload :Region, 'solargraph/source_map/region'
|
8
10
|
|
9
11
|
# @return [Source]
|
10
12
|
attr_reader :source
|
@@ -15,6 +17,9 @@ module Solargraph
|
|
15
17
|
# @return [Array<Pin::Base>]
|
16
18
|
attr_reader :locals
|
17
19
|
|
20
|
+
# @param source [Source]
|
21
|
+
# @param pins [Array<Pin::Base>]
|
22
|
+
# @param locals [Array<Pin::Base>]
|
18
23
|
def initialize source, pins, locals
|
19
24
|
# HACK: Keep the library from changing this
|
20
25
|
@source = source.dup
|
@@ -22,14 +27,17 @@ module Solargraph
|
|
22
27
|
@locals = locals
|
23
28
|
end
|
24
29
|
|
30
|
+
# @return [String]
|
25
31
|
def filename
|
26
32
|
source.filename
|
27
33
|
end
|
28
34
|
|
35
|
+
# @return [String]
|
29
36
|
def code
|
30
37
|
source.code
|
31
38
|
end
|
32
39
|
|
40
|
+
# @return [Array<Pin::Reference::Require>]
|
33
41
|
def requires
|
34
42
|
@requires ||= pins.select{|p| p.kind == Pin::REQUIRE_REFERENCE}
|
35
43
|
end
|
@@ -46,12 +54,15 @@ module Solargraph
|
|
46
54
|
@source.comment_at?(position)
|
47
55
|
end
|
48
56
|
|
57
|
+
# @return [Array<Pin::Base>]
|
49
58
|
def document_symbols
|
50
59
|
@document_symbols ||= pins.select { |pin|
|
51
60
|
[Pin::ATTRIBUTE, Pin::CONSTANT, Pin::METHOD, Pin::NAMESPACE].include?(pin.kind) and !pin.path.empty?
|
52
61
|
}
|
53
62
|
end
|
54
63
|
|
64
|
+
# @param query [String]
|
65
|
+
# @return [Array<Pin::Base>]
|
55
66
|
def query_symbols query
|
56
67
|
document_symbols.select{|pin| pin.path.include?(query)}
|
57
68
|
end
|
@@ -82,6 +93,7 @@ module Solargraph
|
|
82
93
|
end
|
83
94
|
|
84
95
|
# @param other_map [SourceMap]
|
96
|
+
# @return Boolean
|
85
97
|
def try_merge! other_map
|
86
98
|
return false if pins.length != other_map.pins.length || locals.length != other_map.locals.length || requires.map(&:name).uniq.sort != other_map.requires.map(&:name).uniq.sort
|
87
99
|
pins.each_index do |i|
|
@@ -101,12 +113,15 @@ module Solargraph
|
|
101
113
|
end
|
102
114
|
|
103
115
|
class << self
|
116
|
+
# @param filename [String]
|
104
117
|
# @return [SourceMap]
|
105
118
|
def load filename
|
106
119
|
source = Solargraph::Source.load(filename)
|
107
120
|
SourceMap.map(source)
|
108
121
|
end
|
109
122
|
|
123
|
+
# @param code [String]
|
124
|
+
# @param filename [String, nil]
|
110
125
|
# @return [SourceMap]
|
111
126
|
def load_string code, filename = nil
|
112
127
|
source = Solargraph::Source.load_string(code, filename)
|
@@ -29,7 +29,7 @@ module Solargraph
|
|
29
29
|
type = cursor.chain.base.infer(api_map, context_pin, locals)
|
30
30
|
else
|
31
31
|
full = cursor.chain.links.first.word
|
32
|
-
if full.include?('::')
|
32
|
+
if full.include?('::') && cursor.chain.links.length == 1
|
33
33
|
type = ComplexType.parse(full.split('::')[0..-2].join('::'))
|
34
34
|
elsif cursor.chain.links.length > 1
|
35
35
|
type = ComplexType.parse(full)
|
@@ -13,29 +13,14 @@ module Solargraph
|
|
13
13
|
# Generate the data.
|
14
14
|
#
|
15
15
|
# @return [Array]
|
16
|
-
def map
|
17
|
-
@filename = filename
|
18
|
-
@code = code
|
19
|
-
@
|
20
|
-
@
|
21
|
-
@node_stack = []
|
22
|
-
@directives = {}
|
23
|
-
@comment_ranges = comments.map do |c|
|
24
|
-
Range.from_to(c.loc.expression.line, c.loc.expression.column, c.loc.expression.last_line, c.loc.expression.last_column)
|
25
|
-
end
|
26
|
-
@node_comments = associate_comments(node, comments)
|
27
|
-
@pins = []
|
28
|
-
@locals = []
|
29
|
-
@strings = []
|
30
|
-
|
31
|
-
# HACK make sure the first node gets processed
|
32
|
-
root = AST::Node.new(:source, [filename])
|
33
|
-
root = root.append node
|
34
|
-
# @todo Is the root namespace a class or a module? Assuming class for now.
|
35
|
-
@pins.push Pin::Namespace.new(get_node_location(nil), '', '', nil, :class, :public)
|
36
|
-
process root
|
16
|
+
def map source
|
17
|
+
@filename = source.filename
|
18
|
+
@code = source.code
|
19
|
+
@comments = source.comments
|
20
|
+
@pins = Solargraph::SourceMap::NodeProcessor.process(source.node, Solargraph::SourceMap::Region.new(source: source), [])
|
37
21
|
process_comment_directives
|
38
|
-
|
22
|
+
locals = @pins.select{|p| [Pin::LocalVariable, Pin::MethodParameter, Pin::BlockParameter].include?(p.class)}
|
23
|
+
[@pins - locals, locals]
|
39
24
|
end
|
40
25
|
|
41
26
|
def unmap filename, code
|
@@ -50,23 +35,10 @@ module Solargraph
|
|
50
35
|
# @return [Array]
|
51
36
|
def map source
|
52
37
|
return new.unmap(source.filename, source.code) unless source.parsed?
|
53
|
-
new.map source
|
38
|
+
new.map source
|
54
39
|
end
|
55
40
|
end
|
56
41
|
|
57
|
-
# @param node [Parser::AST::Node]
|
58
|
-
# @return [String]
|
59
|
-
def code_for node
|
60
|
-
# @todo Using node locations on code with converted EOLs seems
|
61
|
-
# slightly more efficient than calculating offsets.
|
62
|
-
b = node.location.expression.begin.begin_pos
|
63
|
-
e = node.location.expression.end.end_pos
|
64
|
-
# b = Position.line_char_to_offset(@code, node.location.line - 1, node.location.column)
|
65
|
-
# e = Position.line_char_to_offset(@code, node.location.last_line - 1, node.location.last_column)
|
66
|
-
frag = source_from_parser[b..e-1].to_s
|
67
|
-
frag.strip.gsub(/,$/, '')
|
68
|
-
end
|
69
|
-
|
70
42
|
# @return [String]
|
71
43
|
def filename
|
72
44
|
@filename
|
@@ -77,346 +49,6 @@ module Solargraph
|
|
77
49
|
@pins ||= []
|
78
50
|
end
|
79
51
|
|
80
|
-
# @param node [Parser::AST::Node]
|
81
|
-
def process node, tree = [], visibility = :public, scope = :instance, fqn = '', stack = []
|
82
|
-
return unless node.is_a?(AST::Node)
|
83
|
-
return if node.type == :str
|
84
|
-
stack.push node
|
85
|
-
if node.kind_of?(AST::Node)
|
86
|
-
@node_stack.unshift node
|
87
|
-
if node.type == :class or node.type == :module
|
88
|
-
visibility = :public
|
89
|
-
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
|
90
|
-
tree = pack_name(node.children[0])
|
91
|
-
tree.shift if tree.first.empty?
|
92
|
-
else
|
93
|
-
tree = tree + pack_name(node.children[0])
|
94
|
-
end
|
95
|
-
fqn = tree.join('::')
|
96
|
-
sc = nil
|
97
|
-
if node.type == :class and !node.children[1].nil?
|
98
|
-
sc = unpack_name(node.children[1])
|
99
|
-
end
|
100
|
-
pins.push Solargraph::Pin::Namespace.new(get_node_location(node), tree[0..-2].join('::') || '', pack_name(node.children[0]).last.to_s, comments_for(node), node.type, visibility)
|
101
|
-
pins.push Pin::Reference::Superclass.new(pins.last.location, pins.last.path, sc) unless sc.nil?
|
102
|
-
end
|
103
|
-
file = filename
|
104
|
-
node.children.each do |c|
|
105
|
-
if c.kind_of?(AST::Node)
|
106
|
-
if c.type == :ivasgn
|
107
|
-
here = get_node_start_position(c)
|
108
|
-
named_path = get_named_path_pin(here)
|
109
|
-
if c.children[1].nil?
|
110
|
-
ora = find_parent(stack, :or_asgn)
|
111
|
-
unless ora.nil?
|
112
|
-
u = c.updated(:ivasgn, c.children + ora.children[1..-1], nil)
|
113
|
-
pins.push Solargraph::Pin::InstanceVariable.new(get_node_location(u), fqn || '', c.children[0].to_s, comments_for(u), u.children[1], infer_literal_node_type(u.children[1]), named_path.context)
|
114
|
-
if visibility == :module_function and named_path.kind == Pin::METHOD
|
115
|
-
other = ComplexType.parse("Module<#{named_path.context.namespace}>")
|
116
|
-
pins.push Solargraph::Pin::InstanceVariable.new(get_node_location(u), fqn || '', c.children[0].to_s, comments_for(u), u.children[1], infer_literal_node_type(u.children[1]), other) #unless other.nil?
|
117
|
-
end
|
118
|
-
end
|
119
|
-
else
|
120
|
-
pins.push Solargraph::Pin::InstanceVariable.new(get_node_location(c), fqn || '',c.children[0].to_s, comments_for(c), c.children[1], infer_literal_node_type(c.children[1]), named_path.context)
|
121
|
-
if visibility == :module_function and named_path.kind == Pin::METHOD
|
122
|
-
other = ComplexType.parse("Module<#{named_path.context.namespace}>")
|
123
|
-
pins.push Solargraph::Pin::InstanceVariable.new(get_node_location(c), fqn || '',c.children[0].to_s, comments_for(c), c.children[1], infer_literal_node_type(c.children[1]), other)
|
124
|
-
end
|
125
|
-
end
|
126
|
-
elsif c.type == :cvasgn
|
127
|
-
here = get_node_start_position(c)
|
128
|
-
context = get_named_path_pin(here)
|
129
|
-
if c.children[1].nil?
|
130
|
-
ora = find_parent(stack, :or_asgn)
|
131
|
-
unless ora.nil?
|
132
|
-
u = c.updated(:cvasgn, c.children + ora.children[1..-1], nil)
|
133
|
-
pins.push Solargraph::Pin::ClassVariable.new(get_node_location(u), fqn || '', c.children[0].to_s, comments_for(u), u.children[1], infer_literal_node_type(u.children[1]), context.context)
|
134
|
-
end
|
135
|
-
else
|
136
|
-
pins.push Solargraph::Pin::ClassVariable.new(get_node_location(c), fqn || '', c.children[0].to_s, comments_for(c), c.children[1], infer_literal_node_type(c.children[1]), context.context)
|
137
|
-
end
|
138
|
-
elsif c.type == :lvasgn
|
139
|
-
here = get_node_start_position(c)
|
140
|
-
context = get_named_path_pin(here)
|
141
|
-
block = get_block_pin(here)
|
142
|
-
presence = Range.new(here, block.location.range.ending)
|
143
|
-
if c.children[1].nil?
|
144
|
-
ora = find_parent(stack, :or_asgn)
|
145
|
-
unless ora.nil?
|
146
|
-
u = c.updated(:lvasgn, c.children + ora.children[1..-1], nil)
|
147
|
-
@locals.push Solargraph::Pin::LocalVariable.new(get_node_location(u), fqn, u.children[0].to_s, comments_for(ora), u.children[1], infer_literal_node_type(c.children[1]), context.context, block, presence)
|
148
|
-
end
|
149
|
-
else
|
150
|
-
@locals.push Solargraph::Pin::LocalVariable.new(get_node_location(c), fqn, c.children[0].to_s, comments_for(c), c.children[1], infer_literal_node_type(c.children[1]), context.context, block, presence)
|
151
|
-
end
|
152
|
-
elsif c.type == :gvasgn
|
153
|
-
if c.children[1].nil?
|
154
|
-
ora = find_parent(stack, :or_asgn)
|
155
|
-
unless ora.nil?
|
156
|
-
u = c.updated(:gvasgn, c.children + ora.children[1..-1], nil)
|
157
|
-
pins.push Solargraph::Pin::GlobalVariable.new(get_node_location(c), fqn, u.children[0].to_s, comments_for(c), u.children[1], infer_literal_node_type(c.children[1]), @pins.first.context)
|
158
|
-
end
|
159
|
-
else
|
160
|
-
pins.push Solargraph::Pin::GlobalVariable.new(get_node_location(c), fqn, c.children[0].to_s, comments_for(c), c.children[1], infer_literal_node_type(c.children[1]), @pins.first.context)
|
161
|
-
end
|
162
|
-
elsif c.type == :sym
|
163
|
-
pins.push Solargraph::Pin::Symbol.new(get_node_location(c), ":#{c.children[0]}")
|
164
|
-
elsif c.type == :casgn
|
165
|
-
here = get_node_start_position(c)
|
166
|
-
block = get_block_pin(here)
|
167
|
-
pins.push Solargraph::Pin::Constant.new(get_node_location(c), fqn, c.children[1].to_s, comments_for(c), c.children[2], infer_literal_node_type(c.children[2]), block.context, :public)
|
168
|
-
elsif c.type == :def
|
169
|
-
methpin = Solargraph::Pin::Method.new(get_node_location(c), fqn || '', c.children[(c.type == :def ? 0 : 1)].to_s, comments_for(c), scope, visibility, get_method_args(c))
|
170
|
-
if methpin.name == 'initialize' and methpin.scope == :instance
|
171
|
-
pins.push Solargraph::Pin::Method.new(methpin.location, methpin.namespace, 'new', methpin.comments, :class, :public, methpin.parameters)
|
172
|
-
# @todo Smelly instance variable access.
|
173
|
-
pins.last.instance_variable_set(:@return_complex_type, ComplexType.parse(methpin.namespace))
|
174
|
-
pins.push Solargraph::Pin::Method.new(methpin.location, methpin.namespace, methpin.name, methpin.comments, methpin.scope, :private, methpin.parameters)
|
175
|
-
elsif visibility == :module_function
|
176
|
-
pins.push Solargraph::Pin::Method.new(methpin.location, methpin.namespace, methpin.name, methpin.comments, :class, :public, methpin.parameters)
|
177
|
-
pins.push Solargraph::Pin::Method.new(methpin.location, methpin.namespace, methpin.name, methpin.comments, :instance, :private, methpin.parameters)
|
178
|
-
else
|
179
|
-
pins.push methpin
|
180
|
-
end
|
181
|
-
elsif c.type == :defs
|
182
|
-
s_visi = visibility
|
183
|
-
s_visi = :public if s_visi == :module_function or scope != :class
|
184
|
-
if c.children[0].is_a?(AST::Node) and c.children[0].type == :self
|
185
|
-
dfqn = fqn || ''
|
186
|
-
else
|
187
|
-
dfqn = unpack_name(c.children[0])
|
188
|
-
end
|
189
|
-
unless dfqn.nil?
|
190
|
-
pins.push Solargraph::Pin::Method.new(get_node_location(c), dfqn, "#{c.children[(node.type == :def ? 0 : 1)]}", comments_for(c), :class, s_visi, get_method_args(c))
|
191
|
-
process c, tree, scope, :class, dfqn, stack
|
192
|
-
end
|
193
|
-
next
|
194
|
-
elsif c.type == :send and [:public, :protected, :private].include?(c.children[1])
|
195
|
-
visibility = c.children[1]
|
196
|
-
elsif c.type == :send and [:private_class_method].include?(c.children[1]) and c.children[2].kind_of?(AST::Node)
|
197
|
-
if c.children[2].type == :sym or c.children[2].type == :str
|
198
|
-
ref = pins.select{|p| p.namespace == (fqn || '') and p.name == c.children[2].children[0].to_s}.first
|
199
|
-
unless ref.nil?
|
200
|
-
pins.delete ref
|
201
|
-
pins.push Solargraph::Pin::Method.new(ref.location, ref.namespace, ref.name, ref.comments, ref.scope, :private, ref.parameters)
|
202
|
-
end
|
203
|
-
else
|
204
|
-
process c, tree, :private, :class, fqn, stack
|
205
|
-
next
|
206
|
-
end
|
207
|
-
elsif c.type == :send and [:private_constant].include?(c.children[1]) and c.children[2].kind_of?(AST::Node)
|
208
|
-
if c.children[2].type == :sym or c.children[2].type == :str
|
209
|
-
# @todo What to do about references?
|
210
|
-
cn = c.children[2].children[0].to_s
|
211
|
-
ref = pins.select{|p| p.namespace == (fqn || '') and p.name == cn}.first
|
212
|
-
unless ref.nil?
|
213
|
-
pins.delete ref
|
214
|
-
# Might be either a namespace or constant
|
215
|
-
if ref.kind == Pin::CONSTANT
|
216
|
-
pins.push ref.class.new(ref.location, ref.namespace, ref.name, ref.comments, ref.signature, ref.return_type, ref.context, :private)
|
217
|
-
else
|
218
|
-
# pins.push ref.class.new(ref.location, ref.namespace, ref.name, ref.comments, ref.type, :private, (ref.superclass_reference.nil? ? nil : ref.superclass_reference.name))
|
219
|
-
pins.push ref.class.new(ref.location, ref.namespace, ref.name, ref.comments, ref.type, :private)
|
220
|
-
end
|
221
|
-
end
|
222
|
-
end
|
223
|
-
next
|
224
|
-
elsif c.type == :send and c.children[1] == :module_function
|
225
|
-
if c.children[2].nil?
|
226
|
-
visibility = :module_function
|
227
|
-
elsif c.children[2].type == :sym or c.children[2].type == :str
|
228
|
-
# @todo What to do about references?
|
229
|
-
c.children[2..-1].each do |x|
|
230
|
-
cn = x.children[0].to_s
|
231
|
-
ref = pins.select{|p| p.namespace == (fqn || '') and p.name == cn}.first
|
232
|
-
unless ref.nil?
|
233
|
-
pins.delete ref
|
234
|
-
mm = Solargraph::Pin::Method.new(ref.location, ref.namespace, ref.name, ref.comments, :class, :public, ref.parameters)
|
235
|
-
cm = Solargraph::Pin::Method.new(ref.location, ref.namespace, ref.name, ref.comments, :instance, :private, ref.parameters)
|
236
|
-
pins.push mm, cm
|
237
|
-
pins.select{|pin| pin.kind == Pin::INSTANCE_VARIABLE and pin.context == ref.context}.each do |ivar|
|
238
|
-
pins.delete ivar
|
239
|
-
pins.push Solargraph::Pin::InstanceVariable.new(ivar.location, ivar.namespace, ivar.name, ivar.comments, ivar.signature, ivar.instance_variable_get(:@literal), mm)
|
240
|
-
pins.push Solargraph::Pin::InstanceVariable.new(ivar.location, ivar.namespace, ivar.name, ivar.comments, ivar.signature, ivar.instance_variable_get(:@literal), cm)
|
241
|
-
end
|
242
|
-
end
|
243
|
-
end
|
244
|
-
elsif c.children[2].type == :def
|
245
|
-
# @todo A single function
|
246
|
-
process c, tree, :module_function, :class, fqn, stack
|
247
|
-
next
|
248
|
-
end
|
249
|
-
elsif c.type == :send and c.children[1] == :include and c.children[0].nil?
|
250
|
-
last_node = get_last_in_stack_not_begin(stack)
|
251
|
-
if last_node.nil? or last_node.type == :class or last_node.type == :module or last_node.type == :source
|
252
|
-
if c.children[2].kind_of?(AST::Node) and c.children[2].type == :const
|
253
|
-
c.children[2..-1].each do |i|
|
254
|
-
nspin = @pins.select{|pin| pin.kind == Pin::NAMESPACE and pin.path == fqn}.last
|
255
|
-
unless nspin.nil?
|
256
|
-
# iref = Pin::Reference.new(get_node_location(c), nspin.path, unpack_name(i))
|
257
|
-
# nspin.include_references.push(iref)
|
258
|
-
pins.push Pin::Reference::Include.new(get_node_location(c), nspin.path, unpack_name(i))
|
259
|
-
end
|
260
|
-
end
|
261
|
-
end
|
262
|
-
end
|
263
|
-
elsif c.type == :send and c.children[1] == :extend and c.children[0].nil?
|
264
|
-
last_node = get_last_in_stack_not_begin(stack)
|
265
|
-
if last_node.nil? or last_node.type == :class or last_node.type == :module or last_node.type == :source
|
266
|
-
c.children[2..-1].each do |i|
|
267
|
-
nspin = @pins.select{|pin| pin.kind == Pin::NAMESPACE and pin.path == fqn}.last
|
268
|
-
unless nspin.nil?
|
269
|
-
ref = nil
|
270
|
-
if i.type == :self
|
271
|
-
# ref = Pin::Reference.new(get_node_location(c), nspin.path, nspin.path)
|
272
|
-
ref = Pin::Reference::Extend.new(get_node_location(c), nspin.path, nspin.path)
|
273
|
-
elsif i.type == :const
|
274
|
-
# ref = Pin::Reference.new(get_node_location(c), nspin.path, unpack_name(i))
|
275
|
-
ref = Pin::Reference::Extend.new(get_node_location(c), nspin.path, unpack_name(i))
|
276
|
-
end
|
277
|
-
# nspin.extend_references.push(ref) unless ref.nil?
|
278
|
-
pins.push ref unless ref.nil?
|
279
|
-
end
|
280
|
-
end
|
281
|
-
end
|
282
|
-
elsif c.type == :send && [:attr_reader, :attr_writer, :attr_accessor].include?(c.children[1])
|
283
|
-
c.children[2..-1].each do |a|
|
284
|
-
if c.children[1] == :attr_reader or c.children[1] == :attr_accessor
|
285
|
-
pins.push Solargraph::Pin::Attribute.new(get_node_location(c), fqn || '', "#{a.children[0]}", comments_for(c), :reader, scope, visibility)
|
286
|
-
end
|
287
|
-
if c.children[1] == :attr_writer or c.children[1] == :attr_accessor
|
288
|
-
pins.push Solargraph::Pin::Attribute.new(get_node_location(c), fqn || '', "#{a.children[0]}=", comments_for(c), :writer, scope, visibility)
|
289
|
-
end
|
290
|
-
end
|
291
|
-
elsif c.type == :alias
|
292
|
-
pin = pins.select{|p| p.name == c.children[1].children[0].to_s && p.namespace == fqn && p.scope == scope}.first
|
293
|
-
unless pin.nil?
|
294
|
-
if pin.is_a?(Solargraph::Pin::Method)
|
295
|
-
pins.push Solargraph::Pin::Method.new(get_node_location(c), pin.namespace, c.children[0].children[0].to_s, comments_for(c) || pin.comments, pin.scope, pin.visibility, pin.parameters)
|
296
|
-
elsif pin.is_a?(Solargraph::Pin::Attribute)
|
297
|
-
pins.push Solargraph::Pin::Attribute.new(get_node_location(c), pin.namespace, c.children[0].children[0].to_s, comments_for(c) || pin.comments, pin.access, pin.scope, pin.visibility)
|
298
|
-
end
|
299
|
-
end
|
300
|
-
elsif c.type == :send && c.children[1] == :alias_method && c.children[2] && c.children[2] && c.children[2].type == :sym && c.children[3] && c.children[3].type == :sym
|
301
|
-
pin = pins.select{|p| p.name == c.children[3].children[0].to_s && p.namespace == fqn && p.scope == scope}.first
|
302
|
-
unless pin.nil?
|
303
|
-
if pin.is_a?(Solargraph::Pin::Method)
|
304
|
-
pins.push Solargraph::Pin::Method.new(get_node_location(c), pin.namespace, c.children[2].children[0].to_s, comments_for(c) || pin.comments, pin.scope, pin.visibility, pin.parameters)
|
305
|
-
elsif pin.is_a?(Solargraph::Pin::Attribute)
|
306
|
-
pins.push Solargraph::Pin::Attribute.new(get_node_location(c), pin.namespace, c.children[2].children[0].to_s, comments_for(c) || pin.comments, pin.access, pin.scope, pin.visibility)
|
307
|
-
end
|
308
|
-
end
|
309
|
-
elsif c.type == :sclass && c.children[0].type == :self
|
310
|
-
process c, tree, :public, :class, fqn || '', stack
|
311
|
-
next
|
312
|
-
elsif c.type == :send && c.children[1] == :require
|
313
|
-
if c.children[2].kind_of?(AST::Node) and c.children[2].type == :str
|
314
|
-
# @requires.push Solargraph::Pin::Reference.new(get_node_location(c), fqn, c.children[2].children[0].to_s)
|
315
|
-
pins.push Pin::Reference::Require.new(get_node_location(c), c.children[2].children[0].to_s)
|
316
|
-
end
|
317
|
-
elsif c.type == :args
|
318
|
-
if @node_stack.first.type == :block
|
319
|
-
pi = 0
|
320
|
-
c.children.each do |u|
|
321
|
-
here = get_node_start_position(c)
|
322
|
-
blk = get_block_pin(here)
|
323
|
-
@locals.push Solargraph::Pin::BlockParameter.new(get_node_location(u), fqn || '', "#{u.children[0]}", comments_for(c), blk)
|
324
|
-
blk.parameters.push @locals.push.last
|
325
|
-
pi += 1
|
326
|
-
end
|
327
|
-
else
|
328
|
-
c.children.each do |u|
|
329
|
-
here = get_node_start_position(u)
|
330
|
-
context = get_named_path_pin(here)
|
331
|
-
block = get_block_pin(here)
|
332
|
-
presence = Range.new(here, block.location.range.ending)
|
333
|
-
@locals.push Solargraph::Pin::MethodParameter.new(get_node_location(u), fqn, u.children[0].to_s, comments_for(c), resolve_node_signature(u.children[1]), infer_literal_node_type(u.children[1]), context, block, presence)
|
334
|
-
end
|
335
|
-
end
|
336
|
-
elsif c.type == :block
|
337
|
-
here = get_node_start_position(c)
|
338
|
-
named_path = get_named_path_pin(here)
|
339
|
-
@pins.push Solargraph::Pin::Block.new(get_node_location(c), fqn || '', '', comments_for(c), c.children[0], named_path.context)
|
340
|
-
end
|
341
|
-
process c, tree, visibility, scope, fqn, stack
|
342
|
-
end
|
343
|
-
end
|
344
|
-
@node_stack.shift
|
345
|
-
end
|
346
|
-
stack.pop
|
347
|
-
end
|
348
|
-
|
349
|
-
def get_last_in_stack_not_begin stack
|
350
|
-
index = stack.length - 1
|
351
|
-
last = stack[index]
|
352
|
-
while !last.nil? and last.type == :begin
|
353
|
-
index -= 1
|
354
|
-
last = stack[index]
|
355
|
-
end
|
356
|
-
last
|
357
|
-
end
|
358
|
-
|
359
|
-
def get_block_pin position
|
360
|
-
@pins.select{|pin| [Pin::BLOCK, Pin::NAMESPACE, Pin::METHOD].include?(pin.kind) and pin.location.range.contain?(position)}.last
|
361
|
-
end
|
362
|
-
|
363
|
-
def get_named_path_pin position
|
364
|
-
@pins.select{|pin| [Pin::NAMESPACE, Pin::METHOD].include?(pin.kind) and pin.location.range.contain?(position)}.last
|
365
|
-
end
|
366
|
-
|
367
|
-
def get_namespace_pin position
|
368
|
-
@pins.select{|pin| pin.kind == Pin::NAMESPACE and pin.location.range.contain?(position)}.last
|
369
|
-
end
|
370
|
-
|
371
|
-
# @return [String]
|
372
|
-
def comments_for node
|
373
|
-
result = @node_comments[node.loc]
|
374
|
-
return nil if result.nil?
|
375
|
-
result
|
376
|
-
end
|
377
|
-
|
378
|
-
# @param node [Parser::AST::Node]
|
379
|
-
# @return [Solargraph::Location]
|
380
|
-
def get_node_location(node)
|
381
|
-
if node.nil?
|
382
|
-
st = Position.new(0, 0)
|
383
|
-
en = Position.from_offset(@code, @code.length)
|
384
|
-
else
|
385
|
-
st = Position.new(node.loc.line, node.loc.column)
|
386
|
-
en = Position.new(node.loc.last_line, node.loc.last_column)
|
387
|
-
end
|
388
|
-
range = Range.new(st, en)
|
389
|
-
Location.new(filename, range)
|
390
|
-
end
|
391
|
-
|
392
|
-
# @param node [Parser::AST::Node]
|
393
|
-
# @param comments [Array]
|
394
|
-
# @return [Hash]
|
395
|
-
def associate_comments node, comments
|
396
|
-
return nil if comments.nil?
|
397
|
-
comment_hash = Parser::Source::Comment.associate_locations(node, comments)
|
398
|
-
result_hash = {}
|
399
|
-
comment_hash.each_pair { |k, v|
|
400
|
-
ctxt = ''
|
401
|
-
num = nil
|
402
|
-
started = false
|
403
|
-
v.each { |l|
|
404
|
-
# Trim the comment and minimum leading whitespace
|
405
|
-
p = l.text.gsub(/^#/, '')
|
406
|
-
if num.nil? and !p.strip.empty?
|
407
|
-
num = p.index(/[^ ]/)
|
408
|
-
started = true
|
409
|
-
elsif started and !p.strip.empty?
|
410
|
-
cur = p.index(/[^ ]/)
|
411
|
-
num = cur if cur < num
|
412
|
-
end
|
413
|
-
ctxt += "#{p[num..-1]}\n" if started
|
414
|
-
}
|
415
|
-
result_hash[k] = ctxt
|
416
|
-
}
|
417
|
-
result_hash
|
418
|
-
end
|
419
|
-
|
420
52
|
# @param node [Parser::AST::Node]
|
421
53
|
# @return [Solargraph::Pin::Namespace]
|
422
54
|
def namespace_for(node)
|
@@ -428,46 +60,6 @@ module Solargraph
|
|
428
60
|
@pins.select{|pin| pin.kind == Pin::NAMESPACE and pin.location.range.contain?(position)}.last
|
429
61
|
end
|
430
62
|
|
431
|
-
def find_parent(stack, *types)
|
432
|
-
stack.reverse.each { |p|
|
433
|
-
return p if types.include?(p.type)
|
434
|
-
}
|
435
|
-
nil
|
436
|
-
end
|
437
|
-
|
438
|
-
def get_method_args node
|
439
|
-
return [] if node.nil?
|
440
|
-
list = nil
|
441
|
-
args = []
|
442
|
-
node.children.each { |c|
|
443
|
-
if c.kind_of?(AST::Node) and c.type == :args
|
444
|
-
list = c
|
445
|
-
break
|
446
|
-
end
|
447
|
-
}
|
448
|
-
return args if list.nil?
|
449
|
-
list.children.each { |c|
|
450
|
-
if c.type == :arg
|
451
|
-
args.push c.children[0].to_s
|
452
|
-
elsif c.type == :restarg
|
453
|
-
args.push "*#{c.children[0]}"
|
454
|
-
elsif c.type == :optarg
|
455
|
-
args.push "#{c.children[0]} = #{code_for(c.children[1])}"
|
456
|
-
elsif c.type == :kwarg
|
457
|
-
args.push "#{c.children[0]}:"
|
458
|
-
elsif c.type == :kwoptarg
|
459
|
-
args.push "#{c.children[0]}: #{code_for(c.children[1])}"
|
460
|
-
elsif c.type == :blockarg
|
461
|
-
args.push "&#{c.children[0]}"
|
462
|
-
end
|
463
|
-
}
|
464
|
-
args
|
465
|
-
end
|
466
|
-
|
467
|
-
def source_from_parser
|
468
|
-
@source_from_parser ||= @code.gsub(/\r\n/, "\n")
|
469
|
-
end
|
470
|
-
|
471
63
|
def process_comment position, comment
|
472
64
|
cmnt = remove_inline_comment_hashes(comment)
|
473
65
|
return unless cmnt =~ /(@\!method|@\!attribute|@\!domain|@\!macro)/
|
@@ -485,7 +77,7 @@ module Solargraph
|
|
485
77
|
namespace = namespace_at(position)
|
486
78
|
gen_src = Solargraph::SourceMap.load_string("def #{directive.tag.name};end")
|
487
79
|
gen_pin = gen_src.pins.last # Method is last pin after root namespace
|
488
|
-
@pins.push Solargraph::Pin::Method.new(location, namespace.path, gen_pin.name, docstring.all, :instance, :public, gen_pin.parameters)
|
80
|
+
@pins.push Solargraph::Pin::Method.new(location, namespace.path, gen_pin.name, docstring.all, :instance, :public, gen_pin.parameters, nil)
|
489
81
|
when 'attribute'
|
490
82
|
namespace = namespace_at(position)
|
491
83
|
t = (directive.tag.types.nil? || directive.tag.types.empty?) ? nil : directive.tag.types.flatten.join('')
|
@@ -499,10 +91,6 @@ module Solargraph
|
|
499
91
|
when 'domain'
|
500
92
|
namespace = namespace_at(position)
|
501
93
|
namespace.domains.push directive.tag.text
|
502
|
-
when 'macro'
|
503
|
-
nxt_pos = Position.new(position.line + 1, @code.lines[position.line + 1].length)
|
504
|
-
path_pin = get_named_path_pin(nxt_pos)
|
505
|
-
path_pin.macros.push directive
|
506
94
|
end
|
507
95
|
end
|
508
96
|
|