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/if.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/array.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_symbol.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 => String}
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
-
#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
-
#string_at?(position) ⇒ Boolean
-
#string_ranges ⇒ ::Array<Range>
-
#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.
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
# File 'lib/solargraph/source.rb', line 37
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
22
23
24
|
# File 'lib/solargraph/source.rb', line 22
def code
@code
end
|
28
29
30
|
# File 'lib/solargraph/source.rb', line 28
def
@comments
end
|
#error_ranges ⇒ Array<Range>
194
195
196
|
# File 'lib/solargraph/source.rb', line 194
def error_ranges
@error_ranges ||= []
end
|
#filename ⇒ String
19
20
21
|
# File 'lib/solargraph/source.rb', line 19
def filename
@filename
end
|
#node ⇒ Parser::AST::Node
25
26
27
|
# File 'lib/solargraph/source.rb', line 25
def node
@node
end
|
#version ⇒ Integer
32
33
34
|
# File 'lib/solargraph/source.rb', line 32
def version
@version
end
|
Class Method Details
449
450
451
452
453
454
|
# File 'lib/solargraph/source.rb', line 449
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
460
461
462
|
# File 'lib/solargraph/source.rb', line 460
def load_string code, filename = nil, version = 0
Source.new code, filename, version
end
|
.parse_docstring(comments) ⇒ YARD::DocstringParser
466
467
468
469
470
471
472
473
474
|
# File 'lib/solargraph/source.rb', line 466
def parse_docstring
YARD::Docstring.parser.parse(, YARD::CodeObjects::Base.new(:root, 'stub'))
rescue StandardError => e
Solargraph.logger.info "YARD failed to parse docstring: [#{e.class}] #{e.message}"
Solargraph.logger.debug "Unparsed comment: #{}"
YARD::Docstring.parser
end
|
Instance Method Details
Get a hash of comments grouped by the line numbers of the associated code.
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
|
# File 'lib/solargraph/source.rb', line 261
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
57
58
59
|
# File 'lib/solargraph/source.rb', line 57
def at range
from_to range.start.line, range.start.character, range.ending.line, range.ending.character
end
|
178
179
180
181
182
183
184
185
|
# File 'lib/solargraph/source.rb', line 178
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
|
210
211
212
213
214
215
216
|
# File 'lib/solargraph/source.rb', line 210
def node
rng = Range.from_node(node)
[rng.start.line] ||= begin
buff = [rng.start.line]
buff ? (buff) : nil
end
end
|
122
123
124
|
# File 'lib/solargraph/source.rb', line 122
def cursor_at position
Cursor.new(self, position)
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.
244
245
246
247
248
249
250
251
|
# File 'lib/solargraph/source.rb', line 244
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.
77
78
79
|
# File 'lib/solargraph/source.rb', line 77
def node_at(line, column)
tree_at(line, column).first
end
|
#parsed? ⇒ Boolean
127
128
129
|
# File 'lib/solargraph/source.rb', line 127
def parsed?
@parsed
end
|
#references(name) ⇒ Array<Location>
189
190
191
|
# File 'lib/solargraph/source.rb', line 189
def references name
Parser.references self, name
end
|
#repaired? ⇒ Boolean
131
132
133
|
# File 'lib/solargraph/source.rb', line 131
def repaired?
@is_repaired ||= (@code != @repaired)
end
|
#string_at?(position) ⇒ Boolean
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
# File 'lib/solargraph/source.rb', line 137
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 ⇒ ::Array<Range>
172
173
174
|
# File 'lib/solargraph/source.rb', line 172
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.
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
# File 'lib/solargraph/source.rb', line 100
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
253
254
255
256
|
# File 'lib/solargraph/source.rb', line 253
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.
87
88
89
90
91
92
93
|
# File 'lib/solargraph/source.rb', line 87
def tree_at(line, column)
position = Position.new(line, column)
stack = []
inner_tree_at @node, position, stack
stack
end
|