rubocop 1.69.2 → 1.71.2

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 (253) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +2 -2
  4. data/config/default.yml +36 -2
  5. data/lib/rubocop/cli/command/execute_runner.rb +3 -3
  6. data/lib/rubocop/cli/command/show_cops.rb +24 -2
  7. data/lib/rubocop/comment_config.rb +1 -1
  8. data/lib/rubocop/config.rb +13 -4
  9. data/lib/rubocop/config_loader.rb +4 -0
  10. data/lib/rubocop/config_loader_resolver.rb +14 -3
  11. data/lib/rubocop/config_validator.rb +18 -8
  12. data/lib/rubocop/cop/autocorrect_logic.rb +1 -1
  13. data/lib/rubocop/cop/base.rb +6 -0
  14. data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
  15. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
  16. data/lib/rubocop/cop/internal_affairs/cop_enabled.rb +85 -0
  17. data/lib/rubocop/cop/internal_affairs/location_expression.rb +2 -1
  18. data/lib/rubocop/cop/internal_affairs/node_first_or_last_argument.rb +3 -2
  19. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
  20. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +63 -0
  21. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +131 -0
  22. data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +229 -0
  23. data/lib/rubocop/cop/internal_affairs/node_type_multiple_predicates.rb +126 -0
  24. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +4 -3
  25. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +90 -0
  26. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +3 -1
  27. data/lib/rubocop/cop/internal_affairs/single_line_comparison.rb +5 -4
  28. data/lib/rubocop/cop/internal_affairs.rb +4 -0
  29. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +1 -1
  30. data/lib/rubocop/cop/layout/argument_alignment.rb +2 -8
  31. data/lib/rubocop/cop/layout/block_alignment.rb +1 -1
  32. data/lib/rubocop/cop/layout/class_structure.rb +9 -9
  33. data/lib/rubocop/cop/layout/dot_position.rb +1 -1
  34. data/lib/rubocop/cop/layout/else_alignment.rb +1 -1
  35. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +7 -11
  36. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +1 -0
  37. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +1 -1
  38. data/lib/rubocop/cop/layout/end_alignment.rb +1 -1
  39. data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
  40. data/lib/rubocop/cop/layout/first_argument_indentation.rb +3 -8
  41. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -7
  42. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -7
  43. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +1 -1
  44. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +2 -2
  45. data/lib/rubocop/cop/layout/hash_alignment.rb +6 -4
  46. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -0
  47. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +7 -1
  48. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -2
  49. data/lib/rubocop/cop/layout/line_length.rb +1 -0
  50. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +1 -1
  51. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +25 -0
  52. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -0
  53. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +2 -2
  54. data/lib/rubocop/cop/layout/redundant_line_break.rb +7 -6
  55. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +1 -1
  56. data/lib/rubocop/cop/layout/single_line_block_chain.rb +1 -1
  57. data/lib/rubocop/cop/layout/space_after_colon.rb +2 -2
  58. data/lib/rubocop/cop/layout/space_after_comma.rb +1 -1
  59. data/lib/rubocop/cop/layout/space_after_method_name.rb +1 -1
  60. data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
  61. data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -0
  62. data/lib/rubocop/cop/layout/space_around_operators.rb +3 -3
  63. data/lib/rubocop/cop/layout/space_before_comma.rb +1 -1
  64. data/lib/rubocop/cop/layout/space_before_semicolon.rb +1 -1
  65. data/lib/rubocop/cop/layout/trailing_whitespace.rb +5 -3
  66. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  67. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +119 -0
  68. data/lib/rubocop/cop/lint/assignment_in_condition.rb +1 -3
  69. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +1 -1
  70. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +3 -3
  71. data/lib/rubocop/cop/lint/constant_reassignment.rb +148 -0
  72. data/lib/rubocop/cop/lint/debugger.rb +1 -1
  73. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +1 -1
  74. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
  75. data/lib/rubocop/cop/lint/duplicate_set_element.rb +20 -7
  76. data/lib/rubocop/cop/lint/empty_expression.rb +0 -2
  77. data/lib/rubocop/cop/lint/float_comparison.rb +5 -2
  78. data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
  79. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -1
  80. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
  81. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +24 -6
  82. data/lib/rubocop/cop/lint/missing_super.rb +2 -2
  83. data/lib/rubocop/cop/lint/mixed_case_range.rb +1 -1
  84. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
  85. data/lib/rubocop/cop/lint/nested_method_definition.rb +8 -4
  86. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  87. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +4 -3
  88. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +1 -1
  89. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +18 -31
  90. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -1
  91. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -5
  92. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
  93. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +2 -2
  94. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
  95. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +8 -1
  96. data/lib/rubocop/cop/lint/shared_mutable_default.rb +65 -0
  97. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  98. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  99. data/lib/rubocop/cop/lint/syntax.rb +4 -1
  100. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +1 -4
  101. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +1 -1
  102. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +1 -1
  103. data/lib/rubocop/cop/lint/unreachable_code.rb +1 -1
  104. data/lib/rubocop/cop/lint/unreachable_loop.rb +1 -1
  105. data/lib/rubocop/cop/lint/useless_access_modifier.rb +4 -4
  106. data/lib/rubocop/cop/lint/useless_assignment.rb +1 -1
  107. data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
  108. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +2 -1
  109. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +2 -2
  110. data/lib/rubocop/cop/lint/void.rb +5 -9
  111. data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
  112. data/lib/rubocop/cop/metrics/collection_literal_length.rb +7 -0
  113. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
  114. data/lib/rubocop/cop/metrics/method_length.rb +8 -1
  115. data/lib/rubocop/cop/metrics/module_length.rb +1 -1
  116. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  117. data/lib/rubocop/cop/mixin/check_line_breakable.rb +11 -11
  118. data/lib/rubocop/cop/mixin/comments_help.rb +3 -1
  119. data/lib/rubocop/cop/mixin/dig_help.rb +1 -1
  120. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -1
  121. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +4 -4
  122. data/lib/rubocop/cop/mixin/hash_subset.rb +188 -0
  123. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
  124. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +48 -24
  125. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  126. data/lib/rubocop/cop/mixin/statement_modifier.rb +8 -3
  127. data/lib/rubocop/cop/mixin/string_help.rb +1 -1
  128. data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
  129. data/lib/rubocop/cop/mixin/trailing_comma.rb +3 -3
  130. data/lib/rubocop/cop/naming/block_forwarding.rb +19 -15
  131. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +3 -3
  132. data/lib/rubocop/cop/security/compound_hash.rb +1 -0
  133. data/lib/rubocop/cop/style/access_modifier_declarations.rb +34 -5
  134. data/lib/rubocop/cop/style/and_or.rb +1 -1
  135. data/lib/rubocop/cop/style/arguments_forwarding.rb +39 -23
  136. data/lib/rubocop/cop/style/array_first_last.rb +18 -2
  137. data/lib/rubocop/cop/style/block_delimiters.rb +7 -20
  138. data/lib/rubocop/cop/style/class_and_module_children.rb +6 -3
  139. data/lib/rubocop/cop/style/collection_methods.rb +1 -1
  140. data/lib/rubocop/cop/style/combinable_defined.rb +1 -1
  141. data/lib/rubocop/cop/style/combinable_loops.rb +2 -2
  142. data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
  143. data/lib/rubocop/cop/style/conditional_assignment.rb +6 -4
  144. data/lib/rubocop/cop/style/documentation.rb +1 -1
  145. data/lib/rubocop/cop/style/double_negation.rb +3 -3
  146. data/lib/rubocop/cop/style/each_for_simple_loop.rb +4 -7
  147. data/lib/rubocop/cop/style/each_with_object.rb +2 -3
  148. data/lib/rubocop/cop/style/empty_else.rb +4 -2
  149. data/lib/rubocop/cop/style/empty_literal.rb +1 -1
  150. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  151. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  152. data/lib/rubocop/cop/style/exact_regexp_match.rb +3 -10
  153. data/lib/rubocop/cop/style/explicit_block_argument.rb +15 -2
  154. data/lib/rubocop/cop/style/exponential_notation.rb +1 -1
  155. data/lib/rubocop/cop/style/fetch_env_var.rb +1 -1
  156. data/lib/rubocop/cop/style/float_division.rb +8 -4
  157. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
  158. data/lib/rubocop/cop/style/hash_each_methods.rb +3 -6
  159. data/lib/rubocop/cop/style/hash_except.rb +24 -148
  160. data/lib/rubocop/cop/style/hash_slice.rb +80 -0
  161. data/lib/rubocop/cop/style/hash_syntax.rb +6 -3
  162. data/lib/rubocop/cop/style/identical_conditional_branches.rb +22 -3
  163. data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -3
  164. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +1 -1
  165. data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -2
  166. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  167. data/lib/rubocop/cop/style/inverse_methods.rb +6 -6
  168. data/lib/rubocop/cop/style/it_assignment.rb +36 -0
  169. data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -1
  170. data/lib/rubocop/cop/style/map_into_array.rb +1 -1
  171. data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
  172. data/lib/rubocop/cop/style/map_to_set.rb +3 -2
  173. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +19 -12
  174. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -0
  175. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -1
  176. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -4
  177. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  178. data/lib/rubocop/cop/style/missing_else.rb +2 -0
  179. data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
  180. data/lib/rubocop/cop/style/multiple_comparison.rb +26 -20
  181. data/lib/rubocop/cop/style/mutable_constant.rb +3 -3
  182. data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -1
  183. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
  184. data/lib/rubocop/cop/style/object_then.rb +13 -15
  185. data/lib/rubocop/cop/style/open_struct_use.rb +5 -5
  186. data/lib/rubocop/cop/style/parallel_assignment.rb +1 -5
  187. data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
  188. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  189. data/lib/rubocop/cop/style/proc.rb +1 -2
  190. data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
  191. data/lib/rubocop/cop/style/raise_args.rb +6 -4
  192. data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
  193. data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
  194. data/lib/rubocop/cop/style/redundant_condition.rb +2 -2
  195. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +2 -1
  196. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -10
  197. data/lib/rubocop/cop/style/redundant_each.rb +1 -1
  198. data/lib/rubocop/cop/style/redundant_exception.rb +2 -2
  199. data/lib/rubocop/cop/style/redundant_freeze.rb +2 -2
  200. data/lib/rubocop/cop/style/redundant_initialize.rb +12 -3
  201. data/lib/rubocop/cop/style/redundant_line_continuation.rb +34 -13
  202. data/lib/rubocop/cop/style/redundant_parentheses.rb +10 -10
  203. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +3 -0
  204. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
  205. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
  206. data/lib/rubocop/cop/style/redundant_self_assignment.rb +14 -28
  207. data/lib/rubocop/cop/style/redundant_sort.rb +2 -2
  208. data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -2
  209. data/lib/rubocop/cop/style/return_nil.rb +1 -1
  210. data/lib/rubocop/cop/style/safe_navigation.rb +2 -2
  211. data/lib/rubocop/cop/style/semicolon.rb +1 -1
  212. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +2 -1
  213. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  214. data/lib/rubocop/cop/style/single_line_do_end_block.rb +1 -2
  215. data/lib/rubocop/cop/style/single_line_methods.rb +3 -4
  216. data/lib/rubocop/cop/style/slicing_with_range.rb +40 -11
  217. data/lib/rubocop/cop/style/sole_nested_conditional.rb +2 -2
  218. data/lib/rubocop/cop/style/string_concatenation.rb +1 -1
  219. data/lib/rubocop/cop/style/string_literals.rb +1 -1
  220. data/lib/rubocop/cop/style/string_methods.rb +1 -1
  221. data/lib/rubocop/cop/style/super_arguments.rb +65 -17
  222. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
  223. data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -1
  224. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -1
  225. data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
  226. data/lib/rubocop/cop/style/yoda_condition.rb +8 -4
  227. data/lib/rubocop/cop/style/yoda_expression.rb +2 -1
  228. data/lib/rubocop/cop/util.rb +11 -4
  229. data/lib/rubocop/cop/variable_force/variable.rb +14 -2
  230. data/lib/rubocop/cop/variable_force/variable_table.rb +3 -3
  231. data/lib/rubocop/cops_documentation_generator.rb +13 -13
  232. data/lib/rubocop/directive_comment.rb +9 -8
  233. data/lib/rubocop/formatter/formatter_set.rb +1 -1
  234. data/lib/rubocop/lsp/diagnostic.rb +189 -0
  235. data/lib/rubocop/lsp/logger.rb +2 -2
  236. data/lib/rubocop/lsp/routes.rb +7 -23
  237. data/lib/rubocop/lsp/runtime.rb +15 -49
  238. data/lib/rubocop/lsp/stdin_runner.rb +83 -0
  239. data/lib/rubocop/options.rb +2 -1
  240. data/lib/rubocop/path_util.rb +11 -8
  241. data/lib/rubocop/result_cache.rb +13 -13
  242. data/lib/rubocop/rspec/expect_offense.rb +6 -2
  243. data/lib/rubocop/rspec/shared_contexts.rb +4 -1
  244. data/lib/rubocop/rspec/support.rb +1 -2
  245. data/lib/rubocop/runner.rb +5 -6
  246. data/lib/rubocop/target_finder.rb +1 -0
  247. data/lib/rubocop/target_ruby.rb +15 -0
  248. data/lib/rubocop/version.rb +1 -1
  249. data/lib/rubocop.rb +6 -0
  250. data/lib/ruby_lsp/rubocop/addon.rb +78 -0
  251. data/lib/ruby_lsp/rubocop/wraps_built_in_lsp_runtime.rb +50 -0
  252. metadata +23 -11
  253. data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
