rubocop 0.80.1 → 0.81.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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +62 -15
  4. data/lib/rubocop.rb +4 -1
  5. data/lib/rubocop/ast/builder.rb +2 -0
  6. data/lib/rubocop/ast/node.rb +11 -6
  7. data/lib/rubocop/ast/node/block_node.rb +5 -1
  8. data/lib/rubocop/ast/node/case_match_node.rb +56 -0
  9. data/lib/rubocop/ast/traversal.rb +11 -9
  10. data/lib/rubocop/config_obsoletion.rb +1 -0
  11. data/lib/rubocop/cop/layout/array_alignment.rb +53 -10
  12. data/lib/rubocop/cop/layout/block_end_newline.rb +5 -3
  13. data/lib/rubocop/cop/layout/else_alignment.rb +8 -0
  14. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +1 -1
  15. data/lib/rubocop/cop/lint/boolean_symbol.rb +12 -0
  16. data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -1
  17. data/lib/rubocop/cop/lint/loop.rb +6 -4
  18. data/lib/rubocop/cop/lint/nested_method_definition.rb +2 -2
  19. data/lib/rubocop/cop/lint/raise_exception.rb +39 -0
  20. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +1 -1
  21. data/lib/rubocop/cop/lint/struct_new_override.rb +58 -0
  22. data/lib/rubocop/cop/lint/suppressed_exception.rb +12 -22
  23. data/lib/rubocop/cop/lint/unused_method_argument.rb +32 -6
  24. data/lib/rubocop/cop/migration/department_name.rb +22 -9
  25. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +6 -1
  26. data/lib/rubocop/cop/mixin/method_complexity.rb +5 -0
  27. data/lib/rubocop/cop/naming/method_name.rb +30 -0
  28. data/lib/rubocop/cop/style/access_modifier_declarations.rb +26 -6
  29. data/lib/rubocop/cop/style/collection_methods.rb +2 -0
  30. data/lib/rubocop/cop/style/documentation.rb +43 -5
  31. data/lib/rubocop/cop/style/end_block.rb +6 -0
  32. data/lib/rubocop/cop/style/hash_each_methods.rb +2 -0
  33. data/lib/rubocop/cop/style/hash_transform_keys.rb +6 -2
  34. data/lib/rubocop/cop/style/hash_transform_values.rb +6 -2
  35. data/lib/rubocop/cop/style/inverse_methods.rb +1 -1
  36. data/lib/rubocop/cop/style/lambda.rb +1 -0
  37. data/lib/rubocop/cop/style/module_function.rb +56 -10
  38. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +2 -2
  39. data/lib/rubocop/cop/style/one_line_conditional.rb +3 -2
  40. data/lib/rubocop/cop/style/redundant_sort.rb +2 -2
  41. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +34 -0
  42. data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +41 -0
  43. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +85 -0
  44. data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +44 -0
  45. data/lib/rubocop/formatter/clang_style_formatter.rb +1 -1
  46. data/lib/rubocop/formatter/junit_formatter.rb +17 -6
  47. data/lib/rubocop/formatter/tap_formatter.rb +1 -1
  48. data/lib/rubocop/processed_source.rb +1 -1
  49. data/lib/rubocop/version.rb +1 -1
  50. metadata +8 -5
  51. data/lib/rubocop/cop/lint/end_in_method.rb +0 -40
