# frozen_string_literal: truemoduleRuboCopmoduleCop# Common functionality for checking whether an AST node/token is aligned# with something on a preceding or following linemodulePrecedingFollowingAlignmentprivatedefallow_for_alignment?cop_config['AllowForAlignment']enddefaligned_with_something?(range)aligned_with_adjacent_line?(range,method(:aligned_token?))enddefaligned_with_operator?(range)aligned_with_adjacent_line?(range,method(:aligned_operator?))enddefaligned_with_preceding_assignment(token)preceding_line_range=token.line.downto(1)aligned_with_assignment(token,preceding_line_range)enddefaligned_with_subsequent_assignment(token)subsequent_line_range=token.line.upto(processed_source.lines.length)aligned_with_assignment(token,subsequent_line_range)enddefaligned_with_adjacent_line?(range,predicate)# minus 2 because node.loc.line is zero-basedpre=(range.line-2).downto(0)post=range.line.upto(processed_source.lines.size-1)aligned_with_any_line_range?([pre,post],range,&predicate)enddefaligned_with_any_line_range?(line_ranges,range,&predicate)returntrueifaligned_with_any_line?(line_ranges,range,&predicate)# If no aligned token was found, search for an aligned token on the# nearest line with the same indentation as the checked line.base_indentation=processed_source.lines[range.line-1]=~/\S/aligned_with_any_line?(line_ranges,range,base_indentation,&predicate)enddefaligned_with_any_line?(line_ranges,range,indent=nil,&predicate)line_ranges.any?do|line_nos|aligned_with_line?(line_nos,range,indent,&predicate)endenddefaligned_with_line?(line_nos,range,indent=nil)line_nos.eachdo|lineno|nextifaligned_comment_lines.include?(lineno+1)line=processed_source.lines[lineno]index=line=~/\S/nextunlessindexnextifindent&&indent!=indexreturnyield(range,line)endfalseenddefaligned_comment_lines@aligned_comment_lines||=processed_source.comments.map(&:loc).selectdo|r|begins_its_line?(r.expression)end.map(&:line)enddefaligned_token?(range,line)aligned_words?(range,line)||aligned_char?(range,line)||aligned_assignment?(range,line)enddefaligned_operator?(range,line)(aligned_identical?(range,line)||aligned_assignment?(range,line))enddefaligned_words?(range,line)/\s\S/.match?(line[range.column-1,2])enddefaligned_char?(range,line)line[range.column]==range.source[0]enddefaligned_assignment?(range,line)range.source[-1]=='='&&line[range.last_column-1]=='='enddefaligned_identical?(range,line)range.source==line[range.column,range.size]enddefaligned_with_assignment(token,line_range)token_line_indent=processed_source.line_indentation(token.line)assignment_lines=relevant_assignment_lines(line_range)relevant_line_number=assignment_lines[1]return:noneunlessrelevant_line_numberrelevant_indent=processed_source.line_indentation(relevant_line_number)return:noneifrelevant_indent<token_line_indentassignment_line=processed_source.lines[relevant_line_number-1]return:noneunlessassignment_linealigned_assignment?(token.pos,assignment_line)?:yes::noenddefassignment_lines@assignment_lines||=assignment_tokens.map(&:line)enddefassignment_tokens@assignment_tokens||=begintokens=processed_source.tokens.select(&:equal_sign?)# we don't want to operate on equals signs which are part of an# optarg in a method definition# e.g.: def method(optarg = default_val); endtokens=remove_optarg_equals(tokens,processed_source)# Only attempt to align the first = on each lineSet.new(tokens.uniq(&:line))endend# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity# rubocop:disable Metrics/PerceivedComplexity, Metrics/MethodLengthdefrelevant_assignment_lines(line_range)result=[]original_line_indent=processed_source.line_indentation(line_range.first)relevant_line_indent_at_level=trueline_range.eachdo|line_number|current_line_indent=processed_source.line_indentation(line_number)blank_line=processed_source.lines[line_number-1].blank?if(current_line_indent<original_line_indent&&!blank_line)||(relevant_line_indent_at_level&&blank_line)breakendresult<<line_numberifassignment_lines.include?(line_number)&¤t_line_indent==original_line_indentunlessblank_linerelevant_line_indent_at_level=\current_line_indent==original_line_indentendendresultend# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity# rubocop:enable Metrics/PerceivedComplexity, Metrics/MethodLengthdefremove_optarg_equals(asgn_tokens,processed_source)optargs=processed_source.ast.each_node(:optarg)optarg_eql=optargs.map{|o|o.loc.operator.begin_pos}.to_setasgn_tokens.reject{|t|optarg_eql.include?(t.begin_pos)}endendendend