rubocop 1.8.0 → 1.11.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 (246) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +14 -13
  3. data/assets/output.html.erb +1 -1
  4. data/config/default.yml +89 -22
  5. data/config/obsoletion.yml +4 -0
  6. data/lib/rubocop.rb +9 -0
  7. data/lib/rubocop/cli/command/auto_genenerate_config.rb +5 -4
  8. data/lib/rubocop/cli/command/execute_runner.rb +1 -1
  9. data/lib/rubocop/cli/command/suggest_extensions.rb +1 -1
  10. data/lib/rubocop/config.rb +5 -2
  11. data/lib/rubocop/config_loader.rb +7 -14
  12. data/lib/rubocop/config_store.rb +12 -1
  13. data/lib/rubocop/cop/base.rb +2 -1
  14. data/lib/rubocop/cop/bundler/duplicated_gem.rb +2 -1
  15. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -0
  16. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +1 -0
  17. data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -0
  18. data/lib/rubocop/cop/exclude_limit.rb +26 -0
  19. data/lib/rubocop/cop/gemspec/date_assignment.rb +57 -0
  20. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +2 -0
  21. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -0
  22. data/lib/rubocop/cop/gemspec/required_ruby_version.rb +2 -0
  23. data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +2 -0
  24. data/lib/rubocop/cop/generator.rb +3 -5
  25. data/lib/rubocop/cop/internal_affairs.rb +6 -1
  26. data/lib/rubocop/cop/internal_affairs/empty_line_between_expect_offense_and_correction.rb +68 -0
  27. data/lib/rubocop/cop/internal_affairs/example_description.rb +90 -0
  28. data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +1 -0
  29. data/lib/rubocop/cop/internal_affairs/node_destructuring.rb +2 -0
  30. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +151 -0
  31. data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +1 -0
  32. data/lib/rubocop/cop/internal_affairs/offense_location_keyword.rb +2 -0
  33. data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +62 -0
  34. data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +65 -0
  35. data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +1 -0
  36. data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +3 -0
  37. data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +4 -0
  38. data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +2 -0
  39. data/lib/rubocop/cop/layout/block_alignment.rb +1 -0
  40. data/lib/rubocop/cop/layout/class_structure.rb +8 -2
  41. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +37 -17
  42. data/lib/rubocop/cop/layout/extra_spacing.rb +2 -2
  43. data/lib/rubocop/cop/layout/first_argument_indentation.rb +22 -3
  44. data/lib/rubocop/cop/layout/indentation_width.rb +1 -0
  45. data/lib/rubocop/cop/layout/line_length.rb +2 -1
  46. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +26 -0
  47. data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -1
  48. data/lib/rubocop/cop/layout/space_before_brackets.rb +9 -4
  49. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +1 -1
  50. data/lib/rubocop/cop/lint/big_decimal_new.rb +1 -0
  51. data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -0
  52. data/lib/rubocop/cop/lint/constant_definition_in_block.rb +2 -0
  53. data/lib/rubocop/cop/lint/constant_resolution.rb +1 -0
  54. data/lib/rubocop/cop/lint/debugger.rb +60 -14
  55. data/lib/rubocop/cop/lint/deprecated_constants.rb +5 -0
  56. data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +14 -4
  57. data/lib/rubocop/cop/lint/duplicate_branch.rb +1 -1
  58. data/lib/rubocop/cop/lint/duplicate_methods.rb +3 -0
  59. data/lib/rubocop/cop/lint/duplicate_require.rb +3 -2
  60. data/lib/rubocop/cop/lint/each_with_object_argument.rb +1 -0
  61. data/lib/rubocop/cop/lint/else_layout.rb +1 -1
  62. data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -0
  63. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -0
  64. data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +1 -0
  65. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -0
  66. data/lib/rubocop/cop/lint/inherit_exception.rb +1 -0
  67. data/lib/rubocop/cop/lint/multiple_comparison.rb +5 -4
  68. data/lib/rubocop/cop/lint/nested_method_definition.rb +3 -0
  69. data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -0
  70. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +7 -0
  71. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +3 -0
  72. data/lib/rubocop/cop/lint/number_conversion.rb +43 -6
  73. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +47 -0
  74. data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +39 -0
  75. data/lib/rubocop/cop/lint/raise_exception.rb +2 -0
  76. data/lib/rubocop/cop/lint/rand_one.rb +1 -0
  77. data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +5 -3
  78. data/lib/rubocop/cop/lint/redundant_require_statement.rb +1 -0
  79. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +1 -0
  80. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +7 -3
  81. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +1 -0
  82. data/lib/rubocop/cop/lint/redundant_with_index.rb +1 -0
  83. data/lib/rubocop/cop/lint/redundant_with_object.rb +1 -0
  84. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +1 -0
  85. data/lib/rubocop/cop/lint/safe_navigation_with_empty.rb +1 -0
  86. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -0
  87. data/lib/rubocop/cop/lint/shadowed_argument.rb +1 -0
  88. data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +1 -0
  89. data/lib/rubocop/cop/lint/struct_new_override.rb +1 -0
  90. data/lib/rubocop/cop/lint/symbol_conversion.rb +103 -0
  91. data/lib/rubocop/cop/lint/to_enum_arguments.rb +3 -0
  92. data/lib/rubocop/cop/lint/triple_quotes.rb +71 -0
  93. data/lib/rubocop/cop/lint/unified_integer.rb +1 -0
  94. data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +5 -0
  95. data/lib/rubocop/cop/lint/unreachable_code.rb +1 -0
  96. data/lib/rubocop/cop/lint/unreachable_loop.rb +1 -0
  97. data/lib/rubocop/cop/lint/unused_method_argument.rb +1 -0
  98. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +1 -0
  99. data/lib/rubocop/cop/lint/useless_access_modifier.rb +4 -0
  100. data/lib/rubocop/cop/lint/useless_setter_call.rb +1 -0
  101. data/lib/rubocop/cop/lint/useless_times.rb +3 -0
  102. data/lib/rubocop/cop/message_annotator.rb +4 -1
  103. data/lib/rubocop/cop/metrics/block_nesting.rb +2 -2
  104. data/lib/rubocop/cop/metrics/module_length.rb +1 -0
  105. data/lib/rubocop/cop/metrics/parameter_lists.rb +6 -2
  106. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +6 -4
  107. data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +2 -0
  108. data/lib/rubocop/cop/mixin/check_line_breakable.rb +5 -0
  109. data/lib/rubocop/cop/mixin/code_length.rb +3 -1
  110. data/lib/rubocop/cop/mixin/comments_help.rb +0 -1
  111. data/lib/rubocop/cop/mixin/configurable_max.rb +1 -0
  112. data/lib/rubocop/cop/mixin/def_node.rb +1 -0
  113. data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +3 -0
  114. data/lib/rubocop/cop/mixin/empty_parameter.rb +1 -0
  115. data/lib/rubocop/cop/mixin/enforce_superclass.rb +2 -0
  116. data/lib/rubocop/cop/mixin/hash_transform_method.rb +1 -0
  117. data/lib/rubocop/cop/mixin/method_complexity.rb +4 -1
  118. data/lib/rubocop/cop/mixin/negative_conditional.rb +3 -0
  119. data/lib/rubocop/cop/mixin/preferred_delimiters.rb +3 -3
  120. data/lib/rubocop/cop/mixin/rational_literal.rb +1 -0
  121. data/lib/rubocop/cop/mixin/safe_assignment.rb +5 -0
  122. data/lib/rubocop/cop/mixin/uncommunicative_name.rb +5 -1
  123. data/lib/rubocop/cop/mixin/visibility_help.rb +1 -0
  124. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -0
  125. data/lib/rubocop/cop/naming/constant_name.rb +2 -0
  126. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +2 -0
  127. data/lib/rubocop/cop/naming/method_name.rb +3 -0
  128. data/lib/rubocop/cop/naming/predicate_name.rb +1 -0
  129. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +38 -5
  130. data/lib/rubocop/cop/naming/variable_number.rb +1 -1
  131. data/lib/rubocop/cop/registry.rb +1 -1
  132. data/lib/rubocop/cop/security/eval.rb +1 -0
  133. data/lib/rubocop/cop/security/json_load.rb +1 -0
  134. data/lib/rubocop/cop/security/marshal_load.rb +1 -0
  135. data/lib/rubocop/cop/security/open.rb +1 -0
  136. data/lib/rubocop/cop/security/yaml_load.rb +1 -0
  137. data/lib/rubocop/cop/severity.rb +3 -3
  138. data/lib/rubocop/cop/style/access_modifier_declarations.rb +1 -0
  139. data/lib/rubocop/cop/style/alias.rb +1 -0
  140. data/lib/rubocop/cop/style/arguments_forwarding.rb +3 -0
  141. data/lib/rubocop/cop/style/array_coercion.rb +2 -0
  142. data/lib/rubocop/cop/style/array_join.rb +1 -0
  143. data/lib/rubocop/cop/style/ascii_comments.rb +1 -1
  144. data/lib/rubocop/cop/style/attr.rb +1 -0
  145. data/lib/rubocop/cop/style/case_equality.rb +2 -1
  146. data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -0
  147. data/lib/rubocop/cop/style/collection_compact.rb +2 -0
  148. data/lib/rubocop/cop/style/colon_method_call.rb +1 -0
  149. data/lib/rubocop/cop/style/command_literal.rb +1 -1
  150. data/lib/rubocop/cop/style/conditional_assignment.rb +2 -0
  151. data/lib/rubocop/cop/style/constant_visibility.rb +28 -0
  152. data/lib/rubocop/cop/style/date_time.rb +3 -0
  153. data/lib/rubocop/cop/style/dir.rb +1 -0
  154. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +49 -9
  155. data/lib/rubocop/cop/style/documentation.rb +5 -0
  156. data/lib/rubocop/cop/style/documentation_method.rb +1 -0
  157. data/lib/rubocop/cop/style/double_negation.rb +3 -2
  158. data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -0
  159. data/lib/rubocop/cop/style/each_with_object.rb +1 -0
  160. data/lib/rubocop/cop/style/empty_literal.rb +9 -0
  161. data/lib/rubocop/cop/style/endless_method.rb +1 -0
  162. data/lib/rubocop/cop/style/eval_with_location.rb +140 -49
  163. data/lib/rubocop/cop/style/even_odd.rb +1 -0
  164. data/lib/rubocop/cop/style/expand_path_arguments.rb +3 -0
  165. data/lib/rubocop/cop/style/explicit_block_argument.rb +12 -1
  166. data/lib/rubocop/cop/style/exponential_notation.rb +6 -7
  167. data/lib/rubocop/cop/style/float_division.rb +7 -0
  168. data/lib/rubocop/cop/style/format_string.rb +2 -0
  169. data/lib/rubocop/cop/style/format_string_token.rb +19 -2
  170. data/lib/rubocop/cop/style/global_std_stream.rb +1 -0
  171. data/lib/rubocop/cop/style/hash_conversion.rb +105 -0
  172. data/lib/rubocop/cop/style/hash_each_methods.rb +1 -0
  173. data/lib/rubocop/cop/style/hash_except.rb +1 -0
  174. data/lib/rubocop/cop/style/hash_like_case.rb +1 -0
  175. data/lib/rubocop/cop/style/hash_transform_keys.rb +4 -0
  176. data/lib/rubocop/cop/style/hash_transform_values.rb +4 -0
  177. data/lib/rubocop/cop/style/if_inside_else.rb +14 -7
  178. data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +122 -0
  179. data/lib/rubocop/cop/style/implicit_runtime_error.rb +1 -0
  180. data/lib/rubocop/cop/style/inverse_methods.rb +2 -0
  181. data/lib/rubocop/cop/style/min_max.rb +1 -0
  182. data/lib/rubocop/cop/style/mixin_usage.rb +2 -0
  183. data/lib/rubocop/cop/style/module_function.rb +5 -0
  184. data/lib/rubocop/cop/style/multiple_comparison.rb +21 -2
  185. data/lib/rubocop/cop/style/mutable_constant.rb +3 -0
  186. data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -0
  187. data/lib/rubocop/cop/style/nil_comparison.rb +6 -0
  188. data/lib/rubocop/cop/style/nil_lambda.rb +1 -0
  189. data/lib/rubocop/cop/style/non_nil_check.rb +30 -13
  190. data/lib/rubocop/cop/style/numeric_literals.rb +6 -9
  191. data/lib/rubocop/cop/style/numeric_predicate.rb +4 -1
  192. data/lib/rubocop/cop/style/option_hash.rb +1 -0
  193. data/lib/rubocop/cop/style/or_assignment.rb +2 -0
  194. data/lib/rubocop/cop/style/parallel_assignment.rb +6 -0
  195. data/lib/rubocop/cop/style/parentheses_around_condition.rb +1 -0
  196. data/lib/rubocop/cop/style/proc.rb +1 -0
  197. data/lib/rubocop/cop/style/random_with_offset.rb +5 -0
  198. data/lib/rubocop/cop/style/redundant_assignment.rb +1 -0
  199. data/lib/rubocop/cop/style/redundant_begin.rb +7 -1
  200. data/lib/rubocop/cop/style/redundant_conditional.rb +2 -0
  201. data/lib/rubocop/cop/style/redundant_exception.rb +2 -0
  202. data/lib/rubocop/cop/style/redundant_fetch_block.rb +2 -0
  203. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +1 -0
  204. data/lib/rubocop/cop/style/redundant_freeze.rb +1 -0
  205. data/lib/rubocop/cop/style/redundant_parentheses.rb +13 -0
  206. data/lib/rubocop/cop/style/redundant_self_assignment.rb +2 -0
  207. data/lib/rubocop/cop/style/redundant_sort.rb +1 -0
  208. data/lib/rubocop/cop/style/redundant_sort_by.rb +1 -0
  209. data/lib/rubocop/cop/style/regexp_literal.rb +1 -1
  210. data/lib/rubocop/cop/style/rescue_standard_error.rb +2 -0
  211. data/lib/rubocop/cop/style/return_nil.rb +6 -0
  212. data/lib/rubocop/cop/style/safe_navigation.rb +2 -0
  213. data/lib/rubocop/cop/style/sample.rb +1 -0
  214. data/lib/rubocop/cop/style/signal_exception.rb +3 -0
  215. data/lib/rubocop/cop/style/single_argument_dig.rb +1 -0
  216. data/lib/rubocop/cop/style/single_line_methods.rb +5 -2
  217. data/lib/rubocop/cop/style/slicing_with_range.rb +1 -0
  218. data/lib/rubocop/cop/style/sole_nested_conditional.rb +28 -4
  219. data/lib/rubocop/cop/style/special_global_vars.rb +3 -3
  220. data/lib/rubocop/cop/style/stderr_puts.rb +1 -0
  221. data/lib/rubocop/cop/style/string_concatenation.rb +2 -1
  222. data/lib/rubocop/cop/style/string_hash_keys.rb +2 -0
  223. data/lib/rubocop/cop/style/strip.rb +1 -0
  224. data/lib/rubocop/cop/style/struct_inheritance.rb +1 -0
  225. data/lib/rubocop/cop/style/symbol_proc.rb +25 -1
  226. data/lib/rubocop/cop/style/ternary_parentheses.rb +2 -1
  227. data/lib/rubocop/cop/style/trailing_body_on_method_definition.rb +1 -0
  228. data/lib/rubocop/cop/style/trailing_method_end_statement.rb +1 -1
  229. data/lib/rubocop/cop/style/trivial_accessors.rb +1 -0
  230. data/lib/rubocop/cop/style/unless_logical_operators.rb +99 -0
  231. data/lib/rubocop/cop/style/unpack_first.rb +1 -0
  232. data/lib/rubocop/cop/style/while_until_modifier.rb +2 -4
  233. data/lib/rubocop/cop/style/yoda_condition.rb +1 -0
  234. data/lib/rubocop/cop/style/zero_length_predicate.rb +5 -0
  235. data/lib/rubocop/formatter/git_hub_actions_formatter.rb +1 -0
  236. data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
  237. data/lib/rubocop/formatter/simple_text_formatter.rb +2 -1
  238. data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
  239. data/lib/rubocop/magic_comment.rb +30 -1
  240. data/lib/rubocop/name_similarity.rb +1 -1
  241. data/lib/rubocop/options.rb +1 -1
  242. data/lib/rubocop/rspec/expect_offense.rb +5 -2
  243. data/lib/rubocop/runner.rb +1 -0
  244. data/lib/rubocop/target_ruby.rb +21 -13
  245. data/lib/rubocop/version.rb +2 -2
  246. metadata +21 -7
