rubocop 1.31.1 → 1.51.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 (462) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +5 -5
  4. data/config/default.yml +342 -52
  5. data/config/obsoletion.yml +23 -1
  6. data/exe/rubocop +1 -1
  7. data/lib/rubocop/arguments_env.rb +17 -0
  8. data/lib/rubocop/arguments_file.rb +17 -0
  9. data/lib/rubocop/cache_config.rb +29 -0
  10. data/lib/rubocop/cli/command/{auto_genenerate_config.rb → auto_generate_config.rb} +9 -2
  11. data/lib/rubocop/cli/command/execute_runner.rb +14 -9
  12. data/lib/rubocop/cli/command/init_dotfile.rb +1 -1
  13. data/lib/rubocop/cli/command/suggest_extensions.rb +61 -16
  14. data/lib/rubocop/cli.rb +56 -9
  15. data/lib/rubocop/comment_config.rb +60 -1
  16. data/lib/rubocop/config.rb +48 -20
  17. data/lib/rubocop/config_finder.rb +68 -0
  18. data/lib/rubocop/config_loader.rb +46 -68
  19. data/lib/rubocop/config_loader_resolver.rb +11 -12
  20. data/lib/rubocop/config_obsoletion/changed_parameter.rb +5 -0
  21. data/lib/rubocop/config_obsoletion/parameter_rule.rb +4 -0
  22. data/lib/rubocop/config_obsoletion.rb +9 -4
  23. data/lib/rubocop/config_validator.rb +1 -1
  24. data/lib/rubocop/cop/autocorrect_logic.rb +29 -13
  25. data/lib/rubocop/cop/badge.rb +9 -4
  26. data/lib/rubocop/cop/base.rb +115 -83
  27. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
  28. data/lib/rubocop/cop/commissioner.rb +19 -6
  29. data/lib/rubocop/cop/cop.rb +54 -34
  30. data/lib/rubocop/cop/corrector.rb +31 -11
  31. data/lib/rubocop/cop/correctors/alignment_corrector.rb +3 -3
  32. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +3 -3
  33. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +3 -3
  34. data/lib/rubocop/cop/correctors/line_break_corrector.rb +1 -1
  35. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +23 -7
  36. data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +2 -7
  37. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +58 -0
  38. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
  39. data/lib/rubocop/cop/gemspec/dependency_version.rb +17 -19
  40. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +1 -1
  41. data/lib/rubocop/cop/gemspec/development_dependencies.rb +107 -0
  42. data/lib/rubocop/cop/gemspec/require_mfa.rb +1 -1
  43. data/lib/rubocop/cop/generator/require_file_injector.rb +2 -2
  44. data/lib/rubocop/cop/generator.rb +5 -2
  45. data/lib/rubocop/cop/internal_affairs/cop_description.rb +8 -6
  46. data/lib/rubocop/cop/internal_affairs/create_empty_file.rb +37 -0
  47. data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +111 -0
  48. data/lib/rubocop/cop/internal_affairs/inherit_deprecated_cop_class.rb +1 -1
  49. data/lib/rubocop/cop/internal_affairs/lambda_or_proc.rb +46 -0
  50. data/lib/rubocop/cop/internal_affairs/location_expression.rb +37 -0
  51. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +3 -3
  52. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +1 -1
  53. data/lib/rubocop/cop/internal_affairs/numblock_handler.rb +69 -0
  54. data/lib/rubocop/cop/internal_affairs/processed_source_buffer_name.rb +42 -0
  55. data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +11 -3
  56. data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +1 -1
  57. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +1 -1
  58. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +66 -0
  59. data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +62 -0
  60. data/lib/rubocop/cop/internal_affairs/useless_restrict_on_send.rb +60 -0
  61. data/lib/rubocop/cop/internal_affairs.rb +9 -0
  62. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  63. data/lib/rubocop/cop/layout/block_alignment.rb +16 -12
  64. data/lib/rubocop/cop/layout/block_end_newline.rb +31 -9
  65. data/lib/rubocop/cop/layout/class_structure.rb +37 -27
  66. data/lib/rubocop/cop/layout/closing_heredoc_indentation.rb +1 -1
  67. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +2 -6
  68. data/lib/rubocop/cop/layout/comment_indentation.rb +3 -1
  69. data/lib/rubocop/cop/layout/empty_comment.rb +3 -3
  70. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +1 -1
  71. data/lib/rubocop/cop/layout/empty_lines.rb +3 -1
  72. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +7 -2
  73. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +2 -0
  74. data/lib/rubocop/cop/layout/end_alignment.rb +9 -1
  75. data/lib/rubocop/cop/layout/end_of_line.rb +4 -4
  76. data/lib/rubocop/cop/layout/extra_spacing.rb +15 -6
  77. data/lib/rubocop/cop/layout/first_argument_indentation.rb +15 -4
  78. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +6 -5
  79. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +35 -8
  80. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +5 -5
  81. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +36 -1
  82. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +57 -8
  83. data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +52 -19
  84. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +10 -4
  85. data/lib/rubocop/cop/layout/heredoc_indentation.rb +8 -11
  86. data/lib/rubocop/cop/layout/indentation_style.rb +7 -2
  87. data/lib/rubocop/cop/layout/indentation_width.rb +6 -2
  88. data/lib/rubocop/cop/layout/initial_indentation.rb +1 -1
  89. data/lib/rubocop/cop/layout/leading_comment_space.rb +1 -1
  90. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +80 -12
  91. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +18 -8
  92. data/lib/rubocop/cop/layout/line_length.rb +8 -1
  93. data/lib/rubocop/cop/layout/multiline_array_line_breaks.rb +31 -1
  94. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -1
  95. data/lib/rubocop/cop/layout/multiline_block_layout.rb +3 -1
  96. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +29 -1
  97. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +39 -2
  98. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +77 -0
  99. data/lib/rubocop/cop/layout/redundant_line_break.rb +9 -10
  100. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +2 -2
  101. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
  102. data/lib/rubocop/cop/layout/space_around_keyword.rb +3 -3
  103. data/lib/rubocop/cop/layout/space_around_operators.rb +1 -1
  104. data/lib/rubocop/cop/layout/space_before_block_braces.rb +2 -0
  105. data/lib/rubocop/cop/layout/space_before_first_arg.rb +1 -1
  106. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +2 -2
  107. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +22 -20
  108. data/lib/rubocop/cop/layout/space_inside_array_percent_literal.rb +3 -0
  109. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +27 -9
  110. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +30 -3
  111. data/lib/rubocop/cop/layout/space_inside_parens.rb +2 -2
  112. data/lib/rubocop/cop/layout/space_inside_percent_literal_delimiters.rb +34 -0
  113. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +10 -6
  114. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +5 -4
  115. data/lib/rubocop/cop/layout/trailing_empty_lines.rb +1 -1
  116. data/lib/rubocop/cop/layout/trailing_whitespace.rb +12 -5
  117. data/lib/rubocop/cop/legacy/corrections_proxy.rb +1 -1
  118. data/lib/rubocop/cop/legacy/corrector.rb +1 -1
  119. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +39 -8
  120. data/lib/rubocop/cop/lint/ambiguous_operator.rb +4 -0
  121. data/lib/rubocop/cop/lint/assignment_in_condition.rb +11 -1
  122. data/lib/rubocop/cop/lint/constant_resolution.rb +5 -1
  123. data/lib/rubocop/cop/lint/debugger.rb +27 -31
  124. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +66 -110
  125. data/lib/rubocop/cop/lint/deprecated_constants.rb +8 -1
  126. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +1 -1
  127. data/lib/rubocop/cop/lint/duplicate_branch.rb +0 -2
  128. data/lib/rubocop/cop/lint/duplicate_magic_comment.rb +73 -0
  129. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +122 -0
  130. data/lib/rubocop/cop/lint/duplicate_methods.rb +48 -18
  131. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +26 -9
  132. data/lib/rubocop/cop/lint/duplicate_require.rb +1 -1
  133. data/lib/rubocop/cop/lint/else_layout.rb +3 -7
  134. data/lib/rubocop/cop/lint/empty_block.rb +3 -7
  135. data/lib/rubocop/cop/lint/empty_class.rb +3 -1
  136. data/lib/rubocop/cop/lint/empty_conditional_body.rb +110 -2
  137. data/lib/rubocop/cop/lint/empty_interpolation.rb +1 -1
  138. data/lib/rubocop/cop/lint/erb_new_arguments.rb +11 -11
  139. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +14 -7
  140. data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +15 -17
  141. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
  142. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -2
  143. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -1
  144. data/lib/rubocop/cop/lint/interpolation_check.rb +4 -3
  145. data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
  146. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +48 -2
  147. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +18 -3
  148. data/lib/rubocop/cop/lint/missing_super.rb +31 -2
  149. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -0
  150. data/lib/rubocop/cop/lint/nested_method_definition.rb +53 -9
  151. data/lib/rubocop/cop/lint/next_without_accumulator.rb +25 -6
  152. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +68 -28
  153. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +12 -0
  154. data/lib/rubocop/cop/lint/number_conversion.rb +28 -6
  155. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +2 -2
  156. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +2 -0
  157. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +4 -5
  158. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +17 -2
  159. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +5 -0
  160. data/lib/rubocop/cop/lint/percent_string_array.rb +1 -1
  161. data/lib/rubocop/cop/lint/percent_symbol_array.rb +1 -1
  162. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +49 -9
  163. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +6 -6
  164. data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +7 -0
  165. data/lib/rubocop/cop/lint/redundant_require_statement.rb +48 -10
  166. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +13 -0
  167. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +1 -1
  168. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +35 -15
  169. data/lib/rubocop/cop/lint/redundant_with_index.rb +14 -11
  170. data/lib/rubocop/cop/lint/redundant_with_object.rb +13 -12
  171. data/lib/rubocop/cop/lint/refinement_import_methods.rb +2 -1
  172. data/lib/rubocop/cop/lint/regexp_as_condition.rb +6 -0
  173. data/lib/rubocop/cop/lint/require_parentheses.rb +3 -1
  174. data/lib/rubocop/cop/lint/require_range_parentheses.rb +57 -0
  175. data/lib/rubocop/cop/lint/rescue_type.rb +3 -3
  176. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +41 -8
  177. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +1 -1
  178. data/lib/rubocop/cop/lint/script_permission.rb +1 -1
  179. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +5 -4
  180. data/lib/rubocop/cop/lint/shadowed_exception.rb +16 -11
  181. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +28 -3
  182. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  183. data/lib/rubocop/cop/lint/syntax.rb +4 -0
  184. data/lib/rubocop/cop/lint/to_enum_arguments.rb +13 -3
  185. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +23 -9
  186. data/lib/rubocop/cop/lint/unreachable_loop.rb +12 -6
  187. data/lib/rubocop/cop/lint/unused_method_argument.rb +6 -1
  188. data/lib/rubocop/cop/lint/useless_access_modifier.rb +17 -12
  189. data/lib/rubocop/cop/lint/useless_assignment.rb +56 -1
  190. data/lib/rubocop/cop/lint/useless_method_definition.rb +12 -4
  191. data/lib/rubocop/cop/lint/useless_rescue.rb +89 -0
  192. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +15 -5
  193. data/lib/rubocop/cop/lint/useless_times.rb +1 -1
  194. data/lib/rubocop/cop/lint/void.rb +92 -21
  195. data/lib/rubocop/cop/metrics/abc_size.rb +4 -2
  196. data/lib/rubocop/cop/metrics/block_length.rb +16 -11
  197. data/lib/rubocop/cop/metrics/block_nesting.rb +2 -2
  198. data/lib/rubocop/cop/metrics/class_length.rb +11 -5
  199. data/lib/rubocop/cop/metrics/collection_literal_length.rb +76 -0
  200. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
  201. data/lib/rubocop/cop/metrics/method_length.rb +17 -11
  202. data/lib/rubocop/cop/metrics/module_length.rb +10 -5
  203. data/lib/rubocop/cop/metrics/parameter_lists.rb +27 -0
  204. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  205. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +3 -6
  206. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +9 -6
  207. data/lib/rubocop/cop/migration/department_name.rb +1 -1
  208. data/lib/rubocop/cop/mixin/alignment.rb +2 -2
  209. data/lib/rubocop/cop/mixin/allowed_identifiers.rb +2 -2
  210. data/lib/rubocop/cop/mixin/allowed_methods.rb +23 -2
  211. data/lib/rubocop/cop/mixin/allowed_pattern.rb +17 -1
  212. data/lib/rubocop/cop/mixin/annotation_comment.rb +14 -7
  213. data/lib/rubocop/cop/mixin/check_line_breakable.rb +5 -1
  214. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  215. data/lib/rubocop/cop/mixin/comments_help.rb +29 -7
  216. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +21 -9
  217. data/lib/rubocop/cop/mixin/def_node.rb +2 -7
  218. data/lib/rubocop/cop/mixin/documentation_comment.rb +1 -1
  219. data/lib/rubocop/cop/mixin/enforce_superclass.rb +2 -1
  220. data/lib/rubocop/cop/mixin/first_element_line_break.rb +11 -7
  221. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +4 -0
  222. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +1 -1
  223. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +152 -12
  224. data/lib/rubocop/cop/mixin/hash_transform_method.rb +13 -9
  225. data/lib/rubocop/cop/mixin/line_length_help.rb +11 -2
  226. data/lib/rubocop/cop/mixin/method_complexity.rb +13 -16
  227. data/lib/rubocop/cop/mixin/min_branches_count.rb +40 -0
  228. data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +7 -14
  229. data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +5 -6
  230. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
  231. data/lib/rubocop/cop/mixin/percent_array.rb +58 -1
  232. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +1 -1
  233. data/lib/rubocop/cop/mixin/range_help.rb +22 -5
  234. data/lib/rubocop/cop/mixin/require_library.rb +2 -0
  235. data/lib/rubocop/cop/mixin/rescue_node.rb +5 -3
  236. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
  237. data/lib/rubocop/cop/mixin/statement_modifier.rb +18 -3
  238. data/lib/rubocop/cop/mixin/surrounding_space.rb +13 -11
  239. data/lib/rubocop/cop/mixin/trailing_comma.rb +2 -2
  240. data/lib/rubocop/cop/mixin/visibility_help.rb +40 -5
  241. data/lib/rubocop/cop/naming/ascii_identifiers.rb +1 -1
  242. data/lib/rubocop/cop/naming/block_forwarding.rb +5 -1
  243. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  244. data/lib/rubocop/cop/naming/class_and_module_camel_case.rb +3 -1
  245. data/lib/rubocop/cop/naming/constant_name.rb +3 -3
  246. data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +1 -1
  247. data/lib/rubocop/cop/naming/inclusive_language.rb +28 -6
  248. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +22 -7
  249. data/lib/rubocop/cop/naming/method_name.rb +3 -3
  250. data/lib/rubocop/cop/naming/predicate_name.rb +31 -2
  251. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +12 -4
  252. data/lib/rubocop/cop/registry.rb +73 -45
  253. data/lib/rubocop/cop/security/compound_hash.rb +2 -1
  254. data/lib/rubocop/cop/style/access_modifier_declarations.rb +92 -3
  255. data/lib/rubocop/cop/style/accessor_grouping.rb +46 -20
  256. data/lib/rubocop/cop/style/alias.rb +9 -1
  257. data/lib/rubocop/cop/style/arguments_forwarding.rb +6 -5
  258. data/lib/rubocop/cop/style/array_intersect.rb +111 -0
  259. data/lib/rubocop/cop/style/ascii_comments.rb +1 -1
  260. data/lib/rubocop/cop/style/attr.rb +11 -1
  261. data/lib/rubocop/cop/style/bisected_attr_accessor.rb +1 -1
  262. data/lib/rubocop/cop/style/block_comments.rb +2 -2
  263. data/lib/rubocop/cop/style/block_delimiters.rb +44 -10
  264. data/lib/rubocop/cop/style/case_equality.rb +40 -10
  265. data/lib/rubocop/cop/style/case_like_if.rb +20 -3
  266. data/lib/rubocop/cop/style/character_literal.rb +1 -1
  267. data/lib/rubocop/cop/style/class_and_module_children.rb +8 -15
  268. data/lib/rubocop/cop/style/class_equality_comparison.rb +94 -12
  269. data/lib/rubocop/cop/style/class_methods_definitions.rb +2 -1
  270. data/lib/rubocop/cop/style/collection_compact.rb +21 -5
  271. data/lib/rubocop/cop/style/collection_methods.rb +2 -0
  272. data/lib/rubocop/cop/style/colon_method_call.rb +2 -2
  273. data/lib/rubocop/cop/style/combinable_loops.rb +29 -7
  274. data/lib/rubocop/cop/style/command_literal.rb +1 -1
  275. data/lib/rubocop/cop/style/comment_annotation.rb +1 -1
  276. data/lib/rubocop/cop/style/commented_keyword.rb +2 -2
  277. data/lib/rubocop/cop/style/comparable_clamp.rb +125 -0
  278. data/lib/rubocop/cop/style/concat_array_literals.rb +94 -0
  279. data/lib/rubocop/cop/style/conditional_assignment.rb +8 -14
  280. data/lib/rubocop/cop/style/copyright.rb +6 -3
  281. data/lib/rubocop/cop/style/data_inheritance.rb +75 -0
  282. data/lib/rubocop/cop/style/dir_empty.rb +60 -0
  283. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +2 -2
  284. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +2 -2
  285. data/lib/rubocop/cop/style/documentation.rb +22 -10
  286. data/lib/rubocop/cop/style/documentation_method.rb +10 -4
  287. data/lib/rubocop/cop/style/double_negation.rb +4 -2
  288. data/lib/rubocop/cop/style/each_for_simple_loop.rb +41 -6
  289. data/lib/rubocop/cop/style/each_with_object.rb +40 -9
  290. data/lib/rubocop/cop/style/empty_block_parameter.rb +2 -2
  291. data/lib/rubocop/cop/style/empty_else.rb +37 -0
  292. data/lib/rubocop/cop/style/empty_heredoc.rb +73 -0
  293. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +2 -2
  294. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  295. data/lib/rubocop/cop/style/endless_method.rb +1 -1
  296. data/lib/rubocop/cop/style/eval_with_location.rb +4 -4
  297. data/lib/rubocop/cop/style/exact_regexp_match.rb +62 -0
  298. data/lib/rubocop/cop/style/explicit_block_argument.rb +5 -1
  299. data/lib/rubocop/cop/style/fetch_env_var.rb +10 -177
  300. data/lib/rubocop/cop/style/file_empty.rb +71 -0
  301. data/lib/rubocop/cop/style/file_read.rb +1 -1
  302. data/lib/rubocop/cop/style/file_write.rb +1 -1
  303. data/lib/rubocop/cop/style/for.rb +2 -0
  304. data/lib/rubocop/cop/style/format_string_token.rb +25 -6
  305. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
  306. data/lib/rubocop/cop/style/guard_clause.rb +127 -38
  307. data/lib/rubocop/cop/style/hash_as_last_array_item.rb +1 -0
  308. data/lib/rubocop/cop/style/hash_each_methods.rb +48 -12
  309. data/lib/rubocop/cop/style/hash_except.rb +27 -16
  310. data/lib/rubocop/cop/style/hash_like_case.rb +3 -9
  311. data/lib/rubocop/cop/style/hash_syntax.rb +26 -2
  312. data/lib/rubocop/cop/style/identical_conditional_branches.rb +15 -0
  313. data/lib/rubocop/cop/style/if_inside_else.rb +6 -0
  314. data/lib/rubocop/cop/style/if_unless_modifier.rb +112 -16
  315. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +29 -2
  316. data/lib/rubocop/cop/style/if_with_semicolon.rb +4 -4
  317. data/lib/rubocop/cop/style/infinite_loop.rb +2 -5
  318. data/lib/rubocop/cop/style/inverse_methods.rb +15 -11
  319. data/lib/rubocop/cop/style/invertible_unless_condition.rb +118 -0
  320. data/lib/rubocop/cop/style/line_end_concatenation.rb +4 -1
  321. data/lib/rubocop/cop/style/magic_comment_format.rb +307 -0
  322. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +2 -2
  323. data/lib/rubocop/cop/style/map_to_hash.rb +4 -1
  324. data/lib/rubocop/cop/style/map_to_set.rb +64 -0
  325. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +40 -24
  326. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +5 -1
  327. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +48 -41
  328. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +21 -2
  329. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +4 -1
  330. data/lib/rubocop/cop/style/method_def_parentheses.rb +11 -4
  331. data/lib/rubocop/cop/style/min_max.rb +3 -3
  332. data/lib/rubocop/cop/style/min_max_comparison.rb +83 -0
  333. data/lib/rubocop/cop/style/missing_else.rb +13 -1
  334. data/lib/rubocop/cop/style/mixin_grouping.rb +4 -4
  335. data/lib/rubocop/cop/style/module_function.rb +30 -8
  336. data/lib/rubocop/cop/style/multiline_block_chain.rb +3 -1
  337. data/lib/rubocop/cop/style/multiline_if_modifier.rb +0 -4
  338. data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +1 -1
  339. data/lib/rubocop/cop/style/multiline_memoization.rb +2 -2
  340. data/lib/rubocop/cop/style/multiline_method_signature.rb +7 -4
  341. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +18 -3
  342. data/lib/rubocop/cop/style/negated_if_else_condition.rb +17 -10
  343. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +9 -0
  344. data/lib/rubocop/cop/style/next.rb +3 -5
  345. data/lib/rubocop/cop/style/nil_lambda.rb +4 -4
  346. data/lib/rubocop/cop/style/numbered_parameters_limit.rb +11 -3
  347. data/lib/rubocop/cop/style/numeric_literals.rb +16 -1
  348. data/lib/rubocop/cop/style/numeric_predicate.rb +43 -9
  349. data/lib/rubocop/cop/style/object_then.rb +5 -0
  350. data/lib/rubocop/cop/style/one_line_conditional.rb +3 -6
  351. data/lib/rubocop/cop/style/operator_method_call.rb +67 -0
  352. data/lib/rubocop/cop/style/parallel_assignment.rb +29 -19
  353. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +2 -3
  354. data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
  355. data/lib/rubocop/cop/style/perl_backrefs.rb +22 -1
  356. data/lib/rubocop/cop/style/proc.rb +4 -1
  357. data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
  358. data/lib/rubocop/cop/style/redundant_argument.rb +3 -0
  359. data/lib/rubocop/cop/style/redundant_begin.rb +3 -0
  360. data/lib/rubocop/cop/style/redundant_condition.rb +41 -8
  361. data/lib/rubocop/cop/style/redundant_conditional.rb +0 -4
  362. data/lib/rubocop/cop/style/redundant_constant_base.rb +85 -0
  363. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +45 -0
  364. data/lib/rubocop/cop/style/redundant_each.rb +116 -0
  365. data/lib/rubocop/cop/style/redundant_fetch_block.rb +7 -5
  366. data/lib/rubocop/cop/style/redundant_heredoc_delimiter_quotes.rb +58 -0
  367. data/lib/rubocop/cop/style/redundant_initialize.rb +3 -1
  368. data/lib/rubocop/cop/style/redundant_interpolation.rb +2 -2
  369. data/lib/rubocop/cop/style/redundant_line_continuation.rb +183 -0
  370. data/lib/rubocop/cop/style/redundant_parentheses.rb +22 -24
  371. data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -1
  372. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +9 -3
  373. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +21 -4
  374. data/lib/rubocop/cop/style/redundant_return.rb +7 -0
  375. data/lib/rubocop/cop/style/redundant_self.rb +2 -0
  376. data/lib/rubocop/cop/style/redundant_sort.rb +24 -9
  377. data/lib/rubocop/cop/style/redundant_sort_by.rb +24 -8
  378. data/lib/rubocop/cop/style/redundant_string_escape.rb +183 -0
  379. data/lib/rubocop/cop/style/regexp_literal.rb +11 -2
  380. data/lib/rubocop/cop/style/require_order.rb +138 -0
  381. data/lib/rubocop/cop/style/rescue_modifier.rb +1 -1
  382. data/lib/rubocop/cop/style/rescue_standard_error.rb +2 -2
  383. data/lib/rubocop/cop/style/safe_navigation.rb +41 -10
  384. data/lib/rubocop/cop/style/select_by_regexp.rb +13 -5
  385. data/lib/rubocop/cop/style/self_assignment.rb +2 -2
  386. data/lib/rubocop/cop/style/semicolon.rb +63 -5
  387. data/lib/rubocop/cop/style/signal_exception.rb +8 -6
  388. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  389. data/lib/rubocop/cop/style/slicing_with_range.rb +1 -1
  390. data/lib/rubocop/cop/style/sole_nested_conditional.rb +17 -8
  391. data/lib/rubocop/cop/style/special_global_vars.rb +2 -2
  392. data/lib/rubocop/cop/style/static_class.rb +32 -1
  393. data/lib/rubocop/cop/style/stderr_puts.rb +1 -1
  394. data/lib/rubocop/cop/style/string_hash_keys.rb +4 -1
  395. data/lib/rubocop/cop/style/string_literals.rb +1 -5
  396. data/lib/rubocop/cop/style/struct_inheritance.rb +1 -1
  397. data/lib/rubocop/cop/style/symbol_array.rb +6 -5
  398. data/lib/rubocop/cop/style/symbol_proc.rb +42 -10
  399. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -13
  400. data/lib/rubocop/cop/style/top_level_method_definition.rb +3 -1
  401. data/lib/rubocop/cop/style/trailing_body_on_class.rb +1 -0
  402. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -4
  403. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
  404. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +1 -1
  405. data/lib/rubocop/cop/style/trivial_accessors.rb +4 -1
  406. data/lib/rubocop/cop/style/unless_logical_operators.rb +1 -0
  407. data/lib/rubocop/cop/style/unpack_first.rb +3 -3
  408. data/lib/rubocop/cop/style/word_array.rb +59 -5
  409. data/lib/rubocop/cop/style/yoda_condition.rb +13 -6
  410. data/lib/rubocop/cop/style/yoda_expression.rb +90 -0
  411. data/lib/rubocop/cop/style/zero_length_predicate.rb +40 -19
  412. data/lib/rubocop/cop/team.rb +63 -56
  413. data/lib/rubocop/cop/util.rb +44 -8
  414. data/lib/rubocop/cop/variable_force/assignment.rb +5 -1
  415. data/lib/rubocop/cop/variable_force/scope.rb +3 -3
  416. data/lib/rubocop/cop/variable_force/variable.rb +5 -3
  417. data/lib/rubocop/cop/variable_force/variable_table.rb +6 -4
  418. data/lib/rubocop/cop/variable_force.rb +18 -30
  419. data/lib/rubocop/cops_documentation_generator.rb +45 -15
  420. data/lib/rubocop/directive_comment.rb +4 -4
  421. data/lib/rubocop/ext/comment.rb +18 -0
  422. data/lib/rubocop/ext/processed_source.rb +2 -0
  423. data/lib/rubocop/ext/range.rb +15 -0
  424. data/lib/rubocop/ext/regexp_node.rb +1 -1
  425. data/lib/rubocop/ext/regexp_parser.rb +1 -1
  426. data/lib/rubocop/feature_loader.rb +94 -0
  427. data/lib/rubocop/file_patterns.rb +43 -0
  428. data/lib/rubocop/formatter/clang_style_formatter.rb +1 -1
  429. data/lib/rubocop/formatter/disabled_config_formatter.rb +26 -9
  430. data/lib/rubocop/formatter/html_formatter.rb +4 -4
  431. data/lib/rubocop/formatter/junit_formatter.rb +4 -1
  432. data/lib/rubocop/formatter/markdown_formatter.rb +1 -1
  433. data/lib/rubocop/formatter/offense_count_formatter.rb +8 -5
  434. data/lib/rubocop/formatter/simple_text_formatter.rb +1 -1
  435. data/lib/rubocop/formatter/tap_formatter.rb +1 -1
  436. data/lib/rubocop/formatter/worst_offenders_formatter.rb +6 -3
  437. data/lib/rubocop/formatter.rb +4 -1
  438. data/lib/rubocop/options.rb +55 -22
  439. data/lib/rubocop/path_util.rb +50 -22
  440. data/lib/rubocop/rake_task.rb +5 -1
  441. data/lib/rubocop/result_cache.rb +26 -24
  442. data/lib/rubocop/rspec/cop_helper.rb +26 -3
  443. data/lib/rubocop/rspec/expect_offense.rb +6 -4
  444. data/lib/rubocop/rspec/shared_contexts.rb +31 -14
  445. data/lib/rubocop/rspec/support.rb +17 -2
  446. data/lib/rubocop/runner.rb +73 -18
  447. data/lib/rubocop/server/cache.rb +48 -2
  448. data/lib/rubocop/server/cli.rb +62 -19
  449. data/lib/rubocop/server/client_command/base.rb +1 -1
  450. data/lib/rubocop/server/client_command/exec.rb +6 -1
  451. data/lib/rubocop/server/client_command/start.rb +6 -1
  452. data/lib/rubocop/server/core.rb +42 -10
  453. data/lib/rubocop/server/helper.rb +1 -1
  454. data/lib/rubocop/server/server_command/exec.rb +1 -1
  455. data/lib/rubocop/server/socket_reader.rb +5 -1
  456. data/lib/rubocop/server.rb +1 -1
  457. data/lib/rubocop/target_finder.rb +1 -1
  458. data/lib/rubocop/target_ruby.rb +5 -5
  459. data/lib/rubocop/version.rb +10 -4
  460. data/lib/rubocop.rb +45 -9
  461. metadata +58 -33
  462. data/lib/rubocop/cop/mixin/ignored_methods.rb +0 -52
