rubocop 1.67.0 → 1.75.7

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 (476) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +4 -4
  4. data/config/default.yml +266 -47
  5. data/config/internal_affairs.yml +20 -0
  6. data/config/obsoletion.yml +3 -1
  7. data/lib/rubocop/cached_data.rb +12 -4
  8. data/lib/rubocop/cli/command/execute_runner.rb +4 -4
  9. data/lib/rubocop/cli/command/show_cops.rb +24 -2
  10. data/lib/rubocop/cli/command/suggest_extensions.rb +7 -1
  11. data/lib/rubocop/cli/command/version.rb +2 -2
  12. data/lib/rubocop/cli.rb +1 -1
  13. data/lib/rubocop/comment_config.rb +2 -2
  14. data/lib/rubocop/config.rb +52 -10
  15. data/lib/rubocop/config_loader.rb +52 -9
  16. data/lib/rubocop/config_loader_resolver.rb +36 -10
  17. data/lib/rubocop/config_obsoletion/extracted_cop.rb +4 -3
  18. data/lib/rubocop/config_obsoletion/renamed_cop.rb +18 -3
  19. data/lib/rubocop/config_obsoletion.rb +46 -2
  20. data/lib/rubocop/config_validator.rb +25 -14
  21. data/lib/rubocop/cop/autocorrect_logic.rb +36 -19
  22. data/lib/rubocop/cop/base.rb +7 -1
  23. data/lib/rubocop/cop/bundler/duplicated_gem.rb +2 -2
  24. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
  25. data/lib/rubocop/cop/bundler/gem_filename.rb +0 -1
  26. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +0 -1
  27. data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -12
  28. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +1 -1
  29. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +10 -0
  30. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +1 -2
  31. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +49 -5
  32. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +0 -2
  33. data/lib/rubocop/cop/generator.rb +6 -0
  34. data/lib/rubocop/cop/internal_affairs/cop_enabled.rb +85 -0
  35. data/lib/rubocop/cop/internal_affairs/example_description.rb +8 -4
  36. data/lib/rubocop/cop/internal_affairs/location_exists.rb +116 -0
  37. data/lib/rubocop/cop/internal_affairs/location_expression.rb +2 -1
  38. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +3 -4
  39. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +3 -2
  40. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
  41. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +63 -0
  42. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +131 -0
  43. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +230 -0
  44. data/lib/rubocop/cop/internal_affairs/node_type_group.rb +91 -0
  45. data/lib/rubocop/cop/internal_affairs/node_type_multiple_predicates.rb +126 -0
  46. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +4 -3
  47. data/lib/rubocop/cop/internal_affairs/numblock_handler.rb +1 -1
  48. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +90 -0
  49. data/lib/rubocop/cop/internal_affairs/operator_keyword.rb +48 -0
  50. data/lib/rubocop/cop/internal_affairs/plugin.rb +33 -0
  51. data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +6 -5
  52. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +3 -1
  53. data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +5 -4
  54. data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +0 -2
  55. data/lib/rubocop/cop/internal_affairs/undefined_config.rb +13 -2
  56. data/lib/rubocop/cop/internal_affairs.rb +7 -16
  57. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +1 -1
  58. data/lib/rubocop/cop/layout/argument_alignment.rb +2 -9
  59. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  60. data/lib/rubocop/cop/layout/begin_end_alignment.rb +0 -1
  61. data/lib/rubocop/cop/layout/block_alignment.rb +3 -2
  62. data/lib/rubocop/cop/layout/block_end_newline.rb +1 -0
  63. data/lib/rubocop/cop/layout/class_structure.rb +9 -9
  64. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +4 -4
  65. data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
  66. data/lib/rubocop/cop/layout/dot_position.rb +1 -1
  67. data/lib/rubocop/cop/layout/else_alignment.rb +2 -2
  68. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +3 -3
  69. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +7 -11
  70. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +30 -4
  71. data/lib/rubocop/cop/layout/empty_lines_around_begin_body.rb +5 -6
  72. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +1 -0
  73. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +4 -5
  74. data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +23 -1
  75. data/lib/rubocop/cop/layout/end_alignment.rb +1 -1
  76. data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
  77. data/lib/rubocop/cop/layout/first_argument_indentation.rb +3 -8
  78. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -7
  79. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -7
  80. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +1 -1
  81. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +2 -2
  82. data/lib/rubocop/cop/layout/hash_alignment.rb +8 -6
  83. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -1
  84. data/lib/rubocop/cop/layout/indentation_width.rb +8 -7
  85. data/lib/rubocop/cop/layout/leading_comment_space.rb +57 -2
  86. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +11 -2
  87. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +7 -1
  88. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -2
  89. data/lib/rubocop/cop/layout/line_length.rb +123 -4
  90. data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -0
  91. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +1 -1
  92. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +25 -0
  93. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +2 -1
  94. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +4 -4
  95. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +1 -1
  96. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +1 -0
  97. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +3 -4
  98. data/lib/rubocop/cop/layout/parameter_alignment.rb +3 -4
  99. data/lib/rubocop/cop/layout/redundant_line_break.rb +19 -46
  100. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +6 -7
  101. data/lib/rubocop/cop/layout/single_line_block_chain.rb +1 -1
  102. data/lib/rubocop/cop/layout/space_after_colon.rb +2 -2
  103. data/lib/rubocop/cop/layout/space_after_comma.rb +1 -1
  104. data/lib/rubocop/cop/layout/space_after_method_name.rb +1 -1
  105. data/lib/rubocop/cop/layout/space_after_semicolon.rb +11 -1
  106. data/lib/rubocop/cop/layout/space_around_keyword.rb +2 -1
  107. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
  108. data/lib/rubocop/cop/layout/space_around_operators.rb +23 -21
  109. data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -0
  110. data/lib/rubocop/cop/layout/space_before_brackets.rb +8 -34
  111. data/lib/rubocop/cop/layout/space_before_comma.rb +1 -1
  112. data/lib/rubocop/cop/layout/space_before_semicolon.rb +1 -1
  113. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +11 -1
  114. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +5 -0
  115. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +7 -0
  116. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +0 -1
  117. data/lib/rubocop/cop/layout/trailing_whitespace.rb +5 -3
  118. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  119. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +118 -0
  120. data/lib/rubocop/cop/lint/assignment_in_condition.rb +1 -3
  121. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +10 -12
  122. data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -1
  123. data/lib/rubocop/cop/lint/circular_argument_reference.rb +4 -1
  124. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +3 -3
  125. data/lib/rubocop/cop/lint/constant_reassignment.rb +148 -0
  126. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +84 -0
  127. data/lib/rubocop/cop/lint/debugger.rb +3 -3
  128. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
  129. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +3 -2
  130. data/lib/rubocop/cop/lint/duplicate_branch.rb +39 -4
  131. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +1 -1
  132. data/lib/rubocop/cop/lint/duplicate_methods.rb +86 -19
  133. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
  134. data/lib/rubocop/cop/lint/duplicate_set_element.rb +20 -7
  135. data/lib/rubocop/cop/lint/empty_conditional_body.rb +14 -64
  136. data/lib/rubocop/cop/lint/empty_ensure.rb +1 -1
  137. data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
  138. data/lib/rubocop/cop/lint/empty_file.rb +0 -2
  139. data/lib/rubocop/cop/lint/ensure_return.rb +1 -1
  140. data/lib/rubocop/cop/lint/erb_new_arguments.rb +0 -6
  141. data/lib/rubocop/cop/lint/float_comparison.rb +20 -14
  142. data/lib/rubocop/cop/lint/float_out_of_range.rb +2 -4
  143. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +2 -2
  144. data/lib/rubocop/cop/lint/hash_new_with_keyword_arguments_as_default.rb +55 -0
  145. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
  146. data/lib/rubocop/cop/lint/interpolation_check.rb +9 -0
  147. data/lib/rubocop/cop/lint/it_without_arguments_in_block.rb +3 -0
  148. data/lib/rubocop/cop/lint/literal_as_condition.rb +118 -9
  149. data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +1 -1
  150. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +24 -6
  151. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +1 -1
  152. data/lib/rubocop/cop/lint/missing_super.rb +2 -2
  153. data/lib/rubocop/cop/lint/mixed_case_range.rb +5 -8
  154. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
  155. data/lib/rubocop/cop/lint/nested_method_definition.rb +10 -6
  156. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  157. data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +2 -2
  158. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +12 -3
  159. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +3 -3
  160. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +3 -3
  161. data/lib/rubocop/cop/lint/number_conversion.rb +0 -1
  162. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -2
  163. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +93 -0
  164. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +2 -3
  165. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +3 -2
  166. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -5
  167. data/lib/rubocop/cop/lint/raise_exception.rb +29 -10
  168. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
  169. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
  170. data/lib/rubocop/cop/lint/redundant_require_statement.rb +0 -21
  171. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +12 -7
  172. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +8 -7
  173. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +2 -2
  174. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +261 -0
  175. data/lib/rubocop/cop/lint/redundant_with_index.rb +3 -0
  176. data/lib/rubocop/cop/lint/redundant_with_object.rb +3 -0
  177. data/lib/rubocop/cop/lint/refinement_import_methods.rb +1 -1
  178. data/lib/rubocop/cop/lint/regexp_as_condition.rb +0 -1
  179. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
  180. data/lib/rubocop/cop/lint/rescue_type.rb +3 -7
  181. data/lib/rubocop/cop/lint/return_in_void_context.rb +9 -11
  182. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +17 -1
  183. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +5 -1
  184. data/lib/rubocop/cop/lint/self_assignment.rb +8 -10
  185. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
  186. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +8 -1
  187. data/lib/rubocop/cop/lint/shared_mutable_default.rb +76 -0
  188. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  189. data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +111 -0
  190. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  191. data/lib/rubocop/cop/lint/syntax.rb +4 -1
  192. data/lib/rubocop/cop/lint/to_enum_arguments.rb +1 -1
  193. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
  194. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +88 -0
  195. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +3 -1
  196. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -1
  197. data/lib/rubocop/cop/lint/unreachable_code.rb +52 -2
  198. data/lib/rubocop/cop/lint/unreachable_loop.rb +6 -6
  199. data/lib/rubocop/cop/lint/unused_method_argument.rb +18 -2
  200. data/lib/rubocop/cop/lint/useless_access_modifier.rb +5 -4
  201. data/lib/rubocop/cop/lint/useless_assignment.rb +3 -1
  202. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +71 -0
  203. data/lib/rubocop/cop/lint/useless_defined.rb +55 -0
  204. data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +4 -0
  205. data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
  206. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +2 -1
  207. data/lib/rubocop/cop/lint/useless_rescue.rb +2 -2
  208. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +2 -2
  209. data/lib/rubocop/cop/lint/useless_setter_call.rb +14 -25
  210. data/lib/rubocop/cop/lint/void.rb +16 -12
  211. data/lib/rubocop/cop/message_annotator.rb +7 -3
  212. data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
  213. data/lib/rubocop/cop/metrics/block_length.rb +1 -0
  214. data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
  215. data/lib/rubocop/cop/metrics/class_length.rb +9 -9
  216. data/lib/rubocop/cop/metrics/collection_literal_length.rb +7 -0
  217. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +5 -2
  218. data/lib/rubocop/cop/metrics/method_length.rb +9 -1
  219. data/lib/rubocop/cop/metrics/module_length.rb +1 -1
  220. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  221. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -1
  222. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +3 -4
  223. data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +7 -7
  224. data/lib/rubocop/cop/mixin/alignment.rb +2 -2
  225. data/lib/rubocop/cop/mixin/allowed_pattern.rb +4 -4
  226. data/lib/rubocop/cop/mixin/check_assignment.rb +4 -12
  227. data/lib/rubocop/cop/mixin/check_line_breakable.rb +22 -12
  228. data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +49 -0
  229. data/lib/rubocop/cop/mixin/comments_help.rb +8 -3
  230. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  231. data/lib/rubocop/cop/mixin/dig_help.rb +27 -0
  232. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +1 -1
  233. data/lib/rubocop/cop/mixin/endless_method_rewriter.rb +24 -0
  234. data/lib/rubocop/cop/mixin/forbidden_identifiers.rb +20 -0
  235. data/lib/rubocop/cop/mixin/forbidden_pattern.rb +16 -0
  236. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +3 -2
  237. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +15 -14
  238. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +22 -22
  239. data/lib/rubocop/cop/mixin/hash_subset.rb +203 -0
  240. data/lib/rubocop/cop/mixin/hash_transform_method.rb +74 -74
  241. data/lib/rubocop/cop/mixin/line_length_help.rb +5 -4
  242. data/lib/rubocop/cop/mixin/method_complexity.rb +2 -1
  243. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +7 -9
  244. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
  245. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +68 -30
  246. data/lib/rubocop/cop/mixin/range_help.rb +15 -4
  247. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  248. data/lib/rubocop/cop/mixin/statement_modifier.rb +8 -3
  249. data/lib/rubocop/cop/mixin/string_help.rb +2 -2
  250. data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
  251. data/lib/rubocop/cop/mixin/target_ruby_version.rb +17 -1
  252. data/lib/rubocop/cop/mixin/trailing_comma.rb +21 -5
  253. data/lib/rubocop/cop/naming/accessor_method_name.rb +6 -6
  254. data/lib/rubocop/cop/naming/block_forwarding.rb +20 -16
  255. data/lib/rubocop/cop/naming/constant_name.rb +6 -7
  256. data/lib/rubocop/cop/naming/file_name.rb +0 -2
  257. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +12 -13
  258. data/lib/rubocop/cop/naming/method_name.rb +64 -8
  259. data/lib/rubocop/cop/naming/predicate_name.rb +44 -0
  260. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +6 -14
  261. data/lib/rubocop/cop/naming/variable_name.rb +50 -6
  262. data/lib/rubocop/cop/naming/variable_number.rb +2 -3
  263. data/lib/rubocop/cop/offense.rb +2 -3
  264. data/lib/rubocop/cop/registry.rb +9 -6
  265. data/lib/rubocop/cop/security/compound_hash.rb +2 -0
  266. data/lib/rubocop/cop/security/yaml_load.rb +3 -2
  267. data/lib/rubocop/cop/style/access_modifier_declarations.rb +114 -34
  268. data/lib/rubocop/cop/style/accessor_grouping.rb +19 -5
  269. data/lib/rubocop/cop/style/ambiguous_endless_method_definition.rb +79 -0
  270. data/lib/rubocop/cop/style/and_or.rb +1 -1
  271. data/lib/rubocop/cop/style/arguments_forwarding.rb +47 -28
  272. data/lib/rubocop/cop/style/array_first_last.rb +18 -2
  273. data/lib/rubocop/cop/style/array_intersect.rb +42 -30
  274. data/lib/rubocop/cop/style/bitwise_predicate.rb +100 -0
  275. data/lib/rubocop/cop/style/block_delimiters.rb +43 -25
  276. data/lib/rubocop/cop/style/case_like_if.rb +8 -11
  277. data/lib/rubocop/cop/style/class_and_module_children.rb +52 -11
  278. data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -1
  279. data/lib/rubocop/cop/style/collection_methods.rb +2 -1
  280. data/lib/rubocop/cop/style/combinable_defined.rb +115 -0
  281. data/lib/rubocop/cop/style/combinable_loops.rb +3 -2
  282. data/lib/rubocop/cop/style/command_literal.rb +1 -1
  283. data/lib/rubocop/cop/style/commented_keyword.rb +20 -3
  284. data/lib/rubocop/cop/style/comparable_between.rb +78 -0
  285. data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
  286. data/lib/rubocop/cop/style/conditional_assignment.rb +39 -27
  287. data/lib/rubocop/cop/style/constant_visibility.rb +3 -12
  288. data/lib/rubocop/cop/style/data_inheritance.rb +7 -0
  289. data/lib/rubocop/cop/style/dig_chain.rb +89 -0
  290. data/lib/rubocop/cop/style/documentation.rb +1 -1
  291. data/lib/rubocop/cop/style/double_negation.rb +4 -4
  292. data/lib/rubocop/cop/style/each_for_simple_loop.rb +4 -7
  293. data/lib/rubocop/cop/style/each_with_object.rb +2 -3
  294. data/lib/rubocop/cop/style/empty_else.rb +4 -2
  295. data/lib/rubocop/cop/style/empty_literal.rb +5 -1
  296. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  297. data/lib/rubocop/cop/style/endless_method.rb +150 -18
  298. data/lib/rubocop/cop/style/eval_with_location.rb +4 -4
  299. data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -3
  300. data/lib/rubocop/cop/style/expand_path_arguments.rb +2 -7
  301. data/lib/rubocop/cop/style/explicit_block_argument.rb +16 -3
  302. data/lib/rubocop/cop/style/exponential_notation.rb +3 -3
  303. data/lib/rubocop/cop/style/fetch_env_var.rb +2 -1
  304. data/lib/rubocop/cop/style/file_null.rb +89 -0
  305. data/lib/rubocop/cop/style/file_touch.rb +75 -0
  306. data/lib/rubocop/cop/style/float_division.rb +8 -4
  307. data/lib/rubocop/cop/style/for.rb +1 -1
  308. data/lib/rubocop/cop/style/format_string_token.rb +38 -11
  309. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -2
  310. data/lib/rubocop/cop/style/global_std_stream.rb +3 -0
  311. data/lib/rubocop/cop/style/global_vars.rb +1 -3
  312. data/lib/rubocop/cop/style/guard_clause.rb +17 -3
  313. data/lib/rubocop/cop/style/hash_conversion.rb +1 -2
  314. data/lib/rubocop/cop/style/hash_each_methods.rb +6 -8
  315. data/lib/rubocop/cop/style/hash_except.rb +35 -147
  316. data/lib/rubocop/cop/style/hash_fetch_chain.rb +104 -0
  317. data/lib/rubocop/cop/style/hash_slice.rb +80 -0
  318. data/lib/rubocop/cop/style/hash_syntax.rb +9 -3
  319. data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
  320. data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
  321. data/lib/rubocop/cop/style/identical_conditional_branches.rb +25 -6
  322. data/lib/rubocop/cop/style/if_inside_else.rb +10 -14
  323. data/lib/rubocop/cop/style/if_unless_modifier.rb +25 -5
  324. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +4 -7
  325. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +3 -4
  326. data/lib/rubocop/cop/style/if_with_semicolon.rb +20 -9
  327. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  328. data/lib/rubocop/cop/style/inverse_methods.rb +15 -12
  329. data/lib/rubocop/cop/style/invertible_unless_condition.rb +2 -2
  330. data/lib/rubocop/cop/style/ip_addresses.rb +2 -2
  331. data/lib/rubocop/cop/style/it_assignment.rb +36 -0
  332. data/lib/rubocop/cop/style/it_block_parameter.rb +100 -0
  333. data/lib/rubocop/cop/style/keyword_arguments_merging.rb +67 -0
  334. data/lib/rubocop/cop/style/keyword_parameters_order.rb +14 -8
  335. data/lib/rubocop/cop/style/lambda.rb +1 -0
  336. data/lib/rubocop/cop/style/lambda_call.rb +10 -4
  337. data/lib/rubocop/cop/style/line_end_concatenation.rb +10 -4
  338. data/lib/rubocop/cop/style/map_into_array.rb +11 -3
  339. data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
  340. data/lib/rubocop/cop/style/map_to_set.rb +3 -2
  341. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +27 -17
  342. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -0
  343. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +8 -11
  344. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +3 -4
  345. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  346. data/lib/rubocop/cop/style/missing_else.rb +2 -0
  347. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +33 -3
  348. data/lib/rubocop/cop/style/multiline_block_chain.rb +3 -2
  349. data/lib/rubocop/cop/style/multiline_if_modifier.rb +2 -0
  350. data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
  351. data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -9
  352. data/lib/rubocop/cop/style/multiple_comparison.rb +52 -51
  353. data/lib/rubocop/cop/style/mutable_constant.rb +7 -8
  354. data/lib/rubocop/cop/style/negated_if_else_condition.rb +7 -5
  355. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
  356. data/lib/rubocop/cop/style/nested_ternary_operator.rb +5 -4
  357. data/lib/rubocop/cop/style/next.rb +44 -0
  358. data/lib/rubocop/cop/style/not.rb +1 -1
  359. data/lib/rubocop/cop/style/object_then.rb +15 -15
  360. data/lib/rubocop/cop/style/one_line_conditional.rb +25 -4
  361. data/lib/rubocop/cop/style/open_struct_use.rb +5 -5
  362. data/lib/rubocop/cop/style/operator_method_call.rb +5 -6
  363. data/lib/rubocop/cop/style/or_assignment.rb +3 -6
  364. data/lib/rubocop/cop/style/parallel_assignment.rb +9 -18
  365. data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
  366. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  367. data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
  368. data/lib/rubocop/cop/style/proc.rb +2 -2
  369. data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
  370. data/lib/rubocop/cop/style/raise_args.rb +15 -13
  371. data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
  372. data/lib/rubocop/cop/style/redundant_argument.rb +3 -1
  373. data/lib/rubocop/cop/style/redundant_assignment.rb +1 -1
  374. data/lib/rubocop/cop/style/redundant_begin.rb +2 -1
  375. data/lib/rubocop/cop/style/redundant_condition.rb +95 -23
  376. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +16 -5
  377. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -10
  378. data/lib/rubocop/cop/style/redundant_each.rb +1 -1
  379. data/lib/rubocop/cop/style/redundant_exception.rb +2 -2
  380. data/lib/rubocop/cop/style/redundant_format.rb +257 -0
  381. data/lib/rubocop/cop/style/redundant_freeze.rb +3 -3
  382. data/lib/rubocop/cop/style/redundant_initialize.rb +12 -3
  383. data/lib/rubocop/cop/style/redundant_line_continuation.rb +54 -18
  384. data/lib/rubocop/cop/style/redundant_parentheses.rb +56 -26
  385. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +4 -0
  386. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
  387. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
  388. data/lib/rubocop/cop/style/redundant_return.rb +2 -2
  389. data/lib/rubocop/cop/style/redundant_self.rb +9 -15
  390. data/lib/rubocop/cop/style/redundant_self_assignment.rb +20 -32
  391. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +4 -4
  392. data/lib/rubocop/cop/style/redundant_sort.rb +3 -3
  393. data/lib/rubocop/cop/style/redundant_sort_by.rb +17 -1
  394. data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -2
  395. data/lib/rubocop/cop/style/regexp_literal.rb +1 -1
  396. data/lib/rubocop/cop/style/rescue_modifier.rb +5 -3
  397. data/lib/rubocop/cop/style/return_nil.rb +2 -2
  398. data/lib/rubocop/cop/style/safe_navigation.rb +32 -5
  399. data/lib/rubocop/cop/style/safe_navigation_chain_length.rb +52 -0
  400. data/lib/rubocop/cop/style/select_by_regexp.rb +5 -2
  401. data/lib/rubocop/cop/style/self_assignment.rb +11 -17
  402. data/lib/rubocop/cop/style/semicolon.rb +1 -1
  403. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +2 -1
  404. data/lib/rubocop/cop/style/signal_exception.rb +2 -3
  405. data/lib/rubocop/cop/style/single_argument_dig.rb +9 -5
  406. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  407. data/lib/rubocop/cop/style/single_line_do_end_block.rb +15 -4
  408. data/lib/rubocop/cop/style/single_line_methods.rb +6 -7
  409. data/lib/rubocop/cop/style/slicing_with_range.rb +40 -11
  410. data/lib/rubocop/cop/style/sole_nested_conditional.rb +42 -106
  411. data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
  412. data/lib/rubocop/cop/style/string_concatenation.rb +15 -15
  413. data/lib/rubocop/cop/style/string_literals.rb +1 -1
  414. data/lib/rubocop/cop/style/string_methods.rb +1 -1
  415. data/lib/rubocop/cop/style/struct_inheritance.rb +8 -1
  416. data/lib/rubocop/cop/style/super_arguments.rb +66 -19
  417. data/lib/rubocop/cop/style/swap_values.rb +4 -15
  418. data/lib/rubocop/cop/style/symbol_proc.rb +2 -0
  419. data/lib/rubocop/cop/style/ternary_parentheses.rb +25 -4
  420. data/lib/rubocop/cop/style/top_level_method_definition.rb +2 -1
  421. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +11 -2
  422. data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +47 -6
  423. data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +48 -6
  424. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +4 -4
  425. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  426. data/lib/rubocop/cop/style/variable_interpolation.rb +1 -2
  427. data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
  428. data/lib/rubocop/cop/style/yoda_condition.rb +8 -4
  429. data/lib/rubocop/cop/style/yoda_expression.rb +2 -1
  430. data/lib/rubocop/cop/util.rb +12 -5
  431. data/lib/rubocop/cop/utils/format_string.rb +10 -5
  432. data/lib/rubocop/cop/variable_force/assignment.rb +24 -5
  433. data/lib/rubocop/cop/variable_force/branch.rb +1 -1
  434. data/lib/rubocop/cop/variable_force/scope.rb +1 -1
  435. data/lib/rubocop/cop/variable_force/variable.rb +14 -3
  436. data/lib/rubocop/cop/variable_force/variable_table.rb +5 -5
  437. data/lib/rubocop/cop/variable_force.rb +5 -11
  438. data/lib/rubocop/cops_documentation_generator.rb +50 -25
  439. data/lib/rubocop/directive_comment.rb +45 -11
  440. data/lib/rubocop/ext/regexp_node.rb +0 -1
  441. data/lib/rubocop/formatter/disabled_config_formatter.rb +3 -2
  442. data/lib/rubocop/formatter/formatter_set.rb +1 -1
  443. data/lib/rubocop/formatter/html_formatter.rb +1 -1
  444. data/lib/rubocop/formatter/pacman_formatter.rb +1 -1
  445. data/lib/rubocop/lsp/diagnostic.rb +189 -0
  446. data/lib/rubocop/lsp/logger.rb +2 -2
  447. data/lib/rubocop/lsp/routes.rb +7 -23
  448. data/lib/rubocop/lsp/runtime.rb +18 -50
  449. data/lib/rubocop/lsp/server.rb +0 -2
  450. data/lib/rubocop/lsp/stdin_runner.rb +85 -0
  451. data/lib/rubocop/magic_comment.rb +11 -3
  452. data/lib/rubocop/options.rb +28 -12
  453. data/lib/rubocop/path_util.rb +15 -8
  454. data/lib/rubocop/plugin/configuration_integrator.rb +143 -0
  455. data/lib/rubocop/plugin/load_error.rb +26 -0
  456. data/lib/rubocop/plugin/loader.rb +100 -0
  457. data/lib/rubocop/plugin/not_supported_error.rb +29 -0
  458. data/lib/rubocop/plugin.rb +46 -0
  459. data/lib/rubocop/rake_task.rb +4 -1
  460. data/lib/rubocop/result_cache.rb +13 -13
  461. data/lib/rubocop/rspec/cop_helper.rb +13 -1
  462. data/lib/rubocop/rspec/expect_offense.rb +6 -2
  463. data/lib/rubocop/rspec/shared_contexts.rb +38 -1
  464. data/lib/rubocop/rspec/support.rb +4 -2
  465. data/lib/rubocop/runner.rb +26 -15
  466. data/lib/rubocop/server/cache.rb +47 -11
  467. data/lib/rubocop/server/cli.rb +2 -2
  468. data/lib/rubocop/target_finder.rb +7 -2
  469. data/lib/rubocop/target_ruby.rb +17 -2
  470. data/lib/rubocop/version.rb +53 -12
  471. data/lib/rubocop.rb +32 -1
  472. data/lib/ruby_lsp/rubocop/addon.rb +75 -0
  473. data/lib/ruby_lsp/rubocop/runtime_adapter.rb +65 -0
  474. metadata +79 -20
  475. data/lib/rubocop/cop/utils/regexp_ranges.rb +0 -113
  476. data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
