rubocop 0.92.0 → 0.93.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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +32 -0
  4. data/lib/rubocop.rb +3 -1
  5. data/lib/rubocop/cached_data.rb +2 -1
  6. data/lib/rubocop/cop/correctors/line_break_corrector.rb +2 -2
  7. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +10 -10
  8. data/lib/rubocop/cop/layout/dot_position.rb +6 -9
  9. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +6 -7
  10. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -1
  11. data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +2 -11
  12. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +0 -4
  13. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +2 -0
  14. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +15 -1
  15. data/lib/rubocop/cop/lint/boolean_symbol.rb +3 -0
  16. data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +37 -0
  17. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -0
  18. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
  19. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +45 -0
  20. data/lib/rubocop/cop/metrics/block_length.rb +3 -1
  21. data/lib/rubocop/cop/metrics/class_length.rb +8 -6
  22. data/lib/rubocop/cop/mixin/hash_transform_method.rb +1 -1
  23. data/lib/rubocop/cop/offense.rb +15 -2
  24. data/lib/rubocop/cop/style/access_modifier_declarations.rb +6 -2
  25. data/lib/rubocop/cop/style/accessor_grouping.rb +3 -0
  26. data/lib/rubocop/cop/style/case_like_if.rb +20 -4
  27. data/lib/rubocop/cop/style/class_equality_comparison.rb +49 -0
  28. data/lib/rubocop/cop/style/combinable_loops.rb +8 -1
  29. data/lib/rubocop/cop/style/comment_annotation.rb +6 -0
  30. data/lib/rubocop/cop/style/explicit_block_argument.rb +6 -2
  31. data/lib/rubocop/cop/style/for.rb +0 -4
  32. data/lib/rubocop/cop/style/format_string_token.rb +1 -1
  33. data/lib/rubocop/cop/style/method_def_parentheses.rb +0 -4
  34. data/lib/rubocop/cop/style/nested_ternary_operator.rb +2 -0
  35. data/lib/rubocop/cop/style/raise_args.rb +0 -3
  36. data/lib/rubocop/cop/style/redundant_begin.rb +26 -8
  37. data/lib/rubocop/cop/style/redundant_condition.rb +5 -1
  38. data/lib/rubocop/cop/style/redundant_interpolation.rb +6 -1
  39. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +39 -24
  40. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -15
  41. data/lib/rubocop/cop/style/string_concatenation.rb +1 -1
  42. data/lib/rubocop/cop/variable_force/branch.rb +0 -4
  43. data/lib/rubocop/ext/regexp_node.rb +20 -4
  44. data/lib/rubocop/result_cache.rb +8 -2
  45. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  46. data/lib/rubocop/runner.rb +4 -4
  47. data/lib/rubocop/target_finder.rb +23 -25
  48. data/lib/rubocop/version.rb +1 -1
  49. metadata +10 -8
  50. data/lib/rubocop/cop/mixin/regexp_literal_help.rb +0 -43
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 682e17739f5c067f13eb30a3e84b365533bb0e075da92a40529c943e5a67e3b0
4
- data.tar.gz: 2c7e59ef470ad45515bed37249c97419181add1f451379d00b31ff45b21ddd36
3
+ metadata.gz: 4d381604ba6395ffc42db74e3f57245307935ec7a56d365e10b8d07207d432a1
4
+ data.tar.gz: 2b290525226f487d860b5a1201266d1b20e403a05ed8a704c1270b7edaca5e2f
5
5
  SHA512:
6
- metadata.gz: 0bc3d0c3238795b8563b974c99c20d3cfb34dff97bc33f5231d6ef7497f53ce6f4753923bce17954fe30e69b0a8d4146a3b1377d0489e7f10bc97a0b3c69ae7b
7
- data.tar.gz: 4131b9c8a874e09d8c0581a04e91b44acc76855afa565cd52a324055a0bd7e1a40d37bc532b8b3781c9af9847335c6596ca8ed17fe9bff03d13283171d77c168
6
+ metadata.gz: 8639a2098ab1fb1e50fe6993e0a2d9f305998b7cc0215ab6bdd615506a4f8271de1fe78dbe1592b1ade597b40b79acfe4c5bc0503d8ee72940ff1732fd25a19d
7
+ data.tar.gz: 11278958d9183ba56561ffc1f6b3cc69ac0b2f7d883cf5192cb31ab3ace1eacce21a23a13f998f4f2917d14574a6c27309be8f48085fc7abf940eab2ba0d1cce
data/README.md CHANGED
@@ -49,7 +49,7 @@ haven't reached version 1.0 yet). To prevent an unwanted RuboCop update you
49
49
  might want to use a conservative version lock in your `Gemfile`:
