class RuboCop::Cop::RSpec::ExampleWording

end
it ‘marks the task as done’ do
# good
end
it ‘works’ do
# bad
@example ‘DisallowedExamples: [’works’]‘ (default)
end
it ’does things’ do
# good
end
it ‘it does things’ do
# bad
@example
end
it ‘finds nothing’ do
# good
end
it ‘will find nothing’ do
end
it ‘should find nothing’ do
# bad
@example
case sensitive.
descriptions. Please note that this config will not be treated as
Use the DisallowedExamples setting to prevent unclear or insufficient
with CustomTransform (e.g. have => has) and IgnoredWords (e.g. only).
The autocorrect is experimental - use with care! It can be configured
@see betterspecs.org/#should<br><br>This cop will also look for insufficient examples and call them out.
This cop will correct docstrings that begin with ‘should’ and ‘it’.
Checks for common mistakes in example descriptions.

def add_wording_offense(node, message)

def add_wording_offense(node, message)
  docstring = docstring(node)
  add_offense(docstring, message: message) do |corrector|
    next if node.heredoc?
    corrector.replace(docstring, replacement_text(node))
  end
end

def custom_transform

def custom_transform
  cop_config.fetch('CustomTransform', {})
end

def docstring(node)

def docstring(node)
  expr = node.source_range
  Parser::Source::Range.new(
    expr.source_buffer,
    expr.begin_pos + 1,
    expr.end_pos - 1
  )
end

def ignored_words

def ignored_words
  cop_config.fetch('IgnoredWords', [])
end

def insufficient_docstring?(description_node)

def insufficient_docstring?(description_node)
  insufficient_examples.include?(preprocess(text(description_node)))
end

def insufficient_examples

def insufficient_examples
  examples = cop_config.fetch('DisallowedExamples', [])
  examples.map! { |example| preprocess(example) }
end

def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler

rubocop:disable InternalAffairs/NumblockHandler
def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
  it_description(node) do |description_node, message|
    if message.match?(SHOULD_PREFIX)
      add_wording_offense(description_node, MSG_SHOULD)
    elsif message.match?(WILL_PREFIX)
      add_wording_offense(description_node, MSG_WILL)
    elsif message.match?(IT_PREFIX)
      add_wording_offense(description_node, MSG_IT)
    elsif insufficient_docstring?(description_node)
      add_offense(docstring(description_node),
                  message: MSG_INSUFFICIENT_DESCRIPTION)
    end
  end
end

def preprocess(message)

def preprocess(message)
  message.strip.squeeze(' ').downcase
end

def replacement_text(node)

def replacement_text(node)
  text = text(node)
  if text.match?(SHOULD_PREFIX) || text.match?(WILL_PREFIX)
    RuboCop::RSpec::Wording.new(
      text,
      ignore:  ignored_words,
      replace: custom_transform
    ).rewrite
  else
    text.sub(IT_PREFIX, '')
  end
end

def text(node)

that is the case for \-separated multiline strings with interpolation.
Recursive processing is required to process nested dstr nodes
def text(node)
  case node.type
  when :dstr
    node.node_parts.map { |child_node| text(child_node) }.join
  when :str
    node.value
  else
    node.source
  end
end