rubocop 0.49.1 → 0.50.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/README.md +5 -3
  3. data/bin/rubocop +1 -1
  4. data/config/default.yml +160 -99
  5. data/config/disabled.yml +4 -5
  6. data/config/enabled.yml +149 -47
  7. data/lib/rubocop.rb +41 -14
  8. data/lib/rubocop/ast/builder.rb +4 -1
  9. data/lib/rubocop/ast/node.rb +36 -42
  10. data/lib/rubocop/ast/node/args_node.rb +1 -13
  11. data/lib/rubocop/ast/node/array_node.rb +9 -0
  12. data/lib/rubocop/ast/node/block_node.rb +9 -0
  13. data/lib/rubocop/ast/node/def_node.rb +71 -0
  14. data/lib/rubocop/ast/node/for_node.rb +8 -0
  15. data/lib/rubocop/ast/node/if_node.rb +10 -2
  16. data/lib/rubocop/ast/node/mixin/collection_node.rb +15 -0
  17. data/lib/rubocop/ast/node/mixin/method_dispatch_node.rb +174 -0
  18. data/lib/rubocop/ast/node/mixin/method_identifier_predicates.rb +89 -0
  19. data/lib/rubocop/ast/node/mixin/parameterized_node.rb +18 -31
  20. data/lib/rubocop/ast/node/regexp_node.rb +35 -0
  21. data/lib/rubocop/ast/node/send_node.rb +1 -154
  22. data/lib/rubocop/ast/node/super_node.rb +3 -24
  23. data/lib/rubocop/ast/node/yield_node.rb +21 -0
  24. data/lib/rubocop/ast/traversal.rb +6 -6
  25. data/lib/rubocop/cli.rb +7 -3
  26. data/lib/rubocop/config.rb +45 -8
  27. data/lib/rubocop/config_loader.rb +7 -5
  28. data/lib/rubocop/cop/bundler/duplicated_gem.rb +3 -3
  29. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +64 -0
  30. data/lib/rubocop/cop/bundler/ordered_gems.rb +12 -12
  31. data/lib/rubocop/cop/commissioner.rb +8 -2
  32. data/lib/rubocop/cop/cop.rb +3 -1
  33. data/lib/rubocop/cop/generator.rb +94 -21
  34. data/lib/rubocop/cop/internal_affairs.rb +3 -0
  35. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +14 -3
  36. data/lib/rubocop/cop/internal_affairs/offense_location_keyword.rb +43 -0
  37. data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +46 -0
  38. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +49 -0
  39. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +1 -1
  40. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +2 -3
  41. data/lib/rubocop/cop/layout/align_array.rb +2 -2
  42. data/lib/rubocop/cop/layout/align_hash.rb +2 -2
  43. data/lib/rubocop/cop/layout/align_parameters.rb +5 -11
  44. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +5 -5
  45. data/lib/rubocop/cop/layout/comment_indentation.rb +1 -1
  46. data/lib/rubocop/cop/layout/dot_position.rb +9 -0
  47. data/lib/rubocop/cop/layout/else_alignment.rb +30 -13
  48. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +4 -0
  49. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +20 -4
  50. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +3 -3
  51. data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +3 -3
  52. data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +3 -3
  53. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +5 -2
  54. data/lib/rubocop/cop/layout/indent_heredoc.rb +19 -24
  55. data/lib/rubocop/cop/layout/indentation_consistency.rb +1 -2
  56. data/lib/rubocop/cop/layout/indentation_width.rb +12 -8
  57. data/lib/rubocop/cop/layout/leading_comment_space.rb +33 -18
  58. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +20 -17
  59. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +3 -3
  60. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +6 -0
  61. data/lib/rubocop/cop/layout/space_after_colon.rb +7 -0
  62. data/lib/rubocop/cop/layout/space_after_comma.rb +10 -0
  63. data/lib/rubocop/cop/layout/space_after_method_name.rb +5 -3
  64. data/lib/rubocop/cop/layout/space_after_not.rb +1 -1
  65. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +13 -4
  66. data/lib/rubocop/cop/layout/space_around_keyword.rb +9 -5
  67. data/lib/rubocop/cop/layout/space_before_block_braces.rb +54 -5
  68. data/lib/rubocop/cop/layout/space_before_comment.rb +7 -0
  69. data/lib/rubocop/cop/layout/space_before_semicolon.rb +7 -0
  70. data/lib/rubocop/cop/layout/space_inside_array_percent_literal.rb +1 -1
  71. data/lib/rubocop/cop/layout/space_inside_percent_literal_delimiters.rb +1 -1
  72. data/lib/rubocop/cop/layout/space_inside_range_literal.rb +1 -1
  73. data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +8 -4
  74. data/lib/rubocop/cop/layout/tab.rb +1 -1
  75. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +4 -2
  76. data/lib/rubocop/cop/lint/assignment_in_condition.rb +15 -1
  77. data/lib/rubocop/cop/lint/block_alignment.rb +15 -6
  78. data/lib/rubocop/cop/lint/boolean_symbol.rb +38 -0
  79. data/lib/rubocop/cop/lint/condition_position.rb +5 -1
  80. data/lib/rubocop/cop/lint/debugger.rb +16 -9
  81. data/lib/rubocop/cop/lint/def_end_alignment.rb +4 -4
  82. data/lib/rubocop/cop/lint/duplicate_case_condition.rb +3 -3
  83. data/lib/rubocop/cop/lint/duplicate_methods.rb +73 -5
  84. data/lib/rubocop/cop/lint/duplicated_key.rb +1 -1
  85. data/lib/rubocop/cop/lint/each_with_object_argument.rb +1 -1
  86. data/lib/rubocop/cop/lint/else_layout.rb +1 -1
  87. data/lib/rubocop/cop/lint/empty_expression.rb +1 -1
  88. data/lib/rubocop/cop/lint/empty_interpolation.rb +1 -1
  89. data/lib/rubocop/cop/lint/empty_when.rb +1 -1
  90. data/lib/rubocop/cop/lint/ensure_return.rb +1 -1
  91. data/lib/rubocop/cop/lint/float_out_of_range.rb +5 -5
  92. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +35 -40
  93. data/lib/rubocop/cop/lint/handle_exceptions.rb +1 -1
  94. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +18 -13
  95. data/lib/rubocop/cop/lint/inherit_exception.rb +8 -7
  96. data/lib/rubocop/cop/lint/interpolation_check.rb +36 -0
  97. data/lib/rubocop/cop/lint/literal_in_condition.rb +3 -3
  98. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
  99. data/lib/rubocop/cop/lint/multiple_compare.rb +1 -1
  100. data/lib/rubocop/cop/lint/nested_method_definition.rb +5 -7
  101. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
  102. data/lib/rubocop/cop/lint/percent_string_array.rb +3 -12
  103. data/lib/rubocop/cop/lint/percent_symbol_array.rb +1 -1
  104. data/lib/rubocop/cop/lint/rand_one.rb +7 -1
  105. data/lib/rubocop/cop/lint/redundant_with_index.rb +77 -0
  106. data/lib/rubocop/cop/lint/require_parentheses.rb +1 -1
  107. data/lib/rubocop/cop/lint/rescue_exception.rb +1 -1
  108. data/lib/rubocop/cop/lint/rescue_type.rb +13 -6
  109. data/lib/rubocop/cop/lint/rescue_without_error_class.rb +38 -0
  110. data/lib/rubocop/cop/lint/return_in_void_context.rb +63 -0
  111. data/lib/rubocop/cop/lint/script_permission.rb +6 -0
  112. data/lib/rubocop/cop/lint/syntax.rb +17 -20
  113. data/lib/rubocop/cop/lint/unified_integer.rb +3 -2
  114. data/lib/rubocop/cop/lint/unneeded_disable.rb +1 -1
  115. data/lib/rubocop/cop/lint/unneeded_splat_expansion.rb +1 -1
  116. data/lib/rubocop/cop/lint/unreachable_code.rb +53 -8
  117. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +74 -0
  118. data/lib/rubocop/cop/lint/uri_regexp.rb +73 -0
  119. data/lib/rubocop/cop/lint/useless_access_modifier.rb +4 -8
  120. data/lib/rubocop/cop/lint/useless_setter_call.rb +10 -11
  121. data/lib/rubocop/cop/lint/void.rb +29 -23
  122. data/lib/rubocop/cop/metrics/line_length.rb +2 -2
  123. data/lib/rubocop/cop/metrics/method_length.rb +8 -3
  124. data/lib/rubocop/cop/metrics/parameter_lists.rb +5 -2
  125. data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +1 -1
  126. data/lib/rubocop/cop/mixin/enforce_superclass.rb +2 -2
  127. data/lib/rubocop/cop/mixin/first_element_line_break.rb +12 -3
  128. data/lib/rubocop/cop/mixin/heredoc.rb +28 -0
  129. data/lib/rubocop/cop/mixin/method_complexity.rb +9 -6
  130. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +68 -31
  131. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +18 -0
  132. data/lib/rubocop/cop/mixin/negative_conditional.rb +1 -1
  133. data/lib/rubocop/cop/mixin/percent_array.rb +52 -0
  134. data/lib/rubocop/cop/mixin/string_help.rb +1 -1
  135. data/lib/rubocop/cop/{style → naming}/accessor_method_name.rb +11 -12
  136. data/lib/rubocop/cop/{style → naming}/ascii_identifiers.rb +1 -1
  137. data/lib/rubocop/cop/{style/op_method.rb → naming/binary_operator_parameter_name.rb} +2 -2
  138. data/lib/rubocop/cop/{style → naming}/class_and_module_camel_case.rb +1 -1
  139. data/lib/rubocop/cop/{style → naming}/constant_name.rb +1 -1
  140. data/lib/rubocop/cop/{style → naming}/file_name.rb +8 -4
  141. data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +68 -0
  142. data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +58 -0
  143. data/lib/rubocop/cop/{style → naming}/method_name.rb +1 -1
  144. data/lib/rubocop/cop/{style → naming}/predicate_name.rb +6 -7
  145. data/lib/rubocop/cop/{style → naming}/variable_name.rb +11 -15
  146. data/lib/rubocop/cop/{style → naming}/variable_number.rb +1 -1
  147. data/lib/rubocop/cop/performance/caller.rb +39 -11
  148. data/lib/rubocop/cop/performance/casecmp.rb +4 -4
  149. data/lib/rubocop/cop/performance/compare_with_block.rb +4 -4
  150. data/lib/rubocop/cop/performance/double_start_end_with.rb +4 -4
  151. data/lib/rubocop/cop/performance/end_with.rb +3 -3
  152. data/lib/rubocop/cop/performance/fixed_size.rb +1 -1
  153. data/lib/rubocop/cop/performance/hash_each_methods.rb +66 -25
  154. data/lib/rubocop/cop/performance/lstrip_rstrip.rb +2 -2
  155. data/lib/rubocop/cop/performance/range_include.rb +2 -2
  156. data/lib/rubocop/cop/performance/redundant_block_call.rb +6 -6
  157. data/lib/rubocop/cop/performance/redundant_match.rb +5 -5
  158. data/lib/rubocop/cop/performance/redundant_merge.rb +39 -23
  159. data/lib/rubocop/cop/performance/redundant_sort_by.rb +2 -2
  160. data/lib/rubocop/cop/performance/regexp_match.rb +13 -5
  161. data/lib/rubocop/cop/performance/size.rb +1 -1
  162. data/lib/rubocop/cop/performance/start_with.rb +3 -3
  163. data/lib/rubocop/cop/performance/times_map.rb +23 -12
  164. data/lib/rubocop/cop/performance/unfreeze_string.rb +50 -0
  165. data/lib/rubocop/cop/performance/uri_default_parser.rb +47 -0
  166. data/lib/rubocop/cop/rails/active_support_aliases.rb +1 -1
  167. data/lib/rubocop/cop/rails/delegate.rb +36 -7
  168. data/lib/rubocop/cop/rails/delegate_allow_blank.rb +1 -1
  169. data/lib/rubocop/cop/rails/enum_uniqueness.rb +2 -2
  170. data/lib/rubocop/cop/rails/file_path.rb +3 -4
  171. data/lib/rubocop/cop/rails/find_each.rb +1 -1
  172. data/lib/rubocop/cop/rails/has_many_or_has_one_dependent.rb +48 -0
  173. data/lib/rubocop/cop/rails/http_positional_arguments.rb +5 -5
  174. data/lib/rubocop/cop/rails/not_null_column.rb +1 -1
  175. data/lib/rubocop/cop/rails/pluralization_grammar.rb +2 -2
  176. data/lib/rubocop/cop/rails/relative_date_constant.rb +1 -1
  177. data/lib/rubocop/cop/rails/request_referer.rb +2 -2
  178. data/lib/rubocop/cop/rails/reversible_migration.rb +12 -12
  179. data/lib/rubocop/cop/rails/save_bang.rb +8 -6
  180. data/lib/rubocop/cop/rails/scope_args.rb +1 -1
  181. data/lib/rubocop/cop/security/eval.rb +2 -2
  182. data/lib/rubocop/cop/security/json_load.rb +2 -2
  183. data/lib/rubocop/cop/security/marshal_load.rb +2 -2
  184. data/lib/rubocop/cop/security/yaml_load.rb +2 -2
  185. data/lib/rubocop/cop/style/alias.rb +44 -20
  186. data/lib/rubocop/cop/style/and_or.rb +48 -34
  187. data/lib/rubocop/cop/style/auto_resource_cleanup.rb +1 -1
  188. data/lib/rubocop/cop/style/block_comments.rb +3 -1
  189. data/lib/rubocop/cop/style/block_delimiters.rb +2 -1
  190. data/lib/rubocop/cop/style/command_literal.rb +20 -9
  191. data/lib/rubocop/cop/style/conditional_assignment.rb +30 -28
  192. data/lib/rubocop/cop/style/copyright.rb +10 -10
  193. data/lib/rubocop/cop/style/def_with_parentheses.rb +6 -5
  194. data/lib/rubocop/cop/style/dir.rb +52 -0
  195. data/lib/rubocop/cop/style/documentation_method.rb +2 -6
  196. data/lib/rubocop/cop/style/empty_case_condition.rb +1 -1
  197. data/lib/rubocop/cop/style/empty_else.rb +3 -2
  198. data/lib/rubocop/cop/style/empty_literal.rb +1 -2
  199. data/lib/rubocop/cop/style/empty_method.rb +27 -17
  200. data/lib/rubocop/cop/style/flip_flop.rb +2 -2
  201. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
  202. data/lib/rubocop/cop/style/guard_clause.rb +4 -2
  203. data/lib/rubocop/cop/style/hash_syntax.rb +10 -10
  204. data/lib/rubocop/cop/style/identical_conditional_branches.rb +5 -1
  205. data/lib/rubocop/cop/style/if_with_semicolon.rb +1 -1
  206. data/lib/rubocop/cop/style/implicit_runtime_error.rb +4 -3
  207. data/lib/rubocop/cop/style/inline_comment.rb +1 -1
  208. data/lib/rubocop/cop/style/inverse_methods.rb +20 -8
  209. data/lib/rubocop/cop/style/lambda.rb +19 -9
  210. data/lib/rubocop/cop/style/lambda_call.rb +22 -1
  211. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +4 -20
  212. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +6 -4
  213. data/lib/rubocop/cop/style/method_def_parentheses.rb +18 -26
  214. data/lib/rubocop/cop/style/method_missing.rb +5 -18
  215. data/lib/rubocop/cop/style/min_max.rb +67 -0
  216. data/lib/rubocop/cop/style/missing_else.rb +16 -3
  217. data/lib/rubocop/cop/style/mixin_grouping.rb +2 -2
  218. data/lib/rubocop/cop/style/module_function.rb +8 -4
  219. data/lib/rubocop/cop/style/multiline_if_modifier.rb +5 -1
  220. data/lib/rubocop/cop/style/multiline_memoization.rb +25 -3
  221. data/lib/rubocop/cop/style/multiline_ternary_operator.rb +1 -1
  222. data/lib/rubocop/cop/style/multiple_comparison.rb +1 -1
  223. data/lib/rubocop/cop/style/mutable_constant.rb +2 -6
  224. data/lib/rubocop/cop/style/negated_if.rb +8 -4
  225. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +8 -8
  226. data/lib/rubocop/cop/style/nested_ternary_operator.rb +1 -1
  227. data/lib/rubocop/cop/style/non_nil_check.rb +14 -14
  228. data/lib/rubocop/cop/style/numeric_literal_prefix.rb +6 -2
  229. data/lib/rubocop/cop/style/numeric_literals.rb +2 -2
  230. data/lib/rubocop/cop/style/numeric_predicate.rb +8 -4
  231. data/lib/rubocop/cop/style/one_line_conditional.rb +8 -3
  232. data/lib/rubocop/cop/style/option_hash.rb +1 -1
  233. data/lib/rubocop/cop/style/optional_arguments.rb +1 -2
  234. data/lib/rubocop/cop/style/or_assignment.rb +88 -0
  235. data/lib/rubocop/cop/style/parallel_assignment.rb +2 -2
  236. data/lib/rubocop/cop/style/parentheses_around_condition.rb +12 -11
  237. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  238. data/lib/rubocop/cop/style/percent_q_literals.rb +2 -2
  239. data/lib/rubocop/cop/style/perl_backrefs.rb +1 -1
  240. data/lib/rubocop/cop/style/proc.rb +1 -1
  241. data/lib/rubocop/cop/style/raise_args.rb +16 -17
  242. data/lib/rubocop/cop/style/redundant_begin.rb +6 -5
  243. data/lib/rubocop/cop/style/redundant_conditional.rb +95 -0
  244. data/lib/rubocop/cop/style/redundant_freeze.rb +1 -1
  245. data/lib/rubocop/cop/style/redundant_parentheses.rb +13 -11
  246. data/lib/rubocop/cop/style/redundant_return.rb +23 -11
  247. data/lib/rubocop/cop/style/redundant_self.rb +18 -9
  248. data/lib/rubocop/cop/style/regexp_literal.rb +12 -4
  249. data/lib/rubocop/cop/style/rescue_modifier.rb +1 -1
  250. data/lib/rubocop/cop/style/return_nil.rb +98 -0
  251. data/lib/rubocop/cop/style/safe_navigation.rb +80 -43
  252. data/lib/rubocop/cop/style/single_line_block_params.rb +14 -13
  253. data/lib/rubocop/cop/style/single_line_methods.rb +9 -13
  254. data/lib/rubocop/cop/style/special_global_vars.rb +3 -3
  255. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +17 -39
  256. data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +22 -1
  257. data/lib/rubocop/cop/style/struct_inheritance.rb +1 -1
  258. data/lib/rubocop/cop/style/symbol_array.rb +5 -25
  259. data/lib/rubocop/cop/style/symbol_literal.rb +1 -1
  260. data/lib/rubocop/cop/style/symbol_proc.rb +3 -18
  261. data/lib/rubocop/cop/style/ternary_parentheses.rb +14 -10
  262. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +28 -9
  263. data/lib/rubocop/cop/style/trivial_accessors.rb +39 -56
  264. data/lib/rubocop/cop/style/unless_else.rb +1 -1
  265. data/lib/rubocop/cop/style/unneeded_capital_w.rb +1 -1
  266. data/lib/rubocop/cop/style/unneeded_interpolation.rb +1 -1
  267. data/lib/rubocop/cop/style/unneeded_percent_q.rb +1 -1
  268. data/lib/rubocop/cop/style/variable_interpolation.rb +8 -3
  269. data/lib/rubocop/cop/style/word_array.rb +7 -24
  270. data/lib/rubocop/cop/style/yoda_condition.rb +49 -14
  271. data/lib/rubocop/cop/style/zero_length_predicate.rb +25 -18
  272. data/lib/rubocop/cop/team.rb +16 -8
  273. data/lib/rubocop/cop/util.rb +11 -0
  274. data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -1
  275. data/lib/rubocop/formatter/formatter_set.rb +2 -1
  276. data/lib/rubocop/formatter/offense_count_formatter.rb +2 -0
  277. data/lib/rubocop/formatter/simple_text_formatter.rb +1 -1
  278. data/lib/rubocop/formatter/tap_formatter.rb +71 -0
  279. data/lib/rubocop/formatter/worst_offenders_formatter.rb +2 -0
  280. data/lib/rubocop/node_pattern.rb +44 -26
  281. data/lib/rubocop/options.rb +1 -0
  282. data/lib/rubocop/processed_source.rb +3 -1
  283. data/lib/rubocop/remote_config.rb +5 -1
  284. data/lib/rubocop/result_cache.rb +1 -0
  285. data/lib/rubocop/rspec/cop_helper.rb +10 -10
  286. data/lib/rubocop/rspec/expect_offense.rb +6 -8
  287. data/lib/rubocop/rspec/shared_examples.rb +8 -8
  288. data/lib/rubocop/string_util.rb +2 -0
  289. data/lib/rubocop/version.rb +1 -1
  290. metadata +51 -18
  291. data/lib/rubocop/cop/mixin/access_modifier_node.rb +0 -41
  292. data/lib/rubocop/cop/mixin/on_method_def.rb +0 -44