@@ -23,6 +23,10 @@ module RuboCop
23
23
  # `define_method`, therefore, `super` used within these blocks will be allowed.
24
24
  # This approach might result in false negatives, yet ensuring safe detection takes precedence.
25
25
  #
26
+ # NOTE: When forwarding the same arguments but replacing the block argument with a new inline
27
+ # block, it is not necessary to explicitly list the non-block arguments. As such, an offense
28
+ # will be registered in this case.
29
+ #
26
30
  # @example
27
31
  # # bad
28
32
  # def method(*args, **kwargs)
@@ -44,6 +48,16 @@ module RuboCop
44
48
  # super()
45
49
  # end
46
50
  #
51
+ # # bad - forwarding with overridden block
52
+ # def method(*args, **kwargs, &block)
53
+ # super(*args, **kwargs) { do_something }
54
+ # end
55
+ #
56
+ # # good - implicitly passing all non-block arguments
57
+ # def method(*args, **kwargs, &block)
58
+ # super { do_something }
59
+ # end
60
+ #
47
61
  # # good - assigning to the block variable before calling super
48
62
  # def method(&block)
49
63
  # # Assigning to the block variable would pass the old value to super,
@@ -58,46 +72,77 @@ module RuboCop
58
72
  ASSIGN_TYPES = %i[or_asgn lvasgn].freeze
