rubocop 1.39.0 → 1.40.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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +47 -9
  4. data/exe/rubocop +1 -1
  5. data/lib/rubocop/comment_config.rb +5 -0
  6. data/lib/rubocop/config.rb +5 -4
  7. data/lib/rubocop/config_loader.rb +5 -5
  8. data/lib/rubocop/config_loader_resolver.rb +1 -1
  9. data/lib/rubocop/cop/base.rb +2 -9
  10. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +22 -6
  11. data/lib/rubocop/cop/internal_affairs/lambda_or_proc.rb +46 -0
  12. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  13. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  14. data/lib/rubocop/cop/lint/assignment_in_condition.rb +11 -1
  15. data/lib/rubocop/cop/lint/deprecated_constants.rb +8 -1
  16. data/lib/rubocop/cop/lint/empty_block.rb +1 -5
  17. data/lib/rubocop/cop/lint/empty_conditional_body.rb +1 -1
  18. data/lib/rubocop/cop/lint/interpolation_check.rb +4 -3
  19. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +5 -0
  20. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +13 -3
  21. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +15 -6
  22. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +5 -4
  23. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +4 -3
  24. data/lib/rubocop/cop/lint/void.rb +6 -6
  25. data/lib/rubocop/cop/metrics/block_length.rb +9 -4
  26. data/lib/rubocop/cop/metrics/class_length.rb +9 -4
  27. data/lib/rubocop/cop/metrics/method_length.rb +9 -4
  28. data/lib/rubocop/cop/metrics/module_length.rb +9 -4
  29. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +5 -2
  30. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +24 -5
  31. data/lib/rubocop/cop/mixin/statement_modifier.rb +15 -1
  32. data/lib/rubocop/cop/registry.rb +23 -11
  33. data/lib/rubocop/cop/style/array_intersect.rb +111 -0
  34. data/lib/rubocop/cop/style/guard_clause.rb +32 -5
  35. data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -1
  36. data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
  37. data/lib/rubocop/cop/style/redundant_argument.rb +3 -0
  38. data/lib/rubocop/cop/style/redundant_constant_base.rb +72 -0
  39. data/lib/rubocop/cop/style/redundant_return.rb +7 -0
  40. data/lib/rubocop/cop/style/redundant_sort.rb +1 -1
  41. data/lib/rubocop/cop/style/require_order.rb +88 -0
  42. data/lib/rubocop/cop/style/safe_navigation.rb +35 -6
  43. data/lib/rubocop/cop/style/select_by_regexp.rb +8 -4
  44. data/lib/rubocop/cop/style/string_literals.rb +1 -5
  45. data/lib/rubocop/cop/style/symbol_proc.rb +2 -4
  46. data/lib/rubocop/cop/team.rb +1 -1
  47. data/lib/rubocop/cop/util.rb +1 -1
  48. data/lib/rubocop/cop/variable_force/assignment.rb +1 -1
  49. data/lib/rubocop/cop/variable_force.rb +20 -29
  50. data/lib/rubocop/formatter/disabled_config_formatter.rb +17 -6
  51. data/lib/rubocop/formatter/html_formatter.rb +1 -1
  52. data/lib/rubocop/formatter.rb +3 -1
  53. data/lib/rubocop/optimized_patterns.rb +38 -0
  54. data/lib/rubocop/options.rb +9 -1
  55. data/lib/rubocop/path_util.rb +14 -2
  56. data/lib/rubocop/result_cache.rb +1 -1
  57. data/lib/rubocop/rspec/cop_helper.rb +4 -1
  58. data/lib/rubocop/rspec/support.rb +2 -2
  59. data/lib/rubocop/server/core.rb +1 -1
  60. data/lib/rubocop/target_ruby.rb +1 -1
  61. data/lib/rubocop/version.rb +1 -1
  62. data/lib/rubocop.rb +14 -6
  63. metadata +8 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 881807be0f0f6eea20bd13bd8f08fdb158a5b155c8d3a22fd748683a68c1fef1