@@ -0,0 +1,189 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'severity'
4
+
5
+ #
6
+ # This code is based on https://github.com/standardrb/standard.
7
+ #
8
+ # Copyright (c) 2023 Test Double, Inc.
9
+ #
10
+ # The MIT License (MIT)
11
+ #
12
+ # https://github.com/standardrb/standard/blob/main/LICENSE.txt
13
+ #
14
+ module RuboCop
15
+ module LSP
16
+ # Diagnostic for Language Server Protocol of RuboCop.
17
+ # @api private
18
+ class Diagnostic
19
+ def initialize(document_encoding, offense, uri, cop_class)
20
+ @document_encoding = document_encoding
21
+ @offense = offense
22
+ @uri = uri
23
+ @cop_class = cop_class
24
+ end
25
+
26
+ def to_lsp_code_actions
27
+ code_actions = []
28
+
29
+ code_actions << autocorrect_action if correctable?
30
+ code_actions << disable_line_action
31
+
32
+ code_actions
33
+ end
34
+
35
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
36
+ def to_lsp_diagnostic(config)
37
+ highlighted = @offense.highlighted_area
38
+
39
+ LanguageServer::Protocol::Interface::Diagnostic.new(
40
+ message: message,
41
+ source: 'RuboCop',
42
+ code: @offense.cop_name,
43
+ code_description: code_description(config),
44
+ severity: severity,
45
+ range: LanguageServer::Protocol::Interface::Range.new(
46
+ start: LanguageServer::Protocol::Interface::Position.new(
47
+ line: @offense.line - 1,
48
+ character: highlighted.begin_pos
49
+ ),
50
+ end: LanguageServer::Protocol::Interface::Position.new(
51
+ line: @offense.line - 1,
52
+ character: highlighted.end_pos
53
+ )
54
+ ),
55
+ data: {
56
+ correctable: correctable?,
57
+ code_actions: to_lsp_code_actions
58
+ }
59
+ )
60
+ end
61
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
62
+
63
+ private
64
+
65
+ def message
66
+ message = @offense.message
67
+ message += "\n\nThis offense is not autocorrectable.\n" unless correctable?
68
+ message
69
+ end
70
+
71
+ def severity
72
+ Severity.find_by(@offense.severity.name)
73
+ end
74
+
75
+ def code_description(config)
76
+ return unless @cop_class
77
+ return unless (doc_url = @cop_class.documentation_url(config))
78
+
79
+ LanguageServer::Protocol::Interface::CodeDescription.new(href: doc_url)
80
+ end
81
+
82
+ # rubocop:disable Layout/LineLength, Metrics/MethodLength
83
+ def autocorrect_action
84
+ LanguageServer::Protocol::Interface::CodeAction.new(
85
+ title: "Autocorrect #{@offense.cop_name}",
86
+ kind: LanguageServer::Protocol::Constant::CodeActionKind::QUICK_FIX,
87
+ edit: LanguageServer::Protocol::Interface::WorkspaceEdit.new(
88
+ document_changes: [
89
+ LanguageServer::Protocol::Interface::TextDocumentEdit.new(
90
+ text_document: LanguageServer::Protocol::Interface::OptionalVersionedTextDocumentIdentifier.new(
91
+ uri: ensure_uri_scheme(@uri.to_s).to_s,
92
+ version: nil
93
+ ),
94
+ edits: correctable? ? offense_replacements : []
95
+ )
96
+ ]
97
+ ),
98
+ is_preferred: true
99
+ )
100
+ end
101
+ # rubocop:enable Layout/LineLength, Metrics/MethodLength
102
+
103
+ # rubocop:disable Metrics/MethodLength
104
+ def offense_replacements
105
+ @offense.corrector.as_replacements.map do |range, replacement|
106
+ LanguageServer::Protocol::Interface::TextEdit.new(
107
+ range: LanguageServer::Protocol::Interface::Range.new(
108
+ start: LanguageServer::Protocol::Interface::Position.new(
109
+ line: range.line - 1,
110
+ character: range.column
111
+ ),
112
+ end: LanguageServer::Protocol::Interface::Position.new(
113
+ line: range.last_line - 1,
114
+ character: range.last_column
115
+ )
116
+ ),
117
+ new_text: replacement
118
+ )
119
+ end
120
+ end
121
+ # rubocop:enable Metrics/MethodLength
122
+
123
+ # rubocop:disable Layout/LineLength, Metrics/MethodLength
124
+ def disable_line_action
125
+ LanguageServer::Protocol::Interface::CodeAction.new(
126
+ title: "Disable #{@offense.cop_name} for this line",
127
+ kind: LanguageServer::Protocol::Constant::CodeActionKind::QUICK_FIX,
128
+ edit: LanguageServer::Protocol::Interface::WorkspaceEdit.new(
129
+ document_changes: [
130
+ LanguageServer::Protocol::Interface::TextDocumentEdit.new(
131
+ text_document: LanguageServer::Protocol::Interface::OptionalVersionedTextDocumentIdentifier.new(
132
+ uri: ensure_uri_scheme(@uri.to_s).to_s,
133
+ version: nil
134
+ ),
135
+ edits: line_disable_comment
136
+ )
137
+ ]
138
+ )
139
+ )
140
+ end
141
+ # rubocop:enable Layout/LineLength, Metrics/MethodLength
142
+
143
+ def line_disable_comment
144
+ new_text = if @offense.source_line.include?(' # rubocop:disable ')
145
+ ",#{@offense.cop_name}"
146
+ else
147
+ " # rubocop:disable #{@offense.cop_name}"
148
+ end
149
+
150
+ eol = LanguageServer::Protocol::Interface::Position.new(
151
+ line: @offense.line - 1,
152
+ character: length_of_line(@offense.source_line)
153
+ )
154
+
155
+ # TODO: fails for multiline strings - may be preferable to use block
156
+ # comments to disable some offenses
157
+ inline_comment = LanguageServer::Protocol::Interface::TextEdit.new(
158
+ range: LanguageServer::Protocol::Interface::Range.new(start: eol, end: eol),
159
+ new_text: new_text
160
+ )
161
+
162
+ [inline_comment]
163
+ end
164
+
165
+ def length_of_line(line)
166
+ if @document_encoding == Encoding::UTF_16LE
167
+ line_length = 0
168
+ line.codepoints.each do |codepoint|
169
+ line_length += 1
170
+ line_length += 1 if codepoint > RubyLsp::Document::Scanner::SURROGATE_PAIR_START
171
+ end
172
+ line_length
173
+ else
174
+ line.length
175
+ end
176
+ end
177
+
178
+ def correctable?
179
+ !@offense.corrector.nil?
180
+ end
181
+
182
+ def ensure_uri_scheme(uri)
183
+ uri = URI.parse(uri)
184
+ uri.scheme = 'file' if uri.scheme.nil?
185
+ uri
186
+ end
187
+ end
188
+ end
189
+ end
@@ -14,8 +14,8 @@ module RuboCop
14
14
  # Log for Language Server Protocol of RuboCop.
