rubocop 1.70.0 → 1.71.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 (80) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +17 -0
  4. data/lib/rubocop/cli/command/show_cops.rb +24 -2
  5. data/lib/rubocop/comment_config.rb +1 -1
  6. data/lib/rubocop/cop/internal_affairs/location_expression.rb +2 -1
  7. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +3 -2
  8. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +90 -0
  9. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +2 -1
  10. data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +5 -4
  11. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  12. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
  13. data/lib/rubocop/cop/layout/class_structure.rb +7 -7
  14. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +1 -1
  15. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +1 -1
  16. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +1 -1
  17. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +1 -1
  18. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +1 -0
  19. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -0
  20. data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -0
  21. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +119 -0
  22. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
  23. data/lib/rubocop/cop/lint/duplicate_set_element.rb +1 -1
  24. data/lib/rubocop/cop/lint/float_comparison.rb +5 -2
  25. data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
  26. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +12 -2
  27. data/lib/rubocop/cop/lint/mixed_case_range.rb +1 -1
  28. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
  29. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +12 -17
  30. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -1
  31. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
  32. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +2 -2
  33. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
  34. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +7 -0
  35. data/lib/rubocop/cop/lint/shared_mutable_default.rb +3 -3
  36. data/lib/rubocop/cop/lint/useless_assignment.rb +1 -1
  37. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +2 -1
  38. data/lib/rubocop/cop/metrics/collection_literal_length.rb +7 -0
  39. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
  40. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  41. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -1
  42. data/lib/rubocop/cop/mixin/hash_subset.rb +170 -0
  43. data/lib/rubocop/cop/mixin/statement_modifier.rb +7 -2
  44. data/lib/rubocop/cop/mixin/trailing_comma.rb +2 -2
  45. data/lib/rubocop/cop/security/compound_hash.rb +1 -0
  46. data/lib/rubocop/cop/style/array_first_last.rb +18 -2
  47. data/lib/rubocop/cop/style/block_delimiters.rb +6 -19
  48. data/lib/rubocop/cop/style/collection_methods.rb +1 -1
  49. data/lib/rubocop/cop/style/conditional_assignment.rb +3 -1
  50. data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
  51. data/lib/rubocop/cop/style/exact_regexp_match.rb +1 -1
  52. data/lib/rubocop/cop/style/fetch_env_var.rb +1 -1
  53. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
  54. data/lib/rubocop/cop/style/hash_each_methods.rb +1 -1
  55. data/lib/rubocop/cop/style/hash_except.rb +5 -131
  56. data/lib/rubocop/cop/style/hash_slice.rb +65 -0
  57. data/lib/rubocop/cop/style/map_to_set.rb +3 -2
  58. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -1
  59. data/lib/rubocop/cop/style/mutable_constant.rb +1 -1
  60. data/lib/rubocop/cop/style/open_struct_use.rb +4 -4
  61. data/lib/rubocop/cop/style/raise_args.rb +1 -1
  62. data/lib/rubocop/cop/style/redundant_exception.rb +1 -1
  63. data/lib/rubocop/cop/style/redundant_freeze.rb +1 -1
  64. data/lib/rubocop/cop/style/redundant_line_continuation.rb +27 -10
  65. data/lib/rubocop/cop/style/redundant_parentheses.rb +3 -0
  66. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
  67. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
  68. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  69. data/lib/rubocop/cop/style/sole_nested_conditional.rb +1 -1
  70. data/lib/rubocop/cop/style/string_methods.rb +1 -1
  71. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -1
  72. data/lib/rubocop/cops_documentation_generator.rb +13 -13
  73. data/lib/rubocop/directive_comment.rb +9 -8
  74. data/lib/rubocop/options.rb +2 -1
  75. data/lib/rubocop/result_cache.rb +13 -13
  76. data/lib/rubocop/rspec/expect_offense.rb +6 -2
  77. data/lib/rubocop/target_finder.rb +1 -0
  78. data/lib/rubocop/version.rb +1 -1
  79. data/lib/rubocop.rb +3 -0
  80. metadata +9 -8