50
50
 
51
51
  ```rb
52
- gem 'rubocop', '~> 0.92.0', require: false
52
+ gem 'rubocop', '~> 0.93.0', require: false
53
53
  ```
54
54
 
55
55
  ## Quickstart
@@ -1546,6 +1546,13 @@ Lint/FormatParameterMismatch:
1546
1546
  Enabled: true
1547
1547
  VersionAdded: '0.33'
1548
1548
 
1549
+ Lint/HashCompareByIdentity:
1550
+ Description: 'Prefer using `Hash#compare_by_identity` than using `object_id` for keys.'
1551
+ StyleGuide: '#identity-comparison'
1552
+ Enabled: pending
1553
+ Safe: false
1554
+ VersionAdded: '0.93'
1555
+
1549
1556
  Lint/HeredocMethodCallPosition:
1550
1557
  Description: >-
1551
1558
  Checks for the ordering of a method call where
@@ -1746,6 +1753,21 @@ Lint/RedundantRequireStatement:
1746
1753
  Enabled: true
1747
1754
  VersionAdded: '0.76'
1748
1755
 
1756
+ Lint/RedundantSafeNavigation:
1757
+ Description: 'Checks for redundant safe navigation calls.'
1758
+ Enabled: pending
1759
+ VersionAdded: '0.93'
1760
+ Safe: false
1761
+ IgnoredMethods:
1762
+ - to_c
1763
+ - to_f
1764
+ - to_i
1765
+ - to_r
1766
+ - rationalize
1767
+ - public_send
1768
+ - send
1769
+ - __send__
1770
+
1749
1771
  Lint/RedundantSplatExpansion:
1750
1772
  Description: 'Checks for splat unnecessarily being called on literals.'
1751
1773
  Enabled: true
@@ -2702,6 +2724,16 @@ Style/ClassCheck:
2702
2724
  - is_a?
2703
2725
  - kind_of?
2704
2726
 
2727
+ Style/ClassEqualityComparison:
2728
+ Description: 'Enforces the use of `Object#instance_of?` instead of class comparison for equality.'
2729
+ StyleGuide: '#instance-of-vs-class-comparison'
2730
+ Enabled: pending
2731
+ VersionAdded: '0.93'
2732
+ IgnoredMethods:
2733
+ - ==
2734
+ - equal?
2735
+ - eql?
2736
+
2705
2737
  Style/ClassMethods:
2706
2738
  Description: 'Use self when defining module/class methods.'
2707
2739
  StyleGuide: '#def-self-class-methods'
@@ -105,7 +105,6 @@ require_relative 'rubocop/cop/mixin/percent_literal'
105
105
  require_relative 'rubocop/cop/mixin/preceding_following_alignment'
106
106
  require_relative 'rubocop/cop/mixin/preferred_delimiters'
107
107
  require_relative 'rubocop/cop/mixin/rational_literal'
108
- require_relative 'rubocop/cop/mixin/regexp_literal_help'
109
108
  require_relative 'rubocop/cop/mixin/rescue_node'
110
109
  require_relative 'rubocop/cop/mixin/safe_assignment'
111
110
  require_relative 'rubocop/cop/mixin/space_after_punctuation'
@@ -279,6 +278,7 @@ require_relative 'rubocop/cop/lint/flip_flop'
279
278
  require_relative 'rubocop/cop/lint/float_comparison'
280
279
  require_relative 'rubocop/cop/lint/float_out_of_range'
281
280
  require_relative 'rubocop/cop/lint/format_parameter_mismatch'
281
+ require_relative 'rubocop/cop/lint/hash_compare_by_identity'
282
282
  require_relative 'rubocop/cop/lint/heredoc_method_call_position'
283
283
  require_relative 'rubocop/cop/lint/identity_comparison'
284
284
  require_relative 'rubocop/cop/lint/implicit_string_concatenation'
@@ -308,6 +308,7 @@ require_relative 'rubocop/cop/lint/rand_one'
308
308
  require_relative 'rubocop/cop/lint/redundant_cop_disable_directive'
