rubocop 1.88.0 → 1.89.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 (197) hide show
  1. checksums.yaml +4 -4
  2. data/config/default.yml +72 -12
  3. data/lib/rubocop/comment_config.rb +35 -19
  4. data/lib/rubocop/config.rb +53 -0
  5. data/lib/rubocop/config_validator.rb +38 -1
  6. data/lib/rubocop/cop/badge.rb +8 -0
  7. data/lib/rubocop/cop/base.rb +19 -12
  8. data/lib/rubocop/cop/bundler/gem_comment.rb +3 -1
  9. data/lib/rubocop/cop/bundler.rb +19 -0
  10. data/lib/rubocop/cop/commissioner.rb +13 -11
  11. data/lib/rubocop/cop/corrector.rb +1 -1
  12. data/lib/rubocop/cop/correctors/alignment_corrector.rb +55 -5
  13. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +1 -1
  14. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +7 -1
  15. data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +8 -1
  16. data/lib/rubocop/cop/gemspec/development_dependencies.rb +1 -1
  17. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +12 -2
  18. data/lib/rubocop/cop/gemspec/require_mfa.rb +4 -1
  19. data/lib/rubocop/cop/gemspec.rb +22 -0
  20. data/lib/rubocop/cop/generator/registration_injector.rb +188 -0
  21. data/lib/rubocop/cop/generator.rb +4 -0
  22. data/lib/rubocop/cop/layout/block_alignment.rb +17 -0
  23. data/lib/rubocop/cop/layout/class_structure.rb +14 -4
  24. data/lib/rubocop/cop/layout/comment_indentation.rb +9 -2
  25. data/lib/rubocop/cop/layout/condition_position.rb +13 -3
  26. data/lib/rubocop/cop/layout/else_alignment.rb +1 -14
  27. data/lib/rubocop/cop/layout/empty_comment.rb +8 -10
  28. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +14 -1
  29. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +1 -1
  30. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +13 -14
  31. data/lib/rubocop/cop/layout/indentation_width.rb +31 -1
  32. data/lib/rubocop/cop/layout/leading_comment_space.rb +27 -0
  33. data/lib/rubocop/cop/layout/line_length.rb +95 -17
  34. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +18 -3
  35. data/lib/rubocop/cop/layout/redundant_line_break.rb +77 -0
  36. data/lib/rubocop/cop/layout/space_around_operators.rb +6 -2
  37. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +33 -34
  38. data/lib/rubocop/cop/layout.rb +114 -0
  39. data/lib/rubocop/cop/lazy_loader.rb +41 -0
  40. data/lib/rubocop/cop/lint/ambiguous_assignment.rb +9 -7
  41. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +71 -0
  42. data/lib/rubocop/cop/lint/assignment_in_condition.rb +13 -1
  43. data/lib/rubocop/cop/lint/constant_reassignment.rb +1 -10
  44. data/lib/rubocop/cop/lint/constant_resolution.rb +25 -0
  45. data/lib/rubocop/cop/lint/debugger.rb +13 -1
  46. data/lib/rubocop/cop/lint/deprecated_reference.rb +185 -0
  47. data/lib/rubocop/cop/lint/duplicate_methods.rb +202 -22
  48. data/lib/rubocop/cop/lint/inherit_exception.rb +53 -7
  49. data/lib/rubocop/cop/lint/literal_as_condition.rb +5 -0
  50. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
  51. data/lib/rubocop/cop/lint/missing_super.rb +31 -1
  52. data/lib/rubocop/cop/lint/name_typo.rb +223 -0
  53. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +7 -0
  54. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +0 -4
  55. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +7 -0
  56. data/lib/rubocop/cop/lint/to_enum_arguments.rb +44 -2
  57. data/lib/rubocop/cop/lint/to_json.rb +8 -1
  58. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +32 -8
  59. data/lib/rubocop/cop/lint/unreachable_code.rb +9 -4
  60. data/lib/rubocop/cop/lint/unused_private_method.rb +157 -0
  61. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +10 -10
  62. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +2 -0
  63. data/lib/rubocop/cop/lint/void.rb +19 -8
  64. data/lib/rubocop/cop/lint.rb +176 -0
  65. data/lib/rubocop/cop/metrics/method_length.rb +1 -1
  66. data/lib/rubocop/cop/metrics/perceived_complexity.rb +38 -7
  67. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
  68. data/lib/rubocop/cop/metrics.rb +31 -0
  69. data/lib/rubocop/cop/migration/department_name.rb +0 -4
  70. data/lib/rubocop/cop/migration.rb +13 -0
  71. data/lib/rubocop/cop/mixin/allowed_methods.rb +5 -5
  72. data/lib/rubocop/cop/mixin/allowed_pattern.rb +5 -1
  73. data/lib/rubocop/cop/mixin/check_line_breakable.rb +23 -5
  74. data/lib/rubocop/cop/mixin/endless_method_rewriter.rb +13 -5
  75. data/lib/rubocop/cop/mixin/forbidden_pattern.rb +5 -1
  76. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +23 -6
  77. data/lib/rubocop/cop/mixin/hash_subset.rb +8 -0
  78. data/lib/rubocop/cop/mixin/hash_transform_method.rb +4 -0
  79. data/lib/rubocop/cop/mixin/project_index_help.rb +140 -0
  80. data/lib/rubocop/cop/mixin/reparsed_equivalence.rb +171 -0
  81. data/lib/rubocop/cop/mixin/statement_modifier.rb +43 -7
  82. data/lib/rubocop/cop/mixin.rb +78 -77
  83. data/lib/rubocop/cop/naming/accessor_method_name.rb +24 -0
  84. data/lib/rubocop/cop/naming/file_name.rb +4 -3
  85. data/lib/rubocop/cop/naming/inclusive_language.rb +8 -2
  86. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +9 -0
  87. data/lib/rubocop/cop/naming/predicate_prefix.rb +33 -5
  88. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +9 -3
  89. data/lib/rubocop/cop/naming/variable_number.rb +3 -1
  90. data/lib/rubocop/cop/naming.rb +31 -0
  91. data/lib/rubocop/cop/offense.rb +10 -6
  92. data/lib/rubocop/cop/registry.rb +153 -43
  93. data/lib/rubocop/cop/security/io_methods.rb +1 -1
  94. data/lib/rubocop/cop/security/marshal_load.rb +1 -1
  95. data/lib/rubocop/cop/security.rb +19 -0
  96. data/lib/rubocop/cop/style/accessor_grouping.rb +11 -1
  97. data/lib/rubocop/cop/style/arguments_forwarding.rb +1 -1
  98. data/lib/rubocop/cop/style/array_intersect.rb +24 -5
  99. data/lib/rubocop/cop/style/class_and_module_children.rb +78 -18
  100. data/lib/rubocop/cop/style/collection_compact.rb +1 -1
  101. data/lib/rubocop/cop/style/conditional_assignment.rb +22 -0
  102. data/lib/rubocop/cop/style/copyright.rb +6 -1
  103. data/lib/rubocop/cop/style/data_inheritance.rb +4 -0
  104. data/lib/rubocop/cop/style/def_with_parentheses.rb +6 -2
  105. data/lib/rubocop/cop/style/dir_empty.rb +4 -0
  106. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +41 -3
  107. data/lib/rubocop/cop/style/documentation.rb +47 -0
  108. data/lib/rubocop/cop/style/documentation_method.rb +5 -1
  109. data/lib/rubocop/cop/style/empty_case_condition.rb +12 -2
  110. data/lib/rubocop/cop/style/empty_class_definition.rb +8 -1
  111. data/lib/rubocop/cop/style/empty_heredoc.rb +4 -0
  112. data/lib/rubocop/cop/style/empty_literal.rb +7 -2
  113. data/lib/rubocop/cop/style/empty_string_inside_interpolation.rb +30 -20
  114. data/lib/rubocop/cop/style/endless_method.rb +0 -10
  115. data/lib/rubocop/cop/style/env_home.rb +4 -0
  116. data/lib/rubocop/cop/style/even_odd.rb +11 -1
  117. data/lib/rubocop/cop/style/exact_regexp_match.rb +8 -1
  118. data/lib/rubocop/cop/style/file_null.rb +4 -2
  119. data/lib/rubocop/cop/style/format_string.rb +13 -1
  120. data/lib/rubocop/cop/style/hash_conversion.rb +14 -6
  121. data/lib/rubocop/cop/style/hash_lookup_method.rb +2 -6
  122. data/lib/rubocop/cop/style/hash_syntax.rb +2 -0
  123. data/lib/rubocop/cop/style/identical_conditional_branches.rb +15 -4
  124. data/lib/rubocop/cop/style/if_unless_modifier.rb +11 -52
  125. data/lib/rubocop/cop/style/if_with_semicolon.rb +9 -1
  126. data/lib/rubocop/cop/style/inline_comment.rb +1 -1
  127. data/lib/rubocop/cop/style/invertible_unless_condition.rb +25 -5
  128. data/lib/rubocop/cop/style/keyword_arguments_merging.rb +4 -0
  129. data/lib/rubocop/cop/style/keyword_parameters_order.rb +7 -3
  130. data/lib/rubocop/cop/style/lambda.rb +11 -1
  131. data/lib/rubocop/cop/style/lambda_call.rb +11 -0
  132. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +11 -0
  133. data/lib/rubocop/cop/style/map_into_array.rb +1 -1
  134. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +20 -3
  135. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +11 -5
  136. data/lib/rubocop/cop/style/method_def_parentheses.rb +5 -1
  137. data/lib/rubocop/cop/style/min_max_comparison.rb +3 -0
  138. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +40 -7
  139. data/lib/rubocop/cop/style/mixin_usage.rb +1 -1
  140. data/lib/rubocop/cop/style/module_function.rb +4 -2
  141. data/lib/rubocop/cop/style/multiline_if_then.rb +7 -1
  142. data/lib/rubocop/cop/style/multiline_memoization.rb +7 -1
  143. data/lib/rubocop/cop/style/multiline_method_signature.rb +11 -4
  144. data/lib/rubocop/cop/style/multiple_comparison.rb +33 -22
  145. data/lib/rubocop/cop/style/mutable_constant.rb +5 -0
  146. data/lib/rubocop/cop/style/negative_array_index.rb +3 -1
  147. data/lib/rubocop/cop/style/nil_lambda.rb +8 -0
  148. data/lib/rubocop/cop/style/numeric_predicate.rb +1 -1
  149. data/lib/rubocop/cop/style/open_struct_use.rb +1 -1
  150. data/lib/rubocop/cop/style/option_hash.rb +1 -1
  151. data/lib/rubocop/cop/style/optional_arguments.rb +1 -0
  152. data/lib/rubocop/cop/style/parallel_assignment.rb +11 -2
  153. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +2 -0
  154. data/lib/rubocop/cop/style/perl_backrefs.rb +5 -3
  155. data/lib/rubocop/cop/style/redundant_assignment.rb +11 -0
  156. data/lib/rubocop/cop/style/redundant_constant_base.rb +37 -1
  157. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +13 -1
  158. data/lib/rubocop/cop/style/redundant_exception.rb +6 -0
  159. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +9 -0
  160. data/lib/rubocop/cop/style/redundant_filter_chain.rb +1 -1
  161. data/lib/rubocop/cop/style/redundant_format.rb +40 -3
  162. data/lib/rubocop/cop/style/redundant_heredoc_delimiter_quotes.rb +6 -1
  163. data/lib/rubocop/cop/style/redundant_line_continuation.rb +80 -129
  164. data/lib/rubocop/cop/style/redundant_parentheses.rb +63 -63
  165. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -4
  166. data/lib/rubocop/cop/style/redundant_self.rb +9 -0
  167. data/lib/rubocop/cop/style/redundant_struct_keyword_init.rb +23 -4
  168. data/lib/rubocop/cop/style/safe_navigation.rb +10 -0
  169. data/lib/rubocop/cop/style/semicolon.rb +4 -4
  170. data/lib/rubocop/cop/style/single_line_do_end_block.rb +17 -4
  171. data/lib/rubocop/cop/style/sole_nested_conditional.rb +20 -3
  172. data/lib/rubocop/cop/style/static_class.rb +21 -0
  173. data/lib/rubocop/cop/style/string_hash_keys.rb +1 -0
  174. data/lib/rubocop/cop/style/struct_inheritance.rb +3 -1
  175. data/lib/rubocop/cop/style/ternary_parentheses.rb +11 -0
  176. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +7 -8
  177. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  178. data/lib/rubocop/cop/style.rb +310 -0
  179. data/lib/rubocop/cop/team.rb +66 -7
  180. data/lib/rubocop/cop/variable_force/variable.rb +18 -6
  181. data/lib/rubocop/cops_documentation_generator.rb +1 -1
  182. data/lib/rubocop/directive_comment.rb +2 -0
  183. data/lib/rubocop/feature_loader.rb +0 -6
  184. data/lib/rubocop/lsp/routes.rb +41 -3
  185. data/lib/rubocop/lsp/runtime.rb +4 -0
  186. data/lib/rubocop/lsp/server.rb +4 -0
  187. data/lib/rubocop/lsp/stdin_runner.rb +20 -0
  188. data/lib/rubocop/pending_cops_reporter.rb +1 -6
  189. data/lib/rubocop/project_index_loader.rb +16 -0
  190. data/lib/rubocop/result_cache.rb +6 -4
  191. data/lib/rubocop/rspec/shared_contexts.rb +14 -2
  192. data/lib/rubocop/runner.rb +100 -33
  193. data/lib/rubocop/server/cache.rb +10 -5
  194. data/lib/rubocop/target_ruby.rb +1 -1
  195. data/lib/rubocop/version.rb +1 -1
  196. data/lib/rubocop.rb +17 -626
  197. metadata +18 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 672884fb2ea66b13be308094ffcec44f915943867fac5542b82ceaba3ecf32e9