@@ -72,11 +72,11 @@ module RuboCop
72
72
  PATTERN
73
73
 
74
74
  def allowed_conditional_expression_on_rhs?(node)
75
- node&.if_type? && contains_contant?(node)
75
+ node&.if_type? && contains_constant?(node)
76
76
  end
77
77
 
78
- def contains_contant?(node)
79
- node.branches.any?(&:const_type?)
78
+ def contains_constant?(node)
79
+ node.branches.compact.any?(&:const_type?)
80
80
  end
81
81
  end
82
82
  end
@@ -38,7 +38,7 @@ module RuboCop
38
38
  return if correct_case_delimiters?(node)
39
39
 
40
40
  add_offense(node.loc.heredoc_end) do |corrector|
41
- expr = node.loc.expression
41
+ expr = node.source_range
42
42
 
43
43
  corrector.replace(expr, correct_delimiters(expr.source))
44
44
  corrector.replace(node.loc.heredoc_end, correct_delimiters(delimiter_string(expr)))
@@ -3,8 +3,9 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Naming
6
- # This cops recommends the use of inclusive language instead of problematic terms.
6
+ # Recommends the use of inclusive language instead of problematic terms.
7
7
  # The cop can check the following locations for offenses:
8
+ #
8
9
  # - identifiers
