Class: RuboCop::AST::ProcessedSource

Inherits:
Object
  • Object
show all
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

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source, ruby_version, path = nil, parser_engine: :default, prism_result: nil) ⇒ ProcessedSource

Returns a new instance of ProcessedSource.


49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/rubocop/ast/processed_source.rb', line 49

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).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

#astObject (readonly)

Returns the value of attribute ast.


41
42
43
# File 'lib/rubocop/ast/processed_source.rb', line 41

def ast
  @ast
end

#bufferObject (readonly)

Returns the value of attribute buffer.


41
42
43
# File 'lib/rubocop/ast/processed_source.rb', line 41

def buffer
  @buffer
end

#commentsObject (readonly)

Returns the value of attribute comments.


41
42
43
# File 'lib/rubocop/ast/processed_source.rb', line 41

def comments
  @comments
end

#diagnosticsObject (readonly)

Returns the value of attribute diagnostics.


41
42
43
# File 'lib/rubocop/ast/processed_source.rb', line 41

def diagnostics
  @diagnostics
end

#parser_engineObject (readonly)

Returns the value of attribute parser_engine.


41
42
43
# File 'lib/rubocop/ast/processed_source.rb', line 41

def parser_engine
  @parser_engine
end

#parser_errorObject (readonly)

Returns the value of attribute parser_error.


41
42
43
# File 'lib/rubocop/ast/processed_source.rb', line 41

def parser_error
  @parser_error
end

#pathObject (readonly)

Returns the value of attribute path.


41
42
43
# File 'lib/rubocop/ast/processed_source.rb', line 41

def path
  @path
end

#raw_sourceObject (readonly)

Returns the value of attribute raw_source.


41
42
43
# File 'lib/rubocop/ast/processed_source.rb', line 41

def raw_source
  @raw_source
end

#ruby_versionObject (readonly)

Returns the value of attribute ruby_version.


41
42
43
# File 'lib/rubocop/ast/processed_source.rb', line 41

def ruby_version
  @ruby_version
end

#tokensObject (readonly)

Returns the value of attribute tokens.


41
42
43
# File 'lib/rubocop/ast/processed_source.rb', line 41

def tokens
  @tokens
end

Class Method Details

.from_file(path, ruby_version, parser_engine: :default) ⇒ Object


44
45
46
47
# File 'lib/rubocop/ast/processed_source.rb', line 44

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

Instance Method Details

#[](*args) ⇒ Object


91
92
93
# File 'lib/rubocop/ast/processed_source.rb', line 91

def [](*args)
  lines[*args]
end

#ast_with_commentsObject


69
70
71
72
73
# File 'lib/rubocop/ast/processed_source.rb', line 69

def ast_with_comments
  return if !ast || !comments

  @ast_with_comments ||= Parser::Source::Comment.associate_by_identity(ast, comments)
end

#blank?Boolean

Returns:

  • (Boolean)

130
131
132
# File 'lib/rubocop/ast/processed_source.rb', line 130

def blank?
  ast.nil?
end

#checksumObject

Raw source checksum for tracking infinite loops.


102
103
104
# File 'lib/rubocop/ast/processed_source.rb', line 102

def checksum
  Digest::SHA1.hexdigest(@raw_source)
end

#comment_at_line(line) ⇒ Comment?

Returns the comment at that line, if any.

Returns:

  • (Comment, nil)

    the comment at that line, if any.


135
136
137
# File 'lib/rubocop/ast/processed_source.rb', line 135

def comment_at_line(line)
  comment_index[line]
end

#comments_before_line(line) ⇒ Object

Deprecated.

Use ‘each_comment_in_lines`

Should have been called ‘comments_before_or_at_line`. Doubtful it has of any valid use.


165
166
167
# File 'lib/rubocop/ast/processed_source.rb', line 165

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