59
73
 
60
74
  MSG = 'Call `super` without arguments and parentheses when the signature is identical.'
75
+ MSG_INLINE_BLOCK = 'Call `super` without arguments and parentheses when all positional ' \
76
+ 'and keyword arguments are forwarded.'
61
77
 
62
78
  def on_super(super_node)
63
- def_node = super_node.ancestors.find do |node|
79
+ return unless (def_node = find_def_node(super_node))
80
+
81
+ def_node_args = def_node.arguments.argument_list
82
+ super_args = preprocess_super_args(super_node.arguments)
83
+
84
+ return unless arguments_identical?(def_node, super_node, def_node_args, super_args)
85
+
86
+ # If the number of arguments to the def node and super node are different here,
87
+ # it's because the block argument is not forwarded.
88
+ message = def_node_args.size == super_args.size ? MSG : MSG_INLINE_BLOCK
89
+ add_offense(super_node, message: message) do |corrector|
90
+ corrector.replace(super_node, 'super')
91
+ end
92
+ end
93
+
94
+ private
95
+
96
+ def find_def_node(super_node)
97
+ super_node.ancestors.find do |node|
64
98
  # When defining dynamic methods, implicitly calling `super` is not possible.
65
99
  # Since there is a possibility of delegation to `define_method`,
