rubocop 1.39.0 → 1.57.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (448) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +6 -4
  4. data/config/default.yml +306 -54
  5. data/config/obsoletion.yml +5 -0
  6. data/exe/rubocop +1 -1
  7. data/lib/rubocop/cli/command/auto_generate_config.rb +7 -0
  8. data/lib/rubocop/cli/command/execute_runner.rb +7 -2
  9. data/lib/rubocop/cli/command/lsp.rb +19 -0
  10. data/lib/rubocop/cli.rb +59 -10
  11. data/lib/rubocop/comment_config.rb +24 -0
  12. data/lib/rubocop/config.rb +46 -18
  13. data/lib/rubocop/config_finder.rb +2 -2
  14. data/lib/rubocop/config_loader.rb +34 -28
  15. data/lib/rubocop/config_loader_resolver.rb +6 -2
  16. data/lib/rubocop/config_obsoletion/parameter_rule.rb +9 -1
  17. data/lib/rubocop/config_obsoletion.rb +2 -2
  18. data/lib/rubocop/config_validator.rb +1 -1
  19. data/lib/rubocop/cop/autocorrect_logic.rb +31 -13
  20. data/lib/rubocop/cop/badge.rb +9 -4
  21. data/lib/rubocop/cop/base.rb +116 -84
  22. data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -0
  23. data/lib/rubocop/cop/bundler/duplicated_group.rb +127 -0
  24. data/lib/rubocop/cop/bundler/gem_comment.rb +2 -2
  25. data/lib/rubocop/cop/bundler/gem_version.rb +2 -2
  26. data/lib/rubocop/cop/bundler/ordered_gems.rb +9 -1
  27. data/lib/rubocop/cop/commissioner.rb +16 -5
  28. data/lib/rubocop/cop/cop.rb +53 -33
  29. data/lib/rubocop/cop/corrector.rb +31 -11
  30. data/lib/rubocop/cop/correctors/alignment_corrector.rb +3 -3
  31. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +3 -3
  32. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +3 -3
  33. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +7 -4
  34. data/lib/rubocop/cop/correctors/line_break_corrector.rb +1 -1
  35. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +23 -7
  36. data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +2 -7
  37. data/lib/rubocop/cop/correctors/parentheses_corrector.rb +1 -1
  38. data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
  39. data/lib/rubocop/cop/gemspec/dependency_version.rb +19 -21
  40. data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +1 -1
  41. data/lib/rubocop/cop/gemspec/development_dependencies.rb +107 -0
  42. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +9 -1
  43. data/lib/rubocop/cop/generator/require_file_injector.rb +1 -1
  44. data/lib/rubocop/cop/internal_affairs/cop_description.rb +38 -12
  45. data/lib/rubocop/cop/internal_affairs/example_description.rb +42 -21
  46. data/lib/rubocop/cop/internal_affairs/example_heredoc_delimiter.rb +3 -3
  47. data/lib/rubocop/cop/internal_affairs/inherit_deprecated_cop_class.rb +1 -1
  48. data/lib/rubocop/cop/internal_affairs/lambda_or_proc.rb +46 -0
  49. data/lib/rubocop/cop/internal_affairs/location_expression.rb +37 -0
  50. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +3 -1
  51. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +6 -6
  52. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +1 -1
  53. data/lib/rubocop/cop/internal_affairs/processed_source_buffer_name.rb +42 -0
  54. data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +11 -3
  55. data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +1 -1
  56. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +1 -1
  57. data/lib/rubocop/cop/internal_affairs/redundant_method_dispatch_node.rb +11 -2
  58. data/lib/rubocop/cop/internal_affairs/redundant_source_range.rb +66 -0
  59. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +2 -0
  60. data/lib/rubocop/cop/internal_affairs.rb +4 -0
  61. data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
  62. data/lib/rubocop/cop/layout/block_end_newline.rb +7 -15
  63. data/lib/rubocop/cop/layout/class_structure.rb +44 -27
  64. data/lib/rubocop/cop/layout/closing_heredoc_indentation.rb +2 -3
  65. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +2 -6
  66. data/lib/rubocop/cop/layout/comment_indentation.rb +3 -1
  67. data/lib/rubocop/cop/layout/dot_position.rb +1 -5
  68. data/lib/rubocop/cop/layout/empty_comment.rb +3 -3
  69. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +42 -9
  70. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +28 -5
  71. data/lib/rubocop/cop/layout/empty_lines.rb +3 -1
  72. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +2 -0
  73. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +2 -0
  74. data/lib/rubocop/cop/layout/end_alignment.rb +9 -1
  75. data/lib/rubocop/cop/layout/extra_spacing.rb +15 -6
  76. data/lib/rubocop/cop/layout/first_argument_indentation.rb +8 -3
  77. data/lib/rubocop/cop/layout/first_array_element_line_break.rb +35 -8
  78. data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +36 -1
  79. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +57 -8
  80. data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +52 -19
  81. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +10 -4
  82. data/lib/rubocop/cop/layout/heredoc_indentation.rb +11 -11
  83. data/lib/rubocop/cop/layout/indentation_style.rb +8 -3
  84. data/lib/rubocop/cop/layout/indentation_width.rb +3 -3
  85. data/lib/rubocop/cop/layout/initial_indentation.rb +1 -1
  86. data/lib/rubocop/cop/layout/leading_comment_space.rb +2 -2
  87. data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +21 -10
  88. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +19 -9
  89. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -0
  90. data/lib/rubocop/cop/layout/line_length.rb +2 -0
  91. data/lib/rubocop/cop/layout/multiline_array_line_breaks.rb +31 -1
  92. data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -1
  93. data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +29 -1
  94. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +35 -1
  95. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +18 -3
  96. data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +33 -1
  97. data/lib/rubocop/cop/layout/redundant_line_break.rb +22 -13
  98. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +2 -2
  99. data/lib/rubocop/cop/layout/space_after_comma.rb +9 -1
  100. data/lib/rubocop/cop/layout/space_after_not.rb +1 -1
  101. data/lib/rubocop/cop/layout/space_around_keyword.rb +2 -2
  102. data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +2 -2
  103. data/lib/rubocop/cop/layout/space_around_operators.rb +4 -2
  104. data/lib/rubocop/cop/layout/space_before_first_arg.rb +1 -1
  105. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +2 -2
  106. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +11 -13
  107. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +3 -1
  108. data/lib/rubocop/cop/layout/space_inside_parens.rb +3 -3
  109. data/lib/rubocop/cop/layout/space_inside_percent_literal_delimiters.rb +1 -1
  110. data/lib/rubocop/cop/layout/space_inside_range_literal.rb +1 -1
  111. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +4 -4
  112. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +5 -4
  113. data/lib/rubocop/cop/layout/trailing_empty_lines.rb +6 -1
  114. data/lib/rubocop/cop/layout/trailing_whitespace.rb +12 -5
  115. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +14 -2
  116. data/lib/rubocop/cop/lint/ambiguous_operator.rb +4 -0
  117. data/lib/rubocop/cop/lint/assignment_in_condition.rb +11 -1
  118. data/lib/rubocop/cop/lint/constant_resolution.rb +5 -1
  119. data/lib/rubocop/cop/lint/debugger.rb +23 -24
  120. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +62 -112
  121. data/lib/rubocop/cop/lint/deprecated_constants.rb +8 -1
  122. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +1 -1
  123. data/lib/rubocop/cop/lint/duplicate_branch.rb +0 -2
  124. data/lib/rubocop/cop/lint/duplicate_hash_key.rb +2 -1
  125. data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +122 -0
  126. data/lib/rubocop/cop/lint/duplicate_methods.rb +20 -9
  127. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +47 -22
  128. data/lib/rubocop/cop/lint/else_layout.rb +3 -7
  129. data/lib/rubocop/cop/lint/empty_block.rb +3 -7
  130. data/lib/rubocop/cop/lint/empty_conditional_body.rb +5 -3
  131. data/lib/rubocop/cop/lint/empty_interpolation.rb +1 -1
  132. data/lib/rubocop/cop/lint/erb_new_arguments.rb +3 -4
  133. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +14 -7
  134. data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +16 -18
  135. data/lib/rubocop/cop/lint/identity_comparison.rb +0 -1
  136. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
  137. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -3
  138. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -1
  139. data/lib/rubocop/cop/lint/inherit_exception.rb +9 -0
  140. data/lib/rubocop/cop/lint/interpolation_check.rb +4 -3
  141. data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
  142. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +47 -5
  143. data/lib/rubocop/cop/lint/missing_super.rb +63 -5
  144. data/lib/rubocop/cop/lint/mixed_case_range.rb +111 -0
  145. data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -0
  146. data/lib/rubocop/cop/lint/nested_method_definition.rb +4 -9
  147. data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +20 -12
  148. data/lib/rubocop/cop/lint/number_conversion.rb +5 -0
  149. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +2 -2
  150. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +2 -0
  151. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +0 -1
  152. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +16 -1
  153. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +5 -0
  154. data/lib/rubocop/cop/lint/percent_string_array.rb +1 -1
  155. data/lib/rubocop/cop/lint/percent_symbol_array.rb +1 -1
  156. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +26 -8
  157. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +6 -6
  158. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +130 -0
  159. data/lib/rubocop/cop/lint/redundant_require_statement.rb +21 -2
  160. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +20 -4
  161. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +1 -1
  162. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +35 -15
  163. data/lib/rubocop/cop/lint/redundant_with_index.rb +1 -1
  164. data/lib/rubocop/cop/lint/redundant_with_object.rb +1 -1
  165. data/lib/rubocop/cop/lint/refinement_import_methods.rb +2 -1
  166. data/lib/rubocop/cop/lint/regexp_as_condition.rb +6 -0
  167. data/lib/rubocop/cop/lint/require_parentheses.rb +3 -1
  168. data/lib/rubocop/cop/lint/rescue_type.rb +3 -3
  169. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +21 -16
  170. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +1 -1
  171. data/lib/rubocop/cop/lint/script_permission.rb +1 -1
  172. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +6 -6
  173. data/lib/rubocop/cop/lint/shadowed_exception.rb +6 -12
  174. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +11 -4
  175. data/lib/rubocop/cop/lint/struct_new_override.rb +12 -12
  176. data/lib/rubocop/cop/lint/suppressed_exception.rb +2 -2
  177. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  178. data/lib/rubocop/cop/lint/syntax.rb +4 -0
  179. data/lib/rubocop/cop/lint/to_enum_arguments.rb +18 -6
  180. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +23 -9
  181. data/lib/rubocop/cop/lint/unreachable_loop.rb +3 -3
  182. data/lib/rubocop/cop/lint/unused_method_argument.rb +2 -1
  183. data/lib/rubocop/cop/lint/useless_access_modifier.rb +10 -7
  184. data/lib/rubocop/cop/lint/useless_assignment.rb +94 -10
  185. data/lib/rubocop/cop/lint/useless_method_definition.rb +12 -4
  186. data/lib/rubocop/cop/lint/useless_rescue.rb +89 -0
  187. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +14 -4
  188. data/lib/rubocop/cop/lint/useless_times.rb +1 -1
  189. data/lib/rubocop/cop/lint/void.rb +84 -21
  190. data/lib/rubocop/cop/metrics/block_length.rb +11 -6
  191. data/lib/rubocop/cop/metrics/block_nesting.rb +2 -2
  192. data/lib/rubocop/cop/metrics/class_length.rb +12 -6
  193. data/lib/rubocop/cop/metrics/collection_literal_length.rb +76 -0
  194. data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
  195. data/lib/rubocop/cop/metrics/method_length.rb +10 -5
  196. data/lib/rubocop/cop/metrics/module_length.rb +10 -5
  197. data/lib/rubocop/cop/metrics/parameter_lists.rb +27 -0
  198. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
  199. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -8
  200. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +39 -8
  201. data/lib/rubocop/cop/migration/department_name.rb +3 -3
  202. data/lib/rubocop/cop/mixin/alignment.rb +2 -2
  203. data/lib/rubocop/cop/mixin/allowed_identifiers.rb +2 -2
  204. data/lib/rubocop/cop/mixin/allowed_methods.rb +3 -1
  205. data/lib/rubocop/cop/mixin/allowed_receivers.rb +34 -0
  206. data/lib/rubocop/cop/mixin/annotation_comment.rb +14 -7
  207. data/lib/rubocop/cop/mixin/code_length.rb +1 -1
  208. data/lib/rubocop/cop/mixin/comments_help.rb +13 -7
  209. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +21 -9
  210. data/lib/rubocop/cop/mixin/def_node.rb +1 -1
  211. data/lib/rubocop/cop/mixin/documentation_comment.rb +1 -1
  212. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -1
  213. data/lib/rubocop/cop/mixin/first_element_line_break.rb +11 -7
  214. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +1 -1
  215. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +75 -13
  216. data/lib/rubocop/cop/mixin/hash_transform_method.rb +3 -3
  217. data/lib/rubocop/cop/mixin/heredoc.rb +6 -2
  218. data/lib/rubocop/cop/mixin/line_length_help.rb +11 -2
  219. data/lib/rubocop/cop/mixin/method_complexity.rb +5 -3
  220. data/lib/rubocop/cop/mixin/min_branches_count.rb +40 -0
  221. data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +5 -6
  222. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -2
  223. data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
  224. data/lib/rubocop/cop/mixin/percent_array.rb +3 -5
  225. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
  226. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +6 -8
  227. data/lib/rubocop/cop/mixin/range_help.rb +1 -6
  228. data/lib/rubocop/cop/mixin/require_library.rb +2 -0
  229. data/lib/rubocop/cop/mixin/rescue_node.rb +3 -3
  230. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
  231. data/lib/rubocop/cop/mixin/statement_modifier.rb +18 -3
  232. data/lib/rubocop/cop/mixin/string_help.rb +4 -2
  233. data/lib/rubocop/cop/mixin/surrounding_space.rb +3 -3
  234. data/lib/rubocop/cop/mixin/trailing_comma.rb +3 -3
  235. data/lib/rubocop/cop/naming/ascii_identifiers.rb +1 -1
  236. data/lib/rubocop/cop/naming/block_forwarding.rb +6 -2
  237. data/lib/rubocop/cop/naming/class_and_module_camel_case.rb +3 -1
  238. data/lib/rubocop/cop/naming/constant_name.rb +1 -1
  239. data/lib/rubocop/cop/naming/file_name.rb +1 -1
  240. data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +1 -1
  241. data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +3 -1
  242. data/lib/rubocop/cop/naming/inclusive_language.rb +27 -5
  243. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +25 -10
  244. data/lib/rubocop/cop/naming/method_name.rb +3 -3
  245. data/lib/rubocop/cop/naming/predicate_name.rb +1 -1
  246. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +12 -4
  247. data/lib/rubocop/cop/naming/variable_name.rb +6 -1
  248. data/lib/rubocop/cop/registry.rb +66 -44
  249. data/lib/rubocop/cop/security/compound_hash.rb +2 -1
  250. data/lib/rubocop/cop/style/access_modifier_declarations.rb +26 -11
  251. data/lib/rubocop/cop/style/accessor_grouping.rb +43 -17
  252. data/lib/rubocop/cop/style/alias.rb +18 -9
  253. data/lib/rubocop/cop/style/arguments_forwarding.rb +280 -62
  254. data/lib/rubocop/cop/style/array_intersect.rb +119 -0
  255. data/lib/rubocop/cop/style/ascii_comments.rb +1 -1
  256. data/lib/rubocop/cop/style/attr.rb +11 -1
  257. data/lib/rubocop/cop/style/begin_block.rb +1 -2
  258. data/lib/rubocop/cop/style/bisected_attr_accessor.rb +1 -1
  259. data/lib/rubocop/cop/style/block_comments.rb +3 -3
  260. data/lib/rubocop/cop/style/block_delimiters.rb +22 -6
  261. data/lib/rubocop/cop/style/case_like_if.rb +20 -3
  262. data/lib/rubocop/cop/style/class_and_module_children.rb +5 -12
  263. data/lib/rubocop/cop/style/class_equality_comparison.rb +58 -40
  264. data/lib/rubocop/cop/style/collection_compact.rb +20 -7
  265. data/lib/rubocop/cop/style/collection_methods.rb +2 -0
  266. data/lib/rubocop/cop/style/colon_method_call.rb +2 -2
  267. data/lib/rubocop/cop/style/combinable_loops.rb +30 -8
  268. data/lib/rubocop/cop/style/command_literal.rb +1 -1
  269. data/lib/rubocop/cop/style/comment_annotation.rb +1 -1
  270. data/lib/rubocop/cop/style/commented_keyword.rb +2 -2
  271. data/lib/rubocop/cop/style/comparable_clamp.rb +125 -0
  272. data/lib/rubocop/cop/style/concat_array_literals.rb +94 -0
  273. data/lib/rubocop/cop/style/conditional_assignment.rb +11 -15
  274. data/lib/rubocop/cop/style/copyright.rb +6 -3
  275. data/lib/rubocop/cop/style/data_inheritance.rb +75 -0
  276. data/lib/rubocop/cop/style/dir.rb +1 -1
  277. data/lib/rubocop/cop/style/dir_empty.rb +54 -0
  278. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +2 -2
  279. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +3 -3
  280. data/lib/rubocop/cop/style/documentation.rb +22 -10
  281. data/lib/rubocop/cop/style/documentation_method.rb +10 -4
  282. data/lib/rubocop/cop/style/double_negation.rb +2 -2
  283. data/lib/rubocop/cop/style/each_with_object.rb +1 -1
  284. data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
  285. data/lib/rubocop/cop/style/empty_case_condition.rb +6 -1
  286. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
  287. data/lib/rubocop/cop/style/eval_with_location.rb +8 -8
  288. data/lib/rubocop/cop/style/exact_regexp_match.rb +68 -0
  289. data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
  290. data/lib/rubocop/cop/style/file_empty.rb +71 -0
  291. data/lib/rubocop/cop/style/file_read.rb +3 -3
  292. data/lib/rubocop/cop/style/file_write.rb +1 -1
  293. data/lib/rubocop/cop/style/for.rb +1 -1
  294. data/lib/rubocop/cop/style/format_string.rb +24 -3
  295. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +4 -2
  296. data/lib/rubocop/cop/style/guard_clause.rb +73 -10
  297. data/lib/rubocop/cop/style/hash_conversion.rb +10 -0
  298. data/lib/rubocop/cop/style/hash_each_methods.rb +1 -10
  299. data/lib/rubocop/cop/style/hash_except.rb +23 -12
  300. data/lib/rubocop/cop/style/hash_like_case.rb +3 -9
  301. data/lib/rubocop/cop/style/hash_syntax.rb +16 -9
  302. data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
  303. data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
  304. data/lib/rubocop/cop/style/identical_conditional_branches.rb +36 -3
  305. data/lib/rubocop/cop/style/if_inside_else.rb +6 -0
  306. data/lib/rubocop/cop/style/if_unless_modifier.rb +111 -15
  307. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +2 -0
  308. data/lib/rubocop/cop/style/if_with_semicolon.rb +6 -6
  309. data/lib/rubocop/cop/style/infinite_loop.rb +2 -5
  310. data/lib/rubocop/cop/style/inverse_methods.rb +7 -5
  311. data/lib/rubocop/cop/style/invertible_unless_condition.rb +118 -0
  312. data/lib/rubocop/cop/style/lambda.rb +3 -3
  313. data/lib/rubocop/cop/style/lambda_call.rb +5 -0
  314. data/lib/rubocop/cop/style/line_end_concatenation.rb +4 -1
  315. data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +2 -2
  316. data/lib/rubocop/cop/style/map_to_hash.rb +4 -1
  317. data/lib/rubocop/cop/style/map_to_set.rb +64 -0
  318. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +35 -24
  319. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +44 -37
  320. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -0
  321. data/lib/rubocop/cop/style/method_def_parentheses.rb +11 -4
  322. data/lib/rubocop/cop/style/min_max.rb +3 -3
  323. data/lib/rubocop/cop/style/min_max_comparison.rb +83 -0
  324. data/lib/rubocop/cop/style/missing_else.rb +13 -1
  325. data/lib/rubocop/cop/style/mixin_grouping.rb +5 -5
  326. data/lib/rubocop/cop/style/multiline_block_chain.rb +1 -1
  327. data/lib/rubocop/cop/style/multiline_if_modifier.rb +0 -4
  328. data/lib/rubocop/cop/style/multiline_memoization.rb +2 -2
  329. data/lib/rubocop/cop/style/multiline_method_signature.rb +7 -4
  330. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +19 -4
  331. data/lib/rubocop/cop/style/multiple_comparison.rb +14 -0
  332. data/lib/rubocop/cop/style/negated_if_else_condition.rb +13 -12
  333. data/lib/rubocop/cop/style/nested_ternary_operator.rb +3 -11
  334. data/lib/rubocop/cop/style/nil_lambda.rb +3 -3
  335. data/lib/rubocop/cop/style/numbered_parameters_limit.rb +11 -3
  336. data/lib/rubocop/cop/style/numeric_literals.rb +1 -1
  337. data/lib/rubocop/cop/style/one_line_conditional.rb +3 -6
  338. data/lib/rubocop/cop/style/open_struct_use.rb +1 -1
  339. data/lib/rubocop/cop/style/operator_method_call.rb +22 -2
  340. data/lib/rubocop/cop/style/parallel_assignment.rb +29 -19
  341. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +2 -3
  342. data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
  343. data/lib/rubocop/cop/style/preferred_hash_methods.rb +1 -1
  344. data/lib/rubocop/cop/style/redundant_argument.rb +9 -1
  345. data/lib/rubocop/cop/style/redundant_array_constructor.rb +77 -0
  346. data/lib/rubocop/cop/style/redundant_begin.rb +10 -2
  347. data/lib/rubocop/cop/style/redundant_condition.rb +18 -3
  348. data/lib/rubocop/cop/style/redundant_conditional.rb +2 -14
  349. data/lib/rubocop/cop/style/redundant_constant_base.rb +85 -0
  350. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +38 -0
  351. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +126 -0
  352. data/lib/rubocop/cop/style/redundant_exception.rb +32 -12
  353. data/lib/rubocop/cop/style/redundant_fetch_block.rb +6 -4
  354. data/lib/rubocop/cop/style/redundant_filter_chain.rb +117 -0
  355. data/lib/rubocop/cop/style/redundant_heredoc_delimiter_quotes.rb +58 -0
  356. data/lib/rubocop/cop/style/redundant_interpolation.rb +2 -2
  357. data/lib/rubocop/cop/style/redundant_line_continuation.rb +183 -0
  358. data/lib/rubocop/cop/style/redundant_parentheses.rb +26 -8
  359. data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -1
  360. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +100 -0
  361. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +7 -8
  362. data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +46 -0
  363. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +13 -4
  364. data/lib/rubocop/cop/style/redundant_return.rb +14 -2
  365. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +8 -1
  366. data/lib/rubocop/cop/style/redundant_sort.rb +5 -5
  367. data/lib/rubocop/cop/style/redundant_string_escape.rb +11 -7
  368. data/lib/rubocop/cop/style/regexp_literal.rb +11 -2
  369. data/lib/rubocop/cop/style/require_order.rb +139 -0
  370. data/lib/rubocop/cop/style/rescue_modifier.rb +1 -3
  371. data/lib/rubocop/cop/style/rescue_standard_error.rb +2 -2
  372. data/lib/rubocop/cop/style/return_nil.rb +6 -2
  373. data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +95 -0
  374. data/lib/rubocop/cop/style/safe_navigation.rb +37 -8
  375. data/lib/rubocop/cop/style/select_by_regexp.rb +23 -5
  376. data/lib/rubocop/cop/style/self_assignment.rb +2 -2
  377. data/lib/rubocop/cop/style/semicolon.rb +37 -6
  378. data/lib/rubocop/cop/style/signal_exception.rb +9 -7
  379. data/lib/rubocop/cop/style/single_line_do_end_block.rb +65 -0
  380. data/lib/rubocop/cop/style/single_line_methods.rb +1 -1
  381. data/lib/rubocop/cop/style/slicing_with_range.rb +1 -1
  382. data/lib/rubocop/cop/style/sole_nested_conditional.rb +9 -5
  383. data/lib/rubocop/cop/style/special_global_vars.rb +3 -4
  384. data/lib/rubocop/cop/style/stderr_puts.rb +1 -1
  385. data/lib/rubocop/cop/style/string_hash_keys.rb +4 -1
  386. data/lib/rubocop/cop/style/string_literals.rb +1 -5
  387. data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +30 -5
  388. data/lib/rubocop/cop/style/struct_inheritance.rb +1 -1
  389. data/lib/rubocop/cop/style/symbol_array.rb +35 -15
  390. data/lib/rubocop/cop/style/symbol_proc.rb +2 -4
  391. data/lib/rubocop/cop/style/trailing_body_on_class.rb +1 -0
  392. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +4 -4
  393. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +1 -1
  394. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
  395. data/lib/rubocop/cop/style/unless_logical_operators.rb +1 -0
  396. data/lib/rubocop/cop/style/unpack_first.rb +3 -3
  397. data/lib/rubocop/cop/style/word_array.rb +54 -1
  398. data/lib/rubocop/cop/style/yaml_file_read.rb +66 -0
  399. data/lib/rubocop/cop/style/yoda_condition.rb +17 -8
  400. data/lib/rubocop/cop/style/yoda_expression.rb +91 -0
  401. data/lib/rubocop/cop/style/zero_length_predicate.rb +40 -19
  402. data/lib/rubocop/cop/team.rb +61 -53
  403. data/lib/rubocop/cop/util.rb +43 -7
  404. data/lib/rubocop/cop/utils/regexp_ranges.rb +113 -0
  405. data/lib/rubocop/cop/variable_force/assignment.rb +45 -4
  406. data/lib/rubocop/cop/variable_force/scope.rb +3 -3
  407. data/lib/rubocop/cop/variable_force/variable.rb +5 -3
  408. data/lib/rubocop/cop/variable_force/variable_table.rb +5 -3
  409. data/lib/rubocop/cop/variable_force.rb +19 -30
  410. data/lib/rubocop/cops_documentation_generator.rb +44 -15
  411. data/lib/rubocop/directive_comment.rb +4 -4
  412. data/lib/rubocop/ext/comment.rb +18 -0
  413. data/lib/rubocop/ext/regexp_node.rb +1 -1
  414. data/lib/rubocop/ext/regexp_parser.rb +5 -2
  415. data/lib/rubocop/file_finder.rb +4 -7
  416. data/lib/rubocop/file_patterns.rb +43 -0
  417. data/lib/rubocop/formatter/disabled_config_formatter.rb +17 -6
  418. data/lib/rubocop/formatter/html_formatter.rb +1 -1
  419. data/lib/rubocop/formatter/junit_formatter.rb +4 -1
  420. data/lib/rubocop/formatter/simple_text_formatter.rb +1 -1
  421. data/lib/rubocop/formatter.rb +4 -1
  422. data/lib/rubocop/lsp/logger.rb +22 -0
  423. data/lib/rubocop/lsp/routes.rb +246 -0
  424. data/lib/rubocop/lsp/runtime.rb +99 -0
  425. data/lib/rubocop/lsp/server.rb +68 -0
  426. data/lib/rubocop/lsp/severity.rb +27 -0
  427. data/lib/rubocop/magic_comment.rb +12 -10
  428. data/lib/rubocop/options.rb +45 -3
  429. data/lib/rubocop/path_util.rb +50 -22
  430. data/lib/rubocop/result_cache.rb +8 -4
  431. data/lib/rubocop/rspec/cop_helper.rb +6 -3
  432. data/lib/rubocop/rspec/expect_offense.rb +6 -4
  433. data/lib/rubocop/rspec/shared_contexts.rb +6 -3
  434. data/lib/rubocop/rspec/support.rb +3 -2
  435. data/lib/rubocop/runner.rb +55 -10
  436. data/lib/rubocop/server/cache.rb +12 -4
  437. data/lib/rubocop/server/cli.rb +37 -18
  438. data/lib/rubocop/server/client_command/exec.rb +4 -3
  439. data/lib/rubocop/server/client_command/start.rb +6 -1
  440. data/lib/rubocop/server/core.rb +25 -10
  441. data/lib/rubocop/server/helper.rb +1 -1
  442. data/lib/rubocop/server/server_command/exec.rb +1 -1
  443. data/lib/rubocop/string_interpreter.rb +3 -3
  444. data/lib/rubocop/target_finder.rb +8 -4
  445. data/lib/rubocop/target_ruby.rb +14 -10
  446. data/lib/rubocop/version.rb +10 -6
  447. data/lib/rubocop.rb +47 -6
  448. metadata +91 -37
