Class: RuboCop::AST::ProcessedSource
- Inherits:
-
Object
- Object
- RuboCop::AST::ProcessedSource
- Defined in:
- lib/rubocop/ast/processed_source.rb
Overview
ProcessedSource contains objects which are generated by Parser and other information such as disabled lines for cops. It also provides a convenient way to access source lines.
Constant Summary collapse
- STRING_SOURCE_NAME =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
'(string)'
Instance Attribute Summary collapse
-
#ast ⇒ Object
readonly
Returns the value of attribute ast.
-
#buffer ⇒ Object
readonly
Returns the value of attribute buffer.
-
#comments ⇒ Object
readonly
Returns the value of attribute comments.
-
#diagnostics ⇒ Object
readonly
Returns the value of attribute diagnostics.
-
#parser_engine ⇒ Object
readonly
Returns the value of attribute parser_engine.
-
#parser_error ⇒ Object
readonly
Returns the value of attribute parser_error.
-
#path ⇒ Object
readonly
Returns the value of attribute path.
-
#raw_source ⇒ Object
readonly
Returns the value of attribute raw_source.
-
#ruby_version ⇒ Object
readonly
Returns the value of attribute ruby_version.
Class Method Summary collapse
- .from_file(path, ruby_version, parser_engine: :default) ⇒ Object
-
.lazy_tokens_parser_class(base) ⇒ Object
private
Subclasses of the prism translation parsers with lazily built tokens.
Instance Method Summary collapse
- #[](*args) ⇒ Object
- #ast_with_comments ⇒ Object
- #blank? ⇒ Boolean
-
#checksum ⇒ Object
Raw source checksum for tracking infinite loops.
-
#comment_at_line(line) ⇒ Comment?
The comment at that line, if any.
-
#comments_before_line(line) ⇒ Object
deprecated
Deprecated.
Use
each_comment_in_lines -
#contains_comment?(source_range) ⇒ Boolean
(also: #commented?)
Consider using
each_comment_in_linesinstead. - #current_line(token) ⇒ Object
-
#each_comment(&block) ⇒ Object
deprecated
Deprecated.
Use
comments.each -
#each_comment_in_lines(line_range) ⇒ Object
Enumerates on the comments contained with the given
line_range. -
#each_token(&block) ⇒ Object
deprecated
Deprecated.
Use
tokens.each - #file_path ⇒ Object
-
#find_comment(&block) ⇒ Object
deprecated
Deprecated.
Use
comment_at_line,each_comment_in_lines, orcomments.find -
#find_token(&block) ⇒ Object
deprecated
Deprecated.
Use
tokens.find - #first_token_of(range_or_node) ⇒ Object
- #following_line(token) ⇒ Object
-
#initialize(source, ruby_version, path = nil, parser_engine: :default, prism_result: nil) ⇒ ProcessedSource
constructor
A new instance of ProcessedSource.
- #last_token_of(range_or_node) ⇒ Object
- #line_indentation(line_number) ⇒ Object
-
#line_with_comment?(line) ⇒ Boolean
If the given line number has a comment.
-
#lines ⇒ Object
Returns the source lines, line break characters removed, excluding a possible END and everything that comes after.
- #preceding_line(token) ⇒ Object
-
#sorted_tokens ⇒ Object
The tokens list is always sorted by token position, except for cases when heredoc is passed as a method argument.
- #start_with?(string) ⇒ Boolean
-
#tokens ⇒ Object
The tokens of the source.
- #tokens_within(range_or_node) ⇒ Object
- #valid_syntax? ⇒ Boolean
Constructor Details
#initialize(source, ruby_version, path = nil, parser_engine: :default, prism_result: nil) ⇒ ProcessedSource
Returns a new instance of ProcessedSource.
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/rubocop/ast/processed_source.rb', line 94 def initialize( source, ruby_version, path = nil, parser_engine: :default, prism_result: nil ) parser_engine = normalize_parser_engine(parser_engine, ruby_version) # Defaults source encoding to UTF-8, regardless of the encoding it has # been read with, which could be non-utf8 depending on the default # external encoding. source = (+source).force_encoding(Encoding::UTF_8) unless source.encoding == Encoding::UTF_8 @raw_source = source @path = path @diagnostics = [] @ruby_version = ruby_version @parser_engine = parser_engine @parser_error = nil parse(source, ruby_version, parser_engine, prism_result) end |
Instance Attribute Details
#ast ⇒ Object (readonly)
Returns the value of attribute ast.
79 80 81 |
# File 'lib/rubocop/ast/processed_source.rb', line 79 def ast @ast end |
#buffer ⇒ Object (readonly)
Returns the value of attribute buffer.
79 80 81 |
# File 'lib/rubocop/ast/processed_source.rb', line 79 def buffer @buffer end |
#comments ⇒ Object (readonly)
Returns the value of attribute comments.
79 80 81 |
# File 'lib/rubocop/ast/processed_source.rb', line 79 def comments @comments end |
#diagnostics ⇒ Object (readonly)
Returns the value of attribute diagnostics.
79 80 81 |
# File 'lib/rubocop/ast/processed_source.rb', line 79 def diagnostics @diagnostics end |
#parser_engine ⇒ Object (readonly)
Returns the value of attribute parser_engine.
79 80 81 |
# File 'lib/rubocop/ast/processed_source.rb', line 79 def parser_engine @parser_engine end |
#parser_error ⇒ Object (readonly)
Returns the value of attribute parser_error.
79 80 81 |
# File 'lib/rubocop/ast/processed_source.rb', line 79 def parser_error @parser_error end |
#path ⇒ Object (readonly)
Returns the value of attribute path.
79 80 81 |
# File 'lib/rubocop/ast/processed_source.rb', line 79 def path @path end |
#raw_source ⇒ Object (readonly)
Returns the value of attribute raw_source.
79 80 81 |
# File 'lib/rubocop/ast/processed_source.rb', line 79 def raw_source @raw_source end |
#ruby_version ⇒ Object (readonly)
Returns the value of attribute ruby_version.
79 80 81 |
# File 'lib/rubocop/ast/processed_source.rb', line 79 def ruby_version @ruby_version end |
Class Method Details
.from_file(path, ruby_version, parser_engine: :default) ⇒ Object
82 83 84 85 |
# File 'lib/rubocop/ast/processed_source.rb', line 82 def self.from_file(path, ruby_version, parser_engine: :default) file = File.read(path, mode: 'rb') new(file, ruby_version, path, parser_engine: parser_engine) end |
.lazy_tokens_parser_class(base) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Subclasses of the prism translation parsers with lazily built tokens.
89 90 91 92 |
# File 'lib/rubocop/ast/processed_source.rb', line 89 def self.lazy_tokens_parser_class(base) @lazy_tokens_parser_classes ||= {} @lazy_tokens_parser_classes[base] ||= Class.new(base) { include PrismLazyTokens } end |
Instance Method Details
#[](*args) ⇒ Object
135 136 137 |
# File 'lib/rubocop/ast/processed_source.rb', line 135 def [](*args) lines[*args] end |
#ast_with_comments ⇒ Object
114 115 116 117 118 |
# File 'lib/rubocop/ast/processed_source.rb', line 114 def ast_with_comments return if !ast || !comments @ast_with_comments ||= Parser::Source::Comment.associate_by_identity(ast, comments) end |
#blank? ⇒ Boolean
174 175 176 |
# File 'lib/rubocop/ast/processed_source.rb', line 174 def blank? ast.nil? end |
#checksum ⇒ Object
Raw source checksum for tracking infinite loops.
146 147 148 |
# File 'lib/rubocop/ast/processed_source.rb', line 146 def checksum @checksum ||= Digest::SHA1.hexdigest(@raw_source) end |
#comment_at_line(line) ⇒ Comment?
Returns the comment at that line, if any.
179 180 181 |
# File 'lib/rubocop/ast/processed_source.rb', line 179 def comment_at_line(line) comment_index[line] end |
#comments_before_line(line) ⇒ Object
Use each_comment_in_lines
Should have been called comments_before_or_at_line. Doubtful it has of any valid use.
209 210 211 |
# File 'lib/rubocop/ast/processed_source.rb', line 209 def comments_before_line(line) each_comment_in_lines(0..line).to_a end |
#contains_comment?(source_range) ⇒ Boolean Also known as: commented?
Consider using each_comment_in_lines instead
201 202 203 |
# File 'lib/rubocop/ast/processed_source.rb', line 201 def contains_comment?(source_range) each_comment_in_lines(source_range.line..source_range.last_line).any? end |
#current_line(token) ⇒ Object
225 226 227 |
# File 'lib/rubocop/ast/processed_source.rb', line 225 def current_line(token) lines[token.line - 1] end |
#each_comment(&block) ⇒ Object
Use comments.each
151 152 153 |
# File 'lib/rubocop/ast/processed_source.rb', line 151 def each_comment(&block) comments.each(&block) end |
#each_comment_in_lines(line_range) ⇒ Object
Enumerates on the comments contained with the given line_range
189 190 191 192 193 194 195 196 197 |
# File 'lib/rubocop/ast/processed_source.rb', line 189 def each_comment_in_lines(line_range) return to_enum(:each_comment_in_lines, line_range) unless block_given? line_range.each do |line| if (comment = comment_index[line]) yield comment end end end |
#each_token(&block) ⇒ Object
Use tokens.each
161 162 163 |
# File 'lib/rubocop/ast/processed_source.rb', line 161 def each_token(&block) tokens.each(&block) end |
#file_path ⇒ Object
170 171 172 |
# File 'lib/rubocop/ast/processed_source.rb', line 170 def file_path buffer.name end |
#find_comment(&block) ⇒ Object
Use comment_at_line, each_comment_in_lines, or comments.find
156 157 158 |
# File 'lib/rubocop/ast/processed_source.rb', line 156 def find_comment(&block) comments.find(&block) end |
#find_token(&block) ⇒ Object
Use tokens.find
166 167 168 |
# File 'lib/rubocop/ast/processed_source.rb', line 166 def find_token(&block) tokens.find(&block) end |
#first_token_of(range_or_node) ⇒ Object
259 260 261 |
# File 'lib/rubocop/ast/processed_source.rb', line 259 def first_token_of(range_or_node) sorted_tokens[first_token_index(range_or_node)] end |
#following_line(token) ⇒ Object
229 230 231 |
# File 'lib/rubocop/ast/processed_source.rb', line 229 def following_line(token) lines[token.line] end |
#last_token_of(range_or_node) ⇒ Object
263 264 265 |
# File 'lib/rubocop/ast/processed_source.rb', line 263 def last_token_of(range_or_node) sorted_tokens[last_token_index(range_or_node)] end |
#line_indentation(line_number) ⇒ Object
233 234 235 236 237 238 |
# File 'lib/rubocop/ast/processed_source.rb', line 233 def line_indentation(line_number) lines[line_number - 1] .match(/^(\s*)/)[1] .to_s .length end |
#line_with_comment?(line) ⇒ Boolean
Returns if the given line number has a comment.
184 185 186 |
# File 'lib/rubocop/ast/processed_source.rb', line 184 def line_with_comment?(line) comment_index.include?(line) end |
#lines ⇒ Object
Returns the source lines, line break characters removed, excluding a possible END and everything that comes after.
122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/rubocop/ast/processed_source.rb', line 122 def lines @lines ||= begin all_lines = @buffer.source_lines if all_lines.include?('__END__') trim_lines_after_data_marker(all_lines) else # Don't consult the tokens (which may have to be built first) when # the source can't contain a data section. all_lines.dup end end end |
#preceding_line(token) ⇒ Object
219 220 221 222 223 |
# File 'lib/rubocop/ast/processed_source.rb', line 219 def preceding_line(token) return nil if token.line < 2 lines[token.line - 2] end |
#sorted_tokens ⇒ Object
The tokens list is always sorted by token position, except for cases when heredoc is passed as a method argument. In this case tokens are interleaved by heredoc contents' tokens.
270 271 272 273 274 275 276 277 278 279 280 |
# File 'lib/rubocop/ast/processed_source.rb', line 270 def sorted_tokens # Most sources have their tokens already in order, in which case # sorting can be skipped entirely. Callers only ever read from the # returned array, so it is safe to reuse `tokens` as is. @sorted_tokens ||= if tokens_sorted? tokens else # Use stable sort. tokens.sort_by.with_index { |token, i| [token.begin_pos, i] } end end |
#start_with?(string) ⇒ Boolean
213 214 215 216 217 |
# File 'lib/rubocop/ast/processed_source.rb', line 213 def start_with?(string) return false if self[0].nil? self[0].start_with?(string) end |
#tokens ⇒ Object
The tokens of the source. With the prism engine the tokens are built lazily on first access, since their conversion is costly and not every caller needs them.
243 244 245 246 247 248 249 250 251 |
# File 'lib/rubocop/ast/processed_source.rb', line 243 def tokens @tokens ||= begin tokens = parser_tokens.map { |t| Token.from_parser_token(t) } # The parser tokens are no longer needed, and the deferred conversion # holds on to the parser instance, so release both. @parser_tokens = nil tokens end end |
#tokens_within(range_or_node) ⇒ Object
253 254 255 256 257 |
# File 'lib/rubocop/ast/processed_source.rb', line 253 def tokens_within(range_or_node) begin_index = first_token_index(range_or_node) end_index = last_token_index(range_or_node) sorted_tokens[begin_index..end_index] end |
#valid_syntax? ⇒ Boolean
139 140 141 142 143 |
# File 'lib/rubocop/ast/processed_source.rb', line 139 def valid_syntax? return false if @parser_error @diagnostics.none? { |d| INVALID_LEVELS.include?(d.level) } end |