rubocop 0.45.0 → 0.46.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rubocop might be problematic. Click here for more details.

Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +17 -0
  4. data/config/enabled.yml +29 -2
  5. data/lib/rubocop.rb +6 -1
  6. data/lib/rubocop/config.rb +0 -10
  7. data/lib/rubocop/config_loader.rb +21 -9
  8. data/lib/rubocop/cop/bundler/duplicated_gem.rb +69 -0
  9. data/lib/rubocop/cop/bundler/ordered_gems.rb +54 -0
  10. data/lib/rubocop/cop/cop.rb +1 -0
  11. data/lib/rubocop/cop/lint/debugger.rb +9 -1
  12. data/lib/rubocop/cop/lint/each_with_object_argument.rb +5 -6
  13. data/lib/rubocop/cop/lint/eval.rb +3 -7
  14. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +6 -4
  15. data/lib/rubocop/cop/lint/unneeded_splat_expansion.rb +13 -4
  16. data/lib/rubocop/cop/lint/useless_comparison.rb +5 -9
  17. data/lib/rubocop/cop/lint/useless_setter_call.rb +1 -0
  18. data/lib/rubocop/cop/metrics/line_length.rb +16 -3
  19. data/lib/rubocop/cop/mixin/access_modifier_node.rb +9 -9
  20. data/lib/rubocop/cop/mixin/configurable_numbering.rb +14 -7
  21. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +92 -20
  22. data/lib/rubocop/cop/performance/compare_with_block.rb +61 -0
  23. data/lib/rubocop/cop/performance/count.rb +21 -57
  24. data/lib/rubocop/cop/performance/detect.rb +15 -15
  25. data/lib/rubocop/cop/performance/flat_map.rb +23 -35
  26. data/lib/rubocop/cop/performance/sample.rb +84 -82
  27. data/lib/rubocop/cop/performance/string_replacement.rb +18 -43
  28. data/lib/rubocop/cop/rails/enum_uniqueness.rb +71 -0
  29. data/lib/rubocop/cop/rails/http_positional_arguments.rb +1 -1
  30. data/lib/rubocop/cop/rails/output.rb +8 -12
  31. data/lib/rubocop/cop/rails/read_write_attribute.rb +10 -6
  32. data/lib/rubocop/cop/rails/request_referer.rb +8 -9
  33. data/lib/rubocop/cop/rails/scope_args.rb +5 -11
  34. data/lib/rubocop/cop/style/access_modifier_indentation.rb +1 -1
  35. data/lib/rubocop/cop/style/and_or.rb +1 -1
  36. data/lib/rubocop/cop/style/array_join.rb +4 -8
  37. data/lib/rubocop/cop/style/block_comments.rb +1 -1
  38. data/lib/rubocop/cop/style/case_equality.rb +3 -3
  39. data/lib/rubocop/cop/style/character_literal.rb +2 -4
  40. data/lib/rubocop/cop/style/class_check.rb +6 -6
  41. data/lib/rubocop/cop/style/colon_method_call.rb +6 -6
  42. data/lib/rubocop/cop/style/each_with_object.rb +13 -17
  43. data/lib/rubocop/cop/style/empty_literal.rb +46 -36
  44. data/lib/rubocop/cop/style/empty_method.rb +96 -0
  45. data/lib/rubocop/cop/style/even_odd.rb +19 -50
  46. data/lib/rubocop/cop/style/hash_syntax.rb +4 -1
  47. data/lib/rubocop/cop/style/lambda.rb +8 -18
  48. data/lib/rubocop/cop/style/module_function.rb +14 -11
  49. data/lib/rubocop/cop/style/nil_comparison.rb +4 -7
  50. data/lib/rubocop/cop/style/non_nil_check.rb +18 -36
  51. data/lib/rubocop/cop/style/numeric_predicate.rb +9 -10
  52. data/lib/rubocop/cop/style/op_method.rb +7 -9
  53. data/lib/rubocop/cop/style/parallel_assignment.rb +1 -1
  54. data/lib/rubocop/cop/style/proc.rb +5 -9
  55. data/lib/rubocop/cop/style/redundant_freeze.rb +6 -7
  56. data/lib/rubocop/cop/style/send.rb +6 -3
  57. data/lib/rubocop/cop/style/space_inside_block_braces.rb +1 -1
  58. data/lib/rubocop/cop/style/special_global_vars.rb +3 -3
  59. data/lib/rubocop/cop/style/symbol_proc.rb +22 -43
  60. data/lib/rubocop/cop/style/ternary_parentheses.rb +67 -18
  61. data/lib/rubocop/cop/util.rb +1 -1
  62. data/lib/rubocop/cop/variable_force/assignment.rb +2 -0
  63. data/lib/rubocop/cop/variable_force/locatable.rb +8 -6
  64. data/lib/rubocop/cop/variable_force/reference.rb +2 -0
  65. data/lib/rubocop/formatter/base_formatter.rb +4 -8
  66. data/lib/rubocop/formatter/fuubar_style_formatter.rb +6 -0
  67. data/lib/rubocop/node_pattern.rb +7 -5
  68. data/lib/rubocop/processed_source.rb +1 -0
  69. data/lib/rubocop/rspec/cop_helper.rb +4 -0
  70. data/lib/rubocop/rspec/host_environment_simulation_helper.rb +1 -1
  71. data/lib/rubocop/version.rb +1 -1
  72. metadata +7 -3
  73. data/lib/rubocop/cop/performance/sort_with_block.rb +0 -53
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ # This cop looks for duplicate values in enum declarations.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # enum status: { active: 0, archived: 0 }
11
+ #
12
+ # # good
13
+ # enum status: { active: 0, archived: 1 }
14
+ #
15
+ # # bad
16
+ # enum status: [:active, :archived, :active]
17
+ #
18
+ # # good
19
+ # enum status: [:active, :archived]
20
+ class EnumUniqueness < Cop
21
+ MSG = 'Duplicate value `%s` found in `%s` enum declaration.'.freeze
22
+
23
+ def on_send(node)
24
+ _receiver, method_name, *args = *node
25
+
26
+ return unless method_name == :enum
27
+
28
+ enum_name, enum_args = parse_args(args)
29
+
30
+ dupes = arr_dupes(enum_values(enum_args))
31
+ return if dupes.empty?
32
+
33
+ add_offense(node, :selector, format(MSG, dupes.join(','), enum_name))
34
+ end
35
+
36
+ private
37
+
38
+ def enum_values(enum_args)
39
+ if enum_args.type == :array
40
+ enum_array_keys(enum_args)
41
+ else
42
+ enum_hash_values(enum_args)
43
+ end
44
+ end
45
+
46
+ def enum_array_keys(array_node)
47
+ array_node.each_child_node.map(&:source)
48
+ end
49
+
50
+ def enum_hash_values(hash_node)
51
+ hash_node.each_child_node.map do |child_node|
52
+ child_node.child_nodes.last.source
53
+ end
54
+ end
55
+
56
+ def arr_dupes(array)
57
+ array.select { |element| array.count(element) > 1 }.uniq
58
+ end
59
+
60
+ def parse_args(args)
61
+ enum_config = args.first.each_child_node.first.child_nodes
62
+
63
+ enum_name = enum_config.first.source
64
+ enum_opts = enum_config.last
65
+
66
+ [enum_name, enum_opts]
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -18,7 +18,7 @@ module RuboCop
18
18
  'positional arguments for http call: `%s`.'.freeze