4
- data.tar.gz: f489cbc9ae6385c18d4d97140e4589503ac28a82a4288c5bac915679471ea683
3
+ metadata.gz: e613534eb66c6766aa04d7e1075e0d09aa8a3a78690b8b921583d81ea9fb8e9e
4
+ data.tar.gz: c65ec7b8f764105d8950cc73c4deca24f6bec976c6c4041b5338f4a97e98645c
5
5
  SHA512:
6
- metadata.gz: 8d2cb39bc17b788f176096a12ddf766dbdcfafe8a6fcd09e830544053665b3b42f204b0b7fe01a61d2be94d64fe859f6783710f01df71f136e28d9e46ec1ebf6
7
- data.tar.gz: 18067fc7914382cf8c13a07a34b9774647bd85ea34e85eac8a705da85af7039f31befae4e850b23989ddb91918f4cf10bccd4d578dc79a65de5422db86b51ad2
6
+ metadata.gz: 400677d5633740bb086f3f6e4c6cb9438423ce5a77ea6bc8a4bd72ff0249332c58370bbd98f809673699806cc2ae8dfde4d95a9313bfb8e465c631b506a18d20
7
+ data.tar.gz: a08736ea293673d3cebd8185df6b8b0cf718d24d23b772c20c09c1c00e61838c4963245e84074fe0b8732ad5eb32f9f459c3d915fb5a07ad9ee0e0019d2b9a2c
data/config/default.yml CHANGED
@@ -110,6 +110,12 @@ AllCops:
110
110
  # a warning is shown and the flag has no effect.