@@ -44,146 +44,20 @@ module RuboCop
44
44
  # {foo: 1, bar: 2, baz: 3}.except(:bar)
45
45
  #
46
46
  class HashExcept < Base
47
- include RangeHelp
47
+ include HashSubset
48
48
  extend TargetRubyVersion
49
49
  extend AutoCorrector
50
50
 
51
51
  minimum_target_ruby_version 3.0
52
52
 
53
- MSG = 'Use `%<prefer>s` instead.'
54
- RESTRICT_ON_SEND = %i[reject select filter].freeze
55
-
56
- SUBSET_METHODS = %i[== != eql? include?].freeze
57
- ACTIVE_SUPPORT_SUBSET_METHODS = (SUBSET_METHODS + %i[in? exclude?]).freeze
58
-
59
- # @!method block_with_first_arg_check?(node)
60
- def_node_matcher :block_with_first_arg_check?, <<~PATTERN
61
- (block
62
- (call _ _)
63
- (args
64
- $(arg _key)
65
- (arg _))
66
- {
67
- $(send
68
- {(lvar _key) $_ _ | _ $_ (lvar _key)})
69
- (send
70
- $(send
71
- {(lvar _key) $_ _ | _ $_ (lvar _key)}) :!)
72
- })
73
- PATTERN
74
-
75
- def on_send(node)
76
- block = node.parent
77
- return unless extracts_hash_subset?(block) && semantically_except_method?(node, block)
78
-
79
- except_key = except_key(block)
80
- return unless safe_to_register_offense?(block, except_key)
81
-
82
- range = offense_range(node)
83
- preferred_method = "except(#{except_key_source(except_key)})"
84
-
85
- add_offense(range, message: format(MSG, prefer: preferred_method)) do |corrector|
86
- corrector.replace(range, preferred_method)
87
- end
88
- end
89
- alias on_csend on_send
90
-
91
53
  private
92
54
 
93
- def extracts_hash_subset?(block)
94
- block_with_first_arg_check?(block) do |key_arg, send_node, method|
95
- return false unless supported_subset_method?(method)
96
-
97
- case method
98
- when :include?, :exclude?
99
- send_node.first_argument.source == key_arg.source
100
- when :in?
101
- send_node.receiver.source == key_arg.source
102
- else
103
- true
104
- end
105
- end
106
- end
107
-
108
- def supported_subset_method?(method)
109
- if active_support_extensions_enabled?
110
- ACTIVE_SUPPORT_SUBSET_METHODS.include?(method)
111
- else
112
- SUBSET_METHODS.include?(method)
113
- end
114
- end
115
-
116
- def semantically_except_method?(node, block)
117
- body, negated = extract_body_if_negated(block.body)
118
-
119
- if node.method?('reject')
120
- body.method?('==') || body.method?('eql?') || included?(body, negated)
121
- else
122
- body.method?('!=') || not_included?(body, negated)
123
- end
124
- end
125
-
126
- def included?(body, negated)
127
- if negated
128
- body.method?('exclude?')
129
- else
130
- body.method?('include?') || body.method?('in?')
131
- end
132
- end
133
-
134
- def not_included?(body, negated)
135
- included?(body, !negated)
136
- end
137
-
138
- def safe_to_register_offense?(block, except_key)
139
- body = block.body
140
-
141
- if body.method?('==') || body.method?('!=')
142
- except_key.sym_type? || except_key.str_type?
143
- else
144
- true
145
- end
146
- end
147
-
148
- def extract_body_if_negated(body)
149
- if body.method?('!')
150
- [body.receiver, true]
151
- else
152
- [body, false]
153
- end
154
- end
155
-
156
- def except_key_source(key)
157
- if key.array_type?
158
- key = if key.percent_literal?
159
- key.each_value.map { |v| decorate_source(v) }
160
- else
161
- key.each_value.map(&:source)
162
- end
163
- return key.join(', ')
164
- end
165
-
166
- key.literal? ? key.source : "*#{key.source}"
167
- end
168
-
169
- def decorate_source(value)
170
- return ":\"#{value.source}\"" if value.dsym_type?
171
- return "\"#{value.source}\"" if value.dstr_type?
172
- return ":#{value.source}" if value.sym_type?
173
-
174
- "'#{value.source}'"
175
- end
176
-
177
- def except_key(node)
178
- key_arg = node.argument_list.first.source
179
- body, = extract_body_if_negated(node.body)
180
- lhs, _method_name, rhs = *body
181
-
182
- lhs.source == key_arg ? rhs : lhs
55
+ def semantically_subset_method?(node)
56
+ semantically_except_method?(node)
183
57
  end
