123456789_123456789_123456789_123456789_123456789_

Class: RuboCop::Cop::Layout::MultilineMethodCallIndentation

Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, ::RuboCop::Cop::AutoCorrector, ::RuboCop::Cop::Base, ::RuboCop::ExcludeLimit, NodePattern::Macros, RuboCop::AST::Sexp
Instance Chain:
Inherits: RuboCop::Cop::Base
Defined in: lib/rubocop/cop/layout/multiline_method_call_indentation.rb

Overview

Checks the indentation of the method name part in method calls that span more than one line.

Examples:

EnforcedStyle: aligned (default)

# bad
while myvariable
.b
  # do something
end

# good
while myvariable
      .b
  # do something
end

# good
Thing.a
     .b
     .c

EnforcedStyle: indented

# good
while myvariable
  .b

  # do something
end

EnforcedStyle: indented_relative_to_receiver

# good
while myvariable
        .a
        .b

  # do something
end

# good
myvariable = Thing
               .a
               .b
               .c

Constant Summary

::RuboCop::Cop::Base - Inherited

DEPARTMENT_SEVERITIES, EMPTY_OFFENSES, RESTRICT_ON_SEND

::RuboCop::Cop::ConfigurableEnforcedStyle - Included

SYMBOL_TO_STRING_CACHE

::RuboCop::Cop::Alignment - Included

SPACE

::RuboCop::Cop::MultilineExpressionIndentation - Included

ASSIGNMENT_MESSAGE_TAIL, DEFAULT_MESSAGE_TAIL, KEYWORD_ANCESTOR_TYPES, KEYWORD_MESSAGE_TAIL, UNALIGNED_RHS_TYPES

::RuboCop::Cop::RangeHelp - Included

BYTE_ORDER_MARK, NOT_GIVEN

Class Attribute Summary

::RuboCop::Cop::AutoCorrector - Extended

::RuboCop::Cop::Base - Inherited

.gem_requirements, .lint?,
.support_autocorrect?

Returns if class supports autocorrect.

.support_multiple_source?

Override if your cop should be called repeatedly for multiple investigations Between calls to on_new_investigation and on_investigation_end, the result of processed_source will remain constant.

Class Method Summary

::RuboCop::Cop::Base - Inherited

.autocorrect_incompatible_with

List of cops that should not try to autocorrect at the same time as this cop.

.badge

Naming.

.callbacks_needed, .cop_name, .department,
.documentation_url

Returns a url to view this cops documentation online.

.exclude_from_registry

Call for abstract Cop classes.

.inherited,
.joining_forces

Override and return the Force class(es) you need to join.

.match?

Returns true if the cop name or the cop namespace matches any of the given names.

.new,
.requires_gem

Register a version requirement for the given gem name.

.restrict_on_send

Reserved for Commissioner.

::RuboCop::ExcludeLimit - Extended

exclude_limit

Sets up a configuration option to have an exclude limit tracked.

transform

Instance Attribute Summary

::RuboCop::Cop::Alignment - Included

::RuboCop::Cop::ConfigurableEnforcedStyle - Included

::RuboCop::Cop::Base - Inherited

::RuboCop::Cop::AutocorrectLogic - Included

#autocorrect?, #autocorrect_enabled?, #autocorrect_requested?, #autocorrect_with_disable_uncorrectable?, #correctable?, #disable_uncorrectable?, #safe_autocorrect?,
#skipped_unsafe_correction_with_disable_uncorrectable?

Whether a correction exists but is skipped because it is unsafe in a safe autocorrect run, while --disable-uncorrectable asks for a todo comment on everything this run cannot correct.

#contextual_autocorrect_held_back?

When LSP is enabled or the --editor-mode option is on, it is considered as editing source code, and autocorrection with AutoCorrect: contextual will not be performed.

Instance Method Summary

::RuboCop::Cop::RangeHelp - Included

#add_range,
#arguments_range

A range containing the first to the last argument of a method call or method definition.