111
111
  # The default `false` preserves RuboCop's traditional file-local analysis.
112
112
  UseProjectIndex: false
113
+ # When the project index is enabled, also index the sources of the gems in
114
+ # the project's bundle. This lets index-aware cops resolve ancestry chains
115
+ # and members that live in gems (e.g. framework base classes), at the cost
116
+ # of extra memory proportional to the bundle's size. Has no effect when
117
+ # `UseProjectIndex` is `false` or when RuboCop does not run inside Bundler.
118
+ ProjectIndexIncludesGems: false
113
119
  # Enables the result cache if `true`. Can be overridden by the `--cache` command
114
120
  # line option.
115
121
  UseCache: true
@@ -165,6 +171,7 @@ AllCops:
165
171
  rubocop-capybara: [capybara]
166
172
  rubocop-factory_bot: [factory_bot, factory_bot_rails]
167
173
  rubocop-rspec_rails: [rspec-rails]
174
+ rubocop-i18n: [i18n, gettext]
168
175
  # Enable/Disable checking the methods extended by Active Support.
169
176
  ActiveSupportExtensionsEnabled: false
170
177
  # Future version of Ruby will freeze string literals by default.
@@ -511,7 +518,7 @@ Layout/ClassStructure:
511
518
  Enabled: false
512
519
  SafeAutoCorrect: false
513
520
  VersionAdded: '0.52'
514
- VersionChanged: '1.53'
521
+ VersionChanged: '1.89'
515
522
  Categories:
516
523
  module_inclusion:
517
524
  - include
@@ -524,6 +531,7 @@ Layout/ClassStructure:
524
531
  - initializer
525
532
  - public_methods
526
533
  - protected_methods
534
+ - private_class_methods
527
535
  - private_methods
528
536
 
529
537
  Layout/ClosingHeredocIndentation:
@@ -1069,6 +1077,7 @@ Layout/LeadingCommentSpace:
1069
1077
  AllowGemfileRubyComment: false
1070
1078
  AllowRBSInlineAnnotation: false
1071
1079
  AllowSteepAnnotation: false
1080
+ AllowYARDCommentBlockSeparator: false
1072
1081
 
1073
1082
  Layout/LeadingEmptyLines:
1074
1083
  Description: Checks for unnecessary blank lines at the beginning of a file.
@@ -1615,7 +1624,7 @@ Lint/AmbiguousBlockAssociation:
1615
1624
  parentheses.