309
309
  require_relative 'rubocop/cop/lint/redundant_cop_enable_directive'
310
310
  require_relative 'rubocop/cop/lint/redundant_require_statement'
311
+ require_relative 'rubocop/cop/lint/redundant_safe_navigation'
311
312
  require_relative 'rubocop/cop/lint/redundant_splat_expansion'
312
313
  require_relative 'rubocop/cop/lint/redundant_string_coercion'
313
314
  require_relative 'rubocop/cop/lint/redundant_with_index'
@@ -398,6 +399,7 @@ require_relative 'rubocop/cop/style/case_like_if'
398
399
  require_relative 'rubocop/cop/style/character_literal'
399
400
  require_relative 'rubocop/cop/style/class_and_module_children'
400
401
  require_relative 'rubocop/cop/style/class_check'
402
+ require_relative 'rubocop/cop/style/class_equality_comparison'
401
403
  require_relative 'rubocop/cop/style/class_methods'
402
404
  require_relative 'rubocop/cop/style/class_methods_definitions'
403
405
  require_relative 'rubocop/cop/style/class_vars'
@@ -21,6 +21,7 @@ module RuboCop
21
21
  private
22
22
 
23
23
  def serialize_offense(offense)
24
+ status = :uncorrected if %i[corrected corrected_with_todo].include?(offense.status)
24
25
  {
25
26
  # Calling #to_s here ensures that the serialization works when using
26
27
  # other json serializers such as Oj. Some of these gems do not call
@@ -32,7 +33,7 @@ module RuboCop
32
33
  },
33
34
  message: message(offense),
34
35
  cop_name: offense.cop_name,
35
- status: :uncorrected
36
+ status: status || offense.status
36
37
  }
37
38
  end
38
39
 
@@ -52,8 +52,8 @@ module RuboCop
52
52
  end
53
53
 
54
54
  def semicolon(node)
55
- @semicolon ||= {}
56
- @semicolon[node.object_id] ||= processed_source.tokens_within(node).find(&:semicolon?)
55
+ @semicolon ||= {}.compare_by_identity
56
+ @semicolon[node] ||= processed_source.tokens_within(node).find(&:semicolon?)
57
57
  end
58
58
  end
59
59
  end
@@ -58,24 +58,22 @@ module RuboCop
58
58
  (send _ :required_ruby_version= $_)
59
59
  PATTERN
60
60
 
61
- def_node_matcher :string_version?, <<~PATTERN
62
- {(str _) (array (str _))}
61
+ def_node_matcher :defined_ruby_version, <<~PATTERN
62
+ {$(str _) $(array (str _) (str _))
63
+ (send (const (const nil? :Gem) :Requirement) :new $(str _))}
63
64
  PATTERN
64
65
 
65
66
  # rubocop:disable Metrics/AbcSize
66
67
  def investigate(processed_source)
67
- version = required_ruby_version(processed_source.ast).first
68
+ version_def = required_ruby_version(processed_source.ast).first
68
69
 
69
- if version
70
- return unless string_version?(version)
71
-
72
- ruby_version = extract_ruby_version(version)
73
-
74
- return if ruby_version == target_ruby_version.to_s
70
+ if version_def
71
+ ruby_version = extract_ruby_version(defined_ruby_version(version_def))
72
+ return if !ruby_version || ruby_version == target_ruby_version.to_s
75
73
 
76
74
  add_offense(
77
75
  processed_source.ast,
78
- location: version.loc.expression,
76
+ location: version_def.loc.expression,
79
77
  message: not_equal_message(ruby_version, target_ruby_version)
80
78
  )
81
79
  else
@@ -88,6 +86,8 @@ module RuboCop
88
86
  private
89
87
 
90
88
  def extract_ruby_version(required_ruby_version)
89
+ return unless required_ruby_version
90
+
91
91
  if required_ruby_version.array_type?
92
92
  required_ruby_version = required_ruby_version.children.detect do |v|
93
93
  /[>=]/.match?(v.str_content)
@@ -29,17 +29,14 @@ module RuboCop
29
29
  def on_send(node)
30
30
  return unless node.dot? || ampersand_dot?(node)
31
31
 
32
- if proper_dot_position?(node)
33
- correct_style_detected
34
- else
35
- return unless opposite_style_detected
32
+ return correct_style_detected if proper_dot_position?(node)
36
33
 