9
10
  # - constants
10
11
  # - variables
@@ -12,6 +13,7 @@ module RuboCop
12
13
  # - symbols
13
14
  # - comments
14
15
  # - file paths
16
+ #
15
17
  # Each of these locations can be individually enabled/disabled via configuration,
16
18
  # for example CheckIdentifiers = true/false.
17
19
  #
@@ -22,6 +24,9 @@ module RuboCop
22
24
  # `WholeWord: true` can be set on a flagged term to indicate the cop should only match when
23
25
  # a term matches the whole word (partial matches will not be offenses).
24
26
  #
27
+ # The cop supports autocorrection when there is only one suggestion. When there are multiple
28
+ # suggestions, the best suggestion cannot be identified and will not be autocorrected.
29
+ #
25
30
  # @example FlaggedTerms: { whitelist: { Suggestions: ['allowlist'] } }
26
31
  # # Suggest replacing identifier whitelist with allowlist
27
32
  #
@@ -68,6 +73,7 @@ module RuboCop
68
73
  # TeslaVehicle
69
74
  class InclusiveLanguage < Base
70
75
  include RangeHelp
76
+ extend AutoCorrector
71
77
 
72
78
  EMPTY_ARRAY = [].freeze
73
79
  MSG = "Consider replacing '%<term>s'%<suffix>s."