1616
1625
  Enabled: true
1617
1626
  VersionAdded: '0.48'
1618
- VersionChanged: '1.13'
1627
+ VersionChanged: '1.89'
1619
1628
  AllowedMethods: []
1620
1629
  AllowedPatterns: []
1621
1630
 
@@ -1713,6 +1722,7 @@ Lint/ConstantReassignment:
1713
1722
 
1714
1723
  Lint/ConstantResolution:
1715
1724
  Description: 'Checks that constants are fully qualified with `::`.'
1725
+ VersionChanged: '1.89'
1716
1726
  Enabled: false
1717
1727
  VersionAdded: '0.86'
1718
1728
  # Restrict this cop to only looking at certain names
@@ -1829,6 +1839,14 @@ Lint/DeprecatedOpenSSLConstant:
1829
1839
  Enabled: true
1830
1840
  VersionAdded: '0.84'
1831
1841
 
1842
+ Lint/DeprecatedReference:
1843
+ Description: >-
1844
+ Checks for references to methods and constants documented
1845
+ as deprecated with a YARD `@deprecated` tag.
1846
+ Requires `AllCops/UseProjectIndex` to be enabled.
1847
+ Enabled: pending
1848
+ VersionAdded: '1.89'
1849
+
1832
1850
  Lint/DisjunctiveAssignmentInConstructor:
1833
1851
  Description: 'In constructor, plain assignment is preferred over disjunctive.'
1834
1852
  Enabled: true
@@ -1875,6 +1893,14 @@ Lint/DuplicateMethods:
1875
1893
  Description: 'Checks for duplicate method definitions.'
1876
1894
  Enabled: true
1877
1895
  VersionAdded: '0.29'
1896
+ VersionChanged: '1.89'
1897
+ # Methods that define instance methods by delegation, in the style of
1898
+ # Active Support's `delegate` (`delegate :foo, :bar, to: :target`). Register
1899
+ # a project's own `delegate`-shaped macros here so the cop recognizes the
1900
+ # methods they define. Only takes effect when `AllCops/ActiveSupportExtensionsEnabled`
1901
+ # is `true`.
1902
+ DelegatingMethods:
1903
+ - delegate
1878
1904
 
1879
1905
  Lint/DuplicateRegexpCharacterClassElement:
1880
1906
  Description: 'Checks for duplicate elements in Regexp character classes.'
@@ -2057,7 +2083,7 @@ Lint/InheritException:
2057
2083
  Enabled: true
2058
2084
  SafeAutoCorrect: false
2059
2085
  VersionAdded: '0.41'
2060
- VersionChanged: '1.26'
2086
+ VersionChanged: '1.89'
2061
2087
  # The default base class in favour of `Exception`.
2062
2088
  EnforcedStyle: standard_error
2063
2089
  SupportedStyles:
@@ -2130,7 +2156,7 @@ Lint/MissingSuper:
2130
2156
  without calls to `super`.
2131
2157
  Enabled: true
2132
2158
  VersionAdded: '0.89'
2133
- VersionChanged: '1.4'
2159
+ VersionChanged: '1.89'
2134
2160
  AllowedParentClasses: []
2135
2161
 
2136
2162
  Lint/MixedCaseRange:
@@ -2150,6 +2176,16 @@ Lint/MultipleComparison:
2150
2176
  VersionAdded: '0.47'
2151
2177
  VersionChanged: '1.1'
2152
2178
 
2179
+ Lint/NameTypo:
2180
+ Description: >-
2181
+ Checks for probable typos in constant and method names,
2182
+ using the project index.
2183
+ Enabled: pending
2184
+ CheckConstants: true
2185
+ CheckMethods: true
2186
+ AllowedNames: []
2187
+ VersionAdded: '1.89'
2188
+
2153
2189
  Lint/NestedMethodDefinition:
2154
2190
  Description: 'Do not use nested method definitions.'
2155
2191
  StyleGuide: '#no-nested-methods'
@@ -2213,7 +2249,9 @@ Lint/NumberedParameterAssignment:
2213
2249
  Lint/NumericOperationWithConstantResult:
2214
2250
  Description: 'Checks for numeric operations with constant results.'
2215
2251
  Enabled: pending
2252
+ SafeAutoCorrect: false
2216
2253
  VersionAdded: '1.69'
2254
+ VersionChanged: '1.88'
2217
2255
 
2218
2256
  Lint/OrAssignmentToConstant:
2219
2257
  Description: 'Checks unintended or-assignment to constant.'
@@ -2407,8 +2445,9 @@ Lint/ReturnInVoidContext:
2407
2445
  Lint/SafeNavigationChain:
2408
2446
  Description: 'Do not chain ordinary method call after safe navigation operator.'
2409
2447
  Enabled: true
2448
+ SafeAutoCorrect: false
2410
2449
  VersionAdded: '0.47'
2411
- VersionChanged: '0.77'
2450
+ VersionChanged: '1.89'
2412
2451
  AllowedMethods:
2413
2452
  - present?
2414
2453
  - blank?
@@ -2630,6 +2669,18 @@ Lint/UnusedMethodArgument:
2630
2669
  NotImplementedExceptions:
2631
2670
  - NotImplementedError
2632
2671
 
2672
+ Lint/UnusedPrivateMethod:
2673
+ Description: >-
2674
+ Checks for private instance methods that are not referenced
2675
+ anywhere in the project. Requires `AllCops/UseProjectIndex`
2676
+ to be enabled.
2677
+ # This cop is disabled by default because symbol-based references from other
2678
+ # files (e.g. Rails callbacks declared in a concern) cannot be detected and
2679
+ # would be reported as false positives. It is intended for occasional
2680
+ # dead-code sweeps rather than permanent enforcement.
2681
+ Enabled: false
2682
+ VersionAdded: '1.89'
2683
+
2633
2684
  Lint/UriEscapeUnescape:
2634
2685
  Description: >-
2635
2686
  `URI.escape` method is obsolete and should not be used. Instead, use
