rubocop 0.84.0 → 0.85.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 (101) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +33 -15
  4. data/lib/rubocop.rb +6 -0
  5. data/lib/rubocop/cli.rb +2 -2
  6. data/lib/rubocop/cli/command/auto_genenerate_config.rb +2 -2
  7. data/lib/rubocop/comment_config.rb +1 -1
  8. data/lib/rubocop/config.rb +3 -1
  9. data/lib/rubocop/config_loader.rb +1 -1
  10. data/lib/rubocop/config_loader_resolver.rb +18 -2
  11. data/lib/rubocop/config_store.rb +12 -2
  12. data/lib/rubocop/cop/bundler/gem_comment.rb +70 -1
  13. data/lib/rubocop/cop/commissioner.rb +0 -21
  14. data/lib/rubocop/cop/cop.rb +14 -6
  15. data/lib/rubocop/cop/corrector.rb +3 -1
  16. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +1 -1
  17. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +3 -1
  18. data/lib/rubocop/cop/layout/case_indentation.rb +3 -3
  19. data/lib/rubocop/cop/layout/class_structure.rb +19 -16
  20. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +2 -2
  21. data/lib/rubocop/cop/layout/end_of_line.rb +2 -2
  22. data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -1
  23. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +1 -1
  24. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +2 -2
  25. data/lib/rubocop/cop/layout/hash_alignment.rb +6 -6
  26. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -1
  27. data/lib/rubocop/cop/layout/heredoc_indentation.rb +19 -102
  28. data/lib/rubocop/cop/layout/line_length.rb +17 -17
  29. data/lib/rubocop/cop/layout/multiline_block_layout.rb +3 -1
  30. data/lib/rubocop/cop/layout/space_around_keyword.rb +2 -2
  31. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +3 -1
  32. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +3 -1
  33. data/lib/rubocop/cop/lint/ambiguous_operator.rb +2 -1
  34. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +8 -4
  35. data/lib/rubocop/cop/lint/ensure_return.rb +1 -1
  36. data/lib/rubocop/cop/lint/erb_new_arguments.rb +3 -1
  37. data/lib/rubocop/cop/lint/loop.rb +1 -1
  38. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +62 -0
  39. data/lib/rubocop/cop/lint/nested_percent_literal.rb +1 -1
  40. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +7 -7
  41. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +3 -1
  42. data/lib/rubocop/cop/lint/redundant_require_statement.rb +3 -3
  43. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
  44. data/lib/rubocop/cop/lint/suppressed_exception.rb +4 -2
  45. data/lib/rubocop/cop/lint/unreachable_code.rb +1 -1
  46. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +1 -1
  47. data/lib/rubocop/cop/lint/useless_setter_call.rb +1 -1
  48. data/lib/rubocop/cop/migration/department_name.rb +9 -5
  49. data/lib/rubocop/cop/mixin/array_min_size.rb +3 -1
  50. data/lib/rubocop/cop/mixin/check_line_breakable.rb +3 -1
  51. data/lib/rubocop/cop/mixin/configurable_formatting.rb +1 -1
  52. data/lib/rubocop/cop/mixin/ignored_pattern.rb +1 -1
  53. data/lib/rubocop/cop/mixin/line_length_help.rb +1 -1
  54. data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +3 -1
  55. data/lib/rubocop/cop/mixin/regexp_literal_help.rb +16 -0
  56. data/lib/rubocop/cop/mixin/surrounding_space.rb +3 -1
  57. data/lib/rubocop/cop/mixin/uncommunicative_name.rb +1 -1
  58. data/lib/rubocop/cop/naming/class_and_module_camel_case.rb +11 -1
  59. data/lib/rubocop/cop/naming/file_name.rb +26 -11
  60. data/lib/rubocop/cop/naming/predicate_name.rb +1 -1
  61. data/lib/rubocop/cop/registry.rb +3 -1
  62. data/lib/rubocop/cop/style/array_join.rb +1 -1
  63. data/lib/rubocop/cop/style/bare_percent_literals.rb +1 -1
  64. data/lib/rubocop/cop/style/copyright.rb +2 -2
  65. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  66. data/lib/rubocop/cop/style/exponential_notation.rb +3 -3
  67. data/lib/rubocop/cop/style/format_string_token.rb +2 -3
  68. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -2
  69. data/lib/rubocop/cop/style/hash_each_methods.rb +1 -1
  70. data/lib/rubocop/cop/style/hash_syntax.rb +5 -3
  71. data/lib/rubocop/cop/style/inline_comment.rb +1 -1
  72. data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
  73. data/lib/rubocop/cop/style/negated_if.rb +3 -3
  74. data/lib/rubocop/cop/style/negated_unless.rb +3 -3
  75. data/lib/rubocop/cop/style/non_nil_check.rb +1 -1
  76. data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -1
  77. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +89 -0
  78. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +130 -0
  79. data/lib/rubocop/cop/style/symbol_array.rb +1 -1
  80. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +3 -3
  81. data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +3 -3
  82. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +13 -13
  83. data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +3 -3
  84. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +3 -1
  85. data/lib/rubocop/cop/style/unless_else.rb +1 -1
  86. data/lib/rubocop/cop/style/when_then.rb +1 -1
  87. data/lib/rubocop/cop/team.rb +61 -25
  88. data/lib/rubocop/cop/util.rb +1 -1
  89. data/lib/rubocop/cop/variable_force/branch.rb +3 -1
  90. data/lib/rubocop/formatter/junit_formatter.rb +14 -4
  91. data/lib/rubocop/magic_comment.rb +1 -1
  92. data/lib/rubocop/options.rb +17 -3
  93. data/lib/rubocop/result_cache.rb +4 -4
  94. data/lib/rubocop/rspec/cop_helper.rb +2 -23
  95. data/lib/rubocop/rspec/expect_offense.rb +42 -6
  96. data/lib/rubocop/rspec/shared_contexts.rb +2 -2
  97. data/lib/rubocop/runner.rb +14 -10
  98. data/lib/rubocop/target_finder.rb +3 -1
  99. data/lib/rubocop/target_ruby.rb +4 -1
  100. data/lib/rubocop/version.rb +1 -1
  101. metadata +21 -3