184
58
 
185
- def offense_range(node)
186
- range_between(node.loc.selector.begin_pos, node.parent.loc.end.end_pos)
59
+ def preferred_method_name
60
+ 'except'
187
61
  end
188
62
  end
189
63
  end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Checks for usages of `Hash#reject`, `Hash#select`, and `Hash#filter` methods
7
+ # that can be replaced with `Hash#slice` method.
8
+ #
9
+ # This cop should only be enabled on Ruby version 2.5 or higher.
10
+ # (`Hash#slice` was added in Ruby 2.5.)
11
+ #
12
+ # For safe detection, it is limited to commonly used string and symbol comparisons
13
+ # when using `==` or `!=`.
14
+ #
15
+ # This cop doesn't check for `Hash#delete_if` and `Hash#keep_if` because they
16
+ # modify the receiver.
17
+ #
18
+ # @safety
19
+ # This cop is unsafe because it cannot be guaranteed that the receiver
20
+ # is a `Hash` or responds to the replacement method.
21
+ #
22
+ # @example
23
+ #
24
+ # # bad
25
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| k == :bar }
26
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| k != :bar }
27
+ # {foo: 1, bar: 2, baz: 3}.filter {|k, v| k == :bar }
28
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| k.eql?(:bar) }
29
+ #
30
+ # # bad
31
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| %i[bar].include?(k) }
32
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| !%i[bar].include?(k) }
33
+ # {foo: 1, bar: 2, baz: 3}.filter {|k, v| %i[bar].include?(k) }
34
+ #
35
+ # # bad
36
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| !%i[bar].exclude?(k) }
37
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| %i[bar].exclude?(k) }
38
+ #
39
+ # # bad
40
+ # {foo: 1, bar: 2, baz: 3}.select {|k, v| k.in?(%i[bar]) }
41
+ # {foo: 1, bar: 2, baz: 3}.reject {|k, v| !k.in?(%i[bar]) }
42
+ #
43
+ # # good
44
+ # {foo: 1, bar: 2, baz: 3}.slice(:bar)
45
+ #
46
+ class HashSlice < Base
47
+ include HashSubset
48
+ extend TargetRubyVersion
49
+ extend AutoCorrector
50
+
51
+ minimum_target_ruby_version 2.5
52
+
53
+ private
54
+
55
+ def semantically_subset_method?(node)
56
+ semantically_slice_method?(node)
57
+ end
58
+
59
+ def preferred_method_name
60
+ 'slice'
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -33,8 +33,8 @@ module RuboCop
33
33
  # @!method map_to_set?(node)
34
34
  def_node_matcher :map_to_set?, <<~PATTERN
35
35
  {
36
- $(send ({block numblock} $(send _ {:map :collect}) ...) :to_set)
37
- $(send $(send _ {:map :collect} (block_pass sym)) :to_set)
36
+ $(call ({block numblock} $(call _ {:map :collect}) ...) :to_set)
37
+ $(call $(call _ {:map :collect} (block_pass sym)) :to_set)
38
38
  }
39
39
  PATTERN
40
40
 
@@ -49,6 +49,7 @@ module RuboCop
49
49
  autocorrect(corrector, to_set_node, map_node)
50
50
  end
51
51
  end
52
+ alias on_csend on_send
52
53
 
53
54
  private
54
55
 
@@ -45,6 +45,7 @@ module RuboCop
45
45
  register_offense(node)
46
46
  end
47
47
  # rubocop:enable Metrics/CyclomaticComplexity
48
+ alias on_csend on_send
48
49
 
49
50
  private