@@ -2844,7 +2895,7 @@ Metrics/PerceivedComplexity:
2844
2895
  Description: 'Checks that the perceived complexity of methods is not higher than the configured maximum.'
2845
2896
  Enabled: true
2846
2897
  VersionAdded: '0.25'
2847
- VersionChanged: '0.81'
2898
+ VersionChanged: '1.88'
2848
2899
  AllowedMethods: []
2849
2900
  AllowedPatterns: []
2850
2901
  Max: 8
@@ -2861,6 +2912,7 @@ Migration/DepartmentName:
2861
2912
  Naming/AccessorMethodName:
2862
2913
  Description: Checks the naming of accessor methods for get_/set_.
2863
2914
  StyleGuide: '#accessor_mutator_method_names'
2915
+ VersionChanged: '1.89'
2864
2916
  Enabled: true
2865
2917
  VersionAdded: '0.50'
2866
2918
 
@@ -3137,7 +3189,7 @@ Naming/PredicatePrefix:
3137
3189
  StyleGuide: '#bool-methods-qmark'
3138
3190
  Enabled: true
3139
3191
  VersionAdded: '0.50'
3140
- VersionChanged: '1.75'
3192
+ VersionChanged: '1.89'
3141
3193
  # Predicate name prefixes.
3142
3194
  NamePrefix:
3143
3195
  - is_
@@ -3605,13 +3657,14 @@ Style/ClassAndModuleChildren:
3605
3657
  StyleGuide: '#namespace-definition'
3606
3658
  # Moving from compact to nested children requires knowledge of whether the
3607
3659
  # outer parent is a module or a class. Moving from nested to compact requires
3608
- # verification that the outer parent is defined elsewhere. RuboCop does not
3609
- # have the knowledge to perform either operation safely and thus requires
3610
- # manual oversight.
3660
+ # verification that the outer parent is defined elsewhere. By default RuboCop
3661
+ # does not have the knowledge to perform either operation safely and thus
3662
+ # requires manual oversight. When `AllCops/UseProjectIndex` is enabled, the
3663
+ # project-wide index is consulted for both operations.
3611
3664
  SafeAutoCorrect: false
3612
3665
  Enabled: true
3613
3666
  VersionAdded: '0.19'
3614
- VersionChanged: '1.74'
3667
+ VersionChanged: '1.89'
3615
3668
  #
3616
3669
  # Basically there are two different styles:
3617
3670
  #
@@ -3923,8 +3976,9 @@ Style/DisableCopsWithinSourceCodeDirective:
3923
3976
  Forbids disabling/enabling cops within source code.
3924
3977
  Enabled: false
3925
3978
  VersionAdded: '0.82'
3926
- VersionChanged: '1.9'
3979
+ VersionChanged: '1.89'
3927
3980
  AllowedCops: []
3981
+ DisallowedCops: []
3928
3982
 
3929
3983
  Style/DocumentDynamicEvalDefinition:
3930
3984
  Description: >-
@@ -3939,6 +3993,7 @@ Style/Documentation:
3939
3993
  Description: 'Document classes and non-namespace modules.'
3940
3994
  Enabled: true
3941
3995
  VersionAdded: '0.9'
3996
+ VersionChanged: '1.89'
3942
3997
  AllowedConstants: []
3943
3998
  Exclude:
3944
3999
  - 'spec/**/*'
@@ -4658,7 +4713,9 @@ Style/MagicCommentFormat:
4658
4713
  Style/MapCompactWithConditionalBlock:
4659
4714
  Description: 'Prefer `select` or `reject` over `map { ... }.compact`.'
4660
4715
  Enabled: pending
4716
+ SafeAutoCorrect: false
4661
4717
  VersionAdded: '1.30'
4718
+ VersionChanged: '1.88'
4662
4719
 
4663
4720
  Style/MapIntoArray:
4664
4721
  Description: 'Checks for usages of `each` with `<<`, `push`, or `append` which can be replaced by `map`.'
@@ -4774,6 +4831,7 @@ Style/MissingRespondToMissing:
4774
4831
  StyleGuide: '#no-method-missing'
4775
4832
  Enabled: true
4776
4833
  VersionAdded: '0.56'
4834
+ VersionChanged: '1.89'
4777
4835
 
4778
4836
  Style/MixinGrouping:
4779
4837
  Description: 'Checks for grouping of mixins in `class` and `module` bodies.'
@@ -5393,6 +5451,7 @@ Style/RedundantConditional:
5393
5451
 
5394
5452
  Style/RedundantConstantBase:
5395
5453
  Description: Avoid redundant `::` prefix on constant.
5454
+ VersionChanged: '1.89'
5396
5455
  Enabled: pending
5397
5456
  VersionAdded: '1.40'
5398
5457
 
@@ -5826,6 +5885,7 @@ Style/StabbyLambdaParentheses:
5826
5885
  Style/StaticClass:
5827
5886
  Description: 'Prefer modules to classes with only class methods.'
5828
5887
  StyleGuide: '#modules-vs-classes'
5888
+ VersionChanged: '1.89'
5829
5889
  Enabled: false
5830
5890
  Safe: false
5831
5891
  VersionAdded: '1.3'
@@ -55,8 +55,8 @@ module RuboCop
55
55
 
56
56
  def extra_enabled_comments
57
57
  disable_count = Hash.new(0)
58
- registry.disabled(config).each do |cop|
59
- disable_count[cop.cop_name] += 1
58
+ registry.disabled_names(config).each do |cop_name|
59
+ disable_count[cop_name] += 1
60
60
  end
61
61
  extra_enabled_comments_with_names(extras: Hash.new { |h, k| h[k] = [] }, names: disable_count)
62
62
  end
@@ -65,6 +65,24 @@ module RuboCop
65
65
  non_comment_token_line_numbers.none?(line_number)
66
66
  end
67
67
 
