rubocop 1.59.0 → 1.68.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (352) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +69 -70
  4. data/assets/output.css.erb +159 -0
  5. data/assets/output.html.erb +1 -160
  6. data/config/default.yml +165 -24
  7. data/config/internal_affairs.yml +11 -0
  8. data/exe/rubocop +4 -3
  9. data/lib/rubocop/cached_data.rb +21 -5
  10. data/lib/rubocop/cli/command/auto_generate_config.rb +18 -10
  11. data/lib/rubocop/cli/command/execute_runner.rb +1 -1
  12. data/lib/rubocop/cli/command/lsp.rb +4 -4
  13. data/lib/rubocop/cli/command/show_docs_url.rb +2 -2
  14. data/lib/rubocop/cli/command/version.rb +2 -2
  15. data/lib/rubocop/cli.rb +10 -1
  16. data/lib/rubocop/comment_config.rb +1 -1
  17. data/lib/rubocop/config.rb +41 -13
  18. data/lib/rubocop/config_finder.rb +12 -2
  19. data/lib/rubocop/config_loader.rb +15 -10
  20. data/lib/rubocop/config_loader_resolver.rb +13 -8
  21. data/lib/rubocop/config_obsoletion.rb +1 -1
  22. data/lib/rubocop/config_validator.rb +17 -9
  23. data/lib/rubocop/cop/autocorrect_logic.rb +28 -3
  24. data/lib/rubocop/cop/base.rb +73 -18
  25. data/lib/rubocop/cop/bundler/gem_version.rb +4 -5
  26. data/lib/rubocop/cop/cop.rb +30 -4
  27. data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -12
  28. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +4 -8
  29. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +5 -13
  30. data/lib/rubocop/cop/correctors/line_break_corrector.rb +2 -0
  31. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +1 -1
  32. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +10 -0
  33. data/lib/rubocop/cop/documentation.rb +32 -5
  34. data/lib/rubocop/cop/exclude_limit.rb +1 -1
  35. data/lib/rubocop/cop/force.rb +12 -0
  36. data/lib/rubocop/cop/gemspec/add_runtime_dependency.rb +38 -0
  37. data/lib/rubocop/cop/gemspec/dependency_version.rb +3 -5
  38. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +2 -2
  39. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +5 -1
  40. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +3 -3
  41. data/lib/rubocop/cop/internal_affairs/cop_description.rb +0 -4
  42. data/lib/rubocop/cop/internal_affairs/empty_line_between_expect_offense_and_correction.rb +2 -1
  43. data/lib/rubocop/cop/internal_affairs/example_description.rb +6 -5
  44. data/lib/rubocop/cop/internal_affairs/method_name_end_with.rb +8 -6
  45. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +123 -29
  46. data/lib/rubocop/cop/internal_affairs/redundant_expect_offense_arguments.rb +34 -0
  47. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +6 -21
  48. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +8 -1
  49. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +11 -1
  50. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +0 -5
  51. data/lib/rubocop/cop/internal_affairs.rb +17 -0
  52. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +5 -1
  53. data/lib/rubocop/cop/layout/assignment_indentation.rb +3 -2
  54. data/lib/rubocop/cop/layout/block_alignment.rb +30 -12
  55. data/lib/rubocop/cop/layout/case_indentation.rb +1 -1
  56. data/lib/rubocop/cop/layout/comment_indentation.rb +1 -1
  57. data/lib/rubocop/cop/layout/condition_position.rb +0 -4
  58. data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
  59. data/lib/rubocop/cop/layout/empty_comment.rb +3 -1
  60. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -1
  61. data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +14 -7
  62. data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +1 -1
  63. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +2 -1
  64. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +8 -3
  65. data/lib/rubocop/cop/layout/end_alignment.rb +8 -2
  66. data/lib/rubocop/cop/layout/first_argument_indentation.rb +2 -2
  67. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +18 -4
  68. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +8 -0
  69. data/lib/rubocop/cop/layout/heredoc_indentation.rb +1 -1
  70. data/lib/rubocop/cop/layout/indentation_width.rb +5 -6
  71. data/lib/rubocop/cop/layout/leading_comment_space.rb +56 -1
  72. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +1 -1
  73. data/lib/rubocop/cop/layout/line_length.rb +20 -20
  74. data/lib/rubocop/cop/layout/redundant_line_break.rb +14 -2
  75. data/lib/rubocop/cop/layout/space_around_operators.rb +3 -0
  76. data/lib/rubocop/cop/layout/space_before_block_braces.rb +19 -10
  77. data/lib/rubocop/cop/layout/space_before_brackets.rb +5 -5
  78. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +4 -0
  79. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +1 -1
  80. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +3 -4
  81. data/lib/rubocop/cop/legacy/corrector.rb +12 -2
  82. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +0 -2
  83. data/lib/rubocop/cop/lint/ambiguous_operator.rb +0 -2
  84. data/lib/rubocop/cop/lint/ambiguous_range.rb +4 -1
  85. data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +0 -2
  86. data/lib/rubocop/cop/lint/assignment_in_condition.rb +2 -2
  87. data/lib/rubocop/cop/lint/big_decimal_new.rb +4 -7
  88. data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -3
  89. data/lib/rubocop/cop/lint/circular_argument_reference.rb +0 -13
  90. data/lib/rubocop/cop/lint/debugger.rb +27 -6
  91. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
  92. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +0 -10
  93. data/lib/rubocop/cop/lint/duplicate_branch.rb +39 -4
  94. data/lib/rubocop/cop/lint/duplicate_case_condition.rb +1 -5
  95. data/lib/rubocop/cop/lint/duplicate_hash_key.rb +0 -4
  96. data/lib/rubocop/cop/lint/duplicate_methods.rb +0 -10
  97. data/lib/rubocop/cop/lint/duplicate_set_element.rb +74 -0
  98. data/lib/rubocop/cop/lint/each_with_object_argument.rb +0 -4
  99. data/lib/rubocop/cop/lint/else_layout.rb +0 -2
  100. data/lib/rubocop/cop/lint/empty_conditional_body.rb +29 -8
  101. data/lib/rubocop/cop/lint/empty_ensure.rb +1 -11
  102. data/lib/rubocop/cop/lint/empty_interpolation.rb +0 -4
  103. data/lib/rubocop/cop/lint/empty_when.rb +1 -3
  104. data/lib/rubocop/cop/lint/ensure_return.rb +1 -9
  105. data/lib/rubocop/cop/lint/erb_new_arguments.rb +21 -14
  106. data/lib/rubocop/cop/lint/float_comparison.rb +1 -1
  107. data/lib/rubocop/cop/lint/float_out_of_range.rb +0 -4
  108. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +0 -10
  109. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +23 -12
  110. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +0 -7
  111. data/lib/rubocop/cop/lint/interpolation_check.rb +0 -4
  112. data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +5 -14
  113. data/lib/rubocop/cop/lint/literal_as_condition.rb +1 -1
  114. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +13 -6
  115. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +25 -6
  116. data/lib/rubocop/cop/lint/loop.rb +6 -12
  117. data/lib/rubocop/cop/lint/mixed_case_range.rb +9 -4
  118. data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -7
  119. data/lib/rubocop/cop/lint/next_without_accumulator.rb +0 -4
  120. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +0 -5
  121. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +7 -0
  122. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +1 -1
  123. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +5 -6
  124. data/lib/rubocop/cop/lint/percent_string_array.rb +0 -4
  125. data/lib/rubocop/cop/lint/percent_symbol_array.rb +0 -4
  126. data/lib/rubocop/cop/lint/rand_one.rb +0 -4
  127. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +3 -1
  128. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +14 -9
  129. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +1 -1
  130. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +0 -4
  131. data/lib/rubocop/cop/lint/redundant_with_index.rb +4 -0
  132. data/lib/rubocop/cop/lint/require_parentheses.rb +0 -4
  133. data/lib/rubocop/cop/lint/rescue_exception.rb +0 -4
  134. data/lib/rubocop/cop/lint/rescue_type.rb +1 -3
  135. data/lib/rubocop/cop/lint/return_in_void_context.rb +0 -2
  136. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +9 -4
  137. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +107 -41
  138. data/lib/rubocop/cop/lint/script_permission.rb +3 -3
  139. data/lib/rubocop/cop/lint/shadowed_argument.rb +1 -0
  140. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +6 -10
  141. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  142. data/lib/rubocop/cop/lint/syntax.rb +6 -3
  143. data/lib/rubocop/cop/lint/to_enum_arguments.rb +1 -3
  144. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +88 -0
  145. data/lib/rubocop/cop/lint/unified_integer.rb +0 -4
  146. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -0
  147. data/lib/rubocop/cop/lint/unreachable_code.rb +4 -7
  148. data/lib/rubocop/cop/lint/unreachable_loop.rb +8 -2
  149. data/lib/rubocop/cop/lint/uri_regexp.rb +25 -7
  150. data/lib/rubocop/cop/lint/useless_assignment.rb +19 -16
  151. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +0 -4
  152. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +77 -0
  153. data/lib/rubocop/cop/lint/useless_setter_call.rb +0 -4
  154. data/lib/rubocop/cop/lint/useless_times.rb +1 -1
  155. data/lib/rubocop/cop/lint/void.rb +41 -9
  156. data/lib/rubocop/cop/metrics/block_length.rb +6 -5
  157. data/lib/rubocop/cop/metrics/block_nesting.rb +19 -7
  158. data/lib/rubocop/cop/metrics/class_length.rb +6 -5
  159. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +4 -1
  160. data/lib/rubocop/cop/metrics/method_length.rb +6 -5
  161. data/lib/rubocop/cop/metrics/module_length.rb +6 -5
  162. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +5 -5
  163. data/lib/rubocop/cop/mixin/alignment.rb +5 -1
  164. data/lib/rubocop/cop/mixin/allowed_methods.rb +7 -1
  165. data/lib/rubocop/cop/mixin/allowed_pattern.rb +15 -3
  166. data/lib/rubocop/cop/mixin/annotation_comment.rb +0 -2
  167. data/lib/rubocop/cop/mixin/check_line_breakable.rb +10 -0
  168. data/lib/rubocop/cop/mixin/code_length.rb +12 -1
  169. data/lib/rubocop/cop/mixin/configurable_formatting.rb +1 -0
  170. data/lib/rubocop/cop/mixin/configurable_max.rb +5 -1
  171. data/lib/rubocop/cop/mixin/endless_method_rewriter.rb +24 -0
  172. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +22 -10
  173. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +9 -2
  174. data/lib/rubocop/cop/mixin/line_length_help.rb +7 -2
  175. data/lib/rubocop/cop/mixin/method_complexity.rb +15 -6
  176. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
  177. data/lib/rubocop/cop/mixin/percent_array.rb +1 -1
  178. data/lib/rubocop/cop/mixin/rescue_node.rb +4 -0
  179. data/lib/rubocop/cop/mixin/safe_assignment.rb +1 -1
  180. data/lib/rubocop/cop/mixin/statement_modifier.rb +3 -2
  181. data/lib/rubocop/cop/mixin/string_literals_help.rb +12 -0
  182. data/lib/rubocop/cop/naming/accessor_method_name.rb +5 -0
  183. data/lib/rubocop/cop/naming/block_forwarding.rb +33 -6
  184. data/lib/rubocop/cop/naming/file_name.rb +2 -2
  185. data/lib/rubocop/cop/naming/inclusive_language.rb +13 -5
  186. data/lib/rubocop/cop/naming/predicate_name.rb +55 -29
  187. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +10 -1
  188. data/lib/rubocop/cop/offense.rb +4 -5
  189. data/lib/rubocop/cop/registry.rb +1 -1
  190. data/lib/rubocop/cop/security/compound_hash.rb +2 -2
  191. data/lib/rubocop/cop/security/open.rb +2 -2
  192. data/lib/rubocop/cop/style/access_modifier_declarations.rb +62 -2
  193. data/lib/rubocop/cop/style/accessor_grouping.rb +10 -2
  194. data/lib/rubocop/cop/style/alias.rb +2 -1
  195. data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +79 -0
  196. data/lib/rubocop/cop/style/arguments_forwarding.rb +141 -24
  197. data/lib/rubocop/cop/style/bitwise_predicate.rb +100 -0
  198. data/lib/rubocop/cop/style/block_delimiters.rb +31 -3
  199. data/lib/rubocop/cop/style/case_like_if.rb +1 -1
  200. data/lib/rubocop/cop/style/class_vars.rb +3 -3
  201. data/lib/rubocop/cop/style/collection_compact.rb +19 -10
  202. data/lib/rubocop/cop/style/combinable_defined.rb +115 -0
  203. data/lib/rubocop/cop/style/combinable_loops.rb +7 -0
  204. data/lib/rubocop/cop/style/commented_keyword.rb +12 -3
  205. data/lib/rubocop/cop/style/conditional_assignment.rb +7 -8
  206. data/lib/rubocop/cop/style/copyright.rb +31 -21
  207. data/lib/rubocop/cop/style/data_inheritance.rb +1 -1
  208. data/lib/rubocop/cop/style/def_with_parentheses.rb +0 -2
  209. data/lib/rubocop/cop/style/documentation.rb +24 -24
  210. data/lib/rubocop/cop/style/documentation_method.rb +20 -0
  211. data/lib/rubocop/cop/style/each_for_simple_loop.rb +7 -8
  212. data/lib/rubocop/cop/style/empty_else.rb +6 -5
  213. data/lib/rubocop/cop/style/empty_heredoc.rb +1 -14
  214. data/lib/rubocop/cop/style/empty_literal.rb +31 -22
  215. data/lib/rubocop/cop/style/endless_method.rb +1 -14
  216. data/lib/rubocop/cop/style/eval_with_location.rb +16 -24
  217. data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -1
  218. data/lib/rubocop/cop/style/file_read.rb +2 -5
  219. data/lib/rubocop/cop/style/file_write.rb +2 -5
  220. data/lib/rubocop/cop/style/for.rb +2 -0
  221. data/lib/rubocop/cop/style/format_string.rb +9 -9
  222. data/lib/rubocop/cop/style/format_string_token.rb +2 -2
  223. data/lib/rubocop/cop/style/global_std_stream.rb +7 -1
  224. data/lib/rubocop/cop/style/guard_clause.rb +17 -2
  225. data/lib/rubocop/cop/style/hash_each_methods.rb +35 -8
  226. data/lib/rubocop/cop/style/hash_except.rb +8 -5
  227. data/lib/rubocop/cop/style/hash_syntax.rb +26 -4
  228. data/lib/rubocop/cop/style/identical_conditional_branches.rb +5 -2
  229. data/lib/rubocop/cop/style/if_inside_else.rb +1 -1
  230. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +5 -4
  231. data/lib/rubocop/cop/style/if_with_semicolon.rb +49 -6
  232. data/lib/rubocop/cop/style/in_pattern_then.rb +6 -2
  233. data/lib/rubocop/cop/style/inverse_methods.rb +8 -8
  234. data/lib/rubocop/cop/style/invertible_unless_condition.rb +46 -4
  235. data/lib/rubocop/cop/style/keyword_arguments_merging.rb +67 -0
  236. data/lib/rubocop/cop/style/lambda.rb +1 -1
  237. data/lib/rubocop/cop/style/magic_comment_format.rb +1 -1
  238. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +81 -50
  239. data/lib/rubocop/cop/style/map_into_array.rb +233 -0
  240. data/lib/rubocop/cop/style/map_to_hash.rb +10 -6
  241. data/lib/rubocop/cop/style/map_to_set.rb +1 -1
  242. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +29 -11
  243. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -4
  244. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -2
  245. data/lib/rubocop/cop/style/missing_else.rb +0 -4
  246. data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
  247. data/lib/rubocop/cop/style/multiline_method_signature.rb +10 -1
  248. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +5 -3
  249. data/lib/rubocop/cop/style/multiline_when_then.rb +0 -4
  250. data/lib/rubocop/cop/style/multiple_comparison.rb +28 -47
  251. data/lib/rubocop/cop/style/nested_modifier.rb +1 -1
  252. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
  253. data/lib/rubocop/cop/style/nil_comparison.rb +2 -0
  254. data/lib/rubocop/cop/style/numeric_literal_prefix.rb +1 -1
  255. data/lib/rubocop/cop/style/numeric_predicate.rb +12 -4
  256. data/lib/rubocop/cop/style/object_then.rb +5 -3
  257. data/lib/rubocop/cop/style/one_line_conditional.rb +6 -2
  258. data/lib/rubocop/cop/style/operator_method_call.rb +25 -6
  259. data/lib/rubocop/cop/style/parallel_assignment.rb +8 -9
  260. data/lib/rubocop/cop/style/parentheses_around_condition.rb +8 -0
  261. data/lib/rubocop/cop/style/quoted_symbols.rb +1 -3
  262. data/lib/rubocop/cop/style/raise_args.rb +4 -1
  263. data/lib/rubocop/cop/style/redundant_argument.rb +25 -2
  264. data/lib/rubocop/cop/style/redundant_assignment.rb +10 -2
  265. data/lib/rubocop/cop/style/redundant_begin.rb +5 -1
  266. data/lib/rubocop/cop/style/redundant_condition.rb +4 -4
  267. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +5 -4
  268. data/lib/rubocop/cop/style/redundant_each.rb +7 -4
  269. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +1 -1
  270. data/lib/rubocop/cop/style/redundant_filter_chain.rb +1 -1
  271. data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +46 -0
  272. data/lib/rubocop/cop/style/redundant_line_continuation.rb +40 -7
  273. data/lib/rubocop/cop/style/redundant_parentheses.rb +27 -13
  274. data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -1
  275. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +4 -1
  276. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -24
  277. data/lib/rubocop/cop/style/redundant_return.rb +6 -0
  278. data/lib/rubocop/cop/style/require_order.rb +2 -2
  279. data/lib/rubocop/cop/style/rescue_modifier.rb +13 -1
  280. data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +54 -12
  281. data/lib/rubocop/cop/style/safe_navigation.rb +106 -52
  282. data/lib/rubocop/cop/style/safe_navigation_chain_length.rb +52 -0
  283. data/lib/rubocop/cop/style/sample.rb +1 -3
  284. data/lib/rubocop/cop/style/select_by_regexp.rb +9 -6
  285. data/lib/rubocop/cop/style/semicolon.rb +1 -1
  286. data/lib/rubocop/cop/style/send.rb +4 -4
  287. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +104 -0
  288. data/lib/rubocop/cop/style/slicing_with_range.rb +76 -10
  289. data/lib/rubocop/cop/style/sole_nested_conditional.rb +21 -2
  290. data/lib/rubocop/cop/style/special_global_vars.rb +1 -2
  291. data/lib/rubocop/cop/style/struct_inheritance.rb +1 -1
  292. data/lib/rubocop/cop/style/super_arguments.rb +174 -0
  293. data/lib/rubocop/cop/style/symbol_proc.rb +75 -5
  294. data/lib/rubocop/cop/style/ternary_parentheses.rb +26 -5
  295. data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -1
  296. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  297. data/lib/rubocop/cop/style/while_until_do.rb +0 -2
  298. data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
  299. data/lib/rubocop/cop/style/zero_length_predicate.rb +32 -24
  300. data/lib/rubocop/cop/team.rb +27 -3
  301. data/lib/rubocop/cop/util.rb +8 -2
  302. data/lib/rubocop/cop/utils/regexp_ranges.rb +1 -1
  303. data/lib/rubocop/cop/variable_force/assignment.rb +18 -3
  304. data/lib/rubocop/cop/variable_force/branch.rb +1 -1
  305. data/lib/rubocop/cop/variable_force/variable.rb +5 -1
  306. data/lib/rubocop/cop/variable_force/variable_table.rb +2 -2
  307. data/lib/rubocop/cop/variable_force.rb +13 -1
  308. data/lib/rubocop/cops_documentation_generator.rb +96 -43
  309. data/lib/rubocop/core_ext/string.rb +2 -6
  310. data/lib/rubocop/directive_comment.rb +10 -8
  311. data/lib/rubocop/ext/regexp_node.rb +18 -35
  312. data/lib/rubocop/ext/regexp_parser.rb +4 -21
  313. data/lib/rubocop/file_finder.rb +9 -4
  314. data/lib/rubocop/formatter/clang_style_formatter.rb +3 -7
  315. data/lib/rubocop/formatter/disabled_config_formatter.rb +24 -9
  316. data/lib/rubocop/formatter/formatter_set.rb +7 -1
  317. data/lib/rubocop/formatter/html_formatter.rb +32 -10
  318. data/lib/rubocop/formatter/json_formatter.rb +0 -1
  319. data/lib/rubocop/formatter/junit_formatter.rb +70 -23
  320. data/lib/rubocop/formatter/offense_count_formatter.rb +12 -2
  321. data/lib/rubocop/formatter/tap_formatter.rb +3 -7
  322. data/lib/rubocop/formatter.rb +1 -1
  323. data/lib/rubocop/lockfile.rb +58 -7
  324. data/lib/rubocop/lsp/logger.rb +1 -1
  325. data/lib/rubocop/lsp/routes.rb +12 -15
  326. data/lib/rubocop/lsp/runtime.rb +3 -1
  327. data/lib/rubocop/lsp/server.rb +6 -2
  328. data/lib/rubocop/lsp/severity.rb +1 -1
  329. data/lib/rubocop/lsp.rb +36 -0
  330. data/lib/rubocop/magic_comment.rb +1 -1
  331. data/lib/rubocop/options.rb +17 -12
  332. data/lib/rubocop/path_util.rb +6 -2
  333. data/lib/rubocop/rake_task.rb +1 -1
  334. data/lib/rubocop/remote_config.rb +5 -1
  335. data/lib/rubocop/result_cache.rb +2 -8
  336. data/lib/rubocop/rspec/cop_helper.rb +8 -2
  337. data/lib/rubocop/rspec/expect_offense.rb +17 -8
  338. data/lib/rubocop/rspec/shared_contexts.rb +75 -18
  339. data/lib/rubocop/rspec/support.rb +3 -0
  340. data/lib/rubocop/runner.rb +31 -9
  341. data/lib/rubocop/server/cache.rb +16 -2
  342. data/lib/rubocop/server/client_command/exec.rb +2 -3
  343. data/lib/rubocop/server/client_command/start.rb +1 -1
  344. data/lib/rubocop/server/core.rb +5 -0
  345. data/lib/rubocop/server/server_command/exec.rb +0 -1
  346. data/lib/rubocop/target_finder.rb +84 -78
  347. data/lib/rubocop/target_ruby.rb +87 -81
  348. data/lib/rubocop/version.rb +45 -9
  349. data/lib/rubocop/yaml_duplication_checker.rb +20 -26
  350. data/lib/rubocop.rb +21 -1
  351. metadata +33 -35
  352. /data/lib/rubocop/formatter/{git_hub_actions_formatter.rb → github_actions_formatter.rb} +0 -0
@@ -29,7 +29,11 @@ module RuboCop
29
29
  end
30
30
 
31
31
  def assign(node)
32
- @assignments << Assignment.new(node, self)
32
+ assignment = Assignment.new(node, self)
33
+
34
+ @assignments.last&.reassigned! unless captured_by_block?
35
+
36
+ @assignments << assignment
33
37
  end
34
38
 
35
39
  def referenced?
@@ -61,8 +61,8 @@ module RuboCop
61
61
  "at #{node.source_range}, #{node.inspect}"
62
62
  end
63
63
 
64
- variable.assign(node)
65
64
  mark_variable_as_captured_by_block_if_so(variable)
65
+ variable.assign(node)
66
66
  end
67
67
 
68
68
  def reference_variable(name, node)
@@ -87,8 +87,8 @@ module RuboCop
87
87
  # So just skip.
88
88
  return unless variable
89
89
 
90
- variable.reference!(node)
91
90
  mark_variable_as_captured_by_block_if_so(variable)
91
+ variable.reference!(node)
92
92
  end
93
93
 
94
94
  def find_variable(name)
@@ -27,7 +27,10 @@ module RuboCop
27
27
  class VariableForce < Force # rubocop:disable Metrics/ClassLength
28
28
  VARIABLE_ASSIGNMENT_TYPE = :lvasgn
29
29
  REGEXP_NAMED_CAPTURE_TYPE = :match_with_lvasgn
30
- VARIABLE_ASSIGNMENT_TYPES = [VARIABLE_ASSIGNMENT_TYPE, REGEXP_NAMED_CAPTURE_TYPE].freeze
30
+ PATTERN_MATCH_VARIABLE_TYPE = :match_var
31
+ VARIABLE_ASSIGNMENT_TYPES = [
32
+ VARIABLE_ASSIGNMENT_TYPE, REGEXP_NAMED_CAPTURE_TYPE, PATTERN_MATCH_VARIABLE_TYPE
33
+ ].freeze
31
34
 
32
35
  ARGUMENT_DECLARATION_TYPES = [
33
36
  :arg, :optarg, :restarg,
@@ -112,6 +115,7 @@ module RuboCop
112
115
  NODE_HANDLER_METHOD_NAMES = [
113
116
  [VARIABLE_ASSIGNMENT_TYPE, :process_variable_assignment],
114
117
  [REGEXP_NAMED_CAPTURE_TYPE, :process_regexp_named_captures],
118
+ [PATTERN_MATCH_VARIABLE_TYPE, :process_pattern_match_variable],
115
119
  [MULTIPLE_ASSIGNMENT_TYPE, :process_variable_multiple_assignment],
116
120
  [VARIABLE_REFERENCE_TYPE, :process_variable_referencing],
117
121
  [RESCUE_TYPE, :process_rescue],
@@ -175,6 +179,14 @@ module RuboCop
175
179
  skip_children!
176
180
  end
177
181
 
182
+ def process_pattern_match_variable(node)
183
+ name = node.children.first
184
+
185
+ variable_table.declare_variable(name, node) unless variable_table.variable_exist?(name)
186
+
187
+ skip_children!
188
+ end
189
+
178
190
  def regexp_captured_names(node)
179
191
  regexp = node.to_regexp
180
192
 
@@ -1,23 +1,49 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'fileutils'
4
+ require 'yard'
4
5
 
5
6
  # Class for generating documentation of all cops departments
6
7
  # @api private
7
8
  class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
8
9
  include ::RuboCop::Cop::Documentation
10
+ CopData = Struct.new(
11
+ :cop, :description, :example_objects, :safety_objects, :see_objects, :config, keyword_init: true
12
+ )
13
+
14
+ STRUCTURE = {
15
+ name: ->(data) { cop_header(data.cop) },
16
+ required_ruby_version: ->(data) { required_ruby_version(data.cop) },
17
+ properties: ->(data) { properties(data.cop) },
18
+ description: ->(data) { "#{data.description}\n" },
19
+ safety: ->(data) { safety_object(data.safety_objects, data.cop) },
20
+ examples: ->(data) { examples(data.example_objects, data.cop) },
21
+ configuration: ->(data) { configurations(data.cop.department, data.config, data.cop) },
22
+ references: ->(data) { references(data.cop, data.see_objects) }
23
+ }.freeze
24
+
9
25
  # This class will only generate documentation for cops that belong to one of
10
26
  # the departments given in the `departments` array. E.g. if we only wanted
11
27
  # documentation for Lint cops:
12
28
  #
13
29
  # CopsDocumentationGenerator.new(departments: ['Lint']).call
14
30
  #
15
- def initialize(departments: [])
31
+ # You can append additional information:
32
+ #
33
+ # callback = ->(data) { required_rails_version(data.cop) }
34
+ # CopsDocumentationGenerator.new(extra_info: { ruby_version: callback }).call
35
+ #
36
+ # This will insert the string returned from the lambda _after_ the section from RuboCop itself.
37
+ # See `CopsDocumentationGenerator::STRUCTURE` for available sections.
38
+ #
39
+ def initialize(departments: [], extra_info: {}, base_dir: Dir.pwd)
16
40
  @departments = departments.map(&:to_sym).sort!
41
+ @extra_info = extra_info
17
42
  @cops = RuboCop::Cop::Registry.global
18
43
  @config = RuboCop::ConfigLoader.default_configuration
19
- @docs_path = "#{Dir.pwd}/docs/modules/ROOT/pages/"
20
- FileUtils.mkdir_p(@docs_path)
44
+ @base_dir = base_dir
45
+ @docs_path = "#{base_dir}/docs/modules/ROOT"
46
+ FileUtils.mkdir_p("#{@docs_path}/pages")
21
47
  end
22
48
 
23
49
  def call
@@ -37,24 +63,21 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
37
63
  cops.with_department(department).sort!
38
64
  end
39
65
 
40
- def cops_body(cop, description, examples_objects, safety_objects, see_objects, pars) # rubocop:disable Metrics/AbcSize, Metrics/ParameterLists
41
- check_examples_to_have_the_default_enforced_style!(examples_objects, cop)
42
-
43
- content = h2(cop.cop_name)
44
- content << required_ruby_version(cop)
45
- content << properties(cop)
46
- content << "#{description}\n"
47
- content << safety_object(safety_objects) if safety_objects.any? { |s| !s.text.blank? }
48
- content << examples(examples_objects) if examples_objects.any?
49
- content << configurations(cop.department, pars)
50
- content << references(cop, see_objects)
66
+ def cops_body(data)
67
+ check_examples_to_have_the_default_enforced_style!(data.example_objects, data.cop)
68
+
69
+ content = +''
70
+ STRUCTURE.each do |section, block|
71
+ content << instance_exec(data, &block)
72
+ content << @extra_info[section].call(data) if @extra_info[section]
73
+ end
51
74
  content
52
75
  end
53
76
 
54
- def check_examples_to_have_the_default_enforced_style!(examples_object, cop)
55
- return if examples_object.none?
77
+ def check_examples_to_have_the_default_enforced_style!(example_objects, cop)
78
+ return if example_objects.none?
56
79
 
57
- examples_describing_enforced_style = examples_object.map(&:name).grep(/EnforcedStyle:/)
80
+ examples_describing_enforced_style = example_objects.map(&:name).grep(/EnforcedStyle:/)
58
81
  return if examples_describing_enforced_style.none?
59
82
 
60
83
  if examples_describing_enforced_style.index { |name| name.match?('default') }.nonzero?
@@ -66,16 +89,20 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
66
89
  raise "Specify the default EnforcedStyle for #{cop.cop_name}"
67
90
  end
68
91
 
69
- def examples(examples_object)
70
- examples_object.each_with_object(h3('Examples').dup) do |example, content|
92
+ def examples(example_objects, cop)
93
+ return '' if example_objects.none?
94
+
95
+ example_objects.each_with_object(cop_subsection('Examples', cop).dup) do |example, content|
71
96
  content << "\n" unless content.end_with?("\n\n")
72
- content << h4(example.name) unless example.name == ''
97
+ content << example_header(example.name, cop) unless example.name == ''
73
98
  content << code_example(example)
74
99
  end
75
100
  end
76
101
 
77
- def safety_object(safety_object_objects)
78
- safety_object_objects.each_with_object(h3('Safety').dup) do |safety_object, content|
102
+ def safety_object(safety_objects, cop)
103
+ return '' if safety_objects.all? { |s| s.text.blank? }
104
+
105
+ safety_objects.each_with_object(cop_subsection('Safety', cop).dup) do |safety_object, content|
79
106
  next if safety_object.text.blank?
80
107
 
81
108
  content << "\n" unless content.end_with?("\n\n")
@@ -97,7 +124,9 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
97
124
  'Version Changed'
98
125
  ]
99
126
  autocorrect = if cop.support_autocorrect?
100
- "Yes#{' (Unsafe)' unless cop.new(config).safe_autocorrect?}"
127
+ context = cop.new.always_autocorrect? ? 'Always' : 'Command-line only'
128
+
129
+ "#{context}#{' (Unsafe)' unless cop.new(config).safe_autocorrect?}"
101
130
  else
102
131
  'No'
103
132
  end
@@ -113,22 +142,25 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
113
142
  end
114
143
  # rubocop:enable Metrics/MethodLength
115
144
 
116
- def h2(title)
145
+ def cop_header(cop)
117
146
  content = +"\n"
118
- content << "== #{title}\n"
147
+ content << "[##{to_anchor(cop.cop_name)}]\n"
148
+ content << "== #{cop.cop_name}\n"
119
149
  content << "\n"
120
150
  content
121
151
  end
122
152
 
123
- def h3(title)
153
+ def cop_subsection(title, cop)
124
154
  content = +"\n"
155
+ content << "[##{to_anchor(title)}-#{to_anchor(cop.cop_name)}]\n"
125
156
  content << "=== #{title}\n"
126
157
  content << "\n"
127
158
  content
128
159
  end
129
160
 
130
- def h4(title)
131
- content = +"==== #{title}\n"
161
+ def example_header(title, cop)
162
+ content = +"[##{to_anchor(title)}-#{to_anchor(cop.cop_name)}]\n"
163
+ content << "==== #{title}\n"
132
164
  content << "\n"
133
165
  content
134
166
  end
@@ -140,7 +172,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
140
172
  content
141
173
  end
142
174
 
143
- def configurations(department, pars)
175
+ def configurations(department, pars, cop)
144
176
  return '' if pars.empty?
145
177
 
146
178
  header = ['Name', 'Default value', 'Configurable values']
@@ -155,7 +187,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
155
187
  [configuration_name(department, name), default, configurable]
156
188
  end
157
189
 
158
- h3('Configurable attributes') + to_table(header, content)
190
+ cop_subsection('Configurable attributes', cop) + to_table(header, content)
159
191
  end
160
192
 
161
193
  def configuration_name(department, name)
@@ -216,7 +248,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
216
248
  else
217
249
  wrap_backtick(val.nil? ? '<none>' : val)
218
250
  end
219
- value.gsub("#{Dir.pwd}/", '').rstrip
251
+ value.gsub("#{@base_dir}/", '').rstrip
220
252
  end
221
253
 
222
254
  def wrap_backtick(value)
@@ -233,7 +265,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
233
265
  urls = RuboCop::Cop::MessageAnnotator.new(config, cop.name, cop_config, {}).urls
234
266
  return '' if urls.empty? && see_objects.empty?
235
267
 
236
- content = h3('References')
268
+ content = cop_subsection('References', cop)
237
269
  content << urls.map { |url| "* #{url}" }.join("\n")
238
270
  content << "\n" unless urls.empty?
239
271
  content << see_objects.map { |see| "* #{see.name}" }.join("\n")
@@ -245,40 +277,52 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
245
277
  return '' unless department == :Layout
246
278
 
247
279
  filename = "#{department_to_basename(department)}_footer.adoc"
248
- file = "#{Dir.pwd}/docs/modules/ROOT/partials/#{filename}"
280
+ file = "#{docs_path}/partials/#{filename}"
249
281
  return '' unless File.exist?(file)
250
282
 
251
283
  "\ninclude::../partials/#{filename}[]\n"
252
284
  end
253
285
 
286
+ # rubocop:disable Metrics/MethodLength
254
287
  def print_cops_of_department(department)
255
288
  selected_cops = cops_of_department(department)
256
- content = +"= #{department}\n"
289
+ content = +<<~HEADER
290
+ ////
291
+ Do NOT edit this file by hand directly, as it is automatically generated.
292
+
293
+ Please make any necessary changes to the cop documentation within the source files themselves.
294
+ ////
295
+
296
+ = #{department}
297
+ HEADER
257
298
  selected_cops.each { |cop| content << print_cop_with_doc(cop) }
258
299
  content << footer_for_department(department)
259
- file_name = "#{docs_path}/#{department_to_basename(department)}.adoc"
300
+ file_name = "#{docs_path}/pages/#{department_to_basename(department)}.adoc"
260
301
  File.open(file_name, 'w') do |file|
261
302
  puts "* generated #{file_name}"
262
303
  file.write("#{content.strip}\n")
263
304
  end
264
305
  end
306
+ # rubocop:enable Metrics/MethodLength
265
307
 
266
308
  def print_cop_with_doc(cop) # rubocop:todo Metrics/AbcSize, Metrics/MethodLength
267
309
  cop_config = config.for_cop(cop)
268
310
  non_display_keys = %w[
269
- Description Enabled StyleGuide Reference Safe SafeAutoCorrect VersionAdded
311
+ AutoCorrect Description Enabled StyleGuide Reference Safe SafeAutoCorrect VersionAdded
270
312
  VersionChanged
271
313
  ]
272
314
  pars = cop_config.reject { |k| non_display_keys.include? k }
273
315
  description = 'No documentation'
274
- examples_object = safety_object = see_object = []
316
+ example_objects = safety_objects = see_objects = []
275
317
  cop_code(cop) do |code_object|
276
318
  description = code_object.docstring unless code_object.docstring.blank?
277
- examples_object = code_object.tags('example')
278
- safety_object = code_object.tags('safety')
279
- see_object = code_object.tags('see')
319
+ example_objects = code_object.tags('example')
320
+ safety_objects = code_object.tags('safety')
321
+ see_objects = code_object.tags('see')
280
322
  end
281
- cops_body(cop, description, examples_object, safety_object, see_object, pars)
323
+ data = CopData.new(cop: cop, description: description, example_objects: example_objects,
324
+ safety_objects: safety_objects, see_objects: see_objects, config: pars)
325
+ cops_body(data)
282
326
  end
283
327
 
284
328
  def cop_code(cop)
@@ -294,7 +338,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
294
338
  filename = "#{department_to_basename(department)}.adoc"
295
339
  content = +"=== Department xref:#{filename}[#{type_title}]\n\n"
296
340
  cops_of_department(department).each do |cop|
297
- anchor = cop.cop_name.sub('/', '').downcase
341
+ anchor = to_anchor(cop.cop_name)
298
342
  content << "* xref:#{filename}##{anchor}[#{cop.cop_name}]\n"
299
343
  end
300
344
 
@@ -302,7 +346,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
302
346
  end
303
347
 
304
348
  def print_table_of_contents
305
- path = "#{docs_path}/cops.adoc"
349
+ path = "#{docs_path}/pages/cops.adoc"
306
350
 
307
351
  File.write(path, table_contents) and return unless File.exist?(path)
308
352
 
@@ -326,4 +370,13 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
326
370
 
327
371
  status == 'pending' ? 'Pending' : 'Enabled'
328
372
  end
373
+
374
+ # HTML anchor are somewhat limited in what characters they can contain, just
375
+ # accept a known-good subset. As long as it's consistent it doesn't matter.
376
+ #
377
+ # Style/AccessModifierDeclarations => styleaccessmodifierdeclarations
378
+ # OnlyFor: [] (default) => onlyfor_-__-_default_
379
+ def to_anchor(title)
380
+ title.delete('/').tr(' ', '-').gsub(/[^a-zA-Z0-9-]/, '_').downcase
381
+ end
329
382
  end
@@ -9,12 +9,8 @@ class String
9
9
  # @return [Boolean] true is the string is blank, false otherwise
10
10
  #
11
11
  # @example
12
- # ''.blank? #=> true
13
- #
14
- # @example
15
- # ' '.blank? #=> true
16
- #
17
- # @example
12
+ # ''.blank? #=> true
13
+ # ' '.blank? #=> true
18
14
  # ' test'.blank? #=> false
19
15
  def blank?
20
16
  empty? || lstrip.empty?
@@ -6,9 +6,11 @@ module RuboCop
6
6
  # cops it contains.
7
7
  class DirectiveComment
8
8
  # @api private
9
- REDUNDANT_DIRECTIVE_COP_DEPARTMENT = 'Lint'
9
+ LINT_DEPARTMENT = 'Lint'
10
10
  # @api private
11
- REDUNDANT_DIRECTIVE_COP = "#{REDUNDANT_DIRECTIVE_COP_DEPARTMENT}/RedundantCopDisableDirective"
11
+ LINT_REDUNDANT_DIRECTIVE_COP = "#{LINT_DEPARTMENT}/RedundantCopDisableDirective"
12
+ # @api private
13
+ LINT_SYNTAX_COP = "#{LINT_DEPARTMENT}/Syntax"
12
14
  # @api private
13
15
  COP_NAME_PATTERN = '([A-Z]\w+/)*(?:[A-Z]\w+)'
14
16
  # @api private
@@ -118,9 +120,10 @@ module RuboCop
118
120
  end
119
121
 
120
122
  def parsed_cop_names
121
- splitted_cops_string.map do |name|
123
+ cops = splitted_cops_string.map do |name|
122
124
  department?(name) ? cop_names_for_department(name) : name
123
125
  end.flatten
126
+ cops - [LINT_SYNTAX_COP]
124
127
  end
125
128
 
126
129
  def department?(name)
@@ -128,17 +131,16 @@ module RuboCop
128
131
  end
129
132
 
130
133
  def all_cop_names
131
- exclude_redundant_directive_cop(cop_registry.names)
134
+ exclude_lint_department_cops(cop_registry.names)
132
135
  end
133
136
 
134
137
  def cop_names_for_department(department)
135
138
  names = cop_registry.names_for_department(department)
136
- has_redundant_directive_cop = department == REDUNDANT_DIRECTIVE_COP_DEPARTMENT
137
- has_redundant_directive_cop ? exclude_redundant_directive_cop(names) : names
139
+ department == LINT_DEPARTMENT ? exclude_lint_department_cops(names) : names
138
140
  end
139
141
 
140
- def exclude_redundant_directive_cop(cops)
141
- cops - [REDUNDANT_DIRECTIVE_COP]
142
+ def exclude_lint_department_cops(cops)
143
+ cops - [LINT_REDUNDANT_DIRECTIVE_COP, LINT_SYNTAX_COP]
142
144
  end
143
145
  end
144
146
  end
@@ -15,49 +15,24 @@ module RuboCop
15
15
  # see `ext/regexp_parser`.
16
16
  attr_reader :parsed_tree
17
17
 
18
- if Gem::Version.new(Regexp::Parser::VERSION) >= Gem::Version.new('2.0')
19
- def assign_properties(*)
20
- super
18
+ def assign_properties(*)
19
+ super
21
20
 
22
- str = with_interpolations_blanked
23
- @parsed_tree = begin
24
- Regexp::Parser.parse(str, options: options)
25
- rescue StandardError
26
- nil
27
- end
28
- origin = loc.begin.end
29
- @parsed_tree&.each_expression(true) { |e| e.origin = origin }
30
- end
31
- # Please remove this `else` branch when support for regexp_parser 1.8 will be dropped.
32
- # It's for compatibility with regexp_parser 1.8 and will never be maintained.
33
- else
34
- def assign_properties(*)
35
- super
36
-
37
- str = with_interpolations_blanked
38
- begin
39
- @parsed_tree = Regexp::Parser.parse(str, options: options)
40
- rescue StandardError
41
- @parsed_tree = nil
42
- else
43
- origin = loc.begin.end
44
- source = @parsed_tree.to_s
45
- @parsed_tree.each_expression(true) do |e|
46
- e.origin = origin
47
- e.source = source
48
- end
49
- end
21
+ str = with_interpolations_blanked
22
+ @parsed_tree = begin
23
+ Regexp::Parser.parse(str, options: options)
24
+ rescue StandardError
25
+ nil
50
26
  end
27
+ origin = loc.begin.end
28
+ @parsed_tree&.each_expression(true) { |e| e.origin = origin }
51
29
  end
52
30
 
53
31
  def each_capture(named: ANY)
54
32
  return enum_for(__method__, named: named) unless block_given?
55
33
 
56
34
  parsed_tree&.traverse do |event, exp, _index|
57
- yield(exp) if event == :enter &&
58
- named == exp.respond_to?(:name) &&
59
- exp.respond_to?(:capturing?) &&
60
- exp.capturing?
35
+ yield(exp) if named_capturing?(exp, event, named)
61
36
  end
62
37
 
63
38
  self
@@ -65,6 +40,14 @@ module RuboCop
65
40
 
66
41
  private
67
42
 
43
+ def named_capturing?(exp, event, named)
44
+ event == :enter &&
45
+ named == exp.respond_to?(:name) &&
46
+ !exp.text.start_with?('(?<=') &&
47
+ exp.respond_to?(:capturing?) &&
48
+ exp.capturing?
49
+ end
50
+
68
51
  def with_interpolations_blanked
69
52
  # Ignore the trailing regopt node
70
53
  children[0...-1].map do |child|
@@ -22,26 +22,9 @@ module RuboCop
22
22
  module Base
23
23
  attr_accessor :origin
24
24
 
25
- if Gem::Version.new(Regexp::Parser::VERSION) >= Gem::Version.new('2.0')
26
- # Shortcut to `loc.expression`
27
- def expression
28
- @expression ||= origin.adjust(begin_pos: ts, end_pos: ts + full_length)
29
- end
30
- # Please remove this `else` branch when support for regexp_parser 1.8 will be dropped.
31
- # It's for compatibility with regexp_parser 1.8 and will never be maintained.
32
- else
33
- attr_accessor :source
34
-
35
- def start_index
36
- # ts is a byte index; convert it to a character index
37
- @start_index ||= source.byteslice(0, ts).length
38
- end
39
-
40
- # Shortcut to `loc.expression`
41
- def expression
42
- end_pos = start_index + full_length
43
- @expression ||= origin.adjust(begin_pos: start_index, end_pos: end_pos)
44
- end
25
+ # Shortcut to `loc.expression`
26
+ def expression
27
+ @expression ||= origin.adjust(begin_pos: ts, end_pos: ts + full_length)
45
28
  end
46
29
 
47
30
  # @returns a location map like `parser` does, with:
@@ -69,8 +52,8 @@ module RuboCop
69
52
 
70
53
  body = expression.adjust(end_pos: -q.text.length)
71
54
  q.origin = origin
72
- q.source = source if q.respond_to?(:source=) # for regexp_parser 1.8
73
55
  q_loc = q.expression
56
+
74
57
  { body: body, quantifier: q_loc }
75
58
  end
76
59
  end
@@ -23,15 +23,20 @@ module RuboCop
23
23
  last_file
24
24
  end
25
25
 
26
+ def traverse_directories_upwards(start_dir, stop_dir = nil)
27
+ Pathname.new(start_dir).expand_path.ascend do |dir|
28
+ yield(dir)
29
+ dir = dir.to_s
30
+ break if dir == stop_dir || dir == FileFinder.root_level
31
+ end
32
+ end
33
+
26
34
  private
27
35
 
28
36
  def traverse_files_upwards(filename, start_dir, stop_dir)
29
- Pathname.new(start_dir).expand_path.ascend do |dir|
37
+ traverse_directories_upwards(start_dir, stop_dir) do |dir|
30
38
  file = dir + filename
31
39
  yield(file.to_s) if file.exist?
32
-
33
- dir = dir.to_s
34
- break if dir == stop_dir || dir == FileFinder.root_level
35
40
  end
36
41
  end
37
42
  end
@@ -24,14 +24,10 @@ module RuboCop
24
24
  message: message(offense)
25
25
  )
26
26
 
27
- begin
28
- return unless valid_line?(offense)
27
+ return unless valid_line?(offense)
29
28
 
30
- report_line(offense.location)
31
- report_highlighted_area(offense.highlighted_area)
32
- rescue IndexError
33
- # range is not on a valid line; perhaps the source file is empty
34
- end
29
+ report_line(offense.location)
30
+ report_highlighted_area(offense.highlighted_area)
35
31
  end
36
32
 
37
33
  def valid_line?(offense)
@@ -10,7 +10,7 @@ module RuboCop
10
10
  HEADING = <<~COMMENTS
11
11
  # This configuration was generated by
12
12
  # `%<command>s`
13
- # %<timestamp>susing RuboCop version #{Version.version}.
13
+ # %<timestamp>susing RuboCop version #{Version::STRING}.
14
14
  # The point is for the user to remove these configuration records
15
15
  # one by one as the offenses are removed from the code base.
16
16
  # Note that changes in the inspected code, or installation of new
@@ -30,7 +30,8 @@ module RuboCop
30
30
  @files_with_offenses ||= {}
31
31
  end
32
32
 
33
- def file_started(_file, _file_info)
33
+ def file_started(_file, options)
34
+ @config_for_pwd = options[:config_store].for_pwd
34
35
  @exclude_limit_option = @options[:exclude_limit]
35
36
  @exclude_limit = Integer(@exclude_limit_option ||
36
37
  RuboCop::Options::DEFAULT_MAXIMUM_EXCLUSION_ITEMS)
@@ -115,16 +116,24 @@ module RuboCop
115
116
  def set_max(cfg, cop_name)
116
117
  return unless cfg[:exclude_limit]
117
118
 
118
- # In case auto_gen_only_exclude is set, only modify the maximum if the
119
- # files are not excluded one by one.
120
- if !@options[:auto_gen_only_exclude] || @files_with_offenses[cop_name].size > @exclude_limit
121
- cfg.merge!(cfg[:exclude_limit])
122
- end
119
+ cfg.merge!(cfg[:exclude_limit]) if should_set_max?(cop_name)
123
120
 
124
121
  # Remove already used exclude_limit.
125
122
  cfg.reject! { |key| key == :exclude_limit }
126
123
  end
127
124
 
125
+ def should_set_max?(cop_name)
126
+ max_set_in_user_config =
127
+ @config_for_pwd.for_cop(cop_name)['Max'] != default_config(cop_name)['Max']
128
+
129
+ max_allowed = !max_set_in_user_config && !no_exclude_limit?
130
+ return false unless max_allowed
131
+
132
+ # In case auto_gen_only_exclude is set, only modify the maximum if the files are not
133
+ # excluded one by one.
134
+ !@options[:auto_gen_only_exclude] || @files_with_offenses[cop_name].size > @exclude_limit
135
+ end
136
+
128
137
  def output_cop_comments(output_buffer, cfg, cop_name, offense_count)
129
138
  output_buffer.puts "# Offense count: #{offense_count}" if show_offense_counts?
130
139
 
@@ -192,8 +201,8 @@ module RuboCop
192
201
  # 'Enabled' option will be put into file only if exclude
193
202
  # limit is exceeded.
194
203
  rejected_keys = ['Enabled']
195
- rejected_keys << 'EnforcedStyle' unless auto_gen_enforced_style?
196
- cfg.reject { |key| rejected_keys.include?(key) }
204
+ rejected_keys << /\AEnforcedStyle\w*/ unless auto_gen_enforced_style?
205
+ cfg.reject { |key| include_or_match?(rejected_keys, key) }
197
206
  end
198
207
 
199
208
  def output_offending_files(output_buffer, cfg, cop_name)
@@ -262,6 +271,12 @@ module RuboCop
262
271
  def no_exclude_limit?
263
272
  @options[:no_exclude_limit] == false
264
273
  end
274
+
275
+ # Returns true if the given arr include the given elm or if any of the
276
+ # given arr is a regexp that matches the given elm.
277
+ def include_or_match?(arr, elm)
278
+ arr.include?(elm) || arr.any? { |x| x.is_a?(Regexp) && x.match?(elm) }
279
+ end
265
280
  end
266
281
  end
267
282
  end
@@ -27,6 +27,7 @@ module RuboCop
27
27
  '[t]ap' => 'TapFormatter',
28
28
  '[w]orst' => 'WorstOffendersFormatter'
29
29
  }.freeze
30
+ BUILTIN_FORMATTER_NAMES = BUILTIN_FORMATTERS_FOR_KEYS.keys.map { |key| key.delete('[]') }
30
31
 
31
32
  FORMATTER_APIS = %i[started finished].freeze
32
33
 
@@ -88,7 +89,12 @@ module RuboCop
88
89
  /^\[#{specified_key}\]/.match?(key) || specified_key == key.delete('[]')
89
90
  end
90
91
 
91
- raise %(No formatter for "#{specified_key}") if matching_keys.empty?
92
+ if matching_keys.empty?
93
+ similar_name = NameSimilarity.find_similar_name(specified_key, BUILTIN_FORMATTER_NAMES)
94
+ suggestion = %( Did you mean? "#{similar_name}") if similar_name
95
+
96
+ raise Rainbow(%(Formatter "#{specified_key}" not found.#{suggestion})).red
97
+ end
92
98
 
93
99
  raise %(Cannot determine formatter for "#{specified_key}") if matching_keys.size > 1
94
100