@@ -48,33 +48,30 @@ module RuboCop
48
48
 
49
49
  MSG = 'Use safe navigation (`&.`) instead of checking if an object ' \
50
50
  'exists before calling the method.'.freeze
51
- NIL_METHODS = nil.methods.freeze
51
+ NIL_METHODS = nil.methods.map(&:to_s).freeze
52
52
 
53
53
  minimum_target_ruby_version 2.3
54
54
 
55
- def_node_matcher :safe_navigation_candidate, <<-PATTERN
55
+ # if format: (if checked_variable body nil)
56
+ # unless format: (if checked_variable nil body)
57
+ def_node_matcher :modifier_if_safe_navigation_candidate?, <<-PATTERN
56
58
  {
57
- (if
58
- {(send (send $_ :nil?) :!) $_}
59
- {(send $_ $_ ...) (block (send $_ $_ ...) ...)}
60
- ...)
61
- (if
62
- (send $_ {:nil? :!}) nil
63
- {(send $_ $_ ...) (block (send $_ $_ ...) ...)}
64
- ...)
59
+ (if {
60
+ (send $_ {:nil? :!})
61
+ $_
62
+ } nil $_)
63
+
64
+ (if {
65
+ (send (send $_ :nil?) :!)
66
+ $_
67
+ } $_ nil)
65
68
  }
