rubocop 0.52.1 → 0.53.0

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 (292) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +2 -2
  4. data/config/default.yml +118 -46
  5. data/config/disabled.yml +8 -8
  6. data/config/enabled.yml +84 -28
  7. data/lib/rubocop.rb +28 -8
  8. data/lib/rubocop/ast/builder.rb +35 -37
  9. data/lib/rubocop/ast/node.rb +16 -1
  10. data/lib/rubocop/ast/node/and_node.rb +0 -8
  11. data/lib/rubocop/ast/node/block_node.rb +1 -9
  12. data/lib/rubocop/ast/node/case_node.rb +0 -8
  13. data/lib/rubocop/ast/node/ensure_node.rb +0 -8
  14. data/lib/rubocop/ast/node/for_node.rb +0 -8
  15. data/lib/rubocop/ast/node/or_node.rb +0 -8
  16. data/lib/rubocop/ast/node/pair_node.rb +0 -8
  17. data/lib/rubocop/ast/node/resbody_node.rb +0 -8
  18. data/lib/rubocop/ast/node/send_node.rb +0 -8
  19. data/lib/rubocop/ast/node/symbol_node.rb +0 -8
  20. data/lib/rubocop/ast/node/until_node.rb +0 -8
  21. data/lib/rubocop/ast/node/when_node.rb +0 -8
  22. data/lib/rubocop/ast/node/while_node.rb +0 -8
  23. data/lib/rubocop/cli.rb +17 -7
  24. data/lib/rubocop/comment_config.rb +24 -3
  25. data/lib/rubocop/config.rb +75 -6
  26. data/lib/rubocop/config_loader.rb +18 -28
  27. data/lib/rubocop/config_loader_resolver.rb +61 -9
  28. data/lib/rubocop/cop/bundler/duplicated_gem.rb +3 -1
  29. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +4 -2
  30. data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -1
  31. data/lib/rubocop/cop/commissioner.rb +2 -2
  32. data/lib/rubocop/cop/cop.rb +4 -0
  33. data/lib/rubocop/cop/corrector.rb +11 -1
  34. data/lib/rubocop/cop/correctors/alignment_corrector.rb +3 -6
  35. data/lib/rubocop/cop/correctors/line_break_corrector.rb +59 -0
  36. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +1 -1
  37. data/lib/rubocop/cop/correctors/space_corrector.rb +13 -0
  38. data/lib/rubocop/cop/correctors/unused_arg_corrector.rb +1 -1
  39. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +3 -1
  40. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
  41. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +3 -5
  42. data/lib/rubocop/cop/generator.rb +29 -8
  43. data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +2 -0
  44. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +2 -0
  45. data/lib/rubocop/cop/layout/align_hash.rb +106 -37
  46. data/lib/rubocop/cop/{lint → layout}/block_alignment.rb +8 -5
  47. data/lib/rubocop/cop/layout/block_end_newline.rb +7 -17
  48. data/lib/rubocop/cop/layout/case_indentation.rb +1 -0
  49. data/lib/rubocop/cop/layout/class_structure.rb +6 -7
  50. data/lib/rubocop/cop/layout/comment_indentation.rb +1 -1
  51. data/lib/rubocop/cop/{lint → layout}/condition_position.rb +3 -3
  52. data/lib/rubocop/cop/{lint → layout}/def_end_alignment.rb +2 -1
  53. data/lib/rubocop/cop/layout/else_alignment.rb +1 -1
  54. data/lib/rubocop/cop/layout/empty_comment.rb +140 -0
  55. data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +2 -0
  56. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +2 -0
  57. data/lib/rubocop/cop/layout/empty_lines.rb +3 -1
  58. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +7 -5
  59. data/lib/rubocop/cop/layout/empty_lines_around_arguments.rb +20 -10
  60. data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +20 -0
  61. data/lib/rubocop/cop/{lint → layout}/end_alignment.rb +37 -6
  62. data/lib/rubocop/cop/layout/end_of_line.rb +1 -0
  63. data/lib/rubocop/cop/layout/extra_spacing.rb +30 -37
  64. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -0
  65. data/lib/rubocop/cop/layout/indent_heredoc.rb +38 -2
  66. data/lib/rubocop/cop/layout/indentation_consistency.rb +105 -1
  67. data/lib/rubocop/cop/layout/indentation_width.rb +4 -3
  68. data/lib/rubocop/cop/layout/initial_indentation.rb +15 -1
  69. data/lib/rubocop/cop/layout/leading_comment_space.rb +4 -2
  70. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -0
  71. data/lib/rubocop/cop/layout/multiline_block_layout.rb +2 -0
  72. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +62 -29
  73. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +1 -1
  74. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +74 -33
  75. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +16 -2
  76. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +3 -1
  77. data/lib/rubocop/cop/layout/space_after_method_name.rb +2 -0
  78. data/lib/rubocop/cop/layout/space_after_not.rb +2 -0
  79. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -0
  80. data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +15 -2
  81. data/lib/rubocop/cop/layout/space_around_operators.rb +15 -13
  82. data/lib/rubocop/cop/layout/space_before_block_braces.rb +13 -1
  83. data/lib/rubocop/cop/layout/space_before_comment.rb +6 -4
  84. data/lib/rubocop/cop/layout/space_before_first_arg.rb +1 -0
  85. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +1 -0
  86. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +30 -45
  87. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +3 -2
  88. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +48 -18
  89. data/lib/rubocop/cop/layout/space_inside_parens.rb +8 -7
  90. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +57 -11
  91. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +1 -0
  92. data/lib/rubocop/cop/layout/tab.rb +42 -16
  93. data/lib/rubocop/cop/layout/trailing_blank_lines.rb +46 -13
  94. data/lib/rubocop/cop/layout/trailing_whitespace.rb +12 -0
  95. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +5 -3
  96. data/lib/rubocop/cop/lint/big_decimal_new.rb +44 -0
  97. data/lib/rubocop/cop/lint/boolean_symbol.rb +2 -2
  98. data/lib/rubocop/cop/lint/circular_argument_reference.rb +2 -2
  99. data/lib/rubocop/cop/lint/debugger.rb +2 -2
  100. data/lib/rubocop/cop/lint/deprecated_class_methods.rb +5 -4
  101. data/lib/rubocop/cop/lint/duplicate_methods.rb +20 -9
  102. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +4 -3
  103. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +16 -10
  104. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +5 -4
  105. data/lib/rubocop/cop/lint/inherit_exception.rb +2 -2
  106. data/lib/rubocop/cop/lint/interpolation_check.rb +4 -3
  107. data/lib/rubocop/cop/lint/literal_as_condition.rb +2 -2
  108. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +2 -0
  109. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +7 -5
  110. data/lib/rubocop/cop/lint/nested_percent_literal.rb +1 -1
  111. data/lib/rubocop/cop/lint/number_conversion.rb +59 -0
  112. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +86 -0
  113. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +2 -0
  114. data/lib/rubocop/cop/lint/percent_string_array.rb +0 -2
  115. data/lib/rubocop/cop/lint/rand_one.rb +2 -2
  116. data/lib/rubocop/cop/lint/redundant_with_index.rb +2 -0
  117. data/lib/rubocop/cop/lint/redundant_with_object.rb +2 -0
  118. data/lib/rubocop/cop/lint/require_parentheses.rb +2 -0
  119. data/lib/rubocop/cop/lint/rescue_type.rb +6 -3
  120. data/lib/rubocop/cop/lint/return_in_void_context.rb +2 -2
  121. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +17 -21
  122. data/lib/rubocop/cop/lint/script_permission.rb +30 -10
  123. data/lib/rubocop/cop/lint/shadowed_argument.rb +3 -3
  124. data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -0
  125. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +2 -2
  126. data/lib/rubocop/cop/lint/unified_integer.rb +2 -2
  127. data/lib/rubocop/cop/lint/{unneeded_disable.rb → unneeded_cop_disable_directive.rb} +13 -7
  128. data/lib/rubocop/cop/lint/unneeded_cop_enable_directive.rb +97 -0
  129. data/lib/rubocop/cop/lint/unneeded_require_statement.rb +1 -0
  130. data/lib/rubocop/cop/lint/unreachable_code.rb +3 -3
  131. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +11 -10
  132. data/lib/rubocop/cop/lint/useless_access_modifier.rb +7 -5
  133. data/lib/rubocop/cop/lint/useless_assignment.rb +2 -2
  134. data/lib/rubocop/cop/lint/useless_setter_call.rb +2 -2
  135. data/lib/rubocop/cop/lint/void.rb +49 -10
  136. data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
  137. data/lib/rubocop/cop/metrics/line_length.rb +5 -2
  138. data/lib/rubocop/cop/mixin/alignment.rb +4 -0
  139. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +1 -1
  140. data/lib/rubocop/cop/mixin/def_node.rb +4 -0
  141. data/lib/rubocop/cop/mixin/documentation_comment.rb +11 -3
  142. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +12 -2
  143. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +20 -1
  144. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +4 -0
  145. data/lib/rubocop/cop/mixin/hash_alignment.rb +2 -2
  146. data/lib/rubocop/cop/mixin/match_range.rb +2 -0
  147. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +6 -0
  148. data/lib/rubocop/cop/mixin/nil_methods.rb +19 -0
  149. data/lib/rubocop/cop/mixin/percent_literal.rb +57 -9
  150. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +6 -5
  151. data/lib/rubocop/cop/mixin/range_help.rb +102 -0
  152. data/lib/rubocop/cop/mixin/rescue_node.rb +1 -1
  153. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +8 -7
  154. data/lib/rubocop/cop/mixin/space_before_punctuation.rb +11 -9
  155. data/lib/rubocop/cop/mixin/statement_modifier.rb +3 -10
  156. data/lib/rubocop/cop/mixin/surrounding_space.rb +38 -8
  157. data/lib/rubocop/cop/mixin/trailing_body.rb +26 -0
  158. data/lib/rubocop/cop/mixin/trailing_comma.rb +15 -3
  159. data/lib/rubocop/cop/mixin/uncommunicative_name.rb +104 -0
  160. data/lib/rubocop/cop/naming/ascii_identifiers.rb +3 -1
  161. data/lib/rubocop/cop/naming/file_name.rb +5 -10
  162. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +76 -0
  163. data/lib/rubocop/cop/naming/uncommunicative_block_param_name.rb +48 -0
  164. data/lib/rubocop/cop/naming/uncommunicative_method_param_name.rb +57 -0
  165. data/lib/rubocop/cop/offense.rb +3 -2
  166. data/lib/rubocop/cop/performance/case_when_splat.rb +1 -0
  167. data/lib/rubocop/cop/performance/casecmp.rb +17 -8
  168. data/lib/rubocop/cop/performance/compare_with_block.rb +2 -0
  169. data/lib/rubocop/cop/performance/count.rb +1 -0
  170. data/lib/rubocop/cop/performance/fixed_size.rb +41 -0
  171. data/lib/rubocop/cop/performance/flat_map.rb +2 -0
  172. data/lib/rubocop/cop/performance/lstrip_rstrip.rb +2 -0
  173. data/lib/rubocop/cop/performance/redundant_merge.rb +1 -1
  174. data/lib/rubocop/cop/performance/redundant_sort_by.rb +2 -0
  175. data/lib/rubocop/cop/performance/regexp_match.rb +4 -0
  176. data/lib/rubocop/cop/performance/reverse_each.rb +2 -0
  177. data/lib/rubocop/cop/performance/string_replacement.rb +2 -0
  178. data/lib/rubocop/cop/rails/active_record_aliases.rb +46 -0
  179. data/lib/rubocop/cop/rails/blank.rb +3 -3
  180. data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +6 -0
  181. data/lib/rubocop/cop/rails/delegate.rb +6 -6
  182. data/lib/rubocop/cop/rails/file_path.rb +7 -1
  183. data/lib/rubocop/cop/rails/find_by.rb +2 -0
  184. data/lib/rubocop/cop/rails/http_positional_arguments.rb +17 -5
  185. data/lib/rubocop/cop/rails/inverse_of.rb +21 -2
  186. data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +45 -9
  187. data/lib/rubocop/cop/rails/presence.rb +8 -2
  188. data/lib/rubocop/cop/rails/present.rb +5 -5
  189. data/lib/rubocop/cop/rails/read_write_attribute.rb +4 -3
  190. data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +1 -0
  191. data/lib/rubocop/cop/rails/relative_date_constant.rb +4 -3
  192. data/lib/rubocop/cop/rails/request_referer.rb +3 -2
  193. data/lib/rubocop/cop/rails/reversible_migration.rb +9 -8
  194. data/lib/rubocop/cop/rails/safe_navigation.rb +3 -2
  195. data/lib/rubocop/cop/rails/save_bang.rb +11 -12
  196. data/lib/rubocop/cop/rails/skips_model_validations.rb +2 -2
  197. data/lib/rubocop/cop/rails/time_zone.rb +38 -16
  198. data/lib/rubocop/cop/rails/uniq_before_pluck.rb +26 -16
  199. data/lib/rubocop/cop/rails/validation.rb +30 -2
  200. data/lib/rubocop/cop/security/open.rb +48 -0
  201. data/lib/rubocop/cop/style/and_or.rb +1 -0
  202. data/lib/rubocop/cop/style/ascii_comments.rb +3 -1
  203. data/lib/rubocop/cop/style/attr.rb +2 -0
  204. data/lib/rubocop/cop/style/block_comments.rb +3 -1
  205. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +2 -5
  206. data/lib/rubocop/cop/style/class_and_module_children.rb +1 -0
  207. data/lib/rubocop/cop/style/class_vars.rb +23 -0
  208. data/lib/rubocop/cop/style/colon_method_call.rb +1 -2
  209. data/lib/rubocop/cop/style/comment_annotation.rb +6 -4
  210. data/lib/rubocop/cop/style/commented_keyword.rb +3 -1
  211. data/lib/rubocop/cop/style/conditional_assignment.rb +1 -1
  212. data/lib/rubocop/cop/style/copyright.rb +3 -1
  213. data/lib/rubocop/cop/style/each_with_object.rb +15 -1
  214. data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -0
  215. data/lib/rubocop/cop/style/empty_case_condition.rb +2 -0
  216. data/lib/rubocop/cop/style/empty_else.rb +9 -5
  217. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -0
  218. data/lib/rubocop/cop/style/empty_line_after_guard_clause.rb +80 -0
  219. data/lib/rubocop/cop/style/empty_literal.rb +1 -0
  220. data/lib/rubocop/cop/style/encoding.rb +2 -0
  221. data/lib/rubocop/cop/style/expand_path_arguments.rb +194 -0
  222. data/lib/rubocop/cop/style/for.rb +33 -0
  223. data/lib/rubocop/cop/style/format_string.rb +1 -1
  224. data/lib/rubocop/cop/style/format_string_token.rb +4 -5
  225. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +2 -1
  226. data/lib/rubocop/cop/style/hash_syntax.rb +1 -0
  227. data/lib/rubocop/cop/style/if_unless_modifier.rb +1 -1
  228. data/lib/rubocop/cop/style/inline_comment.rb +1 -1
  229. data/lib/rubocop/cop/style/lambda.rb +1 -1
  230. data/lib/rubocop/cop/style/line_end_concatenation.rb +2 -0
  231. data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -0
  232. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -0
  233. data/lib/rubocop/cop/style/missing_else.rb +72 -7
  234. data/lib/rubocop/cop/style/mixin_usage.rb +3 -5
  235. data/lib/rubocop/cop/style/module_function.rb +10 -0
  236. data/lib/rubocop/cop/style/multiline_block_chain.rb +2 -0
  237. data/lib/rubocop/cop/style/multiline_if_then.rb +1 -0
  238. data/lib/rubocop/cop/style/nested_modifier.rb +2 -0
  239. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +2 -0
  240. data/lib/rubocop/cop/style/next.rb +1 -0
  241. data/lib/rubocop/cop/style/not.rb +2 -0
  242. data/lib/rubocop/cop/style/numeric_literals.rb +1 -1
  243. data/lib/rubocop/cop/style/one_line_conditional.rb +2 -2
  244. data/lib/rubocop/cop/style/redundant_exception.rb +8 -3
  245. data/lib/rubocop/cop/style/redundant_return.rb +37 -3
  246. data/lib/rubocop/cop/style/redundant_self.rb +1 -1
  247. data/lib/rubocop/cop/style/rescue_standard_error.rb +1 -0
  248. data/lib/rubocop/cop/style/safe_navigation.rb +74 -32
  249. data/lib/rubocop/cop/style/semicolon.rb +3 -1
  250. data/lib/rubocop/cop/style/single_line_methods.rb +14 -23
  251. data/lib/rubocop/cop/style/stderr_puts.rb +2 -0
  252. data/lib/rubocop/cop/style/string_hash_keys.rb +12 -0
  253. data/lib/rubocop/cop/style/string_literals.rb +1 -1
  254. data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +1 -1
  255. data/lib/rubocop/cop/style/symbol_array.rb +29 -0
  256. data/lib/rubocop/cop/style/symbol_proc.rb +2 -0
  257. data/lib/rubocop/cop/style/trailing_body_on_class.rb +43 -0
  258. data/lib/rubocop/cop/style/trailing_body_on_method_definition.rb +7 -54
  259. data/lib/rubocop/cop/style/trailing_body_on_module.rb +43 -0
  260. data/lib/rubocop/cop/style/{trailing_comma_in_literal.rb → trailing_comma_in_array_literal.rb} +2 -20
  261. data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +56 -0
  262. data/lib/rubocop/cop/style/trailing_method_end_statement.rb +17 -20
  263. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +1 -0
  264. data/lib/rubocop/cop/style/unless_else.rb +2 -0
  265. data/lib/rubocop/cop/style/word_array.rb +0 -1
  266. data/lib/rubocop/cop/style/yoda_condition.rb +1 -0
  267. data/lib/rubocop/cop/team.rb +5 -5
  268. data/lib/rubocop/cop/util.rb +23 -188
  269. data/lib/rubocop/cop/variable_force.rb +1 -1
  270. data/lib/rubocop/file_finder.rb +45 -0
  271. data/lib/rubocop/formatter/disabled_config_formatter.rb +23 -14
  272. data/lib/rubocop/formatter/fuubar_style_formatter.rb +1 -1
  273. data/lib/rubocop/formatter/html_formatter.rb +12 -5
  274. data/lib/rubocop/formatter/json_formatter.rb +1 -1
  275. data/lib/rubocop/node_pattern.rb +8 -5
  276. data/lib/rubocop/options.rb +40 -33
  277. data/lib/rubocop/path_util.rb +5 -8
  278. data/lib/rubocop/processed_source.rb +53 -0
  279. data/lib/rubocop/remote_config.rb +1 -1
  280. data/lib/rubocop/result_cache.rb +1 -1
  281. data/lib/rubocop/rspec/cop_helper.rb +0 -4
  282. data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -4
  283. data/lib/rubocop/rspec/shared_contexts.rb +3 -1
  284. data/lib/rubocop/rspec/shared_examples.rb +23 -25
  285. data/lib/rubocop/rspec/support.rb +5 -0
  286. data/lib/rubocop/runner.rb +3 -2
  287. data/lib/rubocop/string_util.rb +10 -9
  288. data/lib/rubocop/target_finder.rb +4 -1
  289. data/lib/rubocop/token.rb +26 -16
  290. data/lib/rubocop/version.rb +6 -4
  291. metadata +31 -17
  292. data/lib/rubocop/cop/performance/hash_each_methods.rb +0 -129