#column_offset_between,
#contents_range

A range containing only the contents of a literal with delimiters (e.g.

#directions,
#effective_column

Returns the column attribute of the range, except if the range is on the first line and there’s a byte order mark at the beginning of that line, in which case 1 is subtracted from the column value.

#final_pos

rubocop:disable-next Metrics/ParameterLists.

#move_pos, #move_pos_str, #range_between, #range_by_whole_lines, #range_with_comments, #range_with_comments_and_lines, #range_with_surrounding_comma, #range_with_surrounding_space, #source_range

::RuboCop::Cop::MultilineExpressionIndentation - Included

#on_csend
#on_send,
#argument_in_method_call

rubocop:todo Metrics/CyclomaticComplexity.

#assignment_rhs, #check,
#correct_indentation

The correct indentation of node is usually IndentationWidth, with one exception: prefix keywords.

#disqualified_rhs?, #grouped_expression?, #incorrect_style_detected, #indentation, #indented_keyword_expression, #inside_arg_list_parentheses?, #keyword_message_tail, #kw_node_with_special_indentation,
#left_hand_side

In a chain of method calls, we regard the top call node as the base for indentation of all lines following the first.

#not_for_this_cop?, #operation_description, #part_of_assignment_rhs, #part_of_block_body?,
#postfix_conditional?

Returns true if node is a conditional whose body and condition begin on the same line.

#valid_method_rhs_candidate?

The []= operator and setters (a.b = c) are parsed as :send nodes.

#valid_rhs?, #valid_rhs_candidate?, #within_node?

::RuboCop::Cop::Alignment - Included

::RuboCop::Cop::ConfigurableEnforcedStyle - Included

::RuboCop::Cop::Base - Inherited

#add_global_offense

Adds an offense that has no particular location.

#add_offense

Adds an offense on the specified range (or node with an expression) Unless that offense is disabled for this range, a corrector will be yielded to provide the cop the opportunity to autocorrect the offense.

#begin_investigation

Called before any investigation.

#callbacks_needed

 — grouped under the Commissioner heading above.

#cop_config

Configuration Helpers.

#cop_name, #excluded_file?,
#external_dependency_checksum

This method should be overridden when a cop’s behavior depends on state that lives outside of these locations:

#inspect,
#message

Gets called if no message is specified when calling add_offense or add_global_offense Cops are discouraged to override this; instead pass your message directly.

#name

Alias for Base#cop_name.

#offenses,
#on_investigation_end

Called after all on_…​

#on_new_investigation

Called before all on_…​

#on_other_file

Called instead of all on_…​

#parse

There should be very limited reasons for a Cop to do it’s own parsing.

#parser_engine,
#ready

Called between investigations.

#relevant_file?,
#target_gem_version

Returns the version of a gem in the target, by default its locked version (i.e. from Gemfile.lock or gems.locked).

#target_rails_version, #target_ruby_version, #annotate, #apply_correction, #attempt_correction,
#callback_argument

Reserved for Cop::Cop.

#complete_investigation

Called to complete an investigation.

#correct, #covering_disabled_range, #current_corrector,
#current_offense_locations

Reserved for Commissioner:

#current_offenses, #currently_disabled_lines, #custom_severity, #default_severity, #disable_uncorrectable, #enabled_line?,
#enabled_lines?

A multi-line offense is suppressed by a directive on any line of its range, not only its first line, matching the intuition that the directive is attached to the offending code.

#file_name_matches_any?, #find_message, #find_severity, #matches_absolute_include_pattern?, #new_offense, #range_for_original, #range_from_node_or_range,
#reset_investigation

Actually private methods.

#suppression_reason

The -- reason on the directive that suppresses offenses on this range, or nil when the directive carries none.

#use_corrector

::RuboCop::Cop::AutocorrectLogic - Included

::RuboCop::Cop::IgnoredNode - Included

Constructor Details

This class inherits a constructor from RuboCop::Cop::Base

Instance Attribute Details

#should_align_with_base? ⇒ Boolean (readonly, private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 301

def should_align_with_base?
  @base && style == :aligned
end

#should_indent_relative_to_receiver? ⇒ Boolean (readonly, private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 297

def should_indent_relative_to_receiver?
  @base && style == :indented_relative_to_receiver
end

Instance Method Details

#after_multiline_block_base(first_call, node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 221

def after_multiline_block_base(first_call, node)
  return unless first_call.block_node&.multiline?

  after_block = first_call.block_node.parent
  return unless after_block&.call_type? && after_block.loc?(:dot) && after_block != node

  after_block.loc.dot.join(after_block.loc.selector)
end

#align_with_base_message(rhs) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 310

def align_with_base_message(rhs)
  "Align `#{rhs.source}` with `#{base_source}` on line #{@base.line}."
end

#aligned_with_first_line_dot?(node, rhs) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 249

def aligned_with_first_line_dot?(node, rhs)
  return false unless rhs.source.start_with?('.', '&.')

  first_call = first_call_has_a_dot(node)
  return false if first_call == node.receiver

  dot = first_call.loc.dot
  dot.line == node.first_line && dot.column == rhs.column
end

#alignment_base(node, rhs, given_style) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 332

def alignment_base(node, rhs, given_style)
  case given_style
  when :aligned
    semantic_alignment_base(node, rhs) || syntactic_alignment_base(node, rhs)
  when :indented_relative_to_receiver
    receiver_alignment_base(node)
  end
end

#alignment_base_for_chained_receiver?(receiver_chain, base_receiver) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 391

def alignment_base_for_chained_receiver?(receiver_chain, base_receiver)
  base_receiver&.hash_type? ||
    method_on_receiver_last_line?(receiver_chain, base_receiver, :begin)
end

#autocorrect(corrector, node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 102

def autocorrect(corrector, node)
  if @send_node.block_node
    correct_selector_only(corrector, node)
    correct_block(corrector, @send_node.block_node, node.first_line)
  else
    AlignmentCorrector.correct(corrector, processed_source, node, @column_delta)
  end
end

#base_source (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 314

def base_source
  @base.source[/[^\n]*/]
end

#block_lines(block_node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 127

def block_lines(block_node)
  body = block_node.body
  lines = body ? (body.first_line..body.last_line).to_a : []

  (lines << block_node.loc.end.line).uniq
end

#calculate_column_delta_offense(rhs, correct_column) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 272

def calculate_column_delta_offense(rhs, correct_column)
  @column_delta = correct_column - rhs.column
  rhs if @column_delta.nonzero?
end

#check_hash_pair_indentation(node, lhs, rhs) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 187

def check_hash_pair_indentation(node, lhs, rhs)
  @base = find_hash_pair_alignment_base(node)
  return false if !@base && inside_multiline_chain_arg?(node)

  @base ||= first_dot_alignment_base(node, rhs) || lhs.source_range
  return if aligned_with_first_line_dot?(node, rhs)

  calculate_column_delta_offense(rhs, @base.column)
end

#check_hash_pair_indented_style(rhs, pair_ancestor) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 178

def check_hash_pair_indented_style(rhs, pair_ancestor)
  pair_key = pair_ancestor.key
  double_indentation = configured_indentation_width * 2
  correct_column = pair_key.source_range.column + double_indentation
  @hash_pair_base_column = pair_key.source_range.column + configured_indentation_width

  calculate_column_delta_offense(rhs, correct_column)
end

#check_regular_indentation(node, lhs, rhs, given_style) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 259

def check_regular_indentation(node, lhs, rhs, given_style)
  @base = alignment_base(node, rhs, given_style)
  correct_column = if @base
                     parent = node.parent
                     parent = parent.parent if parent&.any_block_type?
                     @base.column + extra_indentation(given_style, parent)
                   else
                     indentation(lhs) + correct_indentation(node)
                   end

  calculate_column_delta_offense(rhs, correct_column)
end

#correct_block(corrector, block_node, selector_line) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 117

def correct_block(corrector, block_node, selector_line)
  lines_to_shift = block_lines(block_node) - [selector_line]

  lines_to_shift.each do |line|
    line_range = processed_source.buffer.line_range(line)

    AlignmentCorrector.correct(corrector, processed_source, line_range, @column_delta)
  end
end

#correct_selector_only(corrector, node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 111

def correct_selector_only(corrector, node)
  selector_line = processed_source.buffer.line_range(node.first_line)
  selector_range = range_between(selector_line.begin_pos, selector_line.end_pos)
  AlignmentCorrector.correct(corrector, processed_source, selector_range, @column_delta)
end

#extra_indentation(given_style, parent) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 277

def extra_indentation(given_style, parent)
  return 0 unless given_style == :indented_relative_to_receiver

  if parent&.type?(:splat, :kwsplat)
    configured_indentation_width - parent.loc.operator.length
  else
    configured_indentation_width
  end
end

#find_base_receiver(node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 69

def find_base_receiver(node)
  base_receiver = node
  base_receiver = base_receiver.receiver while base_receiver.receiver
  base_receiver
end

#find_continuation_node(node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 436

def find_continuation_node(node)
  receiver = node.receiver
  return leftmost_call_on_same_line(receiver) if single_line_block_receiver?(receiver)
  return unless receiver.call_type? && receiver.loc.dot
  return receiver if receiver.receiver.begin_type? && node.block_node.single_line?
  return unless receiver.loc.dot.line > receiver.receiver.last_line

  receiver
end

#find_enclosing_chain_call(node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 237

def find_enclosing_chain_call(node)
  hash_ancestor = find_pair_ancestor(node).parent
  enclosing_call = hash_ancestor.parent
  return unless hash_arg_in_chain?(enclosing_call, hash_ancestor)

  enclosing_call
end

#find_hash_method_base_in_receiver_chain(node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 379

def find_hash_method_base_in_receiver_chain(node)
  receiver_chain = unwrap_block_node(node.receiver)
  while receiver_chain&.call_type?
    base_receiver = unwrap_block_node(receiver_chain.receiver)
    if alignment_base_for_chained_receiver?(receiver_chain, base_receiver)
      return receiver_chain.loc.dot.join(receiver_chain.loc.selector)
    end

    receiver_chain = base_receiver
  end
end

#find_hash_pair_alignment_base(node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 197

def find_hash_pair_alignment_base(node)
  base_receiver = find_base_receiver(node.receiver)
  return unless base_receiver.hash_type?

  first_call = first_call_has_a_dot(node)
  first_call.loc.dot.join(first_call.loc.selector)
end

#find_multiline_block_chain_node(node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 430

def find_multiline_block_chain_node(node)
  return find_continuation_node(node) if node.block_node

  handle_descendant_block(node)
end

#find_pair_ancestor(node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 75

def find_pair_ancestor(node)
  child = node
  node.each_ancestor do |ancestor|
    return ancestor if ancestor.pair_type?
    break if grouped_expression?(ancestor) || inside_arg_list_parentheses?(node, ancestor)
    break if inside_body?(ancestor, child)

    child = ancestor
  end

  nil
end

#first_call_alignment_node(node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 404

def first_call_alignment_node(node)
  node = first_call_has_a_dot(node)
  base_receiver = find_base_receiver(node)

  return node if method_on_receiver_last_line?(node, base_receiver, :array)
  return if node.loc.dot.line != node.first_line
  return if method_on_receiver_last_line?(node, base_receiver, :begin)

  node
end

#first_call_has_a_dot(node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 470

def first_call_has_a_dot(node)
  base = find_base_receiver(node)
  node = base.parent
  node = node.parent until node.loc?(:dot)
  node
end

#first_dot_alignment_base(node, rhs) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 205

def first_dot_alignment_base(node, rhs)
  return unless rhs.source.start_with?('.', '&.')

  first_call = first_call_has_a_dot(node)
  dot = first_call.loc.dot
  return unless dot
  return if first_call == node

  after_block_base = after_multiline_block_base(first_call, node)
  return after_block_base if after_block_base

  return unless same_line?(dot, first_call.receiver.source_range)

  dot.join(first_call.loc.selector)
end

#get_dot_right_above(node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 421

def get_dot_right_above(node)
  node.each_ancestor.find do |a|
    dot = a.loc.dot if a.loc?(:dot)
    next unless dot

    dot.line == node.loc.dot.line - 1 && dot.column == node.loc.dot.column
  end
end

#handle_descendant_block(node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 460

def handle_descendant_block(node)
  receiver = node.receiver
  return leftmost_call_on_same_line(receiver) if single_line_block_receiver?(receiver)

  block_node = node.each_descendant(:any_block).first
  return unless block_node&.multiline?

  receiver.call_type? ? receiver : block_node.parent
end

#hash_arg_in_chain?(call, hash_node) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 245

def hash_arg_in_chain?(call, hash_node)
  call&.call_type? && call.receiver != hash_node && call.loc?(:dot)
end

#hash_pair_aligned?(pair_ancestor, given_style) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 170

def hash_pair_aligned?(pair_ancestor, given_style)
  pair_ancestor && given_style == :aligned
end

#hash_pair_indented?(node, pair_ancestor, given_style) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 174

def hash_pair_indented?(node, pair_ancestor, given_style)
  pair_ancestor && given_style == :indented && find_base_receiver(node).hash_type?
end

#inside_body?(ancestor, child) ⇒ Boolean (private)

A block, begin, if or loop body is a separate set of statements, so a method chain in it is not the value of a hash pair the body is nested in. The send node of a block is still part of the value.

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 91

def inside_body?(ancestor, child)
  return !child.equal?(ancestor.send_node) if ancestor.any_block_type?
  return !ancestor.ternary? if ancestor.if_type?

  ancestor.type?(:kwbegin, :while, :until, :for)
end

#inside_multiline_chain_arg?(node) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 230

def inside_multiline_chain_arg?(node)
  enclosing_call = find_enclosing_chain_call(node)
  return false unless enclosing_call

  !same_line?(enclosing_call.loc.selector, enclosing_call.receiver.source_range)
end

#leftmost_call_on_same_line(node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 450

def leftmost_call_on_same_line(node)
  current = unwrap_block_node(node)
  while (receiver = unwrap_block_node(current.receiver)) &&
        receiver.call_type? && receiver.loc?(:dot) &&
        receiver.loc.dot.line == current.loc.dot.line
    current = receiver
  end
  current
end

#message(node, lhs, rhs) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 287

def message(node, lhs, rhs)
  if should_indent_relative_to_receiver?
    relative_to_receiver_message(rhs)
  elsif should_align_with_base?
    align_with_base_message(rhs)
  else
    no_base_message(lhs, rhs, node)
  end
end

#method_on_receiver_last_line?(node, base_receiver, type) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 415

def method_on_receiver_last_line?(node, base_receiver, type)
  return false unless base_receiver

  same_line?(node.loc.dot, base_receiver.source_range.end) && base_receiver.type?(type)
end

#no_base_message(lhs, rhs, node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 318

def no_base_message(lhs, rhs, node)
  if @hash_pair_base_column
    used_indentation = rhs.column - @hash_pair_base_column
    expected_indentation = configured_indentation_width
  else
    used_indentation = rhs.column - indentation(lhs)
    expected_indentation = correct_indentation(node)
  end
  what = operation_description(node, rhs)

  "Use #{expected_indentation} (not #{used_indentation}) " \
    "spaces for indenting #{what} spanning multiple lines."
end

#offending_range(node, lhs, rhs, given_style) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 150

def offending_range(node, lhs, rhs, given_style)
  return false unless begins_its_line?(rhs)

  @send_node = node # Store for use in autocorrect
  pair_ancestor = find_pair_ancestor(node)
  if hash_pair_aligned?(pair_ancestor, given_style)
    return check_hash_pair_indentation(node, lhs, rhs)
  end
  if hash_pair_indented?(node, pair_ancestor, given_style)
    return check_hash_pair_indented_style(rhs, pair_ancestor)
  end
  return false if skip_for_context?(node, pair_ancestor)

  check_regular_indentation(node, lhs, rhs, given_style)
end

#operation_rhs(node) {|operation_rhs.first_argument| ... } (private)

Yields:

  • (operation_rhs.first_argument)
[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 477

def operation_rhs(node)
  operation_rhs = node.receiver.each_ancestor(:send).find do |rhs|
    operator_rhs?(rhs, node.receiver)
  end

  return unless operation_rhs

  yield operation_rhs.first_argument
end

#operator_rhs?(node, receiver) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 487

def operator_rhs?(node, receiver)
  node.operator_method? && node.arguments? && within_node?(receiver, node.first_argument)
end

#receiver_alignment_base(node) (private)

a .b .c

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 371

def receiver_alignment_base(node)
  hash_method_base = find_hash_method_base_in_receiver_chain(node)
  return hash_method_base if hash_method_base

  first_call = first_call_has_a_dot(node)
  first_call.receiver.source_range
end

#relative_to_receiver_message(rhs) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 305

def relative_to_receiver_message(rhs)
  "Indent `#{rhs.source}` #{configured_indentation_width} spaces " \
    "more than `#{base_source}` on line #{@base.line}."
end

#relevant_node?(send_node) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 134

def relevant_node?(send_node)
  send_node.loc.dot # Only check method calls with dot operator
end

#right_hand_side(send_node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 138

def right_hand_side(send_node)
  dot = send_node.loc.dot
  selector = send_node.loc.selector
  if (send_node.dot? || send_node.safe_navigation?) && selector && same_line?(dot, selector)
    dot.join(selector)
  elsif selector
    selector
  elsif send_node.implicit_call?
    dot.join(send_node.loc.begin)
  end
end

#semantic_alignment_base(node, rhs) (private)

a.b .c

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 359

def semantic_alignment_base(node, rhs)
  return unless rhs.source.start_with?('.', '&.')

  node = semantic_alignment_node(node)
  return unless node&.loc?(:selector) && node.loc.dot

  node.loc.dot.join(node.loc.selector)
end

#semantic_alignment_node(node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 396

def semantic_alignment_node(node)
  return if argument_in_method_call(node, :with_parentheses)

  get_dot_right_above(node) ||
    find_multiline_block_chain_node(node) ||
    first_call_alignment_node(node)
end

#single_line_block_receiver?(receiver) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 446

def single_line_block_receiver?(receiver)
  receiver.single_line? && receiver.any_block_type?
end

#skip_for_context?(node, pair_ancestor) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 166

def skip_for_context?(node, pair_ancestor)
  pair_ancestor ? inside_multiline_chain_arg?(node) : not_for_this_cop?(node)
end

#syntactic_alignment_base(lhs, rhs) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 341

def syntactic_alignment_base(lhs, rhs)
  # a if b
  #      .c
  kw_node_with_special_indentation(lhs) do |base|
    return indented_keyword_expression(base).source_range
  end

  # a = b
  #     .c
  part_of_assignment_rhs(lhs, rhs) { |base| return assignment_rhs(base).source_range }

  # a + b
  #     .c
  operation_rhs(lhs) { |base| return base.source_range }
end

#unwrap_block_node(node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 98

def unwrap_block_node(node)
  node&.any_block_type? ? node.send_node : node
end

#validate_config

Raises:

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/multiline_method_call_indentation.rb', line 57

def validate_config
  return unless style == :aligned && cop_config['IndentationWidth']

  raise ValidationError,
        'The `Layout/MultilineMethodCallIndentation` ' \
        'cop only accepts an `IndentationWidth` ' \
        'configuration parameter when ' \
        '`EnforcedStyle` is `indented`.'
end