rubocop 0.55.0 → 0.56.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 +45 -0
  4. data/config/disabled.yml +4 -4
  5. data/config/enabled.yml +32 -16
  6. data/lib/rubocop.rb +8 -2
  7. data/lib/rubocop/cli.rb +4 -0
  8. data/lib/rubocop/comment_config.rb +36 -9
  9. data/lib/rubocop/config.rb +8 -1
  10. data/lib/rubocop/cop/generator.rb +4 -3
  11. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +101 -29
  12. data/lib/rubocop/cop/{style → layout}/empty_line_after_guard_clause.rb +1 -1
  13. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +5 -5
  14. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +112 -2
  15. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +8 -4
  16. data/lib/rubocop/cop/lint/erb_new_arguments.rb +107 -0
  17. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +4 -0
  18. data/lib/rubocop/cop/lint/nested_percent_literal.rb +0 -8
  19. data/lib/rubocop/cop/lint/percent_string_array.rb +1 -1
  20. data/lib/rubocop/cop/lint/percent_symbol_array.rb +1 -1
  21. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +3 -0
  22. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +16 -3
  23. data/lib/rubocop/cop/lint/splat_keyword_arguments.rb +36 -0
  24. data/lib/rubocop/cop/lint/unneeded_cop_enable_directive.rb +20 -2
  25. data/lib/rubocop/cop/performance/inefficient_hash_search.rb +95 -0
  26. data/lib/rubocop/cop/performance/unneeded_sort.rb +41 -6
  27. data/lib/rubocop/cop/rails/assert_not.rb +44 -0
  28. data/lib/rubocop/cop/rails/blank.rb +34 -28
  29. data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +1 -1
  30. data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +12 -2
  31. data/lib/rubocop/cop/rails/http_positional_arguments.rb +7 -7
  32. data/lib/rubocop/cop/rails/present.rb +31 -25
  33. data/lib/rubocop/cop/rails/refute_methods.rb +76 -0
  34. data/lib/rubocop/cop/rails/reversible_migration.rb +6 -4
  35. data/lib/rubocop/cop/rails/save_bang.rb +4 -1
  36. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +1 -10
  37. data/lib/rubocop/cop/style/command_literal.rb +15 -3
  38. data/lib/rubocop/cop/style/comment_annotation.rb +6 -1
  39. data/lib/rubocop/cop/style/empty_method.rb +6 -3
  40. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +12 -2
  41. data/lib/rubocop/cop/style/method_missing_super.rb +34 -0
  42. data/lib/rubocop/cop/style/{method_missing.rb → missing_respond_to_missing.rb} +7 -29
  43. data/lib/rubocop/cop/style/parentheses_around_condition.rb +28 -2
  44. data/lib/rubocop/node_pattern.rb +1 -1
  45. data/lib/rubocop/processed_source.rb +12 -6
  46. data/lib/rubocop/result_cache.rb +9 -4
  47. data/lib/rubocop/rspec/shared_contexts.rb +4 -0
  48. data/lib/rubocop/runner.rb +8 -2
  49. data/lib/rubocop/target_finder.rb +40 -60
  50. data/lib/rubocop/version.rb +1 -1
  51. metadata +10 -4
@@ -2,7 +2,7 @@
2
2
 
3
3
  module RuboCop
4
4
  module Cop
5
- module Style
5
+ module Layout
6
6
  # This cop enforces empty line after guard clause
7
7
  #
8
8
  # @example
@@ -6,12 +6,12 @@ module RuboCop
6
6
  # This cop checks whether method definitions are
7
7
  # separated by one empty line.
8
8
  #
9
- # `NumberOfEmptyLines` can be and integer (e.g. 1 by default) or
10
- # an array (e.g. [1, 2]) to specificy a minimum and a maximum of
11
- # empty lines.
9
+ # `NumberOfEmptyLines` can be an integer (default is 1) or
10
+ # an array (e.g. [1, 2]) to specify a minimum and maximum
11
+ # number of empty lines permitted.
12
12
  #
