rubocop 1.66.1 → 1.68.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 (123) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +55 -6
  4. data/config/internal_affairs.yml +11 -0
  5. data/lib/rubocop/cached_data.rb +12 -4
  6. data/lib/rubocop/cli/command/auto_generate_config.rb +6 -7
  7. data/lib/rubocop/cli/command/execute_runner.rb +1 -1
  8. data/lib/rubocop/cli/command/lsp.rb +2 -2
  9. data/lib/rubocop/cli/command/version.rb +2 -2
  10. data/lib/rubocop/config_loader_resolver.rb +3 -3
  11. data/lib/rubocop/config_validator.rb +2 -1
  12. data/lib/rubocop/cop/autocorrect_logic.rb +22 -2
  13. data/lib/rubocop/cop/base.rb +6 -2
  14. data/lib/rubocop/cop/bundler/gem_version.rb +1 -0
  15. data/lib/rubocop/cop/cop.rb +8 -0
  16. data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -12
  17. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +1 -1
  18. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +10 -0
  19. data/lib/rubocop/cop/internal_affairs/cop_description.rb +0 -4
  20. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +6 -21
  21. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +8 -1
  22. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +0 -5
  23. data/lib/rubocop/cop/internal_affairs.rb +16 -0
  24. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +5 -1
  25. data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
  26. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -1
  27. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +8 -0
  28. data/lib/rubocop/cop/layout/indentation_width.rb +4 -5
  29. data/lib/rubocop/cop/layout/leading_comment_space.rb +56 -1
  30. data/lib/rubocop/cop/layout/space_before_brackets.rb +5 -5
  31. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +4 -0
  32. data/lib/rubocop/cop/lint/ambiguous_range.rb +4 -1
  33. data/lib/rubocop/cop/lint/big_decimal_new.rb +4 -7
  34. data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -1
  35. data/lib/rubocop/cop/lint/duplicate_branch.rb +39 -4
  36. data/lib/rubocop/cop/lint/duplicate_set_element.rb +74 -0
  37. data/lib/rubocop/cop/lint/ensure_return.rb +0 -3
  38. data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -1
  39. data/lib/rubocop/cop/lint/float_comparison.rb +1 -1
  40. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +10 -4
  41. data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +5 -14
  42. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +25 -2
  43. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +7 -0
  44. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +5 -6
  45. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +1 -1
  46. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +9 -0
  47. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +107 -41
  48. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  49. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +88 -0
  50. data/lib/rubocop/cop/lint/uri_regexp.rb +25 -7
  51. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +4 -1
  52. data/lib/rubocop/cop/mixin/check_line_breakable.rb +10 -0
  53. data/lib/rubocop/cop/mixin/endless_method_rewriter.rb +24 -0
  54. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +3 -1
  55. data/lib/rubocop/cop/mixin/percent_array.rb +1 -1
  56. data/lib/rubocop/cop/mixin/statement_modifier.rb +3 -2
  57. data/lib/rubocop/cop/naming/block_forwarding.rb +1 -1
  58. data/lib/rubocop/cop/naming/inclusive_language.rb +12 -3
  59. data/lib/rubocop/cop/naming/predicate_name.rb +1 -1
  60. data/lib/rubocop/cop/offense.rb +4 -5
  61. data/lib/rubocop/cop/style/access_modifier_declarations.rb +12 -2
  62. data/lib/rubocop/cop/style/accessor_grouping.rb +10 -2
  63. data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +79 -0
  64. data/lib/rubocop/cop/style/arguments_forwarding.rb +46 -6
  65. data/lib/rubocop/cop/style/bitwise_predicate.rb +100 -0
  66. data/lib/rubocop/cop/style/block_delimiters.rb +31 -3
  67. data/lib/rubocop/cop/style/collection_compact.rb +10 -10
  68. data/lib/rubocop/cop/style/combinable_defined.rb +115 -0
  69. data/lib/rubocop/cop/style/combinable_loops.rb +7 -0
  70. data/lib/rubocop/cop/style/commented_keyword.rb +7 -1
  71. data/lib/rubocop/cop/style/conditional_assignment.rb +1 -1
  72. data/lib/rubocop/cop/style/data_inheritance.rb +1 -1
  73. data/lib/rubocop/cop/style/endless_method.rb +1 -14
  74. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  75. data/lib/rubocop/cop/style/guard_clause.rb +15 -2
  76. data/lib/rubocop/cop/style/hash_each_methods.rb +6 -0
  77. data/lib/rubocop/cop/style/hash_syntax.rb +2 -2
  78. data/lib/rubocop/cop/style/if_inside_else.rb +1 -1
  79. data/lib/rubocop/cop/style/if_with_semicolon.rb +7 -3
  80. data/lib/rubocop/cop/style/keyword_arguments_merging.rb +67 -0
  81. data/lib/rubocop/cop/style/lambda.rb +1 -1
  82. data/lib/rubocop/cop/style/map_into_array.rb +59 -8
  83. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +12 -7
  84. data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
  85. data/lib/rubocop/cop/style/multiple_comparison.rb +28 -39
  86. data/lib/rubocop/cop/style/nested_modifier.rb +1 -1
  87. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
  88. data/lib/rubocop/cop/style/one_line_conditional.rb +4 -0
  89. data/lib/rubocop/cop/style/operator_method_call.rb +25 -6
  90. data/lib/rubocop/cop/style/redundant_begin.rb +4 -0
  91. data/lib/rubocop/cop/style/redundant_condition.rb +1 -1
  92. data/lib/rubocop/cop/style/redundant_line_continuation.rb +23 -5
  93. data/lib/rubocop/cop/style/redundant_parentheses.rb +9 -11
  94. data/lib/rubocop/cop/style/require_order.rb +1 -1
  95. data/lib/rubocop/cop/style/rescue_modifier.rb +13 -1
  96. data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +54 -12
  97. data/lib/rubocop/cop/style/safe_navigation.rb +104 -50
  98. data/lib/rubocop/cop/style/safe_navigation_chain_length.rb +52 -0
  99. data/lib/rubocop/cop/style/select_by_regexp.rb +9 -6
  100. data/lib/rubocop/cop/style/semicolon.rb +1 -1
  101. data/lib/rubocop/cop/style/struct_inheritance.rb +1 -1
  102. data/lib/rubocop/cop/style/ternary_parentheses.rb +26 -5
  103. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  104. data/lib/rubocop/cop/team.rb +8 -1
  105. data/lib/rubocop/cop/util.rb +1 -1
  106. data/lib/rubocop/cop/variable_force/assignment.rb +18 -3
  107. data/lib/rubocop/cop/variable_force/branch.rb +1 -1
  108. data/lib/rubocop/cop/variable_force/variable.rb +5 -1
  109. data/lib/rubocop/cop/variable_force/variable_table.rb +2 -2
  110. data/lib/rubocop/cops_documentation_generator.rb +81 -40
  111. data/lib/rubocop/file_finder.rb +9 -4
  112. data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -1
  113. data/lib/rubocop/lsp/runtime.rb +2 -0
  114. data/lib/rubocop/lsp/server.rb +0 -1
  115. data/lib/rubocop/rspec/expect_offense.rb +1 -0
  116. data/lib/rubocop/runner.rb +17 -6
  117. data/lib/rubocop/server/cache.rb +6 -1
  118. data/lib/rubocop/server/core.rb +1 -0
  119. data/lib/rubocop/target_ruby.rb +13 -13
  120. data/lib/rubocop/version.rb +28 -7
  121. data/lib/rubocop/yaml_duplication_checker.rb +20 -27
  122. data/lib/rubocop.rb +10 -0
  123. metadata +13 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8a10568527197e80492a28c5b524fa524dbce965513daff4f47e260e03b49d98
