rubocop 1.79.2 → 1.82.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 (142) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +35 -7
  4. data/config/obsoletion.yml +4 -0
  5. data/exe/rubocop +1 -8
  6. data/lib/rubocop/cli/command/auto_generate_config.rb +2 -2
  7. data/lib/rubocop/cli.rb +8 -3
  8. data/lib/rubocop/comment_config.rb +62 -17
  9. data/lib/rubocop/config_loader.rb +5 -2
  10. data/lib/rubocop/config_loader_resolver.rb +7 -6
  11. data/lib/rubocop/config_store.rb +5 -0
  12. data/lib/rubocop/cop/autocorrect_logic.rb +6 -4
  13. data/lib/rubocop/cop/correctors/alignment_corrector.rb +8 -7
  14. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +7 -2
  15. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +10 -5
  16. data/lib/rubocop/cop/internal_affairs/location_exists.rb +28 -2
  17. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +1 -1
  18. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +3 -1
  19. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
  20. data/lib/rubocop/cop/layout/class_structure.rb +1 -1
  21. data/lib/rubocop/cop/layout/dot_position.rb +1 -1
  22. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +3 -0
  23. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +30 -12
  24. data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +1 -1
  25. data/lib/rubocop/cop/layout/end_alignment.rb +4 -0
  26. data/lib/rubocop/cop/layout/hash_alignment.rb +2 -5
  27. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
  28. data/lib/rubocop/cop/layout/heredoc_indentation.rb +0 -4
  29. data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
  30. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
  31. data/lib/rubocop/cop/layout/line_length.rb +16 -5
  32. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +8 -4
  33. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +13 -3
  34. data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
  35. data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
  36. data/lib/rubocop/cop/lint/circular_argument_reference.rb +47 -3
  37. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +3 -2
  38. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +14 -8
  39. data/lib/rubocop/cop/lint/debugger.rb +0 -2
  40. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +4 -1
  41. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +5 -42
  42. data/lib/rubocop/cop/lint/else_layout.rb +19 -0
  43. data/lib/rubocop/cop/lint/empty_interpolation.rb +11 -0
  44. data/lib/rubocop/cop/lint/literal_as_condition.rb +4 -0
  45. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
  46. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +17 -8
  47. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +4 -0
  48. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +23 -9
  49. data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -2
  50. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +7 -1
  51. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
  52. data/lib/rubocop/cop/lint/self_assignment.rb +15 -6
  53. data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -7
  54. data/lib/rubocop/cop/lint/unreachable_code.rb +5 -3
  55. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +2 -0
  56. data/lib/rubocop/cop/lint/useless_or.rb +15 -2
  57. data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +1 -1
  58. data/lib/rubocop/cop/lint/void.rb +7 -0
  59. data/lib/rubocop/cop/message_annotator.rb +1 -1
  60. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -3
  61. data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
  62. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +0 -4
  63. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  64. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -7
  65. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +1 -1
  66. data/lib/rubocop/cop/mixin/line_length_help.rb +21 -2
  67. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
  68. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
  69. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
  70. data/lib/rubocop/cop/mixin/statement_modifier.rb +0 -6
  71. data/lib/rubocop/cop/mixin/trailing_comma.rb +5 -6
  72. data/lib/rubocop/cop/naming/method_name.rb +5 -3
  73. data/lib/rubocop/cop/naming/predicate_method.rb +19 -6
  74. data/lib/rubocop/cop/security/json_load.rb +33 -11
  75. data/lib/rubocop/cop/style/array_intersect.rb +46 -12
  76. data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +47 -0
  77. data/lib/rubocop/cop/style/bare_percent_literals.rb +1 -2
  78. data/lib/rubocop/cop/style/bitwise_predicate.rb +8 -1
  79. data/lib/rubocop/cop/style/case_equality.rb +11 -13
  80. data/lib/rubocop/cop/style/class_and_module_children.rb +1 -0
  81. data/lib/rubocop/cop/style/conditional_assignment.rb +8 -14
  82. data/lib/rubocop/cop/style/constant_visibility.rb +17 -12
  83. data/lib/rubocop/cop/style/double_negation.rb +1 -1
  84. data/lib/rubocop/cop/style/empty_method.rb +0 -6
  85. data/lib/rubocop/cop/style/endless_method.rb +15 -2
  86. data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
  87. data/lib/rubocop/cop/style/float_division.rb +15 -1
  88. data/lib/rubocop/cop/style/guard_clause.rb +0 -11
  89. data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
  90. data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -3
  91. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  92. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +12 -1
  93. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +17 -4
  94. data/lib/rubocop/cop/style/module_member_existence_check.rb +74 -0
  95. data/lib/rubocop/cop/style/multiline_method_signature.rb +0 -4
  96. data/lib/rubocop/cop/style/nil_comparison.rb +9 -7
  97. data/lib/rubocop/cop/style/one_line_conditional.rb +17 -9
  98. data/lib/rubocop/cop/style/parallel_assignment.rb +2 -2
  99. data/lib/rubocop/cop/style/redundant_argument.rb +2 -0
  100. data/lib/rubocop/cop/style/redundant_begin.rb +34 -0
  101. data/lib/rubocop/cop/style/redundant_condition.rb +1 -1
  102. data/lib/rubocop/cop/style/redundant_exception.rb +1 -1
  103. data/lib/rubocop/cop/style/redundant_format.rb +26 -5
  104. data/lib/rubocop/cop/style/redundant_interpolation.rb +11 -2
  105. data/lib/rubocop/cop/style/redundant_parentheses.rb +14 -11
  106. data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -2
  107. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +9 -0
  108. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -0
  109. data/lib/rubocop/cop/style/redundant_sort.rb +7 -7
  110. data/lib/rubocop/cop/style/safe_navigation.rb +18 -1
  111. data/lib/rubocop/cop/style/semicolon.rb +23 -7
  112. data/lib/rubocop/cop/style/sole_nested_conditional.rb +8 -1
  113. data/lib/rubocop/cop/style/string_concatenation.rb +17 -13
  114. data/lib/rubocop/cop/style/super_arguments.rb +2 -2
  115. data/lib/rubocop/cop/style/symbol_array.rb +1 -1
  116. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +45 -0
  117. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +11 -11
  118. data/lib/rubocop/cop/style/unless_else.rb +10 -9
  119. data/lib/rubocop/cop/util.rb +2 -3
  120. data/lib/rubocop/cop/utils/format_string.rb +10 -0
  121. data/lib/rubocop/cop/variable_force/variable.rb +1 -1
  122. data/lib/rubocop/cop/variable_force.rb +9 -7
  123. data/lib/rubocop/cops_documentation_generator.rb +4 -4
  124. data/lib/rubocop/directive_comment.rb +46 -3
  125. data/lib/rubocop/formatter/disabled_config_formatter.rb +19 -5
  126. data/lib/rubocop/lsp/diagnostic.rb +10 -14
  127. data/lib/rubocop/lsp/routes.rb +31 -2
  128. data/lib/rubocop/lsp/stdin_runner.rb +0 -16
  129. data/lib/rubocop/magic_comment.rb +20 -0
  130. data/lib/rubocop/rake_task.rb +1 -1
  131. data/lib/rubocop/remote_config.rb +7 -8
  132. data/lib/rubocop/result_cache.rb +1 -1
  133. data/lib/rubocop/rspec/shared_contexts.rb +2 -2
  134. data/lib/rubocop/rspec/support.rb +1 -1
  135. data/lib/rubocop/runner.rb +6 -4
  136. data/lib/rubocop/target_finder.rb +9 -9
  137. data/lib/rubocop/target_ruby.rb +11 -2
  138. data/lib/rubocop/version.rb +1 -1
  139. data/lib/rubocop.rb +2 -0
  140. data/lib/ruby_lsp/rubocop/addon.rb +23 -8
  141. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +49 -15
  142. metadata +8 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f846b1bf660549b8197375e32c8219bff1e42888b925976bd3514cd9b32c1d3b
