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.
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