@@ -72,7 +72,9 @@ module RuboCop
72
72
  left = previous_token(operator)
73
73
  right = next_token(operator)
74
74
 
75
- no_space_offenses(node, operator, right, MSG) if !right.comment? && valid_right_token?(right, operator)
75
+ if !right.comment? && valid_right_token?(right, operator)
76
+ no_space_offenses(node, operator, right, MSG)
77
+ end
76
78
  return unless valid_left_token?(left, operator)
77
79
 
78
80
  no_space_offenses(node, left, operator, MSG) if add_left_offense
@@ -72,7 +72,9 @@ module RuboCop
72
72
 
73
73
  right_token = closing_bracket(tokens, left_token)
74
74
 
75
- return empty_offenses(node, left_token, right_token, EMPTY_MSG) if empty_brackets?(left_token, right_token)
75
+ if empty_brackets?(left_token, right_token)
76
+ return empty_offenses(node, left_token, right_token, EMPTY_MSG)
77
+ end
76
78
 
77
79
  if style == :no_space
78
80
  no_space_offenses(node, left_token, right_token, MSG)
@@ -63,7 +63,8 @@ module RuboCop
63
63
  first_argument = send_node.first_argument
64
64
 
65
65
  first_argument &&
66
- offense_position?(first_argument, diagnostic) && unary_operator?(first_argument, diagnostic)
66
+ offense_position?(first_argument, diagnostic) &&
67
+ unary_operator?(first_argument, diagnostic)
67
68
  end
68
69
  end
69
70
 
@@ -53,6 +53,8 @@ module RuboCop
53
53
  PATTERN
54
54
 
55
55
  def on_send(node)