4
- data.tar.gz: 8ea447437cbd36aa805b3941cf51b07eecc9dc538ed6a4584f09a1335e21cb48
3
+ metadata.gz: 7f0623068e9eac24fe4b1f5c7e4987d3a8adc7a2ec7f5f65c6cfb9d0ad9d1278
4
+ data.tar.gz: 9abb03dde6881cb7c11a21ee947c33a7d8874b9893f81e81cd7617f52f1bb714
5
5
  SHA512:
6
- metadata.gz: 1f292c70ffac1cb186e5be899582c4849a29866722c87ab92a60a723dd16fe86fdf12073c8a7190bba197d246eae3b25ba3cdc6b586b28061cef39ac22b3b438
7
- data.tar.gz: 2dbfc28779854fae0d28fd266ba269b92cb0e3b5c26200aa250df02ff9810804b7b1fcc289a43bac1913dc04c79f788487f9351444f7242cbcdad6854a821d69
6
+ metadata.gz: 3392244d7137845de4f7c9867695350666750b349879ac4796590d090b0b1a182f21fb9c96f6d284bfd9eaf21a7594f8b7de2d59da62458400a709430bb6f7a2
7
+ data.tar.gz: e2a5a3dd61755c091a91ea99828846fa875b3b7ca8ffaea67425245755e147159691c587a7a80089a428480b7ad07fef8da1be7dc209ac0a60bb46cff3a37d0f
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.66', require: false
55
+ gem 'rubocop', '~> 1.68', 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
@@ -861,6 +861,7 @@ Layout/FirstMethodArgumentLineBreak:
861
861
  Enabled: false
862
862
  VersionAdded: '0.49'
