123456789_123456789_123456789_123456789_123456789_

Class: RuboCop::Cop::Layout::LineLength

Overview

Checks the length of lines in the source code. The maximum length is configurable. The tab size is configured in the IndentationWidth of the Layout/IndentationStyle cop. It also ignores a shebang line by default.

This cop has some autocorrection capabilities. It can programmatically shorten certain long lines by inserting line breaks into expressions that can be safely split across lines. These include arrays, hashes, and method calls with argument lists.

If autocorrection is enabled, the following cops are recommended to further format the broken lines. (Many of these are enabled by default.)

  • Layout/ArgumentAlignment

  • Layout/ArrayAlignment

  • Layout/BlockAlignment

  • Layout/BlockEndNewline

  • Layout/ClosingParenthesisIndentation

  • Layout/FirstArgumentIndentation

  • Layout/FirstArrayElementIndentation

  • Layout/FirstHashElementIndentation

  • Layout/FirstParameterIndentation

  • Layout/HashAlignment

  • Layout/IndentationWidth

  • Layout/MultilineArrayLineBreaks

  • Layout/MultilineBlockLayout

  • Layout/MultilineHashBraceLayout

  • Layout/MultilineHashKeyLineBreaks

  • Layout/MultilineMethodArgumentLineBreaks

  • Layout/MultilineMethodParameterLineBreaks

  • Layout/ParameterAlignment

  • Style/BlockDelimiters

Together, these cops will pretty print hashes, arrays, method calls, etc. For example, let’s say the max columns is 25:

Examples:

# bad
{foo: "0000000000", bar: "0000000000", baz: "0000000000"}

# good
{foo: "0000000000",
bar: "0000000000", baz: "0000000000"}

# good (with recommended cops enabled)
{
  foo: "0000000000",
  bar: "0000000000",
  baz: "0000000000",
}

Constant Summary

::RuboCop::Cop::Base - Inherited

EMPTY_OFFENSES, RESTRICT_ON_SEND

::RuboCop::Cop::RangeHelp - Included

BYTE_ORDER_MARK, NOT_GIVEN

::RuboCop::Cop::Alignment - Included

SPACE

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

Instance Method Summary

::RuboCop::Cop::EndlessMethodRewriter - Included

::RuboCop::Cop::LineLengthHelp - Included

::RuboCop::Cop::Alignment - Included

::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::AllowedPattern - Included

::RuboCop::Cop::CheckLineBreakable - Included

#extract_breakable_node, #all_on_same_line?, #already_on_multiple_lines?, #breakable_collection?, #chained_to_heredoc?,
#children_could_be_broken_up?

The result depends only on the given node, but the check may traverse all children of a large collection and is repeated for each contained element, so memoize it per node.

#compute_children_could_be_broken_up?, #contained_by_breakable_collection_on_same_line?, #contained_by_multiline_collection_that_could_be_broken_up?, #extract_breakable_node_from_elements, #extract_first_element_over_column_limit, #first_argument_is_heredoc?, #process_args, #safe_to_ignore?,
#shift_elements_for_heredoc_arg

If a send or csend node contains a heredoc argument, splitting cannot happen after the heredoc or else it will cause a syntax error.

#within_column_limit?

::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,
#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 a gems locked versions (i.e.

#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?, #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

#allow_string_split?Boolean (readonly, private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 400

def allow_string_split?
  cop_config['SplitStrings']
end

#breakable_range (rw, private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 120

attr_accessor :breakable_range

#require_endless_methods?Boolean (readonly, private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 135

def require_endless_methods?
  config.cop_enabled?('Style/EndlessMethod') &&
    config.for_cop('Style/EndlessMethod')['EnforcedStyle'] == 'require_always'
end

Instance Method Details

#allowed_combination?(line, uri_range, qualified_name_range) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 463

def allowed_combination?(line, uri_range, qualified_name_range)
  if uri_range && qualified_name_range
    allowed_position?(line, uri_range) && allowed_position?(line, qualified_name_range)
  elsif uri_range
    allowed_position?(line, uri_range)
  elsif qualified_name_range
    allowed_position?(line, qualified_name_range)
  else
    false
  end
end

#allowed_heredoc (private)

[ GitHub ]

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

def allowed_heredoc
  cop_config['AllowHeredoc']
end

#allowed_line?(line, line_index) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 352

def allowed_line?(line, line_index)
  matches_allowed_pattern?(line) ||
    shebang?(line, line_index) ||
    (heredocs && line_in_permitted_heredoc?(line_index.succ))
end

#breakable_block_range(block_node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 254