4
- data.tar.gz: 2a8e7d4b02f1ba468e02a4c20f8e3b830ce2a1d8ff0210f86aaeafab597c8c88
3
+ metadata.gz: bb2b7b02733dca8e7577cd5ccd776044179cd762685152d9c7d5a739dd7cf9e1
4
+ data.tar.gz: 47b6ef2704e65f30af91def68b22331aca13d629d954cc860288738dccd4f14d
5
5
  SHA512:
6
- metadata.gz: 11ea36bec754b07912e06b5481f964d10a6dbf5bfd56f99d8a8842ca46d56ae03a342a283d843336f977760c28a697ee995aa98268254a55b1218fa57a9fb5c7
7
- data.tar.gz: b5096cb4589d9bafdab0b6ab409ea9e7841dc06b274aeb7f7d5a26e703cb216c2a428d695fb2a087637467f1cdd5ac005398c66ee3e7d28d49cb4b203a87667d
6
+ metadata.gz: c65cd2840052b36832dec3218f2994b0dbaae5e482328c767b0f82ac3d882ce1a29a02ddd53e960c199514ff241d17d0c5f33b139b50634fce4c7fa246018a1c
7
+ data.tar.gz: 51442c821afd72669bb0845386c1c05495618736b46978e1d2fae12f3f69f30ff914025209f6efc2c673692e585e4e2968fe76467f2433ba98f2209d435b46bd
data/README.md CHANGED
@@ -53,7 +53,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
53
53
  in your `Gemfile`:
54
54
 
55
55
  ```rb
56
- gem 'rubocop', '~> 1.39', require: false
56
+ gem 'rubocop', '~> 1.40', require: false
57
57
  ```
58
58
 
59
59
  See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
data/config/default.yml CHANGED
@@ -161,7 +161,9 @@ AllCops:
161
161
  Bundler/DuplicatedGem:
162
162
  Description: 'Checks for duplicate gem entries in Gemfile.'
163
163
  Enabled: true
164
+ Severity: warning
164
165
  VersionAdded: '0.46'
166
+ VersionChanged: '1.40'
165
167
  Include:
166
168
  - '**/*.gemfile'
167
169
  - '**/Gemfile'
@@ -213,7 +215,9 @@ Bundler/InsecureProtocolSource:
213
215
  because HTTP requests are insecure. Please change your source to
214
216
  'https://rubygems.org' if possible, or 'http://rubygems.org' if not.
215
217
  Enabled: true
218
+ Severity: warning
216
219
  VersionAdded: '0.50'
220
+ VersionChanged: '1.40'
217
221
  AllowHttpProtocol: true
218
222
  Include:
219
223
  - '**/*.gemfile'
@@ -252,14 +256,18 @@ Gemspec/DependencyVersion:
252
256
  Gemspec/DeprecatedAttributeAssignment:
253
257
  Description: Checks that deprecated attribute assignments are not set in a gemspec file.
254
258
  Enabled: pending
259
+ Severity: warning
255
260
  VersionAdded: '1.30'
261
+ VersionChanged: '1.40'
256
262
  Include:
257
263
  - '**/*.gemspec'
258
264
 
259
265
  Gemspec/DuplicatedAssignment:
260
266
  Description: 'An attribute assignment method calls should be listed only once in a gemspec.'
261
267
  Enabled: true
268
+ Severity: warning
262
269
  VersionAdded: '0.52'
270
+ VersionChanged: '1.40'
263
271
  Include:
264
272
  - '**/*.gemspec'
265
273
 
@@ -278,7 +286,9 @@ Gemspec/OrderedDependencies:
278
286
  Gemspec/RequireMFA:
279
287
  Description: 'Checks that the gemspec has metadata to require Multi-Factor Authentication from RubyGems.'
280
288
  Enabled: pending
289
+ Severity: warning
281
290
  VersionAdded: '1.23'
291
+ VersionChanged: '1.40'
282
292
  Reference:
283
293
  - https://guides.rubygems.org/mfa-requirement-opt-in/
284
294
  Include:
@@ -287,8 +297,9 @@ Gemspec/RequireMFA:
287
297
  Gemspec/RequiredRubyVersion:
288
298
  Description: 'Checks that `required_ruby_version` of gemspec is specified and equal to `TargetRubyVersion` of .rubocop.yml.'