@@ -16,6 +16,33 @@ module RuboCop
16
16
  # {
17
17
  # a: 1,
18
18
  # b: 2 }
19
+ #
20
+ # # good
21
+ # {
22
+ # a: 1, b: {
23
+ # c: 3
24
+ # }}
25
+ #
26
+ # @example AllowMultilineFinalElement: false (default)
27
+ #
28
+ # # bad
29
+ # { a: 1, b: {
30
+ # c: 3
31
+ # }}
32
+ #
33
+ # @example AllowMultilineFinalElement: true
34
+ #
35
+ # # bad
36
+ # { a: 1,
37
+ # b: {
38
+ # c: 3
39
+ # }}
40
+ #
41
+ # # good
42
+ # { a: 1, b: {
43
+ # c: 3
44
+ # }}
45
+ #
19
46
  class FirstHashElementLineBreak < Base
20
47
  include FirstElementLineBreak
21
48
  extend AutoCorrector
@@ -25,7 +52,15 @@ module RuboCop
25
52
  def on_hash(node)
26
53
  # node.loc.begin tells us whether the hash opens with a {
27
54
  # If it doesn't, Style/FirstMethodArgumentLineBreak will handle it
28
- check_children_line_break(node, node.children) if node.loc.begin
55
+ return unless node.loc.begin
56
+
57
+ check_children_line_break(node, node.children, ignore_last: ignore_last_element?)
58
+ end
59
+
60
+ private
61
+
62
+ def ignore_last_element?
63
+ !!cop_config['AllowMultilineFinalElement']
29
64
  end