15
15
  # @api private
16
16
  class Logger
17
- def self.log(message)
18
- warn("[server] #{message}")
17
+ def self.log(message, prefix: '[server]')
18
+ warn("#{prefix} #{message}")
19
19
  end
20
20
  end
21
21
  end
@@ -16,6 +16,11 @@ module RuboCop
16
16
  # Routes for Language Server Protocol of RuboCop.
17
17
  # @api private
18
18
  class Routes
19
+ CONFIGURATION_FILE_PATTERNS = [
20
+ RuboCop::ConfigFinder::DOTFILE,
21
+ RuboCop::CLI::Command::AutoGenerateConfig::AUTO_GENERATED_FILE
22
+ ].freeze
23
+
19
24
  def self.handle(name, &block)
20
25
  define_method(:"handle_#{name}", &block)
21
26
  end
@@ -96,7 +101,7 @@ module RuboCop
96
101
 
97
102
  handle 'workspace/didChangeWatchedFiles' do |request|
98
103
  changed = request[:params][:changes].any? do |change|
99
- change[:uri].end_with?(RuboCop::ConfigFinder::DOTFILE)
104
+ CONFIGURATION_FILE_PATTERNS.any? { |path| change[:uri].end_with?(path) }
100
105
  end
101
106
 
102
107
  if changed
