rubocop 1.50.2 → 1.59.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 (290) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -3
  3. data/config/default.yml +153 -16
  4. data/config/obsoletion.yml +5 -0
  5. data/lib/rubocop/cli/command/auto_generate_config.rb +10 -5
  6. data/lib/rubocop/cli/command/lsp.rb +19 -0
  7. data/lib/rubocop/cli.rb +4 -1
  8. data/lib/rubocop/config.rb +4 -0
  9. data/lib/rubocop/config_finder.rb +2 -2
  10. data/lib/rubocop/config_loader_resolver.rb +4 -3
  11. data/lib/rubocop/config_obsoletion/parameter_rule.rb +9 -1
  12. data/lib/rubocop/config_obsoletion.rb +13 -10
  13. data/lib/rubocop/cop/autocorrect_logic.rb +3 -1
  14. data/lib/rubocop/cop/base.rb +6 -2
  15. data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -0
  16. data/lib/rubocop/cop/bundler/duplicated_group.rb +127 -0
  17. data/lib/rubocop/cop/bundler/gem_comment.rb +3 -3
  18. data/lib/rubocop/cop/bundler/gem_version.rb +2 -2
  19. data/lib/rubocop/cop/bundler/ordered_gems.rb +9 -1
  20. data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -1
  21. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +7 -4
  22. data/lib/rubocop/cop/gemspec/dependency_version.rb +2 -2
  23. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +2 -2
  24. data/lib/rubocop/cop/gemspec/development_dependencies.rb +1 -1
  25. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +9 -1
  26. data/lib/rubocop/cop/generator/require_file_injector.rb +1 -1
  27. data/lib/rubocop/cop/internal_affairs/cop_description.rb +32 -8
  28. data/lib/rubocop/cop/internal_affairs/example_description.rb +42 -21
  29. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +3 -1
  30. data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +19 -20
  31. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +53 -0
  32. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +7 -7
  33. data/lib/rubocop/cop/internal_affairs/redundant_method_dispatch_node.rb +11 -2
  34. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +2 -0
  35. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  36. data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
  37. data/lib/rubocop/cop/layout/class_structure.rb +7 -0
  38. data/lib/rubocop/cop/layout/closing_heredoc_indentation.rb +1 -2
  39. data/lib/rubocop/cop/layout/dot_position.rb +1 -5
  40. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +42 -9
  41. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +27 -4
  42. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +2 -0
  43. data/lib/rubocop/cop/layout/end_alignment.rb +7 -1
  44. data/lib/rubocop/cop/layout/extra_spacing.rb +4 -10
  45. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +6 -6
  46. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
  47. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +4 -4
  48. data/lib/rubocop/cop/layout/heredoc_indentation.rb +4 -1
  49. data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
  50. data/lib/rubocop/cop/layout/indentation_width.rb +3 -3
  51. data/lib/rubocop/cop/layout/leading_comment_space.rb +1 -1
  52. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +17 -9
  53. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
  54. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -0
  55. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +18 -3
  56. data/lib/rubocop/cop/layout/redundant_line_break.rb +16 -5
  57. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +4 -4
  58. data/lib/rubocop/cop/layout/single_line_block_chain.rb +5 -0
  59. data/lib/rubocop/cop/layout/space_after_comma.rb +9 -1
  60. data/lib/rubocop/cop/layout/space_after_not.rb +1 -1
  61. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +2 -2
  62. data/lib/rubocop/cop/layout/space_around_operators.rb +53 -21
  63. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +2 -0
  64. data/lib/rubocop/cop/layout/space_inside_parens.rb +1 -1
  65. data/lib/rubocop/cop/layout/space_inside_range_literal.rb +1 -1
  66. data/lib/rubocop/cop/layout/trailing_empty_lines.rb +5 -0
  67. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +13 -1
  68. data/lib/rubocop/cop/lint/assignment_in_condition.rb +4 -4
  69. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +2 -2
  70. data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +1 -1
  71. data/lib/rubocop/cop/lint/debugger.rb +19 -5
  72. data/lib/rubocop/cop/lint/duplicate_hash_key.rb +2 -1
  73. data/lib/rubocop/cop/lint/duplicate_methods.rb +1 -1
  74. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +46 -19
  75. data/lib/rubocop/cop/lint/empty_block.rb +1 -1
  76. data/lib/rubocop/cop/lint/erb_new_arguments.rb +6 -7
  77. data/lib/rubocop/cop/lint/float_comparison.rb +10 -0
  78. data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +2 -1
  79. data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +1 -1
  80. data/lib/rubocop/cop/lint/identity_comparison.rb +0 -1
  81. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -3
  82. data/lib/rubocop/cop/lint/inherit_exception.rb +9 -0
  83. data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +56 -0
  84. data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
  85. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +78 -0
  86. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
  87. data/lib/rubocop/cop/lint/missing_super.rb +34 -5
  88. data/lib/rubocop/cop/lint/mixed_case_range.rb +111 -0
  89. data/lib/rubocop/cop/lint/next_without_accumulator.rb +6 -21
  90. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +10 -7
  91. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -5
  92. data/lib/rubocop/cop/lint/number_conversion.rb +14 -4
  93. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +2 -2
  94. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +0 -1
  95. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -2
  96. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +130 -0
  97. data/lib/rubocop/cop/lint/redundant_require_statement.rb +12 -3
  98. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +63 -4
  99. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +1 -1
  100. data/lib/rubocop/cop/lint/redundant_with_index.rb +2 -2
  101. data/lib/rubocop/cop/lint/redundant_with_object.rb +2 -2
  102. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +14 -8
  103. data/lib/rubocop/cop/lint/self_assignment.rb +38 -0
  104. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -2
  105. data/lib/rubocop/cop/lint/shadowed_exception.rb +5 -11
  106. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +7 -1
  107. data/lib/rubocop/cop/lint/struct_new_override.rb +12 -12
  108. data/lib/rubocop/cop/lint/suppressed_exception.rb +2 -2
  109. data/lib/rubocop/cop/lint/symbol_conversion.rb +8 -3
  110. data/lib/rubocop/cop/lint/to_enum_arguments.rb +5 -3
  111. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +23 -9
  112. data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -1
  113. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +2 -2
  114. data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -2
  115. data/lib/rubocop/cop/lint/useless_assignment.rb +94 -10
  116. data/lib/rubocop/cop/lint/useless_times.rb +1 -1
  117. data/lib/rubocop/cop/lint/void.rb +92 -11
  118. data/lib/rubocop/cop/metrics/abc_size.rb +3 -3
  119. data/lib/rubocop/cop/metrics/block_length.rb +1 -1
  120. data/lib/rubocop/cop/metrics/class_length.rb +8 -3
  121. data/lib/rubocop/cop/metrics/method_length.rb +1 -1
  122. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -2
  123. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +32 -4
  124. data/lib/rubocop/cop/migration/department_name.rb +2 -2
  125. data/lib/rubocop/cop/mixin/allowed_receivers.rb +34 -0
  126. data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
  127. data/lib/rubocop/cop/mixin/comments_help.rb +19 -11
  128. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  129. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -1
  130. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +14 -11
  131. data/lib/rubocop/cop/mixin/heredoc.rb +6 -2
  132. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -2
  133. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
  134. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +6 -8
  135. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
  136. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  137. data/lib/rubocop/cop/mixin/string_help.rb +4 -2
  138. data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -1
  139. data/lib/rubocop/cop/naming/block_forwarding.rb +3 -3
  140. data/lib/rubocop/cop/naming/constant_name.rb +2 -3
  141. data/lib/rubocop/cop/naming/file_name.rb +1 -1
  142. data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +3 -1
  143. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +26 -11
  144. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +11 -3
  145. data/lib/rubocop/cop/naming/variable_name.rb +6 -1
  146. data/lib/rubocop/cop/style/access_modifier_declarations.rb +2 -2
  147. data/lib/rubocop/cop/style/accessor_grouping.rb +6 -2
  148. data/lib/rubocop/cop/style/alias.rb +9 -8
  149. data/lib/rubocop/cop/style/arguments_forwarding.rb +342 -63
  150. data/lib/rubocop/cop/style/array_first_last.rb +64 -0
  151. data/lib/rubocop/cop/style/array_intersect.rb +13 -5
  152. data/lib/rubocop/cop/style/attr.rb +11 -1
  153. data/lib/rubocop/cop/style/auto_resource_cleanup.rb +21 -14
  154. data/lib/rubocop/cop/style/begin_block.rb +1 -2
  155. data/lib/rubocop/cop/style/bisected_attr_accessor.rb +2 -2
  156. data/lib/rubocop/cop/style/block_comments.rb +1 -1
  157. data/lib/rubocop/cop/style/block_delimiters.rb +5 -4
  158. data/lib/rubocop/cop/style/case_like_if.rb +4 -4
  159. data/lib/rubocop/cop/style/class_and_module_children.rb +1 -1
  160. data/lib/rubocop/cop/style/class_check.rb +1 -0
  161. data/lib/rubocop/cop/style/class_equality_comparison.rb +24 -39
  162. data/lib/rubocop/cop/style/collection_compact.rb +22 -11
  163. data/lib/rubocop/cop/style/collection_methods.rb +2 -0
  164. data/lib/rubocop/cop/style/colon_method_call.rb +2 -2
  165. data/lib/rubocop/cop/style/combinable_loops.rb +36 -8
  166. data/lib/rubocop/cop/style/concat_array_literals.rb +2 -1
  167. data/lib/rubocop/cop/style/conditional_assignment.rb +6 -4
  168. data/lib/rubocop/cop/style/copyright.rb +5 -2
  169. data/lib/rubocop/cop/style/date_time.rb +5 -4
  170. data/lib/rubocop/cop/style/dir.rb +1 -1
  171. data/lib/rubocop/cop/style/dir_empty.rb +8 -14
  172. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +1 -1
  173. data/lib/rubocop/cop/style/documentation.rb +1 -1
  174. data/lib/rubocop/cop/style/each_with_object.rb +2 -2
  175. data/lib/rubocop/cop/style/empty_case_condition.rb +6 -1
  176. data/lib/rubocop/cop/style/empty_literal.rb +1 -1
  177. data/lib/rubocop/cop/style/eval_with_location.rb +8 -8
  178. data/lib/rubocop/cop/style/exact_regexp_match.rb +69 -0
  179. data/lib/rubocop/cop/style/explicit_block_argument.rb +2 -2
  180. data/lib/rubocop/cop/style/file_read.rb +2 -2
  181. data/lib/rubocop/cop/style/for.rb +1 -1
  182. data/lib/rubocop/cop/style/format_string.rb +24 -3
  183. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -1
  184. data/lib/rubocop/cop/style/guard_clause.rb +28 -0
  185. data/lib/rubocop/cop/style/hash_conversion.rb +10 -0
  186. data/lib/rubocop/cop/style/hash_each_methods.rb +84 -32
  187. data/lib/rubocop/cop/style/hash_except.rb +21 -9
  188. data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
  189. data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
  190. data/lib/rubocop/cop/style/identical_conditional_branches.rb +31 -5
  191. data/lib/rubocop/cop/style/if_inside_else.rb +6 -0
  192. data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -0
  193. data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -2
  194. data/lib/rubocop/cop/style/inverse_methods.rb +6 -5
  195. data/lib/rubocop/cop/style/invertible_unless_condition.rb +10 -6
  196. data/lib/rubocop/cop/style/lambda.rb +3 -3
  197. data/lib/rubocop/cop/style/lambda_call.rb +5 -0
  198. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +3 -2
  199. data/lib/rubocop/cop/style/map_to_hash.rb +10 -4
  200. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +12 -5
  201. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +1 -1
  202. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +20 -0
  203. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  204. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +2 -2
  205. data/lib/rubocop/cop/style/mixin_grouping.rb +1 -1
  206. data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
  207. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +1 -1
  208. data/lib/rubocop/cop/style/multiple_comparison.rb +14 -0
  209. data/lib/rubocop/cop/style/nested_ternary_operator.rb +3 -11
  210. data/lib/rubocop/cop/style/next.rb +1 -1
  211. data/lib/rubocop/cop/style/numeric_literals.rb +1 -1
  212. data/lib/rubocop/cop/style/open_struct_use.rb +1 -1
  213. data/lib/rubocop/cop/style/operator_method_call.rb +8 -2
  214. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  215. data/lib/rubocop/cop/style/preferred_hash_methods.rb +1 -1
  216. data/lib/rubocop/cop/style/redundant_argument.rb +9 -3
  217. data/lib/rubocop/cop/style/redundant_array_constructor.rb +77 -0
  218. data/lib/rubocop/cop/style/redundant_begin.rb +10 -2
  219. data/lib/rubocop/cop/style/redundant_conditional.rb +2 -10
  220. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +38 -0
  221. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +93 -5
  222. data/lib/rubocop/cop/style/redundant_exception.rb +32 -12
  223. data/lib/rubocop/cop/style/redundant_fetch_block.rb +3 -3
  224. data/lib/rubocop/cop/style/redundant_filter_chain.rb +118 -0
  225. data/lib/rubocop/cop/style/redundant_line_continuation.rb +9 -3
  226. data/lib/rubocop/cop/style/redundant_parentheses.rb +54 -21
  227. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +100 -0
  228. data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +46 -0
  229. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +2 -1
  230. data/lib/rubocop/cop/style/redundant_return.rb +8 -3
  231. data/lib/rubocop/cop/style/redundant_self.rb +17 -2
  232. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +8 -1
  233. data/lib/rubocop/cop/style/redundant_sort.rb +10 -9
  234. data/lib/rubocop/cop/style/redundant_sort_by.rb +2 -2
  235. data/lib/rubocop/cop/style/redundant_string_escape.rb +3 -1
  236. data/lib/rubocop/cop/style/regexp_literal.rb +11 -2
  237. data/lib/rubocop/cop/style/require_order.rb +11 -5
  238. data/lib/rubocop/cop/style/rescue_modifier.rb +1 -3
  239. data/lib/rubocop/cop/style/return_nil.rb +6 -2
  240. data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +95 -0
  241. data/lib/rubocop/cop/style/sample.rb +2 -1
  242. data/lib/rubocop/cop/style/select_by_regexp.rb +22 -11
  243. data/lib/rubocop/cop/style/self_assignment.rb +1 -1
  244. data/lib/rubocop/cop/style/semicolon.rb +20 -4
  245. data/lib/rubocop/cop/style/signal_exception.rb +1 -1
  246. data/lib/rubocop/cop/style/single_argument_dig.rb +7 -3
  247. data/lib/rubocop/cop/style/single_line_do_end_block.rb +67 -0
  248. data/lib/rubocop/cop/style/single_line_methods.rb +1 -1
  249. data/lib/rubocop/cop/style/slicing_with_range.rb +1 -1
  250. data/lib/rubocop/cop/style/sole_nested_conditional.rb +6 -2
  251. data/lib/rubocop/cop/style/special_global_vars.rb +3 -4
  252. data/lib/rubocop/cop/style/string_chars.rb +1 -0
  253. data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +30 -5
  254. data/lib/rubocop/cop/style/strip.rb +7 -4
  255. data/lib/rubocop/cop/style/super_with_args_parentheses.rb +35 -0
  256. data/lib/rubocop/cop/style/symbol_array.rb +35 -15
  257. data/lib/rubocop/cop/style/unpack_first.rb +11 -14
  258. data/lib/rubocop/cop/style/yaml_file_read.rb +66 -0
  259. data/lib/rubocop/cop/style/yoda_condition.rb +4 -2
  260. data/lib/rubocop/cop/style/yoda_expression.rb +8 -7
  261. data/lib/rubocop/cop/team.rb +1 -1
  262. data/lib/rubocop/cop/util.rb +1 -1
  263. data/lib/rubocop/cop/utils/regexp_ranges.rb +113 -0
  264. data/lib/rubocop/cop/variable_force/assignment.rb +45 -4
  265. data/lib/rubocop/cop/variable_force/variable_table.rb +2 -2
  266. data/lib/rubocop/cop/variable_force.rb +1 -0
  267. data/lib/rubocop/cops_documentation_generator.rb +1 -1
  268. data/lib/rubocop/ext/regexp_parser.rb +4 -1
  269. data/lib/rubocop/file_finder.rb +4 -7
  270. data/lib/rubocop/formatter/html_formatter.rb +5 -4
  271. data/lib/rubocop/formatter/junit_formatter.rb +1 -1
  272. data/lib/rubocop/lsp/logger.rb +22 -0
  273. data/lib/rubocop/lsp/routes.rb +246 -0
  274. data/lib/rubocop/lsp/runtime.rb +99 -0
  275. data/lib/rubocop/lsp/server.rb +68 -0
  276. data/lib/rubocop/lsp/severity.rb +27 -0
  277. data/lib/rubocop/magic_comment.rb +12 -10
  278. data/lib/rubocop/options.rb +11 -1
  279. data/lib/rubocop/result_cache.rb +5 -2
  280. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  281. data/lib/rubocop/rspec/shared_contexts.rb +2 -3
  282. data/lib/rubocop/runner.rb +6 -4
  283. data/lib/rubocop/server/cache.rb +1 -0
  284. data/lib/rubocop/server/client_command/exec.rb +3 -2
  285. data/lib/rubocop/string_interpreter.rb +3 -3
  286. data/lib/rubocop/target_finder.rb +7 -3
  287. data/lib/rubocop/target_ruby.rb +12 -7
  288. data/lib/rubocop/version.rb +10 -6
  289. data/lib/rubocop.rb +19 -0
  290. metadata +54 -15