863
863
  AllowMultilineFinalElement: false
864
+ AllowedMethods: []
864
865
 
865
866
  Layout/FirstMethodParameterLineBreak:
866
867
  Description: >-
@@ -1036,6 +1037,8 @@ Layout/LeadingCommentSpace:
1036
1037
  VersionChanged: '0.73'
1037
1038
  AllowDoxygenCommentStyle: false
1038
1039
  AllowGemfileRubyComment: false
1040
+ AllowRBSInlineAnnotation: false
1041
+ AllowSteepAnnotation: false
1039
1042
 
1040
1043
  Layout/LeadingEmptyLines:
1041
1044
  Description: Check for unnecessary blank lines at the beginning of a file.
@@ -1783,6 +1786,7 @@ Lint/DuplicateBranch:
1783
1786
  VersionChanged: '1.7'
1784
1787
  IgnoreLiteralBranches: false
1785
1788
  IgnoreConstantBranches: false
1789
+ IgnoreDuplicateElseBranch: false
1786
1790
 
1787
1791
  Lint/DuplicateCaseCondition:
1788
1792
  Description: 'Do not repeat values in case conditionals.'
@@ -1832,6 +1836,11 @@ Lint/DuplicateRescueException:
1832
1836
  Enabled: true
1833
1837
  VersionAdded: '0.89'
1834
1838
 
1839
+ Lint/DuplicateSetElement:
1840
+ Description: 'Checks for duplicate elements in Set.'
1841
+ Enabled: pending
1842
+ VersionAdded: '1.67'
1843
+
1835
1844
  Lint/EachWithObjectArgument:
1836
1845
  Description: 'Check for immutable argument given to each_with_object.'
1837
1846
  Enabled: true
@@ -2327,9 +2336,9 @@ Lint/SafeNavigationChain:
2327
2336
 
2328
2337
  Lint/SafeNavigationConsistency:
2329
2338
  Description: >-
2330
- Check to make sure that if safe navigation is used for a method
2331
- call in an `&&` or `||` condition that safe navigation is used
2332
- for all method calls on that same object.
2339
+ Check to make sure that if safe navigation is used in an `&&` or `||` condition,
2340
+ consistent and appropriate safe navigation, without excess or deficiency,
2341
+ is used for all method calls on the same object.
2333
2342
  Enabled: true
2334
2343
  VersionAdded: '0.55'
2335
2344
  VersionChanged: '0.77'
@@ -2448,6 +2457,11 @@ Lint/UnderscorePrefixedVariableName:
2448
2457
  VersionAdded: '0.21'
2449
2458
  AllowKeywordBlockArguments: false
2450
2459
 
2460
+ Lint/UnescapedBracketInRegexp:
2461
+ Description: 'Checks for unescaped literal `]` in Regexp.'
2462
+ Enabled: pending
2463
+ VersionAdded: '1.68'
2464
+
2451
2465
  Lint/UnexpectedBlockArity:
2452
2466
  Description: 'Looks for blocks that have fewer arguments that the calling method expects.'
2453
2467
  Enabled: pending
@@ -3136,6 +3150,12 @@ Style/Alias:
3136
3150
  - prefer_alias
3137
3151
  - prefer_alias_method
3138
3152
 
3153
+ Style/AmbiguousEndlessMethodDefinition:
3154
+ Description: 'Checks for endless methods inside operators of lower precedence.'
3155
+ StyleGuide: '#ambiguous-endless-method-defintions'
3156
+ Enabled: pending
3157
+ VersionAdded: '1.68'
3158
+
3139
3159
  Style/AndOr:
3140
3160
  Description: 'Use &&/|| instead of and/or.'
3141
3161
  StyleGuide: '#no-and-or-or'
@@ -3243,6 +3263,13 @@ Style/BisectedAttrAccessor:
3243
3263
  Enabled: true
3244
3264
  VersionAdded: '0.87'
3245
3265
 
3266
+ Style/BitwisePredicate:
3267
+ Description: 'Prefer bitwise predicate methods over direct comparison operations.'
3268
+ StyleGuide: '#bitwise-predicate-methods'
3269
+ Enabled: pending
3270
+ Safe: false
3271
+ VersionAdded: '1.68'
3272
+
3246
3273
  Style/BlockComments:
3247
3274
  Description: 'Do not use block comments.'
3248
3275
  StyleGuide: '#no-block-comments'
@@ -3526,6 +3553,11 @@ Style/ColonMethodDefinition:
3526
3553
  Enabled: true
3527
3554
  VersionAdded: '0.52'
3528
3555
 
3556
+ Style/CombinableDefined:
3557
+ Description: 'Checks successive `defined?` calls that can be combined into a single call.'
3558
+ Enabled: pending
3559
+ VersionAdded: '1.68'
3560
+
3529
3561
  Style/CombinableLoops:
3530
3562
  Description: >-
3531
3563
  Checks for places where multiple consecutive loops over the same data
@@ -4069,7 +4101,7 @@ Style/HashSyntax:
4069
4101
  StyleGuide: '#hash-literals'
4070
4102
  Enabled: true
4071
4103
  VersionAdded: '0.9'
4072
- VersionChanged: '1.24'
4104
+ VersionChanged: '1.67'
4073
4105
  EnforcedStyle: ruby19
4074
4106
  SupportedStyles:
4075
4107
  # checks for 1.9 syntax (e.g. {a: 1}) for all symbol keys
@@ -4081,7 +4113,7 @@ Style/HashSyntax:
4081
4113
  # enforces both ruby19 and no_mixed_keys styles
4082
4114
  - ruby19_no_mixed_keys
4083
4115
  # Force hashes that have a hash value omission
4084
- EnforcedShorthandSyntax: always
4116
+ EnforcedShorthandSyntax: either
4085
4117
  SupportedShorthandSyntax:
4086
4118
  # forces use of the 3.1 syntax (e.g. {foo:}) when the hash key and value are the same.
4087
4119
  - always
@@ -4249,6 +4281,14 @@ Style/IpAddresses:
4249
4281
  - '**/gems.rb'
4250
4282
  - '**/*.gemspec'
4251
4283
 
4284
+ Style/KeywordArgumentsMerging:
4285
+ Description: >-
4286
+ When passing an existing hash as keyword arguments, provide additional arguments
4287
+ directly rather than using `merge`.
4288
+ StyleGuide: '#merging-keyword-arguments'
4289
+ Enabled: pending
4290
+ VersionAdded: '1.68'
4291
+
4252
4292
  Style/KeywordParametersOrder:
4253
4293
  Description: 'Enforces that optional keyword parameters are placed at the end of the parameters list.'
4254
4294
  StyleGuide: '#keyword-parameters-order'
@@ -4318,6 +4358,7 @@ Style/MapIntoArray:
4318
4358
  StyleGuide: '#functional-code'
4319
4359
  Enabled: pending
4320
4360
  VersionAdded: '1.63'
4361
+ VersionChanged: '1.67'
4321
4362
  Safe: false
4322
4363
 
4323
4364
  Style/MapToHash:
@@ -5208,6 +5249,7 @@ Style/ReturnNilInPredicateMethodDefinition:
5208
5249
  AllowedMethods: []
5209
5250
  AllowedPatterns: []
5210
5251
  VersionAdded: '1.53'
5252
+ VersionChanged: '1.67'
5211
5253
 
5212
5254
  Style/SafeNavigation:
5213
5255
  Description: >-
@@ -5218,7 +5260,7 @@ Style/SafeNavigation:
5218
5260
  be `nil` or truthy, but never `false`.
5219
5261
  Enabled: true
5220
5262
  VersionAdded: '0.43'
5221
- VersionChanged: '1.27'
5263
+ VersionChanged: '1.67'
5222
5264
  # Safe navigation may cause a statement to start returning `nil` in addition
5223
5265
  # to whatever it used to return.
5224
5266
  ConvertCodeThatCanStartToReturnNil: false
@@ -5232,6 +5274,13 @@ Style/SafeNavigation:
5232
5274
  # Maximum length of method chains for register an offense.
5233
5275
  MaxChainLength: 2
5234
5276
 
5277
+ Style/SafeNavigationChainLength:
5278
+ Description: 'Enforces safe navigation chains length to not exceed the configured maximum.'
5279
+ StyleGuide: '#safe-navigation'
5280
+ Enabled: pending
5281
+ VersionAdded: '1.68'
5282
+ Max: 2
5283
+
5235
5284
  Style/Sample:
5236
5285
  Description: >-
5237
5286
  Use `sample` instead of `shuffle.first`,
@@ -0,0 +1,11 @@
1
+ # Configuration for InternalAffairs cops. This file will be
2
+ # automatically loaded when `rubocop/cop/internal_affairs` is required.
3
+ # Only do this when developing custom cops or a RuboCop extension.
4
+
5
+ InternalAffairs/CopDescription:
6
+ Include:
7
+ - 'lib/rubocop/cop/**/*.rb'
8
+
9
+ InternalAffairs/UselessMessageAssertion:
10
+ Include:
11
+ - '**/*_spec.rb'
@@ -45,15 +45,13 @@ module RuboCop
45
45
 
46
46
  # Restore an offense object loaded from a JSON file.
47
47
  def deserialize_offenses(offenses)
48
- source_buffer = Parser::Source::Buffer.new(@filename)
49
- source_buffer.source = File.read(@filename, encoding: Encoding::UTF_8)
50
48
  offenses.map! do |o|