66
100
  # `super` used within the block is always allowed.
67
- break if node.block_type?
101
+ break if node.any_block_type? && !block_sends_to_super?(super_node, node)
68
102
 
69
103
  break node if DEF_TYPES.include?(node.type)
70
104
  end
71
- return unless def_node
72
- return unless arguments_identical?(def_node, def_node.arguments.argument_list,
73
- super_node.arguments)
74
-
75
- add_offense(super_node) { |corrector| corrector.replace(super_node, 'super') }
76
105
  end
77
106
 
78
- private
79
-
80
107
  # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
81
- def arguments_identical?(def_node, def_args, super_args)
82
- super_args = preprocess_super_args(super_args)
83
- return false if def_args.size != super_args.size
108
+ def arguments_identical?(def_node, super_node, def_args, super_args)
109
+ return false if argument_list_size_differs?(def_args, super_args, super_node)
84
110
 
85
111
  def_args.zip(super_args).each do |def_arg, super_arg|
86
112
  next if positional_arg_same?(def_arg, super_arg)
87
113
  next if positional_rest_arg_same(def_arg, super_arg)
88
114
  next if keyword_arg_same?(def_arg, super_arg)
89
115
  next if keyword_rest_arg_same?(def_arg, super_arg)
90
- next if block_arg_same?(def_node, def_arg, super_arg)
116
+ next if block_arg_same?(def_node, super_node, def_arg, super_arg)
91
117
  next if forward_arg_same?(def_arg, super_arg)