@@ -92,7 +98,7 @@ module RuboCop
92
98
  private
93
99
 
94
100
  def investigate_tokens
95
- processed_source.each_token do |token|
101
+ processed_source.tokens.each do |token|
96
102
  next unless check_token?(token.type)
97
103
 
98
104
  word_locations = scan_for_words(token.text)
@@ -104,9 +110,16 @@ module RuboCop
104
110
 
105
111
  def add_offenses_for_token(token, word_locations)
106
112
  word_locations.each do |word_location|
107
- start_position = token.pos.begin_pos + token.pos.source.index(word_location.word)
108
- range = range_between(start_position, start_position + word_location.word.length)
109
- add_offense(range, message: create_message(word_location.word))
113
+ word = word_location.word
114
+ range = offense_range(token, word)
115
+
116
+ add_offense(range, message: create_message(word)) do |corrector|
117
+ suggestions = find_flagged_term(word)['Suggestions']
118
+
119
+ next unless suggestions.is_a?(String)
120
+
121
+ corrector.replace(range, suggestions)
122
+ end
110
123
  end
111
124
  end
112
125
 
@@ -207,7 +220,10 @@ module RuboCop
207
220
  end
208
221
 
209
222
  def scan_for_words(input)
210
- mask_input(input).enum_for(:scan, @flagged_terms_regex).map do
223
+ masked_input = mask_input(input)
224
+ return EMPTY_ARRAY unless masked_input.match?(@flagged_terms_regex)
225
+
226
+ masked_input.enum_for(:scan, @flagged_terms_regex).map do
211
227
  match = Regexp.last_match
