rubocop 1.69.2 → 1.71.1

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 (248) 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/empty_line_between_defs.rb +7 -5
  35. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +1 -0
  36. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +1 -1
  37. data/lib/rubocop/cop/layout/end_alignment.rb +1 -1
  38. data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
  39. data/lib/rubocop/cop/layout/first_argument_indentation.rb +3 -8
  40. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -7
  41. data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +2 -7
  42. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +1 -1
  43. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +2 -2
  44. data/lib/rubocop/cop/layout/hash_alignment.rb +6 -4
  45. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -0
  46. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +7 -1
  47. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -2
  48. data/lib/rubocop/cop/layout/line_length.rb +1 -0
  49. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +1 -1
  50. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +25 -0
  51. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -0
  52. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +2 -2
  53. data/lib/rubocop/cop/layout/redundant_line_break.rb +7 -6
  54. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +1 -1
  55. data/lib/rubocop/cop/layout/single_line_block_chain.rb +1 -1
  56. data/lib/rubocop/cop/layout/space_after_colon.rb +2 -2
  57. data/lib/rubocop/cop/layout/space_after_comma.rb +1 -1
  58. data/lib/rubocop/cop/layout/space_after_method_name.rb +1 -1
  59. data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
  60. data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -0
  61. data/lib/rubocop/cop/layout/space_around_operators.rb +3 -3
  62. data/lib/rubocop/cop/layout/space_before_comma.rb +1 -1
  63. data/lib/rubocop/cop/layout/space_before_semicolon.rb +1 -1
  64. data/lib/rubocop/cop/layout/trailing_whitespace.rb +5 -3
  65. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +1 -1
  66. data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +119 -0
  67. data/lib/rubocop/cop/lint/assignment_in_condition.rb +1 -3
  68. data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +1 -1
  69. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +3 -3
  70. data/lib/rubocop/cop/lint/constant_reassignment.rb +148 -0
  71. data/lib/rubocop/cop/lint/debugger.rb +1 -1
  72. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +1 -1
  73. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -1
  74. data/lib/rubocop/cop/lint/duplicate_set_element.rb +20 -7
  75. data/lib/rubocop/cop/lint/float_comparison.rb +5 -2
  76. data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
  77. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -1
  78. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
  79. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +24 -6
  80. data/lib/rubocop/cop/lint/missing_super.rb +2 -2
  81. data/lib/rubocop/cop/lint/mixed_case_range.rb +1 -1
  82. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -1
  83. data/lib/rubocop/cop/lint/nested_method_definition.rb +8 -4
  84. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  85. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +4 -3
  86. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +1 -1
  87. data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +18 -31
  88. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -1
  89. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -5
  90. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
  91. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +2 -2
  92. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
  93. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +8 -1
  94. data/lib/rubocop/cop/lint/shared_mutable_default.rb +65 -0
  95. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  96. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  97. data/lib/rubocop/cop/lint/syntax.rb +4 -1
  98. data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +1 -4
  99. data/lib/rubocop/cop/lint/unexpected_block_arity.rb +1 -1
  100. data/lib/rubocop/cop/lint/unreachable_code.rb +1 -1
  101. data/lib/rubocop/cop/lint/unreachable_loop.rb +1 -1
  102. data/lib/rubocop/cop/lint/useless_access_modifier.rb +4 -4
  103. data/lib/rubocop/cop/lint/useless_assignment.rb +1 -1
  104. data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
  105. data/lib/rubocop/cop/lint/useless_numeric_operation.rb +2 -1
  106. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +2 -2
  107. data/lib/rubocop/cop/lint/void.rb +4 -3
  108. data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
  109. data/lib/rubocop/cop/metrics/collection_literal_length.rb +7 -0
  110. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
  111. data/lib/rubocop/cop/metrics/method_length.rb +8 -1
  112. data/lib/rubocop/cop/metrics/module_length.rb +1 -1
  113. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  114. data/lib/rubocop/cop/mixin/check_line_breakable.rb +11 -11
  115. data/lib/rubocop/cop/mixin/comments_help.rb +3 -1
  116. data/lib/rubocop/cop/mixin/dig_help.rb +1 -1
  117. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -1
  118. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +4 -4
  119. data/lib/rubocop/cop/mixin/hash_subset.rb +188 -0
  120. data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
  121. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +48 -24
  122. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
  123. data/lib/rubocop/cop/mixin/statement_modifier.rb +8 -3
  124. data/lib/rubocop/cop/mixin/string_help.rb +1 -1
  125. data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
  126. data/lib/rubocop/cop/mixin/trailing_comma.rb +3 -3
  127. data/lib/rubocop/cop/naming/block_forwarding.rb +19 -15
  128. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +3 -3
  129. data/lib/rubocop/cop/security/compound_hash.rb +1 -0
  130. data/lib/rubocop/cop/style/access_modifier_declarations.rb +34 -5
  131. data/lib/rubocop/cop/style/and_or.rb +1 -1
  132. data/lib/rubocop/cop/style/arguments_forwarding.rb +39 -23
  133. data/lib/rubocop/cop/style/array_first_last.rb +18 -2
  134. data/lib/rubocop/cop/style/block_delimiters.rb +7 -20
  135. data/lib/rubocop/cop/style/class_and_module_children.rb +6 -3
  136. data/lib/rubocop/cop/style/collection_methods.rb +1 -1
  137. data/lib/rubocop/cop/style/combinable_defined.rb +1 -1
  138. data/lib/rubocop/cop/style/combinable_loops.rb +2 -2
  139. data/lib/rubocop/cop/style/concat_array_literals.rb +1 -1
  140. data/lib/rubocop/cop/style/conditional_assignment.rb +6 -4
  141. data/lib/rubocop/cop/style/documentation.rb +1 -1
  142. data/lib/rubocop/cop/style/double_negation.rb +3 -3
  143. data/lib/rubocop/cop/style/each_for_simple_loop.rb +4 -7
  144. data/lib/rubocop/cop/style/empty_else.rb +4 -2
  145. data/lib/rubocop/cop/style/empty_literal.rb +1 -1
  146. data/lib/rubocop/cop/style/empty_method.rb +1 -1
  147. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  148. data/lib/rubocop/cop/style/exact_regexp_match.rb +3 -10
  149. data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
  150. data/lib/rubocop/cop/style/exponential_notation.rb +1 -1
  151. data/lib/rubocop/cop/style/fetch_env_var.rb +1 -1
  152. data/lib/rubocop/cop/style/float_division.rb +8 -4
  153. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
  154. data/lib/rubocop/cop/style/hash_each_methods.rb +3 -6
  155. data/lib/rubocop/cop/style/hash_except.rb +24 -148
  156. data/lib/rubocop/cop/style/hash_slice.rb +80 -0
  157. data/lib/rubocop/cop/style/hash_syntax.rb +6 -3
  158. data/lib/rubocop/cop/style/identical_conditional_branches.rb +22 -3
  159. data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -3
  160. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +1 -1
  161. data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -2
  162. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  163. data/lib/rubocop/cop/style/inverse_methods.rb +6 -6
  164. data/lib/rubocop/cop/style/it_assignment.rb +36 -0
  165. data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -1
  166. data/lib/rubocop/cop/style/map_into_array.rb +1 -1
  167. data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
  168. data/lib/rubocop/cop/style/map_to_set.rb +3 -2
  169. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +19 -12
  170. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -0
  171. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -1
  172. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -4
  173. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  174. data/lib/rubocop/cop/style/missing_else.rb +2 -0
  175. data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
  176. data/lib/rubocop/cop/style/multiple_comparison.rb +26 -20
  177. data/lib/rubocop/cop/style/mutable_constant.rb +3 -3
  178. data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -1
  179. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
  180. data/lib/rubocop/cop/style/object_then.rb +13 -15
  181. data/lib/rubocop/cop/style/open_struct_use.rb +5 -5
  182. data/lib/rubocop/cop/style/parallel_assignment.rb +1 -5
  183. data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
  184. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  185. data/lib/rubocop/cop/style/proc.rb +1 -2
  186. data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
  187. data/lib/rubocop/cop/style/raise_args.rb +6 -4
  188. data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
  189. data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
  190. data/lib/rubocop/cop/style/redundant_condition.rb +2 -2
  191. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +2 -1
  192. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +6 -10
  193. data/lib/rubocop/cop/style/redundant_each.rb +1 -1
  194. data/lib/rubocop/cop/style/redundant_exception.rb +2 -2
  195. data/lib/rubocop/cop/style/redundant_freeze.rb +2 -2
  196. data/lib/rubocop/cop/style/redundant_initialize.rb +12 -3
  197. data/lib/rubocop/cop/style/redundant_line_continuation.rb +34 -13
  198. data/lib/rubocop/cop/style/redundant_parentheses.rb +10 -10
  199. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +3 -0
  200. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +1 -1
  201. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +1 -1
  202. data/lib/rubocop/cop/style/redundant_self_assignment.rb +14 -28
  203. data/lib/rubocop/cop/style/redundant_sort.rb +2 -2
  204. data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -2
  205. data/lib/rubocop/cop/style/return_nil.rb +1 -1
  206. data/lib/rubocop/cop/style/safe_navigation.rb +2 -2
  207. data/lib/rubocop/cop/style/semicolon.rb +1 -1
  208. data/lib/rubocop/cop/style/send_with_literal_method_name.rb +2 -1
  209. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  210. data/lib/rubocop/cop/style/single_line_do_end_block.rb +1 -2
  211. data/lib/rubocop/cop/style/single_line_methods.rb +3 -4
  212. data/lib/rubocop/cop/style/slicing_with_range.rb +40 -11
  213. data/lib/rubocop/cop/style/sole_nested_conditional.rb +2 -2
  214. data/lib/rubocop/cop/style/string_concatenation.rb +1 -1
  215. data/lib/rubocop/cop/style/string_literals.rb +1 -1
  216. data/lib/rubocop/cop/style/string_methods.rb +1 -1
  217. data/lib/rubocop/cop/style/super_arguments.rb +65 -17
  218. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
  219. data/lib/rubocop/cop/style/top_level_method_definition.rb +1 -1
  220. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -1
  221. data/lib/rubocop/cop/style/yoda_condition.rb +8 -4
  222. data/lib/rubocop/cop/style/yoda_expression.rb +2 -1
  223. data/lib/rubocop/cop/util.rb +11 -4
  224. data/lib/rubocop/cop/variable_force/variable.rb +1 -1
  225. data/lib/rubocop/cop/variable_force/variable_table.rb +3 -3
  226. data/lib/rubocop/cops_documentation_generator.rb +13 -13
  227. data/lib/rubocop/directive_comment.rb +9 -8
  228. data/lib/rubocop/formatter/formatter_set.rb +1 -1
  229. data/lib/rubocop/lsp/diagnostic.rb +189 -0
  230. data/lib/rubocop/lsp/logger.rb +2 -2
  231. data/lib/rubocop/lsp/routes.rb +7 -23
  232. data/lib/rubocop/lsp/runtime.rb +15 -49
  233. data/lib/rubocop/lsp/stdin_runner.rb +83 -0
  234. data/lib/rubocop/options.rb +2 -1
  235. data/lib/rubocop/path_util.rb +11 -8
  236. data/lib/rubocop/result_cache.rb +13 -13
  237. data/lib/rubocop/rspec/expect_offense.rb +6 -2
  238. data/lib/rubocop/rspec/shared_contexts.rb +4 -1
  239. data/lib/rubocop/rspec/support.rb +1 -2
  240. data/lib/rubocop/runner.rb +5 -6
  241. data/lib/rubocop/target_finder.rb +1 -0
  242. data/lib/rubocop/target_ruby.rb +15 -0
  243. data/lib/rubocop/version.rb +1 -1
  244. data/lib/rubocop.rb +6 -0
  245. data/lib/ruby_lsp/rubocop/addon.rb +78 -0
  246. data/lib/ruby_lsp/rubocop/wraps_built_in_lsp_runtime.rb +50 -0
  247. metadata +23 -11
  248. data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -28