50
51
 
@@ -100,7 +101,7 @@ module RuboCop
100
101
  # `obj.method ||= value` parses as (or-asgn (send ...) ...)
101
102
  # which IS an `asgn_node`. Similarly, `obj.method += value` parses
102
103
  # as (op-asgn (send ...) ...), which is also an `asgn_node`.
103
- next if asgn_node.shorthand_asgn? && asgn_node.lhs.send_type?
104
+ next if asgn_node.shorthand_asgn? && asgn_node.lhs.call_type?
104
105
 
105
106
  yield asgn_node
106
107
  end
@@ -19,7 +19,7 @@ module RuboCop
19
19
  # acceptable value other than none, it will suppress the offenses
20
20
  # raised by this cop. It enforces frozen state.
21
21
  #
22
- # NOTE: Regexp and Range literals are frozen objects since Ruby 3.0.
22
+ # NOTE: `Regexp` and `Range` literals are frozen objects since Ruby 3.0.
23
23
  #
24
24
  # NOTE: From Ruby 3.0, interpolated strings are not frozen when
25
25
  # `# frozen-string-literal: true` is used, so this cop enforces explicit
@@ -3,15 +3,15 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Flags uses of OpenStruct, as it is now officially discouraged
6
+ # Flags uses of `OpenStruct`, as it is now officially discouraged
7
7
  # to be used for performance, version compatibility, and potential security issues.
8
8
  #
9
9
  # @safety
10
- #
11
10
  # Note that this cop may flag false positives; for instance, the following legal
12
11
  # use of a hand-rolled `OpenStruct` type would be considered an offense:
13
12
  #
14
- # ```
13
+ # [source,ruby]
14
+ # -----
15
15
  # module MyNamespace
16
16
  # class OpenStruct # not the OpenStruct we're looking for
17
17
  # end
@@ -20,7 +20,7 @@ module RuboCop
20
20
  # OpenStruct.new # resolves to MyNamespace::OpenStruct
21
21
  # end
22
22
  # end
23
- # ```
23
+ # -----
24
24
  #
25
25
  # @example
26
26
  #
@@ -14,7 +14,7 @@ module RuboCop
14
14
  # passed multiple arguments.
15
15
  #
16
16
  # The exploded style has an `AllowedCompactTypes` configuration
17
- # option that takes an Array of exception name Strings.
17
+ # option that takes an `Array` of exception name Strings.
18
18
  #
19
19
  # @safety
20
20
  # This cop is unsafe because `raise Foo` calls `Foo.exception`, not `Foo.new`.
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Checks for RuntimeError as the argument of raise/fail.
6
+ # Checks for `RuntimeError` as the argument of `raise`/`fail`.
7
7
  #
8
8
  # @example
9
9
  # # bad
@@ -5,7 +5,7 @@ module RuboCop
5
5
  module Style
6
6
  # Check for uses of `Object#freeze` on immutable objects.
7
7
  #
8
- # NOTE: Regexp and Range literals are frozen objects since Ruby 3.0.
8
+ # NOTE: `Regexp` and `Range` literals are frozen objects since Ruby 3.0.
9
9
  #
10
10
  # NOTE: From Ruby 3.0, this cop allows explicit freezing of interpolated
11
11
  # string literals when `# frozen-string-literal: true` is used.
@@ -73,10 +73,15 @@ module RuboCop
73
73
  LINE_CONTINUATION_PATTERN = /(\\\n)/.freeze
74
74
  ALLOWED_STRING_TOKENS = %i[tSTRING tSTRING_CONTENT].freeze