13
- # `AllowAdjacentOneLineDefs` can be used to configure is adjacent
14
- # one line methods definitions are an offense
13
+ # `AllowAdjacentOneLineDefs` configures whether adjacent
14
+ # one-line method definitions are considered an offense.
15
15
  #
16
16
  # @example
17
17
  #
@@ -4,8 +4,8 @@ module RuboCop
4
4
  module Cop
5
5
  module Layout
6
6
  # This cop checks the indentation of the first parameter in a method call.
7
- # Parameters after the first one are checked by Style/AlignParameters, not
8
- # by this cop.
7
+ # Parameters after the first one are checked by Layout/AlignParameters,
8
+ # not by this cop.
9
9
  #
10
10
  # @example
11
11
  #
@@ -14,10 +14,119 @@ module RuboCop
14
14
  # first_param,
15
15
  # second_param)
16
16
  #
17
+ # foo = some_method(
18
+ # first_param,
19
+ # second_param)
20
+ #
21
+ # foo = some_method(nested_call(
22
+ # nested_first_param),
23
+ # second_param)
24
+ #
25
+ # foo = some_method(
26
+ # nested_call(
27
+ # nested_first_param),
28
+ # second_param)
29
+ #
30
+ # some_method nested_call(
31
+ # nested_first_param),
32
+ # second_param
33
+ #
34
+ # # Style: consistent
35
+ #
36
+ # # good
37
+ # some_method(
38
+ # first_param,
39
+ # second_param)
40
+ #
41
+ # foo = some_method(
42
+ # first_param,
43
+ # second_param)
44
+ #
45
+ # foo = some_method(nested_call(
46
+ # nested_first_param),
47
+ # second_param)
48
+ #
49
+ # foo = some_method(
50
+ # nested_call(
51
+ # nested_first_param),
52
+ # second_param)
53
+ #
54
+ # some_method nested_call(
55
+ # nested_first_param),
56
+ # second_param
57
+ #
58
+ # # Style: consistent_relative_to_receiver
59
+ #
17
60
  # # good
18
61
  # some_method(
19
62
  # first_param,
20
63
  # second_param)
64
+ #
65
+ # foo = some_method(
66
+ # first_param,
67
+ # second_param)
68
+ #
69
+ # foo = some_method(nested_call(
70
+ # nested_first_param),
71
+ # second_param)
72
+ #
73
+ # foo = some_method(
74
+ # nested_call(
75
+ # nested_first_param),
76
+ # second_param)
77
+ #
78
+ # some_method nested_call(
79
+ # nested_first_param),
80
+ # second_params
81
+ #
82
+ # # Style: special_for_inner_method_call
83
+ #
84
+ # # good
85
+ # some_method(
86
+ # first_param,
87
+ # second_param)
88
+ #
89
+ # foo = some_method(
90
+ # first_param,
91
+ # second_param)
92
+ #
93
+ # foo = some_method(nested_call(
94
+ # nested_first_param),
95
+ # second_param)
96
+ #
97
+ # foo = some_method(
98
+ # nested_call(
99
+ # nested_first_param),
100
+ # second_param)
101
+ #
102
+ # some_method nested_call(
103
+ # nested_first_param),
104
+ # second_param
105
+ #
106
+ # # Style: special_for_inner_method_call_in_parentheses
107
+ #
108
+ # # good
109
+ # some_method(
110
+ # first_param,
111
+ # second_param)
112
+ #
113
+ # foo = some_method(
114
+ # first_param,
115
+ # second_param)
116
+ #
117
+ # foo = some_method(nested_call(
118
+ # nested_first_param),
119
+ # second_param)
120
+ #
121
+ # foo = some_method(
122
+ # nested_call(
123
+ # nested_first_param),
124
+ # second_param)
125
+ #
126
+ # some_method nested_call(
127
+ # nested_first_param),
128
+ # second_param
129
+ #
21
130
  class FirstParameterIndentation < Cop
