rubocop 1.73.0 → 1.74.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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +35 -4
  4. data/config/internal_affairs.yml +4 -0
  5. data/lib/rubocop/config_loader.rb +0 -1
  6. data/lib/rubocop/config_loader_resolver.rb +2 -1
  7. data/lib/rubocop/config_obsoletion/extracted_cop.rb +4 -3
  8. data/lib/rubocop/config_obsoletion.rb +1 -1
  9. data/lib/rubocop/cop/internal_affairs/example_description.rb +3 -1
  10. data/lib/rubocop/cop/internal_affairs/node_type_group.rb +91 -0
  11. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  12. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +4 -4
  13. data/lib/rubocop/cop/lint/empty_conditional_body.rb +14 -64
  14. data/lib/rubocop/cop/lint/erb_new_arguments.rb +0 -6
  15. data/lib/rubocop/cop/lint/literal_as_condition.rb +13 -16
  16. data/lib/rubocop/cop/lint/mixed_case_range.rb +1 -1
  17. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +2 -2
  18. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +9 -3
  19. data/lib/rubocop/cop/lint/return_in_void_context.rb +4 -11
  20. data/lib/rubocop/cop/lint/shared_mutable_default.rb +12 -1
  21. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +2 -11
  22. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +1 -1
  23. data/lib/rubocop/cop/mixin/range_help.rb +12 -0
  24. data/lib/rubocop/cop/mixin/target_ruby_version.rb +1 -1
  25. data/lib/rubocop/cop/style/class_and_module_children.rb +29 -7
  26. data/lib/rubocop/cop/style/commented_keyword.rb +10 -3
  27. data/lib/rubocop/cop/style/comparable_between.rb +75 -0
  28. data/lib/rubocop/cop/style/double_negation.rb +1 -1
  29. data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -7
  30. data/lib/rubocop/cop/style/exponential_notation.rb +2 -2
  31. data/lib/rubocop/cop/style/format_string_token.rb +38 -11
  32. data/lib/rubocop/cop/style/if_unless_modifier.rb +2 -2
  33. data/lib/rubocop/cop/style/inverse_methods.rb +8 -5
  34. data/lib/rubocop/cop/style/keyword_parameters_order.rb +13 -7
  35. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +3 -3
  36. data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
  37. data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -9
  38. data/lib/rubocop/cop/style/redundant_condition.rb +11 -0
  39. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +14 -4
  40. data/lib/rubocop/cop/style/redundant_freeze.rb +1 -1
  41. data/lib/rubocop/cop/style/rescue_modifier.rb +3 -0
  42. data/lib/rubocop/cop/style/sole_nested_conditional.rb +0 -6
  43. data/lib/rubocop/cop/utils/format_string.rb +5 -2
  44. data/lib/rubocop/directive_comment.rb +1 -1
  45. data/lib/rubocop/ext/regexp_node.rb +0 -1
  46. data/lib/rubocop/version.rb +1 -1
  47. data/lib/rubocop.rb +1 -0
  48. metadata +6 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e3d6b4b7f7dd2a3128259ff94614da64550ae7c4148106a681987a9ee739b905
4
- data.tar.gz: 023ed07c7e4445c1dc44b3062cf0199321e3cc7fc6d4abf55287d281519bdb11
3
+ metadata.gz: 440bee0e28f294bab2eba4c11e9c681342917c69ad4c00e36eceb88743767c29
4
+ data.tar.gz: 68e9e209a22e891a38b677f97344d2d10e9a8913dd999751472f301deed43b31
5
5
  SHA512:
6
- metadata.gz: cfc82c25468c882682017c7ab8f750970896dcacae270fc00fc6482e4a7d12a20c97f7f56509811fec8c811981be457fc450c977c058d72700490ae72a4aff0a
7
- data.tar.gz: 04cfd985c5527d40ba6fd11e33e64278f37b8fcd78a63cfcdf5fef317bef248bfc8771febfa39a05a474372c1ad56190766dc7a188ea9e17bc72031f16d672da
6
+ metadata.gz: 70db27a5b7a0e00696672a5b4fcd4e3bf35aa40c85ef65ccb630914ab110a5e5b657927aa1b1c8637be76b7041a90e2ad3c4ed188110266c048d0c4d6a4be0b4
7
+ data.tar.gz: e5599d30a4f776d85d202acad2ac03c7e4568e64a1c4038cb87b8ee3372b2428882924a91ea49853c98cf0614280d002918363eef41fe0990dc8b1895d8e9776
data/README.md CHANGED
@@ -52,7 +52,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
52
52
  in your `Gemfile`:
53
53
 
54
54
  ```rb
55
- gem 'rubocop', '~> 1.73', require: false
55
+ gem 'rubocop', '~> 1.74', require: false
56
56
  ```
57
57
 
58
58
  See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
data/config/default.yml CHANGED
@@ -1887,10 +1887,9 @@ Lint/EmptyConditionalBody:
1887
1887
  Description: 'Checks for the presence of `if`, `elsif` and `unless` branches without a body.'
1888
1888
  Enabled: true
1889
1889
  AutoCorrect: contextual
1890
- SafeAutoCorrect: false
1891
1890
  AllowComments: true
1892
1891
  VersionAdded: '0.89'
1893
- VersionChanged: '1.61'
1892
+ VersionChanged: '1.73'
1894
1893
 
1895
1894
  Lint/EmptyEnsure:
1896
1895
  Description: 'Checks for empty ensure block.'
@@ -3105,6 +3104,8 @@ Naming/VariableNumber:
3105
3104
  CheckMethodNames: true
3106
3105
  CheckSymbols: true
3107
3106
  AllowedIdentifiers:
3107
+ - TLS1_1 # OpenSSL::SSL::TLS1_1_VERSION
3108
+ - TLS1_2 # OpenSSL::SSL::TLS1_2_VERSION
3108
3109
  - capture3 # Open3.capture3
3109
3110
  - iso8601 # Time#iso8601
3110
3111
  - rfc1123_date # CGI.rfc1123_date
@@ -3500,6 +3501,7 @@ Style/ClassAndModuleChildren:
3500
3501
  SafeAutoCorrect: false
3501
3502
  Enabled: true
3502
3503
  VersionAdded: '0.19'
3504
+ VersionChanged: '1.74'
3503
3505
  #
3504
3506
  # Basically there are two different styles:
3505
3507
  #
@@ -3515,7 +3517,21 @@ Style/ClassAndModuleChildren:
3515
3517
  #
3516
3518
  # The compact style is only forced, for classes or modules with one child.
3517
3519
  EnforcedStyle: nested
3518
- SupportedStyles:
3520
+ SupportedStyles: &supported_styles
3521
+ - nested
3522
+ - compact
3523
+ # Configure classes separately, if desired. If not set, or set to `nil`,
3524
+ # the `EnforcedStyle` value will be used.
3525
+ EnforcedStyleForClasses: ~
3526
+ SupportedStylesForClasses:
3527
+ - ~
3528
+ - nested
3529
+ - compact
3530
+ # Configure modules separately, if desired. If not set, or set to `nil`,
3531
+ # the `EnforcedStyle` value will be used.
3532
+ EnforcedStyleForModules: ~
3533
+ SupportedStylesForModules:
3534
+ - ~
3519
3535
  - nested
3520
3536
  - compact
3521
3537
 
@@ -3668,6 +3684,12 @@ Style/CommentedKeyword:
3668
3684
  VersionAdded: '0.51'
3669
3685
  VersionChanged: '1.19'
3670
3686
 
3687
+ Style/ComparableBetween:
3688
+ Description: 'Enforces the use of `Comparable#between?` instead of logical comparison.'
3689
+ Enabled: pending
3690
+ VersionAdded: '1.74'
3691
+ StyleGuide: '#ranges-or-between'
3692
+
3671
3693
  Style/ComparableClamp:
3672
3694
  Description: 'Enforces the use of `Comparable#clamp` instead of comparison by minimum and maximum.'