19
19
  KEYWORD_ARGS = [
20
20
  :headers, :env, :params, :body, :flash, :as,
21
- :xhr, :session, :method
21
+ :xhr, :session, :method, :format
22
22
  ].freeze
23
23
  HTTP_METHODS = [:get, :post, :put, :patch, :delete, :head].freeze
24
24
 
@@ -6,22 +6,18 @@ module RuboCop
6
6
  # This cop checks for the use of output calls like puts and print
7
7
  class Output < Cop
8
8
  MSG = 'Do not write to stdout. ' \
9
- 'Use Rails\' logger if you want to log.'.freeze
9
+ "Use Rails's logger if you want to log.".freeze
10
10
 
11
- BLACKLIST = [:puts,
12
- :print,
13
- :p,
14
- :pp,
15
- :pretty_print,
16
- :ap].freeze
11
+ def_node_matcher :output?, <<-PATTERN
12
+ (send nil {:ap :p :pp :pretty_print :print :puts} $...)
13
+ PATTERN
17
14
 
18
15
  def on_send(node)
19
- receiver, method_name, *args = *node
20
- return unless receiver.nil? &&
21
- !args.empty? &&
22
- BLACKLIST.include?(method_name)
16
+ output?(node) do |args|
17
+ return if args.empty?
23
18
 
24
- add_offense(node, :selector)
19
+ add_offense(node, :selector)
20
+ end
25
21
  end
26
22
  end
27
23
  end
@@ -18,13 +18,17 @@ module RuboCop
18
18
  class ReadWriteAttribute < Cop
19
19
  MSG = 'Prefer `%s` over `%s`.'.freeze
20
20
 