92
118
 
93
119
  return false
94
120
  end
121
+
95
122
  true
96
123
  end
97
124
  # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
98
125
 
126
+ def argument_list_size_differs?(def_args, super_args, super_node)
127
+ # If the def node has a block argument and the super node has an explicit block,
128
+ # the number of arguments is the same, so ignore the def node block arg.
129
+ def_args_size = def_args.size
130
+ def_args_size -= 1 if def_args.any?(&:blockarg_type?) && block_sends_to_super?(super_node)
131
+
132
+ def_args_size != super_args.size
133
+ end
134
+
135
+ def block_sends_to_super?(super_node, parent_node = super_node.parent)
136
+ # Checks if the send node of a block is the given super node,
137
+ # or a method chain containing it.
138
+ return false unless parent_node
139
+ return false unless parent_node.any_block_type?
140
+
141
+ parent_node.send_node.each_node(:super).any?(super_node)
142
+ end
143
+
99
144
  def positional_arg_same?(def_arg, super_arg)
100
- return false unless def_arg.arg_type? || def_arg.optarg_type?
145
+ return false unless def_arg.type?(:arg, :optarg)
101
146
  return false unless super_arg.lvar_type?
102
147
 
103
148
  def_arg.name == super_arg.children.first
@@ -114,7 +159,7 @@ module RuboCop
114
159
  end
115
160
 
116
161
  def keyword_arg_same?(def_arg, super_arg)
117
- return false unless def_arg.kwarg_type? || def_arg.kwoptarg_type?
162
+ return false unless def_arg.type?(:kwarg, :kwoptarg)
118
163
  return false unless (pair_node = super_arg).pair_type?
119
164
  return false unless (sym_node = pair_node.key).sym_type?
120
165
  return false unless (lvar_node = pair_node.value).lvar_type?
@@ -133,8 +178,11 @@ module RuboCop
133
178
  def_arg.name == lvar_node.children.first
134
179
  end
135
180
 
136
- def block_arg_same?(def_node, def_arg, super_arg)
137
- return false unless def_arg.blockarg_type? && super_arg.block_pass_type?
181
+ def block_arg_same?(def_node, super_node, def_arg, super_arg)
182
+ return false unless def_arg.blockarg_type?
183
+ return true if block_sends_to_super?(super_node)
184
+ return false unless super_arg.block_pass_type?
185
+
138
186
  # anonymous forwarding
139
187
  return true if (block_pass_child = super_arg.children.first).nil? && def_arg.name.nil?
140
188
 
@@ -232,7 +232,7 @@ module RuboCop
232
232
  end
233
233
 
234
234
  def node_with_args?(node)
235
- node.call_type? || node.defined_type?
235
+ node.type?(:call, :defined?)
236
236
  end
237
237
  end
238
238
  end
@@ -77,7 +77,7 @@ module RuboCop
77
77
 
78
78
  # @!method define_method_block?(node)
79
79
  def_node_matcher :define_method_block?, <<~PATTERN
80
- ({block numblock} (send _ :define_method _) ...)
80
+ (any_block (send _ :define_method _) ...)
81
81
  PATTERN
