lib/rubocop/cop/minitest/empty_line_before_assertion_methods.rb



# frozen_string_literal: true

module RuboCop
  module Cop
    module Minitest
      # Enforces empty line before assertion methods because it separates assertion phase.
      #
      # @example
      #
      #   # bad
      #   do_something
      #   assert_equal(expected, actual)
      #
      #   # good
      #   do_something
      #
      #   assert_equal(expected, actual)
      #
      class EmptyLineBeforeAssertionMethods < Base
        include MinitestExplorationHelpers
        extend AutoCorrector

        MSG = 'Add empty line before assertion.'

        def on_send(node)
          return unless assertion_method?(node)
          return unless (previous_line_node = node.left_sibling)
          return if accept_previous_line?(previous_line_node, node)

          previous_line_node = previous_line_node.arguments.last if use_heredoc_argument?(previous_line_node)
          return unless no_empty_line?(previous_line_node, node)

          register_offense(node, previous_line_node)
        end

        private

        def accept_previous_line?(previous_line_node, node)
          return true if previous_line_node.args_type? || node.parent.basic_conditional?

          previous_line_node.send_type? && assertion_method?(previous_line_node)
        end

        def use_heredoc_argument?(node)
          node.respond_to?(:arguments) && heredoc?(node.arguments.last)
        end

        def heredoc?(last_argument)
          last_argument.respond_to?(:heredoc?) && last_argument.heredoc?
        end

        def no_empty_line?(previous_line_node, node)
          previous_line = if heredoc?(previous_line_node)
                            previous_line_node.loc.heredoc_end.line
                          else
                            previous_line_node.loc.last_line
                          end

          previous_line + 1 == node.loc.line
        end

        def register_offense(node, previous_line_node)
          add_offense(node) do |corrector|
            range = if heredoc?(previous_line_node)
                      previous_line_node.loc.heredoc_end
                    else
                      previous_line_node
                    end

            corrector.insert_after(range, "\n")
          end
        end
      end
    end
  end
end