22
131
  include Alignment
23
132
  include ConfigurableEnforcedStyle
@@ -65,6 +174,7 @@ module RuboCop
65
174
 
66
175
  def special_inner_call_indentation?(node)
67
176
  return false if style == :consistent
177
+ return true if style == :consistent_relative_to_receiver
68
178
 
69
179
  parent = node.parent
70
180
 
@@ -66,7 +66,7 @@ module RuboCop
66
66
  return if node.multiline?
67
67
  return unless bracket_method?(node)
68
68
  tokens = tokens(node)
69
- left_token = left_ref_bracket(tokens)
69
+ left_token = left_ref_bracket(node, tokens)
70
70
  return unless left_token
71
71
  right_token = closing_bracket(tokens, left_token)
72
72
 
@@ -101,7 +101,7 @@ module RuboCop
101
101
 
102
102
  def reference_brackets(node)
103
103
  tokens = tokens(node)
104
- left = left_ref_bracket(tokens)
104
+ left = left_ref_bracket(node, tokens)
105
105
  [left, closing_bracket(tokens, left)]
106
106
  end
107
107
 
@@ -110,8 +110,12 @@ module RuboCop
110
110
  BRACKET_METHODS.include?(method)
111
111
  end
112
112
 
113
- def left_ref_bracket(tokens)
114
- tokens.reverse.find(&:left_ref_bracket?)
113
+ def left_ref_bracket(node, tokens)
114
+ if node.method?(:[]=)
115
+ tokens.find(&:left_ref_bracket?)
116
+ else
117
+ tokens.reverse.find(&:left_ref_bracket?)
118
+ end
115
119
  end
116
120
 
