rubocop 1.36.0 → 1.38.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +27 -1
  4. data/lib/rubocop/arguments_env.rb +17 -0
  5. data/lib/rubocop/arguments_file.rb +17 -0
  6. data/lib/rubocop/cli/command/execute_runner.rb +7 -7
  7. data/lib/rubocop/cli/command/suggest_extensions.rb +8 -1
  8. data/lib/rubocop/comment_config.rb +36 -1
  9. data/lib/rubocop/cop/commissioner.rb +3 -1
  10. data/lib/rubocop/cop/generator.rb +1 -2
  11. data/lib/rubocop/cop/internal_affairs/create_empty_file.rb +37 -0
  12. data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +111 -0
  13. data/lib/rubocop/cop/internal_affairs.rb +2 -0
  14. data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -0
  15. data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
  16. data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
  17. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
  18. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +13 -9
  19. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +30 -3
  20. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +6 -2
  21. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  22. data/lib/rubocop/cop/lint/duplicate_magic_comment.rb +73 -0
  23. data/lib/rubocop/cop/lint/duplicate_methods.rb +11 -1
  24. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +25 -6
  25. data/lib/rubocop/cop/lint/empty_class.rb +3 -1
  26. data/lib/rubocop/cop/lint/empty_conditional_body.rb +20 -8
  27. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +18 -3
  28. data/lib/rubocop/cop/lint/nested_method_definition.rb +50 -1
  29. data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
  30. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +4 -5
  31. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +1 -1
  32. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +23 -1
  33. data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +7 -0
  34. data/lib/rubocop/cop/lint/redundant_require_statement.rb +38 -10
  35. data/lib/rubocop/cop/lint/require_parentheses.rb +1 -1
  36. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +3 -2
  37. data/lib/rubocop/cop/lint/shadowed_exception.rb +0 -10
  38. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +3 -0
  39. data/lib/rubocop/cop/lint/unreachable_loop.rb +1 -1
  40. data/lib/rubocop/cop/lint/unused_method_argument.rb +4 -0
  41. data/lib/rubocop/cop/mixin/comments_help.rb +12 -0
  42. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +4 -0
  43. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +6 -3
  44. data/lib/rubocop/cop/mixin/rescue_node.rb +3 -1
  45. data/lib/rubocop/cop/mixin/surrounding_space.rb +10 -8
  46. data/lib/rubocop/cop/naming/inclusive_language.rb +1 -1
  47. data/lib/rubocop/cop/registry.rb +10 -4
  48. data/lib/rubocop/cop/style/access_modifier_declarations.rb +24 -2
  49. data/lib/rubocop/cop/style/accessor_grouping.rb +7 -3
  50. data/lib/rubocop/cop/style/block_delimiters.rb +2 -2
  51. data/lib/rubocop/cop/style/character_literal.rb +1 -1
  52. data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -1
  53. data/lib/rubocop/cop/style/collection_compact.rb +11 -2
  54. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  55. data/lib/rubocop/cop/style/endless_method.rb +1 -1
  56. data/lib/rubocop/cop/style/explicit_block_argument.rb +4 -0
  57. data/lib/rubocop/cop/style/format_string_token.rb +1 -1
  58. data/lib/rubocop/cop/style/guard_clause.rb +62 -21
  59. data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
  60. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +25 -2
  61. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +13 -2
  62. data/lib/rubocop/cop/style/module_function.rb +28 -6
  63. data/lib/rubocop/cop/style/negated_if_else_condition.rb +7 -1
  64. data/lib/rubocop/cop/style/numeric_predicate.rb +1 -1
  65. data/lib/rubocop/cop/style/operator_method_call.rb +40 -0
  66. data/lib/rubocop/cop/style/redundant_begin.rb +1 -0
  67. data/lib/rubocop/cop/style/redundant_condition.rb +5 -2
  68. data/lib/rubocop/cop/style/redundant_each.rb +111 -0
  69. data/lib/rubocop/cop/style/redundant_initialize.rb +3 -1
  70. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +8 -1
  71. data/lib/rubocop/cop/style/redundant_string_escape.rb +181 -0
  72. data/lib/rubocop/cop/style/rescue_modifier.rb +1 -1
  73. data/lib/rubocop/cop/style/static_class.rb +32 -1
  74. data/lib/rubocop/cop/style/symbol_array.rb +2 -0
  75. data/lib/rubocop/cop/style/symbol_proc.rb +1 -1
  76. data/lib/rubocop/cop/style/word_array.rb +2 -0
  77. data/lib/rubocop/cop/team.rb +3 -4
  78. data/lib/rubocop/cop/variable_force/variable_table.rb +1 -1
  79. data/lib/rubocop/cops_documentation_generator.rb +4 -2
  80. data/lib/rubocop/ext/processed_source.rb +2 -0
  81. data/lib/rubocop/formatter/disabled_config_formatter.rb +8 -2
  82. data/lib/rubocop/formatter/offense_count_formatter.rb +8 -5
  83. data/lib/rubocop/formatter/worst_offenders_formatter.rb +6 -3
  84. data/lib/rubocop/options.rb +19 -15
  85. data/lib/rubocop/rspec/cop_helper.rb +21 -1
  86. data/lib/rubocop/rspec/shared_contexts.rb +14 -1
  87. data/lib/rubocop/runner.rb +15 -11
  88. data/lib/rubocop/server/cache.rb +5 -1
  89. data/lib/rubocop/server/cli.rb +9 -2
  90. data/lib/rubocop/server/client_command/exec.rb +5 -0
  91. data/lib/rubocop/server/core.rb +3 -1
  92. data/lib/rubocop/server/socket_reader.rb +5 -1
  93. data/lib/rubocop/server.rb +1 -1
  94. data/lib/rubocop/version.rb +8 -3
  95. data/lib/rubocop.rb +4 -0
  96. 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
