class RuboCop::Cop::Style::MultilineOperationIndentation

end
something
b
if a +
# bad
@example
binary operations that span more than one line.
This cops checks the indentation of the right hand side operand in

def assignment_rhs?(node)

def assignment_rhs?(node)
  node.ancestors.unshift(node).each_cons(2).any? do |child, parent|
    return true if parent.asgn_rhs.equal?(child)
    grandparent = parent.parent
    return true if grandparent && grandparent.masgn_type? &&
                   grandparent.asgn_rhs.equal?(parent)
  end
end

def check(range, node, lhs, rhs)

def check(range, node, lhs, rhs)
  if range
    incorrect_style_detected(range, node, lhs, rhs)
  else
    correct_style_detected
  end
end

def check_and_or(node)

def check_and_or(node)
  lhs, rhs = *node
  range = offending_range(node, lhs, rhs.loc.expression, style)
  check(range, node, lhs, rhs.loc.expression)
end

def correct_indentation(node)

def correct_indentation(node)
  multiplier = kw_node_with_special_indentation(node) ? 2 : 1
  configured_indentation_width * multiplier
end

def grouped_expression?(node)

def grouped_expression?(node)
  node.type == :begin && node.loc.respond_to?(:begin) && node.loc.begin
end

def incorrect_style_detected(range, node, lhs, rhs)

def incorrect_style_detected(range, node, lhs, rhs)
  add_offense(range, range, message(node, lhs, rhs)) do
    if offending_range(node, lhs, rhs, alternative_style)
      unrecognized_style_detected
    else
      opposite_style_detected
    end
  end
end

def indentation(node)

def indentation(node)
  node.loc.expression.source_line =~ /\S/
end

def inside_arg_list_parentheses?(node, ancestor)

def inside_arg_list_parentheses?(node, ancestor)
  a = ancestor.loc
  return false unless ancestor.type == :send && a.begin &&
                      a.begin.is?('(')
  n = node.loc.expression
  n.begin_pos > a.begin.begin_pos && n.end_pos < a.end.end_pos
end

def kw_node_with_special_indentation(node)

def kw_node_with_special_indentation(node)
  node.each_ancestor.find do |a|
    next unless a.loc.respond_to?(:keyword)
    case a.type
    when :if, :while, :until then condition, = *a
    when :for                then _, collection, = *a
    end
    if condition || collection
      within_node?(node, condition || collection)
    end
  end
end

def left_hand_side(receiver)

d <-- d is indented relative to a
b c { block }. <-- b is indented relative to a
a.
for indentation of all lines following the first. For example:
In a chain of method calls, we regard the top send node as the base
def left_hand_side(receiver)
  lhs = receiver
  while lhs.parent && lhs.parent.type == :send
    _receiver, method_name, *_args = *lhs.parent
    break if operator?(method_name)
    lhs = lhs.parent
  end
  lhs
end

def message(node, lhs, rhs)

def message(node, lhs, rhs)
  what = operation_description(node)
  if should_align?(node, style)
    "Align the operands of #{what} spanning multiple lines."
  else
    used_indentation = rhs.column - indentation(lhs)
    "Use #{correct_indentation(node)} (not #{used_indentation}) " \
      "spaces for indenting #{what} spanning multiple lines."
  end
end

def not_for_this_cop?(node)

def not_for_this_cop?(node)
  node.each_ancestor.any? do |ancestor|
    grouped_expression?(ancestor) ||
      inside_arg_list_parentheses?(node, ancestor)
  end
end

def offending_range(node, lhs, rhs, given_style)

def offending_range(node, lhs, rhs, given_style)
  return false unless begins_its_line?(rhs)
  return false if lhs.loc.line == rhs.line # Needed for unary op.
  return false if not_for_this_cop?(node)
  correct_column = if should_align?(node, given_style)
                     lhs.loc.column
                   else
                     indentation(lhs) + correct_indentation(node)
                   end
  @column_delta = correct_column - rhs.column
  rhs if @column_delta != 0
end

def on_and(node)

def on_and(node)
  check_and_or(node)
end

def on_or(node)

def on_or(node)
  check_and_or(node)
end

def on_send(node)

def on_send(node)
  receiver, method_name, *_args = *node
  return unless receiver
  return if method_name == :[] # Don't check parameters inside [].
  lhs = left_hand_side(receiver)
  rhs = right_hand_side(node)
  range = offending_range(node, lhs, rhs, style)
  check(range, node, lhs, rhs)
end

def operation_description(node)

def operation_description(node)
  ancestor = kw_node_with_special_indentation(node)
  if ancestor
    kw = ancestor.loc.keyword.source
    kind = kw == 'for' ? 'collection' : 'condition'
    article = kw =~ /^[iu]/ ? 'an' : 'a'
    "a #{kind} in #{article} `#{kw}` statement"
  else
    'an expression' + (assignment_rhs?(node) ? ' in an assignment' : '')
  end
end

def right_hand_side(send_node)

def right_hand_side(send_node)
  _, method_name, *args = *send_node
  if operator?(method_name) && args.any?
    args.first.loc.expression
  else
    dot = send_node.loc.dot
    selector = send_node.loc.selector
    if dot && selector && dot.line == selector.line
      dot.join(selector)
    elsif selector
      selector
    elsif dot.line == send_node.loc.begin.line
      # lambda.(args)
      dot.join(send_node.loc.begin)
    end
  end
end

def should_align?(node, given_style)

def should_align?(node, given_style)
  given_style == :aligned && (kw_node_with_special_indentation(node) ||
                              assignment_rhs?(node))
end