212
228
  WordLocation.new(match.to_s, match.offset(0).first)
213
229
  end
@@ -261,6 +277,12 @@ module RuboCop
261
277
  end
262
278
  " with #{suggestion_str}"
263
279
  end
280
+
281
+ def offense_range(token, word)
282
+ start_position = token.pos.begin_pos + token.pos.source.index(word)
283
+
284
+ range_between(start_position, start_position + word.length)
285
+ end
264
286
  end
265
287
  end
266
288
  end
@@ -17,7 +17,8 @@ module RuboCop
17
17
  # @safety
18
18
  # This cop relies on the pattern `@instance_var ||= ...`,
19
19
  # but this is sometimes used for other purposes than memoization
20
- # so this cop is considered unsafe.
20
+ # so this cop is considered unsafe. Also, its autocorrection is unsafe
21
+ # because it may conflict with instance variable names already in use.
21
22
  #
22
23
  # @example EnforcedStyleForLeadingUnderscores: disallowed (default)
23
24
  # # bad
@@ -145,6 +146,8 @@ module RuboCop
145
146
  # @_foo ||= calculate_expensive_thing
146
147
  # end
147
148
  class MemoizedInstanceVariableName < Base
149
+ extend AutoCorrector
150
+
148
151
  include ConfigurableEnforcedStyle