def breakable_block_range(block_node)
  if block_node.arguments? && !block_node.lambda?
    block_node.arguments.loc.end
  else
    block_node.braces? ? block_node.loc.begin : block_node.loc.begin.adjust(begin_pos: 1)
  end
end

#breakable_dstr?(node) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 475

def breakable_dstr?(node)
  # If the `dstr` only contains one child, it cannot be broken
  breakable_string?(node) && !node.child_nodes.one?
end

#breakable_dstr_begin_position(node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 303

def breakable_dstr_begin_position(node)
  source_range = node.source_range
  source_range.begin_pos if source_range.column < max && source_range.last_column >= max
end

#breakable_range_after_semicolon(semicolon_token) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 262

def breakable_range_after_semicolon(semicolon_token)
  range = semicolon_token.pos
  end_pos = range.end_pos
  next_range = range_between(end_pos, end_pos + 1)
  return nil unless same_line?(next_range, range)

  next_char = next_range.source
  return nil if /[\r\n]/.match?(next_char)
  return nil if next_char == ';'

  next_range
end

#breakable_range_by_line_index (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 308

def 
  @breakable_range_by_line_index ||= {}
end

#breakable_string?(node) ⇒ Boolean (private)

[ GitHub ]

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

def breakable_string?(node)
  allow_string_split? &&
    node.single_line? &&
    !node.heredoc? &&
    # TODO: strings inside hashes, kwargs and arrays are currently ignored,
    # but could be considered in the future
    !node.parent&.type?(:pair, :kwoptarg, :array)
end

#breakable_string_delimiters (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 316

def breakable_string_delimiters
  @breakable_string_delimiters ||= {}
end

#breakable_string_position(node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 275

def breakable_string_position(node)
  source_range = node.source_range
  return if source_range.last_column < max
  return unless (pos = breakable_string_range(node))

  pos.end_pos unless pos.end_pos == source_range.begin_pos
end

#breakable_string_range(node) (private)

Locate where to break a string that is too long, ensuring that escape characters are not bisected. If the string contains spaces, use them to determine a place for a clean break; otherwise, the string will be broken at the line length limit.

[ GitHub ]

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

def breakable_string_range(node)
  source_range = node.source_range
  relevant_substr = largest_possible_string(node)

  if (space_pos = relevant_substr.rindex(/\s/))
    source_range.resize(space_pos + 1)
  elsif (escape_pos = relevant_substr.rindex(/\\(u[\da-f]{0,4}|x[\da-f]{0,2})?\z/))
    source_range.resize(escape_pos)
  else
    adjustment = max - source_range.last_column - 3
    return if adjustment.abs > source_range.size

    source_range.adjust(end_pos: adjustment)
  end
end

#check_directive_line(line, line_index) (private)

[ GitHub ]

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

def check_directive_line(line, line_index)
  length_without_directive = line_length_without_directive(line)
  return if length_without_directive <= max

  range = max..(length_without_directive - 1)
  register_offense(
    source_range(
      processed_source.buffer,
      line_index + 1,
      range
    ),
    line,
    line_index,
    length: length_without_directive
  )
end

#check_for_breakable_block(block_node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 207

def check_for_breakable_block(block_node)
  return unless block_node.single_line?
  return if receiver_contains_heredoc?(block_node)

  line_index = block_node.loc.line - 1
  range = breakable_block_range(block_node)
  pos = range.begin_pos + 1

  [line_index] = range_between(pos, pos + 1)
end

#check_for_breakable_dstr(node) (private)

[ GitHub ]

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

def check_for_breakable_dstr(node) # rubocop:disable Metrics/AbcSize
  line_index = node.loc.line - 1
  return if [line_index]

  return unless breakable_dstr?(node)
  return unless (delimiter = string_delimiter(node))

  node.each_child_node(:begin).detect do |begin_node|
    next unless (pos = breakable_dstr_begin_position(begin_node))

    [line_index] = range_between(pos, pos + 1)
    breakable_string_delimiters[line_index] = delimiter
  end
end

#check_for_breakable_node(node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 186

def check_for_breakable_node(node)
  breakable_node = extract_breakable_node(node, max)
  return if breakable_node.nil?

  line_index = breakable_node.first_line - 1
  range = breakable_node.source_range

  existing = [line_index]
  return if existing

  [line_index] = range
end

#check_for_breakable_semicolons(processed_source) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 199

def check_for_breakable_semicolons(processed_source)
  tokens = processed_source.tokens.select { |t| t.type == :tSEMI }
  tokens.reverse_each do |token|
    range = breakable_range_after_semicolon(token)
    [range.line - 1] = range if range
  end