@@ -25,7 +25,7 @@ module RuboCop
25
25
  # x
26
26
  # end
27
27
  class UselessSetterCall < Cop
28
- MSG = 'Useless setter call to local variable `%s`.'.freeze
28
+ MSG = 'Useless setter call to local variable `%<variable>s`.'.freeze
29
29
  ASSIGNMENT_TYPES = %i[lvasgn ivasgn cvasgn gvasgn].freeze
30
30
 
31
31
  def on_def(node)
@@ -42,7 +42,7 @@ module RuboCop
42
42
  add_offense(
43
43
  receiver,
44
44
  location: :name,
45
- message: format(MSG, receiver.loc.name.source)
45
+ message: format(MSG, variable: receiver.loc.name.source)
46
46
  )
47
47
  end
48
48
  alias on_defs on_def
@@ -3,8 +3,8 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # This cop checks for operators, variables and literals used
7
- # in void context.
6
+ # This cop checks for operators, variables, literals, and nonmutating
7
+ # methods used in void context.
8
8
  #
9
9
  # @example
10
10
  #
@@ -26,6 +26,15 @@ module RuboCop
26
26
  #
27
27
  # @example
28
28
  #
29
+ # # bad, when CheckForMethodsWithNoSideEffects is set true
30
+ #
31
+ # def some_method(some_array)
32
+ # some_array.sort
33
+ # do_something(some_array)
34
+ # end
35
+ #
36
+ # @example
37
+ #
29
38
  # # good