@@ -15,6 +15,8 @@ module RuboCop
15
15
  'changed_parameters' => ChangedParameter,
16
16
  'changed_enforced_styles' => ChangedEnforcedStyles
17
17
  }.freeze
18
+ LOAD_RULES_CACHE = {} # rubocop:disable Style/MutableConstant
19
+ private_constant :LOAD_RULES_CACHE
18
20
 
19
21
  attr_reader :rules, :warnings
20
22
 
@@ -48,16 +50,17 @@ module RuboCop
48
50
  # Default rules for obsoletions are in config/obsoletion.yml
49
51
  # Additional rules files can be added with `RuboCop::ConfigObsoletion.files << filename`
50
52
  def load_rules # rubocop:disable Metrics/AbcSize
51
- rules = self.class.files.each_with_object({}) do |filename, hash|
52
- hash.merge!(YAML.safe_load(File.read(filename))) do |_key, first, second|
53
- case first
54
- when Hash
55
- first.merge(second)
56
- when Array
57
- first.concat(second)
53
+ rules = LOAD_RULES_CACHE[self.class.files] ||=
54
+ self.class.files.each_with_object({}) do |filename, hash|
55
+ hash.merge!(YAML.safe_load(File.read(filename))) do |_key, first, second|
56
+ case first
57
+ when Hash
58
+ first.merge(second)
59
+ when Array
60
+ first.concat(second)
61
+ end
58
62
  end
