rubocop 1.36.0 → 1.38.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 +1 -1
- data/config/default.yml +27 -1
- data/lib/rubocop/arguments_env.rb +17 -0
- data/lib/rubocop/arguments_file.rb +17 -0
- data/lib/rubocop/cli/command/execute_runner.rb +7 -7
- data/lib/rubocop/cli/command/suggest_extensions.rb +8 -1
- data/lib/rubocop/comment_config.rb +36 -1
- data/lib/rubocop/cop/commissioner.rb +3 -1
- data/lib/rubocop/cop/generator.rb +1 -2
- data/lib/rubocop/cop/internal_affairs/create_empty_file.rb +37 -0
- data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +111 -0
- data/lib/rubocop/cop/internal_affairs.rb +2 -0
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -0
- data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +13 -9
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +30 -3
- data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +6 -2
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_magic_comment.rb +73 -0
- data/lib/rubocop/cop/lint/duplicate_methods.rb +11 -1
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +25 -6
- data/lib/rubocop/cop/lint/empty_class.rb +3 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +20 -8
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +18 -3
- data/lib/rubocop/cop/lint/nested_method_definition.rb +50 -1
- data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/ordered_magic_comments.rb +4 -5
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +23 -1
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +7 -0
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +38 -10
- data/lib/rubocop/cop/lint/require_parentheses.rb +1 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +3 -2
- data/lib/rubocop/cop/lint/shadowed_exception.rb +0 -10
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +3 -0
- data/lib/rubocop/cop/lint/unreachable_loop.rb +1 -1
- data/lib/rubocop/cop/lint/unused_method_argument.rb +4 -0
- data/lib/rubocop/cop/mixin/comments_help.rb +12 -0
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +4 -0
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +6 -3
- data/lib/rubocop/cop/mixin/rescue_node.rb +3 -1
- data/lib/rubocop/cop/mixin/surrounding_space.rb +10 -8
- data/lib/rubocop/cop/naming/inclusive_language.rb +1 -1
- data/lib/rubocop/cop/registry.rb +10 -4
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +24 -2
- data/lib/rubocop/cop/style/accessor_grouping.rb +7 -3
- data/lib/rubocop/cop/style/block_delimiters.rb +2 -2
- data/lib/rubocop/cop/style/character_literal.rb +1 -1
- data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -1
- data/lib/rubocop/cop/style/collection_compact.rb +11 -2
- data/lib/rubocop/cop/style/empty_method.rb +1 -1
- data/lib/rubocop/cop/style/endless_method.rb +1 -1
- data/lib/rubocop/cop/style/explicit_block_argument.rb +4 -0
- data/lib/rubocop/cop/style/format_string_token.rb +1 -1
- data/lib/rubocop/cop/style/guard_clause.rb +62 -21
- data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +25 -2
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +13 -2
- data/lib/rubocop/cop/style/module_function.rb +28 -6
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +7 -1
- data/lib/rubocop/cop/style/numeric_predicate.rb +1 -1
- data/lib/rubocop/cop/style/operator_method_call.rb +40 -0
- data/lib/rubocop/cop/style/redundant_begin.rb +1 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +5 -2
- data/lib/rubocop/cop/style/redundant_each.rb +111 -0
- data/lib/rubocop/cop/style/redundant_initialize.rb +3 -1
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +8 -1
- data/lib/rubocop/cop/style/redundant_string_escape.rb +181 -0
- data/lib/rubocop/cop/style/rescue_modifier.rb +1 -1
- data/lib/rubocop/cop/style/static_class.rb +32 -1
- data/lib/rubocop/cop/style/symbol_array.rb +2 -0
- data/lib/rubocop/cop/style/symbol_proc.rb +1 -1
- data/lib/rubocop/cop/style/word_array.rb +2 -0
- data/lib/rubocop/cop/team.rb +3 -4
- data/lib/rubocop/cop/variable_force/variable_table.rb +1 -1
- data/lib/rubocop/cops_documentation_generator.rb +4 -2
- data/lib/rubocop/ext/processed_source.rb +2 -0
- data/lib/rubocop/formatter/disabled_config_formatter.rb +8 -2
- data/lib/rubocop/formatter/offense_count_formatter.rb +8 -5
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +6 -3
- data/lib/rubocop/options.rb +19 -15
- data/lib/rubocop/rspec/cop_helper.rb +21 -1
- data/lib/rubocop/rspec/shared_contexts.rb +14 -1
- data/lib/rubocop/runner.rb +15 -11
- data/lib/rubocop/server/cache.rb +5 -1
- data/lib/rubocop/server/cli.rb +9 -2
- data/lib/rubocop/server/client_command/exec.rb +5 -0
- data/lib/rubocop/server/core.rb +3 -1
- data/lib/rubocop/server/socket_reader.rb +5 -1
- data/lib/rubocop/server.rb +1 -1
- data/lib/rubocop/version.rb +8 -3
- data/lib/rubocop.rb +4 -0
- metadata +13 -5
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Checks for redundant dot before operator method call.
|
7
|
+
# The target operator methods are `|`, `^`, `&`, `<=>`, `==`, `===`, `=~`, `>`, `>=`, `<`,
|
8
|
+
# `<=`, `<<`, `>>`, `+`, `-`, `*`, `/`, `%`, `**`, `~`, `!`, `!=`, and `!~`.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
#
|
12
|
+
# # bad
|
13
|
+
# foo.+ bar
|
14
|
+
# foo.& bar
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# foo + bar
|
18
|
+
# foo & bar
|
19
|
+
#
|
20
|
+
class OperatorMethodCall < Base
|
21
|
+
extend AutoCorrector
|
22
|
+
|
23
|
+
MSG = 'Redundant dot detected.'
|
24
|
+
RESTRICT_ON_SEND = %i[| ^ & <=> == === =~ > >= < <= << >> + - * / % ** ~ ! != !~].freeze
|
25
|
+
|
26
|
+
def on_send(node)
|
27
|
+
return unless (dot = node.loc.dot)
|
28
|
+
return if node.receiver.const_type?
|
29
|
+
|
30
|
+
_lhs, _op, rhs = *node
|
31
|
+
return if rhs.nil? || rhs.children.first
|
32
|
+
|
33
|
+
add_offense(dot) do |corrector|
|
34
|
+
corrector.replace(dot, ' ')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -145,11 +145,14 @@ module RuboCop
|
|
145
145
|
|
146
146
|
return false unless if_branch && else_branch
|
147
147
|
|
148
|
-
if_branch
|
149
|
-
else_branch.send_type? && else_branch.arguments.count == 1 &&
|
148
|
+
single_argument_method?(if_branch) && single_argument_method?(else_branch) &&
|
150
149
|
same_method?(if_branch, else_branch)
|
151
150
|
end
|
152
151
|
|
152
|
+
def single_argument_method?(node)
|
153
|
+
node.send_type? && !node.method?(:[]) && node.arguments.one?
|
154
|
+
end
|
155
|
+
|
153
156
|
def same_method?(if_branch, else_branch)
|
154
157
|
if_branch.method?(else_branch.method_name) && if_branch.receiver == else_branch.receiver
|
155
158
|
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Checks for redundant `each`.
|
7
|
+
#
|
8
|
+
# @safety
|
9
|
+
# This cop is unsafe, as it can produce false positives if the receiver
|
10
|
+
# is not an `Enumerable`.
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
#
|
14
|
+
# # bad
|
15
|
+
# array.each.each { |v| do_something(v) }
|
16
|
+
#
|
17
|
+
# # good
|
18
|
+
# array.each { |v| do_something(v) }
|
19
|
+
#
|
20
|
+
# # bad
|
21
|
+
# array.each.each_with_index { |v, i| do_something(v, i) }
|
22
|
+
#
|
23
|
+
# # good
|
24
|
+
# array.each.with_index { |v, i| do_something(v, i) }
|
25
|
+
# array.each_with_index { |v, i| do_something(v, i) }
|
26
|
+
#
|
27
|
+
# # bad
|
28
|
+
# array.each.each_with_object { |v, o| do_something(v, o) }
|
29
|
+
#
|
30
|
+
# # good
|
31
|
+
# array.each.with_object { |v, o| do_something(v, o) }
|
32
|
+
# array.each_with_object { |v, o| do_something(v, o) }
|
33
|
+
#
|
34
|
+
class RedundantEach < Base
|
35
|
+
extend AutoCorrector
|
36
|
+
|
37
|
+
MSG = 'Remove redundant `each`.'
|
38
|
+
MSG_WITH_INDEX = 'Use `with_index` to remove redundant `each`.'
|
39
|
+
MSG_WITH_OBJECT = 'Use `with_object` to remove redundant `each`.'
|
40
|
+
|
41
|
+
RESTRICT_ON_SEND = %i[each each_with_index each_with_object].freeze
|
42
|
+
|
43
|
+
def on_send(node)
|
44
|
+
return unless (redundant_node = redundant_each_method(node))
|
45
|
+
|
46
|
+
range = range(node)
|
47
|
+
|
48
|
+
add_offense(range, message: message(node)) do |corrector|
|
49
|
+
case node.method_name
|
50
|
+
when :each
|
51
|
+
remove_redundant_each(corrector, range, redundant_node)
|
52
|
+
when :each_with_index
|
53
|
+
corrector.replace(node.loc.selector, 'with_index')
|
54
|
+
when :each_with_object
|
55
|
+
corrector.replace(node.loc.selector, 'with_object')
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
63
|
+
def redundant_each_method(node)
|
64
|
+
if node.method?(:each) && !node.parent.block_type?
|
65
|
+
ancestor_node = node.each_ancestor(:send).detect do |ancestor|
|
66
|
+
RESTRICT_ON_SEND.include?(ancestor.method_name) || ancestor.method?(:reverse_each)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
ancestor_node || node.each_descendant(:send).detect do |descendant|
|
71
|
+
next if descendant.parent.block_type?
|
72
|
+
|
73
|
+
detected = descendant.method_name.to_s.start_with?('each_') unless node.method?(:each)
|
74
|
+
|
75
|
+
detected || descendant.method?(:reverse_each)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
79
|
+
|
80
|
+
def range(node)
|
81
|
+
if node.method?(:each)
|
82
|
+
node.loc.dot.join(node.loc.selector)
|
83
|
+
else
|
84
|
+
node.loc.selector
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def message(node)
|
89
|
+
case node.method_name
|
90
|
+
when :each
|
91
|
+
MSG
|
92
|
+
when :each_with_index
|
93
|
+
MSG_WITH_INDEX
|
94
|
+
when :each_with_object
|
95
|
+
MSG_WITH_OBJECT
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def remove_redundant_each(corrector, range, redundant_node)
|
100
|
+
corrector.remove(range)
|
101
|
+
|
102
|
+
if redundant_node.method?(:each_with_index)
|
103
|
+
corrector.replace(redundant_node.loc.selector, 'each.with_index')
|
104
|
+
elsif redundant_node.method?(:each_with_object)
|
105
|
+
corrector.replace(redundant_node.loc.selector, 'each.with_object')
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -140,7 +140,9 @@ module RuboCop
|
|
140
140
|
end
|
141
141
|
|
142
142
|
def allow_comments?(node)
|
143
|
-
cop_config['AllowComments']
|
143
|
+
return false unless cop_config['AllowComments']
|
144
|
+
|
145
|
+
contains_comments?(node) && !comments_contain_disables?(node, name)
|
144
146
|
end
|
145
147
|
|
146
148
|
def same_args?(super_node, args)
|
@@ -74,7 +74,7 @@ module RuboCop
|
|
74
74
|
|
75
75
|
non_redundant =
|
76
76
|
whitespace_in_free_space_mode?(node, class_elem) ||
|
77
|
-
backslash_b?(class_elem) ||
|
77
|
+
backslash_b?(class_elem) || backslash_zero?(class_elem) ||
|
78
78
|
requires_escape_outside_char_class?(class_elem)
|
79
79
|
|
80
80
|
!non_redundant
|
@@ -104,6 +104,13 @@ module RuboCop
|
|
104
104
|
elem == '\b'
|
105
105
|
end
|
106
106
|
|
107
|
+
def backslash_zero?(elem)
|
108
|
+
# See https://github.com/rubocop/rubocop/issues/11067 for details - in short "\0" != "0" -
|
109
|
+
# the former means an Unicode code point `"\u0000"`, the latter a number character `"0"`.
|
110
|
+
# Similarly "\032" means "\u001A". Other numbers starting with "\0" can also be mentioned.
|
111
|
+
elem == '\0'
|
112
|
+
end
|
113
|
+
|
107
114
|
def requires_escape_outside_char_class?(elem)
|
108
115
|
REQUIRES_ESCAPE_OUTSIDE_CHAR_CLASS_CHARS.include?(elem)
|
109
116
|
end
|
@@ -0,0 +1,181 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Checks for redundant escapes in string literals.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad - no need to escape # without following {/$/@
|
10
|
+
# "\#foo"
|
11
|
+
#
|
12
|
+
# # bad - no need to escape single quotes inside double quoted string
|
13
|
+
# "\'foo\'"
|
14
|
+
#
|
15
|
+
# # bad - heredocs are also checked for unnecessary escapes
|
16
|
+
# <<~STR
|
17
|
+
# \#foo \"foo\"
|
18
|
+
# STR
|
19
|
+
#
|
20
|
+
# # good
|
21
|
+
# "#foo"
|
22
|
+
#
|
23
|
+
# # good
|
24
|
+
# "\#{no_interpolation}"
|
25
|
+
#
|
26
|
+
# # good
|
27
|
+
# "'foo'"
|
28
|
+
#
|
29
|
+
# # good
|
30
|
+
# "foo\
|
31
|
+
# bar"
|
32
|
+
#
|
33
|
+
# # good
|
34
|
+
# <<~STR
|
35
|
+
# #foo "foo"
|
36
|
+
# STR
|
37
|
+
class RedundantStringEscape < Base
|
38
|
+
include MatchRange
|
39
|
+
include RangeHelp
|
40
|
+
extend AutoCorrector
|
41
|
+
|
42
|
+
MSG = 'Redundant escape of %<char>s inside string literal.'
|
43
|
+
|
44
|
+
def on_str(node)
|
45
|
+
return if node.parent&.regexp_type? || node.parent&.xstr_type? || node.character_literal?
|
46
|
+
|
47
|
+
str_contents_range = str_contents_range(node)
|
48
|
+
|
49
|
+
each_match_range(str_contents_range, /(\\.)/) do |range|
|
50
|
+
next if allowed_escape?(node, range.resize(3))
|
51
|
+
|
52
|
+
add_offense(range) do |corrector|
|
53
|
+
corrector.remove_leading(range, 1)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def message(range)
|
61
|
+
format(MSG, char: range.source.chars.last)
|
62
|
+
end
|
63
|
+
|
64
|
+
def str_contents_range(node)
|
65
|
+
if heredoc?(node)
|
66
|
+
node.loc.heredoc_body
|
67
|
+
elsif begin_loc_present?(node)
|
68
|
+
contents_range(node)
|
69
|
+
else
|
70
|
+
node.loc.expression
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def begin_loc_present?(node)
|
75
|
+
# e.g. a __FILE__ literal has no begin loc so we can't query if it's nil
|
76
|
+
node.loc.to_hash.key?(:begin) && !node.loc.begin.nil?
|
77
|
+
end
|
78
|
+
|
79
|
+
def allowed_escape?(node, range)
|
80
|
+
escaped = range.source[(1..-1)]
|
81
|
+
|
82
|
+
# Inside a single-quoted string, escapes (except \\ and \') do not have special meaning,
|
83
|
+
# and so are not redundant, as they are a literal backslash.
|
84
|
+
return true if interpolation_not_enabled?(node)
|
85
|
+
|
86
|
+
# Strictly speaking a few single-letter chars are currently unnecessary to "escape", e.g.
|
87
|
+
# d, but enumerating them is rather difficult, and their behavior could change over time
|
88
|
+
# with different versions of Ruby so that e.g. /\d/ != /d/
|
89
|
+
return true if /[\n\\[[:alnum:]]]/.match?(escaped[0])
|
90
|
+
|
91
|
+
return true if escaped[0] == ' ' && percent_array_literal?(node)
|
92
|
+
|
93
|
+
return true if disabling_interpolation?(range)
|
94
|
+
return true if delimiter?(node, escaped[0])
|
95
|
+
|
96
|
+
false
|
97
|
+
end
|
98
|
+
|
99
|
+
def interpolation_not_enabled?(node)
|
100
|
+
single_quoted?(node) ||
|
101
|
+
percent_w_literal?(node) ||
|
102
|
+
percent_q_literal?(node) ||
|
103
|
+
heredoc_with_disabled_interpolation?(node)
|
104
|
+
end
|
105
|
+
|
106
|
+
def single_quoted?(node)
|
107
|
+
delimiter?(node, "'")
|
108
|
+
end
|
109
|
+
|
110
|
+
def percent_q_literal?(node)
|
111
|
+
if literal_in_interpolated_or_multiline_string?(node)
|
112
|
+
percent_q_literal?(node.parent)
|
113
|
+
else
|
114
|
+
node.source.start_with?('%q')
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def array_literal?(node, prefix)
|
119
|
+
if literal_in_interpolated_or_multiline_string?(node)
|
120
|
+
array_literal?(node.parent, prefix)
|
121
|
+
else
|
122
|
+
node.parent&.array_type? && node.parent.source.start_with?(prefix)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def percent_w_literal?(node)
|
127
|
+
array_literal?(node, '%w')
|
128
|
+
end
|
129
|
+
|
130
|
+
def percent_w_upper_literal?(node)
|
131
|
+
array_literal?(node, '%W')
|
132
|
+
end
|
133
|
+
|
134
|
+
def percent_array_literal?(node)
|
135
|
+
(percent_w_literal?(node) || percent_w_upper_literal?(node))
|
136
|
+
end
|
137
|
+
|
138
|
+
def heredoc_with_disabled_interpolation?(node)
|
139
|
+
if heredoc?(node)
|
140
|
+
node.loc.expression.source.end_with?("'")
|
141
|
+
elsif node.parent&.dstr_type?
|
142
|
+
heredoc_with_disabled_interpolation?(node.parent)
|
143
|
+
else
|
144
|
+
false
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def heredoc?(node)
|
149
|
+
(node.str_type? || node.dstr_type?) && node.heredoc?
|
150
|
+
end
|
151
|
+
|
152
|
+
def delimiter?(node, char)
|
153
|
+
return false if heredoc?(node)
|
154
|
+
|
155
|
+
if literal_in_interpolated_or_multiline_string?(node) || percent_array_literal?(node)
|
156
|
+
return delimiter?(node.parent, char)
|
157
|
+
end
|
158
|
+
|
159
|
+
delimiters = [node.loc.begin.source[-1], node.loc.end.source[0]]
|
160
|
+
|
161
|
+
delimiters.include?(char)
|
162
|
+
end
|
163
|
+
|
164
|
+
def literal_in_interpolated_or_multiline_string?(node)
|
165
|
+
node.str_type? && !begin_loc_present?(node) && node.parent&.dstr_type?
|
166
|
+
end
|
167
|
+
|
168
|
+
def disabling_interpolation?(range)
|
169
|
+
# Allow \#{foo}, \#$foo, \#@foo, and \#@@foo
|
170
|
+
# for escaping local, global, instance and class variable interpolations
|
171
|
+
return true if range.source.match?(/\A\\#[{$@]/)
|
172
|
+
|
173
|
+
# Also allow #\{foo}, #\$foo, #\@foo and #\@@foo
|
174
|
+
return true if range.adjust(begin_pos: -2).source.match?(/\A[^\\]#\\[{$@]/)
|
175
|
+
|
176
|
+
false
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
@@ -9,7 +9,7 @@ module RuboCop
|
|
9
9
|
# reasons:
|
10
10
|
#
|
11
11
|
# * The syntax of modifier form `rescue` can be misleading because it
|
12
|
-
# might
|
12
|
+
# might lead us to believe that `rescue` handles the given exception
|
13
13
|
# but it actually rescue all exceptions to return the given rescue
|
14
14
|
# block. In this case, value returned by handle_error or
|
15
15
|
# SomeException.
|
@@ -44,18 +44,49 @@ module RuboCop
|
|
44
44
|
# end
|
45
45
|
#
|
46
46
|
class StaticClass < Base
|
47
|
+
include RangeHelp
|
47
48
|
include VisibilityHelp
|
49
|
+
extend AutoCorrector
|
48
50
|
|
49
51
|
MSG = 'Prefer modules to classes with only class methods.'
|
50
52
|
|
51
53
|
def on_class(class_node)
|
52
54
|
return if class_node.parent_class
|
55
|
+
return unless class_convertible_to_module?(class_node)
|
53
56
|
|
54
|
-
add_offense(class_node)
|
57
|
+
add_offense(class_node) do |corrector|
|
58
|
+
autocorrect(corrector, class_node)
|
59
|
+
end
|
55
60
|
end
|
56
61
|
|
57
62
|
private
|
58
63
|
|
64
|
+
def autocorrect(corrector, class_node)
|
65
|
+
corrector.replace(class_node.loc.keyword, 'module')
|
66
|
+
corrector.insert_after(class_node.loc.name, "\nmodule_function\n")
|
67
|
+
|
68
|
+
class_elements(class_node).each do |node|
|
69
|
+
if node.defs_type?
|
70
|
+
autocorrect_def(corrector, node)
|
71
|
+
elsif node.sclass_type?
|
72
|
+
autocorrect_sclass(corrector, node)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def autocorrect_def(corrector, node)
|
78
|
+
corrector.remove(
|
79
|
+
range_between(node.receiver.source_range.begin_pos, node.loc.name.begin_pos)
|
80
|
+
)
|
81
|
+
end
|
82
|
+
|
83
|
+
def autocorrect_sclass(corrector, node)
|
84
|
+
corrector.remove(
|
85
|
+
range_between(node.loc.keyword.begin_pos, node.identifier.source_range.end_pos)
|
86
|
+
)
|
87
|
+
corrector.remove(node.loc.end)
|
88
|
+
end
|
89
|
+
|
59
90
|
def class_convertible_to_module?(class_node)
|
60
91
|
nodes = class_elements(class_node)
|
61
92
|
return false if nodes.empty?
|
data/lib/rubocop/cop/team.rb
CHANGED
@@ -40,10 +40,9 @@ module RuboCop
|
|
40
40
|
|
41
41
|
# @return [Array<Cop::Cop>]
|
42
42
|
def self.mobilize_cops(cop_classes, config, options = {})
|
43
|
-
cop_classes = Registry.new(cop_classes.to_a) unless cop_classes.is_a?(Registry)
|
44
|
-
|
45
|
-
|
46
|
-
cop_classes.enabled(config, only, only_safe: safe).map do |cop_class|
|
43
|
+
cop_classes = Registry.new(cop_classes.to_a, options) unless cop_classes.is_a?(Registry)
|
44
|
+
|
45
|
+
cop_classes.enabled(config).map do |cop_class|
|
47
46
|
cop_class.new(config, options)
|
48
47
|
end
|
49
48
|
end
|
@@ -109,7 +109,7 @@ module RuboCop
|
|
109
109
|
end
|
110
110
|
|
111
111
|
def accessible_variables
|
112
|
-
scope_stack.reverse_each.
|
112
|
+
scope_stack.reverse_each.with_object([]) do |scope, variables|
|
113
113
|
variables.concat(scope.variables.values)
|
114
114
|
break variables unless scope.node.block_type?
|
115
115
|
end
|
@@ -183,9 +183,11 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
183
183
|
# rubocop:enable Metrics/CyclomaticComplexity,Metrics/MethodLength
|
184
184
|
|
185
185
|
def to_table(header, content)
|
186
|
-
|
186
|
+
# Specify `[separator=¦]` to prevent the regexp `|` is not used as a table separator.
|
187
|
+
# See: https://docs.asciidoctor.org/asciidoc/latest/tables/data-format/#escape-the-cell-separator
|
188
|
+
table = ['[separator=¦]', '|===', "| #{header.join(' | ')}\n\n"].join("\n")
|
187
189
|
marked_contents = content.map do |plain_content|
|
188
|
-
plain_content.map { |c| "
|
190
|
+
plain_content.map { |c| "¦ #{c}" }.join("\n")
|
189
191
|
end
|
190
192
|
table << marked_contents.join("\n\n")
|
191
193
|
table << "\n|===\n"
|
@@ -70,7 +70,9 @@ module RuboCop
|
|
70
70
|
|
71
71
|
command += ' --auto-gen-only-exclude' if @options[:auto_gen_only_exclude]
|
72
72
|
|
73
|
-
if
|
73
|
+
if no_exclude_limit?
|
74
|
+
command += ' --no-exclude-limit'
|
75
|
+
elsif @exclude_limit_option
|
74
76
|
command += format(' --exclude-limit %<limit>d', limit: Integer(@exclude_limit_option))
|
75
77
|
end
|
76
78
|
command += ' --no-offense-counts' unless show_offense_counts?
|
@@ -187,7 +189,7 @@ module RuboCop
|
|
187
189
|
return unless cfg.empty?
|
188
190
|
|
189
191
|
offending_files = @files_with_offenses[cop_name].sort
|
190
|
-
if offending_files.count > @exclude_limit
|
192
|
+
if !no_exclude_limit? && offending_files.count > @exclude_limit
|
191
193
|
output_buffer.puts ' Enabled: false'
|
192
194
|
else
|
193
195
|
output_exclude_list(output_buffer, offending_files, cop_name)
|
@@ -245,6 +247,10 @@ module RuboCop
|
|
245
247
|
def safe_autocorrect?(config)
|
246
248
|
config.fetch('Safe', true) && config.fetch('SafeAutoCorrect', true)
|
247
249
|
end
|
250
|
+
|
251
|
+
def no_exclude_limit?
|
252
|
+
@options[:no_exclude_limit] == false
|
253
|
+
end
|
248
254
|
end
|
249
255
|
end
|
250
256
|
end
|
@@ -12,13 +12,14 @@ module RuboCop
|
|
12
12
|
# 26 LineLength
|
13
13
|
# 3 OneLineConditional
|
14
14
|
# --
|
15
|
-
# 29 Total
|
15
|
+
# 29 Total in 5 files
|
16
16
|
class OffenseCountFormatter < BaseFormatter
|
17
17
|
attr_reader :offense_counts
|
18
18
|
|
19
19
|
def started(target_files)
|
20
20
|
super
|
21
21
|
@offense_counts = Hash.new(0)
|
22
|
+
@offending_files_count = 0
|
22
23
|
@style_guide_links = {}
|
23
24
|
|
24
25
|
return unless output.tty?
|
@@ -43,26 +44,28 @@ module RuboCop
|
|
43
44
|
if options[:display_style_guide]
|
44
45
|
offenses.each { |o| @style_guide_links[o.cop_name] ||= o.message[/ \(http\S+\)\Z/] }
|
45
46
|
end
|
47
|
+
@offending_files_count += 1 unless offenses.empty?
|
46
48
|
@progressbar.increment if instance_variable_defined?(:@progressbar)
|
47
49
|
end
|
48
50
|
|
49
51
|
def finished(_inspected_files)
|
50
|
-
report_summary(@offense_counts)
|
52
|
+
report_summary(@offense_counts, @offending_files_count)
|
51
53
|
end
|
52
54
|
|
53
55
|
# rubocop:disable Metrics/AbcSize
|
54
|
-
def report_summary(offense_counts)
|
56
|
+
def report_summary(offense_counts, offending_files_count)
|
55
57
|
per_cop_counts = ordered_offense_counts(offense_counts)
|
56
58
|
total_count = total_offense_count(offense_counts)
|
57
59
|
|
58
60
|
output.puts
|
59
61
|
|
62
|
+
column_width = total_count.to_s.length + 2
|
60
63
|
per_cop_counts.each do |cop_name, count|
|
61
|
-
output.puts "#{count.to_s.ljust(
|
64
|
+
output.puts "#{count.to_s.ljust(column_width)}#{cop_name}" \
|
62
65
|
"#{@style_guide_links[cop_name]}\n"
|
63
66
|
end
|
64
67
|
output.puts '--'
|
65
|
-
output.puts "#{total_count} Total"
|
68
|
+
output.puts "#{total_count} Total in #{offending_files_count} files"
|
66
69
|
|
67
70
|
output.puts
|
68
71
|
end
|
@@ -12,7 +12,7 @@ module RuboCop
|
|
12
12
|
# 26 this/file/is/really/bad.rb
|
13
13
|
# 3 just/ok.rb
|
14
14
|
# --
|
15
|
-
# 29 Total
|
15
|
+
# 29 Total in 2 files
|
16
16
|
class WorstOffendersFormatter < BaseFormatter
|
17
17
|
attr_reader :offense_counts
|
18
18
|
|
@@ -36,14 +36,17 @@ module RuboCop
|
|
36
36
|
def report_summary(offense_counts)
|
37
37
|
per_file_counts = ordered_offense_counts(offense_counts)
|
38
38
|
total_count = total_offense_count(offense_counts)
|
39
|
+
file_count = per_file_counts.size
|
39
40
|
|
40
41
|
output.puts
|
41
42
|
|
43
|
+
column_width = total_count.to_s.length + 2
|
42
44
|
per_file_counts.each do |file_name, count|
|
43
|
-
output.puts "#{count.to_s.ljust(
|
45
|
+
output.puts "#{count.to_s.ljust(column_width)}#{file_name}\n"
|
44
46
|
end
|
47
|
+
|
45
48
|
output.puts '--'
|
46
|
-
output.puts "#{total_count} Total"
|
49
|
+
output.puts "#{total_count} Total in #{file_count} files"
|
47
50
|
|
48
51
|
output.puts
|
49
52
|
end
|