117
121
  def closing_bracket(tokens, opening_bracket)
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ #
7
+ # This cop emulates the following Ruby warnings in Ruby 2.6.
8
+ #
9
+ # % cat example.rb
10
+ # ERB.new('hi', nil, '-', '@output_buffer')
11
+ # % ruby -rerb example.rb
12
+ # example.rb:1: warning: Passing safe_level with the 2nd argument of
13
+ # ERB.new is deprecated. Do not use it, and specify other arguments as
14
+ # keyword arguments.
15
+ # example.rb:1: warning: Passing trim_mode with the 3rd argument of
16
+ # ERB.new is deprecated. Use keyword argument like
17
+ # ERB.new(str, trim_mode:...) instead.
18
+ # example.rb:1: warning: Passing eoutvar with the 4th argument of ERB.new
19
+ # is deprecated. Use keyword argument like ERB.new(str, eoutvar: ...)
20
+ # instead.
21
+ #
22
+ # Now non-keyword arguments other than first one are softly deprecated
23
+ # and will be removed when Ruby 2.5 becomes EOL.
24
+ # `ERB.new` with non-keyword arguments is deprecated since ERB 2.2.0.
25
+ # Use `:trim_mode` and `:eoutvar` keyword arguments to `ERB.new`.
26
+ # This cop identifies places where `ERB.new(str, trim_mode, eoutvar)` can
27
+ # be replaced by `ERB.new(str, :trim_mode: trim_mode, eoutvar: eoutvar)`.
28
+ #
29
+ # @example
30
+ # # Target codes supports Ruby 2.6 and higher only
31
+ # # bad
32
+ # ERB.new(str, nil, '-', '@output_buffer')
33
+ #
34
+ # # good
35
+ # ERB.new(str, trim_mode: '-', eoutvar: '@output_buffer')
36
+ #
37
+ # # Target codes supports Ruby 2.5 and lower only
38
+ # # good
39
+ # ERB.new(str, nil, '-', '@output_buffer')
40
+ #
41
+ # # Target codes supports Ruby 2.6, 2.5 and lower
42
+ # # bad
43
+ # ERB.new(str, nil, '-', '@output_buffer')
44
+ #
45
+ # # good
46
+ # # Ruby standard library style
47
+ # # https://github.com/ruby/ruby/commit/3406c5d
48
+ # if ERB.instance_method(:initialize).parameters.assoc(:key) # Ruby 2.6+
49
+ # ERB.new(str, trim_mode: '-', eoutvar: '@output_buffer')
50
+ # else
51
+ # ERB.new(str, nil, '-', '@output_buffer')
52
+ # end
53
+ #
54
+ # # good
55
+ # # Use `RUBY_VERSION` style
56
+ # if RUBY_VERSION >= '2.6'
57
+ # ERB.new(str, trim_mode: '-', eoutvar: '@output_buffer')
58
+ # else
59
+ # ERB.new(str, nil, '-', '@output_buffer')
60
+ # end
61
+ #
62
+ class ErbNewArguments < Cop
63
+ extend TargetRubyVersion
64
+
65
+ minimum_target_ruby_version 2.6
66
+
67
+ MESSAGES = [
68
+ 'Passing safe_level with the 2nd argument of `ERB.new` is ' \
69
+ 'deprecated. Do not use it, and specify other arguments as ' \
70
+ 'keyword arguments.',
71
+ 'Passing trim_mode with the 3rd argument of `ERB.new` is ' \
72
+ 'deprecated. Use keyword argument like ' \
73
+ '`ERB.new(str, trim_mode: %<arg_value>s)` instead.',
74
+ 'Passing eoutvar with the 4th argument of `ERB.new` is ' \
75
+ 'deprecated. Use keyword argument like ' \
76
+ '`ERB.new(str, eoutvar: %<arg_value>s)` instead.'
77
+ ].freeze
78
+
79
+ def_node_matcher :erb_new_with_non_keyword_arguments, <<-PATTERN
80
+ (send
81
+ (const {nil? cbase} :ERB) :new $...)
82
+ PATTERN
83
+
84
+ def on_send(node)
85
+ erb_new_with_non_keyword_arguments(node) do |arguments|
86
+ return if correct_arguments?(arguments)
87
+
88
+ 1.upto(3) do |i|
89
+ next if !arguments[i] || arguments[i].hash_type?
90
+
91
+ message = format(MESSAGES[i - 1], arg_value: arguments[i].source)
92
+
93
+ add_offense(
94
+ node, location: arguments[i].source_range, message: message
95
+ )
96
+ end
97
+ end
98
+ end
99
+
100
+ def correct_arguments?(arguments)
101
+ arguments.size == 1 ||
102
+ arguments.size == 2 && arguments[1].hash_type?
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
@@ -50,6 +50,10 @@ module RuboCop
50
50
 
51
51
  def autocorrected_value(node)
52
52
  case node.type
53
+ when :int
54
+ node.children.last.to_i.to_s
55
+ when :float
56
+ node.children.last.to_f.to_s
53
57
  when :str
54
58
  node.children.last
55
59
  when :sym
@@ -38,14 +38,6 @@ module RuboCop
38
38
 
39
39
  private
40
40
 
41
- def str_content(node)
42
- if node.str_type?
43
- node.children[0]
44
- else
45
- node.children.map { |c| str_content(c) }.join
46
- end
47
- end
48
-
49
41
  def contains_percent_literals?(node)
50
42
  node.each_child_node.any? do |child|
51
43
  literal = child.children.first.to_s.scrub
@@ -62,7 +62,7 @@ module RuboCop
62
62
  literal = value.children.first.to_s.scrub
63
63
 
64
64
  # To avoid likely false positives (e.g. a single ' or ")
65
- next if literal.gsub(/[^\p{Alnum}]/, '').empty?
65
+ next if literal.gsub(/[^[[:alnum:]]]/, '').empty?
66
66
 
67
67
  QUOTES_AND_COMMAS.any? { |pat| literal =~ pat }