@@ -14,19 +14,24 @@ module RuboCop
14
14
  /\A(# *rubocop *: *((dis|en)able|todo) +)(.*)/.freeze
15
15
 
16
16
  # The token that makes up a disable comment.
17
- # The token used after `# rubocop: disable` are `A-z`, `/`, and `,`.
18
- # Also `A-z` includes `all`.
19
- DISABLING_COPS_CONTENT_TOKEN = %r{[A-z/,]+}.freeze
17
+ # The allowed specification for comments after `# rubocop: disable` is
18
+ # `DepartmentName/CopName` or` all`.
19
+ DISABLING_COPS_CONTENT_TOKEN = %r{[A-z]+/[A-z]+|all}.freeze
20
20
 
21
21
  def investigate(processed_source)
22
22
  processed_source.each_comment do |comment|
23
23
  next if comment.text !~ DISABLE_COMMENT_FORMAT
24
24
 
25
25
  offset = Regexp.last_match(1).length
26
- Regexp.last_match(4).scan(%r{[\w/]+|\W+}) do |name|
27
- break unless valid_content_token?(name.strip)
28
26
 
29
- check_cop_name(name, comment, offset)
27
+ Regexp.last_match(4).scan(/[^,]+|[\W]+/) do |name|
28
+ trimmed_name = name.strip
29
+
30
+ break if contain_plain_comment?(trimmed_name)
31
+
32
+ unless valid_content_token?(trimmed_name)
33
+ check_cop_name(trimmed_name, comment, offset)
34
+ end
30
35
 
31
36
  offset += name.length
32
37
  end
@@ -47,16 +52,24 @@ module RuboCop
47
52
 
48
53
  private
49
54
 
50
- def check_cop_name(name, comment, offset)
51
- return if name !~ /^[A-Z]/ || name =~ %r{/}
55
+ def disable_comment_offset
56
+ Regexp.last_match(1).length
57
+ end
52
58
 
59
+ def check_cop_name(name, comment, offset)
53
60
  start = comment.location.expression.begin_pos + offset
54
61
  range = range_between(start, start + name.length)
62
+
55
63
  add_offense(range, location: range)
56
64
  end
57
65
 
58
66
  def valid_content_token?(content_token)
59
- !DISABLING_COPS_CONTENT_TOKEN.match(content_token).nil?
67
+ !/\W+/.match(content_token).nil? ||
68
+ !DISABLING_COPS_CONTENT_TOKEN.match(content_token).nil?
69
+ end
70
+
71
+ def contain_plain_comment?(name)
72
+ name == '#'
60
73
  end
61
74
 
62
75
  def qualified_legacy_cop_name(cop_name)
@@ -20,7 +20,7 @@ module RuboCop
20
20
  return if ignored_node?(node)
21
21
 
22
22
  end_loc = node.loc.end
23
- return unless end_loc # Discard modifier forms of if/while/until.
23
+ return if accept_end_kw_alignment?(end_loc)
24
24
 
25
25
  matching = matching_ranges(end_loc, align_ranges)
26
26
 
@@ -49,6 +49,11 @@ module RuboCop
49
49
  add_offense(node, location: end_loc, message: msg)
50
50
  end
51
51
 
52
+ def accept_end_kw_alignment?(end_loc)
53
+ end_loc.nil? || # Discard modifier forms of if/while/until.
54
+ processed_source.lines[end_loc.line - 1] !~ /\A[ \t]*end/
55
+ end
56
+
52
57
  def style_parameter_name
53
58
  'EnforcedStyleAlignWith'
54
59
  end
@@ -5,15 +5,20 @@ module RuboCop
5
5
  # This module handles measurement and reporting of complexity in methods.
6
6
  module MethodComplexity
7
7
  include ConfigurableMax
8
+ include IgnoredMethods
8
9
  extend NodePattern::Macros
9
10
 
10
11
  def on_def(node)
12
+ return if ignored_method?(node.method_name)
13
+
11
14
  check_complexity(node, node.method_name)
12
15
  end
13
16
  alias on_defs on_def
14
17
 
15
18
  def on_block(node)
16
19
  define_method?(node) do |name|
20
+ return if ignored_method?(name)
21
+
17
22
  check_complexity(node, name)
18
23
  end
19
24
  end
@@ -31,9 +31,28 @@ module RuboCop
31
31
  class MethodName < Cop
32
32
  include ConfigurableNaming
33
33
  include IgnoredPattern
34
+ include RangeHelp
34
35
 
35
36
  MSG = 'Use %<style>s for method names.'
36
37
 
38
+ def_node_matcher :attr?, <<~PATTERN
39
+ (send nil? ${:attr_reader :attr_writer :attr_accessor :attr} $...)
40
+ PATTERN
41
+
42
+ def_node_matcher :sym_name, '(sym $_name)'
43
+ def_node_matcher :str_name, '(str $_name)'
44
+
45
+ def on_send(node)
46
+ return unless (attrs = attr?(node))
47
+
48
+ attrs.last.each do |name_item|
49
+ name = attr_name(name_item)
50
+ next if !name || matches_ignored_pattern?(name)
51
+
52
+ check_name(node, name, range_position(node))
53
+ end
54
+ end
55
+
37
56
  def on_def(node)
38
57
  return if node.operator_method? ||
39
58
  matches_ignored_pattern?(node.method_name)
@@ -44,6 +63,17 @@ module RuboCop
44
63
 
45
64
  private
46
65
 
66
+ def attr_name(name_item)
67
+ sym_name(name_item) || str_name(name_item)
68
+ end
69
+
70
+ def range_position(node)
71
+ selector_end_pos = node.loc.selector.end_pos + 1
72
+ expr_end_pos = node.loc.expression.end_pos
73
+
74
+ range_between(selector_end_pos, expr_end_pos)
75
+ end
76
+
47
77
  def message(style)
48
78
  format(MSG, style: style)
49
79
  end
@@ -5,11 +5,12 @@ module RuboCop
5
5
  module Style
6
6
  # Access modifiers should be declared to apply to a group of methods
7
7
  # or inline before each method, depending on configuration.
8
+ # EnforcedStyle config covers only method definitions.
9
+ # Applications of visibility methods to symbols can be controlled
10
+ # using AllowModifiersOnSymbols config.
8
11
  #
9
12
  # @example EnforcedStyle: group (default)
10
- #
11
13
  # # bad
12
- #
13
14
  # class Foo
14
15
  #
15
16
  # private def bar; end
@@ -18,7 +19,6 @@ module RuboCop
18
19
  # end
19
20
  #
20
21
  # # good
21
- #
22
22
  # class Foo
23
23
  #
24
24
  # private
@@ -27,10 +27,9 @@ module RuboCop
27
27
  # def baz; end
28
28
  #
29
29
  # end
30
- # @example EnforcedStyle: inline
31
30
  #
31
+ # @example EnforcedStyle: inline
32
32
  # # bad
33
- #
34
33
  # class Foo
35
34
  #
36
35
  # private
@@ -41,13 +40,28 @@ module RuboCop
41
40
  # end
42
41
  #
43
42
  # # good
44
- #
45
43
  # class Foo
46
44
  #
47
45
  # private def bar; end
48
46
  # private def baz; end
49
47
  #
50
48
  # end
49
+ #
50
+ # @example AllowModifiersOnSymbols: true
51
+ # # good
52
+ # class Foo
53
+ #
54
+ # private :bar, :baz
55
+ #
56
+ # end
57
+ #
58
+ # @example AllowModifiersOnSymbols: false
59
+ # # bad
60
+ # class Foo
61
+ #
62
+ # private :bar, :baz
63
+ #
64
+ # end
51
65
  class AccessModifierDeclarations < Cop
52
66
  include ConfigurableEnforcedStyle
53
67
 
@@ -61,9 +75,15 @@ module RuboCop
61
75
  'inlined in method definitions.'
62
76
  ].join(' ')