@@ -73,10 +73,15 @@ module RuboCop
73
73
  LINE_CONTINUATION_PATTERN = /(\\\n)/.freeze
74
74
  ALLOWED_STRING_TOKENS = %i[tSTRING tSTRING_CONTENT].freeze
75
75
  ARGUMENT_TYPES = %i[
76
- kDEF kFALSE kNIL kSELF kTRUE tCONSTANT tCVAR tFLOAT tGVAR tIDENTIFIER tINTEGER tIVAR
77
- tLBRACK tLCURLY tLPAREN_ARG tSTRING tSTRING_BEG tSYMBOL tXSTRING_BEG
76
+ kDEF kDEFINED kFALSE kNIL kSELF kTRUE tAMPER tBANG tCARET tCHARACTER tCOLON3 tCONSTANT
77
+ tCVAR tDOT2 tDOT3 tFLOAT tGVAR tIDENTIFIER tINTEGER tIVAR tLAMBDA tLBRACK tLCURLY
78
+ tLPAREN_ARG tPIPE tQSYMBOLS_BEG tQWORDS_BEG tREGEXP_BEG tSTAR tSTRING tSTRING_BEG tSYMBEG
79
+ tSYMBOL tSYMBOLS_BEG tTILDE tUMINUS tUNARY_NUM tUPLUS tWORDS_BEG tXSTRING_BEG
78
80
  ].freeze
