rubocop 1.67.0 → 1.73.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 (412) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +4 -4
  4. data/config/default.yml +168 -19
  5. data/config/internal_affairs.yml +16 -0
  6. data/lib/rubocop/cached_data.rb +12 -4
  7. data/lib/rubocop/cli/command/execute_runner.rb +4 -4
  8. data/lib/rubocop/cli/command/show_cops.rb +24 -2
  9. data/lib/rubocop/cli/command/suggest_extensions.rb +7 -1
  10. data/lib/rubocop/cli/command/version.rb +2 -2
  11. data/lib/rubocop/comment_config.rb +2 -2
  12. data/lib/rubocop/config.rb +17 -4
  13. data/lib/rubocop/config_loader.rb +48 -8
  14. data/lib/rubocop/config_loader_resolver.rb +35 -10
  15. data/lib/rubocop/config_validator.rb +19 -9
  16. data/lib/rubocop/cop/autocorrect_logic.rb +36 -19
  17. data/lib/rubocop/cop/base.rb +7 -1
  18. data/lib/rubocop/cop/bundler/duplicated_gem.rb +2 -2
  19. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
  20. data/lib/rubocop/cop/bundler/gem_filename.rb +0 -1
  21. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +0 -1
  22. data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -12
  23. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +1 -1
  24. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +10 -0
  25. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +1 -2
  26. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +0 -2
  27. data/lib/rubocop/cop/generator.rb +6 -0
  28. data/lib/rubocop/cop/internal_affairs/cop_enabled.rb +85 -0
  29. data/lib/rubocop/cop/internal_affairs/example_description.rb +4 -2
  30. data/lib/rubocop/cop/internal_affairs/location_exists.rb +116 -0
  31. data/lib/rubocop/cop/internal_affairs/location_expression.rb +2 -1
  32. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +3 -4
  33. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +3 -2
  34. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
  35. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +63 -0
  36. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +131 -0
  37. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +229 -0
  38. data/lib/rubocop/cop/internal_affairs/node_type_multiple_predicates.rb +126 -0
  39. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +4 -3
  40. data/lib/rubocop/cop/internal_affairs/numblock_handler.rb +1 -1
  41. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +90 -0
  42. data/lib/rubocop/cop/internal_affairs/operator_keyword.rb +48 -0
  43. data/lib/rubocop/cop/internal_affairs/plugin.rb +33 -0
  44. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +3 -1
  45. data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +5 -4
  46. data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +0 -2
  47. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +7 -1
  48. data/lib/rubocop/cop/internal_affairs.rb +6 -16
  49. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +1 -1
  50. data/lib/rubocop/cop/layout/argument_alignment.rb +2 -9
  51. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  52. data/lib/rubocop/cop/layout/begin_end_alignment.rb +0 -1
  53. data/lib/rubocop/cop/layout/block_alignment.rb +3 -2
  54. data/lib/rubocop/cop/layout/class_structure.rb +9 -9
  55. data/lib/rubocop/cop/layout/dot_position.rb +1 -1
  56. data/lib/rubocop/cop/layout/else_alignment.rb +2 -2
  57. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +2 -2
  58. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +7 -11
  59. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +29 -4
  60. data/lib/rubocop/cop/layout/empty_lines_around_begin_body.rb +5 -6
  61. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +4 -5
  62. data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +23 -1
  63. data/lib/rubocop/cop/layout/end_alignment.rb +1 -1
  64. data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
  65. data/lib/rubocop/cop/layout/first_argument_indentation.rb +3 -8
  66. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -7
  67. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -7
  68. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +1 -1
  69. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +2 -2
  70. data/lib/rubocop/cop/layout/hash_alignment.rb +6 -4
  71. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -1
  72. data/lib/rubocop/cop/layout/indentation_width.rb +7 -7
  73. data/lib/rubocop/cop/layout/leading_comment_space.rb +44 -1
  74. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +11 -2
  75. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +7 -1
  76. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -2
  77. data/lib/rubocop/cop/layout/line_length.rb +119 -4
  78. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +1 -1
  79. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +25 -0
  80. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +2 -1
  81. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +4 -4
  82. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +1 -1
  83. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +2 -3
  84. data/lib/rubocop/cop/layout/parameter_alignment.rb +3 -4
  85. data/lib/rubocop/cop/layout/redundant_line_break.rb +10 -41
  86. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +4 -3
  87. data/lib/rubocop/cop/layout/single_line_block_chain.rb +1 -1
  88. data/lib/rubocop/cop/layout/space_after_colon.rb +2 -2
  89. data/lib/rubocop/cop/layout/space_after_comma.rb +1 -1
  90. data/lib/rubocop/cop/layout/space_after_method_name.rb +1 -1
  91. data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
  92. data/lib/rubocop/cop/layout/space_around_keyword.rb +2 -1
  93. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
  94. data/lib/rubocop/cop/layout/space_around_operators.rb +19 -20
  95. data/lib/rubocop/cop/layout/space_before_brackets.rb +5 -5
  96. data/lib/rubocop/cop/layout/space_before_comma.rb +1 -1
  97. data/lib/rubocop/cop/layout/space_before_semicolon.rb +1 -1
  98. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +6 -0
  99. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +4 -0
  100. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +4 -0
  101. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +0 -1
  102. data/lib/rubocop/cop/layout/trailing_whitespace.rb +5 -3
  103. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  104. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +119 -0
  105. data/lib/rubocop/cop/lint/assignment_in_condition.rb +1 -3
  106. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +10 -12
  107. data/lib/rubocop/cop/lint/circular_argument_reference.rb +6 -0
  108. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +3 -3
  109. data/lib/rubocop/cop/lint/constant_reassignment.rb +148 -0
  110. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +84 -0
  111. data/lib/rubocop/cop/lint/debugger.rb +1 -1
  112. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +2 -1
  113. data/lib/rubocop/cop/lint/duplicate_branch.rb +39 -4
  114. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +1 -1
  115. data/lib/rubocop/cop/lint/duplicate_methods.rb +0 -14
  116. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
  117. data/lib/rubocop/cop/lint/duplicate_set_element.rb +20 -7
  118. data/lib/rubocop/cop/lint/empty_ensure.rb +1 -1
  119. data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
  120. data/lib/rubocop/cop/lint/empty_file.rb +0 -2
  121. data/lib/rubocop/cop/lint/ensure_return.rb +1 -1
  122. data/lib/rubocop/cop/lint/float_comparison.rb +20 -14
  123. data/lib/rubocop/cop/lint/float_out_of_range.rb +2 -4
  124. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +2 -2
  125. data/lib/rubocop/cop/lint/hash_new_with_keyword_arguments_as_default.rb +55 -0
  126. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
  127. data/lib/rubocop/cop/lint/interpolation_check.rb +9 -0
  128. data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +3 -0
  129. data/lib/rubocop/cop/lint/literal_as_condition.rb +105 -7
  130. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +1 -1
  131. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +24 -6
  132. data/lib/rubocop/cop/lint/missing_super.rb +2 -2
  133. data/lib/rubocop/cop/lint/mixed_case_range.rb +4 -7
  134. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
  135. data/lib/rubocop/cop/lint/nested_method_definition.rb +9 -5
  136. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  137. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +2 -2
  138. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +12 -3
  139. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -3
  140. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +1 -1
  141. data/lib/rubocop/cop/lint/number_conversion.rb +0 -1
  142. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -2
  143. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +93 -0
  144. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -2
  145. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +3 -2
  146. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -5
  147. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
  148. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
  149. data/lib/rubocop/cop/lint/redundant_require_statement.rb +0 -21
  150. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +12 -7
  151. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +8 -7
  152. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +2 -2
  153. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +252 -0
  154. data/lib/rubocop/cop/lint/refinement_import_methods.rb +1 -1
  155. data/lib/rubocop/cop/lint/regexp_as_condition.rb +0 -1
  156. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
  157. data/lib/rubocop/cop/lint/rescue_type.rb +3 -7
  158. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +17 -1
  159. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +5 -1
  160. data/lib/rubocop/cop/lint/self_assignment.rb +8 -10
  161. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
  162. data/lib/rubocop/cop/lint/shared_mutable_default.rb +65 -0
  163. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  164. data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +111 -0
  165. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  166. data/lib/rubocop/cop/lint/syntax.rb +4 -1
  167. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +88 -0
  168. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +1 -1
  169. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -1
  170. data/lib/rubocop/cop/lint/unreachable_code.rb +51 -2
  171. data/lib/rubocop/cop/lint/unreachable_loop.rb +1 -1
  172. data/lib/rubocop/cop/lint/unused_method_argument.rb +18 -2
  173. data/lib/rubocop/cop/lint/useless_access_modifier.rb +4 -4
  174. data/lib/rubocop/cop/lint/useless_assignment.rb +1 -1
  175. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +80 -0
  176. data/lib/rubocop/cop/lint/useless_defined.rb +55 -0
  177. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +4 -0
  178. data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
  179. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +2 -1
  180. data/lib/rubocop/cop/lint/useless_rescue.rb +1 -1
  181. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +2 -2
  182. data/lib/rubocop/cop/lint/useless_setter_call.rb +14 -25
  183. data/lib/rubocop/cop/lint/void.rb +14 -11
  184. data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
  185. data/lib/rubocop/cop/metrics/class_length.rb +9 -9
  186. data/lib/rubocop/cop/metrics/collection_literal_length.rb +7 -0
  187. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +5 -2
  188. data/lib/rubocop/cop/metrics/method_length.rb +8 -1
  189. data/lib/rubocop/cop/metrics/module_length.rb +1 -1
  190. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  191. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -1
  192. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +2 -3
  193. data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +7 -7
  194. data/lib/rubocop/cop/mixin/alignment.rb +2 -2
  195. data/lib/rubocop/cop/mixin/allowed_pattern.rb +4 -4
  196. data/lib/rubocop/cop/mixin/check_assignment.rb +4 -12
  197. data/lib/rubocop/cop/mixin/check_line_breakable.rb +20 -10
  198. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +49 -0
  199. data/lib/rubocop/cop/mixin/comments_help.rb +8 -3
  200. data/lib/rubocop/cop/mixin/dig_help.rb +27 -0
  201. data/lib/rubocop/cop/mixin/endless_method_rewriter.rb +24 -0
  202. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +4 -2
  203. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +22 -22
  204. data/lib/rubocop/cop/mixin/hash_subset.rb +203 -0
  205. data/lib/rubocop/cop/mixin/hash_transform_method.rb +74 -74
  206. data/lib/rubocop/cop/mixin/line_length_help.rb +5 -4
  207. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
  208. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +5 -9
  209. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
  210. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +68 -30
  211. data/lib/rubocop/cop/mixin/range_help.rb +3 -4
  212. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  213. data/lib/rubocop/cop/mixin/statement_modifier.rb +8 -3
  214. data/lib/rubocop/cop/mixin/string_help.rb +2 -2
  215. data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
  216. data/lib/rubocop/cop/mixin/target_ruby_version.rb +17 -1
  217. data/lib/rubocop/cop/mixin/trailing_comma.rb +15 -3
  218. data/lib/rubocop/cop/naming/accessor_method_name.rb +6 -6
  219. data/lib/rubocop/cop/naming/block_forwarding.rb +20 -16
  220. data/lib/rubocop/cop/naming/constant_name.rb +6 -7
  221. data/lib/rubocop/cop/naming/file_name.rb +0 -2
  222. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +11 -12
  223. data/lib/rubocop/cop/naming/predicate_name.rb +44 -0
  224. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +6 -14
  225. data/lib/rubocop/cop/naming/variable_name.rb +63 -6
  226. data/lib/rubocop/cop/naming/variable_number.rb +2 -3
  227. data/lib/rubocop/cop/offense.rb +2 -3
  228. data/lib/rubocop/cop/security/compound_hash.rb +2 -0
  229. data/lib/rubocop/cop/security/yaml_load.rb +3 -2
  230. data/lib/rubocop/cop/style/access_modifier_declarations.rb +86 -28
  231. data/lib/rubocop/cop/style/accessor_grouping.rb +19 -5
  232. data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +79 -0
  233. data/lib/rubocop/cop/style/and_or.rb +1 -1
  234. data/lib/rubocop/cop/style/arguments_forwarding.rb +39 -23
  235. data/lib/rubocop/cop/style/array_first_last.rb +18 -2
  236. data/lib/rubocop/cop/style/array_intersect.rb +5 -4
  237. data/lib/rubocop/cop/style/bitwise_predicate.rb +100 -0
  238. data/lib/rubocop/cop/style/block_delimiters.rb +41 -24
  239. data/lib/rubocop/cop/style/case_like_if.rb +8 -11
  240. data/lib/rubocop/cop/style/class_and_module_children.rb +6 -3
  241. data/lib/rubocop/cop/style/collection_methods.rb +1 -1
  242. data/lib/rubocop/cop/style/combinable_defined.rb +115 -0
  243. data/lib/rubocop/cop/style/combinable_loops.rb +2 -2
  244. data/lib/rubocop/cop/style/commented_keyword.rb +11 -1
  245. data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
  246. data/lib/rubocop/cop/style/conditional_assignment.rb +25 -25
  247. data/lib/rubocop/cop/style/constant_visibility.rb +3 -12
  248. data/lib/rubocop/cop/style/dig_chain.rb +89 -0
  249. data/lib/rubocop/cop/style/documentation.rb +1 -1
  250. data/lib/rubocop/cop/style/double_negation.rb +3 -3
  251. data/lib/rubocop/cop/style/each_for_simple_loop.rb +4 -7
  252. data/lib/rubocop/cop/style/each_with_object.rb +2 -3
  253. data/lib/rubocop/cop/style/empty_else.rb +4 -2
  254. data/lib/rubocop/cop/style/empty_literal.rb +1 -1
  255. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  256. data/lib/rubocop/cop/style/endless_method.rb +150 -18
  257. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  258. data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -3
  259. data/lib/rubocop/cop/style/explicit_block_argument.rb +15 -2
  260. data/lib/rubocop/cop/style/exponential_notation.rb +1 -1
  261. data/lib/rubocop/cop/style/fetch_env_var.rb +2 -1
  262. data/lib/rubocop/cop/style/file_null.rb +89 -0
  263. data/lib/rubocop/cop/style/file_touch.rb +75 -0
  264. data/lib/rubocop/cop/style/float_division.rb +8 -4
  265. data/lib/rubocop/cop/style/for.rb +0 -1
  266. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
  267. data/lib/rubocop/cop/style/global_vars.rb +1 -3
  268. data/lib/rubocop/cop/style/guard_clause.rb +15 -2
  269. data/lib/rubocop/cop/style/hash_conversion.rb +1 -2
  270. data/lib/rubocop/cop/style/hash_each_methods.rb +3 -6
  271. data/lib/rubocop/cop/style/hash_except.rb +35 -147
  272. data/lib/rubocop/cop/style/hash_slice.rb +80 -0
  273. data/lib/rubocop/cop/style/hash_syntax.rb +6 -3
  274. data/lib/rubocop/cop/style/identical_conditional_branches.rb +22 -3
  275. data/lib/rubocop/cop/style/if_inside_else.rb +0 -1
  276. data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -3
  277. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +2 -3
  278. data/lib/rubocop/cop/style/if_with_semicolon.rb +20 -9
  279. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  280. data/lib/rubocop/cop/style/inverse_methods.rb +6 -7
  281. data/lib/rubocop/cop/style/it_assignment.rb +36 -0
  282. data/lib/rubocop/cop/style/keyword_arguments_merging.rb +67 -0
  283. data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -1
  284. data/lib/rubocop/cop/style/lambda_call.rb +3 -2
  285. data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
  286. data/lib/rubocop/cop/style/map_into_array.rb +7 -2
  287. data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
  288. data/lib/rubocop/cop/style/map_to_set.rb +3 -2
  289. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +20 -13
  290. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -0
  291. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +8 -11
  292. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -4
  293. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  294. data/lib/rubocop/cop/style/missing_else.rb +2 -0
  295. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +33 -3
  296. data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
  297. data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
  298. data/lib/rubocop/cop/style/multiple_comparison.rb +52 -51
  299. data/lib/rubocop/cop/style/mutable_constant.rb +7 -8
  300. data/lib/rubocop/cop/style/negated_if_else_condition.rb +7 -5
  301. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
  302. data/lib/rubocop/cop/style/nested_ternary_operator.rb +5 -4
  303. data/lib/rubocop/cop/style/not.rb +1 -1
  304. data/lib/rubocop/cop/style/object_then.rb +14 -15
  305. data/lib/rubocop/cop/style/one_line_conditional.rb +25 -4
  306. data/lib/rubocop/cop/style/open_struct_use.rb +5 -5
  307. data/lib/rubocop/cop/style/operator_method_call.rb +5 -6
  308. data/lib/rubocop/cop/style/or_assignment.rb +3 -6
  309. data/lib/rubocop/cop/style/parallel_assignment.rb +9 -18
  310. data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
  311. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  312. data/lib/rubocop/cop/style/proc.rb +1 -2
  313. data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
  314. data/lib/rubocop/cop/style/raise_args.rb +7 -5
  315. data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
  316. data/lib/rubocop/cop/style/redundant_argument.rb +3 -1
  317. data/lib/rubocop/cop/style/redundant_assignment.rb +1 -1
  318. data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
  319. data/lib/rubocop/cop/style/redundant_condition.rb +72 -23
  320. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +2 -1
  321. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -10
  322. data/lib/rubocop/cop/style/redundant_each.rb +1 -1
  323. data/lib/rubocop/cop/style/redundant_exception.rb +2 -2
  324. data/lib/rubocop/cop/style/redundant_format.rb +250 -0
  325. data/lib/rubocop/cop/style/redundant_freeze.rb +2 -2
  326. data/lib/rubocop/cop/style/redundant_initialize.rb +12 -3
  327. data/lib/rubocop/cop/style/redundant_line_continuation.rb +54 -15
  328. data/lib/rubocop/cop/style/redundant_parentheses.rb +36 -24
  329. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +4 -0
  330. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
  331. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
  332. data/lib/rubocop/cop/style/redundant_return.rb +2 -2
  333. data/lib/rubocop/cop/style/redundant_self.rb +8 -15
  334. data/lib/rubocop/cop/style/redundant_self_assignment.rb +20 -32
  335. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +4 -4
  336. data/lib/rubocop/cop/style/redundant_sort.rb +3 -3
  337. data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -2
  338. data/lib/rubocop/cop/style/rescue_modifier.rb +2 -3
  339. data/lib/rubocop/cop/style/return_nil.rb +1 -1
  340. data/lib/rubocop/cop/style/safe_navigation.rb +14 -2
  341. data/lib/rubocop/cop/style/safe_navigation_chain_length.rb +52 -0
  342. data/lib/rubocop/cop/style/select_by_regexp.rb +1 -1
  343. data/lib/rubocop/cop/style/self_assignment.rb +11 -17
  344. data/lib/rubocop/cop/style/semicolon.rb +1 -1
  345. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +2 -1
  346. data/lib/rubocop/cop/style/signal_exception.rb +2 -3
  347. data/lib/rubocop/cop/style/single_argument_dig.rb +9 -5
  348. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  349. data/lib/rubocop/cop/style/single_line_do_end_block.rb +12 -3
  350. data/lib/rubocop/cop/style/single_line_methods.rb +6 -7
  351. data/lib/rubocop/cop/style/slicing_with_range.rb +40 -11
  352. data/lib/rubocop/cop/style/sole_nested_conditional.rb +4 -5
  353. data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
  354. data/lib/rubocop/cop/style/string_concatenation.rb +15 -14
  355. data/lib/rubocop/cop/style/string_literals.rb +1 -1
  356. data/lib/rubocop/cop/style/string_methods.rb +1 -1
  357. data/lib/rubocop/cop/style/super_arguments.rb +65 -17
  358. data/lib/rubocop/cop/style/swap_values.rb +4 -15
  359. data/lib/rubocop/cop/style/ternary_parentheses.rb +25 -4
  360. data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -1
  361. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -1
  362. data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +47 -6
  363. data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +48 -6
  364. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +4 -4
  365. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  366. data/lib/rubocop/cop/style/variable_interpolation.rb +1 -2
  367. data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
  368. data/lib/rubocop/cop/style/yoda_condition.rb +8 -4
  369. data/lib/rubocop/cop/style/yoda_expression.rb +2 -1
  370. data/lib/rubocop/cop/util.rb +12 -5
  371. data/lib/rubocop/cop/utils/format_string.rb +7 -5
  372. data/lib/rubocop/cop/variable_force/assignment.rb +18 -3
  373. data/lib/rubocop/cop/variable_force/branch.rb +1 -1
  374. data/lib/rubocop/cop/variable_force/variable.rb +18 -2
  375. data/lib/rubocop/cop/variable_force/variable_table.rb +5 -5
  376. data/lib/rubocop/cop/variable_force.rb +4 -10
  377. data/lib/rubocop/cops_documentation_generator.rb +44 -23
  378. data/lib/rubocop/directive_comment.rb +44 -10
  379. data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -1
  380. data/lib/rubocop/formatter/formatter_set.rb +1 -1
  381. data/lib/rubocop/lsp/diagnostic.rb +189 -0
  382. data/lib/rubocop/lsp/logger.rb +2 -2
  383. data/lib/rubocop/lsp/routes.rb +7 -23
  384. data/lib/rubocop/lsp/runtime.rb +17 -49
  385. data/lib/rubocop/lsp/server.rb +0 -2
  386. data/lib/rubocop/lsp/stdin_runner.rb +83 -0
  387. data/lib/rubocop/magic_comment.rb +3 -3
  388. data/lib/rubocop/options.rb +28 -12
  389. data/lib/rubocop/path_util.rb +15 -8
  390. data/lib/rubocop/plugin/configuration_integrator.rb +143 -0
  391. data/lib/rubocop/plugin/load_error.rb +26 -0
  392. data/lib/rubocop/plugin/loader.rb +100 -0
  393. data/lib/rubocop/plugin/not_supported_error.rb +29 -0
  394. data/lib/rubocop/plugin.rb +46 -0
  395. data/lib/rubocop/rake_task.rb +4 -1
  396. data/lib/rubocop/result_cache.rb +13 -13
  397. data/lib/rubocop/rspec/cop_helper.rb +9 -0
  398. data/lib/rubocop/rspec/expect_offense.rb +6 -2
  399. data/lib/rubocop/rspec/shared_contexts.rb +19 -1
  400. data/lib/rubocop/rspec/support.rb +2 -2
  401. data/lib/rubocop/runner.rb +21 -14
  402. data/lib/rubocop/server/cache.rb +35 -2
  403. data/lib/rubocop/server/cli.rb +2 -2
  404. data/lib/rubocop/target_finder.rb +1 -0
  405. data/lib/rubocop/target_ruby.rb +16 -1
  406. data/lib/rubocop/version.rb +41 -7
  407. data/lib/rubocop.rb +27 -1
  408. data/lib/ruby_lsp/rubocop/addon.rb +75 -0
  409. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +47 -0
  410. metadata +73 -20
  411. data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
  412. data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Layout
