Class: Shirobai::Cop::RSpec::RepeatedDescription

Inherits:
RuboCop::Cop::Base
  • Object
show all
Includes:
BundleEligible
Defined in:
lib/shirobai/cop/rspec/repeated_description.rb

Overview

Drop-in Rust reimplementation of RSpec/RepeatedDescription (rubocop-rspec 3.10.2).

Byte-level signature comparison is impossible here: stock groups examples by parser-node STRUCTURAL equality (it 'a' and it "a" are equal; two dstr doc strings with the same interpolation are equal). So the split is: Rust collects each example group's examples on the shared walk (exact stock scope semantics) and puts the example BLOCK node ranges of every group with >= 2 examples on the wire; the wrapper relocates those parser nodes, wraps them in the stock RuboCop::RSpec::Example, and runs stock's grouping VERBATIM. That gives parity by construction for the equality-sensitive part.

repeated_descriptions (non-its) groups by [metadata, doc_string] and reports each definition (the send node); repeated_its groups by [doc_string, example] and reports the whole node. Both arms keep only groups where the signature is truthy (Array#any?) and larger than one.

Constant Summary collapse

MSG =
"Don't repeat descriptions within an example group."

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.badgeObject



29
# File 'lib/shirobai/cop/rspec/repeated_description.rb', line 29

def self.badge = RuboCop::Cop::Badge.parse(cop_name)

.bundle_args(_config) ⇒ Object

Config-less (the segment's role lists cover everything).



32
33
34
# File 'lib/shirobai/cop/rspec/repeated_description.rb', line 32

def self.bundle_args(_config)
  []
end

.cop_nameObject



28
# File 'lib/shirobai/cop/rspec/repeated_description.rb', line 28

def self.cop_name = "RSpec/RepeatedDescription"

Instance Method Details

#on_new_investigationObject



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/shirobai/cop/rspec/repeated_description.rb', line 36

def on_new_investigation
  groups = resolved_groups
  return if groups.empty?

  source = bundle_eligible? ? processed_source.raw_source : processed_source.buffer.source
  off = SourceOffsets.for(source)
  located = locate_blocks(groups, off)

  groups.each do |ranges|
    examples = examples_for(ranges, off, located)
    next if examples.length < 2

    repeated_descriptions(examples).each { |description| add_offense(description) }
    repeated_its(examples).each { |its| add_offense(its) }
  end
end