@@ -75,6 +75,7 @@ module RuboCop
75
75
 
76
76
  def on_def(node)
77
77
  return unless node.body&.kwbegin_type?
78
+ return if node.endless? && !node.body.children.one?
78
79
 
79
80
  register_offense(node.body)
80
81
  end
@@ -145,11 +145,14 @@ module RuboCop
145
145
 
146
146
  return false unless if_branch && else_branch
147
147
 
148
- if_branch.send_type? && if_branch.arguments.count == 1 &&
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'] && contains_comments?(node)
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 led us to believe that `rescue` handles the given exception
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) if class_convertible_to_module?(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?
@@ -65,6 +65,8 @@ module RuboCop
65
65
  end
66
66
 
67
67
  def build_bracketed_array(node)
68
+ return '[]' if node.children.empty?
69
+
68
70
  syms = node.children.map do |c|
69
71
  if c.dsym_type?
70
72
  string_literal = to_string_literal(c.source)
@@ -82,7 +82,7 @@ module RuboCop
82
82
  # # bad
83
83
  # something.map { |s| s.upcase }
84
84
  #
85
- # @example AllowedPatterns: [/map/] (default)
85
+ # @example AllowedPatterns: ['map'] (default)
86
86
  # # good
87
87
  # something.map { |s| s.upcase }
88
88
  #
@@ -83,6 +83,8 @@ module RuboCop
83
83
  end
84
84
 
85
85
  def build_bracketed_array(node)
86
+ return '[]' if node.children.empty?
87
+
86
88
  words = node.children.map do |word|
87
89
  if word.dstr_type?
88
90
  string_literal = to_string_literal(word.source)
@@ -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
- only = options.fetch(:only, [])
45
- safe = options.fetch(:safe, false)
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.each_with_object([]) do |scope, variables|
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
- table = ['|===', "| #{header.join(' | ')}\n\n"].join("\n")
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| "| #{c}" }.join("\n")
190
+ plain_content.map { |c| "¦ #{c}" }.join("\n")
189
191
  end
190
192
  table << marked_contents.join("\n\n")
191
193
  table << "\n|===\n"
@@ -4,6 +4,8 @@ module RuboCop
4
4
  module Ext
5
5
  # Extensions to AST::ProcessedSource for our cached comment_config
6
6
  module ProcessedSource
7
+ attr_accessor :registry, :config
8
+
7
9
  def comment_config
8
10
  @comment_config ||= CommentConfig.new(self)
9
11
  end
@@ -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 @exclude_limit_option
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(total_count.to_s.length + 2)}#{cop_name}" \
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(total_count.to_s.length + 2)}#{file_name}\n"
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