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
@@ -9,6 +9,8 @@ module RuboCop
9
9
  # A `block` node is essentially a method send with a block. Parser nests
10
10
  # the `send` node inside the `block` node.
11
11
  class BlockNode < Node
12
+ VOID_CONTEXT_METHODS = %i[each].freeze
13
+
12
14
  # The `send` node associated with this block.
13
15
  #
14
16
  # @return [SendNode] the `send` node associated with the `block` node
@@ -95,6 +97,13 @@ module RuboCop
95
97
  send_node.method?(:lambda)
96
98
  end
97
99
 
100
+ # Checks whether this node body is a void context.
101
+ #
102
+ # @return [Boolean] whether the `block` node body is a void context
103
+ def void_context?
104
+ VOID_CONTEXT_METHODS.include?(send_node.method_name)
105
+ end
106
+
98
107
  # Custom destructuring method. This can be used to normalize
99
108
  # destructuring for different variations of the node.
100
109
  #
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module AST
5
+ # A node extension for `def` nodes. This will be used in place of a plain
6
+ # node when the builder constructs the AST, making its methods available
7
+ # to all `def` nodes within RuboCop.
8
+ class DefNode < Node
9
+ include ParameterizedNode
10
+ include MethodIdentifierPredicates
11
+
12
+ # Checks whether this node body is a void context.
13
+ #
14
+ # @return [Boolean] whether the `def` node body is a void context
15
+ def void_context?
16
+ method?(:initialize) || assignment_method?
17
+ end
18
+
19
+ # The name of the defined method as a symbol.
20
+ #
21
+ # @return [Symbol] the name of the defined method
22
+ def method_name
23
+ node_parts[2]
24
+ end
25
+
26
+ # An array containing the arguments of the method definition.
27
+ #
28
+ # @return [Array<Node>] the arguments of the method definition
29
+ def arguments
30
+ node_parts[1]
31
+ end
32
+
33
+ # The body of the method definition.
34
+ #
35
+ # @note this can be either a `begin` node, if the method body contains
36
+ # multiple expressions, or any other node, if it contains a single
37
+ # expression.
38
+ #
39
+ # @return [Node] the body of the method definition
40
+ def body
41
+ node_parts[0]
42
+ end
43
+
44
+ # The receiver of the method definition, if any.
45
+ #
46
+ # @return [Node, nil] the receiver of the method definition, or `nil`.
47
+ def receiver
48
+ node_parts[3]
49
+ end
50
+
51
+ # Custom destructuring method. This can be used to normalize
52
+ # destructuring for different variations of the node.
53
+ #
54
+ # In this case, the `def` node destructures into:
55
+ #
56
+ # `method_name, arguments, body`
57
+ #
58
+ # while the `defs` node destructures into:
59
+ #
60
+ # `receiver, method_name, arguments, body`
61
+ #
62
+ # so we reverse the destructured array to get the optional receiver
63
+ # at the end, where it can be discarded.
64
+ #
65
+ # @return [Array] the different parts of the `def` or `defs` node
66
+ def node_parts
67
+ to_a.reverse
68
+ end
69
+ end
70
+ end
71
+ end
@@ -20,6 +20,14 @@ module RuboCop
20
20
  loc.begin && loc.begin.is?('do')
21
21
  end
22
22
 
23
+ # Checks whether this node body is a void context.
24
+ # Always `true` for `for`.
25
+ #
26
+ # @return [true] whether the `for` node body is a void context
27
+ def void_context?
28
+ true
29
+ end
30
+
23
31
  # Returns the iteration variable of the `for` loop.
24
32
  #
25
33
  # @return [Node] The iteration variable of the `for` loop
@@ -82,10 +82,10 @@ module RuboCop
82
82
  (if? || unless?) && super
83
83
  end
84
84
 
85
- # Chackes whether the `if` node has nested `if` nodes in any of its
85
+ # Chacks whether the `if` node has nested `if` nodes in any of its
86
86
  # branches.
87
87
  #
88
- # @note This is a shallow search.
88
+ # @note This performs a shallow search.
89
89
  #
90
90
  # @return [Boolean] whether the `if` node contains nested conditionals
91
91
  def nested_conditional?
@@ -98,6 +98,14 @@ module RuboCop
98
98
  false
99
99
  end
100
100
 
101
+ # Checks whether the `if` node has at least one `elsif` branch. Returns
102
+ # true if this `if` node itself is an `elsif`.
103
+ #
104
+ # @return [Boolean] whether the `if` node has at least one `elsif` branch
105
+ def elsif_conditional?
106
+ else_branch && else_branch.if_type? && else_branch.elsif?
107
+ end
108
+
101
109
  # Returns the branch of the `if` node that gets evaluated when its
