rubocop 1.74.0 → 1.75.2

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 (125) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +32 -6
  4. data/config/obsoletion.yml +3 -1
  5. data/lib/rubocop/cli.rb +1 -1
  6. data/lib/rubocop/config.rb +35 -6
  7. data/lib/rubocop/config_loader.rb +4 -0
  8. data/lib/rubocop/config_obsoletion/renamed_cop.rb +18 -3
  9. data/lib/rubocop/config_obsoletion.rb +46 -2
  10. data/lib/rubocop/config_validator.rb +1 -0
  11. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +2 -1
  12. data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +6 -5
  13. data/lib/rubocop/cop/layout/block_alignment.rb +2 -2
  14. data/lib/rubocop/cop/layout/block_end_newline.rb +1 -0
  15. data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
  16. data/lib/rubocop/cop/layout/else_alignment.rb +1 -1
  17. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +3 -3
  18. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +1 -0
  19. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +1 -0
  20. data/lib/rubocop/cop/layout/indentation_width.rb +1 -0
  21. data/lib/rubocop/cop/layout/line_length.rb +5 -1
  22. data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -0
  23. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +1 -0
  24. data/lib/rubocop/cop/layout/redundant_line_break.rb +9 -5
  25. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +3 -5
  26. data/lib/rubocop/cop/layout/space_around_operators.rb +4 -1
  27. data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -0
  28. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +1 -0
  29. data/lib/rubocop/cop/lint/debugger.rb +2 -2
  30. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +1 -1
  31. data/lib/rubocop/cop/lint/duplicate_methods.rb +2 -3
  32. data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
  33. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +2 -2
  34. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -1
  35. data/lib/rubocop/cop/lint/raise_exception.rb +29 -10
  36. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +7 -4
  37. data/lib/rubocop/cop/lint/redundant_with_index.rb +3 -0
  38. data/lib/rubocop/cop/lint/redundant_with_object.rb +3 -0
  39. data/lib/rubocop/cop/lint/return_in_void_context.rb +7 -2
  40. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +8 -1
  41. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  42. data/lib/rubocop/cop/lint/to_enum_arguments.rb +1 -1
  43. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
  44. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +2 -0
  45. data/lib/rubocop/cop/lint/unreachable_code.rb +1 -0
  46. data/lib/rubocop/cop/lint/unreachable_loop.rb +5 -5
  47. data/lib/rubocop/cop/lint/useless_access_modifier.rb +1 -0
  48. data/lib/rubocop/cop/lint/void.rb +1 -0
  49. data/lib/rubocop/cop/metrics/block_length.rb +1 -0
  50. data/lib/rubocop/cop/metrics/method_length.rb +1 -0
  51. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
  52. data/lib/rubocop/cop/mixin/check_line_breakable.rb +2 -2
  53. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +1 -1
  54. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  55. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +1 -1
  56. data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +20 -0
  57. data/lib/rubocop/cop/mixin/forbidden_pattern.rb +16 -0
  58. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +0 -1
  59. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -0
  60. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
  61. data/lib/rubocop/cop/naming/method_name.rb +64 -8
  62. data/lib/rubocop/cop/naming/variable_name.rb +6 -19
  63. data/lib/rubocop/cop/registry.rb +9 -6
  64. data/lib/rubocop/cop/style/array_intersect.rb +39 -28
  65. data/lib/rubocop/cop/style/block_delimiters.rb +2 -1
  66. data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -1
  67. data/lib/rubocop/cop/style/collection_methods.rb +1 -0
  68. data/lib/rubocop/cop/style/combinable_loops.rb +1 -0
  69. data/lib/rubocop/cop/style/conditional_assignment.rb +3 -0
  70. data/lib/rubocop/cop/style/double_negation.rb +1 -1
  71. data/lib/rubocop/cop/style/empty_literal.rb +4 -0
  72. data/lib/rubocop/cop/style/explicit_block_argument.rb +2 -2
  73. data/lib/rubocop/cop/style/for.rb +1 -0
  74. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -2
  75. data/lib/rubocop/cop/style/global_std_stream.rb +3 -0
  76. data/lib/rubocop/cop/style/guard_clause.rb +2 -1
  77. data/lib/rubocop/cop/style/hash_each_methods.rb +3 -2
  78. data/lib/rubocop/cop/style/hash_fetch_chain.rb +105 -0
  79. data/lib/rubocop/cop/style/hash_syntax.rb +3 -0
  80. data/lib/rubocop/cop/style/if_inside_else.rb +10 -13
  81. data/lib/rubocop/cop/style/inverse_methods.rb +1 -0
  82. data/lib/rubocop/cop/style/invertible_unless_condition.rb +2 -2
  83. data/lib/rubocop/cop/style/ip_addresses.rb +2 -2
  84. data/lib/rubocop/cop/style/it_block_parameter.rb +100 -0
  85. data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -1
  86. data/lib/rubocop/cop/style/lambda.rb +1 -0
  87. data/lib/rubocop/cop/style/map_into_array.rb +1 -0
  88. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +1 -1
  89. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +1 -0
  90. data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -0
  91. data/lib/rubocop/cop/style/next.rb +44 -0
  92. data/lib/rubocop/cop/style/object_then.rb +1 -0
  93. data/lib/rubocop/cop/style/proc.rb +1 -0
  94. data/lib/rubocop/cop/style/raise_args.rb +8 -8
  95. data/lib/rubocop/cop/style/redundant_begin.rb +1 -0
  96. data/lib/rubocop/cop/style/redundant_condition.rb +13 -1
  97. data/lib/rubocop/cop/style/redundant_format.rb +10 -3
  98. data/lib/rubocop/cop/style/redundant_parentheses.rb +2 -1
  99. data/lib/rubocop/cop/style/redundant_self.rb +1 -0
  100. data/lib/rubocop/cop/style/redundant_sort_by.rb +17 -1
  101. data/lib/rubocop/cop/style/return_nil.rb +2 -2
  102. data/lib/rubocop/cop/style/select_by_regexp.rb +4 -1
  103. data/lib/rubocop/cop/style/single_line_do_end_block.rb +3 -1
  104. data/lib/rubocop/cop/style/sole_nested_conditional.rb +41 -100
  105. data/lib/rubocop/cop/style/super_arguments.rb +1 -2
  106. data/lib/rubocop/cop/style/symbol_proc.rb +2 -0
  107. data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -0
  108. data/lib/rubocop/cop/util.rb +1 -1
  109. data/lib/rubocop/cop/variable_force/scope.rb +1 -1
  110. data/lib/rubocop/cop/variable_force/variable.rb +2 -7
  111. data/lib/rubocop/cop/variable_force.rb +1 -1
  112. data/lib/rubocop/lsp/runtime.rb +4 -4
  113. data/lib/rubocop/lsp/stdin_runner.rb +3 -1
  114. data/lib/rubocop/magic_comment.rb +8 -0
  115. data/lib/rubocop/rspec/cop_helper.rb +4 -1
  116. data/lib/rubocop/rspec/shared_contexts.rb +20 -0
  117. data/lib/rubocop/rspec/support.rb +2 -0
  118. data/lib/rubocop/runner.rb +5 -1
  119. data/lib/rubocop/server/cache.rb +13 -10
  120. data/lib/rubocop/target_finder.rb +1 -1
  121. data/lib/rubocop/target_ruby.rb +1 -1
  122. data/lib/rubocop/version.rb +14 -7
  123. data/lib/rubocop.rb +4 -0
  124. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +20 -2
  125. metadata +10 -6