30
65
  end
31
66
  end
@@ -8,18 +8,61 @@ module RuboCop
8
8
  #
9
9
  # @example
10
10
  #
11
- # # bad
12
- # method(foo, bar,
13
- # baz)
11
+ # # bad
12
+ # method(foo, bar,
13
+ # baz)
14
14
  #
15
- # # good
16
- # method(
17
- # foo, bar,
18
- # baz)
15
+ # # good
16
+ # method(
17
+ # foo, bar,
18
+ # baz)
19
19
  #
20
20
  # # ignored
21
21
  # method foo, bar,
22
22
  # baz
23
+ #
24
+ # @example AllowMultilineFinalElement: false (default)
25
+ #
26
+ # # bad
27
+ # method(foo, bar, {
28
+ # baz: "a",
29
+ # qux: "b",
30
+ # })
31
+ #
32
+ # # good
33
+ # method(
34
+ # foo, bar, {
35
+ # baz: "a",
36
+ # qux: "b",
37
+ # })
38
+ #
39
+ # @example AllowMultilineFinalElement: true
40
+ #
41
+ # # bad
42
+ # method(foo,
43
+ # bar,
44
+ # {
45
+ # baz: "a",
46
+ # qux: "b",
47
+ # }
48
+ # )
49
+ #
50
+ # # good
51
+ # method(foo, bar, {
52
+ # baz: "a",
53
+ # qux: "b",
54
+ # })
55
+ #
56
+ # # good
57
+ # method(
58
+ # foo,
59
+ # bar,
60
+ # {
61
+ # baz: "a",
62
+ # qux: "b",
63
+ # }
64
+ # )
65
+ #
23
66
  class FirstMethodArgumentLineBreak < Base