63
77
 
78
+ def_node_matcher :access_modifier_with_symbol?, <<~PATTERN
79
+ (send nil? {:private :protected :public} (sym _))
80
+ PATTERN
81
+
64
82
  def on_send(node)
65
83
  return unless node.access_modifier?
66
84
  return if node.parent.pair_type?
85
+ return if cop_config['AllowModifiersOnSymbols'] &&
86
+ access_modifier_with_symbol?(node)
67
87
 
68
88
  if offense?(node)
69
89
  add_offense(node, location: :selector) do
@@ -27,6 +27,7 @@ module RuboCop
27
27
  # items.inject
28
28
  # items.detect
29
29
  # items.find_all
30
+ # items.member?
30
31
  #
31
32
  # # good
32
33
  # items.map
@@ -34,6 +35,7 @@ module RuboCop
34
35
  # items.reduce
35
36
  # items.find
36
37
  # items.select
38
+ # items.include?
37
39
  #
38
40
  class CollectionMethods < Cop
39
41
  include MethodPreference
@@ -3,10 +3,11 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # This cop checks for missing top-level documentation of
7
- # classes and modules. Classes with no body are exempt from the
8
- # check and so are namespace modules - modules that have nothing in
9
- # their bodies except classes, other modules, or constant definitions.
6
+ # This cop checks for missing top-level documentation of classes and
7
+ # modules. Classes with no body are exempt from the check and so are
8
+ # namespace modules - modules that have nothing in their bodies except
9
+ # classes, other modules, constant definitions or constant visibility
10
+ # declarations.
10
11
  #
11
12
  # The documentation requirement is annulled if the class or module has
12
13
  # a "#:nodoc:" comment next to it. Likewise, "#:nodoc: all" does the
@@ -18,12 +19,42 @@ module RuboCop
18
19
  # # ...
19
20
  # end
20
21
  #
22
+ # module Math
23
+ # end
24
+ #
21
25
  # # good
22
26
  # # Description/Explanation of Person class
23
27
  # class Person
24
28
  # # ...