21
- def on_send(node)
22
- receiver, method_name, *_args = *node
23
- return if receiver
24
- return unless [:read_attribute,
25
- :write_attribute].include?(method_name)
21
+ def_node_matcher :read_write_attribute?, <<-PATTERN
22
+ {
23
+ (send nil :read_attribute _)
24
+ (send nil :write_attribute _ _)
25
+ }
26
+ PATTERN
26
27
 
27
- add_offense(node, :selector)
28
+ def on_send(node)
29
+ read_write_attribute?(node) do
30
+ add_offense(node, :selector)
31
+ end
28
32
  end
29
33
 
30
34
  def message(node)
@@ -8,10 +8,15 @@ module RuboCop
8
8
  class RequestReferer < Cop
9
9
  include ConfigurableEnforcedStyle
10
10
 
11
- def on_send(node)
12
- return unless offense?(node)
11
+ def_node_matcher :referer?, <<-PATTERN
12
+ (send (send nil :request) ${:referer :referrer})
13
+ PATTERN
13
14
 
14
- add_offense(node.source_range, node.source_range, message)
15
+ def on_send(node)
16
+ referer?(node) do |method_name|
17
+ return unless method_name == wrong_method_name
18
+ add_offense(node.source_range, node.source_range, message)
19
+ end
15
20
  end
16
21
 
17
22
  def autocorrect(node)
@@ -20,12 +25,6 @@ module RuboCop
20
25
 
21
26
  private
22
27
 
23
- def offense?(node)
24
- return false unless node.receiver
25
- receiver_name = node.receiver.method_name
26
- receiver_name == :request && node.method_name == wrong_method_name
27
- end
28
-
29
28
  def message
30
29
  "Use `request.#{style}` instead of `request.#{wrong_method_name}`."
31
30
  end
@@ -16,18 +16,12 @@ module RuboCop
16
16
  class ScopeArgs < Cop
17
17
  MSG = 'Use `lambda`/`proc` instead of a plain method call.'.freeze
18
18
 
19
- def on_send(node)
20
- return unless node.command?(:scope)
21
-
22
- _receiver, _method_name, *args = *node
23
-
24
- return unless args.size == 2
19
+ def_node_matcher :scope?, '(send nil :scope _ $send)'
25
20
 
26
- second_arg = args[1]
27
-
28
- return unless second_arg.send_type?
29
-
30
- add_offense(second_arg, :expression)
21
+ def on_send(node)
22
+ scope?(node) do |second_arg|
23
+ add_offense(second_arg, :expression)
24
+ end
31
25
  end
32
26
  end
33
27
  end
@@ -37,7 +37,7 @@ module RuboCop
37
37
  def check_body(body, node)
38
38
  return if body.nil? # Empty class etc.
39
39
 
40
- modifiers = body.children.select { |c| modifier_node?(c) }
40
+ modifiers = body.each_child_node.select { |c| modifier_node?(c) }
41
41
  class_column = node.source_range.column
42
42
 
43
43
  modifiers.each { |modifier| check_modifier(modifier, class_column) }
@@ -131,7 +131,7 @@ module RuboCop
131
131
  end_paren = begin_paren
132
132
  # Increment position of parenthesis, unless message is a predicate
133
133
  # method followed by a non-whitespace char (e.g. is_a?String).
134
- end_paren += 1 unless node.source =~ /\?[!\S]/
134
+ end_paren += 1 unless node.source =~ /\?\S/
135
135
  range_between(begin_paren, end_paren)
136
136
  end
137
137
  end
@@ -11,18 +11,14 @@ module RuboCop
11
11
  class ArrayJoin < Cop
12
12
  MSG = 'Favor `Array#join` over `Array#*`.'.freeze
13
13
 
14
- def on_send(node)
15
- receiver_node, method_name, *arg_nodes = *node
16
- return unless receiver_node && receiver_node.array_type? &&
17
- method_name == :* && arg_nodes.first.str_type?
14
+ def_node_matcher :join_candidate?, '(send $array :* $str)'
18
15
 
19
- add_offense(node, :selector)
16
+ def on_send(node)
17
+ join_candidate?(node) { add_offense(node, :selector) }
20
18
  end
21
19
 
22
20
  def autocorrect(node)
23
- receiver_node, _method_name, *arg_nodes = *node
24
- array = receiver_node.source
25
- join_arg = arg_nodes.first.source
21
+ array, join_arg = join_candidate?(node).map(&:source)
26
22
 
27
23
  lambda do |corrector|
28
24
  corrector.replace(node.source_range, "#{array}.join(#{join_arg})")
@@ -27,7 +27,7 @@ module RuboCop
27
27
  contents.source
28
28
  .gsub(/\A/, '# ')