68
68
  end
@@ -55,7 +55,7 @@ module RuboCop
55
55
  literal = child.children.first
56
56
 
57
57
  # To avoid likely false positives (e.g. a single ' or ")
58
- next if literal.to_s.gsub(/[^\p{Alnum}]/, '').empty?
58
+ next if literal.to_s.gsub(/[^[[:alnum:]]]/, '').empty?
59
59
 
60
60
  patterns.any? { |pat| literal =~ pat }
61
61
  end
@@ -31,7 +31,10 @@ module RuboCop
31
31
  ' after safe navigation operator.'.freeze
32
32
 
33
33
  def_node_matcher :bad_method?, <<-PATTERN
34
+ {
34
35
  (send $(csend ...) $_ ...)
36
+ (send $(block (csend ...) ...) $_ ...)
37
+ }
35
38
  PATTERN
36
39
 
37
40
  minimum_target_ruby_version 2.3
@@ -27,6 +27,9 @@ module RuboCop
27
27
  # foo&.bar && (foobar.baz || foo&.baz)
28
28
  #
29
29
  class SafeNavigationConsistency < Cop
30
+ include IgnoredNode
31
+ include NilMethods
32
+
30
33
  MSG = 'Ensure that safe navigation is used consistently ' \
31
34
  'inside of `&&` and `||`.'.freeze
32
35
 
@@ -42,15 +45,16 @@ module RuboCop
42
45
  safe_nav_receiver = node.receiver
43
46
 
44
47
  method_calls = conditions.select(&:send_type?)
45
- unsafe_method_calls = method_calls.select do |method_call|
46
- safe_nav_receiver == method_call.receiver
47
- end
48
+ unsafe_method_calls =
49
+ unsafe_method_calls(method_calls, safe_nav_receiver)
48
50
 
49
51
  unsafe_method_calls.each do |unsafe_method_call|
50
52
  location =
51
53
  node.loc.expression.join(unsafe_method_call.loc.expression)
52
54
  add_offense(unsafe_method_call,
53
55
  location: location)
56
+
57
+ ignore_node(unsafe_method_call)
54
58
  end
55
59
  end
56
60
 
@@ -69,11 +73,20 @@ module RuboCop
69
73
  unless parent &&
70
74
  (AST::Node::OPERATOR_KEYWORDS.include?(parent.type) ||
71
75
  (parent.begin_type? &&
76
+ parent.parent &&
72
77
  AST::Node::OPERATOR_KEYWORDS.include?(parent.parent.type)))
73
78
  return node
74
79
  end
75
80
  top_conditional_ancestor(parent)
76
81
  end
82
+
83
+ def unsafe_method_calls(method_calls, safe_nav_receiver)
84
+ method_calls.select do |method_call|
85
+ safe_nav_receiver == method_call.receiver &&
86
+ !nil_methods.include?(method_call.method_name) &&
87
+ !ignored_node?(method_call)
88
+ end
89
+ end
77
90
  end
78
91
  end
79
92
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ #
7
+ # This cop emulates the following Ruby warnings in Ruby 2.6.
8
+ #
9
+ # % ruby -we "def m(a) end; h = {foo: 1}; m(**h)"
10
+ # -e:1: warning: passing splat keyword arguments as a single Hash to `m'
11
+ #
12
+ # It checks for use of splat keyword arguments as a single Hash.
13
+ #
14
+ # @example
15
+ # # bad
16
+ # do_something(**arguments)
17
+ #
18
+ # # good
19
+ # do_something(arguments)
20
+ #
21
+ class SplatKeywordArguments < Cop
22
+ MSG = 'Do not use splat keyword arguments as a single Hash.'.freeze
23
+
24
+ def on_send(node)
25
+ node.arguments.each do |argument|
26
+ next unless argument.hash_type?
27
+
28
+ argument.children.each do |element|
29
+ add_offense(element) if element.kwsplat_type?
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end