289
299
  Enabled: true
300
+ Severity: warning
290
301
  VersionAdded: '0.52'
291
- VersionChanged: '1.22'
302
+ VersionChanged: '1.40'
292
303
  Include:
293
304
  - '**/*.gemspec'
294
305
 
@@ -296,7 +307,9 @@ Gemspec/RubyVersionGlobalsUsage:
296
307
  Description: Checks usage of RUBY_VERSION in gemspec.
297
308
  StyleGuide: '#no-ruby-version-in-the-gemspec'
298
309
  Enabled: true
310
+ Severity: warning
299
311
  VersionAdded: '0.72'
312
+ VersionChanged: '1.40'
300
313
  Include:
301
314
  - '**/*.gemspec'
302
315
 
@@ -378,8 +391,9 @@ Layout/AssignmentIndentation:
378
391
  Checks the indentation of the first line of the
379
392
  right-hand-side of a multi-line assignment.
380
393
  Enabled: true
394
+ SafeAutoCorrect: false
381
395
  VersionAdded: '0.49'
382
- VersionChanged: '0.77'
396
+ VersionChanged: '1.40'
383
397
  # By default the indentation width from `Layout/IndentationWidth` is used,
384
398
  # but it can be overridden by setting this parameter.
385
399
  IndentationWidth: ~
@@ -1643,7 +1657,7 @@ Lint/DeprecatedConstants:
1643
1657
  Description: 'Checks for deprecated constants.'
1644
1658
  Enabled: pending
1645
1659
  VersionAdded: '1.8'
1646
- VersionChanged: '1.22'
1660
+ VersionChanged: '1.40'
1647
1661
  # You can configure deprecated constants.
1648
1662
  # If there is an alternative method, you can set alternative value as `Alternative`.
1649
1663
  # And you can set the deprecated version as `DeprecatedVersion`.
@@ -1670,6 +1684,12 @@ Lint/DeprecatedConstants:
1670
1684
  'Random::DEFAULT':
1671
1685
  Alternative: 'Random.new'
1672
1686
  DeprecatedVersion: '3.0'
1687
+ 'Struct::Group':
1688
+ Alternative: 'Etc::Group'
1689
+ DeprecatedVersion: '3.0'
1690
+ 'Struct::Passwd':
1691
+ Alternative: 'Etc::Passwd'
1692
+ DeprecatedVersion: '3.0'
1673
1693
 
1674
1694
  Lint/DeprecatedOpenSSLConstant:
1675
1695
  Description: "Don't use algorithm constants for `OpenSSL::Cipher` and `OpenSSL::Digest`."
@@ -1894,11 +1914,11 @@ Lint/InheritException:
1894
1914
  - runtime_error
1895
1915
 
1896
1916
  Lint/InterpolationCheck:
1897
- Description: 'Raise warning for interpolation in single q strs.'
1917
+ Description: 'Checks for interpolation in a single quoted string.'
1898
1918
  Enabled: true
1899
- Safe: false
1919
+ SafeAutoCorrect: false
1900
1920
  VersionAdded: '0.50'
1901
- VersionChanged: '0.87'
1921
+ VersionChanged: '1.40'
1902
1922
 
1903
1923
  Lint/LambdaWithoutLiteralBlock:
1904
1924
  Description: 'Checks uses of lambda without a literal block.'
@@ -2806,6 +2826,7 @@ Naming/MethodParameterName:
2806
2826
  - as
2807
2827
  - at
2808
2828
  - by
2829
+ - cc
2809
2830
  - db
2810
2831
  - id
2811
2832
  - if
@@ -3013,6 +3034,11 @@ Style/ArrayCoercion:
3013
3034
  Enabled: false
3014
3035
  VersionAdded: '0.88'
3015
3036
 
3037
+ Style/ArrayIntersect:
3038
+ Description: 'Use `array1.intersect?(array2)` instead of `(array1 & array2).any?`.'
3039
+ Enabled: 'pending'
3040
+ VersionAdded: '1.40'
3041
+
3016
3042
  Style/ArrayJoin:
3017
3043
  Description: 'Use Array#join instead of Array#*.'
3018
3044
  StyleGuide: '#array-join'
@@ -4660,10 +4686,12 @@ Style/RedundantArgument:
4660
4686
  Enabled: pending
4661
4687
  Safe: false
4662
4688
  VersionAdded: '1.4'
4663
- VersionChanged: '1.7'
4689
+ VersionChanged: '1.40'
4664
4690
  Methods:
4665
4691
  # Array#join
4666
4692
  join: ''
4693
+ # Array#sum
4694
+ sum: 0
4667
4695
  # String#split
4668
4696
  split: ' '
4669
4697
  # String#chomp
@@ -4698,6 +4726,11 @@ Style/RedundantConditional:
4698
4726
  Enabled: true
4699
4727
  VersionAdded: '0.50'
4700
4728
 
4729
+ Style/RedundantConstantBase:
4730
+ Description: Avoid redundant `::` prefix on constant.
4731
+ Enabled: pending
4732
+ VersionAdded: '1.40'
4733
+
4701
4734
  Style/RedundantEach:
4702
4735
  Description: 'Checks for redundant `each`.'
4703
4736
  Enabled: pending
@@ -4838,6 +4871,12 @@ Style/RegexpLiteral:
4838
4871
  # are found in the regexp string.
4839
4872
  AllowInnerSlashes: false
4840
4873
 
4874
+ Style/RequireOrder:
4875
+ Description: Sort `require` and `require_relative` in alphabetical order.
4876
+ Enabled: false
4877
+ SafeAutoCorrect: false
4878
+ VersionAdded: '1.40'
4879
+
4841
4880
  Style/RescueModifier:
4842
4881
  Description: 'Avoid using rescue in its modifier form.'
4843
4882
  StyleGuide: '#no-rescue-modifiers'
@@ -5122,12 +5161,11 @@ Style/SymbolProc:
5122
5161
  Enabled: true
5123
5162
  Safe: false
5124
5163
  VersionAdded: '0.26'
5125
- VersionChanged: '1.28'
5164
+ VersionChanged: '1.40'
5126
5165
  AllowMethodsWithArguments: false
5127
5166
  # A list of method names to be always allowed by the check.
5128
5167
  # The names should be fairly unique, otherwise you'll end up ignoring lots of code.
5129
5168
  AllowedMethods:
5130
- - respond_to
5131
5169
  - define_method
5132
5170
  AllowedPatterns: []
5133
5171
  IgnoredMethods: [] # deprecated
data/exe/rubocop CHANGED
@@ -11,8 +11,8 @@ exit exit_status if server_cli.exit?
11
11
  if RuboCop::Server.running?
12
12
  exit_status = RuboCop::Server::ClientCommand::Exec.new.run
13
13
  else
14
- require 'rubocop'
15
14
  require 'benchmark'
15
+ require 'rubocop'
16
16
 
17
17
  cli = RuboCop::CLI.new
18
18
 
@@ -31,6 +31,7 @@ module RuboCop
31
31
 
32
32
  def initialize(processed_source)
33
33
  @processed_source = processed_source
34
+ @no_directives = !processed_source.raw_source.include?('rubocop')
34
35
  end
35
36
 
36
37
  def cop_enabled_at_line?(cop, line_number)
@@ -74,6 +75,8 @@ module RuboCop
74
75
  end
75
76
 
76
77
  def analyze # rubocop:todo Metrics/AbcSize
78
+ return {} if @no_directives
79
+
77
80
  analyses = Hash.new { |hash, key| hash[key] = CopAnalysis.new([], nil) }
78
81
  inject_disabled_cops_directives(analyses)
79
82
 
@@ -146,6 +149,8 @@ module RuboCop
146
149
  end
147
150
 
148
151
  def each_directive
152
+ return if @no_directives
153
+
149
154
  processed_source.comments.each do |comment|
150
155
  directive = DirectiveComment.new(comment)
151
156
  yield directive if directive.cop_names
@@ -24,10 +24,11 @@ module RuboCop
24
24
  def initialize(hash = {}, loaded_path = nil)
25
25
  @loaded_path = loaded_path
26
26
  @for_cop = Hash.new do |h, cop|