6
- # Checks for semicolon (;) preceded by space.
6
+ # Checks for semicolon (`;`) preceded by space.
7
7
  #
8
8
  # @example
9
9
  # # bad
@@ -12,9 +12,11 @@ module RuboCop
12
12
  #
13
13
  # # bad
14
14
  # array = [ a, b, c, d ]
15
+ # array = [ a, [ b, c ]]
15
16
  #
16
17
  # # good
17
18
  # array = [a, b, c, d]
19
+ # array = [a, [b, c]]
18
20
  #
19
21
  # @example EnforcedStyle: space
20
22
  # # The `space` style enforces that array literals have
@@ -22,9 +24,11 @@ module RuboCop
22
24
  #
23
25
  # # bad
24
26
  # array = [a, b, c, d]
27
+ # array = [ a, [ b, c ]]
25
28
  #
26
29
  # # good
27
30
  # array = [ a, b, c, d ]
31
+ # array = [ a, [ b, c ] ]
28
32
  #
29
33
  # @example EnforcedStyle: compact
30
34
  # # The `compact` style normally requires a space inside
@@ -32,6 +36,7 @@ module RuboCop
32
36
  # # or right brackets are collapsed together in nested arrays.
33
37
  #
34
38
  # # bad
39
+ # array = [a, b, c, d]
35
40
  # array = [ a, [ b, c ] ]