4
- data.tar.gz: 4e862ade4bbe0c24c7734427695733316c893b5278f9868aa88c44255d03461c
3
+ metadata.gz: 395ade8767ec51e33acbc9c14c0b11300df6100806f9e2c9bd23241f22f7f206
4
+ data.tar.gz: ed5bf8c5e1f3f7adc724fd900ec7d8b0cda4c91892276349177e7eb7c06d87a7
5
5
  SHA512:
6
- metadata.gz: 05ff2343d4ddcdd26cf94325a5b9026fb7468f456b5714da5108030c39fb0fcfb7218848596d07b04817052af53bc225e66b1f81c53f18adb780c2b4bd417012
7
- data.tar.gz: 9c2ce30fbd9467d85bed0aa581beaa225f3e5b032f0e7a5b09130c8eb2918b25e452f3704a9774e8199c1b9e1ccb1b7d10e558a710c7a73d9f9bd86940475ebf
6
+ metadata.gz: 53fd7c4276518804677378c9c958c96c5512d9b3cfa89c0a5a8597a676a54efb18077a45e30d47f15c15a08448c9ad8c6b5c931cc0e244bb34abef88b5d30238
7
+ data.tar.gz: e7298eed68c7cb9d9d7c294bc7ca031b538ea1a3205bb34ab854ef76bf1230a4e664c178088f1489030f51dd1ad4f9e1bfd1dc4397a5a240904b27bc55965428
data/README.md CHANGED
@@ -51,7 +51,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
51
51
  in your `Gemfile`:
52
52
 
53
53
  ```rb
54
- gem 'rubocop', '~> 1.79', require: false
54
+ gem 'rubocop', '~> 1.82', require: false
55
55
  ```
56
56
 
57
57
  See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
data/config/default.yml CHANGED
@@ -275,7 +275,7 @@ Gemspec/AddRuntimeDependency:
275
275
  Description: 'Prefer `add_dependency` over `add_runtime_dependency`.'
276
276
  StyleGuide: '#add_dependency_vs_add_runtime_dependency'
277
277
  References:
278
- - https://github.com/rubygems/rubygems/issues/7799#issuecomment-2192720316
278
+ - https://github.com/ruby/rubygems/issues/7799#issuecomment-2192720316
279
279
  Enabled: pending
280
280
  VersionAdded: '1.65'
281
281
  Include:
@@ -1102,7 +1102,7 @@ Layout/LineLength:
1102
1102
  StyleGuide: '#max-line-length'
1103
1103
  Enabled: true
1104
1104
  VersionAdded: '0.25'
1105
- VersionChanged: '1.69'
1105
+ VersionChanged: '1.82'
1106
1106
  Max: 120
1107
1107
  AllowHeredoc: true
1108
1108
  # To make it possible to copy or click on URIs in the code, we allow lines
@@ -1112,9 +1112,12 @@ Layout/LineLength:
1112
1112
  URISchemes:
1113
1113
  - http
1114
1114
  - https
1115
- # The IgnoreCopDirectives option causes the LineLength rule to ignore cop
1115
+ # The AllowRBSInlineAnnotation option makes LineLength allow RBS::Inline annotations
1116
+ # such as `#: (?date: Date) -> Foo` when calculating line length.
1117
+ AllowRBSInlineAnnotation: false
1118
+ # The AllowCopDirectives option causes the LineLength rule to ignore cop
1116
1119
  # directives like '# rubocop: enable ...' when calculating a line's length.
1117
- IgnoreCopDirectives: true
1120
+ AllowCopDirectives: true
1118
1121
  # The AllowedPatterns option is a list of !ruby/regexp and/or string
1119
1122
  # elements. Strings will be converted to Regexp objects. A line that matches
1120
1123
  # any regular expression listed in this option will be ignored by LineLength.
@@ -2669,7 +2672,10 @@ Lint/UselessNumericOperation:
2669
2672
  Lint/UselessOr:
2670
2673
  Description: 'Checks for useless OR expressions.'
2671
2674
  Enabled: pending
2675
+ SafeAutoCorrect: false
2676
+ AutoCorrect: contextual
2672
2677
  VersionAdded: '1.76'
2678
+ VersionChanged: '1.82'
2673
2679
 
2674
2680
  Lint/UselessRescue:
2675
2681
  Description: 'Checks for useless `rescue`s.'
@@ -3207,6 +3213,7 @@ Security/JSONLoad:
3207
3213
  security issues. See reference for more information.
3208
3214
  References:
3209
3215
  - 'https://ruby-doc.org/stdlib-2.7.0/libdoc/json/rdoc/JSON.html#method-i-load'
3216
+ - 'https://bugs.ruby-lang.org/issues/19528'
3210
3217
  Enabled: true
3211
3218
  VersionAdded: '0.43'
3212
3219
  VersionChanged: '1.22'
@@ -3280,7 +3287,7 @@ Style/Alias:
3280
3287
 
3281
3288
  Style/AmbiguousEndlessMethodDefinition:
3282
3289
  Description: 'Checks for endless methods inside operators of lower precedence.'
3283
- StyleGuide: '#ambiguous-endless-method-defintions'
3290
+ StyleGuide: '#ambiguous-endless-method-definitions'
3284
3291
  Enabled: pending
3285
3292
  VersionAdded: '1.68'
3286
3293
 
@@ -3341,6 +3348,12 @@ Style/ArrayIntersect:
3341
3348
  Safe: false
3342
3349
  VersionAdded: '1.40'
3343
3350
 
3351
+ Style/ArrayIntersectWithSingleElement:
3352
+ Description: 'Use `include?(element)` instead of `intersect?([element])`.'
3353
+ Enabled: 'pending'
3354
+ Safe: false
3355
+ VersionAdded: '1.81'
3356
+
3344
3357
  Style/ArrayJoin:
3345
3358
  Description: 'Use Array#join instead of Array#*.'
3346
3359
  StyleGuide: '#array-join'
@@ -3518,9 +3531,11 @@ Style/BlockDelimiters:
3518
3531
  BracesRequiredMethods: []
3519
3532
 
3520
3533
  Style/CaseEquality:
3521
- Description: 'Avoid explicit use of the case equality operator(===).'
3534
+ Description: 'Avoid explicit use of the case equality operator (`===`).'
3522
3535
  StyleGuide: '#no-case-equality'
3523
3536
  Enabled: true
3537
+ References:
3538
+ - 'https://docs.rubocop.org/rubocop-performance/cops_performance.html#performanceregexpmatch'
3524
3539
  VersionAdded: '0.9'
3525
3540
  VersionChanged: '0.89'
3526
3541
  # If `AllowOnConstant` option is enabled, the cop will ignore violations when the receiver of
@@ -4546,8 +4561,9 @@ Style/LambdaCall:
4546
4561
  Description: 'Use lambda.call(...) instead of lambda.(...).'
4547
4562
  StyleGuide: '#proc-call'
4548
4563
  Enabled: true
4564
+ AutoCorrect: contextual
4549
4565
  VersionAdded: '0.13'
4550
- VersionChanged: '0.14'
4566
+ VersionChanged: '1.81'
4551
4567
  EnforcedStyle: call