82
82
  end
83
83
  end
@@ -7,12 +7,15 @@ module RuboCop
7
7
  # The supported styles are:
8
8
  #
9
9
  # * `consistent_comma`: Requires a comma after the last argument,
10
- # for all parenthesized method calls with arguments.
10
+ # for all parenthesized multi-line method calls with arguments.
11
11
  # * `comma`: Requires a comma after the last argument, but only for
12
12
  # parenthesized method calls where each argument is on its own line.
13
13
  # * `no_comma`: Requires that there is no comma after the last
14
14
  # argument.
15
15
  #
16
+ # Regardless of style, trailing commas are not allowed in
17
+ # single-line method calls.
18
+ #
16
19
  # @example EnforcedStyleForMultiline: consistent_comma
17
20
  # # bad
18
21
  # method(1, 2,)
@@ -24,7 +24,6 @@ module RuboCop
24
24
  # # good
25
25
  # x += 1 until x > 10
26
26
  #
27
- # @example
28
27
  # # bad
29
28
  # x += 100 while x < 500 # a long comment that makes code too long if it were a single line
30
29
  #
@@ -85,6 +85,12 @@ module RuboCop
85
85
  NONCOMMUTATIVE_OPERATORS = %i[===].freeze
86
86
  PROGRAM_NAMES = %i[$0 $PROGRAM_NAME].freeze
87
87
  RESTRICT_ON_SEND = RuboCop::AST::Node::COMPARISON_OPERATORS
88
+ ENFORCE_YODA_STYLES = %i[
89
+ require_for_all_comparison_operators require_for_equality_operators_only
90
+ ].freeze
91
+ EQUALITY_ONLY_STYLES = %i[
92
+ forbid_for_equality_operators_only require_for_equality_operators_only
93
+ ].freeze
88
94
 
89
95
  # @!method file_constant_equal_program_name?(node)
90
96
  def_node_matcher :file_constant_equal_program_name?, <<~PATTERN
@@ -105,13 +111,11 @@ module RuboCop
105
111
  private
106
112
 
107
113
  def enforce_yoda?
108
- style == :require_for_all_comparison_operators ||
109
- style == :require_for_equality_operators_only
114
+ ENFORCE_YODA_STYLES.include?(style)
110
115
  end
111
116
 
112
117
  def equality_only?
113
- style == :forbid_for_equality_operators_only ||
114
- style == :require_for_equality_operators_only
118
+ EQUALITY_ONLY_STYLES.include?(style)
115
119
  end
116
120
 
117
121
  def yoda_compatible_condition?(node)
@@ -50,6 +50,7 @@ module RuboCop
50
50
 
51
51
  def on_send(node)
52
52
  return unless supported_operators.include?(node.method_name.to_s)
53
+ return unless node.arguments?
53
54
 
54
55
  lhs = node.receiver
55
56
  rhs = node.first_argument
@@ -71,7 +72,7 @@ module RuboCop
71
72
  end
72
73
 
73
74
  def constant_portion?(node)
74
- node.numeric_type? || node.const_type?
75
+ node.type?(:numeric, :const)
75
76
  end
76
77
 
77
78
  def supported_operators
@@ -74,9 +74,9 @@ module RuboCop
74
74
 
75
75
  def args_begin(node)
76
76
  loc = node.loc
77
- selector = if node.super_type? || node.yield_type?
77
+ selector = if node.type?(:super, :yield)
78
78
  loc.keyword
79
- elsif node.def_type? || node.defs_type?
79
+ elsif node.type?(:def, :defs)
80
80
  loc.name
81
81
  else
82
82
  loc.selector
@@ -193,11 +193,18 @@ module RuboCop
193
193
  enforced_style.sub(/^Enforced/, 'Supported').sub('Style', 'Styles')
194
194
  end
195
195
 
196
+ def parse_regexp(text)
197
+ Regexp::Parser.parse(text)
198
+ rescue Regexp::Parser::Error
199
+ # Upon encountering an invalid regular expression,
200
+ # we aim to proceed and identify any remaining potential offenses.
201
+ nil
202
+ end
203
+
196
204
  private
197
205
 
198
206
  def compatible_external_encoding_for?(src)