end

#check_for_breakable_str(node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 218

def check_for_breakable_str(node)
  line_index = node.loc.line - 1
  return if [line_index]

  return unless breakable_string?(node)
  return unless (delimiter = string_delimiter(node))
  return unless (pos = breakable_string_position(node))

  [line_index] = range_between(pos, pos + 1)
  breakable_string_delimiters[line_index] = delimiter
end

#check_line(line, line_index) (private)

rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity

[ GitHub ]

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

def check_line(line, line_index)
  return if line_length(line) <= max
  return if allowed_line?(line, line_index)

  if .key?(line_index)
    return handle_endless_method_line(line, line_index)
  end

  if allow_rbs_inline_annotation? && rbs_inline_annotation_on_source_line?(line_index)
    return
  end

  if allow_cop_directives? && directive_on_source_line?(line_index)
    return check_directive_line(line, line_index)
  end
  return check_line_for_exemptions(line, line_index) if allow_uri? || allow_qualified_name?

  register_offense(excess_range(nil, line, line_index), line, line_index)
end

#check_line_for_exemptions(line, line_index) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 447

def check_line_for_exemptions(line, line_index)
  uri_range            = range_if_applicable(line, :uri)
  qualified_name_range = range_if_applicable(line, :qualified_name)

  return if allowed_combination?(line, uri_range, qualified_name_range)

  range = uri_range || qualified_name_range
  register_offense(excess_range(range, line, line_index), line, line_index)
end

#correct_endless_method_block_to_multiline(corrector, node) (private)

[ GitHub ]

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

def correct_endless_method_block_to_multiline(corrector, node)
  block_node = node.body
  block_arguments = block_node.arguments? ? " #{block_node.arguments.source}" : ''
  replacement = [
    "#{block_node.send_node.source} do#{block_arguments}",
    "#{indent(node, offset: 2)}#{block_node.body.source}",
    "#{indent(node)}end"
  ].join("\n")

  corrector.replace(block_node, replacement)
end

#correctable_endless_method_block?(node) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 164

def correctable_endless_method_block?(node)
  block_node = node.body

  block_node&.type?(:any_block) &&
    block_node.braces? &&
    block_node.single_line? &&
    block_node.body &&
    !receiver_contains_heredoc?(block_node)
end

#endless_methods_by_line (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 312

def 
  @endless_methods_by_line ||= {}
end

#excess_range(uri_range, line, line_index) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 380

def excess_range(uri_range, line, line_index)
  excessive_position = if uri_range && uri_range.begin < max
                         uri_range.end
                       else
                         highlight_start(line)
                       end

  source_range(processed_source.buffer, line_index + 1,
               excessive_position...(line_length(line)))
end

#extract_heredocs(ast) (private)

[ GitHub ]

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

def extract_heredocs(ast)
  return [] unless ast

  ast.each_node(:any_str).select(&:heredoc?).map do |node|
    body = node.location.heredoc_body
    delimiter = node.location.heredoc_end.source.strip
    [body.first_line...body.last_line, delimiter]
  end
end

#handle_endless_method_line(line, line_index) (private)

[ GitHub ]

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

def handle_endless_method_line(line, line_index)
  if require_endless_methods?
    return register_required_endless_method_offense(line, line_index)
  end

  register_endless_method_offense(line, line_index)
end

#heredocs (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 320

def heredocs
  @heredocs ||= extract_heredocs(processed_source.ast)
end

#highlight_start(line) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 324

def highlight_start(line)
  # TODO: The max with 0 is a quick fix to avoid crashes when a line
  # begins with many tabs, but getting a correct highlighting range
  # when tabs are used for indentation doesn't work currently.
  [max - indentation_difference(line), 0].max
end

#largest_possible_string(node) (private)

Find the largest possible substring of a string node to retain before a break

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 491

def largest_possible_string(node)
  # The maximum allowed length of a string value is:
  # `Max` - end delimiter (quote) - continuation characters (space and slash)
  max_length = max - 3
  # Offset by the string's starting column so the broken line actually fits
  # within `Max`. When on the same line as its parent, use the column difference;
  # otherwise the string is indented on its own line, so subtract that indentation.
  # (Without this, an indented string under a multi-line parent never shortens
  # below `Max` and the autocorrect loops, inserting empty `"" \` fragments.)
  max_length -= if same_line?(node, node.parent)
                  column_offset_between(node.loc, node.parent.loc)
                else
                  node.loc.column
                end
  node.source[0...(max_length)]
end