3673
3695
  Enabled: pending
@@ -4070,8 +4092,14 @@ Style/FormatStringToken:
4070
4092
  # style token in a format string to be allowed when enforced style is not
4071
4093
  # `unannotated`.
4072
4094
  MaxUnannotatedPlaceholdersAllowed: 1
4095
+ # The mode the cop operates in. Two values are allowed:
4096
+ # * aggressive (default): all strings are considered
4097
+ # * conservative:
4098
+ # only register offenses for strings given to `printf`, `sprintf`,
4099
+ # format` and `%` methods. Other strings are not considered.
4100
+ Mode: aggressive
4073
4101
  VersionAdded: '0.49'
4074
- VersionChanged: '1.0'
4102
+ VersionChanged: '1.74'
4075
4103
  AllowedMethods: []
4076
4104
  AllowedPatterns: []
4077
4105
 
@@ -5108,6 +5136,9 @@ Style/RedundantCondition:
5108
5136
  Description: 'Checks for unnecessary conditional expressions.'
5109
5137
  Enabled: true
5110
5138
  VersionAdded: '0.76'
5139
+ VersionChanged: '1.73'
5140
+ AllowedMethods:
5141
+ - nonzero?
5111
5142
 
5112
5143
  Style/RedundantConditional:
5113
5144
  Description: "Don't return true/false from a conditional."
@@ -14,6 +14,10 @@ InternalAffairs/ExampleDescription:
14
14
  Include:
15
15
  - 'spec/rubocop/cop/**/*.rb'
16
16
 
17
+ InternalAffairs/NodeTypeGroup:
18
+ Include:
19
+ - 'lib/rubocop/cop/**/*.rb'
20
+
17
21
  InternalAffairs/OnSendWithoutOnCSend:
18
22
  Include:
19
23
  - 'lib/rubocop/cop/**/*.rb'
@@ -63,7 +63,6 @@ module RuboCop
63
63
  loaded_features = resolver.resolve_requires(path, hash)
64
64
  add_loaded_features(loaded_features)
65
65
 
66
- resolver.override_department_setting_for_cops({}, hash)
67
66
  resolver.resolve_inheritance_from_gems(hash)
68
67
  resolver.resolve_inheritance(path, hash, file, debug?)
69
68
  hash.delete('inherit_from')
@@ -9,7 +9,8 @@ module RuboCop
9
9
  # @api private
10
10
  class ConfigLoaderResolver # rubocop:disable Metrics/ClassLength
11
11
  def resolve_plugins(rubocop_config, plugins)
12
- return if (plugins = Array(plugins)).empty?
12
+ plugins = Array(plugins) - ConfigLoader.loaded_plugins.map { |plugin| plugin.about.name }
13
+ return if plugins.empty?
13
14
 
14
15
  Plugin.integrate_plugins(rubocop_config, plugins)
15
16
  end
@@ -15,7 +15,7 @@ module RuboCop
15
15
  end
16
16
 
17
17
  def violated?
18
- return false if feature_loaded?
18
+ return false if plugin_loaded?
19
19
 
20
20
  affected_cops.any?
21
21
  end
@@ -38,8 +38,9 @@ module RuboCop
38
38
  end
39
39
  end
40
40
 
41
- def feature_loaded?
42
- config.loaded_features.include?(gem)
41
+ def plugin_loaded?
42
+ # Plugins loaded via `require` are included in `loaded_features`.
43
+ config.loaded_plugins.include?(gem) || config.loaded_features.include?(gem)
43
44
  end
44
45
  end
45
46
  end
@@ -50,7 +50,7 @@ module RuboCop
50
50
  # Default rules for obsoletions are in config/obsoletion.yml
51
51
  # Additional rules files can be added with `RuboCop::ConfigObsoletion.files << filename`
52
52
  def load_rules # rubocop:disable Metrics/AbcSize
53
- rules = LOAD_RULES_CACHE[self.class.files] ||=
53
+ rules = LOAD_RULES_CACHE[self.class.files.hash] ||=
54
54
  self.class.files.each_with_object({}) do |filename, hash|