30
39
  #
31
40
  # def some_method
@@ -41,17 +50,34 @@ module RuboCop
41
50
  # do_something
42
51
  # some_var
43
52
  # end
53
+ #
54
+ # @example
55
+ #
56
+ # # good, when CheckForMethodsWithNoSideEffects is set true
57
+ #
58
+ # def some_method(some_array)
59
+ # some_array.sort!
60
+ # do_something(some_array)
61
+ # end
44
62
  class Void < Cop
45
- OP_MSG = 'Operator `%s` used in void context.'.freeze
46
- VAR_MSG = 'Variable `%s` used in void context.'.freeze
47
- LIT_MSG = 'Literal `%s` used in void context.'.freeze
63
+ OP_MSG = 'Operator `%<op>s` used in void context.'.freeze
64
+ VAR_MSG = 'Variable `%<var>s` used in void context.'.freeze
65
+ LIT_MSG = 'Literal `%<lit>s` used in void context.'.freeze
48
66
  SELF_MSG = '`self` used in void context.'.freeze
49
- DEFINED_MSG = '`%s` used in void context.'.freeze
67
+ DEFINED_MSG = '`%<defined>s` used in void context.'.freeze
68
+ NONMUTATING_MSG = 'Method `#%<method>s` used in void context. ' \
69
+ 'Did you mean `#%<method>s!`?'.freeze
50
70
 