@@ -204,14 +209,12 @@ module RuboCop
204
209
 
205
210
  def diagnostic(file_uri, text)
206
211
  @text_cache[file_uri] = text
207
- offenses = @server.offenses(remove_file_protocol_from(file_uri), text)
208
- diagnostics = offenses.map { |offense| to_diagnostic(offense) }
209
212
 
210
213
  {
211
214
  method: 'textDocument/publishDiagnostics',
212
215
  params: {
213
216
  uri: file_uri,
214
- diagnostics: diagnostics
217
+ diagnostics: @server.offenses(remove_file_protocol_from(file_uri), text)
215
218
  }
216
219
  }
217
220
  end
@@ -219,25 +222,6 @@ module RuboCop
219
222
  def remove_file_protocol_from(uri)
220
223
  uri.delete_prefix('file://')
221
224
  end
222
-
223
- def to_diagnostic(offense)
224
- code = offense[:cop_name]
225
- message = offense[:message]
226
- loc = offense[:location]
227
- rubocop_severity = offense[:severity]
228
- severity = Severity.find_by(rubocop_severity)
229
-
230
- {
231
- code: code, message: message, range: to_range(loc), severity: severity, source: 'rubocop'
232
- }
233
- end
234
-
235
- def to_range(location)
236
- {
237
- start: { character: location[:start_column] - 1, line: location[:start_line] - 1 },
238
- end: { character: location[:last_column], line: location[:last_line] - 1 }
239
- }
240
- end
241
225
  end