27
- qualified_cop_name = Cop::Registry.qualified_cop_name(cop, loaded_path)
27
+ cop_name = cop.respond_to?(:cop_name) ? cop.cop_name : cop
28
+ qualified_cop_name = Cop::Registry.qualified_cop_name(cop_name, loaded_path)
28
29
  cop_options = self[qualified_cop_name].dup || {}
29
30
  cop_options['Enabled'] = enable_cop?(qualified_cop_name, cop_options)
30
- h[cop] = cop_options
31
+ h[cop] = h[cop_name] = cop_options
31
32
  end
32
33
  @hash = hash
33
34
  @validator = ConfigValidator.new(self)
@@ -116,7 +117,7 @@ module RuboCop
116
117
  # Note: the 'Enabled' attribute is calculated according to the department's
117
118
  # and 'AllCops' configuration; other attributes are not inherited.
118
119
  def for_cop(cop)
119
- @for_cop[cop.respond_to?(:cop_name) ? cop.cop_name : cop]
120
+ @for_cop[cop]
120
121
  end
121
122
 
122
123
  # @return [Config] for the given cop merged with that of its department (if any)
@@ -215,7 +216,7 @@ module RuboCop
215
216
  # directory since that wouldn't work.
216
217
  def base_dir_for_path_parameters
217
218
  @base_dir_for_path_parameters ||=
218
- if File.basename(loaded_path).start_with?('.rubocop') &&
219
+ if loaded_path && File.basename(loaded_path).start_with?('.rubocop') &&
219
220
  loaded_path != File.join(Dir.home, ConfigLoader::DOTFILE)
220
221
  File.expand_path(File.dirname(loaded_path))
221
222
  else
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'erb'
4
- require 'yaml'
5
4
  require 'pathname'
5
+ require 'yaml'
6
6
  require_relative 'config_finder'
7
7
 
8
8
  module RuboCop
@@ -42,18 +42,18 @@ module RuboCop
42
42
 
43
43
  hash = load_yaml_configuration(path)
44
44
 
45
- # Resolve requires first in case they define additional cops
46
45
  loaded_features = resolver.resolve_requires(path, hash)
47
46
  add_loaded_features(loaded_features)
48
47
 
49
- add_missing_namespaces(path, hash)
50
-
51
48
  resolver.override_department_setting_for_cops({}, hash)
52
49
  resolver.resolve_inheritance_from_gems(hash)
53
50
  resolver.resolve_inheritance(path, hash, file, debug?)
54
-
55
51
  hash.delete('inherit_from')
56
52
 
53
+ # Adding missing namespaces only after resolving requires & inheritance,
54
+ # since both can introduce new cops that need to be considered here.
55
+ add_missing_namespaces(path, hash)
56
+
57
57
  Config.create(hash, path, check: check)
58
58
  end
59
59
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'yaml'
4
3
  require 'pathname'
4
+ require 'yaml'
5
5
 
6
6
  module RuboCop
7
7
  # A help class for ConfigLoader that handles configuration resolution.
@@ -412,15 +412,8 @@ module RuboCop
412
412
  patterns = cop_config[parameter]
413
413
  return default_result unless patterns
414
414
 
415
- path = nil
416
- patterns.any? do |pattern|
417
- # Try to match the absolute path, as Exclude properties are absolute.
418
- next true if match_path?(pattern, file)
419
-
420
- # Try with relative path.
421
- path ||= config.path_relative_to_config(file)
422
- match_path?(pattern, path)
423
- end
415
+ patterns = OptimizedPatterns.from(patterns)
416
+ patterns.match?(config.path_relative_to_config(file)) || patterns.match?(file)
424
417
  end
425
418
 
426
419
  def enabled_line?(line_number)
@@ -28,7 +28,10 @@ module RuboCop
28
28
  # put the comment.
29
29
  return if new_line_needed_before_closing_brace?(node)
30
30
 
31
- correct_next_line_brace(corrector)
31
+ end_range = last_element_range_with_trailing_comma(node).end
32
+
33
+ correct_next_line_brace(corrector, end_range)
34
+ correct_heredoc_argument_method_chain(corrector, end_range)
32
35
  end
33
36
  end
34
37
 