56
+ return if node.arguments.any? { |arg| arg.variable? || arg.send_type? || arg.const_type? }
57
+
56
58
  add_offense(node) if algorithm_const(node)
57
59
  end
58
60
 
@@ -88,9 +90,7 @@ module RuboCop
88
90
  end
89
91
 
90
92
  def correction_range(node)
91
- begin_pos = node.loc.selector.column
92
- end_pos = node.loc.expression.last_column
93
- range_between(begin_pos, end_pos)
93
+ range_between(node.loc.dot.end_pos, node.loc.expression.end_pos)
94
94
  end
95
95
 
96
96
  def openssl_class(node)
@@ -108,7 +108,11 @@ module RuboCop
108
108
  end
109
109
 
110
110
  def sanitize_arguments(arguments)
111
- arguments.flat_map { |arg| arg.source.tr(":'", '').split('-') }
111
+ arguments.flat_map do |arg|
112
+ argument = arg.str_type? ? arg.value : arg.source
113
+
114
+ argument.tr(":'", '').split('-')
115
+ end
112
116
  end
113
117
 
114
118
  def replacement_args(node)
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # This cop checks for *return* from an *ensure* block.
6
+ # This cop checks for `return` from an `ensure` block.
7
7
  # Explicit return from an ensure block alters the control flow
8
8
  # as the return will take precedence over any exception being raised,
9
9
  # and the exception will be silently thrown away as if it were rescued.
@@ -143,7 +143,9 @@ module RuboCop
143
143
 
144
144
  overridden_kwargs[0] = "trim_mode: #{arguments[2].source}" if arguments[2]
145
145
 
146
- overridden_kwargs[1] = "eoutvar: #{arguments[3].source}" if arguments[3] && !arguments[3].hash_type?
146
+ if arguments[3] && !arguments[3].hash_type?
147
+ overridden_kwargs[1] = "eoutvar: #{arguments[3].source}"
148
+ end
147
149
 
148
150
  overridden_kwargs
149
151
  end
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # This cop checks for uses of *begin...end while/until something*.
6
+ # This cop checks for uses of `begin...end while/until something`.
7
7
  #
8
8
  # @example
9
9
  #
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Do not mix named captures and numbered captures in a Regexp literal
7
+ # because numbered capture is ignored if they're mixed.
8
+ # Replace numbered captures with non-capturing groupings or
9
+ # named captures.
10
+ #
11
+ # # bad
12
+ # /(?<foo>FOO)(BAR)/
13
+ #
14
+ # # good
15
+ # /(?<foo>FOO)(?<bar>BAR)/
16
+ #
17
+ # # good
18
+ # /(?<foo>FOO)(?:BAR)/
19
+ #
20
+ # # good
21
+ # /(FOO)(BAR)/
22
+ #
23
+ class MixedRegexpCaptureTypes < Cop
24
+ MSG = 'Do not mix named captures and numbered captures ' \
25
+ 'in a Regexp literal.'
26
+
27
+ def on_regexp(node)
28
+ return if contain_non_literal?(node)
29
+
30
+ tree = Regexp::Parser.parse(node.content)
31
+ return unless named_capture?(tree)
32
+ return unless numbered_capture?(tree)
33
+
34
+ add_offense(node)
35
+ end
36
+
37
+ private
38
+
39
+ def contain_non_literal?(node)
40
+ if node.respond_to?(:type) && (node.variable? || node.send_type? || node.const_type?)
41
+ return true
42
+ end
43
+ return false unless node.respond_to?(:children)
44
+
45
+ node.children.any? { |child| contain_non_literal?(child) }
46
+ end
47
+
48
+ def named_capture?(tree)
49
+ tree.each_expression.any? do |e|
50
+ e.instance_of?(Regexp::Expression::Group::Capture)
51
+ end
52
+ end
53
+
54
+ def numbered_capture?(tree)
55
+ tree.each_expression.any? do |e|
56
+ e.instance_of?(Regexp::Expression::Group::Named)
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -42,7 +42,7 @@ module RuboCop
42
42
  def contains_percent_literals?(node)