24
67
  include FirstElementLineBreak
25
68
  extend AutoCorrector
@@ -38,10 +81,16 @@ module RuboCop
38
81
  last_arg = args.last
39
82
  args.concat(args.pop.children) if last_arg&.hash_type? && !last_arg&.braces?
40
83
 
41
- check_method_line_break(node, args)
84
+ check_method_line_break(node, args, ignore_last: ignore_last_element?)
42
85
  end
43
86
  alias on_csend on_send
44
87
  alias on_super on_send
88
+
89
+ private
90
+
91
+ def ignore_last_element?
92
+ !!cop_config['AllowMultilineFinalElement']
93
+ end
45
94
  end
46
95
  end
47
96
  end
@@ -8,24 +8,51 @@ module RuboCop
8
8
  #
9
9
  # @example
10
10
  #
11
- # # bad
12
- # def method(foo, bar,
13
- # baz)
14
- # do_something
15
- # end
16
- #
17
- # # good
18
- # def method(
19
- # foo, bar,
20
- # baz)
21
- # do_something
22
- # end
23
- #
24
- # # ignored
25
- # def method foo,
26
- # bar
27
- # do_something
28
- # end
11
+ # # bad
12
+ # def method(foo, bar,
13
+ # baz)
14
+ # do_something
15
+ # end
16
+ #
17
+ # # good
18
+ # def method(
19
+ # foo, bar,
20
+ # baz)
21
+ # do_something
22
+ # end
23
+ #
24
+ # # ignored
25
+ # def method foo,
26
+ # bar
27
+ # do_something
28
+ # end
29
+ #
30
+ # @example AllowMultilineFinalElement: false (default)
31
+ #
32
+ # # bad
33
+ # def method(foo, bar, baz = {
34
+ # :a => "b",
35
+ # })
36
+ # do_something
37
+ # end
38
+ #
39
+ # # good
40
+ # def method(
41
+ # foo, bar, baz = {
42
+ # :a => "b",
43
+ # })
44
+ # do_something
45
+ # end
46
+ #
47
+ # @example AllowMultilineFinalElement: true
48
+ #
49
+ # # good
50
+ # def method(foo, bar, baz = {
51
+ # :a => "b",
52
+ # })
53
+ # do_something
54
+ # end
55
+ #
29
56
  class FirstMethodParameterLineBreak < Base