@@ -134,7 +134,7 @@ module RuboCop
134
134
  if NO_ARG_ALGORITHM.include?(algorithm_parts.first.upcase) && no_arguments
135
135
  "'#{algorithm_parts.first}'"
136
136
  else
137
- mode = 'cbc' unless size_and_mode == ['cbc']
137
+ mode = 'cbc' if size_and_mode.empty?
138
138
 
139
139
  "'#{(algorithm_parts + size_and_mode + [mode]).compact.take(3).join('-')}'"
140
140
  end
@@ -42,7 +42,6 @@ module RuboCop
42
42
  class DuplicateMethods < Base
43
43
  MSG = 'Method `%<method>s` is defined at both %<defined>s and %<current>s.'
44
44
  RESTRICT_ON_SEND = %i[alias_method attr_reader attr_writer attr_accessor attr].freeze
45
- DEF_TYPES = %i[def defs].freeze
46
45
 
47
46
  def initialize(config = nil, options = nil)
48
47
  super
@@ -162,7 +161,7 @@ module RuboCop
162
161
  end
163
162
 
164
163
  def method_key(node, method_name)
165
- if (ancestor_def = node.each_ancestor(*DEF_TYPES).first)
164
+ if (ancestor_def = node.each_ancestor(:any_def).first)
166
165
  "#{ancestor_def.method_name}.#{method_name}"