36
41
  # array = [
37
42
  # [ a ],
@@ -39,6 +44,7 @@ module RuboCop
39
44
  # ]
40
45
  #
41
46
  # # good
47
+ # array = [ a, b, c, d ]
42
48
  # array = [ a, [ b, c ]]
43
49
  # array = [[ a ],
44
50
  # [ b, c ]]
@@ -82,6 +82,10 @@ module RuboCop
82
82
  include RangeHelp
83
83
  extend AutoCorrector
84
84
 
85
+ def self.autocorrect_incompatible_with
86
+ [Style::BlockDelimiters]
87
+ end
88
+
85
89
  def on_block(node)
86
90
  return if node.keywords?
87
91
 
@@ -12,9 +12,11 @@ module RuboCop
12
12
  #
13
13
  # # bad
14
14
  # h = {a: 1, b: 2}
15
+ # foo = {{ a: 1 } => { b: { c: 2 }}}
15
16
  #
16
17
  # # good
17
18
  # h = { a: 1, b: 2 }
19
+ # foo = { { a: 1 } => { b: { c: 2 } } }
18
20
  #
19
21
  # @example EnforcedStyle: no_space
20
22
  # # The `no_space` style enforces that hash literals have
@@ -22,9 +24,11 @@ module RuboCop
22
24
  #