37
- dot = node.loc.dot
38
- message = message(dot)
34
+ opposite_style_detected
35
+ dot = node.loc.dot
36
+ message = message(dot)
39
37
 
40
- add_offense(dot, message: message) do |corrector|
41
- autocorrect(corrector, dot, node)
42
- end
38
+ add_offense(dot, message: message) do |corrector|
39
+ autocorrect(corrector, dot, node)
43
40
  end
44
41
  end
45
42
  alias on_csend on_send
@@ -84,7 +84,8 @@ module RuboCop
84
84
  end
85
85
 
86
86
  def on_send(node)
87
- return unless register_offense?(node)
87
+ return unless node.bare_access_modifier? && !node.parent&.block_type?
88
+ return if expected_empty_lines?(node)
88
89
 
89
90
  message = message(node)
90
91
  add_offense(node, message: message) do |corrector|
@@ -98,17 +99,15 @@ module RuboCop
98
99
 
99
100
  private
100
101
 
101
- def register_offense?(node)
102
- return false unless node.bare_access_modifier? && !node.parent.block_type?
103
-
102
+ def expected_empty_lines?(node)
104
103
  case style
105
104
  when :around
106
- return false if empty_lines_around?(node)
105
+ return true if empty_lines_around?(node)
107
106
  when :only_before
108
- return false if allowed_only_before_style?(node)
107
+ return true if allowed_only_before_style?(node)
109
108
  end
110
109
 
111
- true
110
+ false
112
111
  end
113
112
 
114
113
  def allowed_only_before_style?(node)
@@ -88,7 +88,7 @@ module RuboCop
88
88
  end
89
89
 
90
90
  def require_empty_line?(node)
91
- return false unless node&.respond_to?(:type)
91
+ return false unless node.respond_to?(:type)
92
92
 
93
93
  !allow_alias?(node) && !attribute_or_allowed_method?(node)
94
94
  end
@@ -51,22 +51,13 @@ module RuboCop
51
51
  style == :no_space && no_surrounding_space
52
52
  correct_style_detected
53
53
  else
54
- incorrect_style_detected(arg, value, space_on_both_sides,
55
- no_surrounding_space)
54
+ incorrect_style_detected(arg, value)
56
55
  end
57
56
  end
58
57
 
59
- def incorrect_style_detected(arg, value, space_on_both_sides,
60
- no_surrounding_space)
58
+ def incorrect_style_detected(arg, value)
61
59
  range = range_between(arg.end_pos, value.begin_pos)
62
60
 
63
- if style == :space && no_surrounding_space ||
64
- style == :no_space && space_on_both_sides
65
- return unless opposite_style_detected
66
- else
67
- return unless unrecognized_style_detected
68
- end
69
-
70
61
  add_offense(range) do |corrector|
71
62
  autocorrect(corrector, range)
72
63
  end
@@ -206,8 +206,6 @@ module RuboCop
206
206
 
207
207
  def no_space(begin_pos, end_pos, msg)
208
208
  if style == :space
209
- return unless opposite_style_detected
210
-
211
209
  offense(begin_pos, end_pos, msg)
212
210
  else
213
211
  correct_style_detected
@@ -216,8 +214,6 @@ module RuboCop
216
214
 
217
215
  def space(begin_pos, end_pos, msg)
218
216
  if style == :no_space
219
- return unless opposite_style_detected
220
-
221
217
  offense(begin_pos, end_pos, msg)
222
218
  else
223
219
  correct_style_detected
@@ -15,6 +15,8 @@ module RuboCop
15
15
  #
16
16
  # # good
17
17
  # # With parentheses, there's no ambiguity.
18
+ # some_method(a { |val| puts val })
19
+ # # or (different meaning)
18
20
  # some_method(a) { |val| puts val }
19
21
  #
20
22
  # # good
@@ -47,7 +47,21 @@ module RuboCop
47
47
  regexp_node.source_range.begin_pos == diagnostic.location.begin_pos
48
48
  end
49
49
 
50
- node.parent
50
+ find_offense_node(node.parent, node)
51
+ end
52
+
53
+ def find_offense_node(node, regexp_receiver)
54
+ return node unless node.parent
55
+
56
+ if node.parent.send_type? || method_chain_to_regexp_receiver?(node)
57
+ node = find_offense_node(node.parent, regexp_receiver)
58
+ end
59
+
60
+ node
61
+ end
62
+
63
+ def method_chain_to_regexp_receiver?(node)
64
+ node.parent.parent && node.parent.receiver.receiver == regexp_receiver
51
65
  end
