# frozen_string_literal: truemoduleRuboCopmoduleCopmoduleLayout# This cops 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# )##classClosingParenthesisIndentation<CopincludeAlignmentMSG_INDENT='Indent `)` to column %<expected>d (not %<actual>d)'.freezeMSG_ALIGN='Align `)` with `(`.'.freezedefon_send(node)check(node,node.arguments)enddefon_begin(node)check(node,node.children)enddefon_def(node)check(node.arguments,node.arguments)endaliason_defson_defdefautocorrect(node)AlignmentCorrector.correct(processed_source,node,@column_delta)endprivatedefcheck(node,elements)ifelements.empty?check_for_no_elements(node)elsecheck_for_elements(node,elements)endenddefcheck_for_elements(node,elements)left_paren=node.loc.beginright_paren=node.loc.endreturnunlessright_paren&&begins_its_line?(right_paren)correct_column=expected_column(left_paren,elements)@column_delta=correct_column-right_paren.columnreturnif@column_delta.zero?add_offense(right_paren,location: right_paren,message: message(correct_column,left_paren,right_paren))enddefcheck_for_no_elements(node)left_paren=node.loc.beginright_paren=node.loc.endreturnunlessright_paren&&begins_its_line?(right_paren)candidates=correct_column_candidates(node,left_paren)returnifcandidates.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.firstadd_offense(right_paren,location: right_paren,message: message(correct_column,left_paren,right_paren))enddefexpected_column(left_paren,elements)if!line_break_after_left_paren?(left_paren,elements)&&all_elements_aligned?(elements)left_paren.columnelsesource_indent=processed_source.line_indentation(last_argument_line(elements))new_indent=source_indent-indentation_widthnew_indent<0?0:new_indentendenddefall_elements_aligned?(elements)elements.map{|e|e.loc.column}.uniq.count==1enddeflast_argument_line(elements)elements.last.loc.first_lineenddefcorrect_column_candidates(node,left_paren)[processed_source.line_indentation(left_paren.line),left_paren.column,node.loc.column]enddefmessage(correct_column,left_paren,right_paren)ifcorrect_column==left_paren.columnMSG_ALIGNelseformat(MSG_INDENT,expected: correct_column,actual: right_paren.column)endenddefindentation_width@config.for_cop('IndentationWidth')['Width']||2enddefline_break_after_left_paren?(left_paren,elements)elements.first&&elements.first.loc.line>left_paren.lineendendendendend