23
25
  # # bad
24
26
  # h = { a: 1, b: 2 }
27
+ # foo = {{ a: 1 } => { b: { c: 2 }}}
25
28
  #
26
29
  # # good
27
30
  # h = {a: 1, b: 2}
31
+ # foo = {{a: 1} => {b: {c: 2}}}
28
32
  #
29
33
  # @example EnforcedStyle: compact
30
34
  # # The `compact` style normally requires a space inside
@@ -22,7 +22,6 @@ module RuboCop
22
22
  include Interpolation
23
23
  include SurroundingSpace
24
24
  include ConfigurableEnforcedStyle
25
- include RangeHelp
26
25
  extend AutoCorrector
27
26
 
28
27
  MSG = '%<command>s space inside string interpolation.'
@@ -48,7 +48,7 @@ module RuboCop
48
48
 
49
49
  def on_new_investigation
50
50
  processed_source.lines.each_with_index do |line, index|
51
- next unless line.end_with?(' ', "\t")
51
+ next unless line.match?(/[[:blank:]]\z/)
52
52
 
53
53
  process_line(line, index + 1)
54
54
  end
@@ -84,7 +84,7 @@ module RuboCop
84
84
  end
85
85
 
86
86
  def whitespace_is_indentation?(range, level)
87
- range.source[/[ \t]+/].length <= level
87
+ range.source[/[[:blank:]]+/].length <= level
88
88
  end