66
69
  PATTERN
67
70
 
68
- def_node_matcher :candidate_that_may_introduce_nil, <<-PATTERN
69
- (and
70
- {(send (send $_ :nil?) :!) $_}
71
- {(send $_ $_ ...) (block (send $_ $_ ...) ...)}
72
- ...)
73
- PATTERN
71
+ def_node_matcher :not_nil_check?, '(send (send $_ :nil?) :!)'
74
72
 
75
73
  def on_if(node)
76
- return if node.ternary?
77
-
74
+ return if allowed_if_condition?(node)
78
75
  check_node(node)
79
76
  end
80
77
 
@@ -82,51 +79,91 @@ module RuboCop
82
79
  check_node(node)
83
80
  end
84
81
 
85
- def on_or(node)
86
- check_node(node)
87
- end
88
-
89
82
  def check_node(node)
90
83
  return if target_ruby_version < 2.3
91
- return if allowed_if_condition?(node)
92
84
  checked_variable, receiver, method = extract_parts(node)
93
85
  return unless receiver == checked_variable
94
- return if NIL_METHODS.include?(method)
95
- return unless method =~ /\w+[=!?]?/
86
+ return if unsafe_method?(method)
87
+
88
+ add_offense(node)
89
+ end
90
+
91
+ def autocorrect(node)
92
+ _check, body, = node.node_parts
93
+ _checked_variable, matching_receiver, = extract_parts(node)
94
+ method_call, = matching_receiver.parent
96
95
 