242
226
  end
243
227
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'stringio'
3
+ require_relative 'diagnostic'
4
+ require_relative 'stdin_runner'
4
5
 
5
6
  #
6
7
  # This code is based on https://github.com/standardrb/standard.
@@ -19,59 +20,40 @@ module RuboCop
19
20
  attr_writer :safe_autocorrect, :lint_mode, :layout_mode
20
21
 
21
22
  def initialize(config_store)
22
- @config_store = config_store
23
- @logged_paths = []
23
+ RuboCop::LSP.enable
24
+
25
+ @runner = RuboCop::Lsp::StdinRunner.new(config_store)
26
+ @cop_registry = RuboCop::Cop::Registry.global.to_h
27
+
24
28
  @safe_autocorrect = true
25
29
  @lint_mode = false
26
30
  @layout_mode = false
27
31
  end
28
32
 
29
- # This abuses the `--stdin` option of rubocop and reads the formatted text
30
- # from the `options[:stdin]` that rubocop mutates. This depends on
31
- # `parallel: false` as well as the fact that RuboCop doesn't otherwise dup
32
- # or reassign that options object. Risky business!
33
- #
34
- # Reassigning `options[:stdin]` is done here:
35
- # https://github.com/rubocop/rubocop/blob/v1.52.0/lib/rubocop/cop/team.rb#L131
36
- # Printing `options[:stdin]`
37
- # https://github.com/rubocop/rubocop/blob/v1.52.0/lib/rubocop/cli/command/execute_runner.rb#L95
38
- # Setting `parallel: true` would break this here:
39
- # https://github.com/rubocop/rubocop/blob/v1.52.0/lib/rubocop/runner.rb#L72
40
- def format(path, text, command:)
33
+ def format(path, text, command:, prism_result: nil)
41
34
  safe_autocorrect = if command