51
- location = location_from_source_buffer(o, source_buffer)
49
+ location = location_from_source_buffer(o)
52
50
  Cop::Offense.new(o['severity'], location, o['message'], o['cop_name'], o['status'].to_sym)
53
51
  end
54
52
  end
55
53
 
56
- def location_from_source_buffer(offense, source_buffer)
54
+ def location_from_source_buffer(offense)
57
55
  begin_pos = offense['location']['begin_pos']
58
56
  end_pos = offense['location']['end_pos']
59
57
  if begin_pos.zero? && end_pos.zero?
@@ -62,5 +60,15 @@ module RuboCop
62
60
  Parser::Source::Range.new(source_buffer, begin_pos, end_pos)
63
61
  end
64
62
  end
63
+
64
+ # Delay creation until needed. Some type of offenses will have no buffer associated with them
65
+ # and be global only. For these, trying to create the buffer will likely fail, for example
66
+ # because of unknown encoding comments.
67
+ def source_buffer
68
+ @source_buffer ||= begin
69
+ source = File.read(@filename, encoding: Encoding::UTF_8)
70
+ Parser::Source::Buffer.new(@filename, source: source)
71
+ end
72
+ end
65
73
  end
66
74
  end
@@ -151,16 +151,15 @@ module RuboCop
151
151
  end
152
152
 
153
153
  def relative_path_to_todo_from_options_config
154
- return AUTO_GENERATED_FILE if !@options[:config] || options_config_in_root?
154
+ return AUTO_GENERATED_FILE unless @options[:config]
155
155
 
156
- base = Pathname.new('.')
157
- config_dir = Pathname.new(File.dirname(@options[:config]))
156
+ base = Pathname.new(Dir.pwd)
157
+ config_dir = Pathname.new(@options[:config]).realpath.dirname
158
158
 
159
- "#{base.relative_path_from(config_dir)}/#{AUTO_GENERATED_FILE}"
160
- end
159
+ # Don't have the path start with `/`
160
+ return AUTO_GENERATED_FILE if config_dir == base
161
161
 
162
- def options_config_in_root?
163
- File.dirname(@options[:config]) == '.'
162
+ "#{base.relative_path_from(config_dir)}/#{AUTO_GENERATED_FILE}"
164
163
  end
165
164
  end
166
165
  end
@@ -78,7 +78,7 @@ module RuboCop
78
78
  Please, report your problems to RuboCop's issue tracker.
79
79
  #{bug_tracker_uri}
80
80
  Mention the following information in the issue report:
81
- #{RuboCop::Version.version(debug: true)}
81
+ #{RuboCop::Version.verbose}
82
82
  WARNING
83
83
  end
84
84
 
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../../lsp/server'
4
-
5
3
  module RuboCop
6
4
  class CLI
7
5
  module Command
@@ -11,6 +9,8 @@ module RuboCop
11
9
  self.command_name = :lsp
12
10
 
13
11
  def run
12
+ # Load on demand, `languge-server-protocol` is heavy to require.
13
+ require_relative '../../lsp/server'
14
14
  RuboCop::LSP::Server.new(@config_store).start
15
15
  end
16
16
  end
@@ -9,8 +9,8 @@ module RuboCop
9
9
  self.command_name = :version
10
10
 
11
11
  def run
12
- puts RuboCop::Version.version(debug: false) if @options[:version]
13
- puts RuboCop::Version.version(debug: true, env: env) if @options[:verbose_version]
12
+ puts RuboCop::Version::STRING if @options[:version]
13
+ puts RuboCop::Version.verbose(env: env) if @options[:verbose_version]
14
14
  end
15
15
  end
16
16
  end
@@ -166,7 +166,7 @@ module RuboCop
166
166
  return unless duplicate_setting?(base_hash, derived_hash, key, opts[:inherited_file])
167
167
 
168
168
  inherit_mode = opts[:inherit_mode]['merge'] || opts[:inherit_mode]['override']
169
- return if base_hash[key].is_a?(Array) && inherit_mode && inherit_mode.include?(key)
169
+ return if base_hash[key].is_a?(Array) && inherit_mode&.include?(key)
170
170
 
171
171
  puts "#{PathUtil.smart_path(opts[:file])}: " \
172
172
  "#{opts[:cop_name]}:#{key} overrides " \
@@ -194,11 +194,11 @@ module RuboCop
194
194
  end
195
195
 
196
196
  def should_merge?(mode, key)
197
- mode && mode['merge'] && mode['merge'].include?(key)
197
+ mode && mode['merge']&.include?(key)
198
198
  end
199
199
 
200
200
  def should_override?(mode, key)
201
- mode && mode['override'] && mode['override'].include?(key)
201
+ mode && mode['override']&.include?(key)
202
202
  end
203
203
 
204
204
  def merge_hashes?(base_hash, derived_hash, key)
@@ -7,7 +7,8 @@ module RuboCop
7
7
  extend SimpleForwardable
8
8
 
9
9
  # @api private
10
- COMMON_PARAMS = %w[Exclude Include Severity inherit_mode AutoCorrect StyleGuide Details].freeze
10
+ COMMON_PARAMS = %w[Exclude Include Severity inherit_mode AutoCorrect StyleGuide Details
11
+ Enabled].freeze
11
12
  # @api private
12
13
  INTERNAL_PARAMS = %w[Description StyleGuide
13
14
  VersionAdded VersionChanged VersionRemoved
@@ -49,7 +49,9 @@ module RuboCop
49
49
  private
50
50
 
51
51
  def disable_offense(offense_range)
52
- range = surrounding_heredoc(offense_range) || surrounding_percent_array(offense_range)
52
+ range = surrounding_heredoc(offense_range) ||
53
+ surrounding_percent_array(offense_range) ||
54
+ string_continuation(offense_range)
53
55
 
54
56
  if range
55
57
  disable_offense_before_and_after(range_by_lines(range))
@@ -88,10 +90,28 @@ module RuboCop
88
90
  end
89
91
 
90
92
  percent_array.map(&:source_range).find do |range|
91
- offense_range.begin_pos > range.begin_pos && range.overlaps?(offense_range)
93
+ range_overlaps_offense?(offense_range, range)
92
94
  end
93
95
  end
94
96
 
97
+ def string_continuation(offense_range)
98
+ return nil if offense_range.empty?
99
+
100
+ string_continuation_nodes = processed_source.ast.each_descendant.filter_map do |node|
101
+ range_by_lines(node.source_range) if string_continuation?(node)
102
+ end
103
+
104
+ string_continuation_nodes.find { |range| range_overlaps_offense?(offense_range, range) }
105
+ end
106
+
107
+ def range_overlaps_offense?(offense_range, range)
108
+ offense_range.begin_pos > range.begin_pos && range.overlaps?(offense_range)
109
+ end
110
+
111
+ def string_continuation?(node)
112
+ (node.str_type? || node.dstr_type? || node.xstr_type?) && node.source.match?(/\\\s*$/)
113
+ end
114
+
95
115
  def range_of_first_line(range)
96
116
  begin_of_first_line = range.begin_pos - range.column
97
117
  end_of_first_line = begin_of_first_line + range.source_line.length
@@ -322,8 +322,12 @@ module RuboCop
322
322
  # @api private
323
323
  def self.callbacks_needed
324
324
  @callbacks_needed ||= public_instance_methods.select do |m|
325
- m.start_with?(/on_|after_/) &&
326
- !Base.method_defined?(m) # exclude standard "callbacks" like 'on_begin_investigation'
325
+ # OPTIMIZE: Check method existence first to make fewer `start_with?` calls.
326
+ # At the time of writing this comment, this excludes 98 of ~104 methods.
327
+ # `start_with?` with two string arguments instead of a regex is faster
328
+ # in this specific case as well.
329
+ !Base.method_defined?(m) && # exclude standard "callbacks" like 'on_begin_investigation'
330
+ m.start_with?('on_', 'after_')
327
331
  end
328
332
  end
329
333
  # rubocop:enable Layout/ClassStructure
@@ -56,6 +56,7 @@ module RuboCop
56
56
 
57
57
  REQUIRED_MSG = 'Gem version specification is required.'
58
58
  FORBIDDEN_MSG = 'Gem version specification is forbidden.'
59
+ RESTRICT_ON_SEND = %i[gem].freeze
59
60
  VERSION_SPECIFICATION_REGEX = /^\s*[~<>=]*\s*[0-9.]+/.freeze
60
61
 
61
62
  # @!method includes_version_specification?(node)
@@ -22,6 +22,14 @@ module RuboCop
22
22
  end
23
23
  end
24
24
 
25
+ def self.inherited(_subclass)
26
+ super
27
+ warn Rainbow(<<~WARNING).yellow, uplevel: 1
28
+ Inheriting from `RuboCop::Cop::Cop` is deprecated. Use `RuboCop::Cop::Base` instead.
29
+ For more information, see https://docs.rubocop.org/rubocop/v1_upgrade_notes.html.
30
+ WARNING
31
+ end
32
+
25
33
  def self.support_autocorrect?
26
34
  method_defined?(:autocorrect)
27
35
  end
@@ -47,7 +47,7 @@ module RuboCop
47
47
  if column_delta.positive? && range.resize(1).source != "\n"
48
48
  corrector.insert_before(range, ' ' * column_delta)
49
49
  elsif /\A[ \t]+\z/.match?(range.source)
50
- remove(range, corrector)
50
+ corrector.remove(range)
51
51
  end
52
52
  end
53
53
 
@@ -96,17 +96,6 @@ module RuboCop
96
96
  end
97
97
  end
98
98
 
99
- def remove(range, corrector)
100
- original_stderr = $stderr
101
- $stderr = StringIO.new # Avoid error messages on console
102
- corrector.remove(range)
103
- rescue RuntimeError
104
- range = range_between(range.begin_pos + 1, range.end_pos + 1)
105
- retry if /^ +$/.match?(range.source)
106
- ensure
107
- $stderr = original_stderr
108
- end
109
-
110
99
  def each_line(expr)
111
100
  line_begin_pos = expr.begin_pos
112
101
  expr.source.each_line do |line|
@@ -22,7 +22,7 @@ module RuboCop
22
22
  private
23
23
 
24
24
  def ternary_condition?(node)
25
- node.parent&.if_type? && node.parent&.ternary?
25
+ node.parent&.if_type? && node.parent.ternary?
26
26
  end
27
27
 
28
28
  def next_char_is_question_mark?(node)
@@ -94,6 +94,16 @@ module RuboCop
94
94
  end
95
95
 
96
96
  def substitute_escaped_delimiters(content, delimiters)
97
+ if delimiters.first != delimiters.last
98
+ # With different delimiters (eg. `[]`, `()`), if there are the same
99
+ # number of each, escaping is not necessary
100
+ delimiter_counts = delimiters.each_with_object({}) do |delimiter, counts|
101
+ counts[delimiter] = content.count(delimiter)
102
+ end
103
+
104
+ return content if delimiter_counts[delimiters.first] == delimiter_counts[delimiters.last]
105
+ end
106
+
97
107
  delimiters.each { |delim| content.gsub!(delim, "\\#{delim}") }
98
108
  end
99
109
 
@@ -112,10 +112,6 @@ module RuboCop
112
112
  body = comment_body(comment_line)
113
113
  node.source.index(body)
114
114
  end
115
-
116
- def relevant_file?(file)
117
- file.match?(%r{/cop/.*\.rb\z})
118
- end
119
115
  end
120
116
  end
121
117
  end
@@ -11,13 +11,9 @@ module RuboCop
11
11
  #
12
12
  # # bad
13
13
  # add_offense(node, message: MSG)
14
- # add_offense(node, message: message)
15
- # add_offense(node, message: message(node))
16
14
  #
17
15
  # # good
18
16
  # add_offense(node)
19
- # add_offense(node, message: CUSTOM_MSG)
20
- # add_offense(node, message: message(other_node))
21
17
  #
22
18
  class RedundantMessageArgument < Base
23
19
  include RangeHelp
@@ -28,22 +24,21 @@ module RuboCop
28
24
 
29
25
  # @!method node_type_check(node)
30
26
  def_node_matcher :node_type_check, <<~PATTERN
31
- (send nil? :add_offense $_node $hash)
27
+ (send nil? :add_offense _node $hash)
32
28
  PATTERN
33
29
 
34
30
  # @!method redundant_message_argument(node)
35
31
  def_node_matcher :redundant_message_argument, <<~PATTERN
36
32
  (pair
37
33
  (sym :message)
38
- ${(const nil? :MSG) (send nil? :message) (send nil? :message _)})
34
+ $(const nil? :MSG))
39
35
  PATTERN