43
43
  node.each_child_node.any? do |child|
44
44
  literal = child.children.first.to_s.scrub
45
- REGEXES.any? { |regex| literal.match(regex) }
45
+ REGEXES.any? { |regex| literal.match?(regex) }
46
46
  end
47
47
  end
48
48
  end
@@ -6,13 +6,13 @@ module RuboCop
6
6
  # This cop checks for non-local exits from iterators without a return
7
7
  # value. It registers an offense under these conditions:
8
8
  #
9
- # - No value is returned,
10
- # - the block is preceded by a method chain,
11
- # - the block has arguments,
12
- # - the method which receives the block is not `define_method`
13
- # or `define_singleton_method`,
14
- # - the return is not contained in an inner scope, e.g. a lambda or a
15
- # method definition.
9
+ # * No value is returned,
10
+ # * the block is preceded by a method chain,
11
+ # * the block has arguments,
12
+ # * the method which receives the block is not `define_method`
13
+ # or `define_singleton_method`,
14
+ # * the return is not contained in an inner scope, e.g. a lambda or a
15
+ # method definition.
16
16
  #
17
17
  # @example
18
18
  #
@@ -44,7 +44,9 @@ module RuboCop
44
44
  private
45
45
 
46
46
  def valid_context?(node)
47
- return true unless node.arguments.one? && first_argument_starts_with_left_parenthesis?(node)
47
+ unless node.arguments.one? && first_argument_starts_with_left_parenthesis?(node)
48
+ return true
49
+ end
48
50
 
49
51
  node.operator_method? || node.setter_method? || grouped_parentheses?(node)
50
52
  end
@@ -8,9 +8,9 @@ module RuboCop
8
8
  # The following features are unnecessary `require` statement because
9
9
  # they are already loaded.
10
10
  #
11
- # ruby -ve 'p $LOADED_FEATURES.reject { |feature| %r|/| =~ feature }'
12
- # ruby 2.2.8p477 (2017-09-14 revision 59906) [x86_64-darwin13]
13
- # ["enumerator.so", "rational.so", "complex.so", "thread.rb"]
11
+ # ruby -ve 'p $LOADED_FEATURES.reject { |feature| %r|/| =~ feature }'
12
+ # ruby 2.2.8p477 (2017-09-14 revision 59906) [x86_64-darwin13]
13
+ # ["enumerator.so", "rational.so", "complex.so", "thread.rb"]
14
14
  #
15
15
  # This cop targets Ruby 2.2 or higher containing these 4 features.
16
16
  #
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # This cop checks for *rescue* blocks targeting the Exception class.
6
+ # This cop checks for `rescue` blocks targeting the Exception class.
7
7
  #
8
8
  # @example
9
9
  #
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # This cop checks for *rescue* blocks with no body.
6
+ # This cop checks for `rescue` blocks with no body.
7
7
  #
8
8
  # @example
9
9
  #
@@ -78,10 +78,12 @@ module RuboCop
78
78
 
79
79
  def comment_between_rescue_and_end?(node)
80
80
  end_line = nil
81
- node.each_ancestor(:kwbegin) do |ancestor|
81
+ node.each_ancestor(:kwbegin, :def) do |ancestor|
82
82
  end_line = ancestor.loc.end.line
83
83
  break
84
84
  end
85
+ return false unless end_line
86
+
85
87
  processed_source[node.first_line...end_line].any? { |line| comment_line?(line) }
86
88
  end
87
89
  end
@@ -5,7 +5,7 @@ module RuboCop
5
5
  module Lint
6
6
  # This cop checks for unreachable code.
7
7
  # The check are based on the presence of flow of control
8
- # statement in non-final position in *begin*(implicit) blocks.
8
+ # statement in non-final position in `begin` (implicit) blocks.
9
9
  #
10
10
  # @example
11
11
  #
@@ -5,7 +5,7 @@ module RuboCop
5
5
  module Lint
6
6
  # This cop checks for useless `else` in `begin..end` without `rescue`.