68
+ # The names of the cops that are opted in by an `enable` comment directive,
69
+ # used to mobilize cops disabled in the config on demand.
70
+ #
71
+ # @api private
72
+ # @return [Set<String>]
73
+ def opt_in_cops
74
+ @opt_in_cops ||= begin
75
+ cops = Set.new
76
+ each_directive do |directive|
77
+ next unless directive.enabled?
78
+ next if directive.all_cops?
79
+
80
+ cops.merge(directive.raw_cop_names)
81
+ end
82
+ cops
83
+ end
84
+ end
85
+
68
86
  private
69
87
 
70
88
  def extra_enabled_comments_with_names(extras:, names:)
@@ -82,19 +100,6 @@ module RuboCop
82
100
  extras
83
101
  end
84
102
 
85
- def opt_in_cops
86
- @opt_in_cops ||= begin
87
- cops = Set.new
88
- each_directive do |directive|
89
- next unless directive.enabled?
90
- next if directive.all_cops?
91
-
92
- cops.merge(directive.raw_cop_names)
93
- end
94
- cops
95
- end
96
- end
97
-
98
103
  # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
99
104
  def analyze
100
105
  return {} if @no_directives
@@ -119,6 +124,8 @@ module RuboCop
119
124
 
120
125
  analyses.each_with_object({}) do |element, hash|
121
126
  cop_name, analysis = *element
127
+ next if prevent_directive_disabling?(cop_name)
128
+
122
129
  hash[cop_name] = cop_line_ranges(analysis)
123
130
  end
124
131
  end
@@ -163,10 +170,10 @@ module RuboCop
163
170
  end
164
171
 
165
172
  def inject_disabled_cops_directives(analyses)
166
- registry.disabled(config).each do |cop|
167
- analyses[cop.cop_name] = analyze_cop(
168
- analyses[cop.cop_name],
169
- DirectiveComment.new(ConfigDisabledCopDirectiveComment.new(cop.cop_name))
173
+ registry.disabled_names(config).each do |cop_name|
174
+ analyses[cop_name] = analyze_cop(
175
+ analyses[cop_name],
176
+ DirectiveComment.new(ConfigDisabledCopDirectiveComment.new(cop_name))
170
177
  )
171
178
  end
172
179
  end
@@ -222,6 +229,15 @@ module RuboCop
222
229
  Cop::Registry.qualified_cop_name(cop_name.strip, processed_source.file_path)
223
230
  end
224
231
 
232
+ # `Style/DisableCopsWithinSourceCodeDirective` cannot be disabled via
233
+ # directive comments when it is explicitly enabled with `Enabled: true`.
234
+ # This prevents users from bypassing the cop by writing a disable
235
+ # directive that targets this cop itself.
236
+ def prevent_directive_disabling?(cop_name)
237
+ cop_name == DirectiveComment::STYLE_DISABLE_COPS_DIRECTIVE_COP &&
238
+ config.dig(cop_name, 'Enabled') == true
239
+ end
240
+
225
241
  def non_comment_token_line_numbers
226
242
  @non_comment_token_line_numbers ||= begin
227
243
  non_comment_tokens = processed_source.tokens.reject(&:comment?)
@@ -209,6 +209,20 @@ module RuboCop
209
209
  for_all_cops['NewCops'] == 'enable'
210
210
  end
211
211
 
212
+ # Whether the given pending cop should be enabled, based on the `NewCops` setting of
213
+ # its department (if any) or of `AllCops`. A department may set `NewCops` to `enable`,
214
+ # `disable`, `pending`, or a version, in which case pending cops added in that version
215
+ # or earlier are enabled.
216
+ def enabled_new_cop?(qualified_cop_name)
217
+ setting = new_cops_setting_for(qualified_cop_name)
218
+
219
+ case setting.to_s
220
+ when 'enable' then true
221
+ when '', 'pending', 'disable' then false
222
+ else new_cops_version_covers?(setting, qualified_cop_name)
223
+ end
224
+ end
225
+
212
226
  def active_support_extensions_enabled?
213
227
  for_all_cops['ActiveSupportExtensionsEnabled']
214
228
  end
@@ -326,6 +340,7 @@ module RuboCop
326
340
 
327
341
  cop_metadata = self[qualified_cop_name]
328
342
  next unless cop_metadata['Enabled'] == 'pending'
343
+ next if new_cops_covered?(qualified_cop_name)
329
344
 
330
345
  pending_cops << CopConfig.new(qualified_cop_name, cop_metadata)
331
346
  end
@@ -399,6 +414,44 @@ module RuboCop
399
414
 
400
415
  self[cop_department.join('/')]
401
416
  end
417
+
418
+ # The effective `NewCops` setting for the given cop: the department-level
419
+ # setting if present, otherwise the `AllCops` setting.
420
+ def new_cops_setting_for(qualified_cop_name)
421
+ department = department_of(qualified_cop_name)
422
+ setting = department['NewCops'] if department
423
+
424
+ setting || for_all_cops['NewCops']
425
+ end
426
+
427
+ # Whether the cop's pending status is resolved by a `NewCops` setting,
428
+ # so that it should not appear in the pending cops warning.
429
+ # Unlike `enabled_new_cop?`, `disable` counts as covered.
430
+ def new_cops_covered?(qualified_cop_name)
431
+ setting = new_cops_setting_for(qualified_cop_name)
432
+
433
+ case setting.to_s
434
+ when 'enable', 'disable' then true
435
+ when '', 'pending' then false
436
+ else new_cops_version_covers?(setting, qualified_cop_name)
437
+ end
438
+ end
439
+
440
+ def new_cops_version_covers?(new_cops_version, qualified_cop_name)
441
+ cop_metadata = self[qualified_cop_name]
442
+ version_added = comparable_version(cop_metadata['VersionAdded']) if cop_metadata
443
+ pinned_version = comparable_version(new_cops_version)
444
+ return false if version_added.nil? || pinned_version.nil?
445
+
446
+ version_added <= pinned_version
447
+ end
448
+
449
+ # Returns a `Gem::Version` for values like `'1.19'` or `1.19`, and `nil`
450
+ # for non-version values like `'N/A'` or `'<<next>>'`.
451
+ def comparable_version(value)
452
+ value = value.to_s
453
+ Gem::Version.new(value) if value.match?(/\A\d/) && Gem::Version.correct?(value)
454
+ end
402
455
  end
403
456
  end
404
457
  # rubocop:enable Metrics/ClassLength
@@ -16,6 +16,8 @@ module RuboCop
16
16
  Reference References Safe SafeAutoCorrect].freeze