40
36
 
41
- # @!method message_method_call(node)
42
- def_node_matcher :message_method_call, '(send nil? :message $_node)'
43
-
44
37
  def on_send(node)
45
- node_type_check(node) do |node_arg, kwargs|
46
- find_offending_argument(node_arg, kwargs) do |pair|
38
+ return unless (kwargs = node_type_check(node))
39
+
40
+ kwargs.pairs.each do |pair|
41
+ redundant_message_argument(pair) do
47
42
  add_offense(pair) do |corrector|
48
43
  range = offending_range(pair)
49
44
 
@@ -60,16 +55,6 @@ module RuboCop
60
55
 
61
56
  range_with_surrounding_comma(with_space, :left)
62
57
  end
63
-
64
- def find_offending_argument(searched_node, kwargs)
65
- kwargs.pairs.each do |pair|
66
- redundant_message_argument(pair) do |message_argument|
67
- node = message_method_call(message_argument)
68
-
69
- yield pair if !node || node == searched_node
70
- end
71
- end
72
- end
73
58
  end
74
59
  end
75
60
  end
@@ -14,6 +14,12 @@ module RuboCop
14
14
  # node.source
15
15
  #
16
16
  # # bad
17
+ # add_offense(node.source_range)
18
+ #
19
+ # # good
20
+ # add_offense(node)
21
+ #
22
+ # # bad
17
23
  # add_offense(node) { |corrector| corrector.replace(node.source_range, prefer) }
