class RuboCop::Cop::Layout::ClosingParenthesisIndentation

This cop checks the indentation of hanging closing parentheses in method calls, method definitions, and grouped expressions. A hanging closing parenthesis means `)` preceded by a line break.

@example

# bad
some_method(
  a,
  b
  )

some_method(
  a, b
  )

some_method(a, b, c
  )

some_method(a,
            b,
            c
  )

some_method(a,
  x: 1,
  y: 2
  )

# Scenario 1: When First Parameter Is On Its Own Line

# good: when first param is on a new line, right paren is *always*
#       outdented by IndentationWidth
some_method(
  a,
  b
)

# good
some_method(
  a, b
)

# Scenario 2: When First Parameter Is On The Same Line

# good: when all other params are also on the same line, outdent
#       right paren by IndentationWidth
some_method(a, b, c
           )

# good: when all other params are on multiple lines, but are lined
#       up, align right paren with left paren
some_method(a,
            b,
            c
           )

# good: when other params are not lined up on multiple lines, outdent
#       right paren by IndentationWidth
some_method(a,
  x: 1,
  y: 2
)

Constants

MSG_ALIGN
MSG_INDENT

Public Instance Methods

autocorrect(node) click to toggle source
# File lib/rubocop/cop/layout/closing_parenthesis_indentation.rb, line 92
def autocorrect(node)
  AlignmentCorrector.correct(processed_source, node, @column_delta)
end
on_begin(node) click to toggle source
# File lib/rubocop/cop/layout/closing_parenthesis_indentation.rb, line 83
def on_begin(node)
  check(node, node.children)
end
on_csend(node)
Alias for: on_send
on_def(node) click to toggle source
# File lib/rubocop/cop/layout/closing_parenthesis_indentation.rb, line 87
def on_def(node)
  check(node.arguments, node.arguments)
end
Also aliased as: on_defs
on_defs(node)
Alias for: on_def
on_send(node) click to toggle source
# File lib/rubocop/cop/layout/closing_parenthesis_indentation.rb, line 78
def on_send(node)
  check(node, node.arguments)
end
Also aliased as: on_csend

Private Instance Methods

all_elements_aligned?(elements) click to toggle source
# File lib/rubocop/cop/layout/closing_parenthesis_indentation.rb, line 159
def all_elements_aligned?(elements)
  elements
    .map { |e| e.loc.column }
    .uniq
    .count == 1
end
check(node, elements) click to toggle source
# File lib/rubocop/cop/layout/closing_parenthesis_indentation.rb, line 98
def check(node, elements)
  if elements.empty?
    check_for_no_elements(node)
  else
    check_for_elements(node, elements)
  end
end
check_for_elements(node, elements) click to toggle source
# File lib/rubocop/cop/layout/closing_parenthesis_indentation.rb, line 106
def check_for_elements(node, elements)
  left_paren  = node.loc.begin
  right_paren = node.loc.end

  return unless right_paren && begins_its_line?(right_paren)

  correct_column = expected_column(left_paren, elements)

  @column_delta = correct_column - right_paren.column

  return if @column_delta.zero?

  add_offense(right_paren,
              location: right_paren,
              message:  message(correct_column,
                                left_paren,
                                right_paren))
end
check_for_no_elements(node) click to toggle source
# File lib/rubocop/cop/layout/closing_parenthesis_indentation.rb, line 125
def check_for_no_elements(node)
  left_paren = node.loc.begin
  right_paren = node.loc.end
  return unless right_paren && begins_its_line?(right_paren)

  candidates = correct_column_candidates(node, left_paren)

  return if candidates.include?(right_paren.column)

  # Although there are multiple choices for a correct column,
  # select the first one of candidates to determine a specification.
  correct_column = candidates.first
  @column_delta = correct_column - right_paren.column
  add_offense(right_paren,
              location: right_paren,
              message:  message(correct_column,
                                left_paren,
                                right_paren))
end
correct_column_candidates(node, left_paren) click to toggle source
# File lib/rubocop/cop/layout/closing_parenthesis_indentation.rb, line 173
def correct_column_candidates(node, left_paren)
  [
    processed_source.line_indentation(left_paren.line),
    left_paren.column,
    node.loc.column
  ]
end
expected_column(left_paren, elements) click to toggle source
# File lib/rubocop/cop/layout/closing_parenthesis_indentation.rb, line 145
def expected_column(left_paren, elements)
  if line_break_after_left_paren?(left_paren, elements)
    source_indent = processed_source
                    .line_indentation(first_argument_line(elements))
    new_indent    = source_indent - indentation_width

    new_indent.negative? ? 0 : new_indent
  elsif all_elements_aligned?(elements)
    left_paren.column
  else
    processed_source.line_indentation(first_argument_line(elements))
  end
end
first_argument_line(elements) click to toggle source
# File lib/rubocop/cop/layout/closing_parenthesis_indentation.rb, line 166
def first_argument_line(elements)
  elements
    .first
    .loc
    .first_line
end
indentation_width() click to toggle source
# File lib/rubocop/cop/layout/closing_parenthesis_indentation.rb, line 193
def indentation_width
  @config.for_cop('IndentationWidth')['Width'] || 2
end
line_break_after_left_paren?(left_paren, elements) click to toggle source
# File lib/rubocop/cop/layout/closing_parenthesis_indentation.rb, line 197
def line_break_after_left_paren?(left_paren, elements)
  elements.first && elements.first.loc.line > left_paren.line
end
message(correct_column, left_paren, right_paren) click to toggle source
# File lib/rubocop/cop/layout/closing_parenthesis_indentation.rb, line 181
def message(correct_column, left_paren, right_paren)
  if correct_column == left_paren.column
    MSG_ALIGN
  else
    format(
      MSG_INDENT,
      expected: correct_column,
      actual: right_paren.column
    )
  end
end