167
166
  else
168
167
  method_name
@@ -170,7 +169,7 @@ module RuboCop
170
169
  end
171
170
 
172
171
  def location(node)
173
- if DEF_TYPES.include?(node.type)
172
+ if node.any_def_type?
174
173
  node.loc.keyword.join(node.loc.name)
175
174
  else
176
175
  node.source_range
@@ -98,7 +98,7 @@ module RuboCop
98
98
  subject, = *node # rubocop:disable InternalAffairs/NodeDestructuring
99
99
  return if node.defs_type? && allowed_subject_type?(subject)
100
100
 
101
- def_ancestor = node.each_ancestor(:def, :defs).first
101
+ def_ancestor = node.each_ancestor(:any_def).first
102
102
  return unless def_ancestor
103
103
 
104
104
  within_scoping_def =
@@ -46,7 +46,7 @@ module RuboCop
46
46
  def on_return(return_node)
47
47
  return if return_value?(return_node)
48
48
 
49
- return_node.each_ancestor(:any_block, :def, :defs) do |node|
49
+ return_node.each_ancestor(:any_block, :any_def) do |node|
50
50
  break if scoped_node?(node)
51
51
 
52
52
  # if a proc is passed to `Module#define_method` or
@@ -66,7 +66,7 @@ module RuboCop
66
66
  private
67
67
 
68
68
  def scoped_node?(node)
69
- node.type?(:def, :defs) || node.lambda?
69
+ node.any_def_type? || node.lambda?
70
70
  end
71
71
 
72
72
  def return_value?(return_node)
@@ -30,7 +30,7 @@ module RuboCop
30
30
  return unless node.lhs&.casgn_type?
31
31
 
32
32
  add_offense(node.loc.operator) do |corrector|
33
- next if node.each_ancestor(:def, :defs).any?
33
+ next if node.each_ancestor(:any_def).any?
34
34
 
35
35
  corrector.replace(node.loc.operator, '=')
36
36
  end
@@ -3,15 +3,18 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Checks for `raise` or `fail` statements which are
7
- # raising `Exception` class.
6
+ # Checks for `raise` or `fail` statements which raise `Exception` or
7
+ # `Exception.new`. Use `StandardError` or a specific exception class instead.
8
8
  #
9
- # You can specify a module name that will be an implicit namespace
10
- # using `AllowedImplicitNamespaces` option. The cop cause a false positive
11
- # for namespaced `Exception` when a namespace is omitted. This option can
12
- # prevent the false positive by specifying a namespace to be omitted for
13
- # `Exception`. Alternatively, make `Exception` a fully qualified class
14
- # name with an explicit namespace.
9
+ # If you have defined your own namespaced `Exception` class, it is possible
10
+ # to configure the cop to allow it by setting `AllowedImplicitNamespaces` to
11
+ # an array with the names of the namespaces to allow. By default, this is set to
12
+ # `['Gem']`, which allows `Gem::Exception` to be raised without an explicit namespace.
13
+ # If not allowed, a false positive may be registered if `raise Exception` is called
14
+ # within the namespace.
15
+ #
16
+ # Alternatively, use a fully qualified name with `raise`/`fail`
17
+ # (eg. `raise Namespace::Exception`).
15
18
  #
16
19
  # @safety
17
20
  # This cop is unsafe because it will change the exception class being
@@ -20,15 +23,31 @@ module RuboCop
20
23
  # @example
21
24
  # # bad
22
25
  # raise Exception, 'Error message here'
26
+ # raise Exception.new('Error message here')
23
27
  #
24
28
  # # good