@@ -77,6 +77,7 @@ module RuboCop
77
77
 
78
78
  RESTRICT_ON_SEND = %i[private protected public module_function].freeze
79
79
 
80
+ # @!method access_modifier_with_symbol?(node)
80
81
  def_node_matcher :access_modifier_with_symbol?, <<~PATTERN
81
82
  (send nil? {:private :protected :public} (sym _))
82
83
  PATTERN
@@ -145,6 +145,7 @@ module RuboCop
145
145
  corrector.replace(node.old_identifier, node.old_identifier.source[1..-1])
146
146
  end
147
147
 
148
+ # @!method identifier(node)
148
149
  def_node_matcher :identifier, <<~PATTERN
149
150
  (sym $_)
150
151
  PATTERN
@@ -47,14 +47,17 @@ module RuboCop
47
47
 
48
48
  MSG = 'Use arguments forwarding.'
49
49
 
50
+ # @!method use_rest_arguments?(node)
50
51
  def_node_matcher :use_rest_arguments?, <<~PATTERN
51
52
  (args (restarg $_) $...)
52
53
  PATTERN
53
54
 
55
+ # @!method only_rest_arguments?(node, name)
54
56
  def_node_matcher :only_rest_arguments?, <<~PATTERN
55
57
  (send _ _ (splat (lvar %1)))