30
57
  include FirstElementLineBreak
31
58
  extend AutoCorrector
@@ -33,9 +60,15 @@ module RuboCop
33
60
  MSG = 'Add a line break before the first parameter of a multi-line method parameter list.'
34
61
 
35
62
  def on_def(node)
36
- check_method_line_break(node, node.arguments)
63
+ check_method_line_break(node, node.arguments, ignore_last: ignore_last_element?)
37
64
  end
38
65
  alias on_defs on_def
66
+
67
+ private
68
+
69
+ def ignore_last_element?
70
+ !!cop_config['AllowMultilineFinalElement']
71
+ end
39
72
  end
40
73
  end
41
74
  end
@@ -67,8 +67,7 @@ module RuboCop
67
67
 
68
68
  outermost_send = outermost_send_on_same_line(heredoc_arg)
69
69
  return unless outermost_send
70
- return unless outermost_send.loc.end
71
- return unless heredoc_arg.first_line != outermost_send.loc.end.line
70
+ return if end_keyword_before_closing_parenthesis?(node)
72
71
  return if subsequent_closing_parentheses_in_same_line?(outermost_send)
73
72
  return if exist_argument_between_heredoc_end_and_closing_parentheses?(node)
74
73
 
@@ -160,6 +159,12 @@ module RuboCop
160
159
 
161
160
  # Closing parenthesis helpers.
162
161
 
162
+ def end_keyword_before_closing_parenthesis?(parenthesized_send_node)
163
+ parenthesized_send_node.ancestors.any? do |ancestor|
164
+ ancestor.loc.respond_to?(:end) && ancestor.loc.end&.source == 'end'
165
+ end
166
+ end
167
+
163
168
  def subsequent_closing_parentheses_in_same_line?(outermost_send)
164
169
  last_arg_of_outer_send = outermost_send.last_argument
165
170
  return false unless last_arg_of_outer_send&.loc.respond_to?(:end) &&
@@ -215,6 +220,7 @@ module RuboCop
215
220
  end
216
221
 
217
222
  def exist_argument_between_heredoc_end_and_closing_parentheses?(node)
223
+ return true unless node.loc.end
218
224
  return false unless (heredoc_end = find_most_bottom_of_heredoc_end(node.arguments))
219
225
 
220
226
  heredoc_end < node.loc.end.begin_pos &&
@@ -222,9 +228,9 @@ module RuboCop
222
228
  end
223
229
 
224
230
  def find_most_bottom_of_heredoc_end(arguments)
225
- arguments.map do |argument|
231
+ arguments.filter_map do |argument|
226
232
  argument.loc.heredoc_end.end_pos if argument.loc.respond_to?(:heredoc_end)
227
- end.compact.max
233
+ end.max
228
234
  end
229
235
 
230
236
  # Internal trailing comma helpers.
@@ -22,8 +22,12 @@ module RuboCop
22
22
  # RUBY
23
23
  #
24
24
  class HeredocIndentation < Base
25
+ include Alignment
25
26
  include Heredoc
26
27
  extend AutoCorrector
28
+ extend TargetRubyVersion
29
+
30
+ minimum_target_ruby_version 2.3
27
31
 
28
32
  TYPE_MSG = 'Use %<indentation_width>d spaces for indentation in a ' \
29
33
  'heredoc by using `<<~` instead of `%<current_indent_type>s`.'
@@ -37,7 +41,7 @@ module RuboCop
37
41
  heredoc_indent_type = heredoc_indent_type(node)
38
42
 
39
43
  if heredoc_indent_type == '~'
40
- expected_indent_level = base_indent_level(node) + indentation_width
44
+ expected_indent_level = base_indent_level(node) + configured_indentation_width
41
45
  return if expected_indent_level == body_indent_level
42
46
  else
43
47
  return unless body_indent_level.zero?
@@ -66,9 +70,9 @@ module RuboCop
66
70
  current_indent_type = "<<#{heredoc_indent_type}"
67
71
 
68
72
  if current_indent_type == '<<~'
69
- width_message(indentation_width)
73
+ width_message(configured_indentation_width)
70
74
  else
71
- type_message(indentation_width, current_indent_type)
75
+ type_message(configured_indentation_width, current_indent_type)
72
76
  end
73
77
  end
74
78
 
@@ -89,7 +93,7 @@ module RuboCop
89
93
 
90
94
  body = heredoc_body(node)
91
95
 
92
- expected_indent = base_indent_level(node) + indentation_width
96
+ expected_indent = base_indent_level(node) + configured_indentation_width
93
97
  actual_indent = indent_level(body)
94
98
  increase_indent_level = expected_indent - actual_indent
95
99
 
@@ -114,7 +118,7 @@ module RuboCop
114
118
  end
115
119
 
116
120
  def adjust_minus(corrector, node)
117
- heredoc_beginning = node.loc.expression.source
121
+ heredoc_beginning = node.source
118
122
  corrected = heredoc_beginning.sub(/<<-?/, '<<~')
119
123
  corrector.replace(node, corrected)
120
124
  end
@@ -122,7 +126,7 @@ module RuboCop
122
126
  def indented_body(node)
123
127
  body = heredoc_body(node)
124
128
  body_indent_level = indent_level(body)