@@ -40,13 +43,19 @@ module RuboCop
40
43
  corrector.insert_before(node.loc.end, "\n")
41
44
  end
42
45
 
43
- def correct_next_line_brace(corrector)
46
+ def correct_next_line_brace(corrector, end_range)
44
47
  corrector.remove(range_with_surrounding_space(node.loc.end, side: :left))
48
+ corrector.insert_before(end_range, content_if_comment_present(corrector, node))
49
+ end
45
50
 
46
- corrector.insert_before(
47
- last_element_range_with_trailing_comma(node).end,
48
- content_if_comment_present(corrector, node)
49
- )
51
+ def correct_heredoc_argument_method_chain(corrector, end_range)
52
+ return unless (parent = node.parent)
53
+ return unless use_heredoc_argument_method_chain?(parent)
54
+
55
+ chained_method = range_between(parent.loc.dot.begin_pos, parent.loc.expression.end_pos)
56
+
57
+ corrector.remove(chained_method)
58
+ corrector.insert_after(end_range, chained_method.source)
50
59
  end
51
60
 
52
61
  def content_if_comment_present(corrector, node)
@@ -61,6 +70,13 @@ module RuboCop
61
70
  end
62
71
  end
63
72
 
73
+ def use_heredoc_argument_method_chain?(parent)
74
+ return false unless node.respond_to?(:first_argument)
75
+ return false unless (first_argument = node.first_argument)
76
+
77
+ parent.call_type? && first_argument.str_type? && first_argument.heredoc?
78
+ end
79
+
64
80
  def select_content_to_be_inserted_after_last_element(corrector, node)