79
- ARGUMENT_TAKING_FLOW_TOKEN_TYPES = %i[tIDENTIFIER kRETURN kBREAK kNEXT kYIELD].freeze
81
+ ARGUMENT_TAKING_FLOW_TOKEN_TYPES = %i[
82
+ tIDENTIFIER kBREAK kNEXT kRETURN kSUPER kYIELD
83
+ ].freeze
84
+ ARITHMETIC_OPERATOR_TOKENS = %i[tDIVIDE tDSTAR tMINUS tPERCENT tPLUS tSTAR2].freeze
80
85
 
81
86
  def on_new_investigation
82
87
  return unless processed_source.ast
@@ -96,15 +101,20 @@ module RuboCop
96
101
  private
97
102
 
98
103
  def require_line_continuation?(range)
99
- !ends_with_backslash_without_comment?(range.source_line) ||
104
+ !ends_with_uncommented_backslash?(range) ||
100
105
  string_concatenation?(range.source_line) ||
101
- start_with_arithmetic_operator?(processed_source[range.line]) ||
106
+ start_with_arithmetic_operator?(range) ||
102
107
  inside_string_literal_or_method_with_argument?(range) ||
103
108
  leading_dot_method_chain_with_blank_line?(range)
104
109
  end
105
110
 
106
- def ends_with_backslash_without_comment?(source_line)
107
- source_line.gsub(/#.+/, '').end_with?('\\')
111
+ def ends_with_uncommented_backslash?(range)
112
+ # A line continuation always needs to be the last character on the line, which
113
+ # means that it is impossible to have a comment following a continuation.
114
+ # Therefore, if the line contains a comment, it cannot end with a continuation.
115
+ return false if processed_source.line_with_comment?(range.line)
116
+
117
+ range.source_line.end_with?(LINE_CONTINUATION)
108
118
  end
109
119
 
110
120
  def string_concatenation?(source_line)
@@ -112,10 +122,13 @@ module RuboCop
112
122
  end
113
123
 
114
124
  def inside_string_literal_or_method_with_argument?(range)
125
+ line_range = range_by_whole_lines(range)
126
+
115
127
  processed_source.tokens.each_cons(2).any? do |token, next_token|
116
128
  next if token.line == next_token.line
117
129
 
118
- inside_string_literal?(range, token) || method_with_argument?(token, next_token)
130
+ inside_string_literal?(range, token) ||
131
+ method_with_argument?(line_range, token, next_token)
119
132
  end
120
133
  end
121
134
 
@@ -137,7 +150,7 @@ module RuboCop
137
150
 
138
151
  def inspect_end_of_ruby_code_line_continuation
139
152
  last_line = processed_source.lines[processed_source.ast.last_line - 1]
140
- return unless last_line.end_with?(LINE_CONTINUATION)
153
+ return unless code_ends_with_continuation?(last_line)
141
154
 
142
155
  last_column = last_line.length
143
156
  line_continuation_range = range_between(last_column - 1, last_column)
@@ -147,6 +160,12 @@ module RuboCop
147
160
  end
148
161
  end
149
162
 
163
+ def code_ends_with_continuation?(last_line)
164
+ return false if processed_source.line_with_comment?(processed_source.ast.last_line)
165
+
166
+ last_line.end_with?(LINE_CONTINUATION)
167
+ end
168
+
150
169
  def inside_string_literal?(range, token)
151
170
  ALLOWED_STRING_TOKENS.include?(token.type) && token.pos.overlaps?(range)
152
171
  end
@@ -155,8 +174,9 @@ module RuboCop
155
174
  #
156
175
  # do_something \
157
176
  # argument
158
- def method_with_argument?(current_token, next_token)
177
+ def method_with_argument?(line_range, current_token, next_token)
159
178
  return false unless ARGUMENT_TAKING_FLOW_TOKEN_TYPES.include?(current_token.type)
179
+ return false unless current_token.pos.overlaps?(line_range)
160
180
 
161
181
  ARGUMENT_TYPES.include?(next_token.type)
162
182
  end
@@ -180,7 +200,7 @@ module RuboCop
180
200
 
181
201
  def find_node_for_line(last_line)
182
202
  processed_source.ast.each_node do |node|
183
- return node if node.respond_to?(:expression) && node.expression&.last_line == last_line
203
+ return node if same_line?(node, last_line)
184
204
  end
185
205
  end
186
206
 
@@ -209,8 +229,9 @@ module RuboCop
209
229
  node.call_type? && !node.arguments.empty?
210
230
  end
211
231
 
212
- def start_with_arithmetic_operator?(source_line)
213
- %r{\A\s*[+\-*/%]}.match?(source_line)
232
+ def start_with_arithmetic_operator?(range)
233
+ line_range = processed_source.buffer.line_range(range.line + 1)
234
+ ARITHMETIC_OPERATOR_TOKENS.include?(processed_source.first_token_of(line_range).type)
214
235
  end
215
236
  end
216
237
  end
@@ -50,7 +50,7 @@ module RuboCop
50
50
  def ignore_syntax?(node)
51
51
  return false unless (parent = node.parent)
52
52
 
53
- parent.while_post_type? || parent.until_post_type? || parent.match_with_lvasgn_type? ||
53
+ parent.type?(:while_post, :until_post, :match_with_lvasgn) ||
54
54
  like_method_argument_parentheses?(parent) || multiline_control_flow_statements?(node)
55
55
  end
56
56
 
@@ -72,7 +72,7 @@ module RuboCop
72
72
  ancestor = node.ancestors.first
73
73
  return false unless ancestor
74
74
 
75
- !ancestor.begin_type? && !ancestor.def_type? && !ancestor.block_type?
75
+ !ancestor.type?(:begin, :def, :any_block)
76
76
  end
77
77
 
78
78
  def allowed_ternary?(node)
@@ -89,7 +89,7 @@ module RuboCop
89
89
  end
90
90
 
91
91
  def like_method_argument_parentheses?(node)
92
- return false if !node.send_type? && !node.super_type? && !node.yield_type?
92
+ return false unless node.type?(:send, :super, :yield)
93
93
 
94
94
  node.arguments.one? && !node.parenthesized? &&
95
95
  !node.arithmetic_operation? && node.first_argument.begin_type?
@@ -99,7 +99,7 @@ module RuboCop
99
99
  return false unless (parent = node.parent)
100
100
  return false if parent.single_line?
101
101
 
102
- parent.return_type? || parent.next_type? || parent.break_type?
102
+ parent.type?(:return, :next, :break)
103
103
  end
104
104
 
105
105
  def empty_parentheses?(node)
@@ -140,6 +140,9 @@ module RuboCop
140
140
  return 'a literal' if disallowed_literal?(begin_node, node)
141
141
  return 'a variable' if node.variable?
142
142
  return 'a constant' if node.const_type?
143
+ if node.assignment? && (begin_node.parent.nil? || begin_node.parent.begin_type?)
144
+ return 'an assignment'
145
+ end
143
146
  if node.lambda_or_proc? && (node.braces? || node.send_node.lambda_literal?)
144
147
  return 'an expression'
145
148
  end
@@ -166,10 +169,7 @@ module RuboCop
166
169
  def_node_matcher :interpolation?, '[^begin ^^dstr]'
167
170
 
168
171
  def allow_in_multiline_conditions?
169
- parentheses_around_condition_config = config.for_cop('Style/ParenthesesAroundCondition')
170
- return false unless parentheses_around_condition_config['Enabled']
171
-
172
- !!parentheses_around_condition_config['AllowInMultilineConditions']
172
+ !!config.for_enabled_cop('Style/ParenthesesAroundCondition')['AllowInMultilineConditions']
173
173
  end
174
174
 
175
175
  def check_send(begin_node, node)
@@ -279,9 +279,9 @@ module RuboCop
279
279
  end
280
280
 
281
281
  def do_end_block_in_method_chain?(begin_node, node)
282
- return false unless (block = node.each_descendant(:block, :numblock).first)
282
+ return false unless (block = node.each_descendant(:any_block).first)
283
283
 
284
- block.keywords? && begin_node.each_ancestor(:send, :csend).any?
284
+ block.keywords? && begin_node.each_ancestor(:call).any?
285
285
  end
286
286
  end
287
287
  end
@@ -73,6 +73,9 @@ module RuboCop
73
73
  new_argument.gsub!("'", "\\\\'")
74
74
  new_argument.gsub!('\"', '"')
75
75
  quote = "'"
76
+ elsif new_argument.include?('\'')
77
+ new_argument.gsub!("'", "\\\\'")
78
+ quote = "'"
76
79
  elsif new_argument.include?('\\')
77
80
  quote = '"'
78
81
  else
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Checks for unnecessary single-element Regexp character classes.
6
+ # Checks for unnecessary single-element `Regexp` character classes.
7
7
  #
8
8
  # @example
9
9
  #
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Checks for redundant escapes inside Regexp literals.
6
+ # Checks for redundant escapes inside `Regexp` literals.
7
7
  #
8
8
  # @example
9
9
  # # bad
@@ -21,12 +21,8 @@ module RuboCop
21
21
  # args += foo
22
22
  # hash.merge!(other)
23
23
  #
24
- # # bad
25
- # self.foo = foo.concat(ary)
26
- #
27
24
  # # good
28
25
  # foo.concat(ary)
29
- # self.foo += ary
30
26
  #
31
27
  class RedundantSelfAssignment < Base
32
28
  include RangeHelp
@@ -49,10 +45,20 @@ module RuboCop
49
45
  gvasgn: :gvar
50
46
  }.freeze