55
55
  hash.merge!(YAML.safe_load(File.read(filename)) || {}) do |_key, first, second|
56
56
  case first
@@ -50,10 +50,12 @@ module RuboCop
50
50
  }.freeze
51
51
 
52
52
  EXPECT_NO_CORRECTIONS_DESCRIPTION_MAPPING = {
53
- /\A(auto[- ]?)?correct/ => 'does not correct'
53
+ /\A(auto[- ]?)?corrects?/ => 'does not correct',
54
+ /\band (auto[- ]?)?corrects/ => 'but does not correct'
54
55
  }.freeze
55
56
 
56
57
  EXPECT_CORRECTION_DESCRIPTION_MAPPING = {
58
+ /\bbut (does not|doesn't) (auto[- ]?)?correct/ => 'and autocorrects',
57
59
  /\b(does not|doesn't) (auto[- ]?)?correct/ => 'autocorrects'
58
60
  }.freeze
59
61
 
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module InternalAffairs
6
+ # Checks that node types are checked against their group when all types of a
7
+ # group are checked.
8
+ #
9
+ # @example
10
+ # # bad
11
+ # node.type?(:irange, :erange)
12
+ #
13
+ # # good
14
+ # node.range_type?
15
+ #
16
+ # # bad
17
+ # node.type?(:irange, :erange, :send, :csend)
18
+ #
19
+ # # good
20
+ # node.type?(:range, :call)
21
+ #
22
+ class NodeTypeGroup < Base
23
+ extend AutoCorrector
24
+ include RangeHelp
25
+
26
+ MSG = 'Use `:%<group>s` instead of individually listing group types.'
27
+
28
+ RESTRICT_ON_SEND = %i[type? each_ancestor each_child_node each_descendant each_node].freeze
29
+
30
+ def on_send(node)
31
+ return unless node.receiver
32
+
33
+ symbol_args = node.arguments.select(&:sym_type?)
34
+ return if symbol_args.none?
35
+
36
+ NodePatternGroups::NODE_GROUPS.each do |group_name, group_types|
37
+ next unless group_satisfied?(group_types, symbol_args)
38
+
39
+ offense_range = arguments_range(node)
40
+ add_offense(offense_range, message: format(MSG, group: group_name)) do |corrector|
41
+ autocorrect(corrector, node, symbol_args, group_name, group_types)
42
+ end
43
+ end
44
+ end
45
+ alias on_csend on_send
46
+
47
+ private
48
+
49
+ def arguments_range(node)
50
+ range_between(
51
+ node.first_argument.source_range.begin_pos,
52
+ node.last_argument.source_range.end_pos
53
+ )
54
+ end
55
+
56
+ def group_satisfied?(group_types, symbol_args)
57
+ group_types.all? { |type| symbol_args.any? { |arg| arg.value == type } }
58
+ end
59
+
60
+ def autocorrect(corrector, node, symbol_args, group_name, group_types)
61
+ if node.method?(:type?) && node.arguments.count == group_types.count
62
+ autocorrect_to_explicit_predicate(corrector, node, group_name)
63
+ else
64
+ autocorrect_keep_method(corrector, symbol_args, group_name, group_types)
65
+ end
66
+ end
67
+
68
+ def autocorrect_to_explicit_predicate(corrector, node, group_name)
69
+ corrector.replace(node.selector, "#{group_name}_type?")
70
+ corrector.remove(arguments_range(node))
71
+ end
72
+
73
+ def autocorrect_keep_method(corrector, symbol_args, group_name, group_types)
74
+ first_replaced = false
75
+ symbol_args.each do |arg|
76
+ next unless group_types.include?(arg.value)
77
+
78
+ if first_replaced
79
+ range = range_with_surrounding_space(arg.source_range)
80
+ range = range_with_surrounding_comma(range, :left)
81
+ corrector.remove(range)
82
+ else
83
+ first_replaced = true
84
+ corrector.replace(arg, ":#{group_name}")
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -17,6 +17,7 @@ require_relative 'internal_affairs/node_destructuring'
17
17
  require_relative 'internal_affairs/node_first_or_last_argument'
18
18
  require_relative 'internal_affairs/node_matcher_directive'
19
19
  require_relative 'internal_affairs/node_pattern_groups'
20
+ require_relative 'internal_affairs/node_type_group'
20
21
  require_relative 'internal_affairs/node_type_multiple_predicates'
21
22
  require_relative 'internal_affairs/node_type_predicate'
22
23
  require_relative 'internal_affairs/numblock_handler'
@@ -155,10 +155,10 @@ module RuboCop
155
155
  end
156
156
 
157
157
  def all_elements_aligned?(elements)
158
- elements.flat_map do |e|
159
- if e.hash_type?
160
- e.each_child_node.map { |child| child.loc.column }
161
- else
158
+ if elements.first.hash_type?
159
+ elements.first.each_child_node.map { |child| child.loc.column }
160
+ else
161
+ elements.flat_map do |e|
162
162
  e.loc.column
163
163
  end
164
164
  end.uniq.count == 1
@@ -7,11 +7,6 @@ module RuboCop
7
7
  #
8
8
  # NOTE: empty `else` branches are handled by `Style/EmptyElse`.
9
9
  #
10
- # @safety
11
- # Autocorrection for this cop is not safe. The conditions for empty branches that
12
- # the autocorrection removes may have side effects, or the logic in subsequent
13
- # branches may change due to the removal of a previous condition.
14
- #
15
10
  # @example
16
11
  # # bad
17
12
  # if condition
@@ -41,6 +36,13 @@ module RuboCop
41
36
  # if condition
42
37
  # do_something
43
38
  # elsif other_condition
39
+ # nil
40
+ # end
41
+ #
42
+ # # good
43
+ # if condition
44
+ # do_something
45
+ # elsif other_condition
44
46
  # do_something_else
45
47
  # end
46
48
  #
@@ -63,11 +65,9 @@ module RuboCop
63
65
  class EmptyConditionalBody < Base
64
66
  extend AutoCorrector
65
67
  include CommentsHelp
66
- include RangeHelp
67
68
 
68
69
  MSG = 'Avoid `%<keyword>s` branches without a body.'
69
70
 
70
- # rubocop:disable Metrics/AbcSize
71
71
  def on_if(node)
72
72
  return if node.body || same_line?(node.loc.begin, node.loc.end)
73
73
  return if cop_config['AllowComments'] && contains_comments?(node)
@@ -75,12 +75,11 @@ module RuboCop
75
75
  range = offense_range(node)
76
76
 
77
77
  add_offense(range, message: format(MSG, keyword: node.keyword)) do |corrector|
78
- next if node.parent&.call_type?
78
+ next unless can_simplify_conditional?(node)
79
79
 
80
- autocorrect(corrector, node)
80
+ flip_orphaned_else(corrector, node)
81
81
  end
82
82
  end
83
- # rubocop:enable Metrics/AbcSize
84
83
 
85
84
  private
86
85
 
@@ -92,53 +91,23 @@ module RuboCop
92
91
  end
93
92
  end
94
93
 
95
- def autocorrect(corrector, node)
96
- remove_comments(corrector, node)
97
- remove_empty_branch(corrector, node)
98
- correct_other_branches(corrector, node)
99
- end
100
-
101
- def remove_comments(corrector, node)
102
- comments_in_range(node).each do |comment|
103
- range = range_by_whole_lines(comment.source_range, include_final_newline: true)
104
- corrector.remove(range)
105
- end
94
+ def can_simplify_conditional?(node)
95
+ node.else_branch && node.loc.else.source == 'else'
106
96
  end
107
97
 
108
- # rubocop:disable Metrics/AbcSize
109
98
  def remove_empty_branch(corrector, node)
110
99
  range = if empty_if_branch?(node) && else_branch?(node)
111
100
  branch_range(node)
112
- elsif same_line?(node, else_kw_loc = node.loc.else)
113
- node.source_range.begin.join(else_kw_loc.begin)
114
- elsif node.parent&.loc.respond_to?(:end) &&
115
- same_line?(node, end_loc = node.parent.loc.end)
116
- node.source_range.begin.join(end_loc.begin)
117
101
  else
118
102
  deletion_range(branch_range(node))
119
103
  end
120
104
 
121
105
  corrector.remove(range)
122
106
  end
123
- # rubocop:enable Metrics/AbcSize
124
-
125
- def correct_other_branches(corrector, node)
126
- return unless require_other_branches_correction?(node)
127
-
128
- if node.else_branch&.if_type? && !node.else_branch.modifier_form?
129
- # Replace an orphaned `elsif` with `if`
130
- corrector.replace(node.else_branch.loc.keyword, 'if')
131
- else
132
- # Flip orphaned `else`
133
- corrector.replace(node.loc.else, "#{node.inverse_keyword} #{node.condition.source}")
134
- end
135
- end
136
-
137
- def require_other_branches_correction?(node)
138
- return false unless node.if_type? && node.else?
139
- return false if !empty_if_branch?(node) && node.elsif?
140
107
 
141
- !empty_elsif_branch?(node)
108
+ def flip_orphaned_else(corrector, node)
109
+ corrector.replace(node.loc.else, "#{node.inverse_keyword} #{node.condition.source}")
110
+ remove_empty_branch(corrector, node)
142
111
  end
143
112
 
144
113
  def empty_if_branch?(node)
@@ -149,36 +118,17 @@ module RuboCop
149
118
  if_branch.if_type? && !if_branch.body
150
119
  end
151
120
 
152
- def empty_elsif_branch?(node)
153
- return false unless (else_branch = node.else_branch)
154
-
155
- else_branch.if_type? && !else_branch.body
156
- end
157
-
158
121
  def else_branch?(node)
159
122
  node.else_branch && !node.else_branch.if_type?
160
123
  end
161
124
 
162
- # rubocop:disable Metrics/AbcSize
163
125
  def branch_range(node)
164
126
  if empty_if_branch?(node) && else_branch?(node)
165
127
  node.source_range.with(end_pos: node.loc.else.begin_pos)
166
128
  elsif node.loc.else
167
129
  node.source_range.with(end_pos: node.condition.source_range.end_pos)
168
- elsif all_branches_body_missing?(node)
169
- if_node = node.ancestors.detect(&:if?)
170
- node.source_range.join(if_node.loc.end.end)
171
- else
172
- node.source_range
173
130
  end
174
131
  end
175
- # rubocop:enable Metrics/AbcSize
176
-
177
- def all_branches_body_missing?(node)
178
- return false unless node.parent&.if_type?
179
-
180
- node.parent.branches.compact.empty?
181
- end
182
132
 
183
133
  def deletion_range(range)
184
134
  # Collect a range between the start of the `if` node and the next relevant node,
@@ -156,12 +156,6 @@ module RuboCop
156
156
 
157
157
  overridden_kwargs
158
158
  end
159
-
160
- def arguments_range(node)
161
- arguments = node.arguments
162
-
163
- range_between(arguments.first.source_range.begin_pos, arguments.last.source_range.end_pos)
164
- end
165
159
  end
166
160
  end
167
161
  end
@@ -18,12 +18,15 @@ module RuboCop
18
18
  # end
19
19
  #
20
20
  # # bad
21
- # if some_var && true
21
+ # # We're only interested in the left hand side being a truthy literal,
22
+ # # because it affects the evaluation of the &&, whereas the right hand
23
+ # # side will be conditionally executed/called and can be a literal.
24
+ # if true && some_var
22
25
  # do_something
23
26
  # end
24
27
  #
25
28
  # # good
26
- # if some_var && some_condition
29
+ # if some_var
27
30
  # do_something
28
31
  # end
29
32
  #
@@ -39,23 +42,17 @@ module RuboCop
39
42
  MSG = 'Literal `%<literal>s` appeared as a condition.'
40
43
  RESTRICT_ON_SEND = [:!].freeze
41
44
 
42
- # rubocop:disable Metrics/AbcSize
43
45
  def on_and(node)
44
- if node.lhs.truthy_literal? && node.rhs.truthy_literal?
45
- add_offense(node) do |corrector|
46
- corrector.replace(node, 'true')
47
- end
48
- elsif node.lhs.truthy_literal?
49
- add_offense(node.lhs) do |corrector|
50
- corrector.replace(node, node.rhs.source)
51
- end
52
- elsif node.rhs.truthy_literal?
53
- add_offense(node.rhs) do |corrector|
54
- corrector.replace(node, node.lhs.source)
55
- end
46
+ return unless node.lhs.truthy_literal?
47
+
48
+ add_offense(node.lhs) do |corrector|
49
+ # Don't autocorrect `'foo' && return` because having `return` as
50
+ # the leftmost node can lead to a void value expression syntax error.
51
+ next if node.rhs.type?(:return, :break, :next)
52
+
53
+ corrector.replace(node, node.rhs.source)
56
54
  end
57
55
  end
58
- # rubocop:enable Metrics/AbcSize
59
56
 
60
57
  def on_if(node)
61
58
  cond = condition(node)
@@ -94,7 +94,7 @@ module RuboCop
94
94
 
95
95
  def skip_range?(range_start, range_end)
96
96
  [range_start, range_end].any? do |bound|
97
- bound.type != :literal
97
+ bound&.type != :literal
98
98
  end
99
99
  end
100
100
 
@@ -46,7 +46,7 @@ module RuboCop
46
46
  def on_return(return_node)
47
47
  return if return_value?(return_node)
48
48
 
49
- return_node.each_ancestor(:block, :def, :defs) do |node|
49
+ return_node.each_ancestor(:any_block, :def, :defs) do |node|
50
50
  break if scoped_node?(node)
51
51
 
52
52
  # if a proc is passed to `Module#define_method` or
@@ -54,7 +54,7 @@ module RuboCop
54
54
  # non-local exit error
55
55
  break if define_method?(node.send_node)
56
56
 
57
- next unless node.arguments?
57
+ next if node.argument_list.empty?
58
58
 
59
59
  if chained_send?(node.send_node)
60
60
  add_offense(return_node.loc.keyword)
@@ -3,13 +3,13 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # Checks for redundant uses of `to_s`, `to_sym`, `to_i`, `to_f`, `to_r`, `to_c`,
6
+ # Checks for redundant uses of `to_s`, `to_sym`, `to_i`, `to_f`, `to_d`, `to_r`, `to_c`,
7
7
  # `to_a`, `to_h`, and `to_set`.
8
8
  #
9
9
  # When one of these methods is called on an object of the same type, that object
10
10
  # is returned, making the call unnecessary. The cop detects conversion methods called
11
11
  # on object literals, class constructors, class `[]` methods, and the `Kernel` methods
12
- # `String()`, `Integer()`, `Float()`, `Rational()`, `Complex()` and `Array()`.
12
+ # `String()`, `Integer()`, `Float()`, BigDecimal(), `Rational()`, `Complex()`, and `Array()`.
13
13
  #
14
14
  # Specifically, these cases are detected for each conversion method:
15
15
  #
@@ -98,6 +98,7 @@ module RuboCop
98
98
  to_s: 'string_constructor?',
99
99
  to_i: 'integer_constructor?',
100
100
  to_f: 'float_constructor?',
101
+ to_d: 'bigdecimal_constructor?',
101
102
  to_r: 'rational_constructor?',
102
103
  to_c: 'complex_constructor?',
103
104
  to_a: 'array_constructor?',
@@ -110,7 +111,7 @@ module RuboCop
110
111
  TYPED_METHODS = { to_s: %i[inspect] }.freeze
111
112
 
112
113
  CONVERSION_METHODS = Set[*LITERAL_NODE_TYPES.keys].freeze
113
- RESTRICT_ON_SEND = CONVERSION_METHODS
114
+ RESTRICT_ON_SEND = CONVERSION_METHODS + [:to_d]
114
115
 
115
116
  private_constant :LITERAL_NODE_TYPES, :CONSTRUCTOR_MAPPING
116
117
 
@@ -137,6 +138,11 @@ module RuboCop
137
138
  #type_constructor?(:Float)
138
139
  PATTERN
139
140
 
141
+ # @!method bigdecimal_constructor?(node)
142
+ def_node_matcher :bigdecimal_constructor?, <<~PATTERN
143
+ #type_constructor?(:BigDecimal)
144
+ PATTERN
145
+
140
146
  # @!method rational_constructor?(node)
141
147
  def_node_matcher :rational_constructor?, <<~PATTERN
142
148
  #type_constructor?(:Rational)
@@ -35,22 +35,15 @@ module RuboCop
35
35
  def on_return(return_node)
36
36
  return unless return_node.descendants.any?
37
37
 
38
- context_node = non_void_context(return_node)
39
-
40
- return unless context_node&.def_type?
41
- return unless context_node&.void_context?
38
+ def_node = return_node.each_ancestor(:def).first
39
+ return unless def_node&.void_context?
40
+ return if return_node.each_ancestor(:any_block).any?(&:lambda?)
42
41
 
43
42
  add_offense(
44
43
  return_node.loc.keyword,
45
- message: format(message, method: context_node.method_name)
44
+ message: format(message, method: def_node.method_name)
46
45
  )
47
46
  end
48
-
49
- private
50
-
51
- def non_void_context(return_node)
52
- return_node.each_ancestor(:block, :def, :defs).first
53
- end
54
47
  end
55
48
  end
56
49
  end
@@ -51,7 +51,18 @@ module RuboCop
51
51
 
52
52
  # @!method hash_initialized_with_mutable_shared_object?(node)
53
53
  def_node_matcher :hash_initialized_with_mutable_shared_object?, <<~PATTERN
54
- (send (const {nil? cbase} :Hash) :new {array hash (send (const {nil? cbase} {:Array :Hash}) :new)})
54
+ {
55
+ (send (const {nil? cbase} :Hash) :new [
56
+ {array hash (send (const {nil? cbase} {:Array :Hash}) :new)}
57
+ !#capacity_keyword_argument?
58
+ ])
59
+ (send (const {nil? cbase} :Hash) :new hash #capacity_keyword_argument?)
60
+ }
61
+ PATTERN
62
+
63
+ # @!method capacity_keyword_argument?(node)
64
+ def_node_matcher :capacity_keyword_argument?, <<~PATTERN
65
+ (hash (pair (sym :capacity) _))
55
66
  PATTERN
56
67
 
57
68
  def on_send(node)
@@ -4,8 +4,8 @@ module RuboCop
4
4
  module Cop
5
5
  module Lint
6
6
  # Checks for useless constant scoping. Private constants must be defined using
7
- # `private_constant` or `class << self`. Even if `private` access modifier is used,
8
- # it is public scope despite its appearance.
7
+ # `private_constant`. Even if `private` access modifier is used, it is public scope despite
8
+ # its appearance.
9
9
  #
10
10
  # It does not support autocorrection due to behavior change and multiple ways to fix it.
11
11
  # Or a public constant may be intended.
@@ -26,14 +26,6 @@ module RuboCop
26
26
  #
27
27
  # # good
28
28
  # class Foo
29
- # class << self
30
- # private
31
- # PRIVATE_CONST = 42
32
- # end
33
- # end
34
- #
35
- # # good
36
- # class Foo
37
29
  # PUBLIC_CONST = 42 # If private scope is not intended.
38
30
  # end
39
31
  #
@@ -46,7 +38,6 @@ module RuboCop
46
38
  PATTERN
47
39
 
48
40
  def on_casgn(node)
49
- return if node.each_ancestor(:sclass).any?
50
41
  return unless after_private_modifier?(node.left_siblings)
51
42
  return if private_constantize?(node.right_siblings, node.name)
52
43