25
29
  # raise StandardError, 'Error message here'
30
+ # raise MyError.new, 'Error message here'
31
+ #
32
+ # @example AllowedImplicitNamespaces: ['Gem'] (default)
33
+ # # bad - `Foo` is not an allowed implicit namespace
34
+ # module Foo
35
+ # def self.foo
36
+ # raise Exception # This is qualified to `Foo::Exception`.
37
+ # end
38
+ # end
26
39
  #
27
- # @example AllowedImplicitNamespaces: ['Gem']
28
40
  # # good
29
41
  # module Gem
30
42
  # def self.foo
31
- # raise Exception # This exception means `Gem::Exception`.
43
+ # raise Exception # This is qualified to `Gem::Exception`.
44
+ # end
45
+ # end
46
+ #
47
+ # # good
48
+ # module Foo
49
+ # def self.foo
50
+ # raise Foo::Exception
32
51
  # end
33
52
  # end
34
53
  class RaiseException < Base
@@ -27,7 +27,8 @@ module RuboCop
27
27
  # In all cases, chaining one same `to_*` conversion methods listed above is redundant.
28
28
  #
29
29
  # The cop can also register an offense for chaining conversion methods on methods that are
30
- # expected to return a specific type regardless of receiver (eg. `foo.inspect.to_s`).
30
+ # expected to return a specific type regardless of receiver (eg. `foo.inspect.to_s` and
31
+ # `foo.to_json.to_s`).
31
32
  #
32
33
  # @example
33
34
  # # bad
@@ -69,10 +70,12 @@ module RuboCop
69
70
  # foo.to_s
70
71
  #
71
72
  # # bad - chaining a conversion to a method that is expected to return the same type
72
- # inspect.to_s
73
+ # foo.inspect.to_s
74
+ # foo.to_json.to_s
73
75
  #
74
76
  # # good
75
- # inspect
77
+ # foo.inspect
78
+ # foo.to_json
76
79
  #
77
80
  class RedundantTypeConversion < Base
78
81
  extend AutoCorrector
@@ -108,7 +111,7 @@ module RuboCop
108
111
 
109
112
  # Methods that already are expected to return a given type, which makes a further
110
113
  # conversion redundant.
111
- TYPED_METHODS = { to_s: %i[inspect] }.freeze
114
+ TYPED_METHODS = { to_s: %i[inspect to_json] }.freeze
112
115
 
113
116
  CONVERSION_METHODS = Set[*LITERAL_NODE_TYPES.keys].freeze
114
117
  RESTRICT_ON_SEND = CONVERSION_METHODS + [:to_d]
@@ -53,6 +53,7 @@ module RuboCop
53
53
  # rubocop:enable Metrics/AbcSize
54
54
 
55
55
  alias on_numblock on_block
56
+ alias on_itblock on_block
56
57
 
57
58
  private
58
59
 
@@ -64,6 +65,8 @@ module RuboCop
64
65
  (args (arg _)) ...)
65
66
  (numblock
66
67
  $(call _ {:each_with_index :with_index} ...) 1 ...)
68
+ (itblock
69
+ $(call _ {:each_with_index :with_index} ...) _ ...)
67
70
  }
68
71
  PATTERN
69
72
 
@@ -49,6 +49,7 @@ module RuboCop
49
49
  end
50
50
 
51
51
  alias on_numblock on_block
52
+ alias on_itblock on_block
52
53
 
53
54
  private
54
55
 
@@ -59,6 +60,8 @@ module RuboCop
59
60
  $(call _ {:each_with_object :with_object} _) (args (arg _)) ...)
60
61
  (numblock
61
62
  $(call _ {:each_with_object :with_object} _) 1 ...)
63
+ (itblock
64
+ $(call _ {:each_with_object :with_object} _) _ ...)
62
65
  }
63
66
  PATTERN
64
67
 
@@ -32,12 +32,17 @@ module RuboCop
32
32
  class ReturnInVoidContext < Base
33
33
  MSG = 'Do not return a value in `%<method>s`.'
34
34
 
35
+ # Returning out of these methods only exits the block itself.
36
+ SCOPE_CHANGING_METHODS = %i[lambda define_method define_singleton_method].freeze
37
+
35
38
  def on_return(return_node)