51
47
 
48
+ # @!method redundant_self_assignment?
49
+ def_node_matcher :redundant_self_assignment?, <<~PATTERN
50
+ (call
51
+ %1 _
52
+ (call
53
+ (call
54
+ %1 %2) #method_returning_self?
55
+ ...))
56
+ PATTERN
57
+
52
58
  # rubocop:disable Metrics/AbcSize
53
59
  def on_lvasgn(node)
54
60
  return unless (rhs = node.rhs)
55
- return unless rhs.send_type? && method_returning_self?(rhs.method_name)
61
+ return unless rhs.call_type? && method_returning_self?(rhs.method_name)
56
62
  return unless (receiver = rhs.receiver)
57
63
 
58
64
  receiver_type = ASSIGNMENT_TYPE_TO_RECEIVER_TYPE[node.type]
@@ -77,6 +83,7 @@ module RuboCop
77
83
  corrector.remove(correction_range(node))
78
84
  end
79
85
  end
86
+ alias on_csend on_send
80
87
 
81
88
  private
82
89
 
@@ -84,31 +91,10 @@ module RuboCop
84
91
  METHODS_RETURNING_SELF.include?(method_name)
85
92
  end
86
93
 
87
- # @!method redundant_self_assignment?(node, method_name)
88
- def_node_matcher :redundant_self_assignment?, <<~PATTERN
89
- (send
90
- (self) _
91
- (send
92
- (send
93
- {(self) nil?} %1) #method_returning_self?
94
- ...))
95
- PATTERN
96
-
97
- # @!method redundant_nonself_assignment?(node, receiver, method_name)
98
- def_node_matcher :redundant_nonself_assignment?, <<~PATTERN
99
- (send
100
- %1 _
101
- (send
102
- (send
103
- %1 %2) #method_returning_self?
104
- ...))
105
- PATTERN
106
-
107
94
  def redundant_assignment?(node)