25
29
  # end
26
30
  #
31
+ # # allowed
32
+ # # Class without body
33
+ # class Person
34
+ # end
35
+ #
36
+ # # Namespace - A namespace can be a class or a module
37
+ # # Containing a class
38
+ # module Namespace
39
+ # # Description/Explanation of Person class
40
+ # class Person
41
+ # # ...
42
+ # end
43
+ # end
44
+ #
45
+ # # Containing constant visibility declaration
46
+ # module Namespace
47
+ # class Private
48
+ # end
49
+ #
50
+ # private_constant :Private
51
+ # end
52
+ #
53
+ # # Containing constant definition
54
+ # module Namespace
55
+ # Public = Class.new
56
+ # end
57
+ #
27
58
  class Documentation < Cop
28
59
  include DocumentationComment
29
60
 
@@ -31,6 +62,9 @@ module RuboCop
31
62
 
32
63
  def_node_matcher :constant_definition?, '{class module casgn}'
33
64
  def_node_search :outer_module, '(const (const nil? _) _)'
65
+ def_node_matcher :constant_visibility_declaration?, <<~PATTERN
66
+ (send nil? {:public_constant :private_constant} ({sym str} _))
67
+ PATTERN
34
68
 
35
69
  def on_class(node)
36
70
  return unless node.body
@@ -59,12 +93,16 @@ module RuboCop
59
93
  return false unless node
60
94
 
61
95
  if node.begin_type?
62
- node.children.all? { |child| constant_definition?(child) }
96
+ node.children.all?(&method(:constant_declaration?))
63
97
  else
64
98
  constant_definition?(node)
65
99
  end
66
100
  end
67
101
 
102
+ def constant_declaration?(node)
103
+ constant_definition?(node) || constant_visibility_declaration?(node)
104
+ end
105
+
68
106
  def compact_namespace?(node)
69
107
  node.loc.name.source =~ /::/
70
108
  end
@@ -19,6 +19,12 @@ module RuboCop
19
19
  def on_postexe(node)
20
20
  add_offense(node, location: :keyword)
21
21
  end
22
+
23
+ def autocorrect(node)
24
+ lambda do |corrector|
25
+ corrector.replace(node.loc.keyword, 'at_exit')
26
+ end
27
+ end
22
28
  end
23
29
  end
24
30
  end
@@ -40,6 +40,8 @@ module RuboCop
40
40
 
41
41
  def register_kv_offense(node)
42
42
  kv_each(node) do |target, method|
43
+ return unless target.receiver.receiver
44
+
43
45
  msg = format(message, prefer: "each_#{method[0..-2]}",
44
46
  current: "#{method}.each")
45
47
 
@@ -31,7 +31,9 @@ module RuboCop
31
31
 
32
32
  def_node_matcher :on_bad_each_with_object, <<~PATTERN