36
39
  return unless return_node.descendants.any?
37
40
 
38
- def_node = return_node.each_ancestor(:def).first
41
+ def_node = return_node.each_ancestor(:any_def).first
39
42
  return unless def_node&.void_context?
40
- return if return_node.each_ancestor(:any_block).any?(&:lambda?)
43
+ return if return_node.each_ancestor(:any_block).any? do |block_node|
44
+ SCOPE_CHANGING_METHODS.include?(block_node.method_name)
45
+ end
41
46
 
42
47
  add_offense(
43
48
  return_node.loc.keyword,
@@ -56,19 +56,26 @@ module RuboCop
56
56
 
57
57
  outer_local_variable = variable_table.find_variable(variable.name)
58
58
  return unless outer_local_variable
59
+ return if variable_used_in_declaration_of_outer?(variable, outer_local_variable)
59
60
  return if same_conditions_node_different_branch?(variable, outer_local_variable)
60
61
 
61
62
  message = format(MSG, variable: variable.name)
62
63
  add_offense(variable.declaration_node, message: message)
63
64
  end
64
65
 
66
+ private
67
+
68
+ def variable_used_in_declaration_of_outer?(variable, outer_local_variable)
69
+ variable.scope.node.each_ancestor.any?(outer_local_variable.declaration_node)
70
+ end
71
+
65
72
  def same_conditions_node_different_branch?(variable, outer_local_variable)
66
73
  variable_node = variable_node(variable)
67
74
  return false unless node_or_its_ascendant_conditional?(variable_node)
68
75
 
69
76
  outer_local_variable_node =
70
77
  find_conditional_node_from_ascendant(outer_local_variable.declaration_node)
71
- return true unless outer_local_variable_node
78
+ return false unless outer_local_variable_node
72
79
  return false unless outer_local_variable_node.conditional?
73
80
  return true if variable_node == outer_local_variable_node
74
81
 
@@ -116,7 +116,7 @@ module RuboCop
116
116
  private
117
117
 
118
118
  def comment_between_rescue_and_end?(node)
119
- ancestor = node.each_ancestor(:kwbegin, :def, :defs, :any_block).first
119
+ ancestor = node.each_ancestor(:kwbegin, :any_def, :any_block).first
120
120
  return false unless ancestor
121
121
 
122
122
  end_line = ancestor.loc.end&.line || ancestor.loc.last_line
@@ -45,7 +45,7 @@ module RuboCop
45
45
  PATTERN
46
46
 
47
47
  def on_send(node)
48
- def_node = node.each_ancestor(:def, :defs).first
48
+ def_node = node.each_ancestor(:any_def).first
49
49
  return unless def_node
50
50
 
51
51
  enum_conversion_call?(node) do |method_node, arguments|
@@ -40,7 +40,7 @@ module RuboCop
40
40
  # top-level return node's ancestors should not be of block, def, or
41
41
  # defs type.
42
42
  def top_level_return?(return_node)
43
- return_node.each_ancestor(:block, :def, :defs).none?
43
+ return_node.each_ancestor(:block, :any_def).none?
44
44
  end
45
45
  end
46
46
  end
@@ -53,6 +53,7 @@ module RuboCop
53
53
  end
54
54
 
55
55
  alias on_numblock on_block
56
+ alias on_itblock on_block
56
57
 
57
58
  private
58
59
 
@@ -74,6 +75,7 @@ module RuboCop
74
75
 
75
76
  def arg_count(node)
76
77
  return node.children[1] if node.numblock_type? # the maximum numbered param for the block
78
+ return 1 if node.itblock_type? # `it` block parameter is always one
77
79
 
78
80
  # Only `arg`, `optarg` and `mlhs` (destructuring) count as arguments that
79
81
  # can be used. Keyword arguments are not used for these methods so are
@@ -43,6 +43,7 @@ module RuboCop
43
43
  end
44
44
 
45
45
  alias on_numblock on_block
46
+ alias on_itblock on_block
46
47
 
47
48
  def after_block(node)
48
49
  @instance_eval_count -= 1 if instance_eval_block?(node)
@@ -101,9 +101,8 @@ module RuboCop
101
101
  check(node) if loop_method?(node)
102
102
  end
103
103
 
104
- def on_numblock(node)
105
- check(node) if loop_method?(node)
106
- end
104
+ alias on_numblock on_block
105
+ alias on_itblock on_block
107
106
 
108
107
  private
109
108
 
@@ -189,8 +188,9 @@ module RuboCop
189
188
 
190
189
  def preceded_by_continue_statement?(break_statement)
191
190
  break_statement.left_siblings.any? do |sibling|
192
- # Numblocks have the arguments count as a number in the AST.
193
- next if sibling.is_a?(Integer)
191
+ # Numblocks have the arguments count as a number or,
192
+ # itblocks have `:it` symbol in the AST.
193
+ next if sibling.is_a?(Integer) || sibling.is_a?(Symbol)
194
194
  next if sibling.loop_keyword? || loop_method?(sibling)
195
195
 
196
196
  sibling.each_descendant(*CONTINUE_KEYWORDS).any?
@@ -143,6 +143,7 @@ module RuboCop
143
143
  end
144
144
 
145
145
  alias on_numblock on_block
146
+ alias on_itblock on_block
146
147
 
147
148
  private
148
149
 
@@ -86,6 +86,7 @@ module RuboCop
86
86
  check_expression(node.body)
87
87
  end
88
88
  alias on_numblock on_block
89
+ alias on_itblock on_block
89
90
 
90
91
  def on_begin(node)
91
92
  check_begin(node)
@@ -57,6 +57,7 @@ module RuboCop
57
57
  check_code_length(node)
58
58
  end
59
59
  alias on_numblock on_block
60
+ alias on_itblock on_block
60
61
 
61
62
  private
62
63
 
@@ -63,6 +63,7 @@ module RuboCop
63
63
  check_code_length(node)
64
64
  end
65
65
  alias on_numblock on_block
66
+ alias on_itblock on_block
66
67
 
67
68
  private
68
69
 
@@ -145,7 +145,7 @@ module RuboCop
145
145
 
146
146
  def extract_body(node)
147
147
  case node.type
148
- when :class, :module, :sclass, :block, :numblock, :def, :defs
148
+ when :class, :module, :sclass, :block, :numblock, :itblock, :def, :defs
149
149
  node.body
150
150
  when :casgn
151
151
  extract_body(node.expression)
@@ -48,7 +48,7 @@ module RuboCop
48
48
 
49
49
  args = process_args(node.arguments)
50
50
  return extract_breakable_node_from_elements(node, args, max)
51
- elsif node.def_type?
51
+ elsif node.any_def_type?
52
52
  return extract_breakable_node_from_elements(node, node.arguments, max)
53
53
  elsif node.type?(:array, :hash)
54
54
  return extract_breakable_node_from_elements(node, node.children, max)
@@ -220,7 +220,7 @@ module RuboCop
220
220
 
221
221
  # @api private
222
222
  def already_on_multiple_lines?(node)
223
- return node.first_line != node.last_argument.last_line if node.def_type?
223
+ return node.first_line != node.last_argument.last_line if node.any_def_type?
224
224
 
225
225
  !node.single_line?
226
226
  end
@@ -40,7 +40,7 @@ module RuboCop
40
40
  end
41
41
 
42
42
  def safe_to_split?(node)
43
- node.each_descendant(:if, :case, :kwbegin, :def, :defs).none? &&
43
+ node.each_descendant(:if, :case, :kwbegin, :any_def).none? &&
44
44
  node.each_descendant(:dstr, :str).none? { |n| n.heredoc? || n.value.include?("\n") } &&
45
45
  node.each_descendant(:begin, :sym).none? { |b| !b.single_line? }
46
46
  end
@@ -19,7 +19,7 @@ module RuboCop
19
19
 
20
20
  # @!method non_public_modifier?(node)
21
21
  def_node_matcher :non_public_modifier?, <<~PATTERN
22
- (send nil? {:private :protected :private_class_method} ({def defs} ...))
22
+ (send nil? {:private :protected :private_class_method} (any_def ...))
23
23
  PATTERN
24
24
  end
25
25
  end
@@ -21,7 +21,7 @@ module RuboCop
21
21
 
22
22
  # @!method empty_line_required?(node)
23
23
  def_node_matcher :empty_line_required?,
24
- '{def defs class module (send nil? {:private :protected :public})}'
24
+ '{any_def class module (send nil? {:private :protected :public})}'
25
25
 
26
26
  def check(node, body, adjusted_first_line: nil)
27
27
  return if valid_body_style?(body)
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # This module encapsulates the ability to forbid certain identifiers in a cop.
6
+ module ForbiddenIdentifiers
7
+ SIGILS = '@$' # if a variable starts with a sigil it will be removed
8
+
9
+ def forbidden_identifier?(name)
10
+ name = name.to_s.delete(SIGILS)
11
+
12
+ forbidden_identifiers.any? && forbidden_identifiers.include?(name)
13
+ end
14
+
15
+ def forbidden_identifiers
16
+ cop_config.fetch('ForbiddenIdentifiers', [])
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # This module encapsulates the ability to forbid certain patterns in a cop.
6
+ module ForbiddenPattern
7
+ def forbidden_pattern?(name)
8
+ forbidden_patterns.any? { |pattern| Regexp.new(pattern).match?(name) }
9
+ end
10
+
11
+ def forbidden_patterns
12
+ cop_config.fetch('ForbiddenPatterns', [])
13
+ end
14
+ end
15
+ end
16
+ end
@@ -6,7 +6,6 @@ module RuboCop
6
6
  module FrozenStringLiteral
7
7
  module_function
8
8
 
9
- FROZEN_STRING_LITERAL_REGEXP = /#\s*frozen[-_]?string[-_]?literal:/i.freeze
10
9
  FROZEN_STRING_LITERAL_ENABLED = '# frozen_string_literal: true'
11
10
  FROZEN_STRING_LITERAL_TYPES_RUBY27 = %i[str dstr].freeze
12
11
 
@@ -30,6 +30,7 @@ module RuboCop
30
30
  end
31
31
 
32
32
  alias on_numblock on_block
33
+ alias on_itblock on_block
33
34
 
34
35
  private
35
36
 
@@ -242,7 +242,7 @@ module RuboCop
242
242
  def find_definition(node)
243
243
  # Methods can be defined in a `def` or `defs`,
244
244
  # or dynamically via a `block` node.
245
- node.each_ancestor(:def, :defs, :block).each do |ancestor|
245
+ node.each_ancestor(:any_def, :block).each do |ancestor|
246
246
  method_node, method_name = method_definition?(ancestor)
247
247
  return [method_node, method_name] if method_node
248
248
  end
@@ -6,14 +6,31 @@ module RuboCop
6
6
  # Makes sure that all methods use the configured style,
7
7
  # snake_case or camelCase, for their names.
8
8
  #
9
- # This cop has `AllowedPatterns` configuration option.
9
+ # Method names matching patterns are always allowed.
10
10
  #
11
- # Naming/MethodName:
12
- # AllowedPatterns:
13
- # - '\AonSelectionBulkChange\z'
14
- # - '\AonSelectionCleared\z'
11
+ # The cop can be configured with `AllowedPatterns` to allow certain regexp patterns:
15
12
  #
16
- # Method names matching patterns are always allowed.
13
+ # [source,yaml]
14
+ # ----
15
+ # Naming/MethodName:
16
+ # AllowedPatterns:
17
+ # - '\AonSelectionBulkChange\z'
18
+ # - '\AonSelectionCleared\z'
19
+ # ----
20
+ #
21
+ # As well, you can also forbid specific method names or regexp patterns
22
+ # using `ForbiddenIdentifiers` or `ForbiddenPatterns`:
23
+ #
24
+ # [source,yaml]
25
+ # ----
26
+ # Naming/MethodName:
27
+ # ForbiddenIdentifiers:
28
+ # - 'def'
29
+ # - 'super'
30
+ # ForbiddenPatterns:
31
+ # - '_v1\z'
32
+ # - '_gen1\z'
33
+ # ----
17
34
  #
18
35
  # @example EnforcedStyle: snake_case (default)
19
36
  # # bad
@@ -28,12 +45,26 @@ module RuboCop
28
45
  #
29
46
  # # good
30
47
  # def fooBar; end
48
+ #
49
+ # @example ForbiddenIdentifiers: ['def', 'super']
50
+ # # bad
51
+ # def def; end
52
+ # def super; end
53
+ #
54
+ # @example ForbiddenPatterns: ['_v1\z', '_gen1\z']
55
+ # # bad
56
+ # def release_v1; end
57
+ # def api_gen1; end
58
+ #
31
59
  class MethodName < Base
32
60
  include ConfigurableNaming
33
61
  include AllowedPattern
34
62
  include RangeHelp
63
+ include ForbiddenIdentifiers
64
+ include ForbiddenPattern
35
65
 
36
66
  MSG = 'Use %<style>s for method names.'
67
+ MSG_FORBIDDEN = '`%<identifier>s` is forbidden, use another method name instead.'
37
68
 
38
69
  # @!method sym_name(node)
39
70
  def_node_matcher :sym_name, '(sym $_name)'
@@ -48,19 +79,44 @@ module RuboCop
48
79
  name = attr_name(name_item)
49
80
  next if !name || matches_allowed_pattern?(name)
50
81
 
51
- check_name(node, name, range_position(node))
82
+ if forbidden_name?(name.to_s)
83
+ register_forbidden_name(node)
84
+ else
85
+ check_name(node, name, range_position(node))
86
+ end
52
87
  end
53
88
  end
54
89
 
55
90
  def on_def(node)
56
91
  return if node.operator_method? || matches_allowed_pattern?(node.method_name)
57
92
 
58
- check_name(node, node.method_name, node.loc.name)
93
+ if forbidden_name?(node.method_name.to_s)
94
+ register_forbidden_name(node)
95
+ else
96
+ check_name(node, node.method_name, node.loc.name)
97
+ end
59
98
  end
60
99
  alias on_defs on_def
61
100
 
62
101
  private
63
102
 
103
+ def forbidden_name?(name)
104
+ forbidden_identifier?(name) || forbidden_pattern?(name)
105
+ end
106
+
107
+ def register_forbidden_name(node)
108
+ if node.any_def_type?
109
+ name_node = node.loc.name
110
+ method_name = node.method_name
111
+ else
112
+ attrs = node.attribute_accessor?
113
+ name_node = attrs.last.last
114
+ method_name = attr_name(name_node)
115
+ end
116
+ message = format(MSG_FORBIDDEN, identifier: method_name)
117
+ add_offense(name_node, message: message)
118
+ end
119
+
64
120
  def attr_name(name_item)
65
121
  sym_name(name_item) || str_name(name_item)
66
122
  end
@@ -53,6 +53,8 @@ module RuboCop
53
53
  include AllowedIdentifiers
54
54
  include ConfigurableNaming
55
55
  include AllowedPattern
56
+ include ForbiddenIdentifiers
57
+ include ForbiddenPattern
56
58
 
57
59
  MSG = 'Use %<style>s for variable names.'
58
60
  MSG_FORBIDDEN = '`%<identifier>s` is forbidden, use another name instead.'
@@ -92,27 +94,12 @@ module RuboCop
92
94
 
93
95
  private
94
96
 
95
- def message(style)
96
- format(MSG, style: style)
97
- end
98
-
99
- def forbidden_identifiers
100
- cop_config.fetch('ForbiddenIdentifiers', [])
101
- end
102
-
103
- def forbidden_patterns
104
- cop_config.fetch('ForbiddenPatterns', [])
105
- end
106
-
107
- def matches_forbidden_pattern?(name)
108
- forbidden_patterns.any? { |pattern| Regexp.new(pattern).match?(name) }
109
- end
110
-
111
97
  def forbidden_name?(name)
112
- name = name.to_s.delete(SIGILS)
98
+ forbidden_identifier?(name) || forbidden_pattern?(name)
99
+ end
113
100
 
114
- (forbidden_identifiers.any? && forbidden_identifiers.include?(name)) ||
115
- (forbidden_patterns.any? && matches_forbidden_pattern?(name))
101
+ def message(style)
102
+ format(MSG, style: style)
116
103
  end
117
104
 
118
105
  def register_forbidden_name(node)