4552
4568
  SupportedStyles:
4553
4569
  - call
@@ -4617,6 +4633,7 @@ Style/MethodCallWithArgsParentheses:
4617
4633
  AllowedMethods: []
4618
4634
  AllowedPatterns: []
4619
4635
  IncludedMacros: []
4636
+ IncludedMacroPatterns: []
4620
4637
  AllowParenthesesInMultilineCall: false
4621
4638
  AllowParenthesesInChaining: false
4622
4639
  AllowParenthesesInCamelCaseMethod: false
@@ -4727,6 +4744,11 @@ Style/ModuleFunction:
4727
4744
  Autocorrect: false
4728
4745
  SafeAutoCorrect: false
4729
4746
 
4747
+ Style/ModuleMemberExistenceCheck:
4748
+ Description: 'Checks for usage of `Module` methods returning arrays that can be replaced with equivalent predicates.'
4749
+ Enabled: pending
4750
+ VersionAdded: '1.82'
4751
+
4730
4752
  Style/MultilineBlockChain:
4731
4753
  Description: 'Avoid multi-line chains of blocks.'
4732
4754
  StyleGuide: '#single-line-blocks'
@@ -5214,6 +5236,8 @@ Style/RedundantArgument:
5214
5236
  exit: true
5215
5237
  # Kernel.#exit!
5216
5238
  exit!: false
5239
+ # String#to_i
5240
+ to_i: 10
5217
5241
  # String#split
5218
5242
  split: ' '
5219
5243
  # String#chomp
@@ -5844,10 +5868,14 @@ Style/TrailingCommaInArguments:
5844
5868
  # parenthesized method calls where each argument is on its own line.
5845
5869
  # If `consistent_comma`, the cop requires a comma after the last argument,
5846
5870
  # for all parenthesized method calls with arguments.
5871
+ # If `diff_comma`, the cop requires a comma after the last argument, but only
5872
+ # when that argument is followed by an immediate newline, even if
5873
+ # there is an inline comment.
5847
5874
  EnforcedStyleForMultiline: no_comma
5848
5875
  SupportedStylesForMultiline:
5849
5876
  - comma
5850
5877
  - consistent_comma
5878
+ - diff_comma
5851
5879
  - no_comma
5852
5880
 
5853
5881
  Style/TrailingCommaInArrayLiteral:
@@ -145,6 +145,10 @@ changed_parameters:
145
145
  - cops: Layout/CaseIndentation
146
146
  parameters: IndentWhenRelativeTo
147
147
  alternative: EnforcedStyle
148
+ - cops: Layout/LineLength
149
+ parameters: IgnoreCopDirectives
150
+ alternative: AllowCopDirectives
151
+ severity: warning
148
152
  - cops:
149
153
  - Lint/BlockAlignment
150
154
  - Layout/BlockAlignment
data/exe/rubocop CHANGED
@@ -12,13 +12,6 @@ if RuboCop::Server.running?
12
12
  exit_status = RuboCop::Server::ClientCommand::Exec.new.run
13
13
  else
14
14
  require 'rubocop'
15
-
16
- cli = RuboCop::CLI.new
17
-
18
- time_start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
19
- exit_status = cli.run
20
- elapsed_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) - time_start
21
-
22
- puts "Finished in #{elapsed_time} seconds" if cli.options[:debug] || cli.options[:display_time]
15
+ exit_status = RuboCop::CLI.new.run
23
16
  end
24
17
  exit exit_status
@@ -83,7 +83,7 @@ module RuboCop
83
83
  execute_runner
84
84
  @options.delete(:only)
85
85
  @config_store = ConfigStore.new
86
- @config_store.options_config = @options[:config] if @options[:config]
86
+ @config_store.apply_options!(@options)
87
87
  # Save the todo configuration of the LineLength cop.
88
88
  File.read(AUTO_GENERATED_FILE).lines.drop_while { |line| line.start_with?('#') }.join
89
89
  end
@@ -99,7 +99,7 @@ module RuboCop
99
99
 
100
100
  def reset_config_and_auto_gen_file
101
101
  @config_store = ConfigStore.new
102
- @config_store.options_config = @options[:config] if @options[:config]
102
+ @config_store.apply_options!(@options)
103
103
  File.open(AUTO_GENERATED_FILE, 'w') {} # create or truncate if exists
104
104
  add_inheritance_from_auto_generated_file(@options[:config])
105
105
  end
data/lib/rubocop/cli.rb CHANGED
@@ -37,6 +37,8 @@ module RuboCop
37
37
  #
38
38
  # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
39
39
  def run(args = ARGV)
40
+ time_start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
41
+
40
42
  @options, paths = Options.new.parse(args)
41
43
  @env = Environment.new(@options, @config_store, paths)
42
44
 
@@ -64,7 +66,7 @@ module RuboCop
64
66
  STATUS_INTERRUPTED
65
67
  rescue Finished
66
68
  STATUS_SUCCESS
67
- rescue OptionParser::InvalidOption => e
69
+ rescue OptionParser::ParseError => e
68
70
  warn e.message
