class RuboCop::Cop::Layout::RescueEnsureAlignment

end
puts ‘error’
rescue
something
begin
# good
end
puts ‘error’
rescue
something
begin
# bad
@example
properly.
Checks whether the rescue and ensure keywords are aligned

def access_modifier?(node)

def access_modifier?(node)
  return true if node.respond_to?(:access_modifier?) && node.access_modifier?
  return true if node.respond_to?(:method_name) &&
                 ALTERNATIVE_ACCESS_MODIFIERS.include?(node.method_name)
  false
end

def access_modifier_node(node)

def access_modifier_node(node)
  return nil unless
    ANCESTOR_TYPES_WITH_ACCESS_MODIFIERS.include?(node.type)
  access_modifier_node = node.ancestors.first
  return nil unless access_modifier?(access_modifier_node)
  access_modifier_node
end

def aligned_with_leading_dot?(do_keyword_line, send_node_loc, rescue_keyword_column)

def aligned_with_leading_dot?(do_keyword_line, send_node_loc, rescue_keyword_column)
  return false unless send_node_loc.respond_to?(:dot) && (dot = send_node_loc.dot)
  do_keyword_line == dot.line && rescue_keyword_column == dot.column
end

def aligned_with_line_break_method?(ancestor_node, node)

def aligned_with_line_break_method?(ancestor_node, node)
  send_node_loc = ancestor_node.send_node.loc
  do_keyword_line = ancestor_node.loc.begin.line
  rescue_keyword_column = node.loc.keyword.column
  selector = send_node_loc.respond_to?(:selector) ? send_node_loc.selector : send_node_loc
  if aligned_with_leading_dot?(do_keyword_line, send_node_loc, rescue_keyword_column)
    return true
  end
  do_keyword_line == selector&.line && rescue_keyword_column == selector.column
end

def alignment_location(alignment_node)

def alignment_location(alignment_node)
  if begin_end_alignment_style == 'start_of_line'
    start_line_range(alignment_node)
  else
    alignment_node.source_range
  end
end

def alignment_node(node)

def alignment_node(node)
  ancestor_node = ancestor_node(node)
  return ancestor_node if ancestor_node.nil? || ancestor_node.kwbegin_type?
  return if ancestor_node.respond_to?(:send_node) &&
            aligned_with_line_break_method?(ancestor_node, node)
  assignment_node = assignment_node(ancestor_node)
  return assignment_node if same_line?(ancestor_node, assignment_node)
  access_modifier_node = access_modifier_node(ancestor_node)
  return access_modifier_node unless access_modifier_node.nil?
  ancestor_node
end

def alignment_source(node, starting_loc)

def alignment_source(node, starting_loc)
  ending_loc =
    case node.type
    when :block, :kwbegin
      node.loc.begin
    when :def, :defs, :class, :module,
         :lvasgn, :ivasgn, :cvasgn, :gvasgn, :casgn
      node.loc.name
    when :masgn
      mlhs_node, = *node
      mlhs_node.source_range
    else
      # It is a wrapper with access modifier.
      node.child_nodes.first.loc.name
    end
  range_between(starting_loc.begin_pos, ending_loc.end_pos).source
end

def ancestor_node(node)

def ancestor_node(node)
  node.each_ancestor(*ANCESTOR_TYPES).first
end

def assignment_node(node)

def assignment_node(node)
  assignment_node = node.ancestors.first
  return nil unless
    assignment_node&.assignment?
  assignment_node
end

def autocorrect(corrector, node, alignment_location)

def autocorrect(corrector, node, alignment_location)
  whitespace = whitespace_range(node)
  # Some inline node is sitting before current node.
  return nil unless whitespace.source.strip.empty?
  new_column = alignment_location.column
  corrector.replace(whitespace, ' ' * new_column)
end

def begin_end_alignment_style

def begin_end_alignment_style
  begin_end_alignment_conf = config.for_cop('Layout/BeginEndAlignment')
  begin_end_alignment_conf['Enabled'] && begin_end_alignment_conf['EnforcedStyleAlignWith']
end

def check(node)

def check(node)
  alignment_node = alignment_node(node)
  return if alignment_node.nil?
  alignment_loc = alignment_location(alignment_node)
  kw_loc        = node.loc.keyword
  return if alignment_loc.column == kw_loc.column || same_line?(alignment_loc, kw_loc)
  add_offense(
    kw_loc, message: format_message(alignment_node, alignment_loc, kw_loc)
  ) do |corrector|
    autocorrect(corrector, node, alignment_loc)
  end
end

def format_message(alignment_node, alignment_loc, kw_loc)

def format_message(alignment_node, alignment_loc, kw_loc)
  format(
    MSG,
    kw_loc: kw_loc.source,
    kw_loc_line: kw_loc.line,
    kw_loc_column: kw_loc.column,
    beginning: alignment_source(alignment_node, alignment_loc),
    begin_loc_line: alignment_loc.line,
    begin_loc_column: alignment_loc.column
  )
end

def modifier?(node)

def modifier?(node)
  return false unless @modifier_locations.respond_to?(:include?)
  @modifier_locations.include?(node.loc.keyword)
end

def on_ensure(node)

def on_ensure(node)
  check(node)
end

def on_new_investigation

def on_new_investigation
  @modifier_locations =
    processed_source.tokens.each_with_object([]) do |token, locations|
      next unless token.rescue_modifier?
      locations << token.pos
    end
end

def on_resbody(node)

def on_resbody(node)
  check(node) unless modifier?(node)
end

def whitespace_range(node)

def whitespace_range(node)
  begin_pos      = node.loc.keyword.begin_pos
  current_column = node.loc.keyword.column
  range_between(begin_pos - current_column, begin_pos)
end