class RuboCop::Cop::Style::RedundantLineContinuation
Check for redundant line continuation.
This cop marks a line continuation as redundant if removing the backslash does not result in a syntax error. However, a backslash at the end of a comment or for string concatenation is not redundant and is not considered an offense.
@example
# bad foo. \ bar foo \ &.bar \ .baz # good foo. bar foo &.bar .baz # bad [foo, \ bar] {foo: \ bar} # good [foo, bar] {foo: bar} # bad foo(bar, \ baz) # good foo(bar, baz) # also good - backslash in string concatenation is not redundant foo('bar' \ 'baz') # also good - backslash at the end of a comment is not redundant foo(bar, # \ baz) # also good - backslash at the line following the newline begins with a + or -, # it is not redundant 1 \ + 2 \ - 3 # also good - backslash with newline between the method name and its arguments, # it is not redundant. some_method \ (argument)
Constants
- ALLOWED_STRING_TOKENS
- ARGUMENT_TAKING_FLOW_TOKEN_TYPES
- ARGUMENT_TYPES
- LINE_CONTINUATION
- LINE_CONTINUATION_PATTERN
- MSG
Public Instance Methods
on_new_investigation()
click to toggle source
# File lib/rubocop/cop/style/redundant_line_continuation.rb, line 81 def on_new_investigation return unless processed_source.ast each_match_range(processed_source.ast.source_range, LINE_CONTINUATION_PATTERN) do |range| next if require_line_continuation?(range) next unless redundant_line_continuation?(range) add_offense(range) do |corrector| corrector.remove_leading(range, 1) end end inspect_eof_line_continuation end
Private Instance Methods
argument_is_method?(node)
click to toggle source
# File lib/rubocop/cop/style/redundant_line_continuation.rb, line 201 def argument_is_method?(node) return false unless node.send_type? return false unless (first_argument = node.first_argument) method_call_with_arguments?(first_argument) end
argument_newline?(node)
click to toggle source
rubocop:disable Metrics/AbcSize
# File lib/rubocop/cop/style/redundant_line_continuation.rb, line 165 def argument_newline?(node) node = node.to_a.last if node.assignment? return false if node.parenthesized_call? node = node.children.first if node.root? && node.begin_type? if argument_is_method?(node) argument_newline?(node.first_argument) else return false unless method_call_with_arguments?(node) node.loc.selector.line != node.first_argument.loc.line end end
ends_with_backslash_without_comment?(source_line)
click to toggle source
# File lib/rubocop/cop/style/redundant_line_continuation.rb, line 106 def ends_with_backslash_without_comment?(source_line) source_line.gsub(/#.+/, '').end_with?('\\') end
find_node_for_line(last_line)
click to toggle source
rubocop:enable Metrics/AbcSize
# File lib/rubocop/cop/style/redundant_line_continuation.rb, line 181 def find_node_for_line(last_line) processed_source.ast.each_node do |node| return node if node.respond_to?(:expression) && node.expression&.last_line == last_line end end
inside_string_literal?(range, token)
click to toggle source
# File lib/rubocop/cop/style/redundant_line_continuation.rb, line 150 def inside_string_literal?(range, token) ALLOWED_STRING_TOKENS.include?(token.type) && token.pos.overlaps?(range) end
inside_string_literal_or_method_with_argument?(range)
click to toggle source
# File lib/rubocop/cop/style/redundant_line_continuation.rb, line 114 def inside_string_literal_or_method_with_argument?(range) processed_source.tokens.each_cons(2).any? do |token, next_token| next if token.line == next_token.line inside_string_literal?(range, token) || method_with_argument?(token, next_token) end end
inspect_eof_line_continuation()
click to toggle source
# File lib/rubocop/cop/style/redundant_line_continuation.rb, line 139 def inspect_eof_line_continuation return unless processed_source.raw_source.end_with?(LINE_CONTINUATION) rindex = processed_source.raw_source.rindex(LINE_CONTINUATION) line_continuation_range = range_between(rindex, rindex + 1) add_offense(line_continuation_range) do |corrector| corrector.remove_trailing(line_continuation_range, 1) end end
leading_dot_method_chain_with_blank_line?(range)
click to toggle source
# File lib/rubocop/cop/style/redundant_line_continuation.rb, line 122 def leading_dot_method_chain_with_blank_line?(range) return false unless range.source_line.strip.start_with?('.', '&.') processed_source[range.line].strip.empty? end
method_call_with_arguments?(node)
click to toggle source
# File lib/rubocop/cop/style/redundant_line_continuation.rb, line 208 def method_call_with_arguments?(node) node.call_type? && !node.arguments.empty? end
method_with_argument?(current_token, next_token)
click to toggle source
A method call without parentheses such as the following cannot remove ‘`:
do_something \ argument
# File lib/rubocop/cop/style/redundant_line_continuation.rb, line 158 def method_with_argument?(current_token, next_token) return false unless ARGUMENT_TAKING_FLOW_TOKEN_TYPES.include?(current_token.type) ARGUMENT_TYPES.include?(next_token.type) end
redundant_line_continuation?(range)
click to toggle source
# File lib/rubocop/cop/style/redundant_line_continuation.rb, line 128 def redundant_line_continuation?(range) return true unless (node = find_node_for_line(range.last_line)) return false if argument_newline?(node) source = node.source while (node = node.parent) source = node.source end parse(source.gsub("\\\n", "\n")).valid_syntax? end
require_line_continuation?(range)
click to toggle source
# File lib/rubocop/cop/style/redundant_line_continuation.rb, line 98 def require_line_continuation?(range) !ends_with_backslash_without_comment?(range.source_line) || string_concatenation?(range.source_line) || start_with_arithmetic_operator?(processed_source[range.line]) || inside_string_literal_or_method_with_argument?(range) || leading_dot_method_chain_with_blank_line?(range) end
same_line?(node, line)
click to toggle source
# File lib/rubocop/cop/style/redundant_line_continuation.rb, line 187 def same_line?(node, line) return false unless (source_range = node.source_range) if node.is_a?(AST::StrNode) if node.heredoc? (node.loc.heredoc_body.line..node.loc.heredoc_body.last_line).cover?(line) else (source_range.line..source_range.last_line).cover?(line) end else source_range.line == line end end
start_with_arithmetic_operator?(source_line)
click to toggle source
# File lib/rubocop/cop/style/redundant_line_continuation.rb, line 212 def start_with_arithmetic_operator?(source_line) %r{\A\s*[+\-*/%]}.match?(source_line) end
string_concatenation?(source_line)
click to toggle source
# File lib/rubocop/cop/style/redundant_line_continuation.rb, line 110 def string_concatenation?(source_line) /["']\s*\\\z/.match?(source_line) end