class RuboCop::Cop::Layout::FirstArgumentIndentation


second_param
nested_first_param),
some_method nested_call(
second_param)
nested_first_param),
nested_call(
foo = some_method(
second_param)
nested_first_param),
foo = some_method(nested_call(
second_param)
first_param,
foo = some_method(
second_param)
first_param,
some_method(
# good
# should be indented relative to the inner method.
# is itself a argument in a method call, then the inner argument
# the preceding line, but if it’s a argument for a method call that
# The first argument should normally be indented one step more than
@example EnforcedStyle: special_for_inner_method_call
second_params
nested_first_param),
some_method nested_call(
second_param)
nested_first_param),
nested_call(
foo = some_method(
second_param)
nested_first_param),
foo = some_method(nested_call(
second_param)
first_param,
foo = some_method(
second_param)
first_param,
some_method(
# good
# the parent that is receiving the argument
# The first argument should always be indented one level relative to
@example EnforcedStyle: consistent_relative_to_receiver
second_param
nested_first_param),
some_method nested_call(
second_param)
nested_first_param),
nested_call(
foo = some_method(
second_param)
nested_first_param),
foo = some_method(nested_call(
second_param)
first_param,
foo = some_method(
second_param)
first_param,
some_method(
# good
# preceding line.
# The first argument should always be indented one step more than the
@example EnforcedStyle: consistent
second_param
nested_first_param),
some_method nested_call(
second_param)
nested_first_param),
nested_call(
foo = some_method(
second_param)
nested_first_param),
foo = some_method(nested_call(
second_param)
first_param,
foo = some_method(
second_param)
first_param,
some_method(
# good
# parentheses.
# only applies if the outer method call encloses its arguments in
# Same as ‘special_for_inner_method_call` except that the special rule
@example EnforcedStyle: special_for_inner_method_call_in_parentheses (default)
second_param
nested_first_param),
some_method nested_call(
second_param)
nested_first_param),
nested_call(
foo = some_method(
second_param)
nested_first_param),
foo = some_method(nested_call(
second_param)
first_param,
foo = some_method(
second_param)
first_param,
some_method(
# bad
@example
`EnforcedStyle: with_fixed_indentation` is specified for `Layout/ArgumentAlignment`.
This cop will respect `Layout/ArgumentAlignment` and will not work when
`Layout/FirstParameterIndentation`.
For indenting the first parameter of method definitions, check out
not by this cop.
Arguments after the first one are checked by `Layout/ArgumentAlignment`,
Checks the indentation of the first argument in a method call.

def argument_alignment_config

def argument_alignment_config
  config.for_cop('Layout/ArgumentAlignment')
end

def autocorrect(corrector, node)

def autocorrect(corrector, node)
  AlignmentCorrector.correct(corrector, processed_source, node, column_delta)
end

def bare_operator?(node)

def bare_operator?(node)
  node.operator_method? && !node.dot?
end

def base_indentation(node)

def base_indentation(node)
  if special_inner_call_indentation?(node)
    column_of(base_range(node, node.first_argument))
  else
    previous_code_line(node.first_argument.first_line) =~ /\S/
  end
end

def base_range(send_node, arg_node)

def base_range(send_node, arg_node)
  parent = send_node.parent
  start_node = if parent && (parent.splat_type? || parent.kwsplat_type?)
                 send_node.parent
               else
                 send_node
               end
  range_between(start_node.source_range.begin_pos, arg_node.source_range.begin_pos)
end

def column_of(range)

is simple. For ranges with line breaks, we look a the last code line.
Returns the column of the given range. For single line ranges, this
def column_of(range)
  source = range.source.strip
  if source.include?("\n")
    previous_code_line(range.line + source.count("\n") + 1) =~ /\S/
  else
    display_column(range)
  end
end

def comment_lines

def comment_lines
  @comment_lines ||=
    processed_source
    .comments
    .select { |c| begins_its_line?(c.source_range) }
    .map { |c| c.loc.line }
end

def enable_layout_first_method_argument_line_break?

def enable_layout_first_method_argument_line_break?
  config.for_cop('Layout/FirstMethodArgumentLineBreak')['Enabled']
end

def enforce_first_argument_with_fixed_indentation?

def enforce_first_argument_with_fixed_indentation?
  return false unless argument_alignment_config['Enabled']
  argument_alignment_config['EnforcedStyle'] == 'with_fixed_indentation'
end

def message(arg_node)

def message(arg_node)
  return 'Bad indentation of the first argument.' unless arg_node
  send_node = arg_node.parent
  text = base_range(send_node, arg_node).source.strip
  base = if !text.include?("\n") && special_inner_call_indentation?(send_node)
           "`#{text}`"
         elsif comment_line?(text.lines.reverse_each.first)
           'the start of the previous line (not counting the comment)'
         else
           'the start of the previous line'
         end
  format(MSG, base: base)
end

def on_new_investigation

def on_new_investigation
  @comment_lines = nil
end

def on_send(node)

def on_send(node)
  return unless should_check?(node)
  return if same_line?(node, node.first_argument)
  return if style != :consistent && enforce_first_argument_with_fixed_indentation? &&
            !enable_layout_first_method_argument_line_break?
  indent = base_indentation(node) + configured_indentation_width
  check_alignment([node.first_argument], indent)
end

def previous_code_line(line_number)

line.
containing the previous line that's not a comment line or a blank
Takes the line number of a given code line and returns a string
def previous_code_line(line_number)
  line = ''
  while line.blank? || comment_lines.include?(line_number)
    line_number -= 1
    line = processed_source.lines[line_number - 1]
  end
  line
end

def should_check?(node)

def should_check?(node)
  node.arguments? && !bare_operator?(node) && !node.setter_method?
end

def special_inner_call_indentation?(node)

def special_inner_call_indentation?(node)
  return false if style == :consistent
  return true  if style == :consistent_relative_to_receiver
  parent = node.parent
  return false unless eligible_method_call?(parent)
  return false if !parent.parenthesized? &&
                  style == :special_for_inner_method_call_in_parentheses
  # The node must begin inside the parent, otherwise node is the first
  # part of a chained method call.
  node.source_range.begin_pos > parent.source_range.begin_pos
end