lib/rubocop/cop/style/space_around_operators.rb



# encoding: utf-8

module RuboCop
  module Cop
    module Style
      # Checks that operators have space around them, except for **
      # which should not have surrounding space.
      class SpaceAroundOperators < Cop
        TYPES = %w(and or class) + ASGN_NODES

        TYPES.each { |t| define_method(:"on_#{t}") { |node| check(node) } }

        def on_pair(node)
          check(node) if node.loc.operator.is?('=>')
        end

        def on_if(node)
          return unless node.loc.respond_to?(:question)

          check_operator(node.loc.question)
          check_operator(node.loc.colon)
        end

        def on_resbody(node)
          check_operator(node.loc.assoc) if node.loc.assoc
        end

        def on_send(node)
          if node.loc.operator
            check(node)
          elsif !unary_operation?(node) && !called_with_dot?(node)
            op = node.loc.selector
            check_operator(op) if operator?(op)
          end
        end

        private

        def operator?(range)
          range.source !~ /^\[|\w/
        end

        def unary_operation?(node)
          whole, selector = node.loc.expression, node.loc.selector
          return unless selector
          operator?(selector) && whole.begin_pos == selector.begin_pos
        end

        def called_with_dot?(node)
          node.loc.dot
        end

        def check(node)
          check_operator(node.loc.operator) if node.loc.operator
        end

        def check_operator(op)
          with_space = range_with_surrounding_space(op)
          if op.is?('**')
            unless with_space.is?('**')
              add_offense(with_space, op, 'Space around operator ** detected.')
            end
          elsif with_space.source !~ /^\s.*\s$/
            add_offense(with_space, op,
                        'Surrounding space missing for operator' \
                        " '#{op.source}'.")
          end
        end

        def autocorrect(range)
          @corrections << lambda do |corrector|
            case range.source
            when /\*\*/
              corrector.replace(range, '**')
            else
              corrector.replace(range, " #{range.source.strip} ")
            end
          end
        end
      end
    end
  end
end