Module: RuboCop::Cop::AutocorrectLogic
Overview
This module encapsulates the logic for autocorrect behavior for a cop.
Instance Attribute Summary
- #autocorrect? ⇒ Boolean readonly
- #autocorrect_enabled? ⇒ Boolean readonly
- #autocorrect_requested? ⇒ Boolean readonly
- #autocorrect_with_disable_uncorrectable? ⇒ Boolean readonly
- #correctable? ⇒ Boolean readonly
- #disable_uncorrectable? ⇒ Boolean readonly
- #safe_autocorrect? ⇒ Boolean readonly
-
#skipped_unsafe_correction_with_disable_uncorrectable? ⇒ Boolean
readonly
Whether a correction exists but is skipped because it is unsafe in a safe autocorrect run, while
--disable-uncorrectableasks for a todo comment on everything this run cannot correct. -
#contextual_autocorrect_held_back? ⇒ Boolean
readonly
private
When LSP is enabled or the
--editor-modeoption is on, it is considered as editing source code, and autocorrection withAutoCorrect: contextualwill not be performed.
Instance Method Summary
- #disable_offense(offense_range) private
- #disable_offense_at_end_of_line(range) private
- #disable_offense_before_and_after(range_by_lines) private
- #disable_offense_with_eol_or_surround_comment(range) private
- #eol_comment private
- #eol_comment_would_be_inside_literal?(offense_range, literal_range) ⇒ Boolean private
- #heredoc_range(node) private
- #line_with_eol_comment_too_long?(range) ⇒ Boolean private
- #max_line_length private
- #multiline_ranges(offense_range) private
- #multiline_string?(node) ⇒ Boolean private
-
#range_by_lines(range)
private
Expand the given range to include all of any lines it covers.
- #range_of_first_line(range) private
- #string_continuation?(node) ⇒ Boolean private
- #surrounding_heredoc?(node) ⇒ Boolean private
- #surrounding_percent_array?(node) ⇒ Boolean private
Instance Attribute Details
#autocorrect? ⇒ Boolean (readonly)
[ GitHub ]
# File 'lib/rubocop/cop/autocorrect_logic.rb', line 7
def autocorrect? autocorrect_requested? && correctable? && autocorrect_enabled? end
#autocorrect_enabled? ⇒ Boolean (readonly)
[ GitHub ]
# File 'lib/rubocop/cop/autocorrect_logic.rb', line 39
def autocorrect_enabled? # allow turning off autocorrect on a cop by cop basis return true unless cop_config return false if disabled_autocorrect? return false if contextual_autocorrect_held_back? # :safe_autocorrect is a derived option based on several command-line # arguments - see RuboCop::Options#add_autocorrection_options return safe_autocorrect? if @options.fetch(:safe_autocorrect, false) true end
#autocorrect_requested? ⇒ Boolean (readonly)
[ GitHub ]
# File 'lib/rubocop/cop/autocorrect_logic.rb', line 23
def autocorrect_requested? @options.fetch(:autocorrect, false) end
#autocorrect_with_disable_uncorrectable? ⇒ Boolean (readonly)
[ GitHub ]
# File 'lib/rubocop/cop/autocorrect_logic.rb', line 11
def autocorrect_with_disable_uncorrectable? autocorrect_requested? && disable_uncorrectable? && autocorrect_enabled? end
#contextual_autocorrect_held_back? ⇒ Boolean (readonly, private)
When LSP is enabled or the --editor-mode option is on, it is considered as editing
source code, and autocorrection with AutoCorrect: contextual will not be performed.
The editing option says the same without the rest of LSP mode, which
is about showing offenses in an editor.
#correctable? ⇒ Boolean (readonly)
[ GitHub ]
# File 'lib/rubocop/cop/autocorrect_logic.rb', line 27
def correctable? self.class.support_autocorrect? || disable_uncorrectable? end
#disable_uncorrectable? ⇒ Boolean (readonly)
[ GitHub ]
# File 'lib/rubocop/cop/autocorrect_logic.rb', line 31
def disable_uncorrectable? @options[:disable_uncorrectable] == true end
#safe_autocorrect? ⇒ Boolean (readonly)
[ GitHub ]
# File 'lib/rubocop/cop/autocorrect_logic.rb', line 35
def safe_autocorrect? cop_config.fetch('Safe', true) && cop_config.fetch('SafeAutoCorrect', true) end
#skipped_unsafe_correction_with_disable_uncorrectable? ⇒ Boolean (readonly)
Whether a correction exists but is skipped because it is unsafe in a
safe autocorrect run, while --disable-uncorrectable asks for a todo
comment on everything this run cannot correct.
# File 'lib/rubocop/cop/autocorrect_logic.rb', line 18
def skipped_unsafe_correction_with_disable_uncorrectable? autocorrect_requested? && disable_uncorrectable? && @options.fetch(:safe_autocorrect, false) && !safe_autocorrect? end
Instance Method Details
#disable_offense(offense_range) (private)
[ GitHub ]# File 'lib/rubocop/cop/autocorrect_logic.rb', line 64
def disable_offense(offense_range) unbreakable_range = multiline_ranges(offense_range)&.find do |range| offense_range.overlaps?(range) && eol_comment_would_be_inside_literal?(offense_range, range) end if unbreakable_range disable_offense_before_and_after(range_by_lines(unbreakable_range)) else disable_offense_with_eol_or_surround_comment(offense_range) end end
#disable_offense_at_end_of_line(range) (private)
[ GitHub ]# File 'lib/rubocop/cop/autocorrect_logic.rb', line 157
def disable_offense_at_end_of_line(range) Corrector.new(range).insert_after(range, eol_comment) end
#disable_offense_before_and_after(range_by_lines) (private)
[ GitHub ]# File 'lib/rubocop/cop/autocorrect_logic.rb', line 165
def disable_offense_before_and_after(range_by_lines) range_with_newline = range_by_lines.resize(range_by_lines.size + 1) leading_whitespace = range_by_lines.source_line[/^\s*/] Corrector.new(range_by_lines).wrap( range_with_newline, "#{leading_whitespace}# rubocop:todo #{cop_name}\n", "#{leading_whitespace}# rubocop:enable #{cop_name}\n" ) end
#disable_offense_with_eol_or_surround_comment(range) (private)
[ GitHub ]# File 'lib/rubocop/cop/autocorrect_logic.rb', line 91
def disable_offense_with_eol_or_surround_comment(range) if line_with_eol_comment_too_long?(range) disable_offense_before_and_after(range_by_lines(range)) else disable_offense_at_end_of_line(range_of_first_line(range)) end end
#eol_comment (private)
[ GitHub ]# File 'lib/rubocop/cop/autocorrect_logic.rb', line 161
def eol_comment " # rubocop:todo #{cop_name}" end
#eol_comment_would_be_inside_literal?(offense_range, literal_range) ⇒ Boolean (private)
# File 'lib/rubocop/cop/autocorrect_logic.rb', line 99
def eol_comment_would_be_inside_literal?(offense_range, literal_range) return true if line_with_eol_comment_too_long?(offense_range) offense_line = offense_range.line offense_line >= literal_range.first_line && offense_line < literal_range.last_line end
#heredoc_range(node) (private)
[ GitHub ]# File 'lib/rubocop/cop/autocorrect_logic.rb', line 116
def heredoc_range(node) node.source_range.join(node.loc.heredoc_end) end
#line_with_eol_comment_too_long?(range) ⇒ Boolean (private)
# File 'lib/rubocop/cop/autocorrect_logic.rb', line 106
def line_with_eol_comment_too_long?(range) return false unless max_line_length (range.source_line + eol_comment).length > max_line_length end
#max_line_length (private)
[ GitHub ]#multiline_ranges(offense_range) (private)
[ GitHub ]# File 'lib/rubocop/cop/autocorrect_logic.rb', line 77
def multiline_ranges(offense_range) return if offense_range.empty? processed_source.ast.each_node.filter_map do |node| if surrounding_heredoc?(node) heredoc_range(node) elsif string_continuation?(node) range_by_lines(node.source_range) elsif surrounding_percent_array?(node) || multiline_string?(node) node.source_range end end end
#multiline_string?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/autocorrect_logic.rb', line 128
def multiline_string?(node) node.dstr_type? && node.multiline? end
#range_by_lines(range) (private)
Expand the given range to include all of any lines it covers. Does not include newline at end of the last line.
# File 'lib/rubocop/cop/autocorrect_logic.rb', line 141
def range_by_lines(range) begin_of_first_line = range.begin_pos - range.column last_line = range.source_buffer.source_line(range.last_line) last_line_offset = last_line.length - range.last_column end_of_last_line = range.end_pos + last_line_offset Parser::Source::Range.new(range.source_buffer, begin_of_first_line, end_of_last_line) end
#range_of_first_line(range) (private)
[ GitHub ]# File 'lib/rubocop/cop/autocorrect_logic.rb', line 132
def range_of_first_line(range) begin_of_first_line = range.begin_pos - range.column end_of_first_line = begin_of_first_line + range.source_line.length Parser::Source::Range.new(range.source_buffer, begin_of_first_line, end_of_first_line) end
#string_continuation?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/autocorrect_logic.rb', line 124
def string_continuation?(node) node.any_str_type? && node.source.match?(/\\\s*$/) end
#surrounding_heredoc?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/autocorrect_logic.rb', line 112
def surrounding_heredoc?(node) node.any_str_type? && node.heredoc? end
#surrounding_percent_array?(node) ⇒ Boolean (private)
# File 'lib/rubocop/cop/autocorrect_logic.rb', line 120
def surrounding_percent_array?(node) node.array_type? && node.percent_literal? end