solargraph 0.28.4 → 0.29.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/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
|
|