rubocop 0.80.1 → 0.81.0

Sign up to get free protection for your applications and to get access to all the features.
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