149
152
 
150
153
  MSG = 'Memoized variable `%<var>s` does not match ' \
@@ -163,6 +166,7 @@ module RuboCop
163
166
  PATTERN
164
167
 
165
168
  # rubocop:disable Metrics/AbcSize
169
+ # rubocop:disable Metrics/MethodLength
166
170
  def on_or_asgn(node)
167
171
  lhs, _value = *node
168
172
  return unless lhs.ivasgn_type?
@@ -175,14 +179,18 @@ module RuboCop
175
179
 
176
180
  return if matches?(method_name, lhs)
177
181
 
182
+ suggested_var = suggested_var(method_name)
178
183
  msg = format(
179
184
  message(lhs.children.first.to_s),
180
185
  var: lhs.children.first.to_s,
181
- suggested_var: suggested_var(method_name),
186
+ suggested_var: suggested_var,
182
187
  method: method_name
183
188
  )
184
- add_offense(lhs, message: msg)
189
+ add_offense(lhs, message: msg) do |corrector|
190
+ corrector.replace(lhs.loc.name, "@#{suggested_var}")
191
+ end
185
192
  end
193
+ # rubocop:enable Metrics/MethodLength
186
194
  # rubocop:enable Metrics/AbcSize
187
195
 
188
196
  # @!method defined_memoized?(node, ivar)
@@ -205,15 +213,22 @@ module RuboCop
205
213
  defined_memoized?(method_node.body, var_name) do |defined_ivar, return_ivar, ivar_assign|
206
214
  return if matches?(method_name, ivar_assign)
207
215
 
216
+ suggested_var = suggested_var(method_name)
208
217
  msg = format(
209
218
  message(var_name.to_s),
210
219
  var: var_name.to_s,
211
- suggested_var: suggested_var(method_name),
220
+ suggested_var: suggested_var,
212
221
  method: method_name
213
222
  )
214
- add_offense(defined_ivar, message: msg)
215
- add_offense(return_ivar, message: msg)
216
- add_offense(ivar_assign.loc.name, message: msg)
223
+ add_offense(defined_ivar, message: msg) do |corrector|
224
+ corrector.replace(defined_ivar, "@#{suggested_var}")
225
+ end
226
+ add_offense(return_ivar, message: msg) do |corrector|
227
+ corrector.replace(return_ivar, "@#{suggested_var}")
228
+ end
229
+ add_offense(ivar_assign.loc.name, message: msg) do |corrector|
230
+ corrector.replace(ivar_assign.loc.name, "@#{suggested_var}")
231
+ end
217
232
  end
218
233
  end
219
234
  # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
@@ -10,8 +10,8 @@ module RuboCop
10
10
  #
11
11
  # Naming/MethodName:
12
12
  # AllowedPatterns:
13
- # - '\A\s*onSelectionBulkChange\s*'
14
- # - '\A\s*onSelectionCleared\s*'
13
+ # - '\AonSelectionBulkChange\z'
14
+ # - '\AonSelectionCleared\z'
15
15
  #
16
16
  # Method names matching patterns are always allowed.
17
17
  #
@@ -67,7 +67,7 @@ module RuboCop
67
67
 
68
68
  def range_position(node)
69
69
  selector_end_pos = node.loc.selector.end_pos + 1
70
- expr_end_pos = node.loc.expression.end_pos
70
+ expr_end_pos = node.source_range.end_pos
71
71
 
72
72
  range_between(selector_end_pos, expr_end_pos)
73
73
  end
@@ -3,7 +3,30 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Naming
6
- # Makes sure that predicates are named properly.
6
+ # Checks that predicate methods names end with a question mark and
7
+ # do not start with a forbidden prefix.
8
+ #
9
+ # A method is determined to be a predicate method if its name starts
10
+ # with one of the prefixes defined in the `NamePrefix` configuration.
11
+ # You can change what prefixes are considered by changing this option.
12
+ # Any method name that starts with one of these prefixes is required by
13
+ # the cop to end with a `?`. Other methods can be allowed by adding to
14
+ # the `AllowedMethods` configuration.
15
+ #
16
+ # NOTE: The `is_a?` method is allowed by default.
17
+ #
18
+ # If `ForbiddenPrefixes` is set, methods that start with the configured
19
+ # prefixes will not be allowed and will be removed by autocorrection.
20
+ #
21
+ # In other words, if `ForbiddenPrefixes` is empty, a method named `is_foo`
22
+ # will register an offense only due to the lack of question mark (and will be
23
+ # autocorrected to `is_foo?`). If `ForbiddenPrefixes` contains `is_`,
24
+ # `is_foo` will register an offense both because the ? is missing and because of
25
+ # the `is_` prefix, and will be corrected to `foo?`.
26
+ #
27
+ # NOTE: `ForbiddenPrefixes` is only applied to prefixes in `NamePrefix`;
28
+ # a prefix in the former but not the latter will not be considered by
29
+ # this cop.
7
30
  #
8
31
  # @example
9
32
  # # bad
@@ -27,6 +50,12 @@ module RuboCop
27
50
  # # good
28
51
  # def value?
29
52
  # end
53
+ #
54
+ # @example AllowedMethods: ['is_a?'] (default)
55
+ # # good
56
+ # def is_a?(value)
57
+ # end
58
+ #
30
59
  class PredicateName < Base
31
60
  include AllowedMethods
32
61
 
@@ -43,7 +72,7 @@ module RuboCop
43
72
  next if allowed_method_name?(method_name.to_s, prefix)
44
73
 
45
74
  add_offense(
46
- node.first_argument.loc.expression,
75
+ node.first_argument.source_range,
47
76
  message: message(method_name, expected_name(method_name.to_s, prefix))
48
77
  )
49
78
  end
@@ -82,9 +82,7 @@ module RuboCop
82
82
  message = message(node)
83
83
 
84
84
  add_offense(range, message: message) do |corrector|
85
- corrector.replace(range, preferred_name)
86
-
87
- correct_node(corrector, node.body, offending_name, preferred_name)
85
+ autocorrect(corrector, node, range, offending_name, preferred_name)
88
86
  end
89
87
  end
90
88
 
@@ -92,7 +90,17 @@ module RuboCop
92
90
 
93
91
  def offense_range(resbody)
94
92
  variable = resbody.exception_variable
95
- variable.loc.expression
93
+ variable.source_range
94
+ end
95
+
96
+ def autocorrect(corrector, node, range, offending_name, preferred_name)
97
+ corrector.replace(range, preferred_name)
98
+ correct_node(corrector, node.body, offending_name, preferred_name)
99
+ return unless (kwbegin_node = node.parent.each_ancestor(:kwbegin).first)
100
+
101
+ kwbegin_node.right_siblings.each do |child_node|
102
+ correct_node(corrector, child_node, offending_name, preferred_name)
103
+ end
96
104
  end
97
105
 
98
106
  def variable_name_matches?(node, name)
@@ -19,6 +19,33 @@ module RuboCop
19
19
  class Registry