125
- correct_indent_level = base_indent_level(node) + indentation_width
129
+ correct_indent_level = base_indent_level(node) + configured_indentation_width
126
130
  body.gsub(/^[^\S\r\n]{#{body_indent_level}}/, ' ' * correct_indent_level)
127
131
  end
128
132
 
@@ -138,7 +142,7 @@ module RuboCop
138
142
  end
139
143
 
140
144
  def base_indent_level(node)
141
- base_line_num = node.loc.expression.line
145
+ base_line_num = node.source_range.line
142
146
  base_line = processed_source.lines[base_line_num - 1]
143
147
  indent_level(base_line)
144
148
  end
@@ -148,10 +152,6 @@ module RuboCop
148
152
  node.source[/^<<([~-])/, 1]
149
153
  end
150
154
 
151
- def indentation_width
152
- @config.for_cop('Layout/IndentationWidth')['Width'] || 2
153
- end
154
-
155
155
  def heredoc_body(node)
156
156
  node.loc.heredoc_body.source
157
157
  end
@@ -40,10 +40,13 @@ module RuboCop
40
40
  MSG = '%<type>s detected in indentation.'
41
41
 
42
42
  def on_new_investigation
43
- str_ranges = string_literal_ranges(processed_source.ast)
43
+ str_ranges = nil
44
44
 
45
45
  processed_source.lines.each.with_index(1) do |line, lineno|
46
46
  next unless (range = find_offense(line, lineno))
47
+
48
+ # Perform costly calculation only when needed.
49
+ str_ranges ||= string_literal_ranges(processed_source.ast)
47
50
  next if in_string_literal?(str_ranges, range)
48
51
 
49
52
  add_offense(range) { |corrector| autocorrect(corrector, range) }
@@ -73,7 +76,7 @@ module RuboCop
73
76
 
74
77
  def autocorrect_lambda_for_tabs(corrector, range)
75
78
  spaces = ' ' * configured_indentation_width
76
- corrector.replace(range, range.source.gsub(/\t/, spaces))
79
+ corrector.replace(range, range.source.gsub("\t", spaces))
77
80
  end
78
81
 
79
82
  def autocorrect_lambda_for_spaces(corrector, range)
@@ -90,7 +93,8 @@ module RuboCop
90
93
  # which lines start inside a string literal?
91
94
  return [] if ast.nil?
92
95
 
93
- ast.each_node(:str, :dstr).with_object(Set.new) do |str, ranges|
96
+ ranges = Set.new
97
+ ast.each_node(:str, :dstr) do |str|
94
98
  loc = str.location
95
99
 
96
100
  if str.heredoc?
@@ -99,6 +103,7 @@ module RuboCop
99
103
  ranges << loc.expression
100
104
  end
101
105
  end
106
+ ranges
102
107
  end
103
108
 
104
109
  def message(_node)
@@ -354,7 +354,7 @@ module RuboCop
354
354
  # Don't check indentation if the line doesn't start with the body.
355
355
  # For example, lines like "else do_something".
356
356
  first_char_pos_on_line = body_node.source_range.source_line =~ /\S/
357
- return true unless body_node.loc.column == first_char_pos_on_line
357
+ body_node.loc.column != first_char_pos_on_line
358
358
  end
359
359
 
360
360
  def offending_range(body_node, indentation)
@@ -366,10 +366,10 @@ module RuboCop
366
366
  end
367
367
 
368
368
  def starts_with_access_modifier?(body_node)
369
- return unless body_node.begin_type?
369
+ return false unless body_node.begin_type?
370
370
 
371
371
  starting_node = body_node.children.first
372
- return unless starting_node
372
+ return false unless starting_node
373
373
 
374
374
  starting_node.send_type? && starting_node.bare_access_modifier?
375
375
  end
@@ -34,7 +34,7 @@ module RuboCop
34
34
  private
35
35
 
36
36
  def first_token
37
- processed_source.find_token { |t| !t.text.start_with?('#') }
37
+ processed_source.tokens.find { |t| !t.text.start_with?('#') }
38
38
  end
39
39
 
40
40
  def space_before(token)
@@ -57,13 +57,13 @@ module RuboCop
57
57
 
58
58
  def on_new_investigation
59
59
  processed_source.comments.each do |comment|
60
- next unless /\A#+[^#\s=+-]/.match?(comment.text)
60
+ next unless /\A(?!#\+\+|#--)(#+[^#\s=])/.match?(comment.text)
61
61
  next if comment.loc.line == 1 && allowed_on_first_line?(comment)
62
62
  next if doxygen_comment_style?(comment)
63
63
  next if gemfile_ruby_comment?(comment)
64
64
 
65
65
  add_offense(comment) do |corrector|
66
- expr = comment.loc.expression
66
+ expr = comment.source_range
67
67
 
68
68
  corrector.insert_after(hash_mark(expr), ' ')
69
69
  end
@@ -52,18 +52,18 @@ module RuboCop
52
52
  :LEADING_STYLE_OFFENSE, :TRAILING_STYLE_OFFENSE
53
53
 
54
54
  def on_dstr(node)
55
- end_of_first_line = node.loc.expression.begin_pos - node.loc.expression.column
55
+ # Quick check if we possibly have line continuations.
56
+ return unless node.source.include?('\\')
56
57
 
57
- raw_lines(node).each_cons(2) do |raw_line_one, raw_line_two|
58
+ end_of_first_line = node.source_range.begin_pos - node.source_range.column
59
+
60
+ lines = raw_lines(node)
61
+ lines.each_cons(2).with_index(node.first_line) do |(raw_line_one, raw_line_two), line_num|
58
62
  end_of_first_line += raw_line_one.length
59
63
 
60
- next unless continuation?(raw_line_one)
64
+ next unless continuation?(raw_line_one, line_num, node)
61
65
 
62
- if enforced_style_leading?
63
- investigate_leading_style(raw_line_one, raw_line_two, end_of_first_line)
64
- else
65
- investigate_trailing_style(raw_line_one, raw_line_two, end_of_first_line)
66
- end
66
+ investigate(raw_line_one, raw_line_two, end_of_first_line)
67
67
  end
68
68
  end
69
69
 
@@ -73,6 +73,14 @@ module RuboCop
73
73
  processed_source.raw_source.lines[node.first_line - 1, line_range(node).size]
74
74
  end
75
75
 
76
+ def investigate(first_line, second_line, end_of_first_line)
77
+ if enforced_style_leading?
78
+ investigate_leading_style(first_line, second_line, end_of_first_line)
79
+ else
80
+ investigate_trailing_style(first_line, second_line, end_of_first_line)
81
+ end
82
+ end
83
+
76
84
  def investigate_leading_style(first_line, second_line, end_of_first_line)
77
85
  matches = first_line.match(LEADING_STYLE_OFFENSE)
78
86
  return if matches.nil?
@@ -95,8 +103,11 @@ module RuboCop
95
103
  end
96
104
  end
97
105
 
98
- def continuation?(line)
99
- line.end_with?("\\\n")
106
+ def continuation?(line, line_num, node)
107
+ return false unless line.end_with?("\\\n")
108
+
109
+ # Ensure backslash isn't part of a token spanning to the next line.
110
+ node.children.none? { |c| c.first_line == line_num && c.multiline? }
100
111
  end
101
112
 
102
113
  def autocorrect(corrector, offense_range, insert_pos, spaces)
@@ -32,10 +32,9 @@ module RuboCop
32
32
  extend AutoCorrector
33
33
 
34
34
  def on_new_investigation
35
- last_line = last_line(processed_source)
35
+ return unless processed_source.raw_source.include?('\\')
36
36
 
37
- @ignored_ranges = string_literal_ranges(processed_source.ast) +
38
- comment_ranges(processed_source.comments)
37
+ last_line = last_line(processed_source)
39
38
 
40
39
  processed_source.raw_source.lines.each_with_index do |line, index|
41
40
  break if index >= last_line
@@ -88,23 +87,29 @@ module RuboCop
88
87
  corrector.replace(range, correction)
89
88
  end
90
89
 
91
- def string_literal_ranges(ast)
90
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
91
+ def ignored_literal_ranges(ast)
92
92
  # which lines start inside a string literal?
93
93
  return [] if ast.nil?
94
94
 
95
- ast.each_node(:str, :dstr).with_object(Set.new) do |str, ranges|
96
- loc = str.location
95
+ ast.each_node(:str, :dstr, :array).with_object(Set.new) do |literal, ranges|
96
+ loc = literal.location
97
+
98
+ if literal.array_type?
99
+ next unless literal.percent_literal?
97
100
 
98
- if str.heredoc?
101
+ ranges << loc.expression
102
+ elsif literal.heredoc?
99
103
  ranges << loc.heredoc_body
100
104
  elsif loc.respond_to?(:begin) && loc.begin
101
105
  ranges << loc.expression
102
106
  end
103
107
  end
104
108
  end
109
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
105
110
 
106
111
  def comment_ranges(comments)
107
- comments.map(&:loc).map(&:expression)
112
+ comments.map(&:source_range)
108
113
  end
109
114
 
110
115
  def last_line(processed_source)
@@ -114,7 +119,12 @@ module RuboCop
114
119
  end
115
120
 
116
121
  def ignore_range?(backtick_range)
117
- @ignored_ranges.any? { |range| range.contains?(backtick_range) }
122
+ ignored_ranges.any? { |range| range.contains?(backtick_range) }
123
+ end
124
+
125
+ def ignored_ranges
126
+ @ignored_ranges ||= ignored_literal_ranges(processed_source.ast) +
127
+ comment_ranges(processed_source.comments)
118
128
  end
119
129
 
120
130
  def no_space_style?
@@ -84,6 +84,8 @@ module RuboCop
84
84
  return unless strings_concatenated_with_backslash?(node)
85
85
 
86
86
  children = node.children
87
+ return if children.empty?
88
+
87
89
  if style == :aligned && !always_indented?(node)
88
90
  check_aligned(children, 1)
89
91
  else
@@ -86,6 +86,8 @@ module RuboCop
86
86
  alias on_def on_potential_breakable_node
87
87
 
88
88
  def on_new_investigation
89
+ return unless processed_source.raw_source.include?(';')
90
+
89
91
  check_for_breakable_semicolons(processed_source)
90
92
  end
91
93
 
@@ -20,6 +20,30 @@ module RuboCop
20
20
  # b,
21
21
  # c
22
22
  # ]
23
+ #
24
+ # # good
25
+ # [
26
+ # a,
27
+ # b,
28
+ # foo(
29
+ # bar
30
+ # )
31
+ # ]
32
+ #
33
+ # @example AllowMultilineFinalElement: false (default)
34
+ #
35
+ # # bad
36
+ # [a, b, foo(
37
+ # bar
38
+ # )]
39
+ #
40
+ # @example AllowMultilineFinalElement: true
41
+ #
42
+ # # good
43
+ # [a, b, foo(
44
+ # bar
45
+ # )]
46
+ #
23
47
  class MultilineArrayLineBreaks < Base
24
48
  include MultilineElementLineBreaks
25
49
  extend AutoCorrector
@@ -27,7 +51,13 @@ module RuboCop
27
51
  MSG = 'Each item in a multi-line array must start on a separate line.'
28
52
 
29
53
  def on_array(node)
30
- check_line_breaks(node, node.children)
54
+ check_line_breaks(node, node.children, ignore_last: ignore_last_element?)
55
+ end
56
+
57
+ private
58
+
59
+ def ignore_last_element?
60
+ !!cop_config['AllowMultilineFinalElement']
31
61
  end
32
62
  end
33
63
  end
@@ -91,7 +91,7 @@ module RuboCop
91
91
  if node.source.lines.first.end_with?("|\n")
92
92
  PIPE_SIZE
93
93
  else
94
- 1 + (PIPE_SIZE * 2)
94
+ (PIPE_SIZE * 2) + 1
95
95
  end
96
96
  end
97
97
 
@@ -20,6 +20,29 @@ module RuboCop
20
20
  # b: 2,
21
21
  # c: 3
22
22
  # }
23
+ #
24
+ # # good
25
+ # {
26
+ # a: 1,
27
+ # b: {
28
+ # c: 3,
29
+ # }
30
+ # }
31
+ #
32
+ # @example AllowMultilineFinalElement: false (default)
33
+ #
34
+ # # bad
35
+ # { a: 1, b: {
36
+ # c: 3,
37
+ # }}
38
+ #
39
+ # @example AllowMultilineFinalElement: true
40
+ #
41
+ # # good
42
+ # { a: 1, b: {
43
+ # c: 3,
44
+ # }}
45
+ #
23
46
  class MultilineHashKeyLineBreaks < Base
24
47
  include MultilineElementLineBreaks
25
48
  extend AutoCorrector
@@ -31,8 +54,9 @@ module RuboCop
31
54
  # braces like {foo: 1}. That is, not a kwargs hashes.
32
55
  # Style/MultilineMethodArgumentLineBreaks handles those.
33
56
  return unless starts_with_curly_brace?(node)
57
+ return unless node.loc.begin
34
58
 
35
- check_line_breaks(node, node.children) if node.loc.begin
59
+ check_line_breaks(node, node.children, ignore_last: ignore_last_element?)
36
60
  end
37
61
 
38
62
  private
@@ -40,6 +64,10 @@ module RuboCop
40
64
  def starts_with_curly_brace?(node)
41
65
  node.loc.begin
42
66
  end
67
+
68
+ def ignore_last_element?
69
+ !!cop_config['AllowMultilineFinalElement']
70
+ end
43
71
  end
44
72
  end
45
73
  end