29
29
  .gsub(/\n\n/, "\n#\n")
30
- .gsub(/\n(?=[^\z#])/, "\n# "))
30
+ .gsub(/\n(?=[^#])/, "\n# "))
31
31
  end
32
32
  corrector.remove(eq_end)
33
33
  end
@@ -7,10 +7,10 @@ module RuboCop
7
7
  class CaseEquality < Cop
8
8
  MSG = 'Avoid the use of the case equality operator `===`.'.freeze
9
9
 
10
- def on_send(node)
11
- _receiver, method_name, *_args = *node
10
+ def_node_matcher :case_equality?, '(send _ :=== _)'
12
11
 
13
- add_offense(node, :selector) if method_name == :===
12
+ def on_send(node)
13
+ case_equality?(node) { add_offense(node, :selector) }
14
14
  end
15
15
  end
16
16
  end
@@ -32,13 +32,11 @@ module RuboCop
32
32
 
33
33
  # Dummy implementation of method in ConfigurableEnforcedStyle that is
34
34
  # called from StringHelp.
35
- def opposite_style_detected
36
- end
35
+ def opposite_style_detected; end
37
36
 
38
37
  # Dummy implementation of method in ConfigurableEnforcedStyle that is
39
38
  # called from StringHelp.
40
- def correct_style_detected
41
- end
39
+ def correct_style_detected; end
42
40
  end
43
41
  end
44
42
  end
@@ -9,13 +9,13 @@ module RuboCop
9
9
 
10
10
  MSG = 'Prefer `Object#%s` over `Object#%s`.'.freeze
11
11
 
12
- def on_send(node)
13
- _receiver, method_name, *_args = *node
14
- return unless [:is_a?,
15
- :kind_of?].include?(method_name)
12
+ def_node_matcher :class_check?, '(send _ ${:is_a? :kind_of?} _)'
16
13
 
17
- return if style == method_name
18
- add_offense(node, :selector)
14
+ def on_send(node)
15
+ class_check?(node) do |method_name|
16
+ return if style == method_name
17
+ add_offense(node, :selector)
18
+ end
19
19
  end
20
20
 
21
21
  def message(node)
@@ -8,15 +8,15 @@ module RuboCop
8
8
  class ColonMethodCall < Cop
9
9
  MSG = 'Do not use `::` for method calls.'.freeze
10
10
 
11
- JAVA_TYPES = [:byte, :boolean, :byte, :short, :char,
12
- :int, :long, :float, :double].freeze
13
-
14
- JAVA_TYPE_NODES =
15
- JAVA_TYPES.map { |t| s(:send, s(:const, nil, :Java), t) }
11
+ def_node_matcher :java_type_node?, <<-PATTERN
12
+ (send
13
+ (const nil :Java)
14
+ {:boolean :byte :char :double :float :int :long :short})
15
+ PATTERN
16
16
 
17
17
  def on_send(node)
18
18
  # ignore Java interop code like Java::int
19
- return if JAVA_TYPE_NODES.include?(node)
19
+ return if java_type_node?(node)
20
20
 
21
21
  receiver, method_name, *_args = *node
22
22
 
@@ -20,19 +20,22 @@ module RuboCop
20
20
  MSG = 'Use `each_with_object` instead of `%s`.'.freeze
21
21
  METHODS = [:inject, :reduce].freeze
22
22
 
23
- def on_block(node)
24
- method, args, body = *node
25
- return unless reduce_method?(method)
23
+ def_node_matcher :each_with_object_candidate?, <<-PATTERN
24
+ (block $(send _ {:inject :reduce} _) $_ $_)
25
+ PATTERN
26
26
 
27
- _, method_name, method_arg = *method
28
- return if simple_method_arg?(method_arg)
27
+ def on_block(node)
28
+ each_with_object_candidate?(node) do |method, args, body|
29
+ _, method_name, method_arg = *method
30
+ return if simple_method_arg?(method_arg)
29
31
 
30
- return_value = return_value(body)
31
- return unless return_value
32
- return unless first_argument_returned?(args, return_value)
33
- return if accumulator_param_assigned_to?(body, args)
32
+ return_value = return_value(body)
33
+ return unless return_value
34
+ return unless first_argument_returned?(args, return_value)
35
+ return if accumulator_param_assigned_to?(body, args)
34
36
 
35
- add_offense(node, method.loc.selector, format(MSG, method_name))
37
+ add_offense(node, method.loc.selector, format(MSG, method_name))
38
+ end
36
39
  end
37
40
 
38
41
  def autocorrect(node)
@@ -47,13 +50,6 @@ module RuboCop
47
50
 
48
51
  private
49
52
 
50
- def reduce_method?(method)
51
- return false unless method.send_type?
52
-
53
- _, method_name, _method_arg = *method
54
- METHODS.include? method_name
55
- end
56
-
57
53
  def simple_method_arg?(method_arg)
58
54
  method_arg && method_arg.basic_literal?
59
55
  end
@@ -12,34 +12,21 @@ module RuboCop
12
12
  HASH_MSG = 'Use hash literal `{}` instead of `Hash.new`.'.freeze
13
13
  STR_MSG = 'Use string literal `%s` instead of `String.new`.'.freeze
14
14
 
15
- # Empty array node
16
- #
17
- # (send
18
- # (const nil :Array) :new)
19
- ARRAY_NODE = s(:send, s(:const, nil, :Array), :new)
20
-
21
- # Empty hash node
22
- #
23
- # (send
24
- # (const nil :Hash) :new)
25
- HASH_NODE = s(:send, s(:const, nil, :Hash), :new)
26
-
27
- # Empty string node
28
- #
29
- # (send
30
- # (const nil :String) :new)
31
- STR_NODE = s(:send, s(:const, nil, :String), :new)
15
+ def_node_matcher :array_node, '(send (const nil :Array) :new)'
16
+ def_node_matcher :hash_node, '(send (const nil :Hash) :new)'
17
+ def_node_matcher :str_node, '(send (const nil :String) :new)'
32
18
 
33
19
  def on_send(node)
34
- case node
35
- when ARRAY_NODE
36
- add_offense(node, :expression, ARR_MSG)
37
- when HASH_NODE
20
+ array_node(node) { add_offense(node, :expression, ARR_MSG) }
21
+
22
+ hash_node(node) do
38
23
  # If Hash.new takes a block, it can't be changed to {}.
39
24
  return if node.parent && node.parent.block_type?
40
25
 
41
26
  add_offense(node, :expression, HASH_MSG)
42
- when STR_NODE
27
+ end
28
+
29
+ str_node(node) do
43
30
  return if frozen_string_literals_enabled?(processed_source)
44
31
 
45
32
  add_offense(node, :expression,
@@ -48,20 +35,9 @@ module RuboCop
48
35
  end
49
36
 
50
37
  def autocorrect(node)
51
- name = case node
52
- when ARRAY_NODE
53
- '[]'
54
- when HASH_NODE
55
- # `some_method {}` is not same as `some_method Hash.new`
56
- # because the braces are interpreted as a block, so we avoid
57
- # the correction. Parentheses around the arguments would
58
- # solve the problem, but we let the user add those manually.
59
- return if first_arg_in_method_call_without_parentheses?(node)
60
- '{}'
61
- when STR_NODE
62
- preferred_string_literal
63
- end
64
- ->(corrector) { corrector.replace(node.source_range, name) }
38
+ lambda do |corrector|
39
+ corrector.replace(replacement_range(node), correction(node))
40
+ end
65
41
  end
66
42
 
67
43
  private
@@ -84,6 +60,40 @@ module RuboCop
84
60
  _receiver, _method_name, *args = *node.parent
85
61
  node.object_id == args.first.object_id && !parentheses?(node.parent)
86
62
  end
63
+
64
+ def replacement_range(node)
65
+ if hash_node(node) &&
66
+ first_arg_in_method_call_without_parentheses?(node)
67
+ # `some_method {}` is not same as `some_method Hash.new`
68
+ # because the braces are interpreted as a block. We will have
69
+ # to rewrite the arguments to wrap them in parenthesis.
70
+ _receiver, _method_name, *args = *node.parent
71
+
72
+ Parser::Source::Range.new(node.parent.loc.expression,
73
+ args[0].loc.expression.begin_pos - 1,
74
+ args[-1].loc.expression.end_pos)
75
+ else
76
+ node.source_range
77
+ end
78
+ end
79
+
80
+ def correction(node)
81
+ if array_node(node)
82
+ '[]'
83
+ elsif str_node(node)
84
+ preferred_string_literal
85
+ elsif hash_node(node)
86
+ if first_arg_in_method_call_without_parentheses?(node)
87
+ # `some_method {}` is not same as `some_method Hash.new`
88
+ # because the braces are interpreted as a block. We will have
89
+ # to rewrite the arguments to wrap them in parenthesis.
90
+ _receiver, _method_name, *args = *node.parent
91
+ "(#{args[1..-1].map(&:source).unshift('{}').join(', ')})"
92
+ else
93
+ '{}'
94
+ end
95
+ end
96
+ end
87
97
  end
88
98
  end
89
99
  end