59
63
  end
60
- end
61
64
 
62
65
  cop_rules = rules.slice(*COP_RULE_CLASSES.keys)
63
66
  parameter_rules = rules.slice(*PARAMETER_RULE_CLASSES.keys)
@@ -68,11 +71,11 @@ module RuboCop
68
71
  # Cop rules are keyed by the name of the original cop
69
72
  def load_cop_rules(rules)
70
73
  rules.flat_map do |rule_type, data|
71
- data.map do |cop_name, configuration|
74
+ data.filter_map do |cop_name, configuration|
72
75
  next unless configuration # allow configurations to be disabled with `CopName: ~`
73
76
 
74
77
  COP_RULE_CLASSES[rule_type].new(@config, cop_name, configuration)
75
- end.compact
78
+ end
76
79
  end
77
80
  end
78
81
 
@@ -82,7 +82,9 @@ module RuboCop
82
82
  node.array_type? && node.percent_literal?
83
83
  end
84
84
 
85
- percent_array.map(&:source_range).find { |range| range.overlaps?(offense_range) }
85
+ percent_array.map(&:source_range).find do |range|
86
+ offense_range.begin_pos > range.begin_pos && range.overlaps?(offense_range)
87
+ end
86
88
  end
87
89
 
88
90
  def range_of_first_line(range)