17
17
  # @api private
18
18
  NEW_COPS_VALUES = %w[pending disable enable].freeze
19
+ # @api private
20
+ NEW_COPS_VERSION_PATTERN = /\A\d+(\.\d+)*\z/.freeze
19
21
 
20
22
  # @api private
21
23
  CONFIG_CHECK_KEYS = %w[Enabled Safe SafeAutoCorrect AutoCorrect References].to_set.freeze
@@ -164,16 +166,48 @@ module RuboCop
164
166
  end
165
167
 
166
168
  def validate_new_cops_parameter
169
+ validate_all_cops_new_cops_parameter
170
+ validate_department_new_cops_parameters
171
+ end
172
+
173
+ def validate_all_cops_new_cops_parameter
167
174
  new_cop_parameter = @config.for_all_cops['NewCops']
168
175
  return if new_cop_parameter.nil? || NEW_COPS_VALUES.include?(new_cop_parameter)
169
176
 
170
- message = "invalid #{new_cop_parameter} for `NewCops` found in" \
177
+ message = "invalid #{new_cop_parameter} for `NewCops` found in " \
171
178
  "#{smart_loaded_path}\n" \
172
179
  "Valid choices are: #{NEW_COPS_VALUES.join(', ')}"
173
180
 
174
181
  raise ValidationError, message
175
182
  end
176
183
 
184
+ def validate_department_new_cops_parameters
185
+ @config.each do |name, section|
186
+ value = new_cops_value_for_department(name, section)
187
+ next if value.nil? || NEW_COPS_VALUES.include?(value) || new_cops_version_value?(value)
188
+
189
+ raise ValidationError,
190
+ "invalid #{value} for `NewCops` found in #{smart_loaded_path}\n" \
191
+ "Valid choices for a department are: #{NEW_COPS_VALUES.join(', ')}, " \
192
+ "or a version string like '1.50'"
193
+ end
194
+ end
195
+
196
+ def new_cops_value_for_department(name, section)
197
+ return nil if name == 'AllCops' || !section.is_a?(Hash)
198
+ return nil unless Cop::Registry.global.department?(name)
199
+
200
+ section['NewCops']
201
+ end
202
+
203
+ def new_cops_version_value?(value)
204
+ case value
205
+ when Float, Integer then true
206
+ when String then NEW_COPS_VERSION_PATTERN.match?(value)
207
+ else false
208
+ end
209
+ end
210
+
177
211
  def validate_parameter_shape(valid_cop_names)
178
212
  valid_cop_names.each do |name|
179
213
  if @config[name].nil?
@@ -207,6 +241,9 @@ module RuboCop
207
241
 
208
242
  @config[cop_name].each_key do |param|
209
243
  next if COMMON_PARAMS.include?(param) || default_config.key?(param)
244
+ # Departments shipped as top-level sections in an extension's default configuration accept
245
+ # `NewCops`, like any other department.
246
+ next if param == 'NewCops' && Cop::Registry.global.department?(cop_name)
210
247
 
211
248
  supported_params = default_config.keys - INTERNAL_PARAMS
212
249
 
@@ -52,6 +52,14 @@ module RuboCop
52
52
  cop_name == other.cop_name && (!qualified? || department == other.department)
53
53
  end
54
54
 
55
+ # Returns true if the badge's qualified name or the badge's department
56
+ # matches any of the given names.
57
+ def match_name?(given_names)
58
+ return false unless given_names
59
+
60
+ given_names.include?(to_s) || given_names.include?(department_name)
61
+ end
62
+
55
63
  def to_s
56
64
  @to_s ||= qualified? ? "#{department}/#{cop_name}" : cop_name
57
65
  end
@@ -331,12 +331,11 @@ module RuboCop
331
331
  # @api private
332
332
  def self.callbacks_needed
333
333
  @callbacks_needed ||= public_instance_methods.select do |m|
334
- # OPTIMIZE: Check method existence first to make fewer `start_with?` calls.
335
- # At the time of writing this comment, this excludes 98 of ~104 methods.
336
- # `start_with?` with two string arguments instead of a regex is faster
337
- # in this specific case as well.
338
- !Base.method_defined?(m) && # exclude standard "callbacks" like 'on_begin_investigation'
339
- m.start_with?('on_', 'after_')
334
+ # OPTIMIZE: `start_with?` with two string arguments instead of a regex
335
+ # is faster in this specific case.
336
+ m.start_with?('on_', 'after_') &&
337
+ # exclude standard "callbacks" like 'on_new_investigation' unless refined
338
+ instance_method(m).owner != Base
340
339
  end
341
340
  end
342
341
  # rubocop:enable Layout/ClassStructure
@@ -373,6 +372,12 @@ module RuboCop
373
372
 
374
373
  private
375
374
 
375
+ ### Reserved for Commissioner
376
+
377
+ private_class_method def self.restrict_on_send
378
+ @restrict_on_send ||= self::RESTRICT_ON_SEND.to_a.freeze
379
+ end
380
+
376
381
  ### Reserved for Cop::Cop
377
382
 
378
383
  def callback_argument(range)
@@ -401,10 +406,6 @@ module RuboCop
401
406
  @current_offenses ||= []
402
407
  end
403
408
 
404
- private_class_method def self.restrict_on_send
405
- @restrict_on_send ||= self::RESTRICT_ON_SEND.to_a.freeze
406
- end
407
-
408
409
  EMPTY_OFFENSES = [].freeze
409
410
  private_constant :EMPTY_OFFENSES
410
411
  # Called to complete an investigation