42
35
  command == 'rubocop.formatAutocorrects'
43
36
  else
44
37
  @safe_autocorrect
45
38
  end
46
39
 
47
- formatting_options = {
48
- stdin: text, force_exclusion: true, autocorrect: true, safe_autocorrect: safe_autocorrect
49
- }
40
+ formatting_options = { autocorrect: true, safe_autocorrect: safe_autocorrect }
50
41
  formatting_options[:only] = config_only_options if @lint_mode || @layout_mode
51
42
 
52
- redirect_stdout { run_rubocop(formatting_options, path) }
53
-
54
- formatting_options[:stdin]
43
+ @runner.run(path, text, formatting_options, prism_result: prism_result)
44
+ @runner.formatted_source
55
45
  end
56
46
 
57
- def offenses(path, text)
58
- diagnostic_options = {
59
- stdin: text, force_exclusion: true, formatters: ['json'], format: 'json'
60
- }
47
+ def offenses(path, text, document_encoding = nil, prism_result: nil)
48
+ diagnostic_options = {}
61
49
  diagnostic_options[:only] = config_only_options if @lint_mode || @layout_mode
62
50
 
63
- json = redirect_stdout { run_rubocop(diagnostic_options, path) }
64
- results = JSON.parse(json, symbolize_names: true)
65
-
66
- if results[:files].empty?
67
- unless @logged_paths.include?(path)
68
- Logger.log "Ignoring file, per configuration: #{path}"
69
- @logged_paths << path
70
- end
71
- return []
51
+ @runner.run(path, text, diagnostic_options, prism_result: prism_result)
52
+ @runner.offenses.map do |offense|
53
+ Diagnostic.new(
54
+ document_encoding, offense, path, @cop_registry[offense.cop_name]&.first
55
+ ).to_lsp_diagnostic(@runner.config_for_working_directory)
72
56
  end