97
- add_offense(node, :expression)
96
+ lambda do |corrector|
97
+ corrector.remove(begin_range(node, body))
98
+ corrector.remove(end_range(node, body))
99
+ corrector.insert_before((method_call || body).loc.dot, '&')
100
+ end
98
101
  end
99
102
 
103
+ private
104
+
100
105
  def allowed_if_condition?(node)
101
- node.if_type? && (node.else? || node.elsif?)
106
+ node.else? || node.elsif? || node.ternary?
102
107
  end
103
108
 
104
109
  def extract_parts(node)
105
- if cop_config['ConvertCodeThatCanStartToReturnNil']
106
- safe_navigation_candidate(node) ||
107
- candidate_that_may_introduce_nil(node)
108
- else
109
- safe_navigation_candidate(node)
110
+ case node.type
111
+ when :if
112
+ extract_parts_from_if(node)
113
+ when :and
114
+ extract_parts_from_and(node)
110
115
  end
111
116
  end
112
117
 
113
- def autocorrect(node)
114
- if node.if_type?
115
- _check, body, = *node.node_parts
116
- else
117
- _check, body = *node
118
+ def extract_parts_from_if(node)
119
+ checked_variable, receiver =
120
+ modifier_if_safe_navigation_candidate?(node)
121
+
122
+ matching_receiver =
123
+ find_matching_receiver_invocation(receiver, checked_variable)
124
+
125
+ if matching_receiver
126
+ method = matching_receiver.parent.loc.selector.source
118
127
  end