75
75
  ARGUMENT_TYPES = %i[
76
- kDEF kFALSE kNIL kSELF kTRUE tCONSTANT tCVAR tFLOAT tGVAR tIDENTIFIER tINTEGER tIVAR
77
- tLBRACK tLCURLY tLPAREN_ARG tSTRING tSTRING_BEG tSYMBOL tXSTRING_BEG
76
+ kDEF kDEFINED kFALSE kNIL kSELF kTRUE tAMPER tBANG tCARET tCHARACTER tCOLON3 tCONSTANT
77
+ tCVAR tDOT2 tDOT3 tFLOAT tGVAR tIDENTIFIER tINTEGER tIVAR tLAMBDA tLBRACK tLCURLY
78
+ tLPAREN_ARG tPIPE tQSYMBOLS_BEG tQWORDS_BEG tREGEXP_BEG tSTAR tSTRING tSTRING_BEG tSYMBEG
79
+ tSYMBOL tSYMBOLS_BEG tTILDE tUMINUS tUNARY_NUM tUPLUS tWORDS_BEG tXSTRING_BEG
78
80
  ].freeze
79
- ARGUMENT_TAKING_FLOW_TOKEN_TYPES = %i[tIDENTIFIER kRETURN kBREAK kNEXT kYIELD].freeze
81
+ ARGUMENT_TAKING_FLOW_TOKEN_TYPES = %i[
82
+ tIDENTIFIER kBREAK kNEXT kRETURN kSUPER kYIELD
83
+ ].freeze
84
+ ARITHMETIC_OPERATOR_TOKENS = %i[tDIVIDE tDSTAR tMINUS tPERCENT tPLUS tSTAR2].freeze
80
85
 
81
86
  def on_new_investigation
82
87
  return unless processed_source.ast
@@ -96,15 +101,20 @@ module RuboCop
96
101
  private
97
102
 
98
103
  def require_line_continuation?(range)
99
- !ends_with_backslash_without_comment?(range.source_line) ||
104
+ !ends_with_uncommented_backslash?(range) ||
100
105
  string_concatenation?(range.source_line) ||
101
- start_with_arithmetic_operator?(processed_source[range.line]) ||
106
+ start_with_arithmetic_operator?(range) ||
102
107
  inside_string_literal_or_method_with_argument?(range) ||
103
108
  leading_dot_method_chain_with_blank_line?(range)
104
109
  end
105
110
 