@@ -53,7 +53,7 @@ module RuboCop
53
53
  # List of cops that should not try to autocorrect at the same
54
54
  # time as this cop
55
55
  #
56
- # @return [Array<RuboCop::Cop::Cop>]
56
+ # @return [Array<RuboCop::Cop::Base>]
57
57
  #
58
58
  # @api public
59
59
  def self.autocorrect_incompatible_with
@@ -284,7 +284,7 @@ module RuboCop
284
284
  # @api private
285
285
  def self.callbacks_needed
286
286
  @callbacks_needed ||= public_instance_methods.select do |m|
287
- m.match?(/^on_|^after_/) &&
287
+ m.start_with?(/on_|after_/) &&
288
288
  !Base.method_defined?(m) # exclude standard "callbacks" like 'on_begin_investigation'
289
289
  end
290
290
  end
@@ -305,6 +305,10 @@ module RuboCop
305
305
  @current_original = original
306
306
  end
307
307
 
308
+ def inspect # :nodoc:
309
+ "#<#{self.class.name}:#{object_id} @config=#{@config} @options=#{@options}>"
310
+ end
311
+
308
312
  private
309
313
 
310
314
  ### Reserved for Cop::Cop
@@ -4,6 +4,7 @@ module RuboCop
4
4
  module Cop