89
89
 
90
90
  def whitespace_only?(range)
@@ -123,7 +123,9 @@ module RuboCop
123
123
  end
124
124
 
125
125
  def offense_range(lineno, line)
126
- source_range(processed_source.buffer, lineno, (line.rstrip.length)...(line.length))
126
+ source_range(
127
+ processed_source.buffer, lineno, (line.sub(/[[:blank:]]+\z/, '').length)...(line.length)
128
+ )
127
129
  end
128
130
  end
129
131
  end
@@ -77,7 +77,7 @@ module RuboCop
77
77
  private
78
78
 
79
79
  def ambiguous_block_association?(send_node)
80
- send_node.last_argument.block_type? && !send_node.last_argument.send_node.arguments?
80
+ send_node.last_argument.any_block_type? && !send_node.last_argument.send_node.arguments?
81
81
  end
82
82
 
83
83
  def allowed_method_pattern?(node)
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Checks for an array literal interpolated inside a regexp.
7
+ #
8
+ # When interpolating an array literal, it is converted to a string. This means
9
+ # that when inside a regexp, it acts as a character class but with additional
10
+ # quotes, spaces and commas that are likely not intended. For example,
11
+ # `/#{%w[a b c]}/` parses as `/["a", "b", "c"]/` (or `/["a, bc]/` without
12
+ # repeated characters).
13
+ #
14
+ # The cop can autocorrect to a character class (if all items in the array are a
15
+ # single character) or alternation (if the array contains longer items).
16
+ #
17
+ # NOTE: This only considers interpolated arrays that contain only strings, symbols,
18
+ # integers, and floats. Any other type is not easily convertible to a character class
19
+ # or regexp alternation.
20
+ #
21
+ # @safety
22
+ # Autocorrection is unsafe because it will change the regexp pattern, by
23
+ # removing the additional quotes, spaces and commas from the character class.
24
+ #
25
+ # @example
26
+ # # bad
27
+ # /#{%w[a b c]}/
28
+ #
29
+ # # good
30
+ # /[abc]/
31
+ #
32
+ # # bad
33
+ # /#{%w[foo bar baz]}/
34
+ #
35
+ # # good
36
+ # /(?:foo|bar|baz)/
37
+ #
38
+ # # bad - construct a regexp rather than interpolate an array of identifiers
39
+ # /#{[foo, bar]}/
40
+ #
41
+ class ArrayLiteralInRegexp < Base
42
+ include Interpolation
43
+ extend AutoCorrector
44
+
45
+ LITERAL_TYPES = %i[str sym int float true false nil].freeze
46
+ private_constant :LITERAL_TYPES
47
+
48
+ MSG_CHARACTER_CLASS = 'Use a character class instead of interpolating an array in a regexp.'
49
+ MSG_ALTERNATION = 'Use alternation instead of interpolating an array in a regexp.'
50
+ MSG_UNKNOWN = 'Use alternation or a character class instead of interpolating an array ' \
51
+ 'in a regexp.'
52
+
53
+ def on_interpolation(begin_node)
54
+ final_node = begin_node.children.last
55
+
56
+ return unless begin_node.parent.regexp_type?
57
+ return unless final_node.array_type?
58
+
59
+ if array_of_literal_values?(final_node)
60
+ register_array_of_literal_values(begin_node, final_node)
61
+ else
62
+ register_array_of_nonliteral_values(begin_node)
63
+ end
64
+ end
65
+
66
+ private
67
+
68
+ def array_of_literal_values?(node)
69
+ node.each_value.all? { |value| value.type?(*LITERAL_TYPES) }
70
+ end
71
+
72
+ def register_array_of_literal_values(begin_node, node)
73
+ array_values = array_values(node)
74
+
75
+ if character_class?(array_values)
76
+ message = MSG_CHARACTER_CLASS
77
+ replacement = character_class_for(array_values)
78
+ else
79
+ message = MSG_ALTERNATION
80
+ replacement = alternation_for(array_values)
81
+ end
82
+
83
+ add_offense(begin_node, message: message) do |corrector|
84
+ corrector.replace(begin_node, replacement)
85
+ end
86
+ end
87
+
88
+ def register_array_of_nonliteral_values(node)
89
+ # Add offense but do not correct if the array contains any nonliteral values.
90
+ add_offense(node, message: MSG_UNKNOWN)
91
+ end
92
+
93
+ def array_values(node)
94
+ node.each_value.map do |value|
95
+ value.respond_to?(:value) ? value.value : value.source
96
+ end
97
+ end
98
+
99
+ def character_class?(values)
100
+ values.all? { |v| v.to_s.length == 1 }
101
+ end
102
+
103
+ def character_class_for(values)
104
+ "[#{escape_values(values).join}]"
105
+ end
106
+
107
+ def alternation_for(values)
108
+ "(?:#{escape_values(values).join('|')})"
109
+ end
110
+
111
+ def escape_values(values)
112
+ # This may add extraneous escape characters, but they can be cleaned up
113
+ # by `Style/RedundantRegexpEscape`.
114
+ values.map { |value| Regexp.escape(value.to_s) }
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -53,8 +53,6 @@ module RuboCop
53
53
  ASGN_TYPES = [:begin, *AST::Node::EQUALS_ASSIGNMENTS, :send, :csend].freeze
54
54
 
55
55
  def on_if(node)
56
- return if node.condition.block_type?
57
-
58
56
  traverse_node(node.condition) do |asgn_node|
59
57
  next :skip_children if skip_children?(asgn_node)
60
58
  next if allowed_construct?(asgn_node)
@@ -95,7 +93,7 @@ module RuboCop
95
93
 
96
94
  def traverse_node(node, &block)
97
95
  # if the node is a block, any assignments are irrelevant
98
- return if node.block_type?
96
+ return if node.any_block_type?
99
97
 
100
98
  result = yield node if ASGN_TYPES.include?(node.type)
101
99
 
@@ -5,17 +5,16 @@ module RuboCop
5
5
  module Lint
6
6
  # Checks for places where binary operator has identical operands.
7
7
  #
8
- # It covers arithmetic operators: `-`, `/`, `%`;
9
- # comparison operators: `==`, `===`, `=~`, `>`, `>=`, `<`, ``<=``;
8
+ # It covers comparison operators: `==`, `===`, `=~`, `>`, `>=`, `<`, ``<=``;
10
9
  # bitwise operators: `|`, `^`, `&`;
11
10
  # boolean operators: `&&`, `||`
12
11
  # and "spaceship" operator - ``<=>``.
13
12
  #
14
13
  # Simple arithmetic operations are allowed by this cop: `+`, `*`, `**`, `<<` and `>>`.
15
14
  # Although these can be rewritten in a different way, it should not be necessary to
16
- # do so. This does not include operations such as `-` or `/` where the result will
17
- # always be the same (`x - x` will always be 0; `x / x` will always be 1), and
18
- # thus are legitimate offenses.
15
+ # do so. Operations such as `-` or `/` where the result will always be the same
16
+ # (`x - x` will always be 0; `x / x` will always be 1) are offenses, but these
17
+ # are covered by `Lint/NumericOperationWithConstantResult` instead.
19
18
  #
20
19
  # @safety
21
20
  # This cop is unsafe as it does not consider side effects when calling methods
@@ -30,7 +29,6 @@ module RuboCop
30
29
  #
31
30
  # @example
32
31
  # # bad
33
- # x / x
34
32
  # x.top >= x.top
35
33
  #
36
34
  # if a.x != 0 && a.x != 0
@@ -47,19 +45,19 @@ module RuboCop
47
45
  #
48
46
  class BinaryOperatorWithIdenticalOperands < Base
49
47
  MSG = 'Binary operator `%<op>s` has identical operands.'
50
- ALLOWED_MATH_OPERATORS = %i[+ * ** << >>].to_set.freeze
48
+ RESTRICT_ON_SEND = %i[== != === <=> =~ && || > >= < <= | ^].freeze
51
49
 