56
58
  PATTERN
57
59
 
60
+ # @!method forwarding_method_arguments?(node, rest_name, block_name, kwargs_name)
58
61
  def_node_matcher :forwarding_method_arguments?, <<~PATTERN
59
62
  {
60
63
  (send _ _
@@ -26,10 +26,12 @@ module RuboCop
26
26
  SPLAT_MSG = 'Use `Array(%<arg>s)` instead of `[*%<arg>s]`.'
27
27
  CHECK_MSG = 'Use `Array(%<arg>s)` instead of explicit `Array` check.'
28
28
 
29
+ # @!method array_splat?(node)
29
30
  def_node_matcher :array_splat?, <<~PATTERN
30
31
  (array (splat $_))
31
32
  PATTERN
32
33
 
34
+ # @!method unless_array?(node)
33
35
  def_node_matcher :unless_array?, <<~PATTERN
34
36
  (if
35
37
  (send
@@ -23,6 +23,7 @@ module RuboCop
23
23
  MSG = 'Favor `Array#join` over `Array#*`.'
24
24
  RESTRICT_ON_SEND = %i[*].freeze
25
25
 
26
+ # @!method join_candidate?(node)
26
27
  def_node_matcher :join_candidate?, '(send $array :* $str)'
27
28
 
28
29
  def on_send(node)
@@ -7,7 +7,7 @@ module RuboCop
7
7
  module Style
8
8
  # This cop checks for non-ascii (non-English) characters
9
9
  # in comments. You could set an array of allowed non-ascii chars in
10
- # AllowedChars attribute (empty by default).
10
+ # `AllowedChars` attribute (copyright notice "©" by default).
11
11
  #
12
12
  # @example
13
13
  # # bad
@@ -62,6 +62,7 @@ module RuboCop
62
62
  end
63
63
  end
64
64
 
65
+ # @!method class_eval?(node)
65
66
  def_node_matcher :class_eval?, <<~PATTERN
66
67
  (block (send _ {:class_eval :module_eval}) ...)
67
68
  PATTERN
@@ -35,6 +35,7 @@ module RuboCop
35
35
  MSG = 'Avoid the use of the case equality operator `===`.'
36
36
  RESTRICT_ON_SEND = %i[===].freeze
37
37
 
38
+ # @!method case_equality?(node)
38
39
  def_node_matcher :case_equality?, '(send $#const? :=== $_)'
39
40
 
40
41
  def on_send(node)
@@ -64,7 +65,7 @@ module RuboCop
64
65
  # The automatic correction from `a === b` to `a.match?(b)` needs to
65
66
  # consider `Regexp.last_match?`, `$~`, `$1`, and etc.
66
67
  # This correction is expected to be supported by `Performance/Regexp` cop.
67
- # See: https://github.com/rubocop-hq/rubocop-performance/issues/152
68
+ # See: https://github.com/rubocop/rubocop-performance/issues/152
68
69
  #
69
70
  # So here is noop.
70
71
  when :begin
@@ -25,6 +25,7 @@ module RuboCop
25
25
 
26
26
  RESTRICT_ON_SEND = %i[== equal? eql?].freeze
27
27
 
28
+ # @!method class_comparison_candidate?(node)
28
29
  def_node_matcher :class_comparison_candidate?, <<~PATTERN
29
30
  (send
30
31
  {$(send _ :class) (send $(send _ :class) :name)}
@@ -35,6 +35,7 @@ module RuboCop
35
35
 
36
36
  RESTRICT_ON_SEND = %i[reject reject! select select!].freeze
37
37
 
38
+ # @!method reject_method?(node)
38
39
  def_node_matcher :reject_method?, <<~PATTERN
39
40
  (block
40
41
  (send
@@ -44,6 +45,7 @@ module RuboCop
44
45
  $(lvar _) :nil?))
45
46
  PATTERN
46
47
 
48
+ # @!method select_method?(node)
47
49
  def_node_matcher :select_method?, <<~PATTERN
48
50
  (block
49
51
  (send
@@ -22,6 +22,7 @@ module RuboCop
22
22
 
23
23
  MSG = 'Do not use `::` for method calls.'
24
24
 
25
+ # @!method java_type_node?(node)
25
26
  def_node_matcher :java_type_node?, <<~PATTERN
26
27
  (send
27
28
  (const nil? :Java) _)
@@ -165,7 +165,7 @@ module RuboCop
165
165
  end
166
166
 
167
167
  def preferred_delimiter
168
- (command_delimiter || default_delimiter).split(//)
168
+ (command_delimiter || default_delimiter).split('')
169
169
  end
170
170
 
171
171
  def command_delimiter
@@ -231,6 +231,7 @@ module RuboCop
231
231
 
232
232
  # The shovel operator `<<` does not have its own type. It is a `send`
233
233
  # type.
234
+ # @!method assignment_type?(node)
234
235
  def_node_matcher :assignment_type?, <<~PATTERN
235
236
  {
236
237
  #{ASSIGNMENT_TYPES.join(' ')}
@@ -300,6 +301,7 @@ module RuboCop
300
301
  style == :assign_inside_condition && assignment_rhs_exist?(node)
301
302
  end
302
303
 
304
+ # @!method candidate_condition?(node)
303
305
  def_node_matcher :candidate_condition?, '[{if case} !#allowed_ternary?]'
304
306
 
305
307
  def allowed_ternary?(assignment)
@@ -26,6 +26,24 @@ module RuboCop
26
26
  # public_constant :BAZ
27
27
  # end
28
28
  #
29
+ # @example IgnoreModules: false (default)
30
+ # # bad
31
+ # class Foo
32
+ # MyClass = Struct.new()
33
+ # end
34
+ #
35
+ # # good
36
+ # class Foo
37
+ # MyClass = Struct.new()
38
+ # public_constant :MyClass
39
+ # end
40
+ #
41
+ # @example IgnoreModules: true
42
+ # # good
43
+ # class Foo
44
+ # MyClass = Struct.new()
45
+ # end
46
+ #
29
47
  class ConstantVisibility < Base
30
48
  MSG = 'Explicitly make `%<constant_name>s` public or private using ' \
31
49
  'either `#public_constant` or `#private_constant`.'
@@ -33,6 +51,7 @@ module RuboCop
33
51
  def on_casgn(node)
34
52
  return unless class_or_module_scope?(node)
35
53
  return if visibility_declaration?(node)
54
+ return if ignore_modules? && module?(node)
36
55
 
37
56
  message = message(node)
38
57
  add_offense(node, message: message)
@@ -40,6 +59,14 @@ module RuboCop
40
59
 
41
60
  private
42
61
 
62
+ def ignore_modules?
63
+ cop_config.fetch('IgnoreModules', false)
64
+ end
65
+
66
+ def module?(node)
67
+ node.children.last.class_constructor?
68
+ end
69
+
43
70
  def message(node)
44
71
  _namespace, constant_name, _value = *node
45
72
 
@@ -65,6 +92,7 @@ module RuboCop
65
92
  end
66
93
  end
67
94
 
95
+ # @!method visibility_declaration_for?(node, const_name)
68
96
  def_node_matcher :visibility_declaration_for?, <<~PATTERN
69
97
  (send nil? {:public_constant :private_constant} ({sym str} #match_name?(%1)))
70
98
  PATTERN
@@ -47,14 +47,17 @@ module RuboCop
47
47
  CLASS_MSG = 'Prefer Time over DateTime.'
48
48
  COERCION_MSG = 'Do not use #to_datetime.'
49
49
 
50
+ # @!method date_time?(node)
50
51
  def_node_matcher :date_time?, <<~PATTERN
51
52
  (send (const {nil? (cbase)} :DateTime) ...)
52
53
  PATTERN
53
54
 
55
+ # @!method historic_date?(node)
54
56
  def_node_matcher :historic_date?, <<~PATTERN
55
57
  (send _ _ _ (const (const {nil? (cbase)} :Date) _))
56
58
  PATTERN
57
59
 
60
+ # @!method to_datetime?(node)
58
61
  def_node_matcher :to_datetime?, <<~PATTERN
59
62
  (send _ :to_datetime)
60
63
  PATTERN
@@ -22,6 +22,7 @@ module RuboCop
22
22
  MSG = "Use `__dir__` to get an absolute path to the current file's directory."
23
23
  RESTRICT_ON_SEND = %i[expand_path dirname].freeze
24
24
 
25
+ # @!method dir_replacement?(node)
25
26
  def_node_matcher :dir_replacement?, <<~PATTERN
26
27
  {(send (const {nil? cbase} :File) :expand_path (send (const {nil? cbase} :File) :dirname #file_keyword?))
27
28
  (send (const {nil? cbase} :File) :dirname (send (const {nil? cbase} :File) :realpath #file_keyword?))}
@@ -9,37 +9,77 @@ module RuboCop
9
9
  # This is useful if want to make sure that every RuboCop error gets fixed
10
10
  # and not quickly disabled with a comment.
11
11
  #
12
+ # Specific cops can be allowed with the `AllowedCops` configuration. Note that
13
+ # if this configuration is set, `rubocop:disable all` is still disallowed.
14
+ #
12
15
  # @example
13
16
  # # bad
14
17
  # # rubocop:disable Metrics/AbcSize
15
- # def f
18
+ # def foo
16
19
  # end
17
20
  # # rubocop:enable Metrics/AbcSize
18
21
  #
19
22
  # # good
20
- # def fixed_method_name_and_no_rubocop_comments
23
+ # def foo
24
+ # end
25
+ #
26
+ # @example AllowedCops: [Metrics/AbcSize]
27
+ # # good
28
+ # # rubocop:disable Metrics/AbcSize
29
+ # def foo
21
30
  # end
31
+ # # rubocop:enable Metrics/AbcSize
22
32
  #
23
33
  class DisableCopsWithinSourceCodeDirective < Base
24
34
  extend AutoCorrector
25
35
 
26
36
  # rubocop:enable Lint/RedundantCopDisableDirective
27
- MSG = 'Comment to disable/enable RuboCop.'
37
+ MSG = 'Rubocop disable/enable directives are not permitted.'
38
+ MSG_FOR_COPS = 'Rubocop disable/enable directives for %<cops>s are not permitted.'
28
39
 
29
40
  def on_new_investigation
30
41
  processed_source.comments.each do |comment|
31
- next unless rubocop_directive_comment?(comment)
42
+ directive_cops = directive_cops(comment)
43
+ disallowed_cops = directive_cops - allowed_cops
32
44
 
33
- add_offense(comment) do |corrector|
34
- corrector.replace(comment, '')
35
- end
45
+ next unless disallowed_cops.any?
46
+
47
+ register_offense(comment, directive_cops, disallowed_cops)
36
48
  end
37
49
  end
38
50
 
39
51
  private
40
52
 
41
- def rubocop_directive_comment?(comment)
42
- CommentConfig::COMMENT_DIRECTIVE_REGEXP.match?(comment.text)
53
+ def register_offense(comment, directive_cops, disallowed_cops)
54
+ message = if any_cops_allowed?
55
+ format(MSG_FOR_COPS, cops: "`#{disallowed_cops.join('`, `')}`")
56
+ else
57
+ MSG
58
+ end
59
+
60
+ add_offense(comment, message: message) do |corrector|
61
+ replacement = ''
62
+
63
+ if directive_cops.length != disallowed_cops.length
64
+ replacement = comment.text.sub(/#{Regexp.union(disallowed_cops)},?\s*/, '')
65
+ .sub(/,\s*$/, '')
66
+ end
67
+
68
+ corrector.replace(comment, replacement)
69
+ end
70
+ end
71
+
72
+ def directive_cops(comment)
73
+ match = CommentConfig::COMMENT_DIRECTIVE_REGEXP.match(comment.text)
74
+ match && match[2] ? match[2].split(',').map(&:strip) : []
75
+ end
76
+
77
+ def allowed_cops
78
+ Array(cop_config['AllowedCops'])
79
+ end
80
+
81
+ def any_cops_allowed?
82
+ allowed_cops.any?
43
83
  end
44
84
  end
45
85
  end
@@ -65,8 +65,13 @@ module RuboCop
65
65
 
66
66
  MSG = 'Missing top-level %<type>s documentation comment.'
67
67
 
68
+ # @!method constant_definition?(node)
68
69
  def_node_matcher :constant_definition?, '{class module casgn}'
70
+
71
+ # @!method outer_module(node)
69
72
  def_node_search :outer_module, '(const (const nil? _) _)'
73
+
74
+ # @!method constant_visibility_declaration?(node)
70
75
  def_node_matcher :constant_visibility_declaration?, <<~PATTERN
71
76
  (send nil? {:public_constant :private_constant} ({sym str} _))
72
77
  PATTERN
@@ -97,6 +97,7 @@ module RuboCop
97
97
 
98
98
  MSG = 'Missing method documentation comment.'
99
99
 
100
+ # @!method module_function_node?(node)
100
101
  def_node_matcher :module_function_node?, <<~PATTERN
101
102
  (send nil? :module_function ...)
102
103
  PATTERN
@@ -5,8 +5,8 @@ module RuboCop
5
5
  module Style
6
6
  # This cop checks for uses of double negation (`!!`) to convert something to a boolean value.
7
7
  #
8
- # When using `EnforcedStyle: allowed_in_returns`, allow double nagation in contexts
9
- # that use boolean as a return value. When using `EnforcedStyle: forbidden`, double nagation
8
+ # When using `EnforcedStyle: allowed_in_returns`, allow double negation in contexts
9
+ # that use boolean as a return value. When using `EnforcedStyle: forbidden`, double negation
10
10
  # should be forbidden always.
11
11
  #
12
12
  # @example
@@ -39,6 +39,7 @@ module RuboCop
39
39
  MSG = 'Avoid the use of double negation (`!!`).'
40
40
  RESTRICT_ON_SEND = %i[!].freeze
41
41
 
42
+ # @!method double_negative?(node)
42
43
  def_node_matcher :double_negative?, '(send (send _ :!) :!)'
43
44
 
44
45
  def on_send(node)
@@ -46,6 +46,7 @@ module RuboCop
46
46
 
47
47
  private
48
48
 
49
+ # @!method offending_each_range(node)
49
50
  def_node_matcher :offending_each_range, <<~PATTERN
50
51
  (block (send (begin (${irange erange} (int $_) (int $_))) :each) (args) ...)
51
52
  PATTERN
@@ -23,6 +23,7 @@ module RuboCop
23
23
  MSG = 'Use `each_with_object` instead of `%<method>s`.'
24
24
  METHODS = %i[inject reduce].freeze
25
25
 
26
+ # @!method each_with_object_candidate?(node)
26
27
  def_node_matcher :each_with_object_candidate?, <<~PATTERN
27
28
  (block $(send _ {:inject :reduce} _) $_ $_)
28
29
  PATTERN
@@ -27,11 +27,20 @@ module RuboCop
27
27
 
28
28
  RESTRICT_ON_SEND = %i[new].freeze
29
29
 
30
+ # @!method array_node(node)
30
31
  def_node_matcher :array_node, '(send (const {nil? cbase} :Array) :new)'
32
+
33
+ # @!method hash_node(node)
31
34
  def_node_matcher :hash_node, '(send (const {nil? cbase} :Hash) :new)'
35
+
36
+ # @!method str_node(node)
32
37
  def_node_matcher :str_node, '(send (const {nil? cbase} :String) :new)'
38
+
39
+ # @!method array_with_block(node)
33
40
  def_node_matcher :array_with_block,
34
41
  '(block (send (const {nil? cbase} :Array) :new) args _)'
42
+
43
+ # @!method hash_with_block(node)
35
44
  def_node_matcher :hash_with_block, <<~PATTERN
36
45
  {
37
46
  (block (send (const {nil? cbase} :Hash) :new) args _)
@@ -11,6 +11,7 @@ module RuboCop
11
11
  # Other method definition types are not considered by this cop.
12
12
  #
13
13
  # The supported styles are:
14
+ #
14
15
  # * allow_single_line (default) - only single line endless method definitions are allowed.
15
16
  # * allow_always - all endless method definitions are allowed.
16
17
  # * disallow - all endless method definitions are disallowed.
@@ -3,9 +3,19 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # This cop checks `eval` method usage. `eval` can receive source location
7
- # metadata, that are filename and line number. The metadata is used by
8
- # backtraces. This cop recommends to pass the metadata to `eval` method.
6
+ # This cop ensures that eval methods (`eval`, `instance_eval`, `class_eval`
7
+ # and `module_eval`) are given filename and line number values (`__FILE__`
8
+ # and `__LINE__`). This data is used to ensure that any errors raised
9
+ # within the evaluated code will be given the correct identification
10
+ # in a backtrace.
11
+ #
12
+ # The cop also checks that the line number given relative to `__LINE__` is
13
+ # correct.
14
+ #
15
+ # This cop will autocorrect incorrect or missing filename and line number
16
+ # values. However, if `eval` is called without a binding argument, the cop
17
+ # will not attempt to automatically add a binding, or add filename and
18
+ # line values.
9
19
  #
10
20
  # @example
11
21
  # # bad
@@ -31,30 +41,36 @@ module RuboCop
31
41
  # def do_something
32
42
  # end
33
43
  # RUBY
44
+ #
45
+ # This cop works only when a string literal is given as a code string.
46
+ # No offence is reported if a string variable is given as below:
47
+ #
48
+ # @example
49
+ # # not checked
50
+ # code = <<-RUBY
51
+ # def do_something
52
+ # end
53
+ # RUBY
54
+ # eval code
55
+ #
34
56
  class EvalWithLocation < Base
35
- MSG = 'Pass `__FILE__` and `__LINE__` to `eval` method, ' \
36
- 'as they are used by backtraces.'
37
- MSG_INCORRECT_LINE = 'Use `%<expected>s` instead of `%<actual>s`, ' \
38
- 'as they are used by backtraces.'
57
+ extend AutoCorrector
58
+
59
+ MSG = 'Pass `__FILE__` and `__LINE__` to `%<method_name>s`.'
60
+ MSG_EVAL = 'Pass a binding, `__FILE__` and `__LINE__` to `eval`.'
61
+ MSG_INCORRECT_FILE = 'Incorrect file for `%<method_name>s`; ' \
62
+ 'use `%<expected>s` instead of `%<actual>s`.'
63
+ MSG_INCORRECT_LINE = 'Incorrect line number for `%<method_name>s`; ' \
64
+ 'use `%<expected>s` instead of `%<actual>s`.'
39
65
 
40
66
  RESTRICT_ON_SEND = %i[eval class_eval module_eval instance_eval].freeze
41
67
 
42
- def_node_matcher :eval_without_location?, <<~PATTERN
43
- {
44
- (send nil? :eval ${str dstr})
45
- (send nil? :eval ${str dstr} _)
46
- (send nil? :eval ${str dstr} _ #special_file_keyword?)
47
- (send nil? :eval ${str dstr} _ #special_file_keyword? _)
48
-
49
- (send _ {:class_eval :module_eval :instance_eval}
50
- ${str dstr})
51
- (send _ {:class_eval :module_eval :instance_eval}
52
- ${str dstr} #special_file_keyword?)
53
- (send _ {:class_eval :module_eval :instance_eval}
54
- ${str dstr} #special_file_keyword? _)
55
- }
68
+ # @!method valid_eval_receiver?(node)
69
+ def_node_matcher :valid_eval_receiver?, <<~PATTERN
70
+ { nil? (const {nil? cbase} :Kernel) }
56
71
  PATTERN
57
72
 
73
+ # @!method line_with_offset?(node, sign, num)
58
74
  def_node_matcher :line_with_offset?, <<~PATTERN
59
75
  {
60
76
  (send #special_line_keyword? %1 (int %2))
@@ -63,17 +79,38 @@ module RuboCop
63
79
  PATTERN
64
80
 
65
81
  def on_send(node)
66
- eval_without_location?(node) do |code|
67
- if with_lineno?(node)
68
- on_with_lineno(node, code)
69
- else
70
- add_offense(node)
71
- end
72
- end
82
+ # Classes should not redefine eval, but in case one does, it shouldn't
83
+ # register an offense. Only `eval` without a receiver and `Kernel.eval`
84
+ # are considered.
85
+ return if node.method?(:eval) && !valid_eval_receiver?(node.receiver)
86
+
87
+ code = node.arguments.first
88
+ return unless code && (code.str_type? || code.dstr_type?)
89
+
90
+ check_location(node, code)
73
91
  end
74
92
 
75
93
  private
76
94
 
95
+ def check_location(node, code)
96
+ file, line = file_and_line(node)
97
+
98
+ if line
99
+ check_file(node, file)
100
+ check_line(node, code)
101
+ elsif file
102
+ check_file(node, file)
103
+ add_offense_for_missing_line(node, code)
104
+ else
105
+ add_offense_for_missing_location(node, code)
106
+ end
107
+ end
108
+
109
+ def register_offense(node, &block)
110
+ msg = node.method?(:eval) ? MSG_EVAL : format(MSG, method_name: node.method_name)
111
+ add_offense(node, message: msg, &block)
112
+ end
113
+
77
114
  def special_file_keyword?(node)
78
115
  node.str_type? &&
79
116
  node.source == '__FILE__'
@@ -84,6 +121,15 @@ module RuboCop
84
121
  node.source == '__LINE__'
85
122
  end
86
123
 
124
+ def file_and_line(node)
125
+ base = node.method?(:eval) ? 2 : 1
126
+ [node.arguments[base], node.arguments[base + 1]]
127
+ end
128
+
129
+ def with_binding?(node)
130
+ node.method?(:eval) ? node.arguments.size >= 2 : true
131
+ end
132
+
87
133
  # FIXME: It's a Style/ConditionalAssignment's false positive.
88
134
  # rubocop:disable Style/ConditionalAssignment
89
135
  def with_lineno?(node)
@@ -95,20 +141,34 @@ module RuboCop
95
141
  end
96
142
  # rubocop:enable Style/ConditionalAssignment
97
143
 
98
- def message_incorrect_line(actual, sign, line_diff)
99
- expected =
100
- if line_diff.zero?
101
- '__LINE__'
102
- else
103
- "__LINE__ #{sign} #{line_diff}"
104
- end
105
- format(MSG_INCORRECT_LINE, actual: actual.source, expected: expected)
144
+ def add_offense_for_incorrect_line(method_name, line_node, sign, line_diff)
145
+ expected = expected_line(sign, line_diff)
146
+ message = format(MSG_INCORRECT_LINE,
147
+ method_name: method_name,
148
+ actual: line_node.source,
149
+ expected: expected)
150
+
151
+ add_offense(line_node.loc.expression, message: message) do |corrector|
152
+ corrector.replace(line_node, expected)
153
+ end
154
+ end
155
+
156
+ def check_file(node, file_node)
157
+ return true if special_file_keyword?(file_node)
158
+
159
+ message = format(MSG_INCORRECT_FILE,
160
+ method_name: node.method_name,
161
+ expected: '__FILE__',
162
+ actual: file_node.source)
163
+
164
+ add_offense(file_node, message: message) do |corrector|
165
+ corrector.replace(file_node, '__FILE__')
166
+ end
106
167
  end
107
168
 
108
- def on_with_lineno(node, code)
169
+ def check_line(node, code)
109
170
  line_node = node.arguments.last
110
- lineno_range = line_node.loc.expression
111
- line_diff = string_first_line(code) - lineno_range.first_line
171
+ line_diff = line_difference(line_node, code)
112
172
  if line_diff.zero?
113
173
  add_offense_for_same_line(node, line_node)
114
174
  else
@@ -116,6 +176,10 @@ module RuboCop
116
176
  end
117
177
  end
118
178
 
179
+ def line_difference(line_node, code)
180
+ string_first_line(code) - line_node.loc.expression.first_line
181
+ end
182
+
119
183
  def string_first_line(str_node)
120
184
  if str_node.heredoc?
121
185
  str_node.loc.heredoc_body.first_line
@@ -124,23 +188,50 @@ module RuboCop
124
188
  end
125
189
  end
126
190
 
127
- def add_offense_for_same_line(_node, line_node)
191
+ def add_offense_for_same_line(node, line_node)
128
192
  return if special_line_keyword?(line_node)
129
193
 
130
- add_offense(
131
- line_node.loc.expression,
132
- message: message_incorrect_line(line_node, nil, 0)
133
- )
194
+ add_offense_for_incorrect_line(node.method_name, line_node, nil, 0)
134
195
  end
135
196
 
136
- def add_offense_for_different_line(_node, line_node, line_diff)
197
+ def add_offense_for_different_line(node, line_node, line_diff)
137
198
  sign = line_diff.positive? ? :+ : :-
138
199
  return if line_with_offset?(line_node, sign, line_diff.abs)
139
200
 
140
- add_offense(
141
- line_node.loc.expression,
142
- message: message_incorrect_line(line_node, sign, line_diff.abs)
143
- )
201
+ add_offense_for_incorrect_line(node.method_name, line_node, sign, line_diff.abs)
202
+ end
203
+
204
+ def expected_line(sign, line_diff)
205
+ if line_diff.zero?
206
+ '__LINE__'
207
+ else
208
+ "__LINE__ #{sign} #{line_diff.abs}"
209
+ end
210
+ end
211
+
212
+ def add_offense_for_missing_line(node, code)
213
+ register_offense(node) do |corrector|
214
+ line_str = missing_line(node, code)
215
+ corrector.insert_after(node.loc.expression.end, ", #{line_str}")
216
+ end
217
+ end
218
+
219
+ def add_offense_for_missing_location(node, code)
220
+ if node.method?(:eval) && !with_binding?(node)
221
+ register_offense(node)
222
+ return
223
+ end
224
+
225
+ register_offense(node) do |corrector|
226
+ line_str = missing_line(node, code)
227
+ corrector.insert_after(node.loc.expression.end, ", __FILE__, #{line_str}")
228
+ end
229
+ end
230
+
231
+ def missing_line(node, code)
232
+ line_diff = line_difference(node.arguments.last, code)
233
+ sign = line_diff.positive? ? :+ : :-
234
+ expected_line(sign, line_diff)
144
235
  end
145
236
  end
146
237
  end