73
-
74
- results.dig(:files, 0, :offenses)
75
57
  end
76
58
 
77
59
  private
@@ -82,20 +64,6 @@ module RuboCop
82
64
  only_options << 'Layout' if @layout_mode
83
65
  only_options
84
66
  end
85
-
86
- def redirect_stdout(&block)
87
- stdout = StringIO.new
88
-
89
- RuboCop::Server::Helper.redirect(stdout: stdout, &block)
90
-
91
- stdout.string
92
- end
93
-
94
- def run_rubocop(options, path)
95
- runner = RuboCop::Runner.new(options, @config_store)
96
-
97
- runner.run([path])
98
- end
99
67
  end
100
68
  end
101
69
  end
@@ -22,8 +22,6 @@ module RuboCop
22
22
  def initialize(config_store)
23
23
  $PROGRAM_NAME = "rubocop --lsp #{ConfigFinder.project_root}"
24
24
 
25
- RuboCop::LSP.enable
26
-
27
25
  @reader = LanguageServer::Protocol::Transport::Io::Reader.new($stdin)
28
26
  @writer = LanguageServer::Protocol::Transport::Io::Writer.new($stdout)
29
27
  @runtime = RuboCop::LSP::Runtime.new(config_store)
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # This code is based on https://github.com/standardrb/standard.
5
+ #
6
+ # Copyright (c) 2023 Test Double, Inc.
7
+ #
8
+ # The MIT License (MIT)
9
+ #
10
+ # https://github.com/standardrb/standard/blob/main/LICENSE.txt
11
+ #
12
+ module RuboCop
13
+ module Lsp
14
+ # Originally lifted from:
15
+ # https://github.com/Shopify/ruby-lsp/blob/8d4c17efce4e8ecc8e7c557ab2981db6b22c0b6d/lib/ruby_lsp/requests/support/rubocop_runner.rb#L20
16
+ # @api private
17
+ class StdinRunner < RuboCop::Runner
18
+ class ConfigurationError < StandardError; end
19
+
20
+ attr_reader :offenses, :config_for_working_directory
21
+
22
+ DEFAULT_RUBOCOP_OPTIONS = {
23
+ stderr: true,
24
+ force_exclusion: true,
25
+ formatters: ['RuboCop::Formatter::BaseFormatter'],
26
+ raise_cop_error: true,
27
+ todo_file: nil,
28
+ todo_ignore_files: []
29
+ }.freeze
30
+
31
+ def initialize(config_store)
32
+ @options = {}
33
+
34
+ @offenses = []
35
+ @warnings = []
36
+ @errors = []
37
+
38
+ @config_for_working_directory = config_store.for_pwd
39
+
40
+ super(@options, config_store)
41
+ end
42
+
43
+ # rubocop:disable Metrics/MethodLength
44
+ def run(path, contents, options, prism_result: nil)
45
+ @options = options.merge(DEFAULT_RUBOCOP_OPTIONS)
46
+ @options[:stdin] = contents
47
+
48
+ @prism_result = prism_result
49
+
50
+ @offenses = []
51
+ @warnings = []
52
+ @errors = []
53
+
54
+ super([path])
55
+
56
+ raise Interrupt if aborting?
57
+ rescue RuboCop::Runner::InfiniteCorrectionLoop => e
58
+ if defined?(::RubyLsp::Requests::Formatting::Error)
59
+ raise ::RubyLsp::Requests::Formatting::Error, e.message
60
+ end
61
+
62
+ raise e
63
+ rescue RuboCop::ValidationError => e
64
+ raise ConfigurationError, e.message
65
+ rescue StandardError => e
66
+ if defined?(::RubyLsp::Requests::Formatting::Error)
67
+ raise ::RubyLsp::Requests::Support::InternalRuboCopError, e
68
+ end
69
+
70
+ raise e
71
+ end
72
+ # rubocop:enable Metrics/MethodLength
73
+
74
+ def formatted_source
75
+ @options[:stdin]
76
+ end
77
+
78
+ private
79
+
80
+ def file_finished(_file, offenses)
81
+ @offenses = offenses
82
+ end
83
+ end
84
+ end
85
+ end
@@ -80,13 +80,13 @@ module RuboCop
80
80
 
81
81
  # Expose the `frozen_string_literal` value coerced to a boolean if possible.
82
82
  #
83
- # @return [Boolean] if value is `true` or `false`
83
+ # @return [Boolean] if value is `true` or `false` in any case
84
84
  # @return [nil] if frozen_string_literal comment isn't found
85
85
  # @return [String] if comment is found but isn't true or false
86
86
  def frozen_string_literal
87
87
  return unless (setting = extract_frozen_string_literal)
88
88
 
89
- case setting
89
+ case setting.downcase
90
90
  when 'true' then true
91
91
  when 'false' then false
92
92
  else
@@ -193,6 +193,10 @@ module RuboCop
193
193
  SEPARATOR = ';'
194
194
  OPERATOR = ':'
195
195
 
196
+ def new_frozen_string_literal(value)
197
+ "# -*- frozen_string_literal: #{value} -*-"
198
+ end
199
+
196
200
  private
197
201
 
198
202
  def extract_frozen_string_literal
@@ -275,6 +279,10 @@ module RuboCop
275
279
  end
276
280
  end
277
281
 
282
+ def new_frozen_string_literal(value)
283
+ "# frozen_string_literal: #{value}"
284
+ end
285
+
278
286
  private
279
287
 
280
288
  # Extract `frozen_string_literal`.