#line_in_permitted_heredoc?(line_number) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 414

def line_in_permitted_heredoc?(line_number)
  return false unless allowed_heredoc

  heredocs.any? do |range, delimiter|
    range.cover?(line_number) &&
      (allowed_heredoc == true || allowed_heredoc.include?(delimiter))
  end
end

#max (private) Also known as: #max_line_length

[ GitHub ]

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

def max
  cop_config['Max']
end

#max_line_length (private)

Alias for #max.

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 394

alias max_line_length max

#on_array(node)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 92

alias on_array on_potential_breakable_node

#on_block(node) Also known as: #on_numblock, #on_itblock

[ GitHub ]

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

def on_block(node)
  check_for_breakable_block(node)
end

#on_csend(node)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 95

alias on_csend on_potential_breakable_node

#on_def(node) Also known as: #on_defs

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 97

def on_def(node)
  if node.endless?
    track_endless_method(node)
  else
    check_for_breakable_node(node)
  end
end

#on_defs(node)

Alias for #on_def.

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 104

alias on_defs on_def

#on_dstr(node)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 85

def on_dstr(node)
  check_for_breakable_dstr(node)
end

#on_hash(node)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 93

alias on_hash on_potential_breakable_node

#on_investigation_end

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 112

def on_investigation_end
  processed_source.lines.each_with_index do |line, line_index|
    check_line(line, line_index)
  end
end

#on_itblock(node)

Alias for #on_block.

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 79

alias on_itblock on_block

#on_new_investigation

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 106

def on_new_investigation
  return unless processed_source.raw_source.include?(';')

  check_for_breakable_semicolons(processed_source)
end

#on_numblock(node)

Alias for #on_block.

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 78

alias on_numblock on_block

#on_potential_breakable_node(node) Also known as: #on_array, #on_hash, #on_send, #on_csend

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 89

def on_potential_breakable_node(node)
  check_for_breakable_node(node)
end

#on_send(node)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 94

alias on_send on_potential_breakable_node

#on_str(node)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 81

def on_str(node)
  check_for_breakable_str(node)
end

#range_if_applicable(line, type) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 457

def range_if_applicable(line, type)
  return unless type == :uri ? allow_uri? : allow_qualified_name?

  find_excessive_range(line, type)
end

#receiver_contains_heredoc?(node) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 423

def receiver_contains_heredoc?(node)
  return false unless (receiver = node.receiver)
  return true if receiver.any_str_type? && receiver.heredoc?

  receiver.each_descendant(:any_str).any?(&:heredoc?)
end

#register_endless_method_offense(line, line_index) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 140

def register_endless_method_offense(line, line_index)
  message = format(MSG, length: line_length(line), max: max)
  loc = excess_range(nil, line, line_index)

  add_offense(loc, message: message) do |corrector|
    self.max = line_length(line)

    correct_to_multiline(corrector, [line_index])
  end
end

#register_offense(loc, line, line_index, length: line_length(line)) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 362

def register_offense(loc, line, line_index, length: line_length(line))
  message = format(MSG, length: length, max: max)

  self.breakable_range = [line_index]

  add_offense(loc, message: message) do |corrector|
    self.max = line_length(line)

    insertion = if (delimiter = breakable_string_delimiters[line_index])
                  [delimiter, " \\\n", delimiter].join
                else
                  "\n"
                end

    corrector.insert_before(breakable_range, insertion) unless breakable_range.nil?
  end
end

#register_required_endless_method_offense(line, line_index) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 151

def register_required_endless_method_offense(line, line_index)
  node = [line_index]
  loc = excess_range(nil, line, line_index)

  add_offense(loc, message: format(MSG, length: line_length(line), max: max)) do |corrector|
    self.max = line_length(line)

    if correctable_endless_method_block?(node)
      correct_endless_method_block_to_multiline(corrector, node)
    end
  end
end

#shebang?(line, line_index) ⇒ Boolean (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 358

def shebang?(line, line_index)
  line_index.zero? && line.start_with?('#!')
end

#string_delimiter(node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 480

def string_delimiter(node)
  delimiter = if node.loc?(:begin)
                node.loc.begin
              elsif node.parent&.dstr_type? && node.parent.loc?(:begin)
                node.parent.loc.begin
              end&.source

  delimiter if %w[' "].include?(delimiter)
end

#track_endless_method(node) (private)

[ GitHub ]

  
# File 'lib/rubocop/cop/layout/line_length.rb', line 122

def track_endless_method(node)
  line_index = node.first_line - processed_source.buffer.first_line
  [line_index] = node
end