199
- src = src.dup if RUBY_ENGINE == 'jruby'
200
- src.force_encoding(Encoding.default_external).valid_encoding?
207
+ src.dup.force_encoding(Encoding.default_external).valid_encoding?
201
208
  end
202
209
 
203
210
  def include_or_equal?(source, target)
@@ -6,6 +6,8 @@ module RuboCop
6
6
  # A Variable represents existence of a local variable.
7
7
  # This holds a variable declaration node and some states of the variable.
8
8
  class Variable
9
+ extend NodePattern::Macros
10
+
9
11
  VARIABLE_DECLARATION_TYPES = (VARIABLE_ASSIGNMENT_TYPES + ARGUMENT_DECLARATION_TYPES).freeze
10
12
 
11
13
  attr_reader :name, :declaration_node, :scope, :assignments, :references, :captured_by_block
@@ -31,11 +33,21 @@ module RuboCop
31
33
  def assign(node)
32
34
  assignment = Assignment.new(node, self)
33
35
 
34
- @assignments.last&.reassigned! unless captured_by_block?
36
+ mark_last_as_reassigned!(assignment)
35
37
 
36
38
  @assignments << assignment
37
39
  end
38
40
 
41
+ def mark_last_as_reassigned!(assignment)
42
+ return if captured_by_block?
43
+ return if candidate_condition?(assignment.node.parent)
44
+
45
+ @assignments.last&.reassigned!
46
+ end
47
+
48
+ # @!method candidate_condition?(node)
49
+ def_node_matcher :candidate_condition?, '[{if case case_match when}]'
50
+
39
51
  def referenced?
40
52
  !@references.empty?
41
53
  end
@@ -72,7 +84,7 @@ module RuboCop
72
84
  parent = parent.parent if parent&.begin_type?
73
85
  return false if parent.nil?
74
86
 
75
- (parent.if_type? || parent.while_type? || parent.until_type?) && parent.modifier_form?
87
+ parent.type?(:if, :while, :until) && parent.modifier_form?
76
88
  end
77
89
 
78
90
  def capture_with_block!
@@ -100,7 +100,7 @@ module RuboCop
100
100
 
101
101
  # Only block scope allows referencing outer scope variables.
102
102
  node = scope.node
103
- return nil unless node.block_type? || node.numblock_type?
103
+ return nil unless node.any_block_type?
104
104
  end
105
105
 
106
106
  nil
@@ -113,14 +113,14 @@ module RuboCop
113
113
  def accessible_variables
114
114
  scope_stack.reverse_each.with_object([]) do |scope, variables|
115
115
  variables.concat(scope.variables.values)
116
- break variables unless scope.node.block_type? || scope.node.numblock_type?
116
+ break variables unless scope.node.any_block_type?
117
117
  end
118
118
  end
119
119
 
120
120
  private
121
121
 
122
122
  def mark_variable_as_captured_by_block_if_so(variable)
123
- return unless current_scope.node.block_type? || current_scope.node.numblock_type?
123
+ return unless current_scope.node.any_block_type?
124
124
  return if variable.scope == current_scope
125
125
 
126
126
  variable.capture_with_block!
@@ -18,7 +18,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
18
18
  description: ->(data) { "#{data.description}\n" },
19
19
  safety: ->(data) { safety_object(data.safety_objects, data.cop) },
20
20
  examples: ->(data) { examples(data.example_objects, data.cop) },
21
- configuration: ->(data) { configurations(data.cop.department, data.config, data.cop) },
21
+ configuration: ->(data) { configurations(data.cop.department, data.cop, data.config) },
22
22
  references: ->(data) { references(data.cop, data.see_objects) }
23
23
  }.freeze
24
24
 
@@ -180,17 +180,17 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
180
180
  content
181
181
  end
182
182
 
183
- def configurations(department, pars, cop)
184
- return '' if pars.empty?
185
-
183
+ def configurations(department, cop, cop_config)
186
184
  header = ['Name', 'Default value', 'Configurable values']
187
- configs = pars
185
+ configs = cop_config
188
186
  .each_key
189
187
  .reject { |key| key.start_with?('Supported') }
190
188
  .reject { |key| key.start_with?('AllowMultipleStyles') }
189
+ return '' if configs.empty?
190
+
191
191
  content = configs.map do |name|