@@ -283,7 +291,7 @@ module RuboCop
283
291
  # is the only text in the comment.
284
292
  #
285
293
  # Case-insensitive and dashes/underscores are acceptable.
286
- # @see https://github.com/ruby/ruby/blob/78b95b4/parse.y#L7134-L7138
294
+ # @see https://github.com/ruby/ruby/blob/78b95b49f8/parse.y#L7134-L7138
287
295
  def extract_frozen_string_literal
288
296
  extract(/\A\s*#\s*#{KEYWORDS[:frozen_string_literal]}:\s*#{TOKEN}\s*\z/io)
289
297
  end
@@ -243,6 +243,7 @@ module RuboCop
243
243
  option(opts, '--init')
244
244
  option(opts, '-c', '--config FILE')
245
245
  option(opts, '-d', '--debug')
246
+ option(opts, '--plugin FILE') { |f| plugin_feature(f) }
246
247
  option(opts, '-r', '--require FILE') { |f| require_feature(f) }
247
248
  option(opts, '--[no-]color')
248
249
  option(opts, '-v', '--version')
@@ -299,11 +300,25 @@ module RuboCop
299
300
  long_opt[2..].sub('[no-]', '').sub(/ .*/, '').tr('-', '_').gsub(/[\[\]]/, '').to_sym
300
301
  end
301
302
 
302
- def require_feature(file)
303
- # If any features were added on the CLI from `--require`,
303
+ def plugin_feature(file)
304
+ # If any features were added on the CLI from `--plugin`,
304
305
  # add them to the config.
305
- ConfigLoader.add_loaded_features(file)
306
- require file
306
+ ConfigLoaderResolver.new.resolve_plugins(Config.new, file)
307
+ end
308
+
309
+ def require_feature(file)
310
+ if Plugin.plugin_capable?(file)
311
+ # NOTE: Compatibility for before plugins style.
312
+ warn Rainbow(<<~MESSAGE).yellow
313
+ #{file} gem supports plugin, use `--plugin` instead of `--require`.
314
+ MESSAGE
315
+ plugin_feature(file)
316
+ else
317
+ # If any features were added on the CLI from `--require`,
318
+ # add them to the config.
319
+ require file
320
+ ConfigLoader.add_loaded_features(file)
321
+ end
307
322
  end
308
323
  end
309
324
 
@@ -397,7 +412,7 @@ module RuboCop
397
412
  return if @options[:format] == 'junit'
398
413
 
399
414
  raise OptionArgumentError,
400
- format('--display-only-failed can only be used together with --format junit.')
415
+ '--display-only-failed can only be used together with --format junit.'
401
416
  end
402
417
 
403
418
  def validate_display_only_correctable_and_autocorrect
@@ -415,14 +430,13 @@ module RuboCop
415
430
  !@options.key?(:display_only_safe_correctable)
416
431
 
417
432
  raise OptionArgumentError,
418
- format('--display-only-failed cannot be used together with other display options.')
433
+ '--display-only-failed cannot be used together with other display options.'
419
434
  end
420
435
 
421
436
  def validate_lsp_and_editor_mode
422
437
  return if !@options.key?(:lsp) || !@options.key?(:editor_mode)
423
438
 
424
- raise OptionArgumentError,
425
- format('Do not specify `--editor-mode` as it is redundant in `--lsp`.')
439
+ raise OptionArgumentError, 'Do not specify `--editor-mode` as it is redundant in `--lsp`.'
426
440
  end
427
441
 
428
442
  def validate_autocorrect
@@ -436,7 +450,7 @@ module RuboCop
436
450
  return unless @options.key?(:disable_uncorrectable)
437
451
 
438
452
  raise OptionArgumentError,
439
- format('--disable-uncorrectable can only be used together with --autocorrect.')
453
+ '--disable-uncorrectable can only be used together with --autocorrect.'
440
454
  end
441
455
 
442
456
  def disable_parallel_when_invalid_option_combo
@@ -504,6 +518,7 @@ module RuboCop
504
518
  only_guide_cops: ['Run only cops for rules that link to a',
505
519
  'style guide.'],
506
520
  except: 'Exclude the given cop(s).',
521
+ plugin: 'Load a RuboCop plugin.',
507
522
  require: 'Require Ruby file.',
508
523
  config: 'Specify configuration file.',
509
524
  auto_gen_config: ['Generate a configuration file acting as a',
@@ -542,8 +557,8 @@ module RuboCop
542
557
  only_recognized_file_types: ['Inspect files given on the command line only if',
543
558
  'they are listed in `AllCops/Include` parameters',
544
559
  'of user configuration or default configuration.'],
545
- ignore_disable_comments: ['Run cops even when they are disabled locally',
546
- 'by a `rubocop:disable` directive.'],
560
+ ignore_disable_comments: ['Report offenses even if they have been manually disabled',
561
+ 'with a `rubocop:disable` or `rubocop:todo` directive.'],
547
562
  ignore_parent_exclusion: ['Prevent from inheriting `AllCops/Exclude` from',
548
563
  'parent folders.'],
549
564
  ignore_unrecognized_cops: ['Ignore unrecognized cops or departments in the config.'],
@@ -579,7 +594,8 @@ module RuboCop
579
594
  'when combined with --display-only-correctable.'],
580
595
  show_cops: ['Shows the given cops, or all cops by',
581
596
  'default, and their configurations for the',
582
- 'current directory.'],
597
+ 'current directory.',
598
+ 'You can use `*` as a wildcard.'],
583
599
  show_docs_url: ['Display url to documentation for the given',
584
600
  'cops, or base url by default.'],
585
601
  fail_fast: ['Inspect files in order of modification',
@@ -28,20 +28,27 @@ module RuboCop
28
28
  end
29
29
  end
30
30
 
31
+ def remote_file?(uri)
32
+ uri.start_with?('http://', 'https://')
33
+ end
34
+
31
35
  SMART_PATH_CACHE = {} # rubocop:disable Style/MutableConstant
32
36
  private_constant :SMART_PATH_CACHE
33
37
 
34
38
  def smart_path(path)
35
- SMART_PATH_CACHE[path] ||= begin
36
- # Ideally, we calculate this relative to the project root.
37
- base_dir = Dir.pwd
38
-
39
- if path.start_with? base_dir
40
- relative_path(path, base_dir)
39
+ SMART_PATH_CACHE[path] ||=
40
+ if path.is_a?(RemoteConfig)
41
+ path.uri.to_s
41
42
  else
42
- path
43
+ # Ideally, we calculate this relative to the project root.
44
+ base_dir = Dir.pwd
45
+
46
+ if path.start_with? base_dir
47
+ relative_path(path, base_dir)
48
+ else
49
+ path
50
+ end
43
51
  end
44
- end
45
52
  end
46
53
 
47
54
  # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity