rubocop 1.43.0 → 1.50.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (286) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +108 -40
  4. data/lib/rubocop/cli/command/auto_generate_config.rb +7 -0
  5. data/lib/rubocop/cli/command/execute_runner.rb +7 -2
  6. data/lib/rubocop/cli.rb +54 -8
  7. data/lib/rubocop/comment_config.rb +19 -0
  8. data/lib/rubocop/config.rb +3 -3
  9. data/lib/rubocop/config_loader.rb +20 -23
  10. data/lib/rubocop/config_loader_resolver.rb +3 -4
  11. data/lib/rubocop/cop/autocorrect_logic.rb +29 -13
  12. data/lib/rubocop/cop/base.rb +28 -10
  13. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
  14. data/lib/rubocop/cop/commissioner.rb +8 -2
  15. data/lib/rubocop/cop/cop.rb +25 -5
  16. data/lib/rubocop/cop/corrector.rb +11 -3
  17. data/lib/rubocop/cop/correctors/alignment_corrector.rb +2 -2
  18. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +3 -3
  19. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +3 -3
  20. data/lib/rubocop/cop/correctors/line_break_corrector.rb +1 -1
  21. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +2 -2
  22. data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +2 -7
  23. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +1 -1
  24. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
  25. data/lib/rubocop/cop/gemspec/dependency_version.rb +1 -1
  26. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +1 -1
  27. data/lib/rubocop/cop/gemspec/development_dependencies.rb +107 -0
  28. data/lib/rubocop/cop/internal_affairs/cop_description.rb +5 -5
  29. data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +3 -3
  30. data/lib/rubocop/cop/internal_affairs/inherit_deprecated_cop_class.rb +1 -1
  31. data/lib/rubocop/cop/internal_affairs/location_expression.rb +37 -0
  32. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
  33. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +1 -1
  34. data/lib/rubocop/cop/internal_affairs/processed_source_buffer_name.rb +42 -0
  35. data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +11 -3
  36. data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +1 -1
  37. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +1 -1
  38. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +66 -0
  39. data/lib/rubocop/cop/internal_affairs.rb +3 -0
  40. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  41. data/lib/rubocop/cop/layout/block_end_newline.rb +7 -15
  42. data/lib/rubocop/cop/layout/class_structure.rb +8 -19
  43. data/lib/rubocop/cop/layout/closing_heredoc_indentation.rb +1 -1
  44. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +2 -6
  45. data/lib/rubocop/cop/layout/empty_comment.rb +3 -3
  46. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +1 -1
  47. data/lib/rubocop/cop/layout/empty_lines.rb +1 -1
  48. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +2 -0
  49. data/lib/rubocop/cop/layout/end_alignment.rb +9 -1
  50. data/lib/rubocop/cop/layout/extra_spacing.rb +6 -1
  51. data/lib/rubocop/cop/layout/first_argument_indentation.rb +8 -3
  52. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +25 -34
  53. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +7 -19
  54. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +42 -52
  55. data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +38 -55
  56. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +8 -2
  57. data/lib/rubocop/cop/layout/heredoc_indentation.rb +8 -11
  58. data/lib/rubocop/cop/layout/initial_indentation.rb +1 -1
  59. data/lib/rubocop/cop/layout/leading_comment_space.rb +1 -1
  60. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +1 -3
  61. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +11 -7
  62. data/lib/rubocop/cop/layout/multiline_array_line_breaks.rb +8 -27
  63. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +7 -26
  64. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +4 -21
  65. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +6 -30
  66. data/lib/rubocop/cop/layout/redundant_line_break.rb +6 -7
  67. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +2 -2
  68. data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
  69. data/lib/rubocop/cop/layout/space_around_operators.rb +1 -1
  70. data/lib/rubocop/cop/layout/space_before_first_arg.rb +1 -1
  71. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +2 -2
  72. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +11 -13
  73. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +1 -1
  74. data/lib/rubocop/cop/layout/space_inside_parens.rb +2 -2
  75. data/lib/rubocop/cop/layout/space_inside_percent_literal_delimiters.rb +1 -1
  76. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +4 -4
  77. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +5 -4
  78. data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
  79. data/lib/rubocop/cop/lint/ambiguous_operator.rb +4 -0
  80. data/lib/rubocop/cop/lint/constant_resolution.rb +1 -1
  81. data/lib/rubocop/cop/lint/debugger.rb +11 -27
  82. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +62 -112
  83. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +1 -1
  84. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +122 -0
  85. data/lib/rubocop/cop/lint/duplicate_methods.rb +2 -2
  86. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +1 -3
  87. data/lib/rubocop/cop/lint/else_layout.rb +3 -7
  88. data/lib/rubocop/cop/lint/empty_block.rb +1 -1
  89. data/lib/rubocop/cop/lint/empty_conditional_body.rb +4 -2
  90. data/lib/rubocop/cop/lint/empty_interpolation.rb +1 -1
  91. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +14 -7
  92. data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +15 -17
  93. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
  94. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -1
  95. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +46 -4
  96. data/lib/rubocop/cop/lint/missing_super.rb +31 -2
  97. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -0
  98. data/lib/rubocop/cop/lint/nested_method_definition.rb +4 -9
  99. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +2 -0
  100. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +6 -10
  101. data/lib/rubocop/cop/lint/percent_string_array.rb +1 -1
  102. data/lib/rubocop/cop/lint/percent_symbol_array.rb +1 -1
  103. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +11 -5
  104. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +5 -5
  105. data/lib/rubocop/cop/lint/redundant_require_statement.rb +12 -2
  106. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +1 -1
  107. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +35 -15
  108. data/lib/rubocop/cop/lint/redundant_with_index.rb +1 -1
  109. data/lib/rubocop/cop/lint/redundant_with_object.rb +1 -1
  110. data/lib/rubocop/cop/lint/refinement_import_methods.rb +2 -1
  111. data/lib/rubocop/cop/lint/rescue_type.rb +3 -3
  112. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +1 -1
  113. data/lib/rubocop/cop/lint/script_permission.rb +1 -1
  114. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -1
  115. data/lib/rubocop/cop/lint/syntax.rb +4 -0
  116. data/lib/rubocop/cop/lint/to_enum_arguments.rb +13 -3
  117. data/lib/rubocop/cop/lint/unreachable_loop.rb +3 -3
  118. data/lib/rubocop/cop/lint/useless_access_modifier.rb +10 -7
  119. data/lib/rubocop/cop/lint/useless_method_definition.rb +12 -4
  120. data/lib/rubocop/cop/lint/useless_rescue.rb +20 -2
  121. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +9 -1
  122. data/lib/rubocop/cop/lint/useless_times.rb +1 -1
  123. data/lib/rubocop/cop/lint/void.rb +24 -11
  124. data/lib/rubocop/cop/metrics/block_length.rb +1 -1
  125. data/lib/rubocop/cop/metrics/block_nesting.rb +2 -2
  126. data/lib/rubocop/cop/metrics/class_length.rb +1 -0
  127. data/lib/rubocop/cop/metrics/collection_literal_length.rb +76 -0
  128. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
  129. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +2 -5
  130. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +3 -3
  131. data/lib/rubocop/cop/migration/department_name.rb +1 -1
  132. data/lib/rubocop/cop/mixin/alignment.rb +1 -1
  133. data/lib/rubocop/cop/mixin/allowed_methods.rb +3 -1
  134. data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -1
  135. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  136. data/lib/rubocop/cop/mixin/comments_help.rb +8 -6
  137. data/lib/rubocop/cop/mixin/documentation_comment.rb +1 -1
  138. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +1 -1
  139. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +56 -25
  140. data/lib/rubocop/cop/mixin/hash_transform_method.rb +3 -3
  141. data/lib/rubocop/cop/mixin/line_length_help.rb +3 -1
  142. data/lib/rubocop/cop/mixin/min_branches_count.rb +40 -0
  143. data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +0 -3
  144. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
  145. data/lib/rubocop/cop/mixin/range_help.rb +1 -6
  146. data/lib/rubocop/cop/mixin/statement_modifier.rb +3 -3
  147. data/lib/rubocop/cop/mixin/surrounding_space.rb +3 -3
  148. data/lib/rubocop/cop/mixin/trailing_comma.rb +2 -2
  149. data/lib/rubocop/cop/naming/ascii_identifiers.rb +1 -1
  150. data/lib/rubocop/cop/naming/block_forwarding.rb +4 -0
  151. data/lib/rubocop/cop/naming/class_and_module_camel_case.rb +1 -1
  152. data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +1 -1
  153. data/lib/rubocop/cop/naming/inclusive_language.rb +23 -4
  154. data/lib/rubocop/cop/naming/method_name.rb +3 -3
  155. data/lib/rubocop/cop/naming/predicate_name.rb +1 -1
  156. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +1 -1
  157. data/lib/rubocop/cop/registry.rb +15 -8
  158. data/lib/rubocop/cop/style/access_modifier_declarations.rb +26 -11
  159. data/lib/rubocop/cop/style/accessor_grouping.rb +39 -17
  160. data/lib/rubocop/cop/style/arguments_forwarding.rb +4 -3
  161. data/lib/rubocop/cop/style/array_intersect.rb +1 -1
  162. data/lib/rubocop/cop/style/ascii_comments.rb +1 -1
  163. data/lib/rubocop/cop/style/bisected_attr_accessor.rb +1 -1
  164. data/lib/rubocop/cop/style/block_comments.rb +1 -1
  165. data/lib/rubocop/cop/style/block_delimiters.rb +17 -2
  166. data/lib/rubocop/cop/style/case_like_if.rb +20 -3
  167. data/lib/rubocop/cop/style/class_and_module_children.rb +4 -11
  168. data/lib/rubocop/cop/style/class_equality_comparison.rb +42 -9
  169. data/lib/rubocop/cop/style/collection_compact.rb +4 -1
  170. data/lib/rubocop/cop/style/command_literal.rb +1 -1
  171. data/lib/rubocop/cop/style/comment_annotation.rb +1 -1
  172. data/lib/rubocop/cop/style/commented_keyword.rb +2 -2
  173. data/lib/rubocop/cop/style/comparable_clamp.rb +125 -0
  174. data/lib/rubocop/cop/style/concat_array_literals.rb +10 -2
  175. data/lib/rubocop/cop/style/conditional_assignment.rb +6 -12
  176. data/lib/rubocop/cop/style/copyright.rb +1 -1
  177. data/lib/rubocop/cop/style/data_inheritance.rb +75 -0
  178. data/lib/rubocop/cop/style/dir_empty.rb +60 -0
  179. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +2 -2
  180. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +2 -2
  181. data/lib/rubocop/cop/style/documentation.rb +11 -5
  182. data/lib/rubocop/cop/style/documentation_method.rb +10 -4
  183. data/lib/rubocop/cop/style/double_negation.rb +2 -2
  184. data/lib/rubocop/cop/style/each_with_object.rb +1 -1
  185. data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
  186. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
  187. data/lib/rubocop/cop/style/eval_with_location.rb +4 -4
  188. data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
  189. data/lib/rubocop/cop/style/file_empty.rb +71 -0
  190. data/lib/rubocop/cop/style/file_read.rb +1 -1
  191. data/lib/rubocop/cop/style/file_write.rb +1 -1
  192. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
  193. data/lib/rubocop/cop/style/guard_clause.rb +1 -1
  194. data/lib/rubocop/cop/style/hash_except.rb +4 -4
  195. data/lib/rubocop/cop/style/hash_like_case.rb +3 -9
  196. data/lib/rubocop/cop/style/hash_syntax.rb +5 -2
  197. data/lib/rubocop/cop/style/if_unless_modifier.rb +108 -15
  198. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +2 -0
  199. data/lib/rubocop/cop/style/infinite_loop.rb +2 -5
  200. data/lib/rubocop/cop/style/inverse_methods.rb +5 -5
  201. data/lib/rubocop/cop/style/invertible_unless_condition.rb +114 -0
  202. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +2 -2
  203. data/lib/rubocop/cop/style/map_to_hash.rb +4 -1
  204. data/lib/rubocop/cop/style/map_to_set.rb +4 -1
  205. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +14 -12
  206. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +44 -37
  207. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -0
  208. data/lib/rubocop/cop/style/min_max.rb +3 -3
  209. data/lib/rubocop/cop/style/min_max_comparison.rb +11 -1
  210. data/lib/rubocop/cop/style/mixin_grouping.rb +4 -4
  211. data/lib/rubocop/cop/style/multiline_if_modifier.rb +0 -4
  212. data/lib/rubocop/cop/style/multiline_memoization.rb +2 -2
  213. data/lib/rubocop/cop/style/multiline_method_signature.rb +7 -4
  214. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +18 -3
  215. data/lib/rubocop/cop/style/negated_if_else_condition.rb +13 -12
  216. data/lib/rubocop/cop/style/nil_lambda.rb +2 -2
  217. data/lib/rubocop/cop/style/numbered_parameters_limit.rb +11 -3
  218. data/lib/rubocop/cop/style/one_line_conditional.rb +3 -6
  219. data/lib/rubocop/cop/style/operator_method_call.rb +2 -2
  220. data/lib/rubocop/cop/style/parallel_assignment.rb +29 -19
  221. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +2 -3
  222. data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
  223. data/lib/rubocop/cop/style/redundant_condition.rb +18 -3
  224. data/lib/rubocop/cop/style/redundant_conditional.rb +0 -4
  225. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +16 -10
  226. data/lib/rubocop/cop/style/redundant_fetch_block.rb +6 -4
  227. data/lib/rubocop/cop/style/redundant_heredoc_delimiter_quotes.rb +58 -0
  228. data/lib/rubocop/cop/style/redundant_interpolation.rb +2 -2
  229. data/lib/rubocop/cop/style/redundant_line_continuation.rb +179 -0
  230. data/lib/rubocop/cop/style/redundant_parentheses.rb +2 -2
  231. data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -1
  232. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +7 -8
  233. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +11 -4
  234. data/lib/rubocop/cop/style/redundant_sort.rb +3 -3
  235. data/lib/rubocop/cop/style/redundant_string_escape.rb +3 -4
  236. data/lib/rubocop/cop/style/require_order.rb +3 -12
  237. data/lib/rubocop/cop/style/rescue_standard_error.rb +2 -2
  238. data/lib/rubocop/cop/style/safe_navigation.rb +2 -2
  239. data/lib/rubocop/cop/style/self_assignment.rb +2 -2
  240. data/lib/rubocop/cop/style/semicolon.rb +24 -2
  241. data/lib/rubocop/cop/style/slicing_with_range.rb +1 -1
  242. data/lib/rubocop/cop/style/sole_nested_conditional.rb +3 -3
  243. data/lib/rubocop/cop/style/stderr_puts.rb +1 -1
  244. data/lib/rubocop/cop/style/struct_inheritance.rb +1 -1
  245. data/lib/rubocop/cop/style/symbol_array.rb +1 -1
  246. data/lib/rubocop/cop/style/trailing_body_on_class.rb +1 -0
  247. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +1 -1
  248. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  249. data/lib/rubocop/cop/style/unless_logical_operators.rb +1 -0
  250. data/lib/rubocop/cop/style/unpack_first.rb +3 -3
  251. data/lib/rubocop/cop/style/word_array.rb +18 -6
  252. data/lib/rubocop/cop/style/yoda_condition.rb +13 -6
  253. data/lib/rubocop/cop/style/yoda_expression.rb +11 -2
  254. data/lib/rubocop/cop/style/zero_length_predicate.rb +9 -5
  255. data/lib/rubocop/cop/team.rb +30 -22
  256. data/lib/rubocop/cop/util.rb +13 -4
  257. data/lib/rubocop/cop/variable_force/scope.rb +3 -3
  258. data/lib/rubocop/cop/variable_force/variable.rb +5 -3
  259. data/lib/rubocop/cop/variable_force/variable_table.rb +3 -1
  260. data/lib/rubocop/cop/variable_force.rb +1 -1
  261. data/lib/rubocop/cops_documentation_generator.rb +10 -3
  262. data/lib/rubocop/directive_comment.rb +3 -3
  263. data/lib/rubocop/ext/comment.rb +18 -0
  264. data/lib/rubocop/ext/regexp_node.rb +1 -1
  265. data/lib/rubocop/ext/regexp_parser.rb +1 -1
  266. data/lib/rubocop/formatter/junit_formatter.rb +4 -1
  267. data/lib/rubocop/formatter/simple_text_formatter.rb +1 -1
  268. data/lib/rubocop/formatter.rb +0 -1
  269. data/lib/rubocop/options.rb +26 -2
  270. data/lib/rubocop/result_cache.rb +1 -1
  271. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  272. data/lib/rubocop/rspec/expect_offense.rb +6 -4
  273. data/lib/rubocop/rspec/shared_contexts.rb +4 -0
  274. data/lib/rubocop/rspec/support.rb +1 -0
  275. data/lib/rubocop/runner.rb +40 -4
  276. data/lib/rubocop/server/cache.rb +11 -4
  277. data/lib/rubocop/server/cli.rb +37 -18
  278. data/lib/rubocop/server/client_command/exec.rb +1 -1
  279. data/lib/rubocop/server/client_command/start.rb +6 -1
  280. data/lib/rubocop/server/core.rb +24 -9
  281. data/lib/rubocop/server/helper.rb +1 -1
  282. data/lib/rubocop/server/server_command/exec.rb +1 -1
  283. data/lib/rubocop/target_ruby.rb +1 -1
  284. data/lib/rubocop/version.rb +1 -1
  285. data/lib/rubocop.rb +12 -0
  286. metadata +21 -26
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Checks for redundant heredoc delimiter quotes.
7
+ #
8
+ # @example
9
+ #
10
+ # # bad
11
+ # do_something(<<~'EOS')
12
+ # no string interpolation style text
13
+ # EOS
14
+ #
15
+ # # good
16
+ # do_something(<<~EOS)
17
+ # no string interpolation style text
18
+ # EOS
19
+ #
20
+ # do_something(<<~'EOS')
21
+ # #{string_interpolation_style_text_not_evaluated}
22
+ # EOS
23
+ #
24
+ # do_something(<<~'EOS')
25
+ # Preserve \
26
+ # newlines
27
+ # EOS
28
+ #
29
+ class RedundantHeredocDelimiterQuotes < Base
30
+ include Heredoc
31
+ extend AutoCorrector
32
+
33
+ MSG = 'Remove the redundant heredoc delimiter quotes, use `%<replacement>s` instead.'
34
+ STRING_INTERPOLATION_OR_ESCAPED_CHARACTER_PATTERN = /#(\{|@|\$)|\\/.freeze
35
+
36
+ def on_heredoc(node)
37
+ return if need_heredoc_delimiter_quotes?(node)
38
+
39
+ replacement = "#{heredoc_type(node)}#{delimiter_string(node)}"
40
+
41
+ add_offense(node, message: format(MSG, replacement: replacement)) do |corrector|
42
+ corrector.replace(node, replacement)
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def need_heredoc_delimiter_quotes?(node)
49
+ heredoc_delimiter = node.source.delete(heredoc_type(node))
50
+ return true unless heredoc_delimiter.start_with?("'", '"')
51
+
52
+ node.loc.heredoc_end.source.strip.match?(/\W/) ||
53
+ node.loc.heredoc_body.source.match?(STRING_INTERPOLATION_OR_ESCAPED_CHARACTER_PATTERN)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -97,7 +97,7 @@ module RuboCop
97
97
  end
98
98
 
99
99
  def autocorrect_variable_interpolation(corrector, embedded_node, node)
100
- replacement = "#{embedded_node.loc.expression.source}.to_s"
100
+ replacement = "#{embedded_node.source}.to_s"
101
101
 
102
102
  corrector.replace(node, replacement)
103
103
  end
@@ -107,7 +107,7 @@ module RuboCop
107
107
 
108
108
  source = if require_parentheses?(embedded_var)
109
109
  receiver = range_between(
110
- embedded_var.loc.expression.begin_pos, embedded_var.loc.selector.end_pos
110
+ embedded_var.source_range.begin_pos, embedded_var.loc.selector.end_pos
111
111
  )
112
112
  arguments = embedded_var.arguments.map(&:source).join(', ')
113
113
 
@@ -0,0 +1,179 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Check for redundant line continuation.
7
+ #
8
+ # This cop marks a line continuation as redundant if removing the backslash
9
+ # does not result in a syntax error.
10
+ # However, a backslash at the end of a comment or
11
+ # for string concatenation is not redundant and is not considered an offense.
12
+ #
13
+ # @example
14
+ # # bad
15
+ # foo. \
16
+ # bar
17
+ # foo \
18
+ # &.bar \
19
+ # .baz
20
+ #
21
+ # # good
22
+ # foo.
23
+ # bar
24
+ # foo
25
+ # &.bar
26
+ # .baz
27
+ #
28
+ # # bad
29
+ # [foo, \
30
+ # bar]
31
+ # {foo: \
32
+ # bar}
33
+ #
34
+ # # good
35
+ # [foo,
36
+ # bar]
37
+ # {foo:
38
+ # bar}
39
+ #
40
+ # # bad
41
+ # foo(bar, \
42
+ # baz)
43
+ #
44
+ # # good
45
+ # foo(bar,
46
+ # baz)
47
+ #
48
+ # # also good - backslash in string concatenation is not redundant
49
+ # foo('bar' \
50
+ # 'baz')
51
+ #
52
+ # # also good - backslash at the end of a comment is not redundant
53
+ # foo(bar, # \
54
+ # baz)
55
+ #
56
+ # # also good - backslash at the line following the newline begins with a + or -,
57
+ # # it is not redundant
58
+ # 1 \
59
+ # + 2 \
60
+ # - 3
61
+ #
62
+ # # also good - backslash with newline between the method name and its arguments,
63
+ # # it is not redundant.
64
+ # some_method \
65
+ # (argument)
66
+ #
67
+ class RedundantLineContinuation < Base
68
+ include MatchRange
69
+ extend AutoCorrector
70
+
71
+ MSG = 'Redundant line continuation.'
72
+ ALLOWED_STRING_TOKENS = %i[tSTRING tSTRING_CONTENT].freeze
73
+
74
+ def on_new_investigation
75
+ return unless processed_source.ast
76
+
77
+ each_match_range(processed_source.ast.source_range, /(\\\n)/) do |range|
78
+ next if require_line_continuation?(range)
79
+ next unless redundant_line_continuation?(range)
80
+
81
+ add_offense(range) do |corrector|
82
+ corrector.remove_leading(range, 1)
83
+ end
84
+ end
85
+ end
86
+
87
+ private
88
+
89
+ def require_line_continuation?(range)
90
+ !ends_with_backslash_without_comment?(range.source_line) ||
91
+ string_concatenation?(range.source_line) ||
92
+ start_with_arithmetic_operator?(processed_source[range.line]) ||
93
+ inside_string_literal_or_method_with_argument?(range)
94
+ end
95
+
96
+ def ends_with_backslash_without_comment?(source_line)
97
+ source_line.gsub(/#.+/, '').end_with?('\\')
98
+ end
99
+
100
+ def string_concatenation?(source_line)
101
+ /["']\s*\\\z/.match?(source_line)
102
+ end
103
+
104
+ def inside_string_literal_or_method_with_argument?(range)
105
+ processed_source.tokens.each_cons(2).any? do |token, next_token|
106
+ inside_string_literal?(range, token) || method_with_argument?(token, next_token)
107
+ end
108
+ end
109
+
110
+ def redundant_line_continuation?(range)
111
+ return true unless (node = find_node_for_line(range.line))
112
+ return false if argument_newline?(node)
113
+
114
+ source = node.parent ? node.parent.source : node.source
115
+ parse(source.gsub(/\\\n/, "\n")).valid_syntax?
116
+ end
117
+
118
+ def inside_string_literal?(range, token)
119
+ ALLOWED_STRING_TOKENS.include?(token.type) && token.pos.overlaps?(range)
120
+ end
121
+
122
+ # A method call without parentheses such as the following cannot remove `\`:
123
+ #
124
+ # do_something \
125
+ # argument
126
+ def method_with_argument?(current_token, next_token)
127
+ current_token.type == :tIDENTIFIER && next_token.type == :tIDENTIFIER
128
+ end
129
+
130
+ def argument_newline?(node)
131
+ node = node.children.first if node.root? && node.begin_type?
132
+
133
+ if argument_is_method?(node)
134
+ argument_newline?(node.first_argument)
135
+ else
136
+ return false unless method_call_with_arguments?(node)
137
+
138
+ node.loc.selector.line != node.first_argument.loc.line
139
+ end
140
+ end
141
+
142
+ def find_node_for_line(line)
143
+ processed_source.ast.each_node do |node|
144
+ return node if same_line?(node, line)
145
+ end
146
+ end
147
+
148
+ def same_line?(node, line)
149
+ return unless (source_range = node.source_range)
150
+
151
+ if node.is_a?(AST::StrNode)
152
+ if node.heredoc?
153
+ (node.loc.heredoc_body.line..node.loc.heredoc_body.last_line).cover?(line)
154
+ else
155
+ (source_range.line..source_range.last_line).cover?(line)
156
+ end
157
+ else
158
+ source_range.line == line
159
+ end
160
+ end
161
+
162
+ def argument_is_method?(node)
163
+ return false unless node.send_type?
164
+ return false unless (first_argument = node.first_argument)
165
+
166
+ method_call_with_arguments?(first_argument)
167
+ end
168
+
169
+ def method_call_with_arguments?(node)
170
+ node.call_type? && !node.arguments.empty?
171
+ end
172
+
173
+ def start_with_arithmetic_operator?(source_line)
174
+ %r{\A\s*[+\-*/%]}.match?(source_line)
175
+ end
176
+ end
177
+ end
178
+ end
179
+ end
@@ -98,7 +98,7 @@ module RuboCop
98
98
  end
99
99
 
100
100
  def like_method_argument_parentheses?(node)
101
- node.send_type? && node.arguments.one? &&
101
+ node.send_type? && node.arguments.one? && !node.parenthesized? &&
102
102
  !node.arithmetic_operation? && node.first_argument.begin_type?
103
103
  end
104
104
 
@@ -153,7 +153,7 @@ module RuboCop
153
153
 
154
154
  return if node.send_type? && !method_call_with_redundant_parentheses?(node)
155
155
 
156
- offense(begin_node, 'an unary operation')
156
+ offense(begin_node, 'a unary operation')
157
157
  end
158
158
 
159
159
  def offense(node, msg)
@@ -93,7 +93,7 @@ module RuboCop
93
93
 
94
94
  return true if STRING_INTERPOLATION_REGEXP.match?(src)
95
95
 
96
- src.scan(/\\./).any? { |s| ESCAPED_NON_BACKSLASH.match?(s) }
96
+ src.scan(/\\./).any?(ESCAPED_NON_BACKSLASH)
97
97
  end
98
98
 
99
99
  def acceptable_capital_q?(node)
@@ -63,7 +63,7 @@ module RuboCop
63
63
  next if expr.type != :set || expr.expressions.size != 1
64
64
  next if expr.negative?
65
65
  next if %i[set posixclass nonposixclass].include?(expr.expressions.first.type)
66
- next if multiple_codepoins?(expr.expressions.first)
66
+ next if multiple_codepoints?(expr.expressions.first)
67
67
 
68
68
  yield expr
69
69
  end
@@ -74,13 +74,13 @@ module RuboCop
74
74
 
75
75
  non_redundant =
76
76
  whitespace_in_free_space_mode?(node, class_elem) ||
77
- backslash_b?(class_elem) || backslash_zero?(class_elem) ||
77
+ backslash_b?(class_elem) || octal_requiring_char_class?(class_elem) ||
78
78
  requires_escape_outside_char_class?(class_elem)
79
79
 
80
80
  !non_redundant
81
81
  end
82
82
 
83
- def multiple_codepoins?(expression)
83
+ def multiple_codepoints?(expression)
84
84
  expression.respond_to?(:codepoints) && expression.codepoints.count >= 2
85
85
  end
86
86
 
@@ -104,11 +104,10 @@ module RuboCop
104
104
  elem == '\b'
105
105
  end
106
106
 
107
- def backslash_zero?(elem)
108
- # See https://github.com/rubocop/rubocop/issues/11067 for details - in short "\0" != "0" -
109
- # the former means an Unicode code point `"\u0000"`, the latter a number character `"0"`.
110
- # Similarly "\032" means "\u001A". Other numbers starting with "\0" can also be mentioned.
111
- elem == '\0'
107
+ def octal_requiring_char_class?(elem)
108
+ # The octal escapes \1 to \7 only work inside a character class
109
+ # because they would be a backreference outside it.
110
+ elem.match?(/\A\\[1-7]\z/)
112
111
  end
113
112
 
114
113
  def requires_escape_outside_char_class?(elem)
@@ -74,11 +74,18 @@ module RuboCop
74
74
 
75
75
  def char_class_begins_or_ends_with_escaped_hyphen?(node, index)
76
76
  # The hyphen character is allowed to be escaped within a character class
77
- # but it's not necessry to escape hyphen if it's the first or last character
77
+ # but it's not necessary to escape hyphen if it's the first or last character
78
78
  # within the character class. This method checks if that's the case.
79
79
  # e.g. "[0-9\\-]" or "[\\-0-9]" would return true
80
- contents_range(node).source[index - 1] == '[' ||
81
- contents_range(node).source[index + 2] == ']'
80
+ content = contents_range(node).source
81
+
82
+ if content[index + 2] == ']'
83
+ true
84
+ elsif content[index - 1] == '['
85
+ index < 2 || content[index - 2] != '\\'
86
+ else
87
+ false
88
+ end
82
89
  end
83
90
 
84
91
  def delimiter?(node, char)
@@ -100,7 +107,7 @@ module RuboCop
100
107
  end
101
108
  end
102
109
  # Please remove this `else` branch when support for regexp_parser 1.8 will be dropped.
103
- # It's for compatibility with regexp_arser 1.8 and will never be maintained.
110
+ # It's for compatibility with regexp_parser 1.8 and will never be maintained.
104
111
  else
105
112
  def each_escape(node)
106
113
  node.parsed_tree&.traverse&.reduce(0) do |char_class_depth, (event, expr)|
@@ -129,13 +129,13 @@ module RuboCop
129
129
  end
130
130
 
131
131
  def offense_range(sort_node, node)
132
- range_between(sort_node.loc.selector.begin_pos, node.loc.expression.end_pos)
132
+ range_between(sort_node.loc.selector.begin_pos, node.source_range.end_pos)
133
133
  end
134
134
 
135
135
  def message(node, sorter, accessor)
136
136
  accessor_source = range_between(
137
137
  node.loc.selector.begin_pos,
138
- node.loc.expression.end_pos
138
+ node.source_range.end_pos
139
139
  ).source
140
140
 
141
141
  format(MSG,
@@ -146,7 +146,7 @@ module RuboCop
146
146
 
147
147
  def autocorrect(corrector, node, sort_node, sorter, accessor)
148
148
  # Remove accessor, e.g. `first` or `[-1]`.
149
- corrector.remove(range_between(accessor_start(node), node.loc.expression.end_pos))
149
+ corrector.remove(range_between(accessor_start(node), node.source_range.end_pos))
150
150
  # Replace "sort" or "sort_by" with the appropriate min/max method.
151
151
  corrector.replace(sort_node.loc.selector, suggestion(sorter, accessor, arg_value(node)))
152
152
  # Replace to avoid syntax errors when followed by a logical operator.
@@ -36,7 +36,6 @@ module RuboCop
36
36
  # STR
37
37
  class RedundantStringEscape < Base
38
38
  include MatchRange
39
- include RangeHelp
40
39
  extend AutoCorrector
41
40
 
42
41
  MSG = 'Redundant escape of %<char>s inside string literal.'
@@ -64,10 +63,10 @@ module RuboCop
64
63
  def str_contents_range(node)
65
64
  if heredoc?(node)
66
65
  node.loc.heredoc_body
66
+ elsif node.str_type?
67
+ node.source_range
67
68
  elsif begin_loc_present?(node)
68
69
  contents_range(node)
69
- else
70
- node.loc.expression
71
70
  end
72
71
  end
73
72
 
@@ -139,7 +138,7 @@ module RuboCop
139
138
 
140
139
  def heredoc_with_disabled_interpolation?(node)
141
140
  if heredoc?(node)
142
- node.loc.expression.source.end_with?("'")
141
+ node.source.end_with?("'")
143
142
  elsif node.parent&.dstr_type?
144
143
  heredoc_with_disabled_interpolation?(node.parent)
145
144
  else
@@ -88,10 +88,9 @@ module RuboCop
88
88
  return unless previous_older_sibling
89
89
 
90
90
  add_offense(node, message: format(MSG, name: node.method_name)) do |corrector|
91
- swap(
91
+ corrector.swap(
92
92
  range_with_comments_and_lines(previous_older_sibling),
93
- range_with_comments_and_lines(node.parent.if_type? ? node.parent : node),
94
- corrector: corrector
93
+ range_with_comments_and_lines(node.parent.if_type? ? node.parent : node)
95
94
  )
96
95
  end
97
96
  end
@@ -126,15 +125,7 @@ module RuboCop
126
125
  end
127
126
 
128
127
  def in_same_section?(node1, node2)
129
- !node1.location.expression.with(
130
- end_pos: node2.location.expression.end_pos
131
- ).source.include?("\n\n")
132
- end
133
-
134
- def swap(range1, range2, corrector:)
135
- inserted = range2.source
136
- corrector.insert_before(range1, inserted)
137
- corrector.remove(range2)
128
+ !node1.source_range.with(end_pos: node2.source_range.end_pos).source.include?("\n\n")
138
129
  end
139
130
  end
140
131
  end
@@ -105,11 +105,11 @@ module RuboCop
105
105
  private
106
106
 
107
107
  def offense_for_implicit_enforced_style(node, error)
108
- range = node.loc.keyword.join(error.loc.expression)
108
+ range = node.loc.keyword.join(error.source_range)
109
109
 
110
110
  add_offense(range, message: MSG_IMPLICIT) do |corrector|
111
111
  error = rescue_standard_error?(node)
112
- range = range_between(node.loc.keyword.end_pos, error.loc.expression.end_pos)
112
+ range = range_between(node.loc.keyword.end_pos, error.source_range.end_pos)
113
113
 
114
114
  corrector.remove(range)
115
115
  end
@@ -297,11 +297,11 @@ module RuboCop
297
297
  end
298
298
 
299
299
  def begin_range(node, method_call)
300
- range_between(node.loc.expression.begin_pos, method_call.loc.expression.begin_pos)
300
+ range_between(node.source_range.begin_pos, method_call.source_range.begin_pos)
301
301
  end
302
302
 
303
303
  def end_range(node, method_call)
304
- range_between(method_call.loc.expression.end_pos, node.loc.expression.end_pos)
304
+ range_between(method_call.source_range.end_pos, node.source_range.end_pos)
305
305
  end
306
306
 
307
307
  def add_safe_nav_to_all_methods_in_chain(corrector,
@@ -42,7 +42,7 @@ module RuboCop
42
42
 
43
43
  if rhs.send_type?
44
44
  check_send_node(node, rhs, var_name, var_type)
45
- elsif %i[and or].include?(rhs.type)
45
+ elsif rhs.operator_keyword?
46
46
  check_boolean_node(node, rhs, var_name, var_type)
47
47
  end
48
48
  end
@@ -76,7 +76,7 @@ module RuboCop
76
76
 
77
77
  if rhs.send_type?
78
78
  autocorrect_send_node(corrector, node, rhs)
79
- elsif %i[and or].include?(rhs.type)
79
+ elsif rhs.operator_keyword?
80
80
  autocorrect_boolean_node(corrector, node, rhs)
81
81
  end
82
82
  end
@@ -72,8 +72,10 @@ module RuboCop
72
72
 
73
73
  def each_semicolon
74
74
  tokens_for_lines.each do |line, tokens|
75
- yield line, tokens.last.column, tokens[-2] if tokens.last.semicolon?
76
- yield line, tokens.first.column if tokens.first.semicolon?
75
+ semicolon_pos = semicolon_position(tokens)
76
+ after_expr_pos = semicolon_pos == -1 ? -2 : semicolon_pos
77
+
78
+ yield line, tokens[semicolon_pos].column, tokens[after_expr_pos] if semicolon_pos
77
79
  end
78
80
  end
79
81
 
@@ -81,6 +83,26 @@ module RuboCop
81
83
  processed_source.tokens.group_by(&:line)
82
84
  end
83
85
 
86
+ def semicolon_position(tokens)
87
+ if tokens.last.semicolon?
88
+ -1
89
+ elsif tokens.first.semicolon?
90
+ 0
91
+ elsif exist_semicolon_before_right_curly_brace?(tokens)
92
+ -3
93
+ elsif exist_semicolon_after_left_curly_brace?(tokens)
94
+ 2
95
+ end
96
+ end
97
+
98
+ def exist_semicolon_before_right_curly_brace?(tokens)
99
+ tokens[-2]&.right_curly_brace? && tokens[-3]&.semicolon?
100
+ end
101
+
102
+ def exist_semicolon_after_left_curly_brace?(tokens)
103
+ tokens[1]&.left_curly_brace? && tokens[2]&.semicolon?
104
+ end
105
+
84
106
  def register_semicolon(line, column, after_expression, token_before_semicolon = nil)
85
107
  range = source_range(processed_source.buffer, line, column)
86
108
 
@@ -8,7 +8,7 @@ module RuboCop
8
8
  #
9
9
  # @safety
10
10
  # This cop is unsafe because `x..-1` and `x..` are only guaranteed to
11
- # be equivalent for `Array#[]`, and the cop cannot determine what class
11
+ # be equivalent for `Array#[]`, `String#[]`, and the cop cannot determine what class
12
12
  # the receiver is.
13
13
  #
14
14
  # For example:
@@ -167,7 +167,7 @@ module RuboCop
167
167
  corrector.insert_before(condition,
168
168
  "#{'!' if node.unless?}#{replace_condition(node.condition)} && ")
169
169
 
170
- corrector.remove(node.condition.loc.expression)
170
+ corrector.remove(node.condition)
171
171
  corrector.remove(range_with_surrounding_space(node.loc.keyword, newlines: false))
172
172
  corrector.replace(if_branch.loc.keyword, 'if')
173
173
  end
@@ -187,7 +187,7 @@ module RuboCop
187
187
  return if end_pos > begin_pos
188
188
 
189
189
  corrector.replace(range_between(end_pos, begin_pos), '(')
190
- corrector.insert_after(condition.last_argument.source_range, ')')
190
+ corrector.insert_after(condition.last_argument, ')')
191
191
  end
192
192
 
193
193
  def insert_bang(corrector, node, is_modify_form)
@@ -240,7 +240,7 @@ module RuboCop
240
240
  end
241
241
 
242
242
  def outer_condition_modify_form?(node, if_branch)
243
- node.condition.loc.expression.begin_pos > if_branch.condition.loc.expression.begin_pos
243
+ node.condition.source_range.begin_pos > if_branch.condition.source_range.begin_pos
244
244
  end
245
245
  end
246
246
  end
@@ -49,7 +49,7 @@ module RuboCop
49
49
  end
50
50
 
51
51
  def stderr_puts_range(send)
52
- range_between(send.loc.expression.begin_pos, send.loc.selector.end_pos)
52
+ range_between(send.source_range.begin_pos, send.loc.selector.end_pos)
53
53
  end
54
54
  end
55
55
  end
@@ -55,7 +55,7 @@ module RuboCop
55
55
  elsif (class_node = parent.parent).body.nil?
56
56
  corrector.remove(range_for_empty_class_body(class_node, parent))
57
57
  else
58
- corrector.insert_after(parent.loc.expression, ' do')
58
+ corrector.insert_after(parent, ' do')
59
59
  end
60
60
  end
61
61
 
@@ -60,7 +60,7 @@ module RuboCop
60
60
  def symbols_contain_spaces?(node)
61
61
  node.children.any? do |sym|
62
62
  content, = *sym
63
- / /.match?(content)
63
+ content.to_s.include?(' ')
64
64
  end
65
65
  end
66
66
 
@@ -34,6 +34,7 @@ module RuboCop
34
34
  )
35
35
  end
36
36
  end
37
+ alias on_sclass on_class
37
38
  end
38
39
  end
39
40
  end
@@ -144,7 +144,7 @@ module RuboCop
144
144
  end
145
145
 
146
146
  def range_for_parentheses(offense, left)
147
- range_between(offense.source_range.begin_pos - 1, left.loc.expression.end_pos - 1)
147
+ range_between(offense.source_range.begin_pos - 1, left.source_range.end_pos - 1)
148
148
  end
149
149
  end
150
150
  end
@@ -238,7 +238,7 @@ module RuboCop
238
238
 
239
239
  indent = ' ' * node.loc.column
240
240
  corrector.replace(
241
- node.source_range,
241
+ node,
242
242
  ['class << self',
243
243
  "#{indent} #{accessor(kind, node.method_name)}",
244
244
  "#{indent}end"].join("\n")
@@ -8,6 +8,7 @@ module RuboCop
8
8
  # to read and understand.
9
9
  #
10
10
  # This cop supports two styles:
11
+ #
11
12
  # - `forbid_mixed_logical_operators` (default)
12
13
  # - `forbid_logical_operators`
13
14
  #
@@ -52,9 +52,9 @@ module RuboCop
52
52
  private
53
53
 
54
54
  def first_element_range(node, unpack_call)
55
- Parser::Source::Range.new(node.loc.expression.source_buffer,
56
- unpack_call.loc.expression.end_pos,
57
- node.loc.expression.end_pos)
55
+ Parser::Source::Range.new(node.source_range.source_buffer,
56
+ unpack_call.source_range.end_pos,
57
+ node.source_range.end_pos)
58
58
  end
59
59
  end
60
60
  end