192
- configurable = configurable_values(pars, name)
193
- default = format_table_value(pars[name])
192
+ configurable = configurable_values(cop_config, name)
193
+ default = format_table_value(cop_config[name])
194
194
 
195
195
  [configuration_name(department, name), default, configurable]
196
196
  end
@@ -206,17 +206,17 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
206
206
  end
207
207
 
208
208
  # rubocop:disable Metrics/CyclomaticComplexity,Metrics/MethodLength
209
- def configurable_values(pars, name)
209
+ def configurable_values(cop_config, name)
210
210
  case name
211
211
  when /^Enforced/
212
212
  supported_style_name = RuboCop::Cop::Util.to_supported_styles(name)
213
- format_table_value(pars[supported_style_name])
213
+ format_table_value(cop_config[supported_style_name])
214
214
  when 'IndentationWidth'
215
215
  'Integer'
216
216
  when 'Database'
217
- format_table_value(pars['SupportedDatabases'])
217
+ format_table_value(cop_config['SupportedDatabases'])
218
218
  else
219
- case pars[name]
219
+ case cop_config[name]
220
220
  when String
221
221
  'String'
222
222
  when Integer
@@ -319,7 +319,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
319
319
  AutoCorrect Description Enabled StyleGuide Reference Safe SafeAutoCorrect VersionAdded
320
320
  VersionChanged
321
321
  ]
322
- pars = cop_config.reject { |k| non_display_keys.include? k }
322
+ parameters = cop_config.reject { |k| non_display_keys.include? k }
323
323
  description = 'No documentation'
324
324
  example_objects = safety_objects = see_objects = []
325
325
  cop_code(cop) do |code_object|
@@ -329,7 +329,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
329
329
  see_objects = code_object.tags('see')
330
330
  end
331
331
  data = CopData.new(cop: cop, description: description, example_objects: example_objects,
332
- safety_objects: safety_objects, see_objects: see_objects, config: pars)
332
+ safety_objects: safety_objects, see_objects: see_objects, config: parameters)
333
333
  cops_body(data)
334
334
  end
335
335
 
@@ -88,10 +88,15 @@ module RuboCop
88
88
  @cop_names ||= all_cops? ? all_cop_names : parsed_cop_names
89
89
  end
90
90
 
91
+ # Returns an array of cops for this directive comment, without resolving departments
92
+ def raw_cop_names
93
+ @raw_cop_names ||= (cops || '').split(/,\s*/)
94
+ end
95
+
91
96
  # Returns array of specified in this directive department names
92
97
  # when all department disabled
93
98
  def department_names
94
- splitted_cops_string.select { |cop| department?(cop) }
99
+ raw_cop_names.select { |cop| department?(cop) }
95
100
  end
96
101
 
97
102
  # Checks if directive departments include cop
@@ -101,11 +106,11 @@ module RuboCop
101
106
 
102
107
  # Checks if cop department has already used in directive comment
103
108
  def overridden_by_department?(cop)
104
- in_directive_department?(cop) && splitted_cops_string.include?(cop)
109
+ in_directive_department?(cop) && raw_cop_names.include?(cop)
105
110
  end
106
111
 
107
112
  def directive_count
108
- splitted_cops_string.count
113
+ raw_cop_names.count
109
114
  end
110
115
 
111
116
  # Returns line number for directive
@@ -115,12 +120,8 @@ module RuboCop
115
120
 
116
121
  private
117
122
 
118
- def splitted_cops_string
119
- (cops || '').split(/,\s*/)
120
- end
121
-
122
123
  def parsed_cop_names
123
- cops = splitted_cops_string.map do |name|
124
+ cops = raw_cop_names.map do |name|
124
125
  department?(name) ? cop_names_for_department(name) : name
125
126
  end.flatten
126
127
  cops - [LINT_SYNTAX_COP]
@@ -77,7 +77,7 @@ module RuboCop
77
77
  case formatter_type
78
78
  when Class
79
79
  formatter_type
80
- when /\A[A-Z]/
80
+ when /\A(::)?[A-Z]/
81
81
  custom_formatter_class(formatter_type)
82
82
  else
83
83
  builtin_formatter_class(formatter_type)
@@ -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