7
7
  #
8
- # Note: This syntax is no longer valid on Ruby 2.6 or higher and
8
+ # NOTE: This syntax is no longer valid on Ruby 2.6 or higher and
9
9
  # this cop is going to be removed at some point the future.
10
10
  #
11
11
  # @example
@@ -6,7 +6,7 @@ module RuboCop
6
6
  # This cop checks for setter call to local variable as the final
7
7
  # expression of a function definition.
8
8
  #
9
- # Note: There are edge cases in which the local variable references a
9
+ # NOTE: There are edge cases in which the local variable references a
10
10
  # value that is also accessible outside the local scope. This is not
11
11
  # detected by the cop, and it can yield a false positive.
12
12
  #
@@ -24,10 +24,12 @@ module RuboCop
24
24
 
25
25
  offset = Regexp.last_match(1).length
26
26
 
27
- Regexp.last_match(4).scan(/[^,]+|[\W]+/) do |name|
27
+ Regexp.last_match(4).scan(/[^,]+|\W+/) do |name|
28
28
  trimmed_name = name.strip
29
29
 
30
- check_cop_name(trimmed_name, comment, offset) unless valid_content_token?(trimmed_name)
30
+ unless valid_content_token?(trimmed_name)
31
+ check_cop_name(trimmed_name, comment, offset)
32
+ end
31
33
 
32
34
  break if contain_unexpected_character_for_department_name?(name)
33
35
 
@@ -41,7 +43,9 @@ module RuboCop
41
43
  cop_name = range.source
42
44
  qualified_cop_name = Cop.registry.qualified_cop_name(cop_name,
43
45
  nil, shall_warn)
44
- qualified_cop_name = qualified_legacy_cop_name(cop_name) unless qualified_cop_name.include?('/')
46
+ unless qualified_cop_name.include?('/')
47
+ qualified_cop_name = qualified_legacy_cop_name(cop_name)
48
+ end
45
49
 
46
50
  ->(corrector) { corrector.replace(range, qualified_cop_name) }
47
51
  end
@@ -60,8 +64,8 @@ module RuboCop
60
64
  end
61
65
 
62
66
  def valid_content_token?(content_token)
63
- !/\W+/.match(content_token).nil? ||
64
- !DISABLING_COPS_CONTENT_TOKEN.match(content_token).nil?
67
+ /\W+/.match?(content_token) ||
68
+ DISABLING_COPS_CONTENT_TOKEN.match?(content_token)
65
69
  end
66
70
 
67
71
  def contain_unexpected_character_for_department_name?(name)
@@ -38,7 +38,9 @@ module RuboCop
38
38
  def largest_brackets_size(style, ary_size)
39
39
  self.class.largest_brackets ||= -Float::INFINITY
40
40
 
41
- self.class.largest_brackets = ary_size if style == :brackets && ary_size > self.class.largest_brackets
41
+ if style == :brackets && ary_size > self.class.largest_brackets
42
+ self.class.largest_brackets = ary_size
43
+ end
42
44
 
43
45
  self.class.largest_brackets
44
46
  end
@@ -131,7 +131,9 @@ module RuboCop
131
131
  def contained_by_multiline_collection_that_could_be_broken_up?(node)
132
132
  node.each_ancestor.find do |ancestor|
133
133
  if ancestor.hash_type? || ancestor.array_type?
134
- return children_could_be_broken_up?(ancestor.children) if breakable_collection?(ancestor, ancestor.children)
134
+ if breakable_collection?(ancestor, ancestor.children)
135
+ return children_could_be_broken_up?(ancestor.children)
136
+ end
135
137
  end
136
138
 
137
139
  next unless ancestor.send_type?
@@ -23,7 +23,7 @@ module RuboCop
23
23
  end
24
24
 
25
25
  def valid_name?(node, name, given_style = style)
26
- name.match(self.class::FORMATS.fetch(given_style)) ||
26
+ name.match?(self.class::FORMATS.fetch(given_style)) ||
27
27
  class_emitter_method?(node, name)
