[ create a new paste ] login | about

Link: http://codepad.org/XePPWUzt    [ raw code | fork ]

Ruby, pasted on Jan 6:
require 'rubocop'

module Helpers
  # Shoulda => Spec
  BLOCK_KEYWORD_MAPPINGS = { should: :it,
                             context: :describe,
                             setup: :before,
                             teardown: :after }

  MATCHERS_KEYWORDS = %w[should should_not should_eventually].map(&:to_sym)

  def node_call(node)
    _, call, *_ = node.to_a
    call
  end

  def meth_call?(node)
    h, *_ = node.to_a
    h.nil?
  end

  def node_args(node)
    _, _, *args = node.to_a
    args
  end

  def shoulda_block_node?(node)
    call = node_call(node)
    first_arg = node_args(node).first

    BLOCK_KEYWORD_MAPPINGS.keys.include?(call) &&
      node.parent.block_type? &&
      first_arg &&
      first_arg.type == :str
  end

  def shoulda_meth_node?(node)
    call = node_call(node)

    MATCHERS_KEYWORDS.include?(call) &&
      !shoulda_block_node?(node) &&
      meth_call?(node)
  end
  
  def matchy_node?(node)
    _, call = node.to_a
    
    MATCHERS_KEYWORDS.include?(call) &&
    node.parent.send_type?
  end
  
  def matchy_call(node)
    _, call = node.to_a
    
    call
  end
end

class MatchersCop < RuboCop::Cop::Cop
  include Helpers
  
  def self.cop_type
    :magic
  end

  def on_send(node)
    add_offense(node, :expression) if shoulda_meth_node?(node)
  end

  def autocorrect(node)
    lambda do |corrector|
      location = node.loc.expression
      corrector.replace(location, convert_to_it(node))
    end
  end

  def message(node)
    "Do not use `#{node_call(node)}` in a test"
  end

  private

  def convert_to_it(node)
    _, call, matcher = node.to_a
    matcher_str = Unparser.unparse(matcher)

    case call
    when :should
      "# it { assert #{matcher_str} } # REMOVE_ME"
    when :should_not
      "# it { refute #{matcher_str} } # REMOVE_ME"
    end
  end
end


Create a new paste based on this one


Comments: