rubocop 0.55.0 → 0.56.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 +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
@@ -10,6 +10,8 @@ module RuboCop
10
10
  # This cop detects instances of rubocop:enable comments that can be
11
11
  # removed.
12
12
  #
13
+ # When comment enables all cops at once `rubocop:enable all`
14
+ # that cop checks whether any cop was actually enabled.
13
15
  # @example
14
16
  # # bad
15
17
  # foo = 1
@@ -17,6 +19,19 @@ module RuboCop
17
19
  #
18
20
  # # good
19
21
  # foo = 1
22
+ # @example
23
+ # # bad
24
+ # # rubocop:disable Metrics/LineLength
25
+ # baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarrrrrrrrrrrrr
26
+ # # rubocop:enable Metrics/LineLength
27
+ # baz
28
+ # # rubocop:enable all
29
+ #
30
+ # # good
31
+ # # rubocop:disable Metrics/LineLength
32
+ # baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarrrrrrrrrrrrr
33
+ # # rubocop:enable all
34
+ # baz
20
35
  class UnneededCopEnableDirective < Cop
21
36
  include RangeHelp
22
37
  include SurroundingSpace
@@ -30,7 +45,7 @@ module RuboCop
30
45
  add_offense(
31
46
  [comment, name],
32
47
  location: range_of_offense(comment, name),
33
- message: format(MSG, cop: name)
48
+ message: format(MSG, cop: all_or_name(name))
34
49
  )
35
50
  end
36
51
  end
@@ -90,8 +105,11 @@ module RuboCop
90
105
  range_class.new(buffer, start, comment.loc.expression.end_pos)
91
106
  end
92
107
  end
108
+
109
+ def all_or_name(name)
110
+ name == 'all' ? 'all cops' : name
111
+ end
93
112
  end
94
113
  end
95
114
  end
96
115
  end
97
- # rubocop:enable Lint/UnneededCopEnableDirective
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Performance
6
+ # This cop checks for inefficient searching of keys and values within
7
+ # hashes.
8
+ #
9
+ # `Hash#keys.include?` is less efficient than `Hash#key?` because
10
+ # the former allocates a new array and then performs an O(n) search
11
+ # through that array, while `Hash#key?` does not allocate any array and
12
+ # performs a faster O(1) search for the key.
13
+ #
14
+ # `Hash#values.include?` is less efficient than `Hash#value?`. While they
15
+ # both perform an O(n) search through all of the values, calling `values`
16
+ # allocates a new array while using `value?` does not.
17
+ #
18
+ # @example
19
+ # # bad
20
+ # { a: 1, b: 2 }.keys.include?(:a)
21
+ # { a: 1, b: 2 }.keys.include?(:z)
22
+ # h = { a: 1, b: 2 }; h.keys.include?(100)
23
+ #
24
+ # # good
25
+ # { a: 1, b: 2 }.key?(:a)
26
+ # { a: 1, b: 2 }.has_key?(:z)
27
+ # h = { a: 1, b: 2 }; h.key?(100)
28
+ #
29
+ # # bad
30
+ # { a: 1, b: 2 }.values.include?(2)
31
+ # { a: 1, b: 2 }.values.include?('garbage')
32
+ # h = { a: 1, b: 2 }; h.values.include?(nil)
33
+ #
34
+ # # good
35
+ # { a: 1, b: 2 }.value?(2)
36
+ # { a: 1, b: 2 }.has_value?('garbage')
37
+ # h = { a: 1, b: 2 }; h.value?(nil)
38
+ #
39
+ class InefficientHashSearch < Cop
40
+ def_node_matcher :inefficient_include?, <<-PATTERN
41
+ (send $(send _ ${:keys :values}) :include? $_)
42
+ PATTERN
43
+
44
+ def on_send(node)
45
+ add_offense(node, message: msg(node)) if inefficient_include?(node)
46
+ end
47
+
48
+ def autocorrect(node)
49
+ lambda do |corrector|
50
+ # Replace `keys.include?` or `values.include?` with the appropriate
51
+ # `key?`/`value?` method.
52
+ corrector.replace(
53
+ node.loc.expression,
54
+ "#{autocorrect_hash_expression(node)}."\
55
+ "#{autocorrect_method(node)}(#{autocorrect_argument(node)})"
56
+ )
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ def msg(node)
63
+ "Use `##{autocorrect_method(node)}` instead of "\
64
+ "`##{current_method(node)}.include?`."
65
+ end
66
+
67
+ def autocorrect_method(node)
68
+ case current_method(node)
69
+ when :keys then use_long_method ? 'has_key?' : 'key?'
70
+ when :values then use_long_method ? 'has_value?' : 'value?'
71
+ end
72
+ end
73
+
74
+ def current_method(node)
75
+ node.children[0].method_name
76
+ end
77
+
78
+ def use_long_method
79
+ preferred_config = config.for_all_cops['Style/PreferredHashMethods']
80
+ preferred_config &&
81
+ preferred_config['EnforcedStyle'] == 'long' &&
82
+ preferred_config['Enabled']
83
+ end
84
+
85
+ def autocorrect_argument(node)
86
+ node.arguments.first.source
87
+ end
88
+
89
+ def autocorrect_hash_expression(node)
90
+ node.children[0].children[0].loc.expression.source
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -3,17 +3,52 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Performance
6
- # This cop is used to identify instances of sorting and then taking
7
- # only the first or last element.
6
+ # This cop is used to identify instances of sorting and then
7
+ # taking only the first or last element. The same behavior can
8
+ # be accomplished without a relatively expensive sort by using
9
+ # `Enumerable#min` instead of sorting and taking the first
10
+ # element and `Enumerable#max` instead of sorting and taking the
11
+ # last element. Similarly, `Enumerable#min_by` and
12
+ # `Enumerable#max_by` can replace `Enumerable#sort_by` calls
13
+ # after which only the first or last element is used.
8
14
  #
9
15
  # @example
10
16
  # # bad
11
- # [].sort.first
12
- # [].sort_by(&:length).last
17
+ # [2, 1, 3].sort.first
18
+ # [2, 1, 3].sort[0]
19
+ # [2, 1, 3].sort.at(0)
20
+ # [2, 1, 3].sort.slice(0)
13
21
  #
14
22
  # # good
15
- # [].min
16
- # [].max_by(&:length)
23
+ # [2, 1, 3].min
24
+ #
25
+ # # bad
26
+ # [2, 1, 3].sort.last
27
+ # [2, 1, 3].sort[-1]
28
+ # [2, 1, 3].sort.at(-1)
29
+ # [2, 1, 3].sort.slice(-1)
30
+ #
31
+ # # good
32
+ # [2, 1, 3].max
33
+ #
34
+ # # bad
35
+ # arr.sort_by(&:foo).first
36
+ # arr.sort_by(&:foo)[0]
37
+ # arr.sort_by(&:foo).at(0)
38
+ # arr.sort_by(&:foo).slice(0)
39
+ #
40
+ # # good
41
+ # arr.min_by(&:foo)
42
+ #
43
+ # # bad
44
+ # arr.sort_by(&:foo).last
45
+ # arr.sort_by(&:foo)[-1]
46
+ # arr.sort_by(&:foo).at(-1)
47
+ # arr.sort_by(&:foo).slice(-1)
48
+ #
49
+ # # good
50
+ # arr.max_by(&:foo)
51
+ #
17
52
  class UnneededSort < Cop
18
53
  include RangeHelp
19
54
 
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Rails
6
+ #
7
+ # Use `assert_not` instead of `assert !`.
8
+ #
9
+ # @example
10
+ # # bad
11
+ # assert !x
12
+ #
13
+ # # good
14
+ # assert_not x
15
+ #
16
+ class AssertNot < RuboCop::Cop::Cop
17
+ MSG = 'Prefer `assert_not` over `assert !`.'.freeze
18
+
19
+ def_node_matcher :offensive?, '(send nil? :assert (send ... :!))'
20
+
21
+ def on_send(node)
22
+ add_offense(node) if offensive?(node)
23
+ end
24
+
25
+ def autocorrect(node)
26
+ expression = node.loc.expression
27
+
28
+ lambda do |corrector|
29
+ corrector.replace(
30
+ expression,
31
+ corrected_source(expression.source)
32
+ )
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def corrected_source(source)
39
+ source.gsub(/^assert(\(| ) *! */, 'assert_not\\1')
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -3,40 +3,46 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Rails
6
- # This cops checks for code that can be changed to `blank?`.
7
- # Settings:
8
- # NilOrEmpty: Convert checks for `nil` or `empty?` to `blank?`
9
- # NotPresent: Convert usages of not `present?` to `blank?`
10
- # UnlessPresent: Convert usages of `unless` `present?` to `blank?`
6
+ # This cop checks for code that can be written with simpler conditionals
7
+ # using `Object#blank?` defined by Active Support.
11
8
  #
12
- # @example
13
- # # NilOrEmpty: true
14
- # # bad
15
- # foo.nil? || foo.empty?
16
- # foo == nil || foo.empty?
9
+ # @example NilOrEmpty: true (default)
10
+ # # Converts usages of `nil? || empty?` to `blank?`
17
11
  #
18
- # # good
19
- # foo.blank?
12
+ # # bad
13
+ # foo.nil? || foo.empty?
14
+ # foo == nil || foo.empty?
20
15
  #
21
- # # NotPresent: true
22
- # # bad
23
- # !foo.present?
16
+ # # good
17
+ # foo.blank?
24
18
  #
25
- # # good
26
- # foo.blank?
19
+ # @example NotPresent: true (default)
20
+ # # Converts usages of `!present?` to `blank?`
27
21
  #
28
- # # UnlessPresent: true
29
- # # bad
30
- # something unless foo.present?
31
- # unless foo.present?
32
- # something
33
- # end
22
+ # # bad
23
+ # !foo.present?
34
24
  #
35
- # # good
36
- # something if foo.blank?
37
- # if foo.blank?
38
- # something
39
- # end
25
+ # # good
26
+ # foo.blank?
27
+ #
28
+ # @example UnlessPresent: true (default)
29
+ # # Converts usages of `unless present?` to `if blank?`
30
+ #
31
+ # # bad
32
+ # something unless foo.present?
33
+ #
34
+ # # good
35
+ # something if foo.blank?
36
+ #
37
+ # # bad
38
+ # unless foo.present?
39
+ # something
40
+ # end
41
+ #
42
+ # # good
43
+ # if foo.blank?
44
+ # something
45
+ # end
40
46
  class Blank < Cop
41
47
  MSG_NIL_OR_EMPTY = 'Use `%<prefer>s` instead of `%<current>s`.'.freeze
42
48
  MSG_NOT_PRESENT = 'Use `%<prefer>s` instead of `%<current>s`.'.freeze
@@ -51,7 +51,7 @@ module RuboCop
51
51
  PATTERN
52
52
 
53
53
  def_node_matcher :create_table_with_timestamps_proc?, <<-PATTERN
54
- (send nil? :create_table (sym _) (block-pass (sym :timestamps)))
54
+ (send nil? :create_table (sym _) ... (block-pass (sym :timestamps)))
55
55
  PATTERN
56
56
 
57
57
  def_node_search :timestamps_included?, <<-PATTERN
@@ -63,8 +63,18 @@ module RuboCop
63
63
 
64
64
  n = node.parent.begin_type? ? node.parent.parent : node.parent
65
65
 
66
- if with_options_block(n)
67
- return true if valid_options?(with_options_block(n))
66
+ contain_valid_options_in_with_options_block?(n)
67
+ end
68
+
69
+ def contain_valid_options_in_with_options_block?(node)
70
+ if with_options_block(node)
71
+ return true if valid_options?(with_options_block(node))
72
+
73
+ return false unless node.parent
74
+
75
+ return true if contain_valid_options_in_with_options_block?(
76
+ node.parent.parent
77
+ )
68
78
  end
69
79
 
70
80
  false
@@ -22,7 +22,7 @@ module RuboCop
22
22
  MSG = 'Use keyword arguments instead of ' \
23
23
  'positional arguments for http call: `%<verb>s`.'.freeze
24
24
  KEYWORD_ARGS = %i[
25
- headers env params body flash as xhr session method
25
+ method params session body flash xhr as
26
26
  ].freeze
27
27
  HTTP_METHODS = %i[get post put patch delete head].freeze
28
28
 
@@ -41,11 +41,11 @@ module RuboCop
41
41
  end
42
42
  end
43
43
 
44
- # given a pre Rails 5 method: get :new, user_id: @user.id, {}
44
+ # given a pre Rails 5 method: get :new, {user_id: @user.id}, {}
45
45
  #
46
46
  # @return lambda of auto correct procedure
47
47
  # the result should look like:
48
- # get :new, params: { user_id: @user.id }, headers: {}
48
+ # get :new, params: { user_id: @user.id }, session: {}
49
49
  # the http_method is the method used to call the controller
50
50
  # the controller node can be a symbol, method, object or string
51
51
  # that represents the path/action on the Rails controller
@@ -56,14 +56,14 @@ module RuboCop
56
56
 
57
57
  controller_action = http_path.source
58
58
  params = convert_hash_data(data.first, 'params')
59
- headers = convert_hash_data(data.last, 'headers') if data.size > 1
59
+ session = convert_hash_data(data.last, 'session') if data.size > 1
60
60
  # the range of the text to replace, which is the whole line
61
61
  code_to_replace = node.loc.expression
62
62
  # what to replace with
63
63
  format = parentheses_format(node)
64
64
  new_code = format(format, name: node.method_name,
65
65
  action: controller_action,
66
- params: params, headers: headers)
66
+ params: params, session: session)
67
67
  ->(corrector) { corrector.replace(code_to_replace, new_code) }
68
68
  end
69
69
 
@@ -103,9 +103,9 @@ module RuboCop
103
103
 
104
104
  def parentheses_format(node)
105
105
  if parentheses?(node)
106
- '%<name>s(%<action>s%<params>s%<headers>s)'
106
+ '%<name>s(%<action>s%<params>s%<session>s)'
107
107
  else
108
- '%<name>s %<action>s%<params>s%<headers>s'
108
+ '%<name>s %<action>s%<params>s%<session>s'
109
109
  end
110
110
  end
111
111
  end
@@ -3,37 +3,43 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Rails
6
- # This cops checks for code that can be changed to `blank?`.
7
- # Settings:
8
- # NotNilAndNotEmpty: Convert checks for not `nil` and `not empty?`
9
- # to `present?`
10
- # NotBlank: Convert usages of not `blank?` to `present?`
11
- # UnlessBlank: Convert usages of `unless` `blank?` to `if` `present?`
6
+ # This cop checks for code that can be written with simpler conditionals
7
+ # using `Object#present?` defined by Active Support.
12
8
  #
13
- # @example
14
- # # NotNilAndNotEmpty: true
15
- # # bad
16
- # !foo.nil? && !foo.empty?
17
- # foo != nil && !foo.empty?
18
- # !foo.blank?
9
+ # simpler conditionals.
19
10
  #
20
- # # good
21
- # foo.present?
11
+ # @example NotNilAndNotEmpty: true (default)
12
+ # # Converts usages of `!nil? && !empty?` to `present?`
22
13
  #
23
- # # NotBlank: true
24
- # # bad
25
- # !foo.blank?
26
- # not foo.blank?
14
+ # # bad
15
+ # !foo.nil? && !foo.empty?
27
16
  #
28
- # # good
29
- # foo.present?
17
+ # # bad
18
+ # foo != nil && !foo.empty?
30
19
  #
31
- # # UnlessBlank: true
32
- # # bad
33
- # something unless foo.blank?
20
+ # # good
21
+ # foo.present?
34
22
  #
35
- # # good
36
- # something if foo.present?
23
+ # @example NotBlank: true (default)
24
+ # # Converts usages of `!blank?` to `present?`
25
+ #
26
+ # # bad
27
+ # !foo.blank?
28
+ #
29
+ # # bad
30
+ # not foo.blank?
31
+ #
32
+ # # good
33
+ # foo.present?
34
+ #
35
+ # @example UnlessBlank: true (default)
36
+ # # Converts usages of `unless blank?` to `if present?`
37
+ #
38
+ # # bad
39
+ # something unless foo.blank?
40
+ #
41
+ # # good
42
+ # something if foo.present?
37
43
  class Present < Cop
38
44
  MSG_NOT_BLANK = 'Use `%<prefer>s` instead of `%<current>s`.'.freeze
39
45
  MSG_EXISTS_AND_NOT_EMPTY = 'Use `%<prefer>s` instead of ' \