18
24
  # add_offense(node) { |corrector| corrector.insert_before(node.source_range, prefer) }
19
25
  # add_offense(node) { |corrector| corrector.insert_before_multi(node.source_range, prefer) }
@@ -34,7 +40,7 @@ module RuboCop
34
40
 
35
41
  MSG = 'Remove the redundant `source_range`.'
36
42
  RESTRICT_ON_SEND = %i[
37
- source
43
+ source add_offense
38
44
  replace remove insert_before insert_before_multi insert_after insert_after_multi swap
39
45
  ].freeze
40
46
 
@@ -42,6 +48,7 @@ module RuboCop
42
48
  def_node_matcher :redundant_source_range, <<~PATTERN
43
49
  {
44
50
  (send $(send _ :source_range) :source)
51
+ (send nil? :add_offense $(send _ :source_range) ...)
45
52
  (send _ {
46
53
  :replace :insert_before :insert_before_multi :insert_after :insert_after_multi
47
54
  } $(send _ :source_range) _)
@@ -43,11 +43,6 @@ module RuboCop
43
43
  node.ancestors.any? { |ancestor| rspec_expectation_on_msg?(ancestor) }
44
44
  end
45
45
  end
46
-
47
- # Only process spec files
48
- def relevant_file?(file)
49
- file.end_with?('_spec.rb')
50
- end
51
46
  end
52
47
  end
53
48
  end
@@ -31,3 +31,19 @@ require_relative 'internal_affairs/style_detected_api_use'
31
31
  require_relative 'internal_affairs/undefined_config'
32
32
  require_relative 'internal_affairs/useless_message_assertion'
33
33
  require_relative 'internal_affairs/useless_restrict_on_send'
34
+
35
+ module RuboCop
36
+ # Patch in the InternalAffairs specific config values
37
+ module InternalAffairs
38
+ def self.inject!
39
+ path = File.join(ConfigLoader::RUBOCOP_HOME, 'config', 'internal_affairs.yml')
40
+ hash = ConfigLoader.load_yaml_configuration(path)
41
+ config = Config.new(hash, path)
42
+ puts "configuration from #{path}" if ConfigLoader.debug?
43
+ config = ConfigLoader.merge_with_default(config, path)
44
+ ConfigLoader.instance_variable_set(:@default_configuration, config)
45
+ end
46
+ end
47
+ end
48
+
49
+ RuboCop::InternalAffairs.inject!
@@ -59,7 +59,11 @@ module RuboCop
59
59
  modifiers = body.each_child_node(:send).select(&:bare_access_modifier?)
60
60
  end_range = node.loc.end
61
61
 
62
- modifiers.each { |modifier| check_modifier(modifier, end_range) }
62
+ modifiers.each do |modifier|
63
+ next if same_line?(node, modifier)
64
+
65
+ check_modifier(modifier, end_range)
66
+ end
63
67
  end
64
68
 
65
69
  def check_modifier(send_node, end_range)
@@ -61,7 +61,7 @@ module RuboCop
61
61
  private
62
62
 
63
63
  def autocorrect(corrector, node)
64
- if style == :start_of_line && node.parent && node.parent.send_type?
64
+ if style == :start_of_line && node.parent&.send_type?
65
65
  AlignmentCorrector.align_end(corrector, processed_source, node, node.parent)
66
66
  else
67
67
  AlignmentCorrector.align_end(corrector, processed_source, node, node)
@@ -135,7 +135,7 @@ module RuboCop
135
135
 
136
136
  parent = next_sibling.parent
137
137
 
138
- parent&.if_type? && parent&.else?
138
+ parent&.if_type? && parent.else?
139
139
  end
140
140
 
141
141
  def next_sibling_empty_or_guard_clause?(node)
@@ -63,13 +63,21 @@ module RuboCop
63
63
  # }
64
64
  # )
65
65
  #
66
+ # @example AllowedMethods: ['some_method']
67
+ #
68
+ # # good
69
+ # some_method(foo, bar,
70
+ # baz)
66
71
  class FirstMethodArgumentLineBreak < Base
67
72
  include FirstElementLineBreak
73
+ include AllowedMethods
68
74
  extend AutoCorrector
69
75
 
70
76
  MSG = 'Add a line break before the first argument of a multi-line method argument list.'
71
77
 
72
78
  def on_send(node)
79
+ return if allowed_method?(node.method_name)
80
+
73
81
  args = node.arguments.dup
74
82
 
75
83
  # If there is a trailing hash arg without explicit braces, like this: