rubocop 1.90.0 → 1.92.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 (303) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +241 -11
  4. data/config/obsoletion.yml +9 -0
  5. data/lib/rubocop/cached_data.rb +47 -7
  6. data/lib/rubocop/changed_files.rb +134 -0
  7. data/lib/rubocop/cli/command/cop_names.rb +57 -0
  8. data/lib/rubocop/cli/command/execute_runner.rb +23 -3
  9. data/lib/rubocop/cli/command/explain.rb +34 -0
  10. data/lib/rubocop/cli/command/show_cops.rb +6 -0
  11. data/lib/rubocop/cli/command/show_docs_url.rb +6 -4
  12. data/lib/rubocop/cli.rb +11 -4
  13. data/lib/rubocop/comment_config/directive_range.rb +3 -1
  14. data/lib/rubocop/comment_config/disable_next.rb +49 -3
  15. data/lib/rubocop/comment_config/push_pop.rb +55 -0
  16. data/lib/rubocop/comment_config.rb +32 -53
  17. data/lib/rubocop/config.rb +10 -0
  18. data/lib/rubocop/config_loader.rb +18 -7
  19. data/lib/rubocop/config_loader_resolver.rb +79 -12
  20. data/lib/rubocop/config_obsoletion/cop_rule.rb +2 -1
  21. data/lib/rubocop/config_obsoletion/removed_cop.rb +9 -1
  22. data/lib/rubocop/config_obsoletion.rb +1 -1
  23. data/lib/rubocop/config_validator.rb +29 -3
  24. data/lib/rubocop/cop/autocorrect_logic.rb +10 -5
  25. data/lib/rubocop/cop/badge.rb +1 -1
  26. data/lib/rubocop/cop/base.rb +57 -24
  27. data/lib/rubocop/cop/bundler/gem_comment.rb +0 -1
  28. data/lib/rubocop/cop/bundler/ordered_gems.rb +0 -8
  29. data/lib/rubocop/cop/cop_documentation.rb +81 -0
  30. data/lib/rubocop/cop/cop_explanation.rb +140 -0
  31. data/lib/rubocop/cop/correctors/alignment_corrector.rb +13 -1
  32. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +22 -7
  33. data/lib/rubocop/cop/correctors/empty_line_corrector.rb +1 -1
  34. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +23 -2
  35. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +45 -8
  36. data/lib/rubocop/cop/correctors.rb +2 -2
  37. data/lib/rubocop/cop/documentation.rb +1 -1
  38. data/lib/rubocop/cop/gemspec/dependency_version.rb +0 -6
  39. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +0 -6
  40. data/lib/rubocop/cop/gemspec/require_mfa.rb +1 -1
  41. data/lib/rubocop/cop/generator.rb +1 -1
  42. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +2 -5
  43. data/lib/rubocop/cop/internal_affairs/node_type_group.rb +0 -7
  44. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
  45. data/lib/rubocop/cop/internal_affairs/redundant_context_config_parameter.rb +1 -7
  46. data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +1 -7
  47. data/lib/rubocop/cop/layout/argument_alignment.rb +2 -0
  48. data/lib/rubocop/cop/layout/block_alignment.rb +27 -0
  49. data/lib/rubocop/cop/layout/case_indentation.rb +25 -9
  50. data/lib/rubocop/cop/layout/class_structure.rb +9 -1
  51. data/lib/rubocop/cop/layout/comment_indentation.rb +8 -5
  52. data/lib/rubocop/cop/layout/def_end_alignment.rb +4 -0
  53. data/lib/rubocop/cop/layout/else_alignment.rb +1 -0
  54. data/lib/rubocop/cop/layout/empty_line_after_multiline_condition.rb +14 -5
  55. data/lib/rubocop/cop/layout/empty_lines.rb +5 -2
  56. data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +1 -1
  57. data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -0
  58. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +1 -1
  59. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +23 -1
  60. data/lib/rubocop/cop/layout/end_alignment.rb +16 -10
  61. data/lib/rubocop/cop/layout/extra_spacing.rb +4 -0
  62. data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -0
  63. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +17 -4
  64. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +5 -3
  65. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +6 -0
  66. data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +4 -0
  67. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +11 -0
  68. data/lib/rubocop/cop/layout/hash_alignment.rb +15 -10
  69. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -0
  70. data/lib/rubocop/cop/layout/heredoc_indentation.rb +15 -0
  71. data/lib/rubocop/cop/layout/indentation_style.rb +4 -1
  72. data/lib/rubocop/cop/layout/indentation_width.rb +4 -4
  73. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +8 -1
  74. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +25 -9
  75. data/lib/rubocop/cop/layout/line_length.rb +71 -19
  76. data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +12 -0
  77. data/lib/rubocop/cop/layout/multiline_block_layout.rb +8 -1
  78. data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +7 -0
  79. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +6 -0
  80. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +14 -0
  81. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +4 -0
  82. data/lib/rubocop/cop/layout/redundant_line_break.rb +22 -1
  83. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +15 -2
  84. data/lib/rubocop/cop/layout/single_line_block_chain.rb +10 -2
  85. data/lib/rubocop/cop/layout/space_after_not.rb +5 -0
  86. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +10 -4
  87. data/lib/rubocop/cop/layout/space_around_keyword.rb +10 -0
  88. data/lib/rubocop/cop/layout/space_around_operators.rb +5 -1
  89. data/lib/rubocop/cop/layout/space_before_block_braces.rb +4 -1
  90. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +15 -2
  91. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +31 -8
  92. data/lib/rubocop/cop/lint/ambiguous_operator.rb +1 -1
  93. data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +2 -1
  94. data/lib/rubocop/cop/lint/argument_mismatch.rb +14 -4
  95. data/lib/rubocop/cop/lint/assignment_in_condition.rb +2 -0
  96. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +88 -14
  97. data/lib/rubocop/cop/lint/duplicate_methods.rb +1 -1
  98. data/lib/rubocop/cop/lint/empty_block.rb +1 -1
  99. data/lib/rubocop/cop/lint/empty_conditional_body.rb +3 -1
  100. data/lib/rubocop/cop/lint/literal_as_condition.rb +23 -2
  101. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +63 -19
  102. data/lib/rubocop/cop/lint/loop.rb +24 -2
  103. data/lib/rubocop/cop/lint/misplaced_magic_comment.rb +245 -0
  104. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +19 -4
  105. data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
  106. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +1 -1
  107. data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
  108. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +17 -1
  109. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +42 -17
  110. data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +13 -2
  111. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +18 -1
  112. data/lib/rubocop/cop/lint/useless_assignment.rb +14 -7
  113. data/lib/rubocop/cop/lint/void.rb +8 -1
  114. data/lib/rubocop/cop/lint.rb +1 -0
  115. data/lib/rubocop/cop/metrics/class_length.rb +4 -2
  116. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +0 -4
  117. data/lib/rubocop/cop/metrics/module_length.rb +4 -2
  118. data/lib/rubocop/cop/migration/department_name.rb +1 -1
  119. data/lib/rubocop/cop/mixin/alignment.rb +5 -1
  120. data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -1
  121. data/lib/rubocop/cop/mixin/check_line_breakable.rb +17 -14
  122. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +5 -1
  123. data/lib/rubocop/cop/mixin/code_length.rb +10 -2
  124. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +12 -1
  125. data/lib/rubocop/cop/mixin/endless_method_body_help.rb +69 -0
  126. data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +2 -2
  127. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +26 -2
  128. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +31 -3
  129. data/lib/rubocop/cop/mixin/hash_transform_method.rb +1 -1
  130. data/lib/rubocop/cop/mixin/min_branches_count.rb +3 -1
  131. data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +11 -1
  132. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +9 -0
  133. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
  134. data/lib/rubocop/cop/mixin/pattern_matching_help.rb +35 -0
  135. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +29 -3
  136. data/lib/rubocop/cop/mixin/project_index_help.rb +15 -0
  137. data/lib/rubocop/cop/mixin/reparsed_equivalence.rb +13 -3
  138. data/lib/rubocop/cop/mixin/statement_modifier.rb +22 -2
  139. data/lib/rubocop/cop/mixin.rb +4 -2
  140. data/lib/rubocop/cop/naming/accessor_method_name.rb +0 -16
  141. data/lib/rubocop/cop/naming/block_forwarding.rb +4 -1
  142. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  143. data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +9 -2
  144. data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +5 -3
  145. data/lib/rubocop/cop/naming/predicate_prefix.rb +7 -22
  146. data/lib/rubocop/cop/offense.rb +59 -3
  147. data/lib/rubocop/cop/registry.rb +10 -2
  148. data/lib/rubocop/cop/security/json_load.rb +16 -4
  149. data/lib/rubocop/cop/severity.rb +12 -0
  150. data/lib/rubocop/cop/style/access_modifier_declarations.rb +10 -2
  151. data/lib/rubocop/cop/style/alias.rb +18 -5
  152. data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +4 -3
  153. data/lib/rubocop/cop/style/and_or.rb +4 -0
  154. data/lib/rubocop/cop/style/arguments_forwarding.rb +6 -3
  155. data/lib/rubocop/cop/style/attr.rb +3 -4
  156. data/lib/rubocop/cop/style/bitwise_predicate.rb +6 -4
  157. data/lib/rubocop/cop/style/block_delimiters.rb +29 -3
  158. data/lib/rubocop/cop/style/case_like_if.rb +9 -6
  159. data/lib/rubocop/cop/style/class_and_module_children.rb +54 -16
  160. data/lib/rubocop/cop/style/class_methods_definitions.rb +8 -0
  161. data/lib/rubocop/cop/style/combinable_loops.rb +85 -11
  162. data/lib/rubocop/cop/style/concat_array_literals.rb +46 -7
  163. data/lib/rubocop/cop/style/conditional_assignment.rb +4 -0
  164. data/lib/rubocop/cop/style/constant_visibility.rb +6 -2
  165. data/lib/rubocop/cop/style/data_inheritance.rb +14 -0
  166. data/lib/rubocop/cop/style/directive_scope.rb +154 -21
  167. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +118 -18
  168. data/lib/rubocop/cop/style/documentation_method.rb +1 -9
  169. data/lib/rubocop/cop/style/double_negation.rb +11 -0
  170. data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
  171. data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
  172. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
  173. data/lib/rubocop/cop/style/empty_literal.rb +1 -1
  174. data/lib/rubocop/cop/style/empty_method.rb +15 -3
  175. data/lib/rubocop/cop/style/endless_method.rb +91 -11
  176. data/lib/rubocop/cop/style/exact_regexp_match.rb +45 -8
  177. data/lib/rubocop/cop/style/explicit_block_argument.rb +50 -10
  178. data/lib/rubocop/cop/style/file_null.rb +2 -2
  179. data/lib/rubocop/cop/style/float_division.rb +28 -14
  180. data/lib/rubocop/cop/style/for.rb +44 -1
  181. data/lib/rubocop/cop/style/format_string.rb +28 -6
  182. data/lib/rubocop/cop/style/format_string_token.rb +1 -1
  183. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +2 -1
  184. data/lib/rubocop/cop/style/guard_clause.rb +13 -1
  185. data/lib/rubocop/cop/style/hash_conversion.rb +28 -8
  186. data/lib/rubocop/cop/style/hash_lookup_method.rb +35 -9
  187. data/lib/rubocop/cop/style/hash_syntax.rb +16 -3
  188. data/lib/rubocop/cop/style/identical_conditional_branches.rb +22 -3
  189. data/lib/rubocop/cop/style/if_inside_else.rb +21 -1
  190. data/lib/rubocop/cop/style/if_unless_modifier.rb +19 -20
  191. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +4 -0
  192. data/lib/rubocop/cop/style/if_with_semicolon.rb +47 -4
  193. data/lib/rubocop/cop/style/inverse_methods.rb +24 -2
  194. data/lib/rubocop/cop/style/it_block_parameter.rb +32 -3
  195. data/lib/rubocop/cop/style/keyword_parameters_order.rb +3 -1
  196. data/lib/rubocop/cop/style/lambda.rb +18 -0
  197. data/lib/rubocop/cop/style/lambda_call.rb +7 -2
  198. data/lib/rubocop/cop/style/magic_comment_format.rb +1 -1
  199. data/lib/rubocop/cop/style/map_into_array.rb +1 -2
  200. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +45 -10
  201. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +25 -2
  202. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +26 -3
  203. data/lib/rubocop/cop/style/method_def_parentheses.rb +29 -3
  204. data/lib/rubocop/cop/style/missing_else.rb +7 -1
  205. data/lib/rubocop/cop/style/multiline_if_modifier.rb +45 -5
  206. data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +7 -0
  207. data/lib/rubocop/cop/style/multiline_method_signature.rb +2 -5
  208. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +7 -3
  209. data/lib/rubocop/cop/style/multiline_when_then.rb +7 -0
  210. data/lib/rubocop/cop/style/mutable_constant.rb +28 -1
  211. data/lib/rubocop/cop/style/negated_if_else_condition.rb +2 -1
  212. data/lib/rubocop/cop/style/negative_array_index.rb +9 -1
  213. data/lib/rubocop/cop/style/nested_modifier.rb +36 -12
  214. data/lib/rubocop/cop/style/nested_ternary_operator.rb +26 -8
  215. data/lib/rubocop/cop/style/next.rb +24 -10
  216. data/lib/rubocop/cop/style/nil_comparison.rb +48 -8
  217. data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
  218. data/lib/rubocop/cop/style/non_nil_check.rb +18 -2
  219. data/lib/rubocop/cop/style/not.rb +10 -3
  220. data/lib/rubocop/cop/style/numeric_literal_prefix.rb +11 -1
  221. data/lib/rubocop/cop/style/numeric_predicate.rb +21 -5
  222. data/lib/rubocop/cop/style/one_line_conditional.rb +14 -3
  223. data/lib/rubocop/cop/style/parallel_assignment.rb +1 -1
  224. data/lib/rubocop/cop/style/parentheses_around_condition.rb +6 -1
  225. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +14 -3
  226. data/lib/rubocop/cop/style/reduce_to_hash.rb +17 -1
  227. data/lib/rubocop/cop/style/redundant_begin.rb +20 -3
  228. data/lib/rubocop/cop/style/redundant_condition.rb +34 -17
  229. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +16 -1
  230. data/lib/rubocop/cop/style/redundant_exception.rb +15 -3
  231. data/lib/rubocop/cop/style/redundant_fetch_block.rb +10 -2
  232. data/lib/rubocop/cop/style/redundant_freeze.rb +10 -1
  233. data/lib/rubocop/cop/style/redundant_parentheses.rb +23 -2
  234. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +7 -0
  235. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +6 -5
  236. data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +25 -5
  237. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +4 -0
  238. data/lib/rubocop/cop/style/regexp_literal.rb +75 -26
  239. data/lib/rubocop/cop/style/require_order.rb +9 -0
  240. data/lib/rubocop/cop/style/rescue_modifier.rb +5 -9
  241. data/lib/rubocop/cop/style/return_nil.rb +17 -2
  242. data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +11 -1
  243. data/lib/rubocop/cop/style/sample.rb +9 -8
  244. data/lib/rubocop/cop/style/self_assignment.rb +12 -15
  245. data/lib/rubocop/cop/style/semicolon.rb +16 -5
  246. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  247. data/lib/rubocop/cop/style/single_line_methods.rb +16 -4
  248. data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
  249. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +29 -5
  250. data/lib/rubocop/cop/style/string_concatenation.rb +9 -3
  251. data/lib/rubocop/cop/style/struct_inheritance.rb +14 -0
  252. data/lib/rubocop/cop/style/super_arguments.rb +3 -0
  253. data/lib/rubocop/cop/style/symbol_proc.rb +23 -5
  254. data/lib/rubocop/cop/style/ternary_parentheses.rb +23 -1
  255. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
  256. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +23 -19
  257. data/lib/rubocop/cop/style/while_until_modifier.rb +1 -1
  258. data/lib/rubocop/cop/style/yoda_condition.rb +24 -9
  259. data/lib/rubocop/cop/style/yoda_expression.rb +10 -1
  260. data/lib/rubocop/cop/style.rb +0 -1
  261. data/lib/rubocop/cop/team.rb +10 -5
  262. data/lib/rubocop/cop/util.rb +1 -1
  263. data/lib/rubocop/cop/variable_force/assignment.rb +1 -1
  264. data/lib/rubocop/cop/variable_force/variable.rb +14 -1
  265. data/lib/rubocop/cops_documentation_generator.rb +23 -2
  266. data/lib/rubocop/directive_comment.rb +37 -8
  267. data/lib/rubocop/formatter/base_formatter.rb +22 -0
  268. data/lib/rubocop/formatter/disabled_config_formatter.rb +19 -1
  269. data/lib/rubocop/formatter/formatter_set.rb +6 -1
  270. data/lib/rubocop/formatter/github_actions_formatter.rb +6 -5
  271. data/lib/rubocop/formatter/html_formatter.rb +2 -2
  272. data/lib/rubocop/formatter/json_formatter.rb +71 -1
  273. data/lib/rubocop/formatter/junit_formatter.rb +1 -1
  274. data/lib/rubocop/formatter/offense_count_formatter.rb +3 -1
  275. data/lib/rubocop/formatter/pacman_formatter.rb +3 -1
  276. data/lib/rubocop/formatter/sarif_formatter.rb +186 -0
  277. data/lib/rubocop/formatter/worst_offenders_formatter.rb +3 -1
  278. data/lib/rubocop/formatter.rb +1 -0
  279. data/lib/rubocop/lsp/runtime.rb +47 -11
  280. data/lib/rubocop/lsp/stdin_runner.rb +11 -5
  281. data/lib/rubocop/lsp.rb +5 -2
  282. data/lib/rubocop/magic_comment.rb +27 -0
  283. data/lib/rubocop/mcp/autocorrection_request.rb +52 -0
  284. data/lib/rubocop/mcp/explain_tool.rb +68 -0
  285. data/lib/rubocop/mcp/scope.rb +65 -0
  286. data/lib/rubocop/mcp/server.rb +184 -76
  287. data/lib/rubocop/mcp/source_files.rb +35 -0
  288. data/lib/rubocop/offense_limit.rb +30 -0
  289. data/lib/rubocop/options.rb +97 -4
  290. data/lib/rubocop/path_util.rb +1 -1
  291. data/lib/rubocop/plugin/configuration_integrator.rb +12 -5
  292. data/lib/rubocop/plugin/loader.rb +1 -1
  293. data/lib/rubocop/rake_task.rb +1 -1
  294. data/lib/rubocop/remote_config.rb +8 -5
  295. data/lib/rubocop/result_cache.rb +36 -18
  296. data/lib/rubocop/runner.rb +160 -49
  297. data/lib/rubocop/server/cache.rb +2 -2
  298. data/lib/rubocop/unified_diff.rb +257 -0
  299. data/lib/rubocop/util.rb +69 -0
  300. data/lib/rubocop/version.rb +1 -1
  301. data/lib/rubocop.rb +9 -1
  302. metadata +21 -6
  303. data/lib/rubocop/cop/style/double_cop_disable_directive.rb +0 -46
@@ -59,15 +59,22 @@ module RuboCop
59
59
 
60
60
  plugin_config.make_excludes_absolute
61
61
 
62
- # `unset_nil: false` keeps `AllCops` keys declared with a nil value by a plugin
63
- # (e.g. `TargetRailsVersion: ~` of rubocop-rails); `merge_all_cop_settings` above
64
- # carries such keys into each subsequent plugin's config, where `unset_nil: true`
65
- # would delete them from the combined configuration.
66
- ConfigLoader.merge_with_default(plugin_config, plugin_config_path, unset_nil: false)
62
+ merge_plugin_config_with_default(plugin_config, plugin_config_path)
67
63
  end
68
64
  end
69
65
  end
70
66
 
67
+ # `unset_nil: false` keeps `AllCops` keys declared with a nil value by a plugin
68
+ # (e.g. `TargetRailsVersion: ~` of rubocop-rails); `merge_all_cop_settings` carries
69
+ # such keys into each subsequent plugin's config, where `unset_nil: true` would
70
+ # delete them from the combined configuration. Preview is left to be applied when
71
+ # a project configuration is resolved against the defaults.
72
+ def merge_plugin_config_with_default(plugin_config, plugin_config_path)
73
+ ConfigLoader.merge_with_default(
74
+ plugin_config, plugin_config_path, unset_nil: false, resolve_preview: false
75
+ )
76
+ end
77
+
71
78
  def merge_plugin_config_into_all_cops!(rubocop_config, plugin_config)
72
79
  rubocop_config['AllCops'].merge!(plugin_config['AllCops'])
73
80
  end
@@ -8,7 +8,7 @@ module RuboCop
8
8
  # A class for loading and resolving plugins.
9
9
  # @api private
10
10
  class Loader
11
- # rubocop:disable Layout/LineLength
11
+ # rubocop:disable Layout/LineLength -- the comment on each key does not wrap
12
12
  DEFAULT_PLUGIN_CONFIG = {
13
13
  'enabled' => true,
14
14
  'require_path' => nil, # If not set, will be set to the plugin name
@@ -74,7 +74,7 @@ module RuboCop
74
74
 
75
75
  def setup_subtasks(name, *args, &task_block) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
76
76
  namespace(name) do
77
- # rubocop:todo-next Naming/InclusiveLanguage
77
+ # rubocop:todo-next Naming/InclusiveLanguage -- the deprecated flag spelling is the subject here
78
78
  task(:auto_correct, *args) do |_, task_args|
79
79
  require 'rainbow'
80
80
  warn Rainbow(
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'net/http'
4
3
  require 'time'
4
+ require 'uri'
5
5
 
6
6
  module RuboCop
7
7
  # Common methods and behaviors for dealing with remote config files.
@@ -45,13 +45,16 @@ module RuboCop
45
45
  def request(uri = @uri, limit = 10, &block)
46
46
  raise ArgumentError, 'HTTP redirect too deep' if limit.zero?
47
47
 
48
+ # Loaded here rather than at the top, since most runs never fetch a remote config.
49
+ require 'net/http'
50
+
48
51
  http = Net::HTTP.new(uri.hostname, uri.port)
49
52
  http.use_ssl = uri.instance_of?(URI::HTTPS)
50
53
 
51
54
  generate_request(uri) do |request|
52
- handle_response(http.request(request), limit, &block)
55
+ handle_response(http.request(request), uri, limit, &block)
53
56
  rescue SocketError => e
54
- handle_response(e, limit, &block)
57
+ handle_response(e, uri, limit, &block)
55
58
  end
56
59
  end
57
60
 
@@ -64,12 +67,12 @@ module RuboCop
64
67
  yield request
65
68
  end
66
69
 
67
- def handle_response(response, limit, &block)
70
+ def handle_response(response, uri, limit, &block)
68
71
  case response
69
72
  when Net::HTTPSuccess, Net::HTTPNotModified, SocketError
70
73
  yield response
71
74
  when Net::HTTPRedirection
72
- request(URI.parse(response['location']), limit - 1, &block)
75
+ request(URI.join(uri, response['location']), limit - 1, &block)
73
76
  else
74
77
  begin
75
78
  response.error!
@@ -59,9 +59,9 @@ module RuboCop
59
59
  puts "Removing the #{remove_count} oldest files from #{rubocop_cache_dir}" if verbose
60
60
  sorted = files.sort_by { |path| File.mtime(path) }
61
61
  remove_files(sorted, remove_count)
62
- rescue Errno::ENOENT
62
+ rescue Errno::ENOENT, Errno::EACCES, Errno::EPERM, Errno::EROFS
63
63
  # This can happen if parallel RuboCop invocations try to remove the
64
- # same files. No problem.
64
+ # same files, or if the cache can't be written to. No problem.
65
65
  puts $ERROR_INFO if verbose
66
66
  end
67
67
 
@@ -123,7 +123,7 @@ module RuboCop
123
123
  end
124
124
 
125
125
  def valid?
126
- File.exist?(@path)
126
+ !@checksum_unavailable && File.exist?(@path)
127
127
  end
128
128
 
129
129
  def load
@@ -132,30 +132,23 @@ module RuboCop
132
132
  end
133
133
 
134
134
  def save(offenses)
135
+ return if @checksum_unavailable
136
+
135
137
  dir = File.dirname(@path)
136
138
 
137
139
  begin
138
140
  FileUtils.mkdir_p(dir)
139
- rescue Errno::EACCES, Errno::EROFS => e
141
+ rescue Errno::EACCES, Errno::EPERM, Errno::EROFS => e
140
142
  warn "Couldn't create cache directory. Continuing without cache.\n #{e.message}"
141
143
  return
142
144
  end
143
145
 
144
- preliminary_path = "#{@path}_#{rand(1_000_000_000)}"
145
146
  # RuboCop must be in control of where its cached data is stored. A
146
147
  # symbolic link anywhere in the cache directory tree can be an
147
148
  # indication that a symlink attack is being waged.
148
149
  return if symlink_protection_triggered?(dir)
149
150
 
150
- File.open(preliminary_path, 'w', encoding: Encoding::UTF_8) do |f|
151
- f.write(@cached_data.to_json(offenses))
152
- end
153
- # The preliminary path is used so that if there are multiple RuboCop
154
- # processes trying to save data for the same inspected file
155
- # simultaneously, the only problem we run in to is a competition who gets
156
- # to write to the final file. The contents are the same, so no corruption
157
- # of data should occur.
158
- FileUtils.mv(preliminary_path, @path)
151
+ write_cache_file(offenses)
159
152
  end
160
153
 
161
154
  private
@@ -175,15 +168,40 @@ module RuboCop
175
168
  false
176
169
  end
177
170
 
171
+ def write_cache_file(offenses)
172
+ preliminary_path = "#{@path}_#{rand(1_000_000_000)}"
173
+ File.open(preliminary_path, 'w', encoding: Encoding::UTF_8) do |f|
174
+ f.write(@cached_data.to_json(offenses))
175
+ end
176
+ # The preliminary path is used so that if there are multiple RuboCop
177
+ # processes trying to save data for the same inspected file
178
+ # simultaneously, the only problem we run in to is a competition who gets
179
+ # to write to the final file. The contents are the same, so no corruption
180
+ # of data should occur.
181
+ FileUtils.mv(preliminary_path, @path)
182
+ rescue Errno::EACCES, Errno::EPERM, Errno::EROFS => e
183
+ FileUtils.rm_f(preliminary_path)
184
+ warn "Couldn't write cache file. Continuing without cache.\n #{e.message}"
185
+ end
186
+
178
187
  def file_checksum(file, config_store)
188
+ stat = File.stat(file)
189
+ return unavailable_checksum unless stat.file?
190
+
179
191
  digester = Digest::SHA1.new
180
- mode = File.stat(file).mode
181
- digester.update("#{file}#{mode}#{config_store.for_file(file).signature}")
192
+ digester.update("#{file}#{stat.mode}#{config_store.for_file(file).signature}")
182
193
  digester.file(file)
183
194
  digester.hexdigest
184
195
  rescue Errno::ENOENT
185
- # Spurious files that come and go should not cause a crash, at least not
186
- # here.
196
+ # Spurious files that come and go should not cause a crash, at least not here.
197
+ unavailable_checksum
198
+ end
199
+
200
+ # Every file that fails to checksum shares this sentinel value, so the cache entry
201
+ # must be neither saved nor considered valid, or one file's cached results could be
202
+ # served as another's.
203
+ def unavailable_checksum
204
+ @checksum_unavailable = true
187
205
  '_'
188
206
  end
189
207
 
@@ -63,9 +63,20 @@ module RuboCop
63
63
  @warnings = []
64
64
  @aborting = false
65
65
  @inspected_files = []
66
+ @diff_sources = {}
66
67
  @report_queue = {}
67
68
  end
68
69
 
70
+ # The `--diff` patches, one per file, from the source on disk (or stdin) to
71
+ # the source once every correction, redundant directive removal included,
72
+ # has been applied.
73
+ def diffs
74
+ @diffs ||= @diff_sources.filter_map do |file, (original_source, corrected_source)|
75
+ diff = UnifiedDiff.new(PathUtil.smart_path(file), original_source, corrected_source).to_s
76
+ diff unless diff.empty?
77
+ end
78
+ end
79
+
69
80
  def run(paths)
70
81
  @inspection_team_by_config = {}.compare_by_identity
71
82
 
@@ -73,7 +84,7 @@ module RuboCop
73
84
  # inconsistencies between workers.
74
85
  ResultCache.source_checksum
75
86
 
76
- target_files = find_target_files(paths)
87
+ target_files = only_changed(find_target_files(paths))
77
88
  build_project_index(target_files)
78
89
 
79
90
  if @options[:list_target_files]
@@ -95,6 +106,14 @@ module RuboCop
95
106
 
96
107
  private
97
108
 
109
+ # The project index is deliberately built from the unfiltered file list:
110
+ # cross-file offenses must not depend on which files happen to have changed.
111
+ def only_changed(target_files)
112
+ return target_files unless @options[:changed]
113
+
114
+ ChangedFiles.new(@options[:changed]).filter(target_files).freeze
115
+ end
116
+
98
117
  def find_target_files(paths)
99
118
  target_finder = TargetFinder.new(@config_store, @options)
100
119
  mode = if @options[:only_recognized_file_types]
@@ -147,11 +166,12 @@ module RuboCop
147
166
 
148
167
  def inspect_files(files) # rubocop:disable Metrics/AbcSize
149
168
  formatter_set.started(files)
169
+ formatters_started = true
150
170
  file_iterator(files) do |file|
151
- offenses = process_file(file)
171
+ offenses, problems = collect_problems { process_file(file) }
152
172
  succeeded = offenses.none? { |o| considered_failure?(o) && offense_displayed?(o) }
153
173
 
154
- [offenses, succeeded]
174
+ [offenses, succeeded, problems]
155
175
  end
156
176
  ensure
157
177
  # OPTIMIZE: Calling `ResultCache.cleanup` takes time. This optimization
@@ -160,17 +180,18 @@ module RuboCop
160
180
  if files.size > 1 && cached_run?
161
181
  ResultCache.cleanup(@config_store, @options[:debug], @options[:cache_root])
162
182
  end
163
- formatter_set.finished(@inspected_files.freeze)
183
+ formatter_set.finished(@inspected_files.freeze) if formatters_started
164
184
  formatter_set.close_output_files
185
+ warn_about_elided_offenses
165
186
  end
166
187
 
167
188
  def file_iterator(files, &block)
168
189
  all_passed = true
169
190
 
170
191
  on_start = ->(file, _index) { file_started(file) }
171
- on_finish = lambda do |file, index, (offenses, passed)|
192
+ on_finish = lambda do |file, index, (offenses, passed, problems)|
172
193
  all_passed &&= passed
173
- finished_report(file, index, offenses)
194
+ finished_report(file, index, offenses, problems)
174
195
  end
175
196
 
176
197
  if run_in_parallel?(files)
@@ -184,8 +205,8 @@ module RuboCop
184
205
  all_passed
185
206
  end
186
207
 
187
- def finished_report(file, index, offenses)
188
- @report_queue[index] = [file, offenses]
208
+ def finished_report(file, index, offenses, problems)
209
+ @report_queue[index] = [file, offenses, problems]
189
210
  @next_index_to_report ||= 0
190
211
  while @report_queue.key?(@next_index_to_report)
191
212
  process_report_queue_entry(@next_index_to_report)
@@ -194,7 +215,10 @@ module RuboCop
194
215
  end
195
216
 
196
217
  def process_report_queue_entry(index)
197
- file, offenses = @report_queue.delete(index)
218
+ file, offenses, (errors, warnings) = @report_queue.delete(index)
219
+ @errors.concat(errors)
220
+ @warnings.concat(warnings)
221
+ file_problems(file, errors, warnings) unless errors.empty? && warnings.empty?
198
222
  file_finished(file, offenses)
199
223
  end
200
224
 
@@ -205,8 +229,7 @@ module RuboCop
205
229
  end
206
230
 
207
231
  def run_in_parallel?(files)
208
- return false if @options[:auto_gen_config]
209
- return false unless @options[:parallel]
232
+ return false unless parallel_supported_by_options?
210
233
 
211
234
  if files.size <= 1
212
235
  puts 'Skipping parallel inspection: only a single file needs inspection' if @options[:debug]
@@ -220,6 +243,13 @@ module RuboCop
220
243
  true
221
244
  end
222
245
 
246
+ # `--auto-gen-config` needs the offenses of every file in one place, and
247
+ # `--diff` collects the diffs in this process, where a worker's copy of
248
+ # them would be lost.
249
+ def parallel_supported_by_options?
250
+ @options[:parallel] && !@options[:auto_gen_config] && !@options[:diff]
251
+ end
252
+
223
253
  def project_index_disables_parallel?
224
254
  return false if @project_index.nil? || !Gem.win_platform?
225
255
 
@@ -252,6 +282,21 @@ module RuboCop
252
282
  paths.each { |path| puts PathUtil.relative_path(path) }
253
283
  end
254
284
 
285
+ # Keeps the errors and warnings a file causes apart from the rest of the
286
+ # run's. A parallel worker inspects files in a copy of the runner that is
287
+ # thrown away, so they have to travel back with the file's offenses.
288
+ def collect_problems
289
+ errors = @errors
290
+ warnings = @warnings
291
+ @errors = []
292
+ @warnings = []
293
+
294
+ [yield, [@errors, @warnings]]
295
+ ensure
296
+ @errors = errors
297
+ @warnings = warnings
298
+ end
299
+
255
300
  def process_file(file)
256
301
  file_offenses(file)
257
302
  rescue InfiniteCorrectionLoop => e
@@ -304,9 +349,11 @@ module RuboCop
304
349
  if redundant_updated
305
350
  # Do one extra inspection loop if any redundant disables were
306
351
  # removed. This is done in order to find rubocop:enable directives that
307
- # have now become useless.
308
- _source, new_offenses = do_inspection_loop(file)
309
- offenses |= new_offenses
352
+ # have now become useless. It finds the offenses that are left again,
353
+ # located in the corrected source, so only the corrected ones are kept
354
+ # from before, as `inspect_and_correct` does.
355
+ _source, new_offenses = do_inspection_loop(file, team.updated_source)
356
+ offenses = offenses.select(&:corrected?) | new_offenses
310
357
  end
311
358
  end
312
359
  offenses
@@ -319,6 +366,8 @@ module RuboCop
319
366
  team = Cop::Team.mobilize([Cop::Lint::RedundantCopDisableDirective], config, @options)
320
367
  return if team.cops.empty?
321
368
 
369
+ team.defer_corrections = @options[:diff]
370
+
322
371
  team.cops.first.offenses_to_check = offenses
323
372
  yield team
324
373
  end
@@ -352,6 +401,15 @@ module RuboCop
352
401
  formatter_set.file_started(file, cli_options: @options, config_store: @config_store)
353
402
  end
354
403
 
404
+ # Formatters get the messages without the colors added for the terminal.
405
+ def file_problems(file, errors, warnings)
406
+ formatter_set.file_problems(file, plain_messages(errors), plain_messages(warnings))
407
+ end
408
+
409
+ def plain_messages(problems)
410
+ problems.map { |problem| Rainbow::StringUtils.uncolor(problem.to_s) }
411
+ end
412
+
355
413
  def file_finished(file, offenses)
356
414
  @inspected_files << file
357
415
  offenses = offenses_to_report(offenses)
@@ -370,15 +428,16 @@ module RuboCop
370
428
  return unless cache
371
429
  # Caching results when a cop has crashed would prevent the crash in the
372
430
  # next run, since the cop would not be called then. We want crashes to
373
- # show up the same in each run.
431
+ # show up the same in each run. Only this file's errors and warnings are
432
+ # visible here, see `collect_problems`.
374
433
  return if errors.any? || warnings.any?
375
434
 
376
435
  cache.save(offenses)
377
436
  end
378
437
 
379
- def do_inspection_loop(file)
380
- # We can reuse the prism result since the source did not change yet.
381
- processed_source = get_processed_source(file, @prism_result)
438
+ def do_inspection_loop(file, source = nil)
439
+ processed_source = initial_processed_source(file, source)
440
+ original_source = processed_source.raw_source
382
441
  # This variable is 2d array used to track corrected offenses after each
383
442
  # inspection iteration. This is used to output meaningful infinite loop
384
443
  # error message.
@@ -391,11 +450,7 @@ module RuboCop
391
450
  # once. The corrections are kept in memory while iterating and written
392
451
  # back to the file when the loop is done.
393
452
  iterate_until_no_changes(processed_source, offenses_by_iteration) do
394
- # The offenses that couldn't be corrected will be found again so we
395
- # only keep the corrected ones in order to avoid duplicate reporting.
396
- !offenses_by_iteration.empty? && offenses_by_iteration.last.select!(&:corrected?)
397
- team, new_offenses, updated_source_file = inspect_iteration(processed_source)
398
- offenses_by_iteration.push(new_offenses)
453
+ team, updated_source_file = inspect_and_correct(processed_source, offenses_by_iteration)
399
454
 
400
455
  # We have to reprocess the source to pickup the changes. Since the
401
456
  # change could (theoretically) introduce parsing errors, we break the
@@ -411,30 +466,64 @@ module RuboCop
411
466
  # Return summary of corrected offenses after all iterations
412
467
  [processed_source, offenses_by_iteration.flatten.uniq]
413
468
  ensure
414
- # Write the file once, even when the loop was left through an exception
415
- # (e.g. an infinite correction loop), like the per-iteration writes
416
- # used to be.
417
- File.write(file, corrected_source) if corrected_source
469
+ finalize_corrections(file, original_source, corrected_source)
470
+ end
471
+
472
+ # `source` is the corrected source to continue from when the corrections
473
+ # are kept in memory rather than written to the file (`--diff`).
474
+ def initial_processed_source(file, source)
475
+ return get_processed_source(file, nil, source: source) if source
476
+
477
+ # We can reuse the prism result since the source did not change yet.
478
+ get_processed_source(file, @prism_result)
479
+ end
480
+
481
+ def inspect_and_correct(processed_source, offenses_by_iteration)
482
+ # The offenses that couldn't be corrected will be found again so we
483
+ # only keep the corrected ones in order to avoid duplicate reporting.
484
+ !offenses_by_iteration.empty? && offenses_by_iteration.last.select!(&:corrected?)
485
+ team, new_offenses, updated_source_file = inspect_iteration(processed_source)
486
+ offenses_by_iteration.push(new_offenses)
487
+
488
+ [team, updated_source_file]
489
+ end
490
+
491
+ # Write the file once, even when the loop was left through an exception
492
+ # (e.g. an infinite correction loop), like the per-iteration writes used
493
+ # to be. Under `--diff` nothing is written at all.
494
+ def finalize_corrections(file, original_source, corrected_source)
495
+ if @options[:diff]
496
+ record_diff(file, original_source, corrected_source)
497
+ elsif corrected_source
498
+ Util.replace_file_contents(file, corrected_source)
499
+ end
500
+ end
501
+
502
+ # `--diff` reports what autocorrection would do instead of doing it. With
503
+ # `--stdin` the corrected source is handed back through the options rather
504
+ # than deferred, so that is where the new source comes from. A file can go
505
+ # through more than one inspection loop, so the diff runs from the source
506
+ # the first loop started with to the one the last loop ended with.
507
+ def record_diff(file, original_source, corrected_source)
508
+ return unless original_source
509
+
510
+ new_source = @options[:stdin] || corrected_source
511
+ # The original source is the file as it is on disk, so the corrected one
512
+ # has to go through the same line ending conversion `File.write` would
513
+ # apply, or on Windows every single line reads as changed.
514
+ new_source = new_source ? Util.emulate_write_read_cycle(new_source) : original_source
515
+
516
+ sources = (@diff_sources[file] ||= [original_source])
517
+ sources[1] = new_source
418
518
  end
419
519
 
420
520
  def inspect_iteration(processed_source)
421
521
  team = mobilize_team(processed_source)
422
- team.defer_corrections = in_memory_corrections_possible?
522
+ team.defer_corrections = @options[:diff] || in_memory_corrections_possible?
423
523
  offenses, updated_source_file = inspect_file(processed_source, team)
424
524
  [team, offenses, updated_source_file]
425
525
  end
426
526
 
427
- # When corrections were written to disk and read back between iterations,
428
- # the text-mode write converted LF to CRLF on Windows, and cops like
429
- # `Layout/EndOfLine` rely on seeing the source as it would be on disk.
430
- # Apply the same conversion to the in-memory source. The final `File.write`
431
- # still performs it for the file itself.
432
- def emulate_write_read_cycle(source)
433
- return source unless Platform.windows?
434
-
435
- source.encode(source.encoding, crlf_newline: true)
436
- end
437
-
438
527
  # Custom ruby extractors may derive their fragments from the file on
439
528
  # disk rather than from the passed processed source, so corrections can
440
529
  # only be kept in memory when the default extractor is used.
@@ -525,6 +614,12 @@ module RuboCop
525
614
  end
526
615
  end
527
616
 
617
+ # Lets a runner that is reused from run to run pick up a different `--only`
618
+ # or `--except`.
619
+ def forget_mobilized_cops
620
+ @mobilized_cop_classes = nil
621
+ end
622
+
528
623
  def mobilize_cop_badge?(badge, config)
529
624
  return false if badge.department == :Test
530
625
  return false if badge.match_name?(@options[:except])
@@ -541,7 +636,7 @@ module RuboCop
541
636
  %i[only except].each do |option|
542
637
  next unless @options[option]
543
638
 
544
- @options[option].map! do |cop_name|
639
+ @options[option] = @options[option].map do |cop_name|
545
640
  Cop::Registry.qualified_cop_name(cop_name, "--#{option} option")
546
641
  end
547
642
  end
@@ -582,7 +677,28 @@ module RuboCop
582
677
  end
583
678
 
584
679
  def offenses_to_report(offenses)
585
- offenses.select { |o| offense_displayed?(o) }
680
+ offenses = offenses.select { |o| offense_displayed?(o) }
681
+ offenses = offense_limit.filter(offenses) if offense_limit
682
+ offenses
683
+ end
684
+
685
+ # Files are reported in order, so which offenses survive the limit does not
686
+ # depend on how the run was parallelized.
687
+ def offense_limit
688
+ return @offense_limit if defined?(@offense_limit)
689
+
690
+ max = @options[:max_offenses_per_cop]
691
+ @offense_limit = (OffenseLimit.new(max.to_i) if max)
692
+ end
693
+
694
+ def warn_about_elided_offenses
695
+ elided = offense_limit&.elided_per_cop
696
+ return unless elided&.any?
697
+
698
+ warn Rainbow(
699
+ "#{elided.values.sum} more offenses were not reported because of " \
700
+ "--max-offenses-per-cop=#{offense_limit.max} (#{elided.keys.join(', ')})."
701
+ ).yellow
586
702
  end
587
703
 
588
704
  def supports_safe_autocorrect?(offense)
@@ -602,13 +718,8 @@ module RuboCop
602
718
  end
603
719
 
604
720
  def minimum_severity_to_fail
605
- @minimum_severity_to_fail ||= begin
606
- # Unless given explicitly as `fail_level`, `:info` severity offenses do not fail
607
- name = @options[:fail_level] || :refactor
608
-
609
- # autocorrect is a fake level - use the default
610
- RuboCop::Cop::Severity.new(name == :autocorrect ? :refactor : name)
611
- end
721
+ @minimum_severity_to_fail ||=
722
+ RuboCop::Cop::Severity.minimum_to_fail(@options, @config_store.for_pwd)
612
723
  end
613
724
 
614
725
  # rubocop:disable-next Metrics/MethodLength
@@ -619,7 +730,7 @@ module RuboCop
619
730
 
620
731
  processed_source = if source
621
732
  ProcessedSource.new(
622
- emulate_write_read_cycle(source),
733
+ Util.emulate_write_read_cycle(source),
623
734
  ruby_version,
624
735
  file,
625
736
  parser_engine: parser_engine
@@ -112,8 +112,8 @@ module RuboCop
112
112
 
113
113
  def pid_running?
114
114
  Process.kill(0, pid_path(create_dir: false).read.to_i) == 1
115
- rescue Errno::ESRCH, Errno::ENOENT, Errno::EACCES, Errno::EROFS, Errno::ENAMETOOLONG,
116
- Errno::ENOTDIR
115
+ rescue Errno::ESRCH, Errno::ENOENT, Errno::EACCES, Errno::EPERM, Errno::EROFS,
116
+ Errno::ENAMETOOLONG, Errno::ENOTDIR
117
117
  false
118
118
  end
119
119