5
5
  module Bundler
6
6
  # A Gem's requirements should be listed only once in a Gemfile.
7
+ #
7
8
  # @example
8
9
  # # bad
9
10
  # gem 'rubocop'
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Bundler
6
+ # A Gem group, or a set of groups, should be listed only once in a Gemfile.
7
+ #
8
+ # For example, if the values of `source`, `git`, `platforms`, or `path`
9
+ # surrounding `group` are different, no offense will be registered:
10
+ #
11
+ # [source,ruby]
12
+ # -----
13
+ # platforms :ruby do
14
+ # group :default do
15
+ # gem 'openssl'
16
+ # end
17
+ # end
18
+ #
19
+ # platforms :jruby do
20
+ # group :default do
21
+ # gem 'jruby-openssl'
22
+ # end
23
+ # end
24
+ # -----
25
+ #
26
+ # @example
27
+ # # bad
28
+ # group :development do
29
+ # gem 'rubocop'
30
+ # end
31
+ #
32
+ # group :development do
33
+ # gem 'rubocop-rails'
34
+ # end
35
+ #
36
+ # # bad (same set of groups declared twice)
37
+ # group :development, :test do
38
+ # gem 'rubocop'
39
+ # end
40
+ #
41
+ # group :test, :development do
42
+ # gem 'rspec'
43
+ # end
44
+ #
45
+ # # good
46
+ # group :development do
47
+ # gem 'rubocop'
48
+ # end
49
+ #
50
+ # group :development, :test do
51
+ # gem 'rspec'
52
+ # end
53
+ #
54
+ # # good
55
+ # gem 'rubocop', groups: [:development, :test]
56
+ # gem 'rspec', groups: [:development, :test]
57
+ #
58
+ class DuplicatedGroup < Base
59
+ include RangeHelp
60
+
61
+ MSG = 'Gem group `%<group_name>s` already defined on line ' \
62
+ '%<line_of_first_occurrence>d of the Gemfile.'
63
+ SOURCE_BLOCK_NAMES = %i[source git platforms path].freeze
64
+
65
+ # @!method group_declarations(node)
66
+ def_node_search :group_declarations, '(send nil? :group ...)'
67
+
68
+ def on_new_investigation
69
+ return if processed_source.blank?
70
+
71
+ duplicated_group_nodes.each do |nodes|
72
+ nodes[1..].each do |node|
73
+ group_name = node.arguments.map(&:source).join(', ')
74
+
75
+ register_offense(node, group_name, nodes.first.first_line)
76
+ end
77
+ end
78
+ end
79
+
80
+ private
81
+
82
+ def duplicated_group_nodes
83
+ group_declarations = group_declarations(processed_source.ast)
84
+ group_keys = group_declarations.group_by do |node|
85
+ source_key = find_source_key(node)
86
+ group_attributes = group_attributes(node).sort.join
87
+
88
+ "#{source_key}#{group_attributes}"
89
+ end
90
+
91
+ group_keys.values.select { |nodes| nodes.size > 1 }
92
+ end
93
+
94
+ def register_offense(node, group_name, line_of_first_occurrence)
95
+ line_range = node.loc.column...node.loc.last_column
96
+ offense_location = source_range(processed_source.buffer, node.first_line, line_range)
97
+ message = format(
98
+ MSG,
99
+ group_name: group_name,
100
+ line_of_first_occurrence: line_of_first_occurrence
101
+ )
102
+ add_offense(offense_location, message: message)
103
+ end
104
+
105
+ def find_source_key(node)
106
+ source_block = node.each_ancestor(:block).find do |block_node|
107
+ SOURCE_BLOCK_NAMES.include?(block_node.method_name)
108
+ end
109
+
110
+ return unless source_block
111
+
112
+ "#{source_block.method_name}#{source_block.send_node.first_argument&.source}"
113
+ end
114
+
115
+ def group_attributes(node)
116
+ node.arguments.map do |argument|
117
+ if argument.hash_type?
118
+ argument.pairs.map(&:source).sort.join(', ')
119
+ else
120
+ argument.respond_to?(:value) ? argument.value.to_s : argument.source
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
@@ -150,7 +150,7 @@ module RuboCop
150
150
  # Version specifications that restrict all updates going forward. This excludes versions
151
151
  # like ">= 1.0" or "!= 2.0.3".
152
152
  def restrictive_version_specified_gem?(node)
153
- return unless version_specified_gem?(node)
153
+ return false unless version_specified_gem?(node)
154
154
 
155
155
  node.arguments[1..]
156
156
  .any? { |arg| arg&.str_type? && RESTRICTIVE_VERSION_PATTERN.match?(arg.value) }
@@ -161,9 +161,9 @@ module RuboCop
161
161
  end
162
162
 
163
163
  def gem_options(node)
164
- return [] unless node.arguments.last&.type == :hash
164
+ return [] unless node.last_argument&.type == :hash
165
165
 
166
- node.arguments.last.keys.map(&:value)
166
+ node.last_argument.keys.map(&:value)
167
167
  end
168
168
  end
169
169
  end
@@ -105,13 +105,13 @@ module RuboCop
105
105
  end