108
- receiver_name = node.method_name.to_s[0...-1].to_sym
95
+ receiver_name = node.method_name.to_s.delete_suffix('=').to_sym
109
96
 
110
- redundant_self_assignment?(node, receiver_name) ||
111
- redundant_nonself_assignment?(node, node.receiver, receiver_name)
97
+ redundant_self_assignment?(node, node.receiver, receiver_name)
112
98
  end
113
99
 
114
100
  def correction_range(node)
@@ -93,9 +93,9 @@ module RuboCop
93
93
  (call $(call _ $:sort_by _) ${:last :first})
94
94
  (send $(send _ $:sort_by _) ${:[] :at :slice} {(int 0) (int -1)})
95
95
 
96
- (call ({block numblock} $(call _ ${:sort_by :sort}) ...) ${:last :first})
96
+ (call (any_block $(call _ ${:sort_by :sort}) ...) ${:last :first})
97
97
  (call
98
- ({block numblock} $(call _ ${:sort_by :sort}) ...)
98
+ (any_block $(call _ ${:sort_by :sort}) ...)
99
99
  ${:[] :at :slice} {(int 0) (int -1)}
100
100
  )
101
101
  }
@@ -41,7 +41,7 @@ module RuboCop
41
41
  MSG = 'Redundant escape of %<char>s inside string literal.'