52
50
  def on_send(node)
53
51
  return unless node.binary_operation?
52
+ return unless node.receiver == node.first_argument
54
53
 
55
- lhs, operation, rhs = *node
56
- return if ALLOWED_MATH_OPERATORS.include?(node.method_name)
57
-
58
- add_offense(node, message: format(MSG, op: operation)) if lhs == rhs
54
+ add_offense(node, message: format(MSG, op: node.method_name))
59
55
  end
60
56
 
61
57
  def on_and(node)
62
- add_offense(node, message: format(MSG, op: node.operator)) if node.lhs == node.rhs
58
+ return unless node.lhs == node.rhs
59
+
60
+ add_offense(node, message: format(MSG, op: node.operator))
63
61
  end
64
62
  alias on_or on_and
65
63
  end
@@ -8,6 +8,8 @@ module RuboCop
8
8
  #
9
9
  # This cop mirrors a warning produced by MRI since 2.2.
10
10
  #
11
+ # NOTE: This syntax is no longer valid on Ruby 2.7 or higher.
12
+ #
11
13
  # @example
12
14
  #
13
15
  # # bad
@@ -35,8 +37,12 @@ module RuboCop
35
37
  # dry_ingredients.combine
36
38
  # end
37
39
  class CircularArgumentReference < Base
40
+ extend TargetRubyVersion
41
+
38
42
  MSG = 'Circular argument reference - `%<arg_name>s`.'
39
43
 
44
+ maximum_target_ruby_version 2.6
45
+
40
46
  def on_kwoptarg(node)
41
47
  check_for_circular_argument_references(*node)
42
48
  end
@@ -68,12 +68,12 @@ module RuboCop
68
68
 
69
69
  # @!method constant_assigned_in_block?(node)
70
70
  def_node_matcher :constant_assigned_in_block?, <<~PATTERN
71
- ({^block_type? [^begin_type? ^^block_type?]} nil? ...)
71
+ ({^any_block [^begin ^^any_block]} nil? ...)
72
72
  PATTERN
73
73
 
74
74
  # @!method module_defined_in_block?(node)
75
75
  def_node_matcher :module_defined_in_block?, <<~PATTERN
76
- ({^block_type? [^begin_type? ^^block_type?]} ...)
76
+ ({^any_block [^begin ^^any_block]} ...)
77
77
  PATTERN
78
78
 
79
79
  def on_casgn(node)
@@ -92,7 +92,7 @@ module RuboCop
92
92
  private
93
93
 
94
94
  def method_name(node)
95
- node.ancestors.find(&:block_type?).method_name
95
+ node.ancestors.find(&:any_block_type?).method_name
96
96
  end
97
97
  end
98
98
  end