20
20
  include Enumerable
21
21
 
22
+ def self.all
23
+ global.without_department(:Test).cops
24
+ end
25
+
26
+ def self.qualified_cop_name(name, origin)
27
+ global.qualified_cop_name(name, origin)
28
+ end
29
+
30
+ # Changes momentarily the global registry
31
+ # Intended for testing purposes
32
+ def self.with_temporary_global(temp_global = global.dup)
33
+ previous = @global
34
+ @global = temp_global
35
+ yield
36
+ ensure
37
+ @global = previous
38
+ end
39
+
40
+ def self.reset!
41
+ @global = new
42
+ end
43
+
44
+ def self.qualified_cop?(name)
45
+ badge = Badge.parse(name)
46
+ global.qualify_badge(badge).first == badge
47
+ end
48
+
22
49
  attr_reader :options
23
50
 
24
51
  def initialize(cops = [], options = {})
@@ -28,6 +55,9 @@ module RuboCop
28
55
 
29
56
  @enrollment_queue = cops
30
57
  @options = options
58
+
59
+ @enabled_cache = {}.compare_by_identity
60
+ @disabled_cache = {}.compare_by_identity
31
61
  end
32
62
 
33
63
  def enlist(cop)
@@ -61,7 +91,7 @@ module RuboCop
61
91
 
62
92
  # @return [Boolean] Checks if given name is department
63
93
  def department?(name)
64
- departments.include? name.to_sym
94
+ departments.include?(name.to_sym)
65
95
  end
66
96
 
67
97
  def contains_cop_matching?(names)
@@ -72,27 +102,27 @@ module RuboCop
72
102
  #
73
103
  # @example gives back a correctly qualified cop name
74
104
  #
75
- # cops = RuboCop::Cop::Cop.all
76
- # cops.
77
- # qualified_cop_name('Layout/EndOfLine') # => 'Layout/EndOfLine'
105
+ # registry = RuboCop::Cop::Registry
106
+ # registry.qualified_cop_name('Layout/EndOfLine', '') # => 'Layout/EndOfLine'
78
107
  #
79
108
  # @example fixes incorrect namespaces
80
109
  #
81
- # cops = RuboCop::Cop::Cop.all
82
- # cops.qualified_cop_name('Lint/EndOfLine') # => 'Layout/EndOfLine'
110
+ # registry = RuboCop::Cop::Registry
111
+ # registry.qualified_cop_name('Lint/EndOfLine', '') # => 'Layout/EndOfLine'
83
112
  #
84
113
  # @example namespaces bare cop identifiers
85
114
  #
86
- # cops = RuboCop::Cop::Cop.all
87
- # cops.qualified_cop_name('EndOfLine') # => 'Layout/EndOfLine'
115
+ # registry = RuboCop::Cop::Registry
116
+ # registry.qualified_cop_name('EndOfLine', '') # => 'Layout/EndOfLine'
88
117
  #
89
118
  # @example passes back unrecognized cop names
90
119
  #
91
- # cops = RuboCop::Cop::Cop.all
92
- # cops.qualified_cop_name('NotACop') # => 'NotACop'
120
+ # registry = RuboCop::Cop::Registry
121
+ # registry.qualified_cop_name('NotACop', '') # => 'NotACop'
93
122
  #
94
123
  # @param name [String] Cop name extracted from config
95
124
  # @param path [String, nil] Path of file that `name` was extracted from
125
+ # @param warn [Boolean] Print a warning if no department given for `name`
96
126
  #
97
127
  # @raise [AmbiguousCopName]
98
128
  # if a bare identifier with two possible namespaces is provided
@@ -133,6 +163,13 @@ module RuboCop
133
163
  'RedundantCopDisableDirective'
134
164
  end
135
165
 
166
+ def qualify_badge(badge)
167
+ clear_enrollment_queue
168
+ @departments
169
+ .map { |department, _| badge.with_department(department) }
170
+ .select { |potential_badge| registered?(potential_badge) }
171
+ end
172
+
136
173
  # @return [Hash{String => Array<Class>}]
137
174
  def to_h
138
175
  clear_enrollment_queue
@@ -149,16 +186,24 @@ module RuboCop
149
186
  @registry.size
150
187
  end
151
188
 
152
- def enabled(config, only = [], only_safe: false)
153
- select { |cop| only.include?(cop.cop_name) || enabled?(cop, config, only_safe) }
189
+ def enabled(config)
190
+ @enabled_cache[config] ||= select { |cop| enabled?(cop, config) }
191
+ end
192
+
193
+ def disabled(config)
194
+ @disabled_cache[config] ||= reject { |cop| enabled?(cop, config) }
154
195
  end
155
196
 
156
- def enabled?(cop, config, only_safe)
157
- cfg = config.for_cop(cop)
197
+ def enabled?(cop, config)
198
+ return true if options[:only]&.include?(cop.cop_name)
199
+
200
+ # We need to use `cop_name` in this case, because `for_cop` uses caching
201
+ # which expects cop names or cop classes as keys.
202
+ cfg = config.for_cop(cop.cop_name)
158
203
 
159
204
  cop_enabled = cfg.fetch('Enabled') == true || enabled_pending_cop?(cfg, config)
160
205
 
161
- if only_safe
206
+ if options.fetch(:safe, false)
162
207
  cop_enabled && cfg.fetch('Safe', true)
163
208
  else
164
209
  cop_enabled
@@ -176,8 +221,12 @@ module RuboCop
176
221
  cops.map(&:cop_name)
177
222
  end
178
223
 
224
+ def cops_for_department(department)
225
+ cops.select { |cop| cop.department == department.to_sym }
226
+ end
227
+
179
228
  def names_for_department(department)
180
- cops.select { |cop| cop.department == department.to_sym }.map(&:cop_name)
229
+ cops_for_department(department).map(&:cop_name)
181
230
  end
182
231
 
183
232
  def ==(other)
@@ -205,6 +254,14 @@ module RuboCop
205
254
  to_h[cop_name].first
206
255
  end
207
256
 
257
+ # When a cop name is given returns a single-element array with the cop class.
258
+ # When a department name is given returns an array with all the cop classes
259
+ # for that department.
260
+ def find_cops_by_directive(directive)
261
+ cop = find_by_cop_name(directive)
262
+ cop ? [cop] : cops_for_department(directive)
263
+ end
264
+
208
265
  def freeze
209
266
  clear_enrollment_queue
210
267
  unqualified_cop_names # build cache
@@ -217,28 +274,6 @@ module RuboCop
217
274
  attr_reader :global
218
275
  end
219
276
 
220
- def self.all
221
- global.without_department(:Test).cops
222
- end
223
-
224
- def self.qualified_cop_name(name, origin)
225
- global.qualified_cop_name(name, origin)
226
- end
227
-
228
- # Changes momentarily the global registry
229
- # Intended for testing purposes
230
- def self.with_temporary_global(temp_global = global.dup)
231
- previous = @global
232
- @global = temp_global
233
- yield
234
- ensure
235
- @global = previous
236
- end
237
-
238
- def self.reset!
239
- @global = new
240
- end
241
-
242
277
  private