@@ -545,15 +546,21 @@ module RuboCop
545
546
  end
546
547
 
547
548
  def range_for_original(range)
549
+ buffer = @current_original.buffer
550
+ return range if @current_offset.zero? && range.source_buffer.equal?(buffer)
551
+
548
552
  ::Parser::Source::Range.new(
549
- @current_original.buffer,
553
+ buffer,
550
554
  range.begin_pos + @current_offset,
551
555
  range.end_pos + @current_offset
552
556
  )
553
557
  end
554
558
 
555
559
  def target_satisfies_all_gem_version_requirements?
556
- self.class.gem_requirements.all? do |gem_name, version_req|
560
+ gem_requirements = self.class.gem_requirements
561
+ return true if gem_requirements.empty?
562
+
563
+ gem_requirements.all? do |gem_name, version_req|
557
564
  all_gem_versions_in_target = @config.gem_versions_in_target
558
565
  next false unless all_gem_versions_in_target
559
566
 
@@ -163,7 +163,9 @@ module RuboCop
163
163
  def gem_options(node)
164
164
  return [] unless node.last_argument&.hash_type?
165
165
 
166
- node.last_argument.keys.map(&:value)
166
+ # Only literal keys carry an option name to check; a non-literal key
167
+ # (e.g. a variable or method call) has no `value` and must be skipped.
168
+ node.last_argument.keys.filter_map { |key| key.value if key.type?(:sym, :str) }
167
169
  end
168
170
  end
169
171
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # Cops for the `Bundler` department. The department's cops are registered for lazy loading
6
+ # and their files are loaded on demand.
7
+ module Bundler
8
+ extend LazyLoader
9
+
10
+ register_cop :DuplicatedGem, "#{__dir__}/bundler/duplicated_gem"
11
+ register_cop :DuplicatedGroup, "#{__dir__}/bundler/duplicated_group"
12
+ register_cop :GemComment, "#{__dir__}/bundler/gem_comment"
13
+ register_cop :GemFilename, "#{__dir__}/bundler/gem_filename"
14
+ register_cop :GemVersion, "#{__dir__}/bundler/gem_version"
15
+ register_cop :InsecureProtocolSource, "#{__dir__}/bundler/insecure_protocol_source"
16
+ register_cop :OrderedGems, "#{__dir__}/bundler/ordered_gems"
17
+ end
18
+ end
19
+ end
@@ -64,14 +64,16 @@ module RuboCop
64
64
  r = '#' unless RESTRICTED_CALLBACKS.include?(method_name) # has Restricted?
65
65
  c = '#' if NO_CHILD_NODES.include?(node_type) # has Children?
66
66
 
67
+ # The `after_` calls are guarded because barely any cop defines an `after_`
68
+ # callback, and the guard is cheaper than the method call it avoids.
67
69
  class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
68
- def on_#{node_type}(node) # def on_send(node)
69
- trigger_responding_cops(:on_#{node_type}, node) # trigger_responding_cops(:on_send, node)
70
- #{r} trigger_restricted_cops(:on_#{node_type}, node) # trigger_restricted_cops(:on_send, node)
71
- #{c} super(node) # super(node)
72
- #{c} trigger_responding_cops(:after_#{node_type}, node) # trigger_responding_cops(:after_send, node)
73
- #{c}#{r} trigger_restricted_cops(:after_#{node_type}, node) # trigger_restricted_cops(:after_send, node)
74
- end # end
70
+ def on_#{node_type}(node) # def on_send(node)
71
+ trigger_responding_cops(:on_#{node_type}, node) # trigger_responding_cops(:on_send, node)
72
+ #{r} trigger_restricted_cops(:on_#{node_type}, node) # trigger_restricted_cops(:on_send, node)
73
+ #{c} super(node) # super(node)
74
+ #{c} trigger_responding_cops(:after_#{node_type}, node) if @callbacks[:after_#{node_type}] # trigger_responding_cops(:after_send, node) if @callbacks[:after_send]
75
+ #{c}#{r} trigger_restricted_cops(:after_#{node_type}, node) unless @restricted_map[:after_#{node_type}].empty? # trigger_restricted_cops(:after_send, node) unless @restricted_map[:after_send].empty?
76
+ end # end
75
77
  RUBY
76
78
  end
77
79
 
@@ -81,13 +83,13 @@ module RuboCop
81
83
 
82
84
  begin_investigation(processed_source, offset: offset, original: original)
83
85
  if processed_source.valid_syntax?
84
- invoke(:on_new_investigation, @cops)
86
+ invoke(:on_new_investigation, @callbacks[:on_new_investigation])
85
87
  invoke_with_argument(:investigate, @forces, processed_source)
86
88
 
87
89
  walk(processed_source.ast) unless @cops.empty?
88
- invoke(:on_investigation_end, @cops)
90
+ invoke(:on_investigation_end, @callbacks[:on_investigation_end])
89
91
  else
90
- invoke(:on_other_file, @cops)
92
+ invoke(:on_other_file, @callbacks[:on_other_file])
91
93
  end
92
94
  reports = @cops.map { |cop| cop.send(:complete_investigation) }
93
95
  InvestigationReport.new(processed_source, reports, @errors)
@@ -157,7 +159,7 @@ module RuboCop
157
159
  end
158
160
 
159
161
  def invoke(callback, cops)
160
- cops.each { |cop| with_cop_error_handling(cop) { cop.send(callback) } }
162
+ cops&.each { |cop| with_cop_error_handling(cop) { cop.send(callback) } }
161
163
  end
162
164
 
163
165
  def invoke_with_argument(callback, cops, arg)
@@ -103,7 +103,7 @@ module RuboCop
103
103
  # :nodoc:
104
104
  def to_range(node_or_range)
105
105
  range = case node_or_range
106
- when ::RuboCop::AST::Node, ::Parser::Source::Comment
106
+ when RuboCop::AST::Node, ::Parser::Source::Comment
107
107
  node_or_range.source_range
108
108
  when ::Parser::Source::Range
109
109
  node_or_range