class RuboCop::Cop::Layout::SpaceAroundOperators
Checks that operators have space around them, except for ** which should or shouldn’t have surrounding space depending on configuration. It allows vertical alignment consisting of one or more whitespace around operators.
This cop has ‘AllowForAlignment` option. When `true`, allows most uses of extra spacing if the intent is to align with an operator on the previous or next line, not counting empty lines or comment lines.
@example
# bad total = 3*4 "apple"+"juice" my_number = 38/4 # good total = 3 * 4 "apple" + "juice" my_number = 38 / 4
@example AllowForAlignment: true (default)
# good { 1 => 2, 11 => 3 }
@example AllowForAlignment: false
# bad { 1 => 2, 11 => 3 }
@example EnforcedStyleForExponentOperator: no_space (default)
# bad a ** b # good a**b
@example EnforcedStyleForExponentOperator: space
# bad a**b # good a ** b
@example EnforcedStyleForRationalLiterals: no_space (default)
# bad 1 / 48r # good 1/48r
@example EnforcedStyleForRationalLiterals: space
# bad 1/48r # good 1 / 48r
Constants
- EXCESSIVE_SPACE
- IRREGULAR_METHODS
Public Class Methods
autocorrect_incompatible_with()
click to toggle source
# File lib/rubocop/cop/layout/space_around_operators.rb, line 76 def self.autocorrect_incompatible_with [Style::SelfAssignment] end
Public Instance Methods
on_assignment(node)
click to toggle source
# File lib/rubocop/cop/layout/space_around_operators.rb, line 117 def on_assignment(node) _, rhs, = *node return unless rhs check_operator(:assignment, node.loc.operator, rhs) end
on_binary(node)
click to toggle source
# File lib/rubocop/cop/layout/space_around_operators.rb, line 133 def on_binary(node) _, rhs, = *node return unless rhs check_operator(:binary, node.loc.operator, rhs) end
on_casgn(node)
click to toggle source
# File lib/rubocop/cop/layout/space_around_operators.rb, line 125 def on_casgn(node) _, _, right, = *node return unless right check_operator(:assignment, node.loc.operator, right) end
on_if(node)
click to toggle source
# File lib/rubocop/cop/layout/space_around_operators.rb, line 92 def on_if(node) return unless node.ternary? check_operator(:if, node.loc.question, node.if_branch) check_operator(:if, node.loc.colon, node.else_branch) end
on_match_pattern(node)
click to toggle source
# File lib/rubocop/cop/layout/space_around_operators.rb, line 149 def on_match_pattern(node) return if target_ruby_version < 3.0 check_operator(:match_pattern, node.loc.operator, node) end
on_pair(node)
click to toggle source
# File lib/rubocop/cop/layout/space_around_operators.rb, line 84 def on_pair(node) return unless node.hash_rocket? return if hash_table_style? && !node.parent.pairs_on_same_line? check_operator(:pair, node.loc.operator, node) end
on_resbody(node)
click to toggle source
# File lib/rubocop/cop/layout/space_around_operators.rb, line 99 def on_resbody(node) return unless node.loc.assoc _, variable, = *node check_operator(:resbody, node.loc.assoc, variable) end
on_sclass(node)
click to toggle source
# File lib/rubocop/cop/layout/space_around_operators.rb, line 80 def on_sclass(node) check_operator(:sclass, node.loc.operator, node) end
on_send(node)
click to toggle source
# File lib/rubocop/cop/layout/space_around_operators.rb, line 107 def on_send(node) return if rational_literal?(node) if node.setter_method? on_special_asgn(node) elsif regular_operator?(node) check_operator(:send, node.loc.selector, node.first_argument) end end
on_special_asgn(node)
click to toggle source
# File lib/rubocop/cop/layout/space_around_operators.rb, line 141 def on_special_asgn(node) _, _, right, = *node return unless right check_operator(:special_asgn, node.loc.operator, right) end
Also aliased as: on_op_asgn
Private Instance Methods
align_hash_cop_config()
click to toggle source
# File lib/rubocop/cop/layout/space_around_operators.rb, line 259 def align_hash_cop_config config.for_cop('Layout/HashAlignment') end
autocorrect(corrector, range, right_operand)
click to toggle source
# File lib/rubocop/cop/layout/space_around_operators.rb, line 198 def autocorrect(corrector, range, right_operand) range_source = range.source if range_source.include?('**') && !space_around_exponent_operator? corrector.replace(range, '**') elsif range_source.include?('/') && !space_around_slash_operator?(right_operand) corrector.replace(range, '/') elsif range_source.end_with?("\n") corrector.replace(range, " #{range_source.strip}\n") else enclose_operator_with_space(corrector, range) end end
check_operator(type, operator, right_operand)
click to toggle source
# File lib/rubocop/cop/layout/space_around_operators.rb, line 179 def check_operator(type, operator, right_operand) with_space = range_with_surrounding_space(operator) return if with_space.source.start_with?("\n") comment = processed_source.comment_at_line(operator.line) return if comment && with_space.last_column == comment.loc.column offense(type, operator, with_space, right_operand) do |msg| add_offense(operator, message: msg) do |corrector| autocorrect(corrector, with_space, right_operand) end end end
enclose_operator_with_space(corrector, range)
click to toggle source
# File lib/rubocop/cop/layout/space_around_operators.rb, line 212 def enclose_operator_with_space(corrector, range) operator = range.source # If `ForceEqualSignAlignment` is true, `Layout/ExtraSpacing` cop # inserts spaces before operator. If `Layout/SpaceAroundOperators` cop # inserts a space, it collides and raises the infinite loop error. if force_equal_sign_alignment? && !operator.end_with?(' ') corrector.insert_after(range, ' ') else corrector.replace(range, " #{operator.strip} ") end end
excess_leading_space?(type, operator, with_space)
click to toggle source
# File lib/rubocop/cop/layout/space_around_operators.rb, line 239 def excess_leading_space?(type, operator, with_space) return false unless allow_for_alignment? return false unless with_space.source.start_with?(EXCESSIVE_SPACE) return !aligned_with_operator?(operator) unless type == :assignment token = Token.new(operator, nil, operator.source) align_preceding = aligned_with_preceding_assignment(token) return false if align_preceding == :yes || aligned_with_subsequent_assignment(token) == :none aligned_with_subsequent_assignment(token) != :yes end
excess_trailing_space?(right_operand, with_space)
click to toggle source
# File lib/rubocop/cop/layout/space_around_operators.rb, line 254 def excess_trailing_space?(right_operand, with_space) with_space.source.end_with?(EXCESSIVE_SPACE) && (!allow_for_alignment? || !aligned_with_something?(right_operand)) end
force_equal_sign_alignment?()
click to toggle source
# File lib/rubocop/cop/layout/space_around_operators.rb, line 277 def force_equal_sign_alignment? config.for_cop('Layout/ExtraSpacing')['ForceEqualSignAlignment'] end
hash_table_style?()
click to toggle source
# File lib/rubocop/cop/layout/space_around_operators.rb, line 263 def hash_table_style? align_hash_cop_config && align_hash_cop_config['EnforcedHashRocketStyle'] == 'table' end
offense(type, operator, with_space, right_operand) { |msg| ... }
click to toggle source
# File lib/rubocop/cop/layout/space_around_operators.rb, line 193 def offense(type, operator, with_space, right_operand) msg = offense_message(type, operator, with_space, right_operand) yield msg if msg end
offense_message(type, operator, with_space, right_operand)
click to toggle source
# File lib/rubocop/cop/layout/space_around_operators.rb, line 225 def offense_message(type, operator, with_space, right_operand) if should_not_have_surrounding_space?(operator, right_operand) return if with_space.is?(operator.source) "Space around operator `#{operator.source}` detected." elsif !/^\s.*\s$/.match?(with_space.source) "Surrounding space missing for operator `#{operator.source}`." elsif excess_leading_space?(type, operator, with_space) || excess_trailing_space?(right_operand.source_range, with_space) "Operator `#{operator.source}` should be surrounded " \ 'by a single space.' end end
operator_with_regular_syntax?(send_node)
click to toggle source
# File lib/rubocop/cop/layout/space_around_operators.rb, line 175 def operator_with_regular_syntax?(send_node) send_node.operator_method? && !IRREGULAR_METHODS.include?(send_node.method_name) end
regular_operator?(send_node)
click to toggle source
# File lib/rubocop/cop/layout/space_around_operators.rb, line 169 def regular_operator?(send_node) return false if send_node.unary_operation? || send_node.dot? || send_node.double_colon? operator_with_regular_syntax?(send_node) end
should_not_have_surrounding_space?(operator, right_operand)
click to toggle source
# File lib/rubocop/cop/layout/space_around_operators.rb, line 281 def should_not_have_surrounding_space?(operator, right_operand) if operator.is?('**') !space_around_exponent_operator? elsif operator.is?('/') !space_around_slash_operator?(right_operand) else false end end
space_around_exponent_operator?()
click to toggle source
# File lib/rubocop/cop/layout/space_around_operators.rb, line 267 def space_around_exponent_operator? cop_config['EnforcedStyleForExponentOperator'] == 'space' end
space_around_slash_operator?(right_operand)
click to toggle source
# File lib/rubocop/cop/layout/space_around_operators.rb, line 271 def space_around_slash_operator?(right_operand) return true unless right_operand.rational_type? cop_config['EnforcedStyleForRationalLiterals'] == 'space' end