102
110
  # condition is truthy.
103
111
  #
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module AST
5
+ # A mixin that helps give collection nodes array polymorphism.
6
+ module CollectionNode
7
+ extend Forwardable
8
+
9
+ ARRAY_METHODS =
10
+ (Array.instance_methods - Object.instance_methods - [:to_a]).freeze
11
+
12
+ def_delegators :to_a, *ARRAY_METHODS
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,174 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module AST
5
+ # Common functionality for nodes that are a kind of method dispatch:
6
+ # `send`, `csend`, `super`, `zsuper`, `yield`
7
+ module MethodDispatchNode
8
+ extend NodePattern::Macros
9
+ include MethodIdentifierPredicates
10
+
11
+ # The receiving node of the method dispatch.
12
+ #
13
+ # @return [Node, nil] the receiver of the dispatched method or `nil`
14
+ def receiver
15
+ node_parts[0]
16
+ end
17
+
18
+ # The name of the dispatched method as a symbol.
19
+ #
20
+ # @return [Symbol] the name of the dispatched method
21
+ def method_name
22
+ node_parts[1]
23
+ end
24
+
25
+ # An array containing the arguments of the dispatched method.
26
+ #
27
+ # @return [Array<Node>] the arguments of the dispatched method
28
+ def arguments
29
+ node_parts[2..-1]
30
+ end
31
+
32
+ # Checks whether the dispatched method is a macro method. A macro method
33
+ # is defined as a method that sits in a class, module, or block body and
34
+ # has an implicit receiver.
35
+ #
36
+ # @note This does not include DSLs that use nested blocks, like RSpec
37
+ #
38
+ # @return [Boolean] whether the dispatched method is a macro method
39
+ def macro?
40
+ !receiver && macro_scope?
41
+ end
42
+
43
+ # Checks whether the dispatched method is a bare access modifier affects
44
+ # all methods defined after the macro.
45
+ #
46
+ # @return [Boolean] whether the dispatched method is access modifier
47
+ def access_modifier?
48
+ macro? && bare_access_modifier?
49
+ end
50
+
51
+ # Checks whether the name of the dispatched method matches the argument
52
+ # and has an implicit receiver.
53
+ #
54
+ # @param [Symbol, String] name the method name to check for
55
+ # @return [Boolean] whether the method name matches the argument
56
+ def command?(name)
57
+ !receiver && method?(name)
58
+ end
59
+
60
+ # Checks whether the dispatched method is a setter method.
61
+ #
62
+ # @return [Boolean] whether the dispatched method is a setter
63
+ def setter_method?
64
+ loc.respond_to?(:operator) && loc.operator
65
+ end
66
+
67
+ # Checks whether the dispatched method uses a dot to connect the
68
+ # receiver and the method name.
69
+ #
70
+ # This is useful for comparison operators, which can be called either
71
+ # with or without a dot, i.e. `foo == bar` or `foo.== bar`.
72
+ #
73
+ # @return [Boolean] whether the method was called with a connecting dot
74
+ def dot?
75
+ loc.respond_to?(:dot) && loc.dot && loc.dot.is?('.')
76
+ end
77
+
78
+ # Checks whether the dispatched method uses a double colon to connect the
79
+ # receiver and the method name.
80
+ #
81
+ # @return [Boolean] whether the method was called with a connecting dot
82
+ def double_colon?
83
+ loc.respond_to?(:dot) && loc.dot && loc.dot.is?('::')
84
+ end
85
+
86
+ # Checks whether the *explicit* receiver of this method dispatch is
87
+ # `self`.
88
+ #
89
+ # @return [Boolean] whether the receiver of this method dispatch is `self`
90
+ def self_receiver?
91
+ receiver && receiver.self_type?
92
+ end
93
+
94
+ # Checks whether the *explicit* receiver of this method dispatch is a
95
+ # `const` node.
96
+ #
97
+ # @return [Boolean] whether the receiver of this method dispatch
98
+ # is a `const` node
99
+ def const_receiver?
100
+ receiver && receiver.const_type?
101
+ end
102
+
103
+ # Checks whether the method dispatch is the implicit form of `#call`,
104
+ # e.g. `foo.(bar)`.
105
+ #
106
+ # @return [Boolean] whether the method is the implicit form of `#call`
107
+ def implicit_call?
108
+ method?(:call) && !loc.selector
109
+ end
110
+
111
+ # Whether this method dispatch has an explicit block.
112
+ #
113
+ # @return [Boolean] whether the dispatched method has a block
114
+ def block_literal?
115
+ parent && parent.block_type? && eql?(parent.send_node)
116
+ end
117
+
118
+ # The `block` node associated with this method dispatch, if any.
119
+ #
120
+ # @return [BlockNode, nil] the `block` node associated with this method
121
+ # call or `nil`
122
+ def block_node
123
+ parent if block_literal?
124
+ end
125
+
126
+ # Checks if this node is part of a chain of `def` modifiers.
127
+ #
128
+ # @example
129
+ #
130
+ # private def foo; end
131
+ #
132
+ # @return [Boolean] whether the dispatched method is a `def` modifier
133
+ def def_modifier?
134
+ send_type? &&
135
+ [self, *each_descendant(:send)].any?(&:adjacent_def_modifier?)
136
+ end
137
+
138
+ private
139
+
140
+ def_node_matcher :macro_scope?, <<-PATTERN
141
+ {^{({sclass class module block} ...) class_constructor?}
142
+ ^^{({sclass class module block} ... (begin ...)) class_constructor?}
143
+ ^#macro_kwbegin_wrapper?
144
+ #root_node?}
145
+ PATTERN
146
+
147
+ # Check if a node's parent is a kwbegin wrapper within a macro scope
148
+ #
149
+ # @param parent [Node] parent of the node being checked
150
+ #
151
+ # @return [Boolean] true if the parent is a kwbegin in a macro scope
152
+ def macro_kwbegin_wrapper?(parent)
153
+ parent.kwbegin_type? && macro_scope?(parent)
154
+ end
155
+
156
+ # Check if a node does not have a parent
157
+ #
158
+ # @param node [Node]
159
+ #
160
+ # @return [Boolean] if the parent is nil
161
+ def root_node?(node)
162
+ node.parent.nil?
163
+ end
164
+
165
+ def_node_matcher :adjacent_def_modifier?, <<-PATTERN
166
+ (send nil _ ({def defs} ...))
167
+ PATTERN
168
+
169
+ def_node_matcher :bare_access_modifier?, <<-PATTERN
170
+ (send nil {:public :protected :private :module_function})
171
+ PATTERN
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module AST
5
+ # Common predicates for nodes that reference method identifiers:
6
+ # `send`, `csend`, `def`, `defs`, `super`, `zsuper`
7
+ #
8
+ # @note this mixin expects `#method_name` and `#receiver` to be implemented
9
+ module MethodIdentifierPredicates
10
+ ENUMERATOR_METHODS = %i[collect collect_concat detect downto each
11
+ find find_all find_index inject loop map!
12
+ map reduce reject reject! reverse_each select
13
+ select! times upto].freeze
14
+
15
+ # Checks whether the method name matches the argument.
16
+ #
17
+ # @param [Symbol, String] name the method name to check for
18
+ # @return [Boolean] whether the method name matches the argument
19
+ def method?(name)
20
+ method_name == name.to_sym
21
+ end
22
+
23
+ # Checks whether the method is an operator method.
24
+ #
25
+ # @return [Boolean] whether the method is an operator
26
+ def operator_method?
27
+ RuboCop::Cop::Util::OPERATOR_METHODS.include?(method_name)
28
+ end
29
+
30
+ # Checks whether the method is a comparison method.
31
+ #
32
+ # @return [Boolean] whether the method is a comparison
33
+ def comparison_method?
34
+ Node::COMPARISON_OPERATORS.include?(method_name)
35
+ end
36
+
37
+ # Checks whether the method is an assignment method.
38
+ #
39
+ # @return [Boolean] whether the method is an assignment
40
+ def assignment_method?
41
+ !comparison_method? && method_name.to_s.end_with?('=')
42
+ end
43
+
44
+ # Checks whether the method is an enumerator method.
45
+ #
46
+ # @return [Boolean] whether the method is an enumerator
47
+ def enumerator_method?
48
+ ENUMERATOR_METHODS.include?(method_name) ||
49
+ method_name.to_s.start_with?('each_')
50
+ end
51
+
52
+ # Checks whether the method is a predicate method.
53
+ #
54
+ # @return [Boolean] whether the method is a predicate method
55
+ def predicate_method?
56
+ method_name.to_s.end_with?('?')
57
+ end
58
+
59
+ # Checks whether the method is a bang method.
60
+ #
61
+ # @return [Boolean] whether the method is a bang method
62
+ def bang_method?
63
+ method_name.to_s.end_with?('!')
64
+ end
65
+
66
+ # Checks whether the method is a camel case method,
67
+ # e.g. `Integer()`.
68
+ #
69
+ # @return [Boolean] whether the method is a camel case method
70
+ def camel_case_method?
71
+ method_name.to_s =~ /\A[A-Z]/
72
+ end
73
+
74
+ # Checks whether the *explicit* receiver of this node is `self`.
75
+ #
76
+ # @return [Boolean] whether the receiver of this node is `self`
77
+ def self_receiver?
78
+ receiver && receiver.self_type?
79
+ end
80
+
81
+ # Checks whether the *explicit* receiver of node is a `const` node.
82
+ #
83
+ # @return [Boolean] whether the receiver of this node is a `const` node
84
+ def const_receiver?
85
+ receiver && receiver.const_type?
86
+ end
87
+ end
88
+ end
89
+ end
@@ -3,71 +3,58 @@
3
3
  module RuboCop
4
4
  module AST
5
5
  # Common functionality for nodes that are parameterized:
6
- # `send`, `super`, `zsuper` ...
6
+ # `send`, `super`, `zsuper`, `def`, `defs`
7
7
  module ParameterizedNode
8
- # Checks whether this super invocation's arguments are wrapped in
9
- # parentheses.
8
+ # Checks whether this node's arguments are wrapped in parentheses.
10
9
  #
11
- # @return [Boolean] whether this super invocation's arguments are
10
+ # @return [Boolean] whether this node's arguments are
12
11
  # wrapped in parentheses
13
12
  def parenthesized?
14
13
  loc.end && loc.end.is?(')')
15
14
  end
16
15
 
17
- # A shorthand for getting the first argument of the method invocation.
16
+ # A shorthand for getting the first argument of the node.
18
17
  # Equivalent to `arguments.first`.
19
18
  #
20
- # @return [Node, nil] the first argument of the method invocation,
19
+ # @return [Node, nil] the first argument of the node,
21
20
  # or `nil` if there are no arguments
22
21
  def first_argument
23
22
  arguments[0]
24
23
  end
25
24
 
26
- # A shorthand for getting the last argument of the method invocation.
25
+ # A shorthand for getting the last argument of the node.
27
26
  # Equivalent to `arguments.last`.
28
27
  #
29
- # @return [Node, nil] the last argument of the method invocation,
28
+ # @return [Node, nil] the last argument of the node,
30
29
  # or `nil` if there are no arguments
31
30
  def last_argument
32
31
  arguments[-1]
33
32
  end
34
33
 
35
- # Checks whether this method was invoked with arguments.
34
+ # Checks whether this node has any arguments.
36
35
  #
37
- # @return [Boolean] whether this method was invoked with arguments
36
+ # @return [Boolean] whether this node has any arguments
38
37
  def arguments?
39
38
  !arguments.empty?
40
39
  end
41
40
 
42
- # Checks whether any argument of the method invocation is a splat
41
+ # Checks whether any argument of the node is a splat
43
42
  # argument, i.e. `*splat`.
44
43
  #
45
- # @return [Boolean] whether the invoked method is a splat argument
44
+ # @return [Boolean] whether the node is a splat argument
46
45
  def splat_argument?
47
- arguments? && arguments.any?(&:splat_type?)
46
+ arguments? &&
47
+ (arguments.any?(&:splat_type?) || arguments.any?(&:restarg_type?))
48
48
  end
49
+ alias rest_argument? splat_argument?
49
50
 
50
- # Whether the last argument of the method invocation is a block pass,
51
+ # Whether the last argument of the node is a block pass,
51
52
  # i.e. `&block`.
52
53
  #
53
- # @return [Boolean] whether the invoked method is a block pass
54
+ # @return [Boolean] whether the last argument of the node is a block pass
54
55
  def block_argument?
55
- arguments? && last_argument.block_pass_type?
56
- end
57
-
58
- # Whether this method invocation has an explicit block.
59
- #
60
- # @return [Boolean] whether the invoked method has a block
61
- def block_literal?
62
- parent && parent.block_type? && eql?(parent.send_node)
63
- end
64
-
65
- # The block node associated with this method call, if any.
66
- #
67
- # @return [BlockNode, nil] the `block` node associated with this method
68
- # call or `nil`
69
- def block_node
70
- parent if block_literal?
56
+ arguments? &&
57
+ (last_argument.block_pass_type? || last_argument.blockarg_type?)
71
58
  end
72
59
  end
73
60
  end