33
33
  (block
34
- ({send csend} !(send _ :each_with_index) :each_with_object (hash))
34
+ ({send csend}
35
+ !{(send _ :each_with_index) (array ...)}
36
+ :each_with_object (hash))
35
37
  (args
36
38
  (mlhs
37
39
  (arg $_)
@@ -55,7 +57,9 @@ module RuboCop
55
57
  def_node_matcher :on_bad_map_to_h, <<~PATTERN
56
58
  ({send csend}
57
59
  (block
58
- ({send csend} !(send _ :each_with_index) {:map :collect})
60
+ ({send csend}
61
+ !{(send _ :each_with_index) (array ...)}
62
+ {:map :collect})
59
63
  (args
60
64
  (arg $_)
61
65
  (arg _val))
@@ -31,7 +31,9 @@ module RuboCop
31
31
 
32
32
  def_node_matcher :on_bad_each_with_object, <<~PATTERN
33
33
  (block
34
- ({send csend} !(send _ :each_with_index) :each_with_object (hash))
34
+ ({send csend}
35
+ !{(send _ :each_with_index) (array ...)}
36
+ :each_with_object (hash))
35
37
  (args
36
38
  (mlhs
37
39
  (arg _key)
@@ -55,7 +57,9 @@ module RuboCop
55
57
  def_node_matcher :on_bad_map_to_h, <<~PATTERN
56
58
  ({send csend}
57
59
  (block
58
- ({send csend} !(send _ :each_with_index) {:map :collect})
60
+ ({send csend}
61
+ !{(send _ :each_with_index) (array ...)}
62
+ {:map :collect})
59
63
  (args
60
64
  (arg _key)
61
65
  (arg $_))
@@ -44,7 +44,7 @@ module RuboCop
44
44
  CAMEL_CASE = /[A-Z]+[a-z]+/.freeze
45
45
 
46
46
  def self.autocorrect_incompatible_with
47
- [Style::Not]
47
+ [Style::Not, Style::SymbolProc]
48
48
  end
49
49
 
50
50
  def_node_matcher :inverse_candidate?, <<~PATTERN
@@ -73,6 +73,7 @@ module RuboCop
73
73
  location: node.send_node.source_range,
74
74
  message: message(node, selector))
75
75
  end
76
+ alias on_numblock on_block
76
77
 
77
78
  def autocorrect(node)
78
79
  if node.send_node.source == 'lambda'
@@ -6,7 +6,7 @@ module RuboCop
6
6
  # This cop checks for use of `extend self` or `module_function` in a
7
7
  # module.
8
8
  #
9
- # Supported styles are: module_function, extend_self.
9
+ # Supported styles are: module_function, extend_self, forbidden.
10
10
  #
11
11
  # @example EnforcedStyle: module_function (default)
12
12
  # # bad
@@ -46,6 +46,29 @@ module RuboCop
46
46
  # # ...
47
47
  # end
48
48
  #
49
+ # The option `forbidden` prohibits the usage of both styles.
50
+ #
51
+ # @example EnforcedStyle: forbidden
52
+ # # bad
53
+ # module Test
54
+ # module_function
55
+ # # ...
56
+ # end
57
+ #
58
+ # # bad
59
+ # module Test
60
+ # extend self
61
+ # # ...
62
+ # end
63
+ #
64
+ # # bad
65
+ # module Test
66
+ # extend self
67
+ # # ...
68
+ # private
69
+ # # ...
70
+ # end
71
+ #
49
72
  # These offenses are not safe to auto-correct since there are different
50
73
  # implications to each approach.
51
74
  class ModuleFunction < Cop
@@ -55,6 +78,8 @@ module RuboCop
55
78
  'Use `module_function` instead of `extend self`.'
56
79
  EXTEND_SELF_MSG =
57
80
  'Use `extend self` instead of `module_function`.'
81
+ FORBIDDEN_MSG =
82
+ 'Do not use `module_function` or `extend self`.'
58
83
 
59
84
  def_node_matcher :module_function_node?, '(send nil? :module_function)'
60
85
  def_node_matcher :extend_self_node?, '(send nil? :extend self)'
@@ -69,6 +94,8 @@ module RuboCop
69
94
  end
70
95
 
71
96
  def autocorrect(node)
97
+ return if style == :forbidden
98
+
72
99
  lambda do |corrector|
73
100
  if extend_self_node?(node)
74
101
  corrector.replace(node.source_range, 'module_function')
@@ -80,22 +107,41 @@ module RuboCop
80
107
 
81
108
  private
82
109
 
83
- def each_wrong_style(nodes)
110
+ def each_wrong_style(nodes, &block)
84
111
  case style
85
112
  when :module_function
86
- private_directive = nodes.any? { |node| private_directive?(node) }
87
-
88
- nodes.each do |node|
89
- yield node if extend_self_node?(node) && !private_directive
90
- end
113
+ check_module_function(nodes, &block)
91
114
  when :extend_self
92
- nodes.each do |node|
93
- yield node if module_function_node?(node)
94
- end
115
+ check_extend_self(nodes, &block)
116
+ when :forbidden
117
+ check_forbidden(nodes, &block)
118
+ end
119
+ end
120
+
121
+ def check_module_function(nodes)
122
+ private_directive = nodes.any? { |node| private_directive?(node) }
123
+
124
+ nodes.each do |node|
125
+ yield node if extend_self_node?(node) && !private_directive
126
+ end
127
+ end
128
+
129
+ def check_extend_self(nodes)
130
+ nodes.each do |node|
131
+ yield node if module_function_node?(node)
132
+ end
133
+ end
134
+
135
+ def check_forbidden(nodes)
136
+ nodes.each do |node|
137
+ yield node if extend_self_node?(node)
138
+ yield node if module_function_node?(node)
95
139
  end
96
140
  end
97
141
 
98
142
  def message(_node)
143
+ return FORBIDDEN_MSG if style == :forbidden
144
+
99
145
  style == :module_function ? MODULE_FUNCTION_MSG : EXTEND_SELF_MSG
100
146
  end
101
147
  end