69
71
  warn 'For usage information, use --help'
70
72
  STATUS_ERROR
@@ -72,6 +74,9 @@ module RuboCop
72
74
  warn e.message
73
75
  warn e.backtrace
74
76
  STATUS_ERROR
77
+ ensure
78
+ elapsed_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) - time_start
79
+ puts "Finished in #{elapsed_time} seconds" if @options[:debug] || @options[:display_time]
75
80
  end
76
81
  # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
77
82
 
@@ -159,8 +164,7 @@ module RuboCop
159
164
  set_options_to_pending_cops_reporter
160
165
  handle_editor_mode
161
166
 
162
- @config_store.options_config = @options[:config] if @options[:config]
163
- @config_store.force_default_config! if @options[:force_default_config]
167
+ @config_store.apply_options!(@options)
164
168
 
165
169
  handle_exiting_options
166
170
 
@@ -179,6 +183,7 @@ module RuboCop
179
183
  ConfigLoader.enable_pending_cops = @options[:enable_pending_cops]
180
184
  ConfigLoader.ignore_parent_exclusion = @options[:ignore_parent_exclusion]
181
185
  ConfigLoader.ignore_unrecognized_cops = @options[:ignore_unrecognized_cops]
186
+ ConfigLoader.cache_root = ResultCache.cache_root(@config_store, @options[:cache_root])
182
187
  end
183
188
 
184
189
  def set_options_to_pending_cops_reporter
@@ -34,6 +34,7 @@ module RuboCop
34
34
  def initialize(processed_source)
35
35
  @processed_source = processed_source
36
36
  @no_directives = !processed_source.raw_source.include?('rubocop')
37
+ @stack = []
37
38
  end
38
39
 
39
40
  def cop_enabled_at_line?(cop, line_number)
@@ -93,16 +94,23 @@ module RuboCop
93
94
  end
94
95
  end
95
96
 
96
- def analyze # rubocop:todo Metrics/AbcSize
97
+ def analyze # rubocop:todo Metrics/AbcSize, Metrics/MethodLength
97
98
  return {} if @no_directives
98
99
 
99
100
  analyses = Hash.new { |hash, key| hash[key] = CopAnalysis.new([], nil) }
100
101
  inject_disabled_cops_directives(analyses)
101
102
 
102
103
  each_directive do |directive|
103
- directive.cop_names.each do |cop_name|
104
- cop_name = qualified_cop_name(cop_name)
105
- analyses[cop_name] = analyze_cop(analyses[cop_name], directive)
104
+ if directive.push?
105
+ @stack.push(snapshot_analyses(analyses))
106
+ apply_push_args(analyses, directive)
107
+ elsif directive.pop?
108
+ pop_state(analyses, directive.line_number) if @stack.any?
109
+ else
110
+ directive.cop_names.each do |cop_name|
111
+ cop_name = qualified_cop_name(cop_name)
112
+ analyses[cop_name] = analyze_cop(analyses[cop_name], directive)
113
+ end
106
114
  end
107
115
  end
108
116
 
@@ -112,6 +120,51 @@ module RuboCop
112
120
  end
113
121
  end
114
122
 
123
+ def snapshot_analyses(analyses)
124
+ analyses.transform_values { |a| CopAnalysis.new(a.line_ranges.dup, a.start_line_number) }
125
+ end
126
+
127
+ def pop_state(analyses, pop_line)
128
+ analyses.each do |cop_name, analysis|
129
+ next unless analysis.start_line_number
130
+
131
+ analyses[cop_name] = CopAnalysis.new(
132
+ analysis.line_ranges + [analysis.start_line_number...pop_line], nil
133
+ )
134
+ end
135
+
136
+ @stack.pop.each do |cop_name, saved_analysis|
137
+ current = analyses[cop_name]
138
+ new_start = saved_analysis.start_line_number ? pop_line : nil
139
+ analyses[cop_name] = CopAnalysis.new(current.line_ranges, new_start)
140
+ end
141
+ end
142
+
143
+ def apply_push_args(analyses, directive)
144
+ directive.push_args.each do |operation, cop_names|
145
+ cop_names.each do |cop_name|
146
+ apply_cop_operation(analyses, operation, qualified_cop_name(cop_name),
147
+ directive.line_number)
148
+ end
149
+ end
150
+ end
151
+
152
+ def apply_cop_operation(analyses, operation, cop_name, line)
153
+ analysis = analyses[cop_name]
154
+ start_line = analysis.start_line_number
155
+
156
+ case operation
157
+ when '+' # Enable cop
158
+ return unless start_line
159
+
160
+ analyses[cop_name] = CopAnalysis.new(analysis.line_ranges + [start_line..line], nil)
161
+ when '-' # Disable cop
162
+ return if start_line
163
+
164
+ analyses[cop_name] = CopAnalysis.new(analysis.line_ranges, line)
165
+ end
166
+ end
167
+
115
168
  def inject_disabled_cops_directives(analyses)
116
169
  registry.disabled(config).each do |cop|
