solargraph 0.26.1 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/solargraph.rb +5 -2
- data/lib/solargraph/api_map.rb +236 -234
- data/lib/solargraph/api_map/store.rb +18 -53
- data/lib/solargraph/bundle.rb +22 -0
- data/lib/solargraph/complex_type.rb +9 -5
- data/lib/solargraph/complex_type/type_methods.rb +113 -0
- data/lib/solargraph/complex_type/unique_type.rb +35 -0
- data/lib/solargraph/core_fills.rb +1 -0
- data/lib/solargraph/diagnostics.rb +6 -4
- data/lib/solargraph/diagnostics/base.rb +3 -0
- data/lib/solargraph/diagnostics/require_not_found.rb +2 -1
- data/lib/solargraph/diagnostics/rubocop.rb +21 -6
- data/lib/solargraph/diagnostics/type_not_defined.rb +4 -3
- data/lib/solargraph/diagnostics/update_errors.rb +18 -0
- data/lib/solargraph/language_server/host.rb +90 -222
- data/lib/solargraph/language_server/host/cataloger.rb +68 -0
- data/lib/solargraph/language_server/host/diagnoser.rb +85 -0
- data/lib/solargraph/language_server/message/extended/check_gem_version.rb +35 -24
- data/lib/solargraph/language_server/message/text_document/completion.rb +6 -8
- data/lib/solargraph/language_server/message/text_document/document_symbol.rb +1 -1
- data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +0 -1
- data/lib/solargraph/language_server/transport/socket.rb +4 -6
- data/lib/solargraph/language_server/transport/stdio.rb +4 -6
- data/lib/solargraph/library.rb +152 -99
- data/lib/solargraph/live_map.rb +1 -1
- data/lib/solargraph/location.rb +28 -0
- data/lib/solargraph/pin.rb +2 -0
- data/lib/solargraph/pin/attribute.rb +26 -12
- data/lib/solargraph/pin/base.rb +15 -35
- data/lib/solargraph/pin/base_variable.rb +7 -15
- data/lib/solargraph/pin/block.rb +5 -9
- data/lib/solargraph/pin/block_parameter.rb +9 -7
- data/lib/solargraph/pin/conversions.rb +5 -5
- data/lib/solargraph/pin/duck_method.rb +1 -1
- data/lib/solargraph/pin/instance_variable.rb +0 -4
- data/lib/solargraph/pin/keyword.rb +4 -0
- data/lib/solargraph/pin/localized.rb +5 -3
- data/lib/solargraph/pin/method.rb +11 -0
- data/lib/solargraph/pin/namespace.rb +7 -3
- data/lib/solargraph/pin/proxy_type.rb +3 -7
- data/lib/solargraph/pin/reference.rb +2 -2
- data/lib/solargraph/pin/symbol.rb +1 -1
- data/lib/solargraph/pin/yard_pin/method.rb +2 -2
- data/lib/solargraph/pin/yard_pin/namespace.rb +16 -7
- data/lib/solargraph/position.rb +103 -0
- data/lib/solargraph/range.rb +70 -0
- data/lib/solargraph/source.rb +159 -328
- data/lib/solargraph/source/chain.rb +38 -55
- data/lib/solargraph/source/chain/call.rb +47 -29
- data/lib/solargraph/source/chain/class_variable.rb +2 -2
- data/lib/solargraph/source/chain/constant.rb +3 -3
- data/lib/solargraph/source/chain/definition.rb +7 -3
- data/lib/solargraph/source/chain/global_variable.rb +1 -1
- data/lib/solargraph/source/chain/head.rb +22 -9
- data/lib/solargraph/source/chain/instance_variable.rb +2 -2
- data/lib/solargraph/source/chain/link.rb +4 -4
- data/lib/solargraph/source/chain/literal.rb +1 -1
- data/lib/solargraph/source/chain/variable.rb +2 -2
- data/lib/solargraph/source/change.rb +0 -6
- data/lib/solargraph/source/cursor.rb +161 -0
- data/lib/solargraph/source/encoding_fixes.rb +1 -1
- data/lib/solargraph/source/node_chainer.rb +28 -21
- data/lib/solargraph/source/node_methods.rb +1 -1
- data/lib/solargraph/source/source_chainer.rb +217 -0
- data/lib/solargraph/source_map.rb +138 -0
- data/lib/solargraph/source_map/clip.rb +123 -0
- data/lib/solargraph/{source → source_map}/completion.rb +3 -3
- data/lib/solargraph/{source → source_map}/mapper.rb +143 -41
- data/lib/solargraph/version.rb +1 -1
- data/lib/solargraph/workspace.rb +13 -20
- data/lib/solargraph/yard_map.rb +77 -48
- metadata +17 -11
- data/lib/solargraph/basic_type.rb +0 -33
- data/lib/solargraph/basic_type_methods.rb +0 -111
- data/lib/solargraph/source/call_chainer.rb +0 -273
- data/lib/solargraph/source/fragment.rb +0 -342
- data/lib/solargraph/source/location.rb +0 -23
- data/lib/solargraph/source/position.rb +0 -95
- data/lib/solargraph/source/range.rb +0 -64
@@ -9,7 +9,7 @@ module Solargraph
|
|
9
9
|
# @return [String]
|
10
10
|
def normalize string
|
11
11
|
begin
|
12
|
-
string.force_encoding('UTF-8')
|
12
|
+
string.clone.force_encoding('UTF-8')
|
13
13
|
rescue ::Encoding::CompatibilityError, ::Encoding::UndefinedConversionError, ::Encoding::InvalidByteSequenceError => e
|
14
14
|
# @todo Improve error handling
|
15
15
|
STDERR.puts "Normalize error: #{e.message}"
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module Solargraph
|
2
2
|
class Source
|
3
3
|
class NodeChainer
|
4
|
-
include NodeMethods
|
4
|
+
include Source::NodeMethods
|
5
5
|
|
6
|
-
def initialize
|
7
|
-
@filename = filename
|
6
|
+
def initialize node, filename = nil
|
8
7
|
@node = node
|
8
|
+
@filename = filename
|
9
9
|
# @source = source
|
10
10
|
# @line = line
|
11
11
|
# @column = column
|
@@ -14,23 +14,23 @@ module Solargraph
|
|
14
14
|
# @return [Source::Chain]
|
15
15
|
def chain
|
16
16
|
links = generate_links(@node)
|
17
|
-
Chain.new(
|
17
|
+
Chain.new(links)
|
18
18
|
end
|
19
19
|
|
20
20
|
class << self
|
21
|
-
# @param
|
22
|
-
# @param
|
23
|
-
# @
|
24
|
-
|
25
|
-
|
26
|
-
NodeChainer.new(filename, node).chain
|
21
|
+
# @param node [Parser::AST::Node]
|
22
|
+
# @param filename [String]
|
23
|
+
# @return [Chain]
|
24
|
+
def chain node, filename = nil
|
25
|
+
NodeChainer.new(node, filename).chain
|
27
26
|
end
|
28
27
|
|
29
28
|
# @param code [String]
|
29
|
+
# @param filename [String, nil]
|
30
30
|
# @return [Chain]
|
31
|
-
def load_string(
|
32
|
-
node = Source.
|
33
|
-
chain =
|
31
|
+
def load_string(code)
|
32
|
+
node = Source.parse(code.sub(/\.$/, ''))
|
33
|
+
chain = NodeChainer.new(node).chain
|
34
34
|
chain.links.push(Chain::Link.new) if code.end_with?('.')
|
35
35
|
chain
|
36
36
|
end
|
@@ -54,24 +54,29 @@ module Solargraph
|
|
54
54
|
result.concat generate_links(n.children[0])
|
55
55
|
args = []
|
56
56
|
n.children[2..-1].each do |c|
|
57
|
-
|
58
|
-
# args.push Chain.new(source, c.loc.last_line - 1, c.loc.column)
|
57
|
+
args.push NodeChainer.chain(c)
|
59
58
|
end
|
60
59
|
result.push Chain::Call.new(n.children[1].to_s, args)
|
61
60
|
elsif n.children[0].nil?
|
62
61
|
args = []
|
63
62
|
n.children[2..-1].each do |c|
|
64
|
-
|
65
|
-
# args.push Chain.new(source, c.loc.last_line - 1, c.loc.column)
|
63
|
+
args.push NodeChainer.chain(c)
|
66
64
|
end
|
67
65
|
result.push Chain::Call.new(n.children[1].to_s, args)
|
68
66
|
else
|
69
67
|
raise "No idea what to do with #{n}"
|
70
68
|
end
|
71
69
|
elsif n.type == :self
|
72
|
-
result.push Chain::
|
70
|
+
result.push Chain::Head.new('self')
|
71
|
+
elsif n.type == :zsuper
|
72
|
+
result.push Chain::Head.new('super')
|
73
73
|
elsif n.type == :const
|
74
|
-
result.push Chain::Constant.new(unpack_name(n))
|
74
|
+
# result.push Chain::Constant.new(unpack_name(n))
|
75
|
+
const = unpack_name(n)
|
76
|
+
parts = const.split('::')
|
77
|
+
last = parts.pop
|
78
|
+
result.push Chain::Constant.new(parts.join('::')) unless parts.empty?
|
79
|
+
result.push Chain::Constant.new(last)
|
75
80
|
elsif [:lvar, :lvasgn].include?(n.type)
|
76
81
|
result.push Chain::Call.new(n.children[0].to_s)
|
77
82
|
elsif [:ivar, :ivasgn].include?(n.type)
|
@@ -81,8 +86,10 @@ module Solargraph
|
|
81
86
|
elsif [:gvar, :gvasgn].include?(n.type)
|
82
87
|
result.push Chain::GlobalVariable.new(n.children[0].to_s)
|
83
88
|
elsif [:class, :module, :def, :defs].include?(n.type)
|
84
|
-
location = Solargraph::
|
85
|
-
result.push Chain::Definition.new(location)
|
89
|
+
# location = Solargraph::Location.new(@filename, Range.from_to(n.loc.expression.line, n.loc.expression.column, n.loc.expression.last_line, n.loc.expression.last_column))
|
90
|
+
# result.push Chain::Definition.new(location)
|
91
|
+
# @todo Undefined or what?
|
92
|
+
result.push Chain::UNDEFINED_CALL
|
86
93
|
else
|
87
94
|
lit = infer_literal_node_type(n)
|
88
95
|
result.push (lit ? Chain::Literal.new(lit) : Chain::Link.new)
|
@@ -0,0 +1,217 @@
|
|
1
|
+
module Solargraph
|
2
|
+
class Source
|
3
|
+
# Information about a location in a source, including the location's word
|
4
|
+
# and signature, literal values at the base of signatures, and whether the
|
5
|
+
# location is inside a string or comment. ApiMaps use Fragments to provide
|
6
|
+
# results for completion and definition queries.
|
7
|
+
#
|
8
|
+
class SourceChainer
|
9
|
+
include Source::NodeMethods
|
10
|
+
|
11
|
+
private_class_method :new
|
12
|
+
|
13
|
+
class << self
|
14
|
+
# @param source [Source]
|
15
|
+
# @param position [Position]
|
16
|
+
# @return [Source::Chain]
|
17
|
+
def chain source, position
|
18
|
+
raise "Not a source" unless source.is_a?(Source)
|
19
|
+
new(source, position).chain
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# @param source [Source]
|
24
|
+
# @param position [Position]
|
25
|
+
def initialize source, position
|
26
|
+
@source = source
|
27
|
+
# @source.code = source.code
|
28
|
+
@position = position
|
29
|
+
# @todo Get rid of line/column
|
30
|
+
@line = position.line
|
31
|
+
@column = position.column
|
32
|
+
@calculated_literal = false
|
33
|
+
end
|
34
|
+
|
35
|
+
# @return [Source::Chain]
|
36
|
+
def chain
|
37
|
+
return Chain.new([Chain::Literal.new('Symbol')]) if phrase.start_with?(':') && !phrase.start_with?('::')
|
38
|
+
begin
|
39
|
+
if source.repaired? && source.parsed?
|
40
|
+
node = source.node_at(fixed_position.line, fixed_position.column)
|
41
|
+
elsif source.parsed?
|
42
|
+
node = source.node_at(position.line, position.column)
|
43
|
+
else
|
44
|
+
node = Source.parse(fixed_phrase)
|
45
|
+
end
|
46
|
+
rescue Parser::SyntaxError
|
47
|
+
return Chain.new([Chain::UNDEFINED_CALL])
|
48
|
+
end
|
49
|
+
return Chain.new([Chain::UNDEFINED_CALL]) if node.nil? || (node.type == :sym && !phrase.start_with?(':'))
|
50
|
+
chain = NodeChainer.chain(node, source.filename)
|
51
|
+
if source.repaired? || !source.parsed?
|
52
|
+
if end_of_phrase.strip == '.'
|
53
|
+
chain.links.push Chain::UNDEFINED_CALL
|
54
|
+
elsif end_of_phrase.strip == '::'
|
55
|
+
chain.links.push Chain::UNDEFINED_CONSTANT
|
56
|
+
end
|
57
|
+
elsif end_of_phrase.strip == '::'
|
58
|
+
chain.links.pop
|
59
|
+
chain.links.push Chain::UNDEFINED_CONSTANT
|
60
|
+
end
|
61
|
+
chain
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
attr_reader :position
|
67
|
+
|
68
|
+
# The zero-based line number of the fragment's location.
|
69
|
+
#
|
70
|
+
# @return [Integer]
|
71
|
+
attr_reader :line
|
72
|
+
|
73
|
+
# The zero-based column number of the fragment's location.
|
74
|
+
#
|
75
|
+
# @return [Integer]
|
76
|
+
attr_reader :column
|
77
|
+
|
78
|
+
# @return [Solargraph::Source]
|
79
|
+
attr_reader :source
|
80
|
+
|
81
|
+
def phrase
|
82
|
+
@phrase ||= source.code[signature_data[0]..offset-1]
|
83
|
+
end
|
84
|
+
|
85
|
+
def fixed_phrase
|
86
|
+
@fixed_phrase ||= phrase[0..-(end_of_phrase.length+1)]
|
87
|
+
end
|
88
|
+
|
89
|
+
def fixed_position
|
90
|
+
@fixed_position ||= Position.from_offset(source.code, offset - end_of_phrase.length)
|
91
|
+
end
|
92
|
+
|
93
|
+
def end_of_phrase
|
94
|
+
@end_of_phrase ||= begin
|
95
|
+
match = phrase.match(/[\s]*(\.{1}|::)[\s]*$/)
|
96
|
+
if match
|
97
|
+
match[0]
|
98
|
+
else
|
99
|
+
''
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# An alias for #column.
|
105
|
+
#
|
106
|
+
# @return [Integer]
|
107
|
+
def character
|
108
|
+
@column
|
109
|
+
end
|
110
|
+
|
111
|
+
# @return [Position]
|
112
|
+
def position
|
113
|
+
@position ||= Position.new(line, column)
|
114
|
+
end
|
115
|
+
|
116
|
+
# True if the current offset is inside a string.
|
117
|
+
#
|
118
|
+
# @return [Boolean]
|
119
|
+
def string?
|
120
|
+
# @string ||= (node.type == :str or node.type == :dstr)
|
121
|
+
@string ||= @source.string_at?(position)
|
122
|
+
end
|
123
|
+
|
124
|
+
# @return [Integer]
|
125
|
+
def offset
|
126
|
+
@offset ||= get_offset(line, column)
|
127
|
+
end
|
128
|
+
|
129
|
+
def get_offset line, column
|
130
|
+
Position.line_char_to_offset(@source.code, line, column)
|
131
|
+
end
|
132
|
+
|
133
|
+
def signature_data
|
134
|
+
@signature_data ||= get_signature_data_at(offset)
|
135
|
+
end
|
136
|
+
|
137
|
+
def get_signature_data_at index
|
138
|
+
brackets = 0
|
139
|
+
squares = 0
|
140
|
+
parens = 0
|
141
|
+
signature = ''
|
142
|
+
index -=1
|
143
|
+
in_whitespace = false
|
144
|
+
while index >= 0
|
145
|
+
pos = Position.from_offset(@source.code, index)
|
146
|
+
break if index > 0 and @source.comment_at?(pos)
|
147
|
+
unless !in_whitespace and string?
|
148
|
+
break if brackets > 0 or parens > 0 or squares > 0
|
149
|
+
char = @source.code[index, 1]
|
150
|
+
break if char.nil? # @todo Is this the right way to handle this?
|
151
|
+
if brackets.zero? and parens.zero? and squares.zero? and [' ', "\r", "\n", "\t"].include?(char)
|
152
|
+
in_whitespace = true
|
153
|
+
else
|
154
|
+
if brackets.zero? and parens.zero? and squares.zero? and in_whitespace
|
155
|
+
unless char == '.' or @source.code[index+1..-1].strip.start_with?('.')
|
156
|
+
old = @source.code[index+1..-1]
|
157
|
+
nxt = @source.code[index+1..-1].lstrip
|
158
|
+
index += (@source.code[index+1..-1].length - @source.code[index+1..-1].lstrip.length)
|
159
|
+
break
|
160
|
+
end
|
161
|
+
end
|
162
|
+
if char == ')'
|
163
|
+
parens -=1
|
164
|
+
elsif char == ']'
|
165
|
+
squares -=1
|
166
|
+
elsif char == '}'
|
167
|
+
brackets -= 1
|
168
|
+
elsif char == '('
|
169
|
+
parens += 1
|
170
|
+
elsif char == '{'
|
171
|
+
brackets += 1
|
172
|
+
elsif char == '['
|
173
|
+
squares += 1
|
174
|
+
signature = ".[]#{signature}" if parens.zero? and brackets.zero? and squares.zero? and @source.code[index-2] != '%'
|
175
|
+
end
|
176
|
+
if brackets.zero? and parens.zero? and squares.zero?
|
177
|
+
break if ['"', "'", ',', ';', '%'].include?(char)
|
178
|
+
signature = char + signature if char.match(/[a-z0-9:\._@\$\?\!]/i) and @source.code[index - 1] != '%'
|
179
|
+
break if char == '$'
|
180
|
+
if char == '@'
|
181
|
+
signature = "@#{signature}" if @source.code[index-1, 1] == '@'
|
182
|
+
break
|
183
|
+
end
|
184
|
+
elsif parens == 1 || brackets == 1 || squares == 1
|
185
|
+
break
|
186
|
+
end
|
187
|
+
in_whitespace = false
|
188
|
+
end
|
189
|
+
end
|
190
|
+
index -= 1
|
191
|
+
end
|
192
|
+
# @todo Smelly exceptional case for integer literals
|
193
|
+
# match = signature.match(/^[0-9]+/)
|
194
|
+
# if match
|
195
|
+
# index += match[0].length
|
196
|
+
# signature = signature[match[0].length..-1].to_s
|
197
|
+
# @base_literal = 'Integer'
|
198
|
+
# # @todo Smelly exceptional case for array literals
|
199
|
+
# elsif signature.start_with?('.[]')
|
200
|
+
# index += 2
|
201
|
+
# signature = signature[3..-1].to_s
|
202
|
+
# @base_literal = 'Array'
|
203
|
+
# elsif signature.start_with?('.')
|
204
|
+
# pos = Position.from_offset(@source.code, index)
|
205
|
+
# node = @source.node_at(pos.line, pos.character)
|
206
|
+
# lit = infer_literal_node_type(node)
|
207
|
+
# unless lit.nil?
|
208
|
+
# signature = signature[1..-1].to_s
|
209
|
+
# index += 1
|
210
|
+
# @base_literal = lit
|
211
|
+
# end
|
212
|
+
# end
|
213
|
+
[index + 1, signature]
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
module Solargraph
|
2
|
+
# An index of pins and other ApiMap-related data for a Source.
|
3
|
+
#
|
4
|
+
class SourceMap
|
5
|
+
autoload :Mapper, 'solargraph/source_map/mapper'
|
6
|
+
autoload :Clip, 'solargraph/source_map/clip'
|
7
|
+
autoload :Completion, 'solargraph/source_map/completion'
|
8
|
+
|
9
|
+
# @return [Source]
|
10
|
+
attr_reader :source
|
11
|
+
|
12
|
+
# @return [Array<Pin::Base>]
|
13
|
+
attr_reader :pins
|
14
|
+
|
15
|
+
# @return [Array<Pin::Base>]
|
16
|
+
attr_reader :locals
|
17
|
+
|
18
|
+
# @return [Array<Pin::Reference>]
|
19
|
+
attr_reader :requires
|
20
|
+
|
21
|
+
def initialize source, pins, locals, requires, symbols
|
22
|
+
# HACK: Keep the library from changing this
|
23
|
+
@source = source.dup
|
24
|
+
@pins = pins
|
25
|
+
@locals = locals
|
26
|
+
@requires = requires
|
27
|
+
@pins.concat symbols
|
28
|
+
end
|
29
|
+
|
30
|
+
def filename
|
31
|
+
source.filename
|
32
|
+
end
|
33
|
+
|
34
|
+
def code
|
35
|
+
source.code
|
36
|
+
end
|
37
|
+
|
38
|
+
# @param position [Position]
|
39
|
+
# @return [Boolean]
|
40
|
+
def string_at? position
|
41
|
+
@source.string_at?(position)
|
42
|
+
end
|
43
|
+
|
44
|
+
# @param position [Position]
|
45
|
+
# @return [Boolean]
|
46
|
+
def comment_at? position
|
47
|
+
@source.comment_at?(position)
|
48
|
+
end
|
49
|
+
|
50
|
+
def document_symbols
|
51
|
+
@document_symbols ||= pins.select { |pin|
|
52
|
+
[Pin::ATTRIBUTE, Pin::CONSTANT, Pin::METHOD, Pin::NAMESPACE].include?(pin.kind) and !pin.path.empty?
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
def query_symbols query
|
57
|
+
document_symbols.select{|pin| pin.path.include?(query)}
|
58
|
+
end
|
59
|
+
|
60
|
+
# @param position [Position]
|
61
|
+
# @return [Solargraph::SourceMap::Fragment]
|
62
|
+
def cursor_at position
|
63
|
+
Source::Cursor.new(source, position)
|
64
|
+
end
|
65
|
+
|
66
|
+
def first_pin path
|
67
|
+
pins.select { |p| p.path == path }.first
|
68
|
+
end
|
69
|
+
|
70
|
+
# @param location [Solargraph::Location]
|
71
|
+
# @return [Solargraph::Pin::Base]
|
72
|
+
def locate_pin location
|
73
|
+
# return nil unless location.start_with?("#{filename}:")
|
74
|
+
pins.select{|pin| pin.location == location}.first
|
75
|
+
end
|
76
|
+
|
77
|
+
def locate_named_path_pin line, character
|
78
|
+
_locate_pin line, character, Pin::NAMESPACE, Pin::METHOD
|
79
|
+
end
|
80
|
+
|
81
|
+
def locate_block_pin line, character
|
82
|
+
_locate_pin line, character, Pin::NAMESPACE, Pin::METHOD, Pin::BLOCK
|
83
|
+
end
|
84
|
+
|
85
|
+
# @param other_map [SourceMap]
|
86
|
+
def try_merge! other_map
|
87
|
+
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
|
88
|
+
pins.each_index do |i|
|
89
|
+
return false unless pins[i].try_merge!(other_map.pins[i])
|
90
|
+
end
|
91
|
+
locals.each_index do |i|
|
92
|
+
return false unless locals[i].try_merge!(other_map.locals[i])
|
93
|
+
end
|
94
|
+
@source = other_map.source
|
95
|
+
true
|
96
|
+
end
|
97
|
+
|
98
|
+
# @param name [String]
|
99
|
+
# @return [Array<Location>]
|
100
|
+
def references name
|
101
|
+
source.references name
|
102
|
+
end
|
103
|
+
|
104
|
+
class << self
|
105
|
+
# @return [SourceMap]
|
106
|
+
def load filename
|
107
|
+
source = Solargraph::Source.load(filename)
|
108
|
+
SourceMap.map(source)
|
109
|
+
end
|
110
|
+
|
111
|
+
# @return [SourceMap]
|
112
|
+
def load_string code, filename = nil
|
113
|
+
source = Solargraph::Source.load_string(code, filename)
|
114
|
+
SourceMap.map(source)
|
115
|
+
end
|
116
|
+
|
117
|
+
# @param source [Source]
|
118
|
+
# @return [SourceMap]
|
119
|
+
def map source
|
120
|
+
result = SourceMap::Mapper.map(source)
|
121
|
+
new(source, *result)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
private
|
126
|
+
|
127
|
+
def _locate_pin line, character, *kinds
|
128
|
+
position = Position.new(line, character)
|
129
|
+
found = nil
|
130
|
+
pins.each do |pin|
|
131
|
+
found = pin if (kinds.empty? || kinds.include?(pin.kind)) && pin.location.range.contain?(position)
|
132
|
+
break if pin.location.range.start.line > line
|
133
|
+
end
|
134
|
+
# @todo Assuming the root pin is always valid
|
135
|
+
found || pins.first
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|