65
81
  range = range_between(
66
82
  node.loc.end.begin_pos,
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module InternalAffairs
6
+ # Enforces the use of `node.lambda_or_proc?` instead of `node.lambda? || node.proc?`.
7
+ #
8
+ # @example
9
+ # # bad
10
+ # node.lambda? || node.proc?
11
+ # node.proc? || node.lambda?
12
+ #
13
+ # # good
14
+ # node.lambda_or_proc?
15
+ #
16
+ class LambdaOrProc < Base
17
+ extend AutoCorrector
18
+
19
+ MSG = 'Use `%<prefer>s`.'
20
+
21
+ # @!method lambda_or_proc(node)
22
+ def_node_matcher :lambda_or_proc, <<~PATTERN
23
+ {
24
+ (or $(send _node :lambda?) $(send _node :proc?))
25
+ (or $(send _node :proc?) $(send _node :lambda?))
26
+ (or
27
+ (or _ $(send _node :lambda?)) $(send _node :proc?))
28
+ (or
29
+ (or _ $(send _node :proc?)) $(send _node :lambda?))
30
+ }
31
+ PATTERN
32
+
33
+ def on_or(node)
34
+ return unless (lhs, rhs = lambda_or_proc(node))
35
+
36
+ offense = lhs.receiver.source_range.join(rhs.source_range.end)
37
+ prefer = "#{lhs.receiver.source}.lambda_or_proc?"
38
+
39
+ add_offense(offense, message: format(MSG, prefer: prefer)) do |corrector|
40
+ corrector.replace(offense, prefer)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -6,6 +6,7 @@ require_relative 'internal_affairs/empty_line_between_expect_offense_and_correct
6
6
  require_relative 'internal_affairs/example_description'
7
7
  require_relative 'internal_affairs/example_heredoc_delimiter'
8
8
  require_relative 'internal_affairs/inherit_deprecated_cop_class'
9
+ require_relative 'internal_affairs/lambda_or_proc'
9
10
  require_relative 'internal_affairs/location_line_equality_comparison'
10
11
  require_relative 'internal_affairs/method_name_end_with'
11
12
  require_relative 'internal_affairs/method_name_equal'
@@ -63,7 +63,7 @@ module RuboCop
63
63
  return unless node.arguments?
64
64
 
65
65
  return unless ambiguous_block_association?(node)
66
- return if node.parenthesized? || node.last_argument.lambda? || node.last_argument.proc? ||
66
+ return if node.parenthesized? || node.last_argument.lambda_or_proc? ||
67
67
  allowed_method_pattern?(node)
68
68
 
69
69
  message = message(node)
@@ -11,6 +11,10 @@ module RuboCop
11
11
  # an assignment to indicate "I know I'm using an assignment
12
12
  # as a condition. It's not a mistake."
13
13
  #
14
+ # @safety
15
+ # This cop's autocorrection is unsafe because it assumes that
16
+ # the author meant to use an assignment result as a condition.
17
+ #
14
18
  # @example
15
19
  # # bad
16
20
  # if some_var = true
@@ -35,6 +39,8 @@ module RuboCop
35
39
  # end
36
40
  #
37
41
  class AssignmentInCondition < Base
42
+ extend AutoCorrector
43
+
38
44
  include SafeAssignment
39
45
 
40
46
  MSG_WITH_SAFE_ASSIGNMENT_ALLOWED =
@@ -53,7 +59,11 @@ module RuboCop
53
59
  next :skip_children if skip_children?(asgn_node)
54
60
  next if allowed_construct?(asgn_node)
55
61
 
56
- add_offense(asgn_node.loc.operator)
62
+ add_offense(asgn_node.loc.operator) do |corrector|
63
+ next unless safe_assignment_allowed?
64
+
65
+ corrector.wrap(asgn_node, '(', ')')
66
+ end
57
67
  end
58
68
  end
59
69
  alias on_while on_if
@@ -14,7 +14,8 @@ module RuboCop
14
14
  # Alternative: 'alternative_value'
15
15
  # DeprecatedVersion: 'deprecated_version'
16
16
  #
17
- # By default, `NIL`, `TRUE`, `FALSE` and `Random::DEFAULT` are configured.
17
+ # By default, `NIL`, `TRUE`, `FALSE`, `Net::HTTPServerException, `Random::DEFAULT`,
18
+ # `Struct::Group`, and `Struct::Passwd` are configured.
18
19
  #
19
20
  # @example
20
21
  #
@@ -22,13 +23,19 @@ module RuboCop
22
23
  # NIL
23
24
  # TRUE
24
25
  # FALSE
26
+ # Net::HTTPServerException
25
27
  # Random::DEFAULT # Return value of Ruby 2 is `Random` instance, Ruby 3.0 is `Random` class.
28
+ # Struct::Group
29
+ # Struct::Passwd
26
30
  #
27
31
  # # good
28
32
  # nil
29
33
  # true
30
34
  # false
35
+ # Net::HTTPClientException
31
36
  # Random.new # `::DEFAULT` has been deprecated in Ruby 3, `.new` is compatible with Ruby 2.
37
+ # Etc::Group
38
+ # Etc::Passwd
32
39
  #
33
40
  class DeprecatedConstants < Base
34
41
  extend AutoCorrector
@@ -65,7 +65,7 @@ module RuboCop
65
65
 
66
66
  def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler
67
67
  return if node.body
68
- return if allow_empty_lambdas? && lambda_or_proc?(node)
68
+ return if allow_empty_lambdas? && node.lambda_or_proc?
69
69
  return if cop_config['AllowComments'] && allow_comment?(node)
70
70
 
71
71
  add_offense(node)
@@ -88,10 +88,6 @@ module RuboCop
88
88
  regexp_pattern = "# rubocop : (disable|todo) ([^,],)* (all|#{cop_name})"
89
89
  Regexp.new(regexp_pattern.gsub(' ', '\s*')).match?(comment)
90
90
  end
91
-
92
- def lambda_or_proc?(node)
93
- node.lambda? || node.proc?
94
- end
95
91
  end
96
92
  end
97
93
  end
@@ -68,7 +68,7 @@ module RuboCop
68
68
  MSG = 'Avoid `%<keyword>s` branches without a body.'
69
69
 
70
70
  def on_if(node)
71
- return if node.body
71
+ return if node.body || same_line?(node.loc.begin, node.loc.end)
72
72
  return if cop_config['AllowComments'] && contains_comments?(node)
73
73
 
74
74
  add_offense(node, message: format(MSG, keyword: node.keyword)) do |corrector|
@@ -6,9 +6,10 @@ module RuboCop
6
6
  # Checks for interpolation in a single quoted string.
7
7
  #
8
8
  # @safety
9
- # This cop is generally safe, but is marked as unsafe because
10
- # it is possible to actually intentionally have text inside
11
- # `#{...}` in a single quoted string.
9
+ # This cop's autocorrection is unsafe because although it always replaces single quotes as
10
+ # if it were miswritten double quotes, it is not always the case. For example,
11
+ # `'#{foo} bar'` would be replaced by `"#{foo} bar"`, so the replaced code would evaluate
12
+ # the expression `foo`.
12
13
  #
13
14
  # @example
14
15
  #
@@ -40,11 +40,16 @@ module RuboCop
40
40
  unless node.arguments.one? && first_argument_starts_with_left_parenthesis?(node)
41
41
  return true
42
42
  end
43
+ return true if first_argument_block_type?(node.first_argument)
43
44
 
44
45
  node.operator_method? || node.setter_method? || chained_calls?(node) ||
45
46
  valid_first_argument?(node.first_argument)
46
47
  end
47
48
 
49
+ def first_argument_block_type?(first_arg)
50
+ first_arg.block_type? || first_arg.numblock_type?
51
+ end
52
+
48
53
  def valid_first_argument?(first_arg)
49
54
  first_arg.operator_keyword? || first_arg.hash_type? || ternary_expression?(first_arg)
50
55
  end
@@ -131,18 +131,28 @@ module RuboCop
131
131
  def each_already_disabled(cop, line_ranges)
132
132
  line_ranges.each_cons(2) do |previous_range, range|
133
133
  next if ignore_offense?(range)
134
- next unless followed_ranges?(previous_range, range)
135
-
136
134
  # If a cop is disabled in a range that begins on the same line as
137
135
  # the end of the previous range, it means that the cop was
138
136
  # already disabled by an earlier comment. So it's redundant
139
137
  # whether there are offenses or not.
138
+ next unless followed_ranges?(previous_range, range)
139
+
140
140
  comment = processed_source.comment_at_line(range.begin)
141
141
 
142
+ next unless comment
142
143
  # Comments disabling all cops don't count since it's reasonable
143
144
  # to disable a few select cops first and then all cops further
144
145
  # down in the code.
145
- yield comment, cop if comment && !all_disabled?(comment)
146
+ next if all_disabled?(comment)
147
+
148
+ redundant =
149
+ if department_disabled?(cop, comment)
150
+ find_redundant_department(cop, range)
151
+ else
152
+ cop
153
+ end
154
+
155
+ yield comment, redundant
146
156
  end
147
157
  end
148
158
 
@@ -62,15 +62,16 @@ module RuboCop
62
62
  # @param [RuboCop::AST::SendNode] send_node
63
63
  # @return [String]
64
64
  def add_safe_navigation_operator(offense_range:, send_node:)
65
- source = \
66
- if send_node.method?(:[]) || send_node.method?(:[]=)
65
+ source =
66
+ if (brackets = find_brackets(send_node))
67
67
  format(
68
- '%<method_name>s(%<arguments>s)',
69
- arguments: send_node.arguments.map(&:source).join(', '),
70
- method_name: send_node.method_name
68
+ '%<method_name>s(%<arguments>s)%<method_chain>s',
69
+ arguments: brackets.arguments.map(&:source).join(', '),
70
+ method_name: brackets.method_name,
71
+ method_chain: brackets.source_range.end.join(send_node.source_range.end).source
71
72
  )
72
73
  else
73
- offense_range.source.dup
74
+ offense_range.source
74
75
  end
75
76
  source.prepend('.') unless source.start_with?('.')
76
77
  source.prepend('&')
@@ -94,6 +95,14 @@ module RuboCop
94
95
  chain = chain.parent if chain.send_type? && chain.parent&.call_type?
95
96
  chain
96
97
  end
98
+
99
+ def find_brackets(send_node)
100
+ return send_node if send_node.method?(:[]) || send_node.method?(:[]=)
101
+
102
+ send_node.descendants.detect do |node|
103
+ node.send_type? && (node.method?(:[]) || node.method?(:[]=))
104
+ end
105
+ end
97
106
  end
98
107
  end
99
108
  end