106
- def ends_with_backslash_without_comment?(source_line)
107
- source_line.gsub(/#.+/, '').end_with?('\\')
111
+ def ends_with_uncommented_backslash?(range)
112
+ # A line continuation always needs to be the last character on the line, which
113
+ # means that it is impossible to have a comment following a continuation.
114
+ # Therefore, if the line contains a comment, it cannot end with a continuation.
115
+ return false if processed_source.line_with_comment?(range.line)
116
+
117
+ range.source_line.end_with?(LINE_CONTINUATION)
108
118
  end
109
119
 
110
120
  def string_concatenation?(source_line)
@@ -140,7 +150,7 @@ module RuboCop
140
150
 
141
151
  def inspect_end_of_ruby_code_line_continuation
142
152
  last_line = processed_source.lines[processed_source.ast.last_line - 1]
143
- return unless last_line.end_with?(LINE_CONTINUATION)
153
+ return unless code_ends_with_continuation?(last_line)
144
154
 
145
155
  last_column = last_line.length
146
156
  line_continuation_range = range_between(last_column - 1, last_column)
@@ -150,6 +160,12 @@ module RuboCop
150
160
  end
151
161
  end
152
162
 
163
+ def code_ends_with_continuation?(last_line)
164
+ return false if processed_source.line_with_comment?(processed_source.ast.last_line)
165
+
166
+ last_line.end_with?(LINE_CONTINUATION)
167
+ end
168
+
153
169
  def inside_string_literal?(range, token)
154
170
  ALLOWED_STRING_TOKENS.include?(token.type) && token.pos.overlaps?(range)
155
171
  end
@@ -213,8 +229,9 @@ module RuboCop
213
229
  node.call_type? && !node.arguments.empty?
214
230
  end
215
231
 
216
- def start_with_arithmetic_operator?(source_line)
217
- %r{\A\s*[+\-*/%]}.match?(source_line)
232
+ def start_with_arithmetic_operator?(range)
233
+ line_range = processed_source.buffer.line_range(range.line + 1)
234
+ ARITHMETIC_OPERATOR_TOKENS.include?(processed_source.first_token_of(line_range).type)
218
235
  end
219
236
  end
220
237
  end
@@ -140,6 +140,9 @@ module RuboCop
140
140
  return 'a literal' if disallowed_literal?(begin_node, node)
141
141
  return 'a variable' if node.variable?
142
142
  return 'a constant' if node.const_type?
143
+ if node.assignment? && (begin_node.parent.nil? || begin_node.parent.begin_type?)
144
+ return 'an assignment'
145
+ end
143
146
  if node.lambda_or_proc? && (node.braces? || node.send_node.lambda_literal?)
144
147
  return 'an expression'
145
148
  end
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Checks for unnecessary single-element Regexp character classes.
6
+ # Checks for unnecessary single-element `Regexp` character classes.
7
7
  #
8
8
  # @example
9
9
  #
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Checks for redundant escapes inside Regexp literals.
6
+ # Checks for redundant escapes inside `Regexp` literals.
7
7
  #
8
8
  # @example
9
9
  # # bad
@@ -10,7 +10,7 @@ module RuboCop
10
10
  # parameters.
11
11
  #
12
12
  # Configuration option: Methods
13
- # Should be set to use this cop. Array of hashes, where each key is the
13
+ # Should be set to use this cop. `Array` of hashes, where each key is the
14
14
  # method name and value - array of argument names.
15
15
  #
16
16
  # @example Methods: [{reduce: %w[a b]}]
@@ -243,7 +243,7 @@ module RuboCop
243
243
  def replace_condition(condition)
244
244
  return condition.source unless wrap_condition?(condition)
245
245
 
246
- if condition.call_type?
246
+ if condition.call_type? && !condition.comparison_method?
247
247
  parenthesized_method_arguments(condition)
248
248
  else
249
249
  "(#{condition.source})"
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module Cop
5
5
  module Style
6
6
  # Enforces the use of consistent method names
7
- # from the String class.
7
+ # from the `String` class.
8
8
  #
9
9
  # @example
10
10
  # # bad
@@ -7,12 +7,15 @@ module RuboCop
7
7
  # The supported styles are:
8
8
  #
9
9
  # * `consistent_comma`: Requires a comma after the last argument,
10
- # for all parenthesized method calls with arguments.
10
+ # for all parenthesized multi-line method calls with arguments.
11
11
  # * `comma`: Requires a comma after the last argument, but only for
12
12
  # parenthesized method calls where each argument is on its own line.
13
13
  # * `no_comma`: Requires that there is no comma after the last
14
14
  # argument.
15
15
  #
16
+ # Regardless of style, trailing commas are not allowed in
17
+ # single-line method calls.
18
+ #
16
19
  # @example EnforcedStyleForMultiline: consistent_comma
17
20
  # # bad
18
21
  # method(1, 2,)
@@ -18,7 +18,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
18
18
  description: ->(data) { "#{data.description}\n" },
19
19
  safety: ->(data) { safety_object(data.safety_objects, data.cop) },
20
20
  examples: ->(data) { examples(data.example_objects, data.cop) },
21
- configuration: ->(data) { configurations(data.cop.department, data.config, data.cop) },
21
+ configuration: ->(data) { configurations(data.cop.department, data.cop, data.config) },
22
22
  references: ->(data) { references(data.cop, data.see_objects) }
23
23
  }.freeze
24
24
 
@@ -180,17 +180,17 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
180
180
  content
181
181
  end
182
182
 
183
- def configurations(department, pars, cop)
184
- return '' if pars.empty?
185
-
183
+ def configurations(department, cop, cop_config)
186
184
  header = ['Name', 'Default value', 'Configurable values']
187
- configs = pars
185
+ configs = cop_config
188
186
  .each_key
189
187
  .reject { |key| key.start_with?('Supported') }
190
188
  .reject { |key| key.start_with?('AllowMultipleStyles') }
189
+ return '' if configs.empty?
190
+
191
191
  content = configs.map do |name|
192
- configurable = configurable_values(pars, name)
193
- default = format_table_value(pars[name])
192
+ configurable = configurable_values(cop_config, name)
193
+ default = format_table_value(cop_config[name])
194
194
 
195
195
  [configuration_name(department, name), default, configurable]