52
66
  end
53
67
  end
@@ -32,6 +32,9 @@ module RuboCop
32
32
  def on_sym(node)
33
33
  return unless boolean_symbol?(node)
34
34
 
35
+ parent = node.parent
36
+ return if parent&.array_type? && parent&.percent_literal?(:symbol)
37
+
35
38
  add_offense(node, message: format(MSG, boolean: node.value)) do |corrector|
36
39
  autocorrect(corrector, node)
37
40
  end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Prefer using `Hash#compare_by_identity` than using `object_id` for hash keys.
7
+ #
8
+ # This cop is marked as unsafe as a hash possibly can contain other keys
9
+ # besides `object_id`s.
10
+ #
11
+ # @example
12
+ # # bad
13
+ # hash = {}
14
+ # hash[foo.object_id] = :bar
15
+ # hash.key?(baz.object_id)
16
+ #
17
+ # # good
18
+ # hash = {}.compare_by_identity
19
+ # hash[foo] = :bar
20
+ # hash.key?(baz)
21
+ #
22
+ class HashCompareByIdentity < Base
23
+ RESTRICT_ON_SEND = %i[key? has_key? fetch [] []=].freeze
24
+
25
+ MSG = 'Use `Hash#compare_by_identity` instead of using `object_id` for keys.'
26
+
27
+ def_node_matcher :id_as_hash_key?, <<~PATTERN
28
+ (send _ {:key? :has_key? :fetch :[] :[]=} (send _ :object_id) ...)
29
+ PATTERN
30
+
31
+ def on_send(node)
32
+ add_offense(node) if id_as_hash_key?(node)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -25,6 +25,7 @@ module RuboCop
25
25
  'in a Regexp literal.'
26
26
 
27
27
  def on_regexp(node)
28
+ return if node.interpolation?
28
29
  return if node.each_capture(named: false).none?
29
30
  return if node.each_capture(named: true).none?
30
31
 
@@ -43,7 +43,7 @@ module RuboCop
43
43
  end
44
44
 
45
45
  node.operator_method? || node.setter_method? || chained_calls?(node) ||
46
- operator_keyword?(node)
46
+ operator_keyword?(node) || node.first_argument.hash_type?
47
47
  end
48
48
 
49
49
  def first_argument_starts_with_left_parenthesis?(node)
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # This cop checks for redundant safe navigation calls.
7
+ # It is marked as unsafe, because it can produce code that returns
8
+ # non `nil` while `nil` result is expected on `nil` receiver.
9
+ #
10
+ # @example
11
+ # # bad
12
+ # attrs&.respond_to?(:[])
13
+ # foo&.dup&.inspect
14
+ #
15
+ # # good
16
+ # attrs.respond_to?(:[])
17
+ # foo.dup.inspect
18
+ #
19
+ class RedundantSafeNavigation < Base
20
+ include IgnoredMethods
21
+ include RangeHelp
22
+ extend AutoCorrector
23
+
24
+ MSG = 'Redundant safe navigation detected.'
25
+
26
+ NIL_METHODS = nil.methods.to_set.freeze
27
+
28
+ def on_csend(node)
29
+ return unless check_method?(node.method_name)
30
+
31
+ range = range_between(node.loc.dot.begin_pos, node.source_range.end_pos)
32
+ add_offense(range) do |corrector|
33
+ corrector.replace(node.loc.dot, '.')
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def check_method?(method_name)
40
+ NIL_METHODS.include?(method_name) && !ignored_method?(method_name)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -29,6 +29,8 @@ module RuboCop
29
29
  # content.
30
30
  # HEREDOC
31
31
  # end # 5 points
32
+ #
33
+ # NOTE: This cop does not apply for `Struct` definitions.
32
34
  class BlockLength < Base
33
35
  include CodeLength
34
36
 
@@ -36,7 +38,7 @@ module RuboCop
36
38
 
37
39
  def on_block(node)
38
40
  return if excluded_method?(node)
39
- return if node.class_constructor?
41
+ return if node.class_constructor? || node.struct_constructor?
40
42
 
41
43
  check_code_length(node)
42
44
  end