119
128
 
120
- method_call, = *body if body.block_type?
129
+ [checked_variable, matching_receiver, method]
130
+ end
121
131
 
122
- lambda do |corrector|
123
- corrector.remove(begin_range(node, body))
124
- corrector.remove(end_range(node, body))
125
- corrector.insert_before((method_call || body).loc.dot, '&')
132
+ def extract_parts_from_and(node)
133
+ checked_variable, rhs = *node
134
+ if cop_config['ConvertCodeThatCanStartToReturnNil']
135
+ checked_variable =
136
+ not_nil_check?(checked_variable) || checked_variable
137
+ end
138
+
139
+ matching_receiver =
140
+ find_matching_receiver_invocation(rhs, checked_variable)
141
+
142
+ if matching_receiver
143
+ method = matching_receiver.parent.loc.selector.source
126
144
  end
145
+
146
+ [checked_variable, matching_receiver, method]
127
147
  end
128
148
 
129
- private
149
+ def find_matching_receiver_invocation(node, checked_variable)
150
+ return nil if node.nil?
151
+
152
+ if node.block_type?
153
+ method_call, = *node
154
+ receiver, _method = *method_call
155
+ elsif node.send_type?
156
+ receiver, _method = *node
157
+ end
158
+
159
+ return receiver if receiver == checked_variable
160
+
161
+ find_matching_receiver_invocation(receiver, checked_variable)
162
+ end
163
+
164
+ def unsafe_method?(method)
165
+ NIL_METHODS.include?(method) || method !~ /\w+[=!?]?/
166
+ end
130
167
 