117
170
  analyses[cop.cop_name] = analyze_cop(
@@ -136,29 +189,21 @@ module RuboCop
136
189
  return analysis unless directive.disabled?
137
190
 
138
191
  line = directive.line_number
139
- start_line = analysis.start_line_number
140
-
141
- CopAnalysis.new(analysis.line_ranges + [(line..line)], start_line)
192
+ CopAnalysis.new(analysis.line_ranges + [(line..line)], analysis.start_line_number)
142
193
  end
143
194
 
144
195
  def analyze_disabled(analysis, directive)
145
196
  line = directive.line_number
146
197
  start_line = analysis.start_line_number
147
-
148
- # Cop already disabled on this line, so we end the current disabled
149
- # range before we start a new range.
150
- return CopAnalysis.new(analysis.line_ranges + [start_line..line], line) if start_line
151
-
152
- CopAnalysis.new(analysis.line_ranges, line)
198
+ new_ranges = start_line ? analysis.line_ranges + [start_line..line] : analysis.line_ranges
199
+ CopAnalysis.new(new_ranges, line)
153
200
  end
154
201
 
155
202
  def analyze_rest(analysis, directive)
156
203
  line = directive.line_number
157
204
  start_line = analysis.start_line_number
158
-
159
- return CopAnalysis.new(analysis.line_ranges + [start_line..line], nil) if start_line
160
-
161
- CopAnalysis.new(analysis.line_ranges, nil)
205
+ new_ranges = start_line ? analysis.line_ranges + [start_line..line] : analysis.line_ranges
206
+ CopAnalysis.new(new_ranges, nil)
162
207
  end
163
208
 
164
209
  def cop_line_ranges(analysis)
@@ -23,7 +23,7 @@ module RuboCop
23
23
  include FileFinder
24
24
 
25
25
  attr_accessor :debug, :ignore_parent_exclusion, :disable_pending_cops, :enable_pending_cops,
26
- :ignore_unrecognized_cops
26
+ :ignore_unrecognized_cops, :cache_root
27
27
  attr_writer :default_configuration
28
28
  attr_reader :loaded_plugins, :loaded_features
29
29
 
@@ -38,6 +38,7 @@ module RuboCop
38
38
  @enable_pending_cops = nil
39
39
  @ignore_parent_exclusion = nil
40
40
  @ignore_unrecognized_cops = nil
41
+ @cache_root = nil
41
42
  FileFinder.root_level = nil
42
43
  end
43
44
 
@@ -75,7 +76,9 @@ module RuboCop
75
76
 
76
77
  puts "configuration from #{absolute_path}" if debug?
77
78
 
78
- raise(TypeError, "Malformed configuration in #{absolute_path}") unless hash.is_a?(Hash)
79
+ unless hash.is_a?(Hash)
80
+ raise(ValidationError, "Malformed configuration in #{absolute_path}")
81
+ end
79
82
 
80
83
  hash
81
84
  end
@@ -246,7 +246,7 @@ module RuboCop
246
246
  def inherited_file(path, inherit_from, file)
247
247
  if PathUtil.remote_file?(inherit_from)
248
248
  # A remote configuration, e.g. `inherit_from: http://example.com/rubocop.yml`.
249
- RemoteConfig.new(inherit_from, File.dirname(path))
249
+ RemoteConfig.new(inherit_from, ConfigLoader.cache_root)
250
250
  elsif Pathname.new(inherit_from).absolute?
251
251
  # An absolute path to a config, e.g. `inherit_from: /Users/me/rubocop.yml`.
252
252
  # The path may come from `inherit_gem` option, where a gem name is expanded
@@ -256,7 +256,7 @@ module RuboCop
256
256
  elsif file.is_a?(RemoteConfig)
257
257
  # A path relative to a URL, e.g. `inherit_from: configs/default.yml`
258
258
  # in a config included with `inherit_from: http://example.com/rubocop.yml`
259
- file.inherit_from_remote(inherit_from, path)
259
+ file.inherit_from_remote(inherit_from)
260
260
  else
261
261
  # A local relative path, e.g. `inherit_from: default.yml`
262
262
  print 'Inheriting ' if ConfigLoader.debug?
@@ -295,10 +295,11 @@ module RuboCop
295
295
  begin
296
296
  gem = Bundler.load.specs[gem_name].first
297
297
  gem_path = gem.full_gem_path if gem
298
- rescue Bundler::GemfileNotFound
299
- # No Gemfile found. Bundler may be loaded manually
300
- rescue Bundler::GitError
301
- # The Gemfile exists but contains an uninstalled git source
298
+ rescue StandardError
299
+ # The Gemfile has a problem, which could be one of:
300
+ # - No Gemfile found. Bundler may be loaded manually
301
+ # - The Gemfile exists but contains an uninstalled git source
302
+ # - The Gemfile exists but cannot be loaded for some other reason
302
303
  end
303
304
  end
304
305
 
@@ -25,6 +25,11 @@ module RuboCop
25
25
  @validated = true
26
26
  end
27
27
 
28
+ def apply_options!(options)
29
+ self.options_config = options[:config] if options[:config]
30
+ force_default_config! if options[:force_default_config]
31
+ end
32
+
28
33
  def options_config=(options_config)
29
34
  loaded_config = ConfigLoader.load_file(options_config)
30
35
  @options_config = ConfigLoader.merge_with_default(loaded_config, options_config)
@@ -35,8 +35,8 @@ module RuboCop
35
35
  # `false` is the same as `disabled` for backward compatibility.
36
36
  return false if ['disabled', false].include?(cop_config['AutoCorrect'])
37
37
 
38
- # When LSP is enabled, it is considered as editing source code,
39
- # and autocorrection with `AutoCorrect: contextual` will not be performed.
38
+ # When LSP is enabled or the `--editor-mode` option is on, it is considered as editing
39
+ # source code, and autocorrection with `AutoCorrect: contextual` will not be performed.
40
40
  return false if contextual_autocorrect? && LSP.enabled?
41
41
 
42
42
  # :safe_autocorrect is a derived option based on several command-line
@@ -94,7 +94,7 @@ module RuboCop
94
94
  end
95
95
 
96
96
  def surrounding_heredoc?(node)
97
- node.type?(:str, :dstr, :xstr) && node.heredoc?
97
+ node.any_str_type? && node.heredoc?
98
98
  end
99
99
 
100
100
  def heredoc_range(node)
@@ -106,7 +106,7 @@ module RuboCop
106
106
  end
107
107
 
108
108
  def string_continuation?(node)
109
- node.type?(:str, :dstr, :xstr) && node.source.match?(/\\\s*$/)
109
+ node.any_str_type? && node.source.match?(/\\\s*$/)
110
110
  end
111
111
 
112
112
  def multiline_string?(node)
@@ -133,6 +133,8 @@ module RuboCop
133
133
  end
134
134
 
135
135
  def max_line_length
136
+ return unless config.cop_enabled?('Layout/LineLength')
137
+
136
138
  config.for_cop('Layout/LineLength')['Max'] || 120
137
139
  end
138
140
 
@@ -29,10 +29,13 @@ module RuboCop
29
29
  def align_end(corrector, processed_source, node, align_to)
30
30
  @processed_source = processed_source
31
31
  whitespace = whitespace_range(node)
32
- return false unless whitespace.source.strip.empty?
33
-
34
32
  column = alignment_column(align_to)
35
- corrector.replace(whitespace, ' ' * column)
33
+
34
+ if whitespace.source.strip.empty?
35
+ corrector.replace(whitespace, ' ' * column)
36
+ else
37
+ corrector.insert_after(whitespace, "\n#{' ' * column}")
38
+ end
36
39
  end
37
40
 
38
41
  private
@@ -54,7 +57,7 @@ module RuboCop
54
57
  def inside_string_ranges(node)
55
58
  return [] unless node.is_a?(Parser::AST::Node)
56
59
 
57
- node.each_node(:str, :dstr, :xstr).filter_map { |n| inside_string_range(n) }
60
+ node.each_node(:any_str).filter_map { |n| inside_string_range(n) }
58
61
  end
59
62
 
60
63
  def inside_string_range(node)
@@ -73,9 +76,7 @@ module RuboCop
73
76
  # nil.
74
77
  # - The source map of `__FILE__` responds to neither :begin nor :end.
75
78
  def delimited_string_literal?(node)
76
- loc = node.location
77
-
78
- loc.respond_to?(:begin) && loc.begin && loc.respond_to?(:end) && loc.end
79
+ node.loc?(:begin) && node.loc?(:end)
79
80
  end
80
81
 
81
82
  def block_comment_within?(expr)
@@ -6,7 +6,7 @@ module RuboCop
6
6
  class ForToEachCorrector
7
7
  extend NodePattern::Macros
8
8
 
9
- CORRECTION = '%<collection>s.each do |%<argument>s|'
9
+ CORRECTION = '%<collection>s%<dot>seach do |%<argument>s|'
10
10
 
11
11
  def initialize(for_node)
12
12
  @for_node = for_node
@@ -25,7 +25,12 @@ module RuboCop
25
25
  attr_reader :for_node, :variable_node, :collection_node
26
26
 
27
27
  def correction
28
- format(CORRECTION, collection: collection_source, argument: variable_node.source)
28
+ format(
29
+ CORRECTION,
30
+ collection: collection_source,
31
+ dot: collection_node.csend_type? ? '&.' : '.',
32
+ argument: variable_node.source
33
+ )
29
34
  end
30
35
 
31
36
  def collection_source
@@ -3,8 +3,8 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Gemspec
6
- # Checks that `RUBY_VERSION` constant is not used in gemspec.
7
- # Using `RUBY_VERSION` is dangerous because value of the
6
+ # Checks that `RUBY_VERSION` and `Ruby::VERSION` constants are not used in gemspec.
7
+ # Using `RUBY_VERSION` and `Ruby::VERSION` are dangerous because value of the
8
8
  # constant is determined by `rake release`.
9
9
  # It's possible to have dependency based on ruby version used
10
10
  # to execute `rake release` and not user's ruby version.
@@ -28,15 +28,20 @@ module RuboCop
28
28
  class RubyVersionGlobalsUsage < Base
29
29
  include GemspecHelp
30
30
 
31
- MSG = 'Do not use `RUBY_VERSION` in gemspec file.'
31
+ MSG = 'Do not use `%<ruby_version>s` in gemspec file.'
32
32
 
33
33
  # @!method ruby_version?(node)
34
- def_node_matcher :ruby_version?, '(const {cbase nil?} :RUBY_VERSION)'
34
+ def_node_matcher :ruby_version?, <<~PATTERN
35
+ {
36
+ (const {cbase nil?} :RUBY_VERSION)
37
+ (const (const {cbase nil?} :Ruby) :VERSION)
38
+ }
39
+ PATTERN
35
40
 
36
41
  def on_const(node)
37
42
  return unless gem_spec_with_ruby_version?(node)
38
43
 
39
- add_offense(node)
44
+ add_offense(node, message: format(MSG, ruby_version: node.source))
40
45
  end
41
46
 
42
47
  private
@@ -9,6 +9,12 @@ module RuboCop
9
9
  #
10
10
  # @example
11
11
  # # bad
12
+ # node.loc.respond_to?(:begin)
13
+ #
14
+ # # good
15
+ # node.loc?(:begin)
16
+ #
17
+ # # bad
12
18
  # node.loc.respond_to?(:begin) && node.loc.begin
13
19
  #
14
20
  # # good
@@ -29,7 +35,16 @@ module RuboCop
29
35
  class LocationExists < Base
30
36
  extend AutoCorrector
31
37
 
32
- MSG = 'Use `%<replacement>s` instead of `%<source>s`.'
38
+ MSG = 'Use `node.loc?` instead of `loc.respond_to?`.'
39
+ MSG_CORRECTABLE = 'Use `%<replacement>s` instead of `%<source>s`.'
40
+ RESTRICT_ON_SEND = %i[respond_to?].freeze
41
+
42
+ # @!method loc_respond_to?(node)
43
+ def_node_matcher :loc_respond_to?, <<~PATTERN
44
+ (call
45
+ (call $_receiver :loc) :respond_to?
46
+ $(sym _location))
47
+ PATTERN
33
48
 
34
49
  # @!method replaceable_with_loc_is(node)
35
50
  def_node_matcher :replaceable_with_loc_is, <<~PATTERN
@@ -64,6 +79,15 @@ module RuboCop
64
79
  replace_with_loc(node) || replace_with_loc_is(node)
65
80
  end
66
81
 
82
+ def on_send(node)
83
+ return if ignored_node?(node.parent)
84
+
85
+ loc_respond_to?(node) do |receiver, location|
86
+ register_offense(node, replacement(receiver, "loc?(#{location.source})"))
87
+ end
88
+ end
89
+ alias on_csend on_send
90
+
67
91
  private
68
92
 
69
93
  def replace_with_loc(node)
@@ -84,11 +108,13 @@ module RuboCop
84
108
  end
85
109
 
86
110
  def register_offense(node, replacement)
87
- message = format(MSG, replacement: replacement, source: node.source)
111
+ message = format(MSG_CORRECTABLE, replacement: replacement, source: node.source)
88
112
 
89
113
  add_offense(node, message: message) do |corrector|
90
114
  corrector.replace(node, replacement)
91
115
  end
116
+
117
+ ignore_node(node)
92
118
  end
93
119
 
94
120
  def replacement(receiver, rest)
@@ -7,7 +7,7 @@ module RuboCop
7
7
  # AST Processor for NodePattern ASTs, for use with `InternalAffairs/NodePatternGroups`.
8
8
  #
9
9
  # Looks for sequences and subsequences where the first item is a `node_type` node,
10
- # and converts them to `node_sequence` nodes (not a true `Rubocop::AST::NodePattern`
10
+ # and converts them to `node_sequence` nodes (not a true `RuboCop::AST::NodePattern`
11
11
  # node type).
12
12
  #
13
13
  # The resulting AST will be walked by `InternalAffairs::NodePatternGroups::ASTWalker`
@@ -30,6 +30,8 @@ module RuboCop
30
30
  any_block: %i[block numblock itblock],
31
31
  any_def: %i[def defs],
32
32
  any_match_pattern: %i[match_pattern match_pattern_p],
33
+ any_str: %i[str dstr xstr],
34
+ any_sym: %i[sym dsym],
33
35
  argument: %i[arg optarg restarg kwarg kwoptarg kwrestarg blockarg forward_arg shadowarg],
34
36
  boolean: %i[true false],
35
37
  call: %i[send csend],
@@ -210,7 +212,7 @@ module RuboCop
210
212
  # A heredoc can be a `dstr` without interpolation, but if there is interpolation
211
213
  # there'll be a `begin` node, in which case, we cannot evaluate the pattern.
212
214
  def acceptable_heredoc?(node)
213
- node.type?(:str, :dstr) && node.heredoc? && node.each_child_node(:begin).none?
215
+ node.any_str_type? && node.heredoc? && node.each_child_node(:begin).none?
214
216
  end
215
217
 
216
218
  def process_pattern(pattern_node)