51
71
  BINARY_OPERATORS = %i[* / % + - == === != < > <= >= <=>].freeze
52
72
  UNARY_OPERATORS = %i[+@ -@ ~ !].freeze
53
73
  OPERATORS = (BINARY_OPERATORS + UNARY_OPERATORS).freeze
54
74
  VOID_CONTEXT_TYPES = %i[def for block].freeze
75
+ NONMUTATING_METHODS = %i[capitalize chomp chop collect compact downcase
76
+ encode flatten gsub lstrip map next reject
77
+ reverse rotate rstrip scrub select shuffle
78
+ slice sort sort_by squeeze strip sub succ
79
+ swapcase tr tr_s transform_values
80
+ unicode_normalize uniq upcase].freeze
55
81
 
56
82
  def on_begin(node)
57
83
  check_begin(node)
@@ -69,6 +95,9 @@ module RuboCop
69
95
  check_var(expr)
70
96
  check_self(expr)
71
97
  check_defined(expr)
98
+ if cop_config['CheckForMethodsWithNoSideEffects']
99
+ check_nonmutating(expr)
100
+ end
72
101
  end
73
102
  end
74
103
 
@@ -77,7 +106,7 @@ module RuboCop
77
106
 
78
107
  add_offense(node,
79
108
  location: :selector,
80
- message: format(OP_MSG, node.method_name))
109
+ message: format(OP_MSG, op: node.method_name))
81
110
  end
82
111
 
83
112
  def check_var(node)
@@ -85,13 +114,13 @@ module RuboCop
85
114
 
86
115
  add_offense(node,
87
116
  location: :name,
88
- message: format(VAR_MSG, node.loc.name.source))
117
+ message: format(VAR_MSG, var: node.loc.name.source))
89
118
  end
90
119
 
91
120
  def check_literal(node)
92
121
  return if !node.literal? || node.xstr_type?
93
122
 
94
- add_offense(node, message: format(LIT_MSG, node.source))
123
+ add_offense(node, message: format(LIT_MSG, lit: node.source))
95
124
  end
96
125
 
97
126
  def check_self(node)
@@ -103,7 +132,17 @@ module RuboCop
103
132
  def check_defined(node)
104
133
  return unless node.defined_type?
105
134
 
106
- add_offense(node, message: format(DEFINED_MSG, node.source))
135
+ add_offense(node, message: format(DEFINED_MSG, defined: node.source))
136
+ end
137
+
138
+ def check_nonmutating(node)
139
+ unless node.send_type? &&
140
+ NONMUTATING_METHODS.include?(node.method_name)
141
+ return
142
+ end
143
+
144
+ add_offense(node, message: format(NONMUTATING_MSG,
145
+ method: node.method_name))
107
146
  end