@@ -0,0 +1,148 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Lint
6
+ # Checks for constant reassignments.
7
+ #
8
+ # Emulates Ruby's runtime warning "already initialized constant X"
9
+ # when a constant is reassigned in the same file and namespace using the
10
+ # `NAME = value` syntax.
11
+ #
12
+ # The cop cannot catch all offenses, like, for example, when a constant
13
+ # is reassigned in another file, or when using metaprogramming (`Module#const_set`).
14
+ #
15
+ # The cop only takes into account constants assigned in a "simple" way: directly
16
+ # inside class/module definition, or within another constant. Other type of assignments
17
+ # (e.g., inside a conditional) are disregarded.
18
+ #
19
+ # The cop also tracks constant removal using `Module#remove_const` with symbol
20
+ # or string argument.
21
+ #
22
+ # @example
23
+ # # bad
24
+ # X = :foo
25
+ # X = :bar
26
+ #
27
+ # # bad
28
+ # class A
29
+ # X = :foo
30
+ # X = :bar
31
+ # end
32
+ #
33
+ # # bad
34
+ # module A
35
+ # X = :foo
36
+ # X = :bar
37
+ # end
38
+ #
39
+ # # good - keep only one assignment
40
+ # X = :bar
41
+ #
42
+ # class A
43
+ # X = :bar
44
+ # end
45
+ #
46
+ # module A
47
+ # X = :bar
48
+ # end
49
+ #
50
+ # # good - use OR assignment
51
+ # X = :foo
52
+ # X ||= :bar
53
+ #
54
+ # # good - use conditional assignment
55
+ # X = :foo
56
+ # X = :bar unless defined?(X)
57
+ #
58
+ # # good - remove the assigned constant first
59
+ # class A
60
+ # X = :foo
61
+ # remove_const :X
62
+ # X = :bar
63
+ # end
64
+ #
65
+ class ConstantReassignment < Base
66
+ MSG = 'Constant `%<constant>s` is already assigned in this namespace.'
67
+
68
+ RESTRICT_ON_SEND = %i[remove_const].freeze
69
+
70
+ # @!method remove_constant(node)
71
+ def_node_matcher :remove_constant, <<~PATTERN
72
+ (send _ :remove_const
73
+ ({sym str} $_))
74
+ PATTERN
75
+
76
+ def on_casgn(node)
77
+ return unless fixed_constant_path?(node)
78
+ return unless simple_assignment?(node)
79
+ return if constant_names.add?(fully_qualified_constant_name(node))
80
+
81
+ add_offense(node, message: format(MSG, constant: node.name))
82
+ end
83
+
84
+ def on_send(node)
85
+ constant = remove_constant(node)
86
+
87
+ return unless constant
88
+
89
+ namespaces = ancestor_namespaces(node)
90
+
91
+ return if namespaces.none?
92
+
93
+ constant_names.delete(fully_qualified_name_for(namespaces, constant))
94
+ end
95
+
96
+ private
97
+
98
+ def fixed_constant_path?(node)
99
+ node.each_path.all? { |path| path.type?(:cbase, :const, :self) }
100
+ end
101
+
102
+ def simple_assignment?(node)
103
+ node.ancestors.all? do |ancestor|
104
+ return true if ancestor.type?(:module, :class)
105
+
106
+ ancestor.begin_type? || ancestor.literal? || ancestor.casgn_type? ||
107
+ freeze_method?(ancestor)
108
+ end
109
+ end
110
+
111
+ def freeze_method?(node)
112
+ node.send_type? && node.method?(:freeze)
113
+ end
114
+
115
+ def fully_qualified_constant_name(node)
116
+ if node.absolute?
117
+ namespace = node.namespace.const_type? ? node.namespace.source : nil
118
+
119
+ "#{namespace}::#{node.name}"
120
+ else
121
+ constant_namespaces = ancestor_namespaces(node) + constant_namespaces(node)
122
+
123
+ fully_qualified_name_for(constant_namespaces, node.name)
124
+ end
125
+ end
126
+
127
+ def fully_qualified_name_for(namespaces, constant)
128
+ ['', *namespaces, constant].join('::')
129
+ end
130
+
131
+ def constant_namespaces(node)
132
+ node.each_path.select(&:const_type?).map(&:short_name)
133
+ end
134
+
135
+ def ancestor_namespaces(node)
136
+ node
137
+ .each_ancestor(:class, :module)
138
+ .map { |ancestor| ancestor.identifier.short_name }
139
+ .reverse
140
+ end
141
+
142
+ def constant_names
143
+ @constant_names ||= Set.new
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubocop:disable Lint/RedundantCopDisableDirective
4
+ # rubocop:disable Style/DoubleCopDisableDirective
5
+ module RuboCop
6
+ module Cop
7
+ module Lint
8
+ # Checks that `# rubocop:enable ...` and `# rubocop:disable ...` statements
9
+ # are strictly formatted.
10
+ #
11
+ # A comment can be added to the directive by prefixing it with `--`.
12
+ #
13
+ # @example
14
+ # # bad
15
+ # # rubocop:disable Layout/LineLength Style/Encoding
16
+ # # ^ missing comma
17
+ #
18
+ # # bad
19
+ # # rubocop:disable
20
+ #
21
+ # # bad
22
+ # # rubocop:disable Layout/LineLength # rubocop:disable Style/Encoding
23
+ #
24
+ # # bad
25
+ # # rubocop:wrongmode Layout/LineLength
26
+ #
27
+ # # good
28
+ # # rubocop:disable Layout/LineLength
29
+ #
30
+ # # good
31
+ # # rubocop:disable Layout/LineLength, Style/Encoding
32
+ #
33
+ # # good
34
+ # # rubocop:disable all
35
+ #
36
+ # # good
37
+ # # rubocop:disable Layout/LineLength -- This is a good comment.
38
+ #
39
+ class CopDirectiveSyntax < Base
40
+ COMMON_MSG = 'Malformed directive comment detected.'
41
+
42
+ MISSING_MODE_NAME_MSG = 'The mode name is missing.'
43
+ INVALID_MODE_NAME_MSG = 'The mode name must be one of `enable`, `disable`, or `todo`.'
44
+ MISSING_COP_NAME_MSG = 'The cop name is missing.'
45
+ MALFORMED_COP_NAMES_MSG = 'Cop names must be separated by commas. ' \
46
+ 'Comment in the directive must start with `--`.'
47
+
48
+ def on_new_investigation
49
+ processed_source.comments.each do |comment|
50
+ directive_comment = DirectiveComment.new(comment)
51
+ next unless directive_comment.start_with_marker?
52
+ next unless directive_comment.malformed?
53
+
54
+ message = offense_message(directive_comment)
55
+ add_offense(comment, message: message)
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ # rubocop:disable Metrics/MethodLength
62
+ def offense_message(directive_comment)
63
+ comment = directive_comment.comment
64
+ after_marker = comment.text.sub(DirectiveComment::DIRECTIVE_MARKER_REGEXP, '')
65
+ mode = after_marker.split(' ', 2).first
66
+ additional_msg = if mode.nil?
67
+ MISSING_MODE_NAME_MSG
68
+ elsif !DirectiveComment::AVAILABLE_MODES.include?(mode)
69
+ INVALID_MODE_NAME_MSG
70
+ elsif directive_comment.missing_cop_name?
71
+ MISSING_COP_NAME_MSG
72
+ else
73
+ MALFORMED_COP_NAMES_MSG
74
+ end
75
+
76
+ "#{COMMON_MSG} #{additional_msg}"
77
+ end
78
+ # rubocop:enable Metrics/MethodLength
79
+ end
80
+ end
81
+ end
82
+ end
83
+ # rubocop:enable Lint/RedundantCopDisableDirective
84
+ # rubocop:enable Style/DoubleCopDisableDirective
@@ -116,7 +116,7 @@ module RuboCop
116
116
 
117
117
  def assumed_usage_context?(node)
118
118
  # Basically, debugger methods are not used as a method argument without arguments.
119
- return false unless node.arguments.empty? && node.each_ancestor(:send, :csend).any?
119
+ return false unless node.arguments.empty? && node.each_ancestor(:call).any?
120
120
  return true if assumed_argument?(node)
121
121
 
122
122
  node.each_ancestor.none? do |ancestor|
@@ -33,6 +33,7 @@ module RuboCop
33
33
 
34
34
  MSG = 'Use `%<constant>s.%<method>s(%<replacement_args>s)` instead of `%<original>s`.'
35
35
 
36
+ RESTRICT_ON_SEND = %i[new digest].freeze
36
37
  NO_ARG_ALGORITHM = %w[BF DES IDEA RC4].freeze
37
38
 
38
39
  # @!method algorithm_const(node)
@@ -51,7 +52,7 @@ module RuboCop
51
52
  PATTERN
52
53
 
53
54
  def on_send(node)
54
- return if node.arguments.any? { |arg| arg.variable? || arg.send_type? || arg.const_type? }
55
+ return if node.arguments.any? { |arg| arg.variable? || arg.call_type? || arg.const_type? }
55
56
  return if digest_const?(node.receiver)
56
57
  return unless algorithm_const(node)
57
58