106
106
 
107
107
  def required_offense?(node)
108
- return unless required_style?
108
+ return false unless required_style?
109
109
 
110
110
  !includes_version_specification?(node) && !includes_commit_reference?(node)
111
111
  end
112
112
 
113
113
  def forbidden_offense?(node)
114
- return unless forbidden_style?
114
+ return false unless forbidden_style?
115
115
 
116
116
  includes_version_specification?(node) || includes_commit_reference?(node)
117
117
  end
@@ -19,7 +19,15 @@ module RuboCop
19
19
  #
20
20
  # gem 'rspec'
21
21
  #
22
- # # good only if TreatCommentsAsGroupSeparators is true
22
+ # @example TreatCommentsAsGroupSeparators: true (default)
23
+ # # good
24
+ # # For code quality
25
+ # gem 'rubocop'
26
+ # # For tests
27
+ # gem 'rspec'
28
+ #
29
+ # @example TreatCommentsAsGroupSeparators: false
30
+ # # bad
23
31
  # # For code quality
24
32
  # gem 'rubocop'
25
33
  # # For tests
@@ -54,7 +54,7 @@ module RuboCop
54
54
  def inside_string_ranges(node)
55
55
  return [] unless node.is_a?(Parser::AST::Node)
56
56
 
57
- node.each_node(:str, :dstr, :xstr).map { |n| inside_string_range(n) }.compact
57
+ node.each_node(:str, :dstr, :xstr).filter_map { |n| inside_string_range(n) }
58
58
  end
59
59
 
60
60
  def inside_string_range(node)
@@ -14,12 +14,15 @@ module RuboCop
14
14
  # Check for unparenthesized args' preceding and trailing whitespaces.
15
15
  remove_unparenthesized_whitespace(corrector)
16
16
 
17
- # Avoid correcting to `lambdado` by inserting whitespace
18
- # if none exists before or after the lambda arguments.
19
- insert_separating_space(corrector)
17
+ if block_node.block_type?
18
+ # Avoid correcting to `lambdado` by inserting whitespace
19
+ # if none exists before or after the lambda arguments.
20
+ insert_separating_space(corrector)
21
+
22
+ remove_arguments(corrector)
23
+ end
20
24
 
21
25
  replace_selector(corrector)
22
- remove_arguments(corrector)
23
26
 
24
27
  replace_delimiters(corrector)
25
28
 
@@ -126,13 +126,13 @@ module RuboCop
126
126
  end
127
127
 
128
128
  def required_offense?(node)
129
- return unless required_style?
129
+ return false unless required_style?
130
130
 
131
131
  !includes_version_specification?(node) && !includes_commit_reference?(node)
132
132
  end
133
133
 
134
134
  def forbidden_offense?(node)
135
- return unless forbidden_style?
135
+ return false unless forbidden_style?
136
136
 
137
137
  includes_version_specification?(node) || includes_commit_reference?(node)
138
138
  end
@@ -43,7 +43,7 @@ module RuboCop
43
43
  def on_block(block_node)
44
44
  return unless gem_specification(block_node)
45
45
 
46
- block_parameter = block_node.arguments.first.source
46
+ block_parameter = block_node.first_argument.source
47
47
 
48
48
  assignment = block_node.descendants.detect do |node|
49
49
  use_deprecated_attributes?(node, block_parameter)
@@ -65,7 +65,7 @@ module RuboCop
65
65
  lhs, _op, _rhs = *node
66
66
  [lhs, attribute]
67
67
  else
68
- [node, "#{attribute}=".to_sym]
68
+ [node, :"#{attribute}="]
69
69
  end
70
70
  end
71
71
 
@@ -75,7 +75,7 @@ module RuboCop
75
75
 
76
76
  # @!method add_development_dependency?(node)
77
77
  def_node_matcher :add_development_dependency?, <<~PATTERN