196
196
  end
@@ -206,17 +206,17 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
206
206
  end
207
207
 
208
208
  # rubocop:disable Metrics/CyclomaticComplexity,Metrics/MethodLength
209
- def configurable_values(pars, name)
209
+ def configurable_values(cop_config, name)
210
210
  case name
211
211
  when /^Enforced/
212
212
  supported_style_name = RuboCop::Cop::Util.to_supported_styles(name)
213
- format_table_value(pars[supported_style_name])
213
+ format_table_value(cop_config[supported_style_name])
214
214
  when 'IndentationWidth'
215
215
  'Integer'
216
216
  when 'Database'
217
- format_table_value(pars['SupportedDatabases'])
217
+ format_table_value(cop_config['SupportedDatabases'])
218
218
  else
219
- case pars[name]
219
+ case cop_config[name]
220
220
  when String
221
221
  'String'
222
222
  when Integer
@@ -319,7 +319,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
319
319
  AutoCorrect Description Enabled StyleGuide Reference Safe SafeAutoCorrect VersionAdded
320
320
  VersionChanged
321
321
  ]
322
- pars = cop_config.reject { |k| non_display_keys.include? k }
322
+ parameters = cop_config.reject { |k| non_display_keys.include? k }
323
323
  description = 'No documentation'
324
324
  example_objects = safety_objects = see_objects = []
325
325
  cop_code(cop) do |code_object|
@@ -329,7 +329,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
329
329
  see_objects = code_object.tags('see')
330
330
  end
331
331
  data = CopData.new(cop: cop, description: description, example_objects: example_objects,
332
- safety_objects: safety_objects, see_objects: see_objects, config: pars)
332
+ safety_objects: safety_objects, see_objects: see_objects, config: parameters)
333
333
  cops_body(data)
334
334
  end
335
335
 
@@ -88,10 +88,15 @@ module RuboCop
88
88
  @cop_names ||= all_cops? ? all_cop_names : parsed_cop_names
89
89
  end
90
90
 
91
+ # Returns an array of cops for this directive comment, without resolving departments
92
+ def raw_cop_names
93
+ @raw_cop_names ||= (cops || '').split(/,\s*/)
94
+ end
95
+
91
96
  # Returns array of specified in this directive department names
92
97
  # when all department disabled
93
98
  def department_names
94
- splitted_cops_string.select { |cop| department?(cop) }
99
+ raw_cop_names.select { |cop| department?(cop) }
95
100
  end
96
101
 
97
102
  # Checks if directive departments include cop
@@ -101,11 +106,11 @@ module RuboCop
101
106
 
102
107
  # Checks if cop department has already used in directive comment
103
108
  def overridden_by_department?(cop)
104
- in_directive_department?(cop) && splitted_cops_string.include?(cop)
109
+ in_directive_department?(cop) && raw_cop_names.include?(cop)
105
110
  end
106
111
 
107
112
  def directive_count
108
- splitted_cops_string.count
113
+ raw_cop_names.count
109
114
  end
110
115
 
111
116
  # Returns line number for directive
@@ -115,12 +120,8 @@ module RuboCop
115
120
 
116
121
  private
117
122
 
118
- def splitted_cops_string
119
- (cops || '').split(/,\s*/)
120
- end
121
-
122
123
  def parsed_cop_names
123
- cops = splitted_cops_string.map do |name|
124
+ cops = raw_cop_names.map do |name|
124
125
  department?(name) ? cop_names_for_department(name) : name
125
126
  end.flatten
126
127
  cops - [LINT_SYNTAX_COP]
@@ -579,7 +579,8 @@ module RuboCop
579
579
  'when combined with --display-only-correctable.'],
580
580
  show_cops: ['Shows the given cops, or all cops by',
581
581
  'default, and their configurations for the',
582
- 'current directory.'],
582
+ 'current directory.',
583
+ 'You can use `*` as a wildcard.'],
583
584
  show_docs_url: ['Display url to documentation for the given',
584
585
  'cops, or base url by default.'],
585
586
  fail_fast: ['Inspect files in order of modification',