28
28
  end
29
29
 
@@ -18,7 +18,7 @@ module RuboCop
18
18
  end
19
19
 
20
20
  def matches_ignored_pattern?(line)
21
- ignored_patterns.any? { |pattern| Regexp.new(pattern).match(line) }
21
+ ignored_patterns.any? { |pattern| Regexp.new(pattern).match?(line) }
22
22
  end
23
23
 
24
24
  def ignored_patterns
@@ -18,7 +18,7 @@ module RuboCop
18
18
 
19
19
  return false unless comment
20
20
 
21
- comment.text.match(CommentConfig::COMMENT_DIRECTIVE_REGEXP)
21
+ comment.text.match?(CommentConfig::COMMENT_DIRECTIVE_REGEXP)
22
22
  end
23
23
 
24
24
  def allow_uri?
@@ -67,7 +67,9 @@ module RuboCop
67
67
  styles << :consistent
68
68
  styles << :special_inside_parentheses unless left_parenthesis
69
69
  end
70
- styles << :special_inside_parentheses if left_parenthesis && column == left_parenthesis.column + 1
70
+ if left_parenthesis && column == left_parenthesis.column + 1
71
+ styles << :special_inside_parentheses
72
+ end
71
73
  styles << brace_alignment_style if column == left_brace.column
72
74
  styles
73
75
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # Common functionality for handling Regexp literals.
6
+ module RegexpLiteralHelp
7
+ private
8
+
9
+ def freespace_mode_regexp?(node)
10
+ regopt = node.children.find(&:regopt_type?)
11
+
12
+ regopt.children.include?(:x)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -107,7 +107,9 @@ module RuboCop
107
107
 
108
108
  def empty_offenses(node, left, right, message)
109
109
  range = range_between(left.begin_pos, right.end_pos)
110
- empty_offense(node, range, message, 'Use one') if offending_empty_space?(empty_config, left, right)
110
+ if offending_empty_space?(empty_config, left, right)
111
+ empty_offense(node, range, message, 'Use one')
112
+ end
111
113
  return unless offending_empty_no_space?(empty_config, left, right)
112
114
 
113
115
  empty_offense(node, range, message, 'Do not use')
@@ -18,7 +18,7 @@ module RuboCop
18
18
  full_name = arg.children.first.to_s
19
19
  next if full_name == '_'
20
20
 
21
- name = full_name.gsub(/\A([_]+)/, '')
21
+ name = full_name.gsub(/\A(_+)/, '')
22
22
  next if (arg.restarg_type? || arg.kwrestarg_type?) && name.empty?
23
23
  next if allowed_names.include?(name)
24
24
 
@@ -6,6 +6,12 @@ module RuboCop
6
6
  # This cop checks for class and module names with
7
7
  # an underscore in them.
8
8
  #
9
+ # `AllowedNames` config takes an array of permitted names.
10
+ # Its default value is `['module_parent']`.
11
+ # These names can be full class/module names or part of the name.
12
+ # eg. Adding `my_class` to the `AllowedNames` config will allow names like
13
+ # `my_class`, `my_class::User`, `App::my_class`, `App::my_class::User`, etc.
14
+ #
9
15
  # @example
10
16
  # # bad
11
17
  # class My_Class
@@ -18,11 +24,15 @@ module RuboCop
18
24
  # end
19
25
  # module MyModule
20
26
  # end
27
+ # class module_parent::MyModule
28
+ # end
21
29
  class ClassAndModuleCamelCase < Cop
22
30
  MSG = 'Use CamelCase for classes and modules.'
23
31
 
24
32
  def on_class(node)
25
- return unless /_/.match?(node.loc.name.source)
33
+ allowed = /#{cop_config['AllowedNames'].join('|')}/
34
+ name = node.loc.name.source.gsub(allowed, '')
35
+ return unless /_/.match?(name)
26
36
 
27
37
  add_offense(node, location: :name)
28
38
  end