class RuboCop::Cop::Metrics::LineLength
This cop 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/Tab` cop.
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 Layout
cops are recommended to further format the broken lines.
- AlignArray - AlignHash - AlignParameters - ClosingParenthesisIndentation - IndentFirstArgument - IndentFirstArrayElement - IndentFirstHashElement - IndentFirstParameter - MultilineArrayLineBreaks - MultilineHashBraceLayout - MultilineHashKeyLineBreaks - MultilineMethodArgumentLineBreaks
Together, these cops will pretty print hashes, arrays, method calls, etc. For example, let's say the max columns is 25:
@example
# 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", }
Constants
- MSG
Public Instance Methods
autocorrect(range)
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 76 def autocorrect(range) return if range.nil? lambda do |corrector| corrector.insert_before(range, "\n") end end
investigate_post_walk(processed_source)
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 70 def investigate_post_walk(processed_source) processed_source.lines.each_with_index do |line, line_index| check_line(line, line_index) end end
on_potential_breakable_node(node)
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 63 def on_potential_breakable_node(node) check_for_breakable_node(node) end
Private Instance Methods
allow_heredoc?()
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 189 def allow_heredoc? allowed_heredoc end
allow_uri?()
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 222 def allow_uri? cop_config['AllowURI'] end
allowed_heredoc()
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 193 def allowed_heredoc cop_config['AllowHeredoc'] end
allowed_uri_position?(line, uri_range)
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 230 def allowed_uri_position?(line, uri_range) uri_range.begin < max && (uri_range.end == line_length(line) || uri_range.end == line_length(line) - 1) end
breakable_nodes_by_line_index()
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 94 def breakable_nodes_by_line_index @breakable_nodes_by_line_index ||= {} end
breakable_range(line, line_index)
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 153 def breakable_range(line, line_index) return if line_in_heredoc?(line_index + 1) semicolon_range = breakable_semicolon_range(line, line_index) return semicolon_range if semicolon_range breakable_node = breakable_nodes_by_line_index[line_index] return breakable_node.source_range if breakable_node end
breakable_semicolon_range(line, line_index)
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 163 def breakable_semicolon_range(line, line_index) semicolon_separated_parts = line.split(';') return if semicolon_separated_parts.length <= 1 column = semicolon_separated_parts.first.length + 1 range = source_range(processed_source.buffer, line_index, column, 1) return if processed_source.commented?(range) range end
check_directive_line(line, line_index)
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 269 def check_directive_line(line, line_index) return if line_length_without_directive(line) <= max range = max..(line_length_without_directive(line) - 1) register_offense( source_range( processed_source.buffer, line_index + 1, range ), line, line_index ) end
check_for_breakable_node(node)
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 86 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 breakable_nodes_by_line_index[line_index] = breakable_node end
check_line(line, line_index)
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 120 def check_line(line, line_index) return if line_length(line) <= max return if ignored_line?(line, line_index) if ignore_cop_directives? && directive_on_source_line?(line_index) return check_directive_line(line, line_index) end return check_uri_line(line, line_index) if allow_uri? register_offense( source_range( processed_source.buffer, line_index, highlight_start(line)...line_length(line) ), line, line_index ) end
check_uri_line(line, line_index)
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 301 def check_uri_line(line, line_index) uri_range = find_excessive_uri_range(line) return if uri_range && allowed_uri_position?(line, uri_range) register_offense( excess_range(uri_range, line, line_index), line, line_index ) end
directive_on_source_line?(line_index)
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 284 def directive_on_source_line?(line_index) source_line_number = line_index + processed_source.buffer.first_line comment = processed_source .comments .detect { |e| e.location.line == source_line_number } return false unless comment comment.text.match(CommentConfig::COMMENT_DIRECTIVE_REGEXP) end
excess_range(uri_range, line, line_index)
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 174 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)
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 197 def extract_heredocs(ast) return [] unless ast ast.each_node(:str, :dstr, :xstr).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
find_excessive_uri_range(line)
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 236 def find_excessive_uri_range(line) last_uri_match = match_uris(line).last return nil unless last_uri_match begin_position, end_position = last_uri_match.offset(0).map do |pos| pos + indentation_difference(line) end return nil if begin_position < max && end_position < max begin_position...end_position end
heredocs()
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 98 def heredocs @heredocs ||= extract_heredocs(processed_source.ast) end
highlight_start(line)
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 116 def highlight_start(line) max - indentation_difference(line) end
ignore_cop_directives?()
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 226 def ignore_cop_directives? cop_config['IgnoreCopDirectives'] end
ignored_line?(line, line_index)
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 139 def ignored_line?(line, line_index) matches_ignored_pattern?(line) || heredocs && line_in_permitted_heredoc?(line_index.succ) end
indentation_difference(line)
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 106 def indentation_difference(line) return 0 unless tab_indentation_width line.match(/^\t*/)[0].size * (tab_indentation_width - 1) end
line_in_heredoc?(line_number)
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 216 def line_in_heredoc?(line_number) heredocs.any? do |range, _delimiter| range.cover?(line_number) end end
line_in_permitted_heredoc?(line_number)
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 207 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
line_length(line)
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 112 def line_length(line) line.length + indentation_difference(line) end
line_length_without_directive(line)
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 296 def line_length_without_directive(line) before_comment, = line.split(CommentConfig::COMMENT_DIRECTIVE_REGEXP) before_comment.rstrip.length end
match_uris(string)
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 249 def match_uris(string) matches = [] string.scan(uri_regexp) do matches << $LAST_MATCH_INFO if valid_uri?($LAST_MATCH_INFO[0]) end matches end
max()
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 185 def max cop_config['Max'] end
register_offense(loc, line, line_index)
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 144 def register_offense(loc, line, line_index) message = format(MSG, length: line_length(line), max: max) breakable_range = breakable_range(line, line_index) add_offense(breakable_range, location: loc, message: message) do self.max = line_length(line) end end
tab_indentation_width()
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 102 def tab_indentation_width config.for_cop('Layout/Tab')['IndentationWidth'] end
uri_regexp()
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 264 def uri_regexp @uri_regexp ||= URI::DEFAULT_PARSER.make_regexp(cop_config['URISchemes']) end
valid_uri?(uri_ish_string)
click to toggle source
# File lib/rubocop/cop/metrics/line_length.rb, line 257 def valid_uri?(uri_ish_string) URI.parse(uri_ish_string) true rescue URI::InvalidURIError, NoMethodError false end