rubocop 0.85.0 → 0.88.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +25 -17
- data/bin/rubocop-profile +31 -0
- data/config/default.yml +132 -11
- data/lib/rubocop.rb +17 -1
- data/lib/rubocop/cli.rb +2 -4
- data/lib/rubocop/cli/command/auto_genenerate_config.rb +42 -7
- data/lib/rubocop/cli/command/init_dotfile.rb +1 -1
- data/lib/rubocop/cli/command/show_cops.rb +1 -1
- data/lib/rubocop/config.rb +1 -1
- data/lib/rubocop/config_loader.rb +39 -67
- data/lib/rubocop/config_loader_resolver.rb +1 -1
- data/lib/rubocop/config_obsoletion.rb +0 -1
- data/lib/rubocop/config_store.rb +4 -0
- data/lib/rubocop/cop/autocorrect_logic.rb +14 -24
- data/lib/rubocop/cop/badge.rb +1 -1
- data/lib/rubocop/cop/base.rb +407 -0
- data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +10 -20
- data/lib/rubocop/cop/commissioner.rb +48 -50
- data/lib/rubocop/cop/cop.rb +91 -235
- data/lib/rubocop/cop/corrector.rb +38 -115
- data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +26 -0
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +7 -2
- data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +1 -1
- data/lib/rubocop/cop/generator.rb +1 -1
- data/lib/rubocop/cop/generator/configuration_injector.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +11 -14
- data/lib/rubocop/cop/layout/case_indentation.rb +18 -19
- data/lib/rubocop/cop/layout/class_structure.rb +2 -37
- data/lib/rubocop/cop/layout/comment_indentation.rb +3 -3
- data/lib/rubocop/cop/layout/empty_comment.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +1 -0
- data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +3 -8
- data/lib/rubocop/cop/layout/end_alignment.rb +3 -2
- data/lib/rubocop/cop/layout/end_of_line.rb +1 -1
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +5 -1
- data/lib/rubocop/cop/layout/first_array_element_line_break.rb +1 -1
- data/lib/rubocop/cop/layout/hash_alignment.rb +2 -3
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +17 -7
- data/lib/rubocop/cop/layout/space_after_colon.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +22 -27
- data/lib/rubocop/cop/layout/space_around_keyword.rb +2 -2
- data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +27 -68
- data/lib/rubocop/cop/layout/space_around_operators.rb +1 -1
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +14 -0
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +4 -3
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +2 -2
- data/lib/rubocop/cop/legacy/corrections_proxy.rb +49 -0
- data/lib/rubocop/cop/legacy/corrector.rb +29 -0
- data/lib/rubocop/cop/lint/constant_resolution.rb +89 -0
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +4 -4
- data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +8 -2
- data/lib/rubocop/cop/lint/duplicate_elsif_condition.rb +39 -0
- data/lib/rubocop/cop/lint/duplicate_methods.rb +2 -2
- data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +38 -2
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +3 -2
- data/lib/rubocop/cop/lint/interpolation_check.rb +13 -0
- data/lib/rubocop/cop/lint/literal_as_condition.rb +11 -1
- data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +8 -1
- data/lib/rubocop/cop/lint/nested_method_definition.rb +14 -20
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +69 -2
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +8 -3
- data/lib/rubocop/cop/lint/percent_string_array.rb +1 -1
- data/lib/rubocop/cop/lint/percent_symbol_array.rb +1 -1
- data/lib/rubocop/cop/lint/raise_exception.rb +12 -4
- data/lib/rubocop/cop/lint/rand_one.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +31 -25
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +2 -2
- data/lib/rubocop/cop/lint/regexp_as_condition.rb +6 -0
- data/lib/rubocop/cop/lint/safe_navigation_with_empty.rb +9 -1
- data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
- data/lib/rubocop/cop/lint/syntax.rb +11 -26
- data/lib/rubocop/cop/lint/unused_method_argument.rb +1 -1
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +1 -1
- data/lib/rubocop/cop/metrics/block_length.rb +22 -0
- data/lib/rubocop/cop/metrics/class_length.rb +25 -2
- data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +35 -3
- data/lib/rubocop/cop/metrics/method_length.rb +23 -0
- data/lib/rubocop/cop/metrics/module_length.rb +25 -2
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +129 -0
- data/lib/rubocop/cop/metrics/utils/iterating_block.rb +61 -0
- data/lib/rubocop/cop/mixin/allowed_methods.rb +19 -0
- data/lib/rubocop/cop/mixin/auto_corrector.rb +12 -0
- data/lib/rubocop/cop/mixin/code_length.rb +4 -0
- data/lib/rubocop/cop/mixin/configurable_formatting.rb +1 -1
- data/lib/rubocop/cop/mixin/configurable_naming.rb +1 -1
- data/lib/rubocop/cop/mixin/documentation_comment.rb +2 -2
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/enforce_superclass.rb +3 -1
- data/lib/rubocop/cop/mixin/first_element_line_break.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
- data/lib/rubocop/cop/mixin/nil_methods.rb +3 -5
- data/lib/rubocop/cop/mixin/ordered_gem_node.rb +6 -1
- data/lib/rubocop/cop/mixin/parentheses.rb +1 -2
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/range_help.rb +1 -1
- data/lib/rubocop/cop/mixin/regexp_literal_help.rb +27 -0
- data/lib/rubocop/cop/mixin/statement_modifier.rb +3 -3
- data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
- data/lib/rubocop/cop/mixin/surrounding_space.rb +10 -5
- data/lib/rubocop/cop/mixin/too_many_lines.rb +3 -13
- data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -1
- data/lib/rubocop/cop/mixin/uncommunicative_name.rb +6 -4
- data/lib/rubocop/cop/mixin/visibility_help.rb +50 -0
- data/lib/rubocop/cop/naming/ascii_identifiers.rb +27 -4
- data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +3 -3
- data/lib/rubocop/cop/naming/file_name.rb +1 -3
- data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +1 -1
- data/lib/rubocop/cop/naming/method_name.rb +1 -1
- data/lib/rubocop/cop/naming/method_parameter_name.rb +1 -1
- data/lib/rubocop/cop/naming/predicate_name.rb +3 -5
- data/lib/rubocop/cop/naming/variable_name.rb +1 -1
- data/lib/rubocop/cop/naming/variable_number.rb +1 -1
- data/lib/rubocop/cop/offense.rb +16 -2
- data/lib/rubocop/cop/registry.rb +62 -7
- data/lib/rubocop/cop/style/accessor_grouping.rb +147 -0
- data/lib/rubocop/cop/style/array_coercion.rb +63 -0
- data/lib/rubocop/cop/style/auto_resource_cleanup.rb +3 -2
- data/lib/rubocop/cop/style/bare_percent_literals.rb +1 -1
- data/lib/rubocop/cop/style/bisected_attr_accessor.rb +146 -0
- data/lib/rubocop/cop/style/block_delimiters.rb +2 -4
- data/lib/rubocop/cop/style/case_like_if.rb +217 -0
- data/lib/rubocop/cop/style/class_and_module_children.rb +1 -1
- data/lib/rubocop/cop/style/class_vars.rb +21 -0
- data/lib/rubocop/cop/style/command_literal.rb +1 -1
- data/lib/rubocop/cop/style/commented_keyword.rb +5 -2
- data/lib/rubocop/cop/style/conditional_assignment.rb +2 -2
- data/lib/rubocop/cop/style/copyright.rb +3 -3
- data/lib/rubocop/cop/style/date_time.rb +1 -1
- data/lib/rubocop/cop/style/dir.rb +2 -2
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +1 -1
- data/lib/rubocop/cop/style/documentation.rb +2 -2
- data/lib/rubocop/cop/style/empty_case_condition.rb +8 -6
- data/lib/rubocop/cop/style/empty_literal.rb +5 -5
- data/lib/rubocop/cop/style/encoding.rb +1 -1
- data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -2
- data/lib/rubocop/cop/style/exponential_notation.rb +8 -10
- data/lib/rubocop/cop/style/float_division.rb +7 -10
- data/lib/rubocop/cop/style/format_string_token.rb +5 -5
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
- data/lib/rubocop/cop/style/hash_as_last_array_item.rb +62 -0
- data/lib/rubocop/cop/style/hash_like_case.rb +76 -0
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +1 -1
- data/lib/rubocop/cop/style/if_inside_else.rb +1 -1
- data/lib/rubocop/cop/style/if_unless_modifier.rb +11 -11
- data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +12 -0
- data/lib/rubocop/cop/style/inverse_methods.rb +1 -1
- data/lib/rubocop/cop/style/ip_addresses.rb +1 -1
- data/lib/rubocop/cop/style/missing_else.rb +1 -11
- data/lib/rubocop/cop/style/multiline_block_chain.rb +10 -1
- data/lib/rubocop/cop/style/multiline_if_then.rb +1 -1
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +17 -6
- data/lib/rubocop/cop/style/mutable_constant.rb +4 -4
- data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +2 -5
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +27 -0
- data/lib/rubocop/cop/style/next.rb +2 -2
- data/lib/rubocop/cop/style/numeric_literal_prefix.rb +2 -2
- data/lib/rubocop/cop/style/numeric_predicate.rb +3 -4
- data/lib/rubocop/cop/style/parallel_assignment.rb +3 -3
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
- data/lib/rubocop/cop/style/proc.rb +1 -1
- data/lib/rubocop/cop/style/random_with_offset.rb +4 -10
- data/lib/rubocop/cop/style/redundant_assignment.rb +117 -0
- data/lib/rubocop/cop/style/redundant_conditional.rb +4 -3
- data/lib/rubocop/cop/style/redundant_exception.rb +14 -10
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +122 -0
- data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +50 -0
- data/lib/rubocop/cop/style/redundant_freeze.rb +1 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +8 -2
- data/lib/rubocop/cop/style/redundant_percent_q.rb +2 -2
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +4 -3
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +14 -23
- data/lib/rubocop/cop/style/redundant_self.rb +6 -9
- data/lib/rubocop/cop/style/redundant_sort.rb +3 -2
- data/lib/rubocop/cop/style/rescue_standard_error.rb +1 -1
- data/lib/rubocop/cop/style/sample.rb +1 -1
- data/lib/rubocop/cop/style/semicolon.rb +1 -1
- data/lib/rubocop/cop/style/signal_exception.rb +1 -1
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +3 -2
- data/lib/rubocop/cop/style/stderr_puts.rb +1 -1
- data/lib/rubocop/cop/style/struct_inheritance.rb +23 -2
- data/lib/rubocop/cop/style/symbol_array.rb +5 -5
- data/lib/rubocop/cop/style/symbol_proc.rb +1 -1
- data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/trailing_method_end_statement.rb +9 -32
- data/lib/rubocop/cop/style/trivial_accessors.rb +8 -7
- data/lib/rubocop/cop/style/word_array.rb +1 -1
- data/lib/rubocop/cop/style/yoda_condition.rb +18 -1
- data/lib/rubocop/cop/style/zero_length_predicate.rb +2 -2
- data/lib/rubocop/cop/team.rb +105 -81
- data/lib/rubocop/cop/util.rb +2 -2
- data/lib/rubocop/cop/utils/format_string.rb +19 -2
- data/lib/rubocop/cop/variable_force/variable.rb +5 -3
- data/lib/rubocop/file_finder.rb +12 -12
- data/lib/rubocop/formatter/disabled_config_formatter.rb +2 -2
- data/lib/rubocop/formatter/formatter_set.rb +1 -1
- data/lib/rubocop/name_similarity.rb +7 -3
- data/lib/rubocop/options.rb +15 -8
- data/lib/rubocop/path_util.rb +4 -19
- data/lib/rubocop/platform.rb +1 -1
- data/lib/rubocop/rake_task.rb +6 -9
- data/lib/rubocop/result_cache.rb +12 -8
- data/lib/rubocop/rspec/cop_helper.rb +4 -4
- data/lib/rubocop/rspec/expect_offense.rb +65 -21
- data/lib/rubocop/rspec/shared_contexts.rb +19 -16
- data/lib/rubocop/runner.rb +34 -33
- data/lib/rubocop/target_finder.rb +3 -3
- data/lib/rubocop/target_ruby.rb +2 -2
- data/lib/rubocop/version.rb +1 -1
- metadata +34 -9
- data/lib/rubocop/cop/mixin/classish_length.rb +0 -37
data/lib/rubocop/cop/util.rb
CHANGED
@@ -14,7 +14,7 @@ module RuboCop
|
|
14
14
|
module_function
|
15
15
|
|
16
16
|
def comment_line?(line_source)
|
17
|
-
|
17
|
+
/^\s*#/.match?(line_source)
|
18
18
|
end
|
19
19
|
|
20
20
|
def comment_lines?(node)
|
@@ -88,7 +88,7 @@ module RuboCop
|
|
88
88
|
|
89
89
|
# Regex matches IF there is a ' or there is a \\ in the string that is
|
90
90
|
# not preceded/followed by another \\ (e.g. "\\x34") but not "\\\\".
|
91
|
-
|
91
|
+
/'|(?<! \\) \\{2}* \\ (?![\\"])/x.match?(string)
|
92
92
|
end
|
93
93
|
|
94
94
|
def needs_escaping?(string)
|
@@ -41,8 +41,7 @@ module RuboCop
|
|
41
41
|
#
|
42
42
|
# @see https://ruby-doc.org/core-2.6.3/Kernel.html#method-i-format
|
43
43
|
class FormatSequence
|
44
|
-
attr_reader :begin_pos, :end_pos
|
45
|
-
attr_reader :flags, :width, :precision, :name, :type
|
44
|
+
attr_reader :begin_pos, :end_pos, :flags, :width, :precision, :name, :type
|
46
45
|
|
47
46
|
def initialize(match)
|
48
47
|
@source = match[0]
|
@@ -97,6 +96,10 @@ module RuboCop
|
|
97
96
|
@format_sequences ||= parse
|
98
97
|
end
|
99
98
|
|
99
|
+
def valid?
|
100
|
+
!mixed_formats?
|
101
|
+
end
|
102
|
+
|
100
103
|
def named_interpolation?
|
101
104
|
format_sequences.any?(&:name)
|
102
105
|
end
|
@@ -114,6 +117,20 @@ module RuboCop
|
|
114
117
|
)
|
115
118
|
end
|
116
119
|
end
|
120
|
+
|
121
|
+
def mixed_formats?
|
122
|
+
formats = format_sequences.reject(&:percent?).map do |seq|
|
123
|
+
if seq.name
|
124
|
+
:named
|
125
|
+
elsif seq.max_digit_dollar_num
|
126
|
+
:numbered
|
127
|
+
else
|
128
|
+
:unnumbered
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
formats.uniq.size > 1
|
133
|
+
end
|
117
134
|
end
|
118
135
|
end
|
119
136
|
end
|
@@ -42,10 +42,10 @@ module RuboCop
|
|
42
42
|
def reference!(node)
|
43
43
|
reference = Reference.new(node, @scope)
|
44
44
|
@references << reference
|
45
|
-
consumed_branches =
|
45
|
+
consumed_branches = nil
|
46
46
|
|
47
47
|
@assignments.reverse_each do |assignment|
|
48
|
-
next if consumed_branches
|
48
|
+
next if consumed_branches&.include?(assignment.branch)
|
49
49
|
|
50
50
|
assignment.reference!(node) unless assignment.run_exclusively_with?(reference)
|
51
51
|
|
@@ -58,7 +58,9 @@ module RuboCop
|
|
58
58
|
|
59
59
|
break if !assignment.branch || assignment.branch == reference.branch
|
60
60
|
|
61
|
-
|
61
|
+
unless assignment.branch.may_run_incompletely?
|
62
|
+
(consumed_branches ||= Set.new) << assignment.branch
|
63
|
+
end
|
62
64
|
end
|
63
65
|
end
|
64
66
|
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
data/lib/rubocop/file_finder.rb
CHANGED
@@ -9,33 +9,33 @@ module RuboCop
|
|
9
9
|
@root_level = level
|
10
10
|
end
|
11
11
|
|
12
|
-
def self.root_level?(path)
|
13
|
-
@root_level == path.to_s
|
12
|
+
def self.root_level?(path, stop_dir)
|
13
|
+
(@root_level || stop_dir) == path.to_s
|
14
14
|
end
|
15
15
|
|
16
|
-
def find_file_upwards(filename, start_dir)
|
17
|
-
traverse_files_upwards(filename, start_dir) do |file|
|
16
|
+
def find_file_upwards(filename, start_dir, stop_dir = nil)
|
17
|
+
traverse_files_upwards(filename, start_dir, stop_dir) do |file|
|
18
18
|
# minimize iteration for performance
|
19
19
|
return file if file
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
def
|
24
|
-
|
25
|
-
traverse_files_upwards(filename, start_dir) do |file|
|
26
|
-
|
23
|
+
def find_last_file_upwards(filename, start_dir, stop_dir = nil)
|
24
|
+
last_file = nil
|
25
|
+
traverse_files_upwards(filename, start_dir, stop_dir) do |file|
|
26
|
+
last_file = file
|
27
27
|
end
|
28
|
-
|
28
|
+
last_file
|
29
29
|
end
|
30
30
|
|
31
31
|
private
|
32
32
|
|
33
|
-
def traverse_files_upwards(filename, start_dir)
|
33
|
+
def traverse_files_upwards(filename, start_dir, stop_dir)
|
34
34
|
Pathname.new(start_dir).expand_path.ascend do |dir|
|
35
|
-
break if FileFinder.root_level?(dir)
|
36
|
-
|
37
35
|
file = dir + filename
|
38
36
|
yield(file.to_s) if file.exist?
|
37
|
+
|
38
|
+
break if FileFinder.root_level?(dir, stop_dir)
|
39
39
|
end
|
40
40
|
end
|
41
41
|
end
|
@@ -74,7 +74,7 @@ module RuboCop
|
|
74
74
|
end
|
75
75
|
|
76
76
|
def timestamp
|
77
|
-
@options[:no_auto_gen_timestamp] ? '' : "on #{Time.now} "
|
77
|
+
@options[:no_auto_gen_timestamp] ? '' : "on #{Time.now.utc} "
|
78
78
|
end
|
79
79
|
|
80
80
|
def output_offenses
|
@@ -115,7 +115,7 @@ module RuboCop
|
|
115
115
|
output_buffer.puts "# Offense count: #{offense_count}" if @show_offense_counts
|
116
116
|
|
117
117
|
cop_class = Cop::Cop.registry.find_by_cop_name(cop_name)
|
118
|
-
output_buffer.puts '# Cop supports --auto-correct.' if cop_class&.
|
118
|
+
output_buffer.puts '# Cop supports --auto-correct.' if cop_class&.support_autocorrect?
|
119
119
|
|
120
120
|
default_cfg = default_config(cop_name)
|
121
121
|
return unless default_cfg
|
@@ -82,7 +82,7 @@ module RuboCop
|
|
82
82
|
|
83
83
|
def builtin_formatter_class(specified_key)
|
84
84
|
matching_keys = BUILTIN_FORMATTERS_FOR_KEYS.keys.select do |key|
|
85
|
-
|
85
|
+
/^\[#{specified_key}\]/.match?(key) || specified_key == key.delete('[]')
|
86
86
|
end
|
87
87
|
|
88
88
|
raise %(No formatter for "#{specified_key}") if matching_keys.empty?
|
@@ -12,13 +12,17 @@ module RuboCop
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def find_similar_names(target_name, names)
|
15
|
+
# DidYouMean::SpellChecker is not available in all versions of Ruby, and
|
16
|
+
# even on versions where it *is* available (>= 2.3), it is not always
|
17
|
+
# required correctly. So we do a feature check first.
|
18
|
+
# See: https://github.com/rubocop-hq/rubocop/issues/7979
|
19
|
+
return [] unless defined?(DidYouMean::SpellChecker)
|
20
|
+
|
15
21
|
names = names.dup
|
16
22
|
names.delete(target_name)
|
17
23
|
|
18
24
|
spell_checker = DidYouMean::SpellChecker.new(dictionary: names)
|
19
|
-
|
20
|
-
|
21
|
-
similar_names
|
25
|
+
spell_checker.correct(target_name)
|
22
26
|
end
|
23
27
|
end
|
24
28
|
end
|
data/lib/rubocop/options.rb
CHANGED
@@ -163,7 +163,7 @@ module RuboCop
|
|
163
163
|
end
|
164
164
|
end
|
165
165
|
|
166
|
-
# rubocop:disable Metrics/MethodLength
|
166
|
+
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
167
167
|
def add_boolean_flags(opts)
|
168
168
|
option(opts, '-F', '--fail-fast')
|
169
169
|
option(opts, '-C', '--cache FLAG')
|
@@ -171,7 +171,16 @@ module RuboCop
|
|
171
171
|
option(opts, '-D', '--[no-]display-cop-names')
|
172
172
|
option(opts, '-E', '--extra-details')
|
173
173
|
option(opts, '-S', '--display-style-guide')
|
174
|
-
option(opts, '-a', '--auto-correct')
|
174
|
+
option(opts, '-a', '--auto-correct') do
|
175
|
+
@options[:safe_auto_correct] = true
|
176
|
+
end
|
177
|
+
option(opts, '--safe-auto-correct') do
|
178
|
+
warn '--safe-auto-correct is deprecated; use --auto-correct'
|
179
|
+
@options[:safe_auto_correct] = @options[:auto_correct] = true
|
180
|
+
end
|
181
|
+
option(opts, '-A', '--auto-correct-all') do
|
182
|
+
@options[:auto_correct] = true
|
183
|
+
end
|
175
184
|
option(opts, '--disable-pending-cops')
|
176
185
|
option(opts, '--enable-pending-cops')
|
177
186
|
option(opts, '--ignore-disable-comments')
|
@@ -184,7 +193,7 @@ module RuboCop
|
|
184
193
|
option(opts, '-V', '--verbose-version')
|
185
194
|
option(opts, '-P', '--parallel')
|
186
195
|
end
|
187
|
-
# rubocop:enable Metrics/MethodLength
|
196
|
+
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
|
188
197
|
|
189
198
|
def add_aliases(opts)
|
190
199
|
option(opts, '-l', '--lint') do
|
@@ -196,9 +205,6 @@ module RuboCop
|
|
196
205
|
@options[:only] << 'Layout'
|
197
206
|
@options[:auto_correct] = true
|
198
207
|
end
|
199
|
-
option(opts, '--safe-auto-correct') do
|
200
|
-
@options[:auto_correct] = true
|
201
|
-
end
|
202
208
|
end
|
203
209
|
|
204
210
|
def add_list_options(opts)
|
@@ -465,8 +471,9 @@ module RuboCop
|
|
465
471
|
lint: 'Run only lint cops.',
|
466
472
|
safe: 'Run only safe cops.',
|
467
473
|
list_target_files: 'List all files RuboCop will inspect.',
|
468
|
-
auto_correct: 'Auto-correct offenses.',
|
469
|
-
safe_auto_correct: '
|
474
|
+
auto_correct: 'Auto-correct offenses (only when it\'s safe).',
|
475
|
+
safe_auto_correct: '(same, deprecated)',
|
476
|
+
auto_correct_all: 'Auto-correct offenses (safe and unsafe)',
|
470
477
|
fix_layout: 'Run only layout cops, with auto-correct on.',
|
471
478
|
color: 'Force color output on or off.',
|
472
479
|
version: 'Display version.',
|
data/lib/rubocop/path_util.rb
CHANGED
@@ -5,7 +5,7 @@ module RuboCop
|
|
5
5
|
module PathUtil
|
6
6
|
module_function
|
7
7
|
|
8
|
-
def relative_path(path, base_dir =
|
8
|
+
def relative_path(path, base_dir = Dir.pwd)
|
9
9
|
# Optimization for the common case where path begins with the base
|
10
10
|
# dir. Just cut off the first part.
|
11
11
|
if path.start_with?(base_dir)
|
@@ -24,7 +24,7 @@ module RuboCop
|
|
24
24
|
|
25
25
|
def smart_path(path)
|
26
26
|
# Ideally, we calculate this relative to the project root.
|
27
|
-
base_dir =
|
27
|
+
base_dir = Dir.pwd
|
28
28
|
|
29
29
|
if path.start_with? base_dir
|
30
30
|
relative_path(path, base_dir)
|
@@ -40,7 +40,7 @@ module RuboCop
|
|
40
40
|
hidden_file_in_not_hidden_dir?(pattern, path)
|
41
41
|
when Regexp
|
42
42
|
begin
|
43
|
-
path
|
43
|
+
pattern.match?(path)
|
44
44
|
rescue ArgumentError => e
|
45
45
|
return false if e.message.start_with?('invalid byte sequence')
|
46
46
|
|
@@ -51,22 +51,7 @@ module RuboCop
|
|
51
51
|
|
52
52
|
# Returns true for an absolute Unix or Windows path.
|
53
53
|
def absolute?(path)
|
54
|
-
|
55
|
-
end
|
56
|
-
|
57
|
-
def self.pwd
|
58
|
-
@pwd ||= Dir.pwd
|
59
|
-
end
|
60
|
-
|
61
|
-
def self.reset_pwd
|
62
|
-
@pwd = nil
|
63
|
-
end
|
64
|
-
|
65
|
-
def self.chdir(dir, &block)
|
66
|
-
reset_pwd
|
67
|
-
Dir.chdir(dir, &block)
|
68
|
-
ensure
|
69
|
-
reset_pwd
|
54
|
+
%r{\A([A-Z]:)?/}i.match?(path)
|
70
55
|
end
|
71
56
|
|
72
57
|
def hidden_file_in_not_hidden_dir?(pattern, path)
|
data/lib/rubocop/platform.rb
CHANGED
data/lib/rubocop/rake_task.rb
CHANGED
@@ -8,14 +8,11 @@ module RuboCop
|
|
8
8
|
#
|
9
9
|
# require 'rubocop/rake_task'
|
10
10
|
# RuboCop::RakeTask.new
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
attr_accessor :patterns
|
16
|
-
attr_accessor :formatters
|
17
|
-
attr_accessor :requires
|
18
|
-
attr_accessor :options
|
11
|
+
#
|
12
|
+
# Use global Rake namespace here to avoid namespace issues with custom
|
13
|
+
# rubocop-rake tasks
|
14
|
+
class RakeTask < ::Rake::TaskLib
|
15
|
+
attr_accessor :name, :verbose, :fail_on_error, :patterns, :formatters, :requires, :options
|
19
16
|
|
20
17
|
def initialize(name = :rubocop, *args, &task_block)
|
21
18
|
setup_ivars(name)
|
@@ -69,7 +66,7 @@ module RuboCop
|
|
69
66
|
task(:auto_correct, *args) do |_, task_args|
|
70
67
|
RakeFileUtils.verbose(verbose) do
|
71
68
|
yield(*[self, task_args].slice(0, task_block.arity)) if block_given?
|
72
|
-
options = full_options.unshift('--auto-correct')
|
69
|
+
options = full_options.unshift('--auto-correct-all')
|
73
70
|
options.delete('--parallel')
|
74
71
|
run_cli(verbose, options)
|
75
72
|
end
|
data/lib/rubocop/result_cache.rb
CHANGED
@@ -33,7 +33,7 @@ module RuboCop
|
|
33
33
|
|
34
34
|
def requires_file_removal?(file_count, config_store)
|
35
35
|
file_count > 1 &&
|
36
|
-
file_count > config_store.
|
36
|
+
file_count > config_store.for_pwd.for_all_cops['MaxFilesInCache']
|
37
37
|
end
|
38
38
|
|
39
39
|
def remove_oldest_files(files, dirs, cache_root, verbose)
|
@@ -60,7 +60,7 @@ module RuboCop
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def self.cache_root(config_store)
|
63
|
-
root = config_store.
|
63
|
+
root = config_store.for_pwd.for_all_cops['CacheRootDirectory']
|
64
64
|
root ||= if ENV.key?('XDG_CACHE_HOME')
|
65
65
|
# Include user ID in the path to make sure the user has write
|
66
66
|
# access.
|
@@ -72,7 +72,7 @@ module RuboCop
|
|
72
72
|
end
|
73
73
|
|
74
74
|
def self.allow_symlinks_in_cache_location?(config_store)
|
75
|
-
config_store.
|
75
|
+
config_store.for_pwd.for_all_cops['AllowSymlinksInCacheRootDirectory']
|
76
76
|
end
|
77
77
|
|
78
78
|
def initialize(file, team, options, config_store, cache_root = nil)
|
@@ -158,6 +158,7 @@ module RuboCop
|
|
158
158
|
end
|
159
159
|
|
160
160
|
# The checksum of the rubocop program running the inspection.
|
161
|
+
# rubocop:disable Metrics/AbcSize
|
161
162
|
def rubocop_checksum
|
162
163
|
ResultCache.source_checksum ||=
|
163
164
|
begin
|
@@ -168,13 +169,16 @@ module RuboCop
|
|
168
169
|
# exe directory. A change to any of them could affect the cop output
|
169
170
|
# so we include them in the cache hash.
|
170
171
|
source_files = $LOADED_FEATURES + Find.find(exe_root).to_a
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
172
|
+
|
173
|
+
digest = Digest::SHA1.new
|
174
|
+
source_files
|
175
|
+
.select { |path| File.file?(path) }
|
176
|
+
.sort!
|
177
|
+
.each { |path| digest << File.mtime(path).to_s }
|
178
|
+
digest.hexdigest
|
176
179
|
end
|
177
180
|
end
|
181
|
+
# rubocop:enable Metrics/AbcSize
|
178
182
|
|
179
183
|
# Return a hash of the options given at invocation, minus the ones that have
|
180
184
|
# no effect on which offenses and disabled line ranges are found, and thus
|
@@ -43,14 +43,14 @@ module CopHelper
|
|
43
43
|
processed_source = parse_source(source, file)
|
44
44
|
_investigate(cop, processed_source)
|
45
45
|
|
46
|
-
|
47
|
-
RuboCop::Cop::Corrector.new(processed_source.buffer, cop.corrections)
|
48
|
-
corrector.rewrite
|
46
|
+
@last_corrector.rewrite
|
49
47
|
end
|
50
48
|
|
51
49
|
def _investigate(cop, processed_source)
|
52
50
|
team = RuboCop::Cop::Team.new([cop], nil, raise_error: true)
|
53
|
-
team.
|
51
|
+
report = team.investigate(processed_source)
|
52
|
+
@last_corrector = report.correctors.first || RuboCop::Cop::Corrector.new(processed_source)
|
53
|
+
report.offenses
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
@@ -72,25 +72,47 @@ module RuboCop
|
|
72
72
|
#
|
73
73
|
# expect_no_corrections
|
74
74
|
#
|
75
|
-
# If your code has variables of different lengths, you can use `%{foo}
|
76
|
-
# and
|
75
|
+
# If your code has variables of different lengths, you can use `%{foo}`,
|
76
|
+
# `^{foo}`, and `_{foo}` to format your template; you can also abbreviate
|
77
|
+
# offense messages with `[...]`:
|
77
78
|
#
|
78
79
|
# %w[raise fail].each do |keyword|
|
79
80
|
# expect_offense(<<~RUBY, keyword: keyword)
|
80
81
|
# %{keyword}(RuntimeError, msg)
|
81
|
-
# ^{keyword}^^^^^^^^^^^^^^^^^^^ Redundant `RuntimeError` argument
|
82
|
+
# ^{keyword}^^^^^^^^^^^^^^^^^^^ Redundant `RuntimeError` argument [...]
|
82
83
|
# RUBY
|
84
|
+
#
|
85
|
+
# %w[has_one has_many].each do |type|
|
86
|
+
# expect_offense(<<~RUBY, type: type)
|
87
|
+
# class Book
|
88
|
+
# %{type} :chapter, foreign_key: 'book_id'
|
89
|
+
# _{type} ^^^^^^^^^^^^^^^^^^^^^^ Specifying the default [...]
|
90
|
+
# end
|
91
|
+
# RUBY
|
92
|
+
# end
|
93
|
+
#
|
94
|
+
# If you need to specify an offense on a blank line, use the empty `^{}` marker:
|
95
|
+
#
|
96
|
+
# @example `^{}` empty line offense
|
97
|
+
#
|
98
|
+
# expect_offense(<<~RUBY)
|
99
|
+
#
|
100
|
+
# ^{} Missing frozen string literal comment.
|
101
|
+
# puts 1
|
102
|
+
# RUBY
|
83
103
|
module ExpectOffense
|
84
104
|
def format_offense(source, **replacements)
|
85
105
|
replacements.each do |keyword, value|
|
106
|
+
value = value.to_s
|
86
107
|
source = source.gsub("%{#{keyword}}", value)
|
87
108
|
.gsub("^{#{keyword}}", '^' * value.size)
|
109
|
+
.gsub("_{#{keyword}}", ' ' * value.size)
|
88
110
|
end
|
89
111
|
source
|
90
112
|
end
|
91
113
|
|
92
114
|
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
93
|
-
def expect_offense(source, file = nil, **replacements)
|
115
|
+
def expect_offense(source, file = nil, severity: nil, **replacements)
|
94
116
|
source = format_offense(source, **replacements)
|
95
117
|
RuboCop::Formatter::DisabledConfigFormatter
|
96
118
|
.config_to_allow_offenses = {}
|
@@ -108,33 +130,32 @@ module RuboCop
|
|
108
130
|
|
109
131
|
raise 'Error parsing example code' unless @processed_source.valid_syntax?
|
110
132
|
|
111
|
-
_investigate(cop, @processed_source)
|
133
|
+
offenses = _investigate(cop, @processed_source)
|
112
134
|
actual_annotations =
|
113
|
-
expected_annotations.with_offense_annotations(
|
135
|
+
expected_annotations.with_offense_annotations(offenses)
|
114
136
|
|
115
|
-
expect(actual_annotations
|
137
|
+
expect(actual_annotations).to eq(expected_annotations)
|
138
|
+
expect(offenses.map(&:severity).uniq).to eq([severity]) if severity
|
116
139
|
end
|
117
140
|
|
118
|
-
def expect_correction(correction, loop:
|
141
|
+
def expect_correction(correction, loop: true)
|
119
142
|
raise '`expect_correction` must follow `expect_offense`' unless @processed_source
|
120
143
|
|
121
144
|
iteration = 0
|
122
145
|
new_source = loop do
|
123
146
|
iteration += 1
|
124
147
|
|
125
|
-
|
126
|
-
RuboCop::Cop::Corrector.new(@processed_source.buffer, cop.corrections)
|
127
|
-
corrected_source = corrector.rewrite
|
148
|
+
corrected_source = @last_corrector.rewrite
|
128
149
|
|
129
150
|
break corrected_source unless loop
|
130
|
-
break corrected_source if
|
151
|
+
break corrected_source if @last_corrector.empty?
|
152
|
+
break corrected_source if corrected_source == @processed_source.buffer.source
|
131
153
|
|
132
154
|
if iteration > RuboCop::Runner::MAX_ITERATIONS
|
133
155
|
raise RuboCop::Runner::InfiniteCorrectionLoop.new(@processed_source.path, [])
|
134
156
|
end
|
135
157
|
|
136
158
|
# Prepare for next loop
|
137
|
-
cop.instance_variable_set(:@corrections, [])
|
138
159
|
@processed_source = parse_source(corrected_source,
|
139
160
|
@processed_source.path)
|
140
161
|
_investigate(cop, @processed_source)
|
@@ -147,30 +168,29 @@ module RuboCop
|
|
147
168
|
def expect_no_corrections
|
148
169
|
raise '`expect_no_corrections` must follow `expect_offense`' unless @processed_source
|
149
170
|
|
150
|
-
return if
|
171
|
+
return if @last_corrector.empty?
|
151
172
|
|
152
173
|
# In order to print a nice diff, e.g. what source got corrected to,
|
153
174
|
# we need to run the actual corrections
|
154
175
|
|
155
|
-
|
156
|
-
RuboCop::Cop::Corrector.new(@processed_source.buffer, cop.corrections)
|
157
|
-
new_source = corrector.rewrite
|
176
|
+
new_source = @last_corrector.rewrite
|
158
177
|
|
159
178
|
expect(new_source).to eq(@processed_source.buffer.source)
|
160
179
|
end
|
161
180
|
|
162
181
|
def expect_no_offenses(source, file = nil)
|
163
|
-
inspect_source(source, file)
|
182
|
+
offenses = inspect_source(source, file)
|
164
183
|
|
165
184
|
expected_annotations = AnnotatedSource.parse(source)
|
166
185
|
actual_annotations =
|
167
|
-
expected_annotations.with_offense_annotations(
|
186
|
+
expected_annotations.with_offense_annotations(offenses)
|
168
187
|
expect(actual_annotations.to_s).to eq(source)
|
169
188
|
end
|
170
189
|
|
171
190
|
# Parsed representation of code annotated with the `^^^ Message` style
|
172
191
|
class AnnotatedSource
|
173
|
-
ANNOTATION_PATTERN = /\A\s
|
192
|
+
ANNOTATION_PATTERN = /\A\s*(\^+|\^{}) /.freeze
|
193
|
+
ABBREV = "[...]\n"
|
174
194
|
|
175
195
|
# @param annotated_source [String] string passed to the matchers
|
176
196
|
#
|
@@ -189,6 +209,7 @@ module RuboCop
|
|
189
209
|
source << source_line
|
190
210
|
end
|
191
211
|
end
|
212
|
+
annotations.each { |a| a[0] = 1 } if source.empty?
|
192
213
|
|
193
214
|
new(source, annotations)
|
194
215
|
end
|
@@ -204,6 +225,27 @@ module RuboCop
|
|
204
225
|
@annotations = annotations.sort.freeze
|
205
226
|
end
|
206
227
|
|
228
|
+
def ==(other)
|
229
|
+
other.is_a?(self.class) &&
|
230
|
+
other.lines == lines &&
|
231
|
+
match_annotations?(other)
|
232
|
+
end
|
233
|
+
|
234
|
+
# Dirty hack: expectations with [...] are rewritten when they match
|
235
|
+
# This way the diff is clean.
|
236
|
+
def match_annotations?(other)
|
237
|
+
annotations.zip(other.annotations) do |(_actual_line, actual_annotation),
|
238
|
+
(_expected_line, expected_annotation)|
|
239
|
+
if expected_annotation&.end_with?(ABBREV)
|
240
|
+
if actual_annotation.start_with?(expected_annotation[0...-ABBREV.length])
|
241
|
+
expected_annotation.replace(actual_annotation)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
annotations == other.annotations
|
247
|
+
end
|
248
|
+
|
207
249
|
# Construct annotated source string (like what we parse)
|
208
250
|
#
|
209
251
|
# Reconstruct a deterministic annotated source string. This is
|
@@ -236,6 +278,7 @@ module RuboCop
|
|
236
278
|
|
237
279
|
reconstructed.join
|
238
280
|
end
|
281
|
+
alias inspect to_s
|
239
282
|
|
240
283
|
# Return the plain source code without annotations
|
241
284
|
#
|
@@ -254,6 +297,7 @@ module RuboCop
|
|
254
297
|
offenses.map do |offense|
|
255
298
|
indent = ' ' * offense.column
|
256
299
|
carets = '^' * offense.column_length
|
300
|
+
carets = '^{}' if offense.column_length.zero?
|
257
301
|
|
258
302
|
[offense.line, "#{indent}#{carets} #{offense.message}\n"]
|
259
303
|
end
|
@@ -261,7 +305,7 @@ module RuboCop
|
|
261
305
|
self.class.new(lines, offense_annotations)
|
262
306
|
end
|
263
307
|
|
264
|
-
|
308
|
+
protected
|
265
309
|
|
266
310
|
attr_reader :lines, :annotations
|
267
311
|
end
|