78
- (send _ :add_development_dependency (str #forbidden_gem? ...))
78
+ (send _ :add_development_dependency (str #forbidden_gem? ...) _? _?)
79
79
  PATTERN
80
80
 
81
81
  # @!method gem?(node)
@@ -45,7 +45,15 @@ module RuboCop
45
45
  #
46
46
  # spec.add_runtime_dependency 'rspec'
47
47
  #
48
- # # good only if TreatCommentsAsGroupSeparators is true
48
+ # @example TreatCommentsAsGroupSeparators: true (default)
49
+ # # good
50
+ # # For code quality
51
+ # spec.add_dependency 'rubocop'
52
+ # # For tests
53
+ # spec.add_dependency 'rspec'
54
+ #
55
+ # @example TreatCommentsAsGroupSeparators: false
56
+ # # bad
49
57
  # # For code quality
50
58
  # spec.add_dependency 'rubocop'
51
59
  # # For tests
@@ -67,7 +67,7 @@ module RuboCop
67
67
 
68
68
  def require_path
69
69
  path = source_path.relative_path_from(root_file_path.dirname)
70
- path.to_s.sub('.rb', '')
70
+ path.to_s.delete_suffix('.rb')
71
71
  end
72
72
  end
73
73
  end
@@ -12,6 +12,13 @@ module RuboCop
12
12
  # ....
13
13
  # end
14
14
  #
15
+ # # bad
16
+ # #
17
+ # # Checks ...
18
+ # class SomeCop < Base
19
+ # ...
20
+ # end
21
+ #
15
22
  # # good
16
23
  # # Checks ...
17
24
  # class SomeCop < Base
@@ -21,27 +28,47 @@ module RuboCop
21
28
  class CopDescription < Base
22
29
  extend AutoCorrector
23
30
 
24
- MSG = 'Description should be started with %<suggestion>s instead of `This cop ...`.'
31
+ MSG_STARTS_WITH_WRONG_WORD =
32
+ 'Description should be started with %<suggestion>s instead of `This cop ...`.'
33
+ MSG_STARTS_WITH_EMPTY_COMMENT_LINE =
34
+ 'Description should not start with an empty comment line.'
25
35
 
26
36
  SPECIAL_WORDS = %w[is can could should will would must may].freeze
27
37
  COP_DESC_OFFENSE_REGEX =
28
38
  /^\s+# This cop (?<special>#{SPECIAL_WORDS.join('|')})?\s*(?<word>.+?) .*/.freeze
29
39
  REPLACEMENT_REGEX = /^\s+# This cop (#{SPECIAL_WORDS.join('|')})?\s*(.+?) /.freeze
40
+ EMPTY_COMMENT_LINE_REGEX = /\A\s*#\s*\n\z/.freeze
30
41
 
31
- # rubocop:disable Metrics/CyclomaticComplexity
32
42
  def on_class(node)
33
43
  return unless (module_node = node.parent) && node.parent_class
34
44
 
35
45
  description_beginning = first_comment_line(module_node)
36
46
  return unless description_beginning
37
47
 
38
- start_with_subject = description_beginning.match(COP_DESC_OFFENSE_REGEX)
39
- return unless start_with_subject
48
+ if description_beginning.match?(EMPTY_COMMENT_LINE_REGEX)
49
+ register_offense_for_empty_comment_line(module_node, description_beginning)
50
+ else
51
+ start_with_subject = description_beginning.match(COP_DESC_OFFENSE_REGEX)
52
+ return unless start_with_subject
53
+
54
+ register_offense_for_wrong_word(module_node, description_beginning, start_with_subject)
55
+ end
56
+ end
57
+
58
+ private
40
59
 
60
+ def register_offense_for_empty_comment_line(module_node, description_beginning)
61
+ range = range(module_node, description_beginning)
62
+ add_offense(range, message: MSG_STARTS_WITH_EMPTY_COMMENT_LINE) do |corrector|
63
+ corrector.remove(range)
64
+ end
65
+ end
66
+
67
+ def register_offense_for_wrong_word(module_node, description_beginning, start_with_subject)
41
68
  suggestion = start_with_subject['word']&.capitalize
42
69
  range = range(module_node, description_beginning)
43
70
  suggestion_for_message = suggestion_for_message(suggestion, start_with_subject)
44
- message = format(MSG, suggestion: suggestion_for_message)
71
+ message = format(MSG_STARTS_WITH_WRONG_WORD, suggestion: suggestion_for_message)
45
72
 
46
73
  add_offense(range, message: message) do |corrector|
47
74
  if suggestion && !start_with_subject['special']
@@ -49,9 +76,6 @@ module RuboCop
49
76
  end
50
77
  end
51
78
  end
52
- # rubocop:enable Metrics/CyclomaticComplexity
53
-
54
- private
55
79
 
56
80
  def replace_with_suggestion(corrector, range, suggestion, description_beginning)
57
81
  replacement = description_beginning.gsub(REPLACEMENT_REGEX, "#{suggestion} ")
@@ -26,9 +26,7 @@ module RuboCop
26
26
  # expect_no_offenses('...')
27
27
  # end
28
28
  class ExampleDescription < Base
29
- class << self
30
- attr_accessor :descriptions
31
- end
29
+ extend AutoCorrector
32
30
 
33
31
  MSG = 'Description does not match use of `%<method_name>s`.'
34
32
 
@@ -39,21 +37,31 @@ module RuboCop
39
37
  expect_no_corrections
40
38
  ].to_set.freeze
41
39
 
42
- EXPECT_NO_OFFENSES_INCORRECT_DESCRIPTIONS = [
43
- /^(adds|registers|reports|finds) (an? )?offense/,
44
- /^(flags|handles|works)\b/
45
- ].freeze
40
+ EXPECT_NO_OFFENSES_DESCRIPTION_MAPPING = {
41
+ /\A(adds|registers|reports|finds) (an? )?offense/ => 'does not register an offense',
42
+ /\A(flags|handles|works)\b/ => 'does not register'
43
+ }.freeze
44
+
45
+ EXPECT_OFFENSE_DESCRIPTION_MAPPING = {
46
+ /\A(does not|doesn't) (register|find|flag|report)/ => 'registers',
47
+ /\A(does not|doesn't) add (a|an|any )?offense/ => 'registers an offense',
48
+ /\Aaccepts\b/ => 'registers'
49
+ }.freeze
46
50
 
47
- EXPECT_OFFENSE_INCORRECT_DESCRIPTIONS = [
48
- /^(does not|doesn't) (register|find|flag|report)/,
49
- /^(does not|doesn't) add (a|an|any )?offense/
50
- ].freeze
51
+ EXPECT_NO_CORRECTIONS_DESCRIPTION_MAPPING = {
52
+ /\A(auto[- ]?)?correct/ => 'does not correct'
53
+ }.freeze
51
54
 
52
- EXPECT_NO_CORRECTIONS_INCORRECT_DESCRIPTIONS = [/^(auto[- ]?)?correct/].freeze
55
+ EXPECT_CORRECTION_DESCRIPTION_MAPPING = {
56
+ /\b(does not|doesn't) (auto[- ]?)?correct/ => 'autocorrects'
57
+ }.freeze
53
58
 
54
- EXPECT_CORRECTION_INCORRECT_DESCRIPTIONS = [
55
- /\b(does not|doesn't) (auto[- ]?)?correct/
56
- ].freeze
59
+ EXAMPLE_DESCRIPTION_MAPPING = {
60
+ expect_no_offenses: EXPECT_NO_OFFENSES_DESCRIPTION_MAPPING,
61
+ expect_offense: EXPECT_OFFENSE_DESCRIPTION_MAPPING,
62
+ expect_no_corrections: EXPECT_NO_CORRECTIONS_DESCRIPTION_MAPPING,
63
+ expect_correction: EXPECT_CORRECTION_DESCRIPTION_MAPPING
64
+ }.freeze
57
65
 
58
66
  # @!method offense_example?(node)
59
67
  def_node_matcher :offense_example?, <<~PATTERN
@@ -66,21 +74,34 @@ module RuboCop
66
74
 
67
75
  def on_send(node)
68
76
  parent = node.each_ancestor(:block).first
69
- return unless parent && (description = offense_example?(parent))
77
+ return unless parent && (current_description = offense_example?(parent))
70
78
 
71
79
  method_name = node.method_name
72
80
  message = format(MSG, method_name: method_name)
73
81
 
74
- regexp_group = self.class.const_get("#{method_name}_incorrect_descriptions".upcase)
75
- check_description(description, regexp_group, message)
82
+ description_map = EXAMPLE_DESCRIPTION_MAPPING[method_name]
83
+ check_description(current_description, description_map, message)
76
84
  end
77
85
 
78
86
  private
79
87
 
80
- def check_description(description, regexps, message)
81
- return unless regexps.any? { |regexp| regexp.match?(string_contents(description)) }
88
+ def check_description(current_description, description_map, message)
89
+ description_text = string_contents(current_description)
90
+ return unless (new_description = correct_description(description_text, description_map))
91
+
92
+ add_offense(current_description, message: message) do |corrector|
93
+ corrector.replace(current_description, "'#{new_description}'")
94
+ end
95
+ end
96
+
97
+ def correct_description(current_description, description_map)
98
+ description_map.each do |incorrect_description_pattern, preferred_description|
99
+ if incorrect_description_pattern.match?(current_description)
100
+ return current_description.gsub(incorrect_description_pattern, preferred_description)
101
+ end
102
+ end
82
103
 
83
- add_offense(description, message: message)
104
+ nil
84
105
  end
85
106
 
86
107
  def string_contents(node)
@@ -51,7 +51,9 @@ module RuboCop
51
51
 
52
52
  def extract_receiver(node)
53
53
  receiver = node.receiver
54
- receiver = receiver.receiver if receiver.method?(:loc) || receiver.method?(:source_range)
54
+ if receiver.send_type? && (receiver.method?(:loc) || receiver.method?(:source_range))
55
+ receiver = receiver.receiver
56
+ end
55
57
  receiver.source
56
58
  end
57
59
  end
@@ -12,38 +12,37 @@ module RuboCop
12
12
  # # good
13
13
  # node.method?(:do_something)
14
14
  #
15
+ # # bad
16
+ # node.method_name != :do_something
17
+ #
18
+ # # good
19
+ # !node.method?(:do_something)
20
+ #
15
21
  class MethodNameEqual < Base
16
- include RangeHelp
17
22
  extend AutoCorrector
18
23
 
19
- MSG = 'Use `method?(%<method_name>s)` instead of `method_name == %<method_name>s`.'
20
- RESTRICT_ON_SEND = %i[==].freeze
24
+ MSG = 'Use `%<prefer>s` instead.'
25
+ RESTRICT_ON_SEND = %i[== !=].freeze
21
26
 
22
- # @!method method_name?(node)
23
- def_node_matcher :method_name?, <<~PATTERN
27
+ # @!method method_name(node)
28
+ def_node_matcher :method_name, <<~PATTERN
24
29
  (send
25
- $(send
26
- (...) :method_name) :==
27
- $...)
30
+ (send
31
+ (...) :method_name) {:== :!=}
32
+ $_)
28
33
  PATTERN
29
34
 
30
35
  def on_send(node)
31
- method_name?(node) do |method_name_node, method_name_arg|
32
- message = format(MSG, method_name: method_name_arg.first.source)
36
+ method_name(node) do |method_name_arg|
37
+ bang = node.method?(:!=) ? '!' : ''
38
+ prefer = "#{bang}#{node.receiver.receiver.source}.method?(#{method_name_arg.source})"
39
+ message = format(MSG, prefer: prefer)
33
40
 
34
- range = range(method_name_node, node)
35
-
36
- add_offense(range, message: message) do |corrector|
37
- corrector.replace(range, "method?(#{method_name_arg.first.source})")
41
+ add_offense(node, message: message) do |corrector|
42
+ corrector.replace(node, prefer)
38
43
  end
39
44
  end
40
45
  end
41
-
42
- private
43
-
44
- def range(method_name_node, node)
45
- range_between(method_name_node.loc.selector.begin_pos, node.source_range.end_pos)
46
- end
47
46
  end
48
47
  end
49
48
  end