42
42
 
43
43
  def on_str(node)
44
- return if node.parent&.regexp_type? || node.parent&.xstr_type? || node.character_literal?
44
+ return if node.parent&.type?(:regexp, :xstr) || node.character_literal?
45
45
 
46
46
  str_contents_range = str_contents_range(node)
47
47
 
@@ -147,7 +147,7 @@ module RuboCop
147
147
  end
148
148
 
149
149
  def heredoc?(node)
150
- (node.str_type? || node.dstr_type?) && node.heredoc?
150
+ node.type?(:str, :dstr) && node.heredoc?
151
151
  end
152
152
 
153
153
  def delimiter?(node, char)
@@ -83,7 +83,7 @@ module RuboCop
83
83
  end
84
84
 
85
85
  def scoped_node?(node)
86
- node.def_type? || node.defs_type? || node.lambda?
86
+ node.type?(:def, :defs) || node.lambda?
87
87
  end
88
88
 
89
89
  # @!method chained_send?(node)
@@ -312,7 +312,7 @@ module RuboCop
312
312
  end
313
313
 
314
314
  def chain_length(method_chain, method)
315
- method.each_ancestor(:send, :csend).inject(0) do |total, ancestor|
315
+ method.each_ancestor(:call).inject(0) do |total, ancestor|
316
316
  break total + 1 if ancestor == method_chain
317
317
 
318
318
  total + 1
@@ -323,7 +323,7 @@ module RuboCop
323
323
  return true if unsafe_method?(method)
324
324
 
325
325
  method.each_ancestor(:send).any? do |ancestor|
326
- break true unless config.for_cop('Lint/SafeNavigationChain')['Enabled']
326
+ break true unless config.cop_enabled?('Lint/SafeNavigationChain')
327
327
 
328
328
  break true if unsafe_method?(ancestor)
329
329
  break true if nil_methods.include?(ancestor.method_name)
@@ -164,7 +164,7 @@ module RuboCop
164
164
 
165
165
  ast = processed_source.ast
166
166
  @range_nodes = ast.range_type? ? [ast] : []
167
- @range_nodes.concat(ast.each_descendant(:irange, :erange).to_a)
167
+ @range_nodes.concat(ast.each_descendant(:range).to_a)
168
168
  end
169
169
  end
170
170
  end
@@ -68,7 +68,7 @@ module RuboCop
68
68
  def on_send(node)
69
69
  return if allow_send? && !node.method?(:public_send)
70
70
  return unless (first_argument = node.first_argument)
71
- return unless STATIC_METHOD_NAME_NODE_TYPES.include?(first_argument.type)
71
+ return unless first_argument.type?(*STATIC_METHOD_NAME_NODE_TYPES)
72
72
 
73
73
  offense_range = offense_range(node)
74
74
  method_name = first_argument.value
@@ -83,6 +83,7 @@ module RuboCop
83
83
  end
84
84
  end
85
85
  end
86
+ alias on_csend on_send
86
87
  # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
87
88
 
88
89
  private
@@ -10,7 +10,7 @@ module RuboCop
10
10
  # parameters.
11
11
  #
12
12
  # Configuration option: Methods
13
- # Should be set to use this cop. Array of hashes, where each key is the
13
+ # Should be set to use this cop. `Array` of hashes, where each key is the
14
14
  # method name and value - array of argument names.
15
15
  #
16
16
  # @example Methods: [{reduce: %w[a b]}]
@@ -68,8 +68,7 @@ module RuboCop
68
68
  end
69
69
 
70
70
  def single_line_blocks_preferred?
71
- redundant_line_break_config = @config.for_cop('Layout/RedundantLineBreak')
72
- redundant_line_break_config['Enabled'] && redundant_line_break_config['InspectBlocks']
71
+ @config.for_enabled_cop('Layout/RedundantLineBreak')['InspectBlocks']
73
72
  end
74
73
  end
75
74
  end
@@ -68,7 +68,7 @@ module RuboCop
68
68
  return false if body_node.parent.assignment_method? ||
69
69
  NOT_SUPPORTED_ENDLESS_METHOD_BODY_TYPES.include?(body_node.type)
70
70
 
71
- !(body_node.begin_type? || body_node.kwbegin_type?)
71
+ !body_node.type?(:begin, :kwbegin)
72
72
  end
73
73
 
74
74
  def correct_to_multiline(corrector, node)
@@ -134,10 +134,9 @@ module RuboCop
134
134
  end
135
135
 
136
136
  def disallow_endless_method_style?
137
- endless_method_config = config.for_cop('Style/EndlessMethod')
138
- return true unless endless_method_config['Enabled']
137
+ return true unless config.cop_enabled?('Style/EndlessMethod')
139
138
 
140
- endless_method_config['EnforcedStyle'] == 'disallow'
139
+ config.for_cop('Style/EndlessMethod')['EnforcedStyle'] == 'disallow'
141
140
  end
142
141
  end
143
142
  end
@@ -78,38 +78,67 @@ module RuboCop
78
78
  return unless node.arguments.one?
79
79
 
80
80
  range_node = node.first_argument
81
- selector = node.loc.selector
82
- unless (message, removal_range = offense_message_with_removal_range(range_node, selector))
83
- return
84
- end
81
+ offense_range = find_offense_range(node)
82
+ return unless (message, removal_range =
83
+ offense_message_with_removal_range(node, range_node, offense_range))
84
+
85
+ # Changing the range to beginningless or endless when unparenthesized
86
+ # changes the semantics of the code, and thus will not be considered
87
+ # an offense.
88
+ return if removal_range != offense_range && unparenthesized_call?(node)
85
89
 
86
- add_offense(selector, message: message) do |corrector|
90
+ add_offense(offense_range, message: message) do |corrector|
87
91
  corrector.remove(removal_range)
88
92
  end
89
93
  end
94
+ alias on_csend on_send
90
95
 
91
96
  private
92
97
 
93
- def offense_message_with_removal_range(range_node, selector)
98
+ def unparenthesized_call?(node)
99
+ node.loc.dot && !node.parenthesized?
100
+ end
101
+
102
+ def find_offense_range(node)
103
+ if node.loc.dot
104
+ node.loc.dot.join(node.source_range.end)
105
+ else
106
+ node.loc.selector
107
+ end
108
+ end
109
+
110
+ def offense_message_with_removal_range(node, range_node, offense_range)
94
111
  if range_from_zero_till_minus_one?(range_node)
95
- [format(MSG_USELESS_RANGE, prefer: selector.source), selector]
112
+ [format(MSG_USELESS_RANGE, prefer: offense_range.source), offense_range]
96
113
  elsif range_till_minus_one?(range_node)
97
114
  [
98
- format(MSG, prefer: endless(range_node), current: selector.source), range_node.end
115
+ offense_message_for_partial_range(node, endless(range_node), offense_range),
116
+ range_node.end
99
117
  ]
100
118
  elsif range_from_zero?(range_node) && target_ruby_version >= 2.7
101
119
  [
102
- format(MSG, prefer: beginless(range_node), current: selector.source), range_node.begin
120
+ offense_message_for_partial_range(node, beginless(range_node), offense_range),
121
+ range_node.begin
103
122
  ]
104
123
  end
105
124
  end
106
125
 
126
+ def offense_message_for_partial_range(node, prefer, offense_range)
127
+ current = node.loc.dot ? arguments_source(node) : offense_range.source
128
+ prefer = "[#{prefer}]" unless node.loc.dot
129
+ format(MSG, prefer: prefer, current: current)
130
+ end
131
+
107
132
  def endless(range_node)
108
- "[#{range_node.begin.source}#{range_node.loc.operator.source}]"
133
+ "#{range_node.begin.source}#{range_node.loc.operator.source}"
109
134
  end
110
135
 
111
136
  def beginless(range_node)
112
- "[#{range_node.loc.operator.source}#{range_node.end.source}]"
137
+ "#{range_node.loc.operator.source}#{range_node.end.source}"
138
+ end
139
+
140
+ def arguments_source(node)
141
+ node.first_argument.source_range.join(node.last_argument.source_range.end).source
113
142
  end
114
143
  end
115
144
  end
@@ -156,7 +156,7 @@ module RuboCop
156
156
  # Handle `send` and `block` nodes that need to be wrapped in parens
157
157
  # FIXME: autocorrection prevents syntax errors by wrapping the entire node in parens,
158
158
  # but wrapping the argument list would be a more ergonomic correction.
159
- node_to_check = condition&.block_type? ? condition.send_node : condition
159
+ node_to_check = condition&.any_block_type? ? condition.send_node : condition
160
160
  return unless wrap_condition?(node_to_check)
161
161
 
162
162
  if condition.call_type?
@@ -243,7 +243,7 @@ module RuboCop
243
243
  def replace_condition(condition)
244
244
  return condition.source unless wrap_condition?(condition)
245
245
 
246
- if condition.call_type?
246
+ if condition.call_type? && !condition.comparison_method?
247
247
  parenthesized_method_arguments(condition)
248
248
  else
249
249
  "(#{condition.source})"
@@ -132,7 +132,7 @@ module RuboCop
132
132
  end
133
133
 
134
134
  def heredoc?(node)
135
- return false unless node.str_type? || node.dstr_type?
135
+ return false unless node.type?(:str, :dstr)
136
136
 
137
137
  node.heredoc?
138
138
  end
@@ -69,7 +69,7 @@ module RuboCop
69
69
  end
70
70
 
71
71
  def all_string_literals?(nodes)
72
- nodes.all? { |n| n.str_type? || n.dstr_type? }
72
+ nodes.all? { |n| n.type?(:str, :dstr) }
73
73
  end
74
74
 
75
75
  def detect_quote_styles(node)
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module Cop
5
5
  module Style
6
6
  # Enforces the use of consistent method names
7
- # from the String class.
7
+ # from the `String` class.
8
8
  #
9
9
  # @example
10
10
  # # bad