Class: Solargraph::Source
- Inherits:
-
Object
- Object
- Solargraph::Source
show all
- Includes:
- EncodingFixes
- Defined in:
- lib/solargraph/source.rb,
lib/solargraph/source/chain.rb,
lib/solargraph/source/change.rb,
lib/solargraph/source/cursor.rb,
lib/solargraph/source/updater.rb,
lib/solargraph/source/chain/or.rb,
lib/solargraph/source/chain/call.rb,
lib/solargraph/source/chain/hash.rb,
lib/solargraph/source/chain/head.rb,
lib/solargraph/source/chain/link.rb,
lib/solargraph/source/chain/q_call.rb,
lib/solargraph/source/chain/literal.rb,
lib/solargraph/source/chain/z_super.rb,
lib/solargraph/source/chain/constant.rb,
lib/solargraph/source/chain/variable.rb,
lib/solargraph/source/encoding_fixes.rb,
lib/solargraph/source/source_chainer.rb,
lib/solargraph/source/chain/block_variable.rb,
lib/solargraph/source/chain/class_variable.rb,
lib/solargraph/source/chain/global_variable.rb,
lib/solargraph/source/chain/instance_variable.rb
Overview
A Ruby file that has been parsed into an AST.
Defined Under Namespace
Modules: EncodingFixes
Classes: Chain, Change, Cursor, SourceChainer, Updater
Constant Summary
collapse
- FOLDING_NODE_TYPES =
if Parser.rubyvm?
%i[
CLASS SCLASS MODULE DEFN DEFS IF WHILE UNLESS ITER STR HASH ARRAY LIST
].freeze
else
%i[
class sclass module def defs if str dstr array while unless kwbegin hash block
].freeze
end
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
-
#associated_comments ⇒ Hash{Integer => Array<Parser::Source::Comment>}
Get a hash of comments grouped by the line numbers of the associated code.
-
#at(range) ⇒ String
-
#code_for(node) ⇒ String
-
#comment_at?(position) ⇒ Boolean
-
#comments_for(node) ⇒ String
-
#cursor_at(position) ⇒ Source::Cursor
-
#finish_synchronize ⇒ Source
Finish synchronizing a source that was updated via #start_synchronize.
-
#folding_ranges ⇒ Array<Range>
Get an array of ranges that can be folded, e.g., the range of a class definition or an if condition.
-
#from_to(l1, c1, l2, c2) ⇒ String
-
#initialize(code, filename = nil, version = 0) ⇒ Source
constructor
A new instance of Source.
-
#location ⇒ Location
A location representing the file in its entirety.
-
#node_at(line, column) ⇒ AST::Node
Get the nearest node that contains the specified index.
-
#parsed? ⇒ Boolean
-
#references(name) ⇒ Array<Location>
-
#repaired? ⇒ Boolean
-
#start_synchronize(updater) ⇒ Source
Start synchronizing the source.
-
#string_at?(position) ⇒ Boolean
-
#string_ranges ⇒ Object
-
#synchronize(updater) ⇒ Source
Synchronize the Source with an update.
-
#synchronized? ⇒ Boolean
-
#tree_at(line, column) ⇒ Array<AST::Node>
Get an array of nodes containing the specified index, starting with the nearest node and ending with the root.
normalize
Constructor Details
#initialize(code, filename = nil, version = 0) ⇒ Source
Returns a new instance of Source.
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
# File 'lib/solargraph/source.rb', line 38
def initialize code, filename = nil, version = 0
@code = normalize(code)
@repaired = code
@filename = filename
@version = version
@domains = []
begin
@node, @comments = Solargraph::Parser.(@code, filename)
@parsed = true
rescue Parser::SyntaxError, EncodingError => e
@node = nil
@comments = {}
@parsed = false
ensure
@code.freeze
end
end
|
Instance Attribute Details
#code ⇒ String
23
24
25
|
# File 'lib/solargraph/source.rb', line 23
def code
@code
end
|
29
30
31
|
# File 'lib/solargraph/source.rb', line 29
def
@comments
end
|
#error_ranges ⇒ Array<Range>
238
239
240
|
# File 'lib/solargraph/source.rb', line 238
def error_ranges
@error_ranges ||= []
end
|
#filename ⇒ String
20
21
22
|
# File 'lib/solargraph/source.rb', line 20
def filename
@filename
end
|
#node ⇒ Parser::AST::Node
26
27
28
|
# File 'lib/solargraph/source.rb', line 26
def node
@node
end
|
#version ⇒ Integer
33
34
35
|
# File 'lib/solargraph/source.rb', line 33
def version
@version
end
|
Class Method Details
498
499
500
501
502
503
|
# File 'lib/solargraph/source.rb', line 498
def load filename
file = File.open(filename)
code = file.read
file.close
Source.load_string(code, filename)
end
|
.load_string(code, filename = nil, version = 0) ⇒ Solargraph::Source
509
510
511
|
# File 'lib/solargraph/source.rb', line 509
def load_string code, filename = nil, version = 0
Source.new code, filename, version
end
|
.parse_docstring(comments) ⇒ YARD::DocstringParser
515
516
517
518
519
|
# File 'lib/solargraph/source.rb', line 515
def parse_docstring
YARD::Docstring.parser.parse(, YARD::CodeObjects::Base.new(:root, 'stub'))
end
|
Instance Method Details
Get a hash of comments grouped by the line numbers of the associated code.
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
|
# File 'lib/solargraph/source.rb', line 305
def
@associated_comments ||= begin
result = {}
buffer = String.new('')
last = nil
@comments.each_pair do |num, snip|
if !last || num == last + 1
buffer.concat "#{snip.text}\n"
else
result[first_not_empty_from(last + 1)] = buffer.clone
buffer.replace "#{snip.text}\n"
end
last = num
end
result[first_not_empty_from(last + 1)] = buffer unless buffer.empty? || last.nil?
result
end
end
|
#at(range) ⇒ String
58
59
60
|
# File 'lib/solargraph/source.rb', line 58
def at range
from_to range.start.line, range.start.character, range.ending.line, range.ending.character
end
|
222
223
224
225
226
227
228
229
|
# File 'lib/solargraph/source.rb', line 222
def position
.each do |range|
return true if range.include?(position) ||
(range.ending.line == position.line && range.ending.column < position.column)
break if range.ending.line > position.line
end
false
end
|
254
255
256
257
258
259
260
|
# File 'lib/solargraph/source.rb', line 254
def node
rng = Range.from_node(node)
[rng.start.line] ||= begin
buff = [rng.start.line]
buff ? (buff) : nil
end
end
|
167
168
169
|
# File 'lib/solargraph/source.rb', line 167
def cursor_at position
Cursor.new(self, position)
end
|
#finish_synchronize ⇒ Source
Finish synchronizing a source that was updated via #start_synchronize. This method returns self if the source is already synchronized. Otherwise it parses the AST and returns a new synchronized Source.
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
# File 'lib/solargraph/source.rb', line 125
def finish_synchronize
return self if synchronized?
synced = Source.new(@code, filename)
if synced.parsed?
synced.version = version
return synced
end
synced = Source.new(@repaired, filename)
synced.error_ranges.concat (error_ranges + last_updater.changes.map(&:range))
synced.code = @code
synced.synchronized = true
synced.version = version
synced
end
|
#folding_ranges ⇒ Array<Range>
Get an array of ranges that can be folded, e.g., the range of a class definition or an if condition.
See FOLDING_NODE_TYPES for the list of node types that can be folded.
288
289
290
291
292
293
294
295
|
# File 'lib/solargraph/source.rb', line 288
def folding_ranges
@folding_ranges ||= begin
result = []
inner_folding_ranges node, result
result.concat
result
end
end
|
#from_to(l1, c1, l2, c2) ⇒ String
A location representing the file in its entirety.
#node_at(line, column) ⇒ AST::Node
Get the nearest node that contains the specified index.
78
79
80
|
# File 'lib/solargraph/source.rb', line 78
def node_at(line, column)
tree_at(line, column).first
end
|
#parsed? ⇒ Boolean
172
173
174
|
# File 'lib/solargraph/source.rb', line 172
def parsed?
@parsed
end
|
#references(name) ⇒ Array<Location>
233
234
235
|
# File 'lib/solargraph/source.rb', line 233
def references name
Parser.references self, name
end
|
#repaired? ⇒ Boolean
176
177
178
|
# File 'lib/solargraph/source.rb', line 176
def repaired?
@is_repaired ||= (@code != @repaired)
end
|
#start_synchronize(updater) ⇒ Source
Start synchronizing the source. This method updates the code without parsing a new AST. The resulting Source object will be marked not synchronized (#synchronized? == false).
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
# File 'lib/solargraph/source.rb', line 102
def start_synchronize updater
raise 'Invalid synchronization' unless updater.filename == filename
real_code = updater.write(@code)
src = Source.allocate
src.filename = filename
src.code = real_code
src.version = updater.version
src.parsed = parsed?
src.repaired = updater.repair(@repaired)
src.synchronized = false
src.node = @node
src. = @comments
src.error_ranges = error_ranges
src.last_updater = updater
return src.finish_synchronize unless real_code.lines.length == @code.lines.length
src
end
|
#string_at?(position) ⇒ Boolean
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
|
# File 'lib/solargraph/source.rb', line 182
def string_at? position
if Parser.rubyvm?
string_ranges.each do |range|
if synchronized?
return true if range.include?(position) || range.ending == position
else
return true if last_updater && last_updater.changes.one? && range.contain?(last_updater.changes.first.range.start)
end
end
false
else
return false if Position.to_offset(code, position) >= code.length
string_nodes.each do |node|
range = Range.from_node(node)
next if range.ending.line < position.line
break if range.ending.line > position.line
return true if node.type == :str && range.include?(position) && range.start != position
return true if [:STR, :str].include?(node.type) && range.include?(position) && range.start != position
if node.type == :dstr
inner = node_at(position.line, position.column)
next if inner.nil?
inner_range = Range.from_node(inner)
next unless range.include?(inner_range.ending)
return true if inner.type == :str
inner_code = at(Solargraph::Range.new(inner_range.start, position))
return true if (inner.type == :dstr && inner_range.ending.character <= position.character) && !inner_code.end_with?('}') ||
(inner.type != :dstr && inner_range.ending.line == position.line && position.character <= inner_range.ending.character && inner_code.end_with?('}'))
end
break if range.ending.line > position.line
end
false
end
end
|
#string_ranges ⇒ Object
216
217
218
|
# File 'lib/solargraph/source.rb', line 216
def string_ranges
@string_ranges ||= Parser.string_ranges(node)
end
|
#synchronize(updater) ⇒ Source
Synchronize the Source with an update. This method applies changes to the code, parses the new code’s AST, and returns the resulting Source object.
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
|
# File 'lib/solargraph/source.rb', line 145
def synchronize updater
raise 'Invalid synchronization' unless updater.filename == filename
real_code = updater.write(@code)
if real_code == @code
@version = updater.version
return self
end
synced = Source.new(real_code, filename)
if synced.parsed?
synced.version = updater.version
return synced
end
incr_code = updater.repair(@repaired)
synced = Source.new(incr_code, filename)
synced.error_ranges.concat (error_ranges + updater.changes.map(&:range))
synced.code = real_code
synced.version = updater.version
synced
end
|
#synchronized? ⇒ Boolean
297
298
299
300
|
# File 'lib/solargraph/source.rb', line 297
def synchronized?
@synchronized = true if @synchronized.nil?
@synchronized
end
|
#tree_at(line, column) ⇒ Array<AST::Node>
Get an array of nodes containing the specified index, starting with the nearest node and ending with the root.
88
89
90
91
92
93
94
|
# File 'lib/solargraph/source.rb', line 88
def tree_at(line, column)
position = Position.new(line, column)
stack = []
inner_tree_at @node, position, stack
stack
end
|