Returns:

  • (Boolean)

    if any of the lines in the given ‘source_range` has a comment.


157
158
159
# File 'lib/rubocop/ast/processed_source.rb', line 157

def contains_comment?(source_range)
  each_comment_in_lines(source_range.line..source_range.last_line).any?
end

#current_line(token) ⇒ Object


179
180
181
# File 'lib/rubocop/ast/processed_source.rb', line 179

def current_line(token)
  lines[token.line - 1]
end

#each_comment(&block) ⇒ Object

Deprecated.

Use ‘comments.each`


107
108
109
# File 'lib/rubocop/ast/processed_source.rb', line 107

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`


145
146
147
148
149
150
151
152
153
# File 'lib/rubocop/ast/processed_source.rb', line 145

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

Deprecated.

Use ‘tokens.each`


117
118
119
# File 'lib/rubocop/ast/processed_source.rb', line 117

def each_token(&block)
  tokens.each(&block)
end

#file_pathObject


126
127
128
# File 'lib/rubocop/ast/processed_source.rb', line 126

def file_path
  buffer.name
end

#find_comment(&block) ⇒ Object

Deprecated.

Use ‘comment_at_line`, `each_comment_in_lines`, or `comments.find`


112
113
114
# File 'lib/rubocop/ast/processed_source.rb', line 112

def find_comment(&block)
  comments.find(&block)
end

#find_token(&block) ⇒ Object

Deprecated.

Use ‘tokens.find`


122
123
124
# File 'lib/rubocop/ast/processed_source.rb', line 122

def find_token(&block)
  tokens.find(&block)
end

#first_token_of(range_or_node) ⇒ Object


200
201
202
# File 'lib/rubocop/ast/processed_source.rb', line 200

def first_token_of(range_or_node)
  sorted_tokens[first_token_index(range_or_node)]
end

#following_line(token) ⇒ Object


183
184
185
# File 'lib/rubocop/ast/processed_source.rb', line 183

def following_line(token)
  lines[token.line]
end

#last_token_of(range_or_node) ⇒ Object


204
205
206
# File 'lib/rubocop/ast/processed_source.rb', line 204

def last_token_of(range_or_node)
  sorted_tokens[last_token_index(range_or_node)]
end

#line_indentation(line_number) ⇒ Object


187
188
189
190
191
192
# File 'lib/rubocop/ast/processed_source.rb', line 187

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.

Returns:

  • (Boolean)

    if the given line number has a comment.


140
141
142
# File 'lib/rubocop/ast/processed_source.rb', line 140

def line_with_comment?(line)
  comment_index.include?(line)
end

#linesObject

Returns the source lines, line break characters removed, excluding a possible __END__ and everything that comes after.


77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/rubocop/ast/processed_source.rb', line 77

def lines
  @lines ||= begin
    all_lines = @buffer.source_lines
    last_token_line = tokens.any? ? tokens.last.line : all_lines.size
    result = []
    all_lines.each_with_index do |line, ix|
      break if ix >= last_token_line && line == '__END__'

      result << line
    end
    result
  end
end

#preceding_line(token) ⇒ Object


175
176
177
# File 'lib/rubocop/ast/processed_source.rb', line 175

def preceding_line(token)
  lines[token.line - 2]
end

#sorted_tokensObject

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.


211
212
213
214
# File 'lib/rubocop/ast/processed_source.rb', line 211

def sorted_tokens
  # Use stable sort.
  @sorted_tokens ||= tokens.sort_by.with_index { |token, i| [token.begin_pos, i] }
end

#start_with?(string) ⇒ Boolean

Returns:

  • (Boolean)

169
170
171
172
173
# File 'lib/rubocop/ast/processed_source.rb', line 169

def start_with?(string)
  return false if self[0].nil?

  self[0].start_with?(string)
end

#tokens_within(range_or_node) ⇒ Object


194
195
196
197
198
# File 'lib/rubocop/ast/processed_source.rb', line 194

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

Returns:

  • (Boolean)

95
96
97
98
99
# File 'lib/rubocop/ast/processed_source.rb', line 95

def valid_syntax?
  return false if @parser_error

  @diagnostics.none? { |d| INVALID_LEVELS.include?(d.level) }
end