108
147
 
109
148
  def in_void_context?(node)
@@ -20,7 +20,7 @@ module RuboCop
20
20
  ].freeze
21
21
 
22
22
  def investigate(processed_source)
23
- return unless processed_source.ast
23
+ return if processed_source.blank?
24
24
  max = cop_config['Max']
25
25
  check_nesting_level(processed_source.ast, max, 0)
26
26
  end
@@ -10,6 +10,7 @@ module RuboCop
10
10
  class LineLength < Cop
11
11
  include ConfigurableMax
12
12
  include IgnoredPattern
13
+ include RangeHelp
13
14
 
14
15
  MSG = 'Line is too long. [%<length>d/%<max>d]'.freeze
15
16
 
@@ -99,7 +100,8 @@ module RuboCop
99
100
  end
100
101
 
101
102
  def allowed_uri_position?(line, uri_range)
102
- uri_range.begin < max && uri_range.end == line.length
103
+ uri_range.begin < max &&
104
+ (uri_range.end == line.length || uri_range.end == line.length - 1)
103
105
  end
104
106
 
105
107
  def find_excessive_uri_range(line)
@@ -126,7 +128,8 @@ module RuboCop
126
128
  end
127
129
 
128
130
  def uri_regexp
129
- @regexp ||= URI::DEFAULT_PARSER.make_regexp(cop_config['URISchemes'])
131
+ @uri_regexp ||=
132
+ URI::DEFAULT_PARSER.make_regexp(cop_config['URISchemes'])
130
133
  end
131
134
 
132
135
  def check_directive_line(line, index)
@@ -65,6 +65,10 @@ module RuboCop
65
65
  def within?(inner, outer)
66
66
  inner.begin_pos >= outer.begin_pos && inner.end_pos <= outer.end_pos
67
67
  end
68
+
69
+ def end_of_line_comment(line)
70
+ processed_source.find_comment { |c| c.loc.line == line }
71
+ end
68
72
  end
69
73
  end
70
74
  end
@@ -61,7 +61,7 @@ module RuboCop
61
61
  alias unrecognized_style_detected no_acceptable_style!
62
62
 
63
63
  def style
64
- @enforced_style ||= begin
64
+ @style ||= begin
65
65
  s = cop_config[style_parameter_name].to_sym
66
66
  unless supported_styles.include?(s)
67
67
  raise "Unknown style #{s} selected!"
@@ -21,6 +21,10 @@ module RuboCop
21
21
  end
22
22
  end
23
23
 
24
+ def stripped_source_upto(index)
25
+ processed_source[0..index].map(&:strip)
26
+ end
27
+
24
28
  def_node_matcher :non_public_modifier?, <<-PATTERN
25
29
  (send nil? {:private :protected} ({def defs} ...))
26
30
  PATTERN
@@ -23,9 +23,17 @@ module RuboCop
23
23
  end
24
24
  end
25
25
 
26
- def preceding_comment?(n1, n2)
27
- n1 && n2 && precede?(n2, n1) &&
28
- comment_line?(n2.loc.expression.source)
26
+ # The args node1 & node2 may represent a RuboCop::AST::Node
27
+ # or a Parser::Source::Comment. Both respond to #loc.
28
+ def preceding_comment?(node1, node2)
29
+ node1 && node2 && precede?(node2, node1) &&
30
+ comment_line?(node2.loc.expression.source)
31
+ end
32
+
33
+ # The args node1 & node2 may represent a RuboCop::AST::Node
34
+ # or a Parser::Source::Comment. Both respond to #loc.
35
+ def precede?(node1, node2)
36
+ node2.loc.line - node1.loc.line == 1
29
37
  end
30
38
 
31
39
  def preceding_lines(node)
@@ -8,6 +8,7 @@ module RuboCop
8
8
  module EmptyLinesAroundBody
9
9
  extend NodePattern::Macros
10
10
  include ConfigurableEnforcedStyle
11
+ include RangeHelp
11
12
 
12
13
  MSG_EXTRA = 'Extra empty line detected at %<kind>s body ' \
13
14
  '%<location>s.'.freeze
@@ -64,8 +65,17 @@ module RuboCop
64
65
  end
65
66
 
66
67
  def check_both(style, first_line, last_line)
67
- check_beginning(style, first_line)
68
- check_ending(style, last_line)
68
+ case style
69
+ when :beginning_only
70
+ check_beginning(:empty_lines, first_line)
71
+ check_ending(:no_empty_lines, last_line)
72
+ when :ending_only
73
+ check_beginning(:no_empty_lines, first_line)
74
+ check_ending(:empty_lines, last_line)
75
+ else
76
+ check_beginning(style, first_line)
77
+ check_ending(style, last_line)
78
+ end
69
79
  end
70
80
 
71
81
  def check_beginning(style, first_line)
@@ -6,6 +6,8 @@ module RuboCop
6
6
  module EndKeywordAlignment
7
7
  include ConfigurableEnforcedStyle
8
8
 
9
+ BYTE_ORDER_MARK = 0xfeff # The Unicode codepoint
10
+
9
11
  MSG = '`end` at %<end_line>d, %<end_col>d is not aligned with ' \
10
12
  '`%<source>s` at %<align_line>d, %<align_col>d.'.freeze
11
13
 
@@ -53,13 +55,30 @@ module RuboCop
53
55
  end
54
56
 
55
57
  def variable_alignment?(whole_expression, rhs, end_alignment_style)
56
- end_alignment_style == :variable &&
58
+ case end_alignment_style
59
+ when :variable
57
60
  !line_break_before_keyword?(whole_expression, rhs)
61
+ when :start_of_line
62
+ true
63
+ end
58
64
  end
59
65
 
60
66
  def line_break_before_keyword?(whole_expression, rhs)
61
67
  rhs.first_line > whole_expression.line
62
68
  end
69
+
70
+ # Returns the column attribute of the range, except if the range is on
71
+ # the first line and there's a byte order mark at the beginning of that
72
+ # line, in which case 1 is subtracted from the column value. This gives
73
+ # the column as it appears when viewing the file in an editor.
74
+ def effective_column(range)
75
+ if range.line == 1 &&
76
+ @processed_source.raw_source.codepoints.first == BYTE_ORDER_MARK
77
+ range.column - 1
78
+ else
79
+ range.column
80
+ end
81
+ end
63
82
  end
64
83
  end
65
84
  end
@@ -21,6 +21,10 @@ module RuboCop
21
21
  def frozen_string_literals_enabled?
22
22
  ruby_version = processed_source.ruby_version
23
23
  return false unless ruby_version
24
+ # TODO: Whether frozen string literals will be the default in Ruby 3.0
25
+ # or not is still unclear as of February 2018.
26
+ # It may be necessary to change this code in the future.
27
+ # See https://bugs.ruby-lang.org/issues/8976#note-41 for details.
24
28
  return true if ruby_version >= 3.0
25
29
  return false unless ruby_version >= 2.3
26
30
 
@@ -10,7 +10,7 @@ module RuboCop
10
10
  true
11
11
  end
12
12
 
13
- def deltas_for_first_pair(*)
13
+ def deltas_for_first_pair(*_nodes)
14
14
  {}
15
15
  end
16
16
 
@@ -93,7 +93,7 @@ module RuboCop
93
93
  class SeparatorAlignment
94
94
  include ValueAlignment
95
95
 
96
- def deltas_for_first_pair(*)
96
+ def deltas_for_first_pair(*_nodes)
97
97
  {}
98
98
  end
99
99
 
@@ -4,6 +4,8 @@ module RuboCop
4
4
  module Cop
5
5
  # Common functionality for obtaining source ranges from regexp matches
6
6
  module MatchRange
7
+ include RangeHelp
8
+
7
9
  private
8
10
 
9
11
  # Return a new `Range` covering the first matching group number for each
@@ -221,6 +221,12 @@ module RuboCop
221
221
  node.source_range.begin_pos > ancestor.loc.begin.begin_pos &&
222
222
  node.source_range.end_pos < ancestor.loc.end.end_pos
223
223
  end
224
+
225
+ def within_node?(inner, outer)
226
+ o = outer.is_a?(AST::Node) ? outer.source_range : outer
227
+ i = inner.is_a?(AST::Node) ? inner.source_range : inner
228
+ i.begin_pos >= o.begin_pos && i.end_pos <= o.end_pos
229
+ end
224
230
  end
225
231
  end
226
232
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # This module provides a list of methods that are either in the NilClass,
6
+ # or in the cop's configuration parameter Whitelist.
7
+ module NilMethods
8
+ private
9
+
10
+ def nil_methods
11
+ nil.methods + whitelist
12
+ end
13
+
14
+ def whitelist
15
+ cop_config['Whitelist'].map(&:to_sym)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -4,6 +4,8 @@ module RuboCop
4
4
  module Cop
5
5
  # Common functionality for handling percent literals.
6
6
  module PercentLiteral
7
+ include RangeHelp
8
+
7
9
  PERCENT_LITERAL_TYPES = %w[% %i %I %q %Q %r %s %w %W %x].freeze
8
10
 
9
11
  private
@@ -38,7 +40,7 @@ module RuboCop
38
40
  escape = words.any? { |w| needs_escaping?(w.children[0]) }
39
41
  char = char.upcase if escape
40
42
  delimiters = preferred_delimiters_for("%#{char}")
41
- contents = autocorrect_words(words, escape, node.first_line, delimiters)
43
+ contents = new_contents(node, escape, delimiters)
42
44
 
43
45
  lambda do |corrector|
44
46
  corrector.replace(
@@ -48,21 +50,67 @@ module RuboCop
48
50
  end
49
51
  end
50
52
 
51
- def autocorrect_words(word_nodes, escape, base_line_number, delimiters)
52
- previous_node_line_number = base_line_number
53
- word_nodes.map do |node|
54
- number_of_line_breaks = node.first_line - previous_node_line_number
55
- line_breaks = "\n" * number_of_line_breaks
56
- previous_node_line_number = node.first_line
57
- content = node.children.first.to_s
53
+ def new_contents(node, escape, delimiters)
54
+ if node.multiline?
55
+ autocorrect_multiline_words(node, escape, delimiters)
56
+ else
57
+ autocorrect_words(node, escape, delimiters)
58
+ end
59
+ end
60
+
61
+ def autocorrect_multiline_words(node, escape, delimiters)
62
+ base_line_number = node.first_line
63
+ previous_line_number = base_line_number
64
+ contents = node.children.map do |word_node|
65
+ line_breaks = line_breaks(word_node,
66
+ node.source,
67
+ previous_line_number,
68
+ base_line_number)
69
+ previous_line_number = word_node.first_line
70
+ content = escaped_content(word_node, escape, delimiters)
71
+ line_breaks + content
72
+ end
73
+ contents << end_content(node.source)
74
+ contents.join('')
75
+ end
76
+
77
+ def autocorrect_words(node, escape, delimiters)
78
+ node.children.map do |word_node|
79
+ content = word_node.children.first.to_s
58
80
  content = escape ? escape_string(content) : content
59
81
  delimiters.each do |delimiter|
60
82
  content.gsub!(delimiter, "\\#{delimiter}")
61
83
  end
62
- line_breaks + content
84
+ content
63
85
  end.join(' ')
64
86
  end
65
87
 
88
+ def line_breaks(node, source, previous_line_number, base_line_number)
89
+ source_in_lines = source.split("\n")
90
+ if node.first_line == previous_line_number
91
+ node.first_line == base_line_number ? '' : ' '
92
+ else
93
+ begin_line_number = previous_line_number - base_line_number + 1
94
+ end_line_number = node.first_line - base_line_number + 1
95
+ lines = source_in_lines[begin_line_number...end_line_number]
96
+ "\n" + lines.join("\n").split(node.source).first
97
+ end
98
+ end
99
+
100
+ def escaped_content(word_node, escape, delimiters)
101
+ content = word_node.children.first.to_s
102
+ content = escape_string(content) if escape
103
+ delimiters.each do |delimiter|
104
+ content.gsub!(delimiter, "\\#{delimiter}")
105
+ end
106
+ content
107
+ end
108
+
109
+ def end_content(source)
110
+ result = /\A(\s*)\]/.match(source.split("\n").last)
111
+ ("\n" + result[1]) if result
112
+ end
113
+
66
114
  def ensure_valid_preferred_delimiters
67
115
  invalid = preferred_delimiters_config.keys -
68
116
  (PERCENT_LITERAL_TYPES + %w[default])