Class: RuboCop::RSpec::ExpectOffense::AnnotatedSource
Relationships & Source Files | |
Inherits: | Object |
Defined in: | lib/rubocop/rspec/expect_offense.rb |
Overview
Parsed representation of code annotated with the ^ Message
style
Constant Summary
-
ABBREV =
# File 'lib/rubocop/rspec/expect_offense.rb', line 225"[...]\n"
-
ANNOTATION_PATTERN =
# File 'lib/rubocop/rspec/expect_offense.rb', line 224/\A\s*(\^+|\^{}) ?/.freeze
Class Method Summary
- .new(lines, annotations) ⇒ AnnotatedSource constructor
-
.parse(annotated_source) ⇒ AnnotatedSource
Separates annotation lines from source lines.
Instance Method Summary
- #==(other)
-
#inspect
Alias for #to_s.
-
#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
.new(lines, annotations) ⇒ AnnotatedSource
annotations are sorted so that reconstructing the annotation text via #to_s is deterministic
# File 'lib/rubocop/rspec/expect_offense.rb', line 255
def initialize(lines, annotations) @lines = lines.freeze @annotations = annotations.sort.freeze end
Class Method Details
.parse(annotated_source) ⇒ AnnotatedSource
Separates annotation lines from source lines. Tracks the real source line number that each annotation corresponds to.
# File 'lib/rubocop/rspec/expect_offense.rb', line 233
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
#==(other)
[ GitHub ]# File 'lib/rubocop/rspec/expect_offense.rb', line 260
def ==(other) other.is_a?(self.class) && other.lines == lines && match_annotations?(other) end
#inspect
Alias for #to_s.
# File 'lib/rubocop/rspec/expect_offense.rb', line 311
alias inspect to_s
#match_annotations?(other) ⇒ Boolean
Dirty hack: expectations with […] are rewritten when they match This way the diff is clean.
# File 'lib/rubocop/rspec/expect_offense.rb', line 266
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
#plain_source ⇒ String
Return the plain source code without annotations
# File 'lib/rubocop/rspec/expect_offense.rb', line 316
def plain_source lines.join end
#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.
# File 'lib/rubocop/rspec/expect_offense.rb', line 302
def to_s reconstructed = lines.dup annotations.reverse_each do |line_number, annotation| reconstructed.insert(line_number, annotation) end reconstructed.join end
#with_offense_annotations(offenses) ⇒ self
Annotate the source code with the RuboCop offenses provided
# File 'lib/rubocop/rspec/expect_offense.rb', line 325
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