131
168
  def begin_range(node, method_call)
132
169
  Parser::Source::Range.new(node.loc.expression.source_buffer,
@@ -14,20 +14,12 @@ module RuboCop
14
14
  def on_block(node)
15
15
  return unless node.single_line?
16
16
 
17
- send_node = node.send_node
17
+ return unless eligible_method?(node)
18
+ return unless eligible_arguments?(node)
18
19
 
19
- return unless send_node.receiver
20
- return unless method_names.include?(send_node.method_name)
20
+ return if args_match?(node.send_node.method_name, node.arguments)
21
21
 
22
- return unless node.arguments?
23
-
24
- arguments = node.arguments.to_a
25
-
26
- # discard cases with argument destructuring
27
- return true unless arguments.all?(&:arg_type?)
28
- return if args_match?(send_node.method_name, arguments)
29
-
30
- add_offense(node.arguments, :expression)
22
+ add_offense(node.arguments)
31
23
  end
32
24
 
33
25
  private
@@ -39,6 +31,15 @@ module RuboCop
39
31
  format(MSG, method_name, arguments)
40
32
  end
41
33
 
34
+ def eligible_arguments?(node)
35
+ node.arguments? && node.arguments.to_a.all?(&:arg_type?)
36
+ end
37
+
38
+ def eligible_method?(node)
39
+ node.send_node.receiver &&
40
+ method_names.include?(node.send_node.method_name)
41
+ end
42
+
42
43
  def methods
43
44
  cop_config['Methods']
44
45
  end
@@ -58,7 +59,7 @@ module RuboCop
58
59
  end
59
60
 
60
61
  def args_match?(method_name, args)
61
- actual_args = args.flat_map(&:to_a)
62
+ actual_args = args.to_a.flat_map(&:to_a)
62
63
 
63
64
  # Prepending an underscore to mark an unused parameter is allowed, so
64
65
  # we remove any leading underscores before comparing.
@@ -7,29 +7,25 @@ module RuboCop
7
7
  # It can optionally accept single-line methods with no body.
8
8
  class SingleLineMethods < Cop
9
9
  include AutocorrectAlignment
10
- include OnMethodDef
11
10
 
12
11
  MSG = 'Avoid single-line method definitions.'.freeze
13
12
 
14
- def allow_empty?
15
- cop_config['AllowIfMethodIsEmpty']
13
+ def on_def(node)
14
+ return unless node.single_line?
15
+ return if allow_empty? && !node.body
16
+
17
+ add_offense(node)
16
18
  end
19
+ alias on_defs on_def
17
20
 
18
21
  private
19
22
 
20
- def on_method_def(node, _method_name, _args, body)
21
- start_line = node.loc.keyword.line
22
- end_line = node.loc.end.line
23
-
24
- empty_body = body.nil?
25
- return unless start_line == end_line && !(allow_empty? && empty_body)
26
-
27
- @body = body
28
- add_offense(node, :expression)
23
+ def allow_empty?
24
+ cop_config['AllowIfMethodIsEmpty']
29
25
  end
30
26
 
31
27
  def autocorrect(node)
32
- body = @body
28
+ body = node.body
33
29
 
34
30
  lambda do |corrector|
35
31
  each_part(body) do |part|
@@ -47,8 +47,8 @@ module RuboCop
47
47
  PERL_VARS.merge!(
48
48
  Hash[PERL_VARS.flat_map { |_, vs| vs.map { |v| [v, [v]] } }]
49
49
  )
50
- ENGLISH_VARS.each { |_, v| v.freeze }.freeze
51
- PERL_VARS.each { |_, v| v.freeze }.freeze
50
+ ENGLISH_VARS.each_value(&:freeze).freeze
51
+ PERL_VARS.each_value(&:freeze).freeze
52
52
 
53
53
  # Anything *not* in this set is provided by the English library.
54
54
  NON_ENGLISH_VARS = Set.new(%i[
@@ -67,7 +67,7 @@ module RuboCop
67
67
  correct_style_detected
68
68
  else
69
69
  opposite_style_detected
70
- add_offense(node, :expression)
70
+ add_offense(node)
71
71
  end
72
72
  end
73
73
 
@@ -27,19 +27,11 @@ module RuboCop
27
27
  ARROW = '->'.freeze
28
28
 
29
29
  def on_send(node)
30
- return unless arrow_lambda_with_args?(node)
30
+ return unless stabby_lambda_with_args?(node)
31
+ return unless redundant_parentheses?(node) ||
32
+ missing_parentheses?(node)
31
33
 
32
- if style == :require_parentheses
33
- if parentheses?(node)
34
- correct_style_detected
35
- else
36
- missing_parentheses(node)
37
- end
38
- elsif parentheses?(node)
39
- unwanted_parentheses(node)
40
- else
41
- correct_style_detected
42
- end
34
+ add_offense(node.parent.arguments)
43
35
  end
44
36
 
45
37
  def autocorrect(node)
@@ -52,21 +44,21 @@ module RuboCop
52
44
 
53
45
  private
54
46
 
55
- def missing_parentheses(node)
56
- add_offense(node_args(node), :expression, MSG_REQUIRE) do
57
- opposite_style_detected
58
- end
47
+ def missing_parentheses?(node)
48
+ style == :require_parentheses && !parentheses?(node)
59
49
  end
60
50
 
61
- def unwanted_parentheses(node)
62
- add_offense(node_args(node), :expression, MSG_NO_REQUIRE) do
63
- opposite_style_detected
64
- end
51
+ def redundant_parentheses?(node)
52
+ style == :require_no_parentheses && parentheses?(node)
53
+ end
54
+
55
+ def message(_node)
56
+ style == :require_parentheses ? MSG_REQUIRE : MSG_NO_REQUIRE
65
57
  end
66
58
 
67
59
  def missing_parentheses_corrector(node)
68
60
  lambda do |corrector|
69
- args_loc = node_args(node).source_range
61
+ args_loc = node.parent.arguments.source_range
70
62
 
71
63
  corrector.insert_before(args_loc, '(')
72
64
  corrector.insert_after(args_loc, ')')
@@ -75,37 +67,23 @@ module RuboCop
75
67
 
76
68
  def unwanted_parentheses_corrector(node)
77
69
  lambda do |corrector|
78
- args_loc = node_args(node).loc
70
+ args_loc = node.parent.arguments.loc
79
71
 
80
72
  corrector.replace(args_loc.begin, '')
81
73
  corrector.remove(args_loc.end)
82
74
  end
83
75
  end
84
76
 
85
- def arrow_lambda_with_args?(node)
86
- lambda_node?(node) && arrow_form?(node) && args?(node)
87
- end
88
-
89
- def lambda_node?(node)
90
- receiver, call = *node
91
- !receiver && call == :lambda
77
+ def stabby_lambda_with_args?(node)
78
+ node.command?(:lambda) && arrow_form?(node) && node.parent.arguments?
92
79
  end
93
80
 
94
81
  def arrow_form?(node)
95
82
  node.loc.selector.source == ARROW
96
83
  end
97
84
 
98
- def node_args(node)
99
- _call, args, _body = *node.parent
100
- args
101
- end
102
-
103
- def args?(node)
104
- !node_args(node).children.empty?
105
- end
106
-
107
85
  def parentheses?(node)
108
- node_args(node).loc.begin
86
+ node.parent.arguments.loc.begin
109
87
  end
110
88
  end
111
89
  end
@@ -3,7 +3,28 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # Checks if uses of quotes match the configured preference.
6
+ # This cop checks that quotes inside the string interpolation
7
+ # match the configured preference.
8
+ #
9
+ # @example
10
+ #
11
+ # # EnforcedStyle: single_quotes
12
+ #
13
+ # # bad
14
+ # result = "Tests #{success ? "PASS" : "FAIL"}"
15
+ #
16
+ # # good
17
+ # result = "Tests #{success ? 'PASS' : 'FAIL'}"
18
+ #
19
+ # @example
20
+ #
21
+ # # EnforcedStyle: double_quotes
22
+ #
23
+ # # bad
24
+ # result = "Tests #{success ? 'PASS' : 'FAIL'}"
25
+ #
26
+ # # good
27
+ # result = "Tests #{success ? "PASS" : "FAIL"}"
7
28
  class StringLiteralsInInterpolation < Cop
8
29
  include ConfigurableEnforcedStyle
9
30
  include StringLiteralsHelp
@@ -19,7 +19,7 @@ module RuboCop
19
19
  _name, superclass, _body = *node
20
20
  return unless struct_constructor?(superclass)
21
21
 
22
- add_offense(node, superclass.source_range, MSG)
22
+ add_offense(node, superclass.source_range)
23
23
  end
24
24
 
25
25
  def_node_matcher :struct_constructor?, <<-PATTERN
@@ -37,6 +37,7 @@ module RuboCop
37
37
  include ArraySyntax
38
38
  include ConfigurableEnforcedStyle
39
39
  include PercentLiteral
40
+ include PercentArray
40
41
  extend TargetRubyVersion
41
42
 
42
43
  minimum_target_ruby_version 2.0
@@ -50,12 +51,16 @@ module RuboCop
50
51
 
51
52
  def on_array(node)
52
53
  if bracketed_array_of?(:sym, node)
54
+ return if symbols_contain_spaces?(node)
55
+
53
56
  check_bracketed_array(node)
54
57
  elsif node.percent_literal?(:symbol)
55
58
  check_percent_array(node)
56
59
  end
57
60
  end
58
61
 
62
+ private
63
+
59
64
  def autocorrect(node)
60
65
  if style == :percent
61
66
  correct_percent(node, 'i')
@@ -64,31 +69,6 @@ module RuboCop
64
69
  end
65
70
  end
66
71
 
67
- private
68
-
69
- def check_bracketed_array(node)
70
- return if comments_in_array?(node) ||
71
- symbols_contain_spaces?(node) ||
72
- below_array_length?(node)
73
-
74
- array_style_detected(:brackets, node.values.size)
75
- add_offense(node, :expression, PERCENT_MSG) if style == :percent
76
- end
77
-
78
- def check_percent_array(node)
79
- array_style_detected(:percent, node.values.size)
80
- add_offense(node, :expression, ARRAY_MSG) if style == :brackets
81
- end
82
-
83
- def comments_in_array?(node)
84
- comments = processed_source.comments
85
- array_range = node.source_range.to_a
86
-
87
- comments.any? do |comment|
88
- !(comment.loc.expression.to_a & array_range).empty?
89
- end
90
- end
91
-
92
72
  def symbols_contain_spaces?(node)
93
73
  node.children.any? do |sym|
94
74
  content, = *sym