243
278
 
244
279
  def initialize_copy(reg)
@@ -261,13 +296,6 @@ module RuboCop
261
296
  self.class.new(cops)
262
297
  end
263
298
 
264
- def qualify_badge(badge)
265
- clear_enrollment_queue
266
- @departments
267
- .map { |department, _| badge.with_department(department) }
268
- .select { |potential_badge| registered?(potential_badge) }
269
- end
270
-
271
299
  def resolve_badge(given_badge, real_badge, source_path)
272
300
  unless given_badge.match?(real_badge)
273
301
  path = PathUtil.smart_path(source_path)
@@ -9,7 +9,8 @@ module RuboCop
9
9
  # Manually combining hashes is error prone and hard to follow, especially
10
10
  # when there are many values. Poor implementations may also introduce
11
11
  # performance or security concerns if they are prone to collisions.
12
- # Delegating to `Array#hash` is clearer, faster, and safer.
12
+ # Delegating to `Array#hash` is clearer and safer, although it might be slower
13
+ # depending on the use case.
13
14
  #
14
15
  # @safety
15
16
  # This cop may be unsafe if the application logic depends on the hash
@@ -9,6 +9,11 @@ module RuboCop
9
9
  # Applications of visibility methods to symbols can be controlled
10
10
  # using AllowModifiersOnSymbols config.
11
11
  #
12
+ # @safety
13
+ # Autocorrection is not safe, because the visibility of dynamically
14
+ # defined methods can vary depending on the state determined by
15
+ # the group access modifier.
16
+ #
12
17
  # @example EnforcedStyle: group (default)
13
18
  # # bad
14
19
  # class Foo
@@ -63,7 +68,10 @@ module RuboCop
63
68
  #
64
69
  # end
65
70
  class AccessModifierDeclarations < Base
71
+ extend AutoCorrector
72
+
66
73
  include ConfigurableEnforcedStyle
74
+ include RangeHelp
67
75
 
68
76
  GROUP_STYLE_MESSAGE = [
69
77
  '`%<access_modifier>s` should not be',
@@ -77,6 +85,8 @@ module RuboCop
77
85
 
78
86
  RESTRICT_ON_SEND = %i[private protected public module_function].freeze
79
87
 
88
+ ALLOWED_NODE_TYPES = %i[pair block].freeze
89
+
80
90
  # @!method access_modifier_with_symbol?(node)
81
91
  def_node_matcher :access_modifier_with_symbol?, <<~PATTERN
82
92
  (send nil? {:private :protected :public :module_function} (sym _))
@@ -84,11 +94,14 @@ module RuboCop
84
94
 
85
95
  def on_send(node)
86
96
  return unless node.access_modifier?
87
- return if node.parent&.pair_type?
97
+ return if ALLOWED_NODE_TYPES.include?(node.parent&.type)
88
98
  return if allow_modifiers_on_symbols?(node)
89
99
 
90
100
  if offense?(node)
91
- add_offense(node.loc.selector) { opposite_style_detected }
101
+ add_offense(node.loc.selector) do |corrector|
102
+ autocorrect(corrector, node)
103
+ end
104
+ opposite_style_detected
92
105
  else
93
106
  correct_style_detected
94
107
  end
@@ -96,12 +109,28 @@ module RuboCop
96
109
 
97
110
  private
98
111
 
112
+ def autocorrect(corrector, node)
113
+ case style
114
+ when :group
115
+ def_node = find_corresponding_def_node(node)
116
+ return unless def_node
117
+
118
+ replace_def(corrector, node, def_node)
119
+ when :inline
120
+ remove_node(corrector, node)
121
+ select_grouped_def_nodes(node).each do |grouped_def_node|
122
+ insert_inline_modifier(corrector, grouped_def_node, node.method_name)
123
+ end
124
+ end
125
+ end
126
+
99
127
  def allow_modifiers_on_symbols?(node)
100
128
  cop_config['AllowModifiersOnSymbols'] && access_modifier_with_symbol?(node)
101
129
  end
102
130
 
103
131
  def offense?(node)
104
- (group_style? && access_modifier_is_inlined?(node)) ||
132
+ (group_style? && access_modifier_is_inlined?(node) &&
133
+ !right_siblings_same_inline_method?(node)) ||
105
134
  (inline_style? && access_modifier_is_not_inlined?(node))
106
135
  end
107
136
 
@@ -121,6 +150,12 @@ module RuboCop
121
150
  !access_modifier_is_inlined?(node)
122
151
  end
123
152
 
153
+ def right_siblings_same_inline_method?(node)
154
+ node.right_siblings.any? do |sibling|
155
+ sibling.send_type? && sibling.method?(node.method_name) && !sibling.arguments.empty?
156
+ end
157
+ end
158
+
124
159
  def message(range)
125
160
  access_modifier = range.source
126
161
 
@@ -130,6 +165,60 @@ module RuboCop
130
165
  format(INLINE_STYLE_MESSAGE, access_modifier: access_modifier)
131
166
  end
132
167
  end
168
+
169
+ def find_corresponding_def_node(node)
170
+ if access_modifier_with_symbol?(node)
171
+ method_name = node.arguments.first.value
172
+ node.parent.each_child_node(:def).find do |child|
173
+ child.method?(method_name)
174
+ end
175
+ else
176
+ node.arguments.first
177
+ end
178
+ end
179
+
180
+ def find_argument_less_modifier_node(node)
181
+ return unless (parent = node.parent)
182
+
183
+ parent.each_child_node(:send).find do |child|
184
+ child.method?(node.method_name) && child.arguments.empty?
185
+ end
186
+ end
187
+
188
+ def select_grouped_def_nodes(node)
189
+ node.right_siblings.take_while do |sibling|
190
+ !(sibling.send_type? && sibling.bare_access_modifier_declaration?)
191
+ end.select(&:def_type?)
192
+ end
193
+
194
+ def replace_def(corrector, node, def_node)
195
+ source = def_source(node, def_node)
196
+ argument_less_modifier_node = find_argument_less_modifier_node(node)
197
+ if argument_less_modifier_node
198
+ corrector.insert_after(argument_less_modifier_node, "\n\n#{source}")
199
+ elsif (ancestor = node.each_ancestor(:block, :class, :module).first)
200
+
201
+ corrector.insert_before(ancestor.loc.end, "#{node.method_name}\n\n#{source}\n")
202
+ else
203
+ corrector.replace(node, "#{node.method_name}\n\n#{source}")
204
+ return
205
+ end
206
+
207
+ remove_node(corrector, def_node)
208
+ remove_node(corrector, node)
209
+ end
210
+
211
+ def insert_inline_modifier(corrector, node, modifier_name)
212
+ corrector.insert_before(node, "#{modifier_name} ")
213
+ end
214
+
215
+ def remove_node(corrector, node)
216
+ corrector.remove(range_with_comments_and_lines(node))
217
+ end
218
+
219
+ def def_source(node, def_node)
220
+ [*processed_source.ast_with_comments[node].map(&:text), def_node.source].join("\n")
221
+ end
133
222
  end
134
223
  end
135
224
  end