Class: RuboCop::RSpec::ExpectOffense::AnnotatedSource
- Inherits:
-
Object
- Object
- RuboCop::RSpec::ExpectOffense::AnnotatedSource
- Defined in:
- lib/rubocop/rspec/expect_offense.rb
Overview
Parsed representation of code annotated with the ‘^^^ Message` style
Constant Summary collapse
- ANNOTATION_PATTERN =
Ignore escaped carets, don’t treat as annotations
/\A\s*((?<!\\)\^+|\^{}) ?/.freeze
- ABBREV =
"[...]\n"
Class Method Summary collapse
-
.parse(annotated_source) ⇒ AnnotatedSource
Separates annotation lines from source lines.
Instance Method Summary collapse
- #==(other) ⇒ Object
-
#initialize(lines, annotations) ⇒ AnnotatedSource
constructor
A new instance of AnnotatedSource.
-
#match_annotations?(other) ⇒ Boolean
Dirty hack: expectations with […] are rewritten when they match This way the diff is clean.
-
#plain_source ⇒ String
Return the plain source code without annotations.
-
#to_s ⇒ String
(also: #inspect)
Construct annotated source string (like what we parse).
-
#with_offense_annotations(offenses) ⇒ self
Annotate the source code with the RuboCop offenses provided.
Constructor Details
permalink #initialize(lines, annotations) ⇒ AnnotatedSource
annotations are sorted so that reconstructing the annotation text via #to_s is deterministic
Returns a new instance of AnnotatedSource.
259 260 261 262 |
# File 'lib/rubocop/rspec/expect_offense.rb', line 259 def initialize(lines, annotations) @lines = lines.freeze @annotations = annotations.sort.freeze end |
Class Method Details
permalink .parse(annotated_source) ⇒ AnnotatedSource
Separates annotation lines from source lines. Tracks the real source line number that each annotation corresponds to.
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
# File 'lib/rubocop/rspec/expect_offense.rb', line 237 def self.parse(annotated_source) source = [] annotations = [] annotated_source.each_line do |source_line| if ANNOTATION_PATTERN.match?(source_line) annotations << [source.size, source_line] else source << source_line end end annotations.each { |a| a[0] = 1 } if source.empty? new(source, annotations) end |
Instance Method Details
permalink #==(other) ⇒ Object
[View source]
264 265 266 |
# File 'lib/rubocop/rspec/expect_offense.rb', line 264 def ==(other) other.is_a?(self.class) && other.lines == lines && match_annotations?(other) end |
permalink #match_annotations?(other) ⇒ Boolean
Dirty hack: expectations with […] are rewritten when they match This way the diff is clean.
270 271 272 273 274 275 276 277 278 279 280 281 |
# File 'lib/rubocop/rspec/expect_offense.rb', line 270 def match_annotations?(other) annotations.zip(other.annotations) do |(_actual_line, actual_annotation), (_expected_line, expected_annotation)| if expected_annotation&.end_with?(ABBREV) && actual_annotation.start_with?(expected_annotation[0...-ABBREV.length]) expected_annotation.replace(actual_annotation) end end annotations == other.annotations end |
permalink #plain_source ⇒ String
Return the plain source code without annotations
320 321 322 |
# File 'lib/rubocop/rspec/expect_offense.rb', line 320 def plain_source lines.join end |
permalink #to_s ⇒ String Also known as: inspect
Construct annotated source string (like what we parse)
Reconstruct a deterministic annotated source string. This is useful for eliminating semantically irrelevant annotation ordering differences.
306 307 308 309 310 311 312 313 314 |
# File 'lib/rubocop/rspec/expect_offense.rb', line 306 def to_s reconstructed = lines.dup annotations.reverse_each do |line_number, annotation| reconstructed.insert(line_number, annotation) end reconstructed.join end |
permalink #with_offense_annotations(offenses) ⇒ self
Annotate the source code with the RuboCop offenses provided
329 330 331 332 333 334 335 336 337 338 339 340 |
# File 'lib/rubocop/rspec/expect_offense.rb', line 329 def with_offense_annotations(offenses) offense_annotations = offenses.map do |offense| indent = ' ' * offense.column carets = '^' * offense.column_length carets = '^{}' if offense.column_length.zero? [offense.line, "#{indent}#{carets} #{offense.}\n"] end self.class.new(lines, offense_annotations) end |