rubocop 1.89.0 → 1.91.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 (248) hide show
  1. checksums.yaml +4 -4
  2. data/config/default.yml +309 -14
  3. data/config/obsoletion.yml +9 -0
  4. data/exe/rubocop +1 -1
  5. data/lib/rubocop/cached_data.rb +7 -2
  6. data/lib/rubocop/changed_files.rb +112 -0
  7. data/lib/rubocop/cli/command/execute_runner.rb +52 -1
  8. data/lib/rubocop/cli.rb +11 -7
  9. data/lib/rubocop/comment_config/directive_range.rb +34 -0
  10. data/lib/rubocop/comment_config/disable_next.rb +143 -0
  11. data/lib/rubocop/comment_config/push_pop.rb +55 -0
  12. data/lib/rubocop/comment_config.rb +50 -64
  13. data/lib/rubocop/config.rb +33 -5
  14. data/lib/rubocop/config_loader.rb +13 -6
  15. data/lib/rubocop/config_loader_resolver.rb +50 -9
  16. data/lib/rubocop/config_obsoletion/cop_rule.rb +2 -1
  17. data/lib/rubocop/config_obsoletion/removed_cop.rb +8 -0
  18. data/lib/rubocop/config_obsoletion.rb +1 -1
  19. data/lib/rubocop/config_validator.rb +19 -5
  20. data/lib/rubocop/cop/autocorrect_logic.rb +8 -0
  21. data/lib/rubocop/cop/badge.rb +1 -1
  22. data/lib/rubocop/cop/base.rb +49 -5
  23. data/lib/rubocop/cop/corrector.rb +3 -3
  24. data/lib/rubocop/cop/correctors.rb +2 -2
  25. data/lib/rubocop/cop/gemspec/require_mfa.rb +1 -1
  26. data/lib/rubocop/cop/generator.rb +1 -1
  27. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -2
  28. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +1 -2
  29. data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
  30. data/lib/rubocop/cop/layout/argument_alignment.rb +2 -0
  31. data/lib/rubocop/cop/layout/block_alignment.rb +1 -2
  32. data/lib/rubocop/cop/layout/class_structure.rb +102 -26
  33. data/lib/rubocop/cop/layout/comment_indentation.rb +8 -5
  34. data/lib/rubocop/cop/layout/else_alignment.rb +1 -0
  35. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -2
  36. data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +63 -5
  37. data/lib/rubocop/cop/layout/empty_lines_after_module_inclusion.rb +1 -1
  38. data/lib/rubocop/cop/layout/end_alignment.rb +1 -2
  39. data/lib/rubocop/cop/layout/extra_spacing.rb +105 -3
  40. data/lib/rubocop/cop/layout/first_argument_indentation.rb +21 -1
  41. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +17 -4
  42. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +11 -0
  43. data/lib/rubocop/cop/layout/hash_alignment.rb +6 -5
  44. data/lib/rubocop/cop/layout/indentation_width.rb +2 -2
  45. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -2
  46. data/lib/rubocop/cop/layout/line_length.rb +20 -3
  47. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -2
  48. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +5 -5
  49. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +1 -2
  50. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +14 -3
  51. data/lib/rubocop/cop/layout/space_around_operators.rb +12 -1
  52. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +2 -4
  53. data/lib/rubocop/cop/lint/ambiguous_range.rb +1 -2
  54. data/lib/rubocop/cop/lint/argument_mismatch.rb +99 -0
  55. data/lib/rubocop/cop/lint/assignment_in_condition.rb +2 -0
  56. data/lib/rubocop/cop/lint/constant_reassignment.rb +17 -11
  57. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +165 -15
  58. data/lib/rubocop/cop/lint/deprecated_reference.rb +11 -2
  59. data/lib/rubocop/cop/lint/duplicate_methods.rb +113 -15
  60. data/lib/rubocop/cop/lint/empty_block.rb +1 -1
  61. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -2
  62. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -2
  63. data/lib/rubocop/cop/lint/interpolation_check.rb +1 -2
  64. data/lib/rubocop/cop/lint/literal_as_condition.rb +11 -8
  65. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +3 -6
  66. data/lib/rubocop/cop/lint/misplaced_magic_comment.rb +185 -0
  67. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +25 -12
  68. data/lib/rubocop/cop/lint/name_typo.rb +53 -6
  69. data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
  70. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +1 -1
  71. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +15 -0
  72. data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +17 -1
  73. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +122 -29
  74. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +47 -7
  75. data/lib/rubocop/cop/lint/redundant_require_statement.rb +1 -2
  76. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +1 -2
  77. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +1 -2
  78. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +1 -2
  79. data/lib/rubocop/cop/lint/redundant_with_index.rb +1 -2
  80. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +1 -2
  81. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +2 -4
  82. data/lib/rubocop/cop/lint/super_argument_mismatch.rb +179 -0
  83. data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +1 -2
  84. data/lib/rubocop/cop/lint/to_enum_arguments.rb +1 -2
  85. data/lib/rubocop/cop/lint/unreachable_code.rb +1 -2
  86. data/lib/rubocop/cop/lint/unused_private_method.rb +94 -17
  87. data/lib/rubocop/cop/lint/useless_access_modifier.rb +1 -2
  88. data/lib/rubocop/cop/lint/useless_assignment.rb +1 -2
  89. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +36 -0
  90. data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
  91. data/lib/rubocop/cop/lint/useless_rescue.rb +1 -2
  92. data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +61 -7
  93. data/lib/rubocop/cop/lint/void.rb +1 -2
  94. data/lib/rubocop/cop/lint.rb +3 -0
  95. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -2
  96. data/lib/rubocop/cop/migration/department_name.rb +1 -2
  97. data/lib/rubocop/cop/mixin/alignment.rb +1 -1
  98. data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -1
  99. data/lib/rubocop/cop/mixin/comments_help.rb +1 -2
  100. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +1 -2
  101. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +11 -1
  102. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +7 -4
  103. data/lib/rubocop/cop/mixin/hash_subset.rb +1 -2
  104. data/lib/rubocop/cop/mixin/hash_transform_method.rb +1 -1
  105. data/lib/rubocop/cop/mixin/indexed_method_arity.rb +94 -0
  106. data/lib/rubocop/cop/mixin/line_length_help.rb +7 -1
  107. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +62 -6
  108. data/lib/rubocop/cop/mixin/range_help.rb +1 -2
  109. data/lib/rubocop/cop/mixin/statement_modifier.rb +13 -7
  110. data/lib/rubocop/cop/mixin/trailing_comma.rb +2 -4
  111. data/lib/rubocop/cop/mixin.rb +6 -2
  112. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +16 -0
  113. data/lib/rubocop/cop/naming/block_forwarding.rb +4 -1
  114. data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
  115. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +2 -4
  116. data/lib/rubocop/cop/naming/method_name.rb +5 -2
  117. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +1 -2
  118. data/lib/rubocop/cop/offense.rb +27 -4
  119. data/lib/rubocop/cop/registry.rb +43 -11
  120. data/lib/rubocop/cop/severity.rb +12 -0
  121. data/lib/rubocop/cop/style/access_modifier_declarations.rb +3 -2
  122. data/lib/rubocop/cop/style/accessor_grouping.rb +1 -2
  123. data/lib/rubocop/cop/style/arguments_forwarding.rb +5 -8
  124. data/lib/rubocop/cop/style/array_first_last.rb +1 -2
  125. data/lib/rubocop/cop/style/bitwise_predicate.rb +1 -2
  126. data/lib/rubocop/cop/style/block_delimiters.rb +3 -6
  127. data/lib/rubocop/cop/style/case_like_if.rb +5 -7
  128. data/lib/rubocop/cop/style/class_and_module_children.rb +1 -2
  129. data/lib/rubocop/cop/style/combinable_loops.rb +1 -2
  130. data/lib/rubocop/cop/style/concat_array_literals.rb +1 -2
  131. data/lib/rubocop/cop/style/conditional_assignment.rb +1 -2
  132. data/lib/rubocop/cop/style/constant_visibility.rb +6 -3
  133. data/lib/rubocop/cop/style/copyright.rb +1 -2
  134. data/lib/rubocop/cop/style/data_inheritance.rb +14 -0
  135. data/lib/rubocop/cop/style/directive_scope.rb +304 -0
  136. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +83 -13
  137. data/lib/rubocop/cop/style/documentation_method.rb +1 -9
  138. data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
  139. data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -1
  140. data/lib/rubocop/cop/style/empty_case_condition.rb +1 -2
  141. data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -1
  142. data/lib/rubocop/cop/style/empty_method.rb +12 -2
  143. data/lib/rubocop/cop/style/endless_method.rb +31 -12
  144. data/lib/rubocop/cop/style/file_null.rb +2 -2
  145. data/lib/rubocop/cop/style/float_division.rb +10 -16
  146. data/lib/rubocop/cop/style/for.rb +5 -0
  147. data/lib/rubocop/cop/style/format_string_token.rb +1 -2
  148. data/lib/rubocop/cop/style/guard_clause.rb +5 -2
  149. data/lib/rubocop/cop/style/hash_each_methods.rb +1 -2
  150. data/lib/rubocop/cop/style/hash_lookup_method.rb +3 -0
  151. data/lib/rubocop/cop/style/hash_syntax.rb +1 -2
  152. data/lib/rubocop/cop/style/identical_conditional_branches.rb +2 -4
  153. data/lib/rubocop/cop/style/if_inside_else.rb +1 -2
  154. data/lib/rubocop/cop/style/if_unless_modifier.rb +1 -2
  155. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +1 -2
  156. data/lib/rubocop/cop/style/magic_comment_format.rb +1 -1
  157. data/lib/rubocop/cop/style/map_to_hash.rb +1 -2
  158. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +2 -4
  159. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +1 -1
  160. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +1 -2
  161. data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -2
  162. data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -2
  163. data/lib/rubocop/cop/style/negative_array_index.rb +2 -4
  164. data/lib/rubocop/cop/style/nested_modifier.rb +9 -4
  165. data/lib/rubocop/cop/style/nil_comparison.rb +36 -9
  166. data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
  167. data/lib/rubocop/cop/style/non_nil_check.rb +18 -2
  168. data/lib/rubocop/cop/style/not.rb +3 -1
  169. data/lib/rubocop/cop/style/numeric_literal_prefix.rb +11 -1
  170. data/lib/rubocop/cop/style/one_line_conditional.rb +1 -1
  171. data/lib/rubocop/cop/style/operator_method_call.rb +1 -2
  172. data/lib/rubocop/cop/style/parallel_assignment.rb +1 -2
  173. data/lib/rubocop/cop/style/parentheses_around_condition.rb +6 -1
  174. data/lib/rubocop/cop/style/redundant_assignment.rb +1 -2
  175. data/lib/rubocop/cop/style/redundant_condition.rb +6 -8
  176. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +11 -3
  177. data/lib/rubocop/cop/style/redundant_each.rb +1 -2
  178. data/lib/rubocop/cop/style/redundant_fetch_block.rb +1 -1
  179. data/lib/rubocop/cop/style/redundant_format.rb +2 -4
  180. data/lib/rubocop/cop/style/redundant_parentheses.rb +13 -5
  181. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +1 -2
  182. data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +6 -5
  183. data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +6 -6
  184. data/lib/rubocop/cop/style/redundant_return.rb +1 -2
  185. data/lib/rubocop/cop/style/redundant_self_assignment.rb +1 -2
  186. data/lib/rubocop/cop/style/redundant_string_escape.rb +1 -2
  187. data/lib/rubocop/cop/style/rescue_modifier.rb +1 -2
  188. data/lib/rubocop/cop/style/safe_navigation.rb +1 -2
  189. data/lib/rubocop/cop/style/sample.rb +11 -6
  190. data/lib/rubocop/cop/style/select_by_regexp.rb +1 -2
  191. data/lib/rubocop/cop/style/semicolon.rb +2 -4
  192. data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
  193. data/lib/rubocop/cop/style/single_line_do_end_block.rb +1 -2
  194. data/lib/rubocop/cop/style/sole_nested_conditional.rb +1 -2
  195. data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
  196. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +2 -0
  197. data/lib/rubocop/cop/style/string_concatenation.rb +18 -5
  198. data/lib/rubocop/cop/style/struct_inheritance.rb +14 -0
  199. data/lib/rubocop/cop/style/super_arguments.rb +1 -2
  200. data/lib/rubocop/cop/style/symbol_proc.rb +1 -2
  201. data/lib/rubocop/cop/style/time_now.rb +41 -0
  202. data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
  203. data/lib/rubocop/cop/style/yoda_condition.rb +1 -2
  204. data/lib/rubocop/cop/style.rb +2 -1
  205. data/lib/rubocop/cop/team.rb +11 -3
  206. data/lib/rubocop/cop/util.rb +3 -5
  207. data/lib/rubocop/cop/variable_force/variable.rb +1 -2
  208. data/lib/rubocop/cops_documentation_generator.rb +26 -8
  209. data/lib/rubocop/directive_comment.rb +73 -10
  210. data/lib/rubocop/formatter/disabled_config_formatter.rb +19 -1
  211. data/lib/rubocop/formatter/emacs_style_formatter.rb +3 -1
  212. data/lib/rubocop/formatter/formatter_set.rb +2 -1
  213. data/lib/rubocop/formatter/github_actions_formatter.rb +6 -5
  214. data/lib/rubocop/formatter/html_formatter.rb +2 -4
  215. data/lib/rubocop/formatter/json_formatter.rb +11 -6
  216. data/lib/rubocop/formatter/junit_formatter.rb +26 -9
  217. data/lib/rubocop/formatter/offense_count_formatter.rb +1 -2
  218. data/lib/rubocop/formatter/sarif_formatter.rb +181 -0
  219. data/lib/rubocop/formatter/simple_text_formatter.rb +4 -3
  220. data/lib/rubocop/formatter/tap_formatter.rb +3 -1
  221. data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -2
  222. data/lib/rubocop/formatter.rb +1 -0
  223. data/lib/rubocop/lockfile.rb +18 -0
  224. data/lib/rubocop/lsp/diagnostic.rb +4 -8
  225. data/lib/rubocop/lsp/routes.rb +48 -19
  226. data/lib/rubocop/magic_comment.rb +27 -0
  227. data/lib/rubocop/mcp/server.rb +1 -2
  228. data/lib/rubocop/options.rb +69 -7
  229. data/lib/rubocop/path_util.rb +2 -3
  230. data/lib/rubocop/plugin/configuration_integrator.rb +6 -3
  231. data/lib/rubocop/plugin/loader.rb +1 -1
  232. data/lib/rubocop/rake_task.rb +1 -2
  233. data/lib/rubocop/remote_config.rb +4 -4
  234. data/lib/rubocop/result_cache.rb +16 -5
  235. data/lib/rubocop/rspec/expect_offense.rb +2 -4
  236. data/lib/rubocop/rspec/shared_contexts.rb +4 -2
  237. data/lib/rubocop/runner.rb +90 -44
  238. data/lib/rubocop/server/cache.rb +1 -2
  239. data/lib/rubocop/server/cli.rb +2 -4
  240. data/lib/rubocop/server.rb +14 -0
  241. data/lib/rubocop/target_finder.rb +4 -1
  242. data/lib/rubocop/todo_audit.rb +111 -0
  243. data/lib/rubocop/unified_diff.rb +257 -0
  244. data/lib/rubocop/version.rb +3 -5
  245. data/lib/rubocop.rb +7 -1
  246. data/lib/ruby_lsp/rubocop/addon.rb +1 -2
  247. metadata +18 -6
  248. data/lib/rubocop/cop/style/double_cop_disable_directive.rb +0 -46
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # Shared machinery for cops that compare a call site's arguments against
6
+ # a method signature from the project index (`Rubydex::Signature`).
7
+ #
8
+ # A signature is reduced to a shape - `[min, max, has_keywords]` where
9
+ # `max` is nil for a rest parameter - and the number of positional
10
+ # arguments a call passes is counted with Ruby's semantics for trailing
11
+ # keyword hashes: keywords passed to a method with no keyword parameters
12
+ # collapse into a single positional hash.
13
+ module IndexedMethodArity
14
+ private
15
+
16
+ def arity_satisfied?(given, min, max)
17
+ given >= min && (max.nil? || given <= max)
18
+ end
19
+
20
+ def expected_range(min, max)
21
+ return "#{min}+" if max.nil?
22
+ return min.to_s if min == max
23
+
24
+ "#{min}..#{max}"
25
+ end
26
+
27
+ # The agreed `[min, max, has_keywords]` shape of an indexed member's
28
+ # method definitions, or nil when the member is not backed by plain
29
+ # method definitions (attr, alias), has no signature, forwards
30
+ # arguments, or its definitions disagree on arity (e.g. reopened with
31
+ # a different one).
32
+ def indexed_member_shape(member)
33
+ definitions = member.definitions.grep(Rubydex::MethodDefinition)
34
+ return nil if definitions.empty?
35
+
36
+ signature_shape(definitions.flat_map(&:signatures))
37
+ end
38
+
39
+ def signature_shape(signatures)
40
+ shapes = signatures.filter_map { |signature| shape_for(signature) }.uniq
41
+ shapes.one? ? shapes.first : nil
42
+ end
43
+
44
+ def shape_for(signature)
45
+ return nil if signature.forward_parameter
46
+
47
+ min = signature.positional_parameters.size + signature.post_parameters.size
48
+
49
+ [min, maximum_positional(signature, min), keyword_parameters?(signature)]
50
+ end
51
+
52
+ def maximum_positional(signature, min)
53
+ return nil if signature.rest_positional_parameter
54
+
55
+ min + signature.optional_positional_parameters.size
56
+ end
57
+
58
+ def keyword_parameters?(signature)
59
+ !signature.keyword_parameters.empty? ||
60
+ !signature.optional_keyword_parameters.empty? ||
61
+ !signature.rest_keyword_parameter.nil?
62
+ end
63
+
64
+ # The number of positional arguments the call passes, or nil when it
65
+ # cannot be determined statically (argument forwarding).
66
+ def positional_argument_count(node, callee_has_keywords)
67
+ arguments = node.arguments
68
+ return nil if forwards_arguments?(arguments)
69
+
70
+ arguments = arguments[0...-1] if arguments.last&.block_pass_type?
71
+ return arguments.size unless (keyword_hash = keyword_hash(arguments.last))
72
+ return nil if double_splat?(keyword_hash)
73
+
74
+ # A keyword-style hash passed to a method with no keyword parameters is
75
+ # received as a single positional hash argument.
76
+ callee_has_keywords ? arguments.size - 1 : arguments.size
77
+ end
78
+
79
+ def forwards_arguments?(arguments)
80
+ arguments.any? do |argument|
81
+ argument.type?(:splat, :forwarded_args, :forwarded_restarg, :forwarded_kwrestarg)
82
+ end
83
+ end
84
+
85
+ def keyword_hash(node)
86
+ node if node&.hash_type? && !node.braces?
87
+ end
88
+
89
+ def double_splat?(hash_node)
90
+ hash_node.each_child_node.any?(&:kwsplat_type?)
91
+ end
92
+ end
93
+ end
94
+ end
@@ -128,7 +128,13 @@ module RuboCop
128
128
  # Additionally, the RFC2396_PARSER alias is only available on 3.4 for now.
129
129
  # Extra info at https://github.com/ruby/uri/issues/118
130
130
  parser = defined?(URI::RFC2396_PARSER) ? URI::RFC2396_PARSER : URI::DEFAULT_PARSER
131
- parser.make_regexp(config.for_cop('Layout/LineLength')['URISchemes'])
131
+ schemes = config.for_cop('Layout/LineLength')['URISchemes']
132
+ regexp = parser.make_regexp(schemes)
133
+
134
+ # `make_regexp` in uri 1.1.0+ matches schemes case-insensitively, which makes
135
+ # constant paths like `Http::UploadedFile` look like URIs. Require the exact case
136
+ # given in `URISchemes`.
137
+ schemes ? /(?=#{Regexp.union(schemes)}:)#{regexp}/ : regexp
132
138
  end
133
139
  end
134
140
 
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module Cop
5
5
  # Common functionality for checking whether an AST node/token is aligned
6
6
  # with something on a preceding or following line
7
- # rubocop:disable Metrics/ModuleLength
7
+ # rubocop:disable-next Metrics/ModuleLength
8
8
  module PrecedingFollowingAlignment
9
9
  # Tokens that end with an `=`, as well as `<<`, that can be aligned together:
10
10
  # `=`, `==`, `===`, `!=`, `<=`, `>=`, `<<` and operator assignment (`+=`, etc).
@@ -69,7 +69,15 @@ module RuboCop
69
69
  line = processed_source.lines[lineno]
70
70
  index = line =~ /\S/
71
71
  next unless index
72
- next if indent && indent != index
72
+
73
+ if indent
74
+ # When searching for the nearest line with the same indentation,
75
+ # more deeply indented lines are nested content of the current group
76
+ # and are skipped, but a less deeply indented line ends the enclosing block:
77
+ # an alignment anchor beyond it would be coincidental.
78
+ break if index < indent
79
+ next if index > indent
80
+ end
73
81
 
74
82
  return yield(range, line, lineno + 1)
75
83
  end
@@ -174,20 +182,69 @@ module RuboCop
174
182
  # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
175
183
  # rubocop:disable Metrics/PerceivedComplexity, Metrics/MethodLength
176
184
  def relevant_assignment_lines(line_range)
185
+ relevant_lines(line_range, interrupting_operator_lines) do |line_number|
186
+ assignment_lines.include?(line_number)
187
+ end
188
+ end
189
+
190
+ def interrupting_operator_lines
191
+ @interrupting_operator_lines ||=
192
+ processed_source.tokens.each_with_object(Set.new) do |token, lines|
193
+ next unless ASSIGNMENT_OR_COMPARISON_TOKENS.include?(token.type)
194
+
195
+ lines << token.line unless assignment_lines.include?(token.line)
196
+ end
197
+ end
198
+
199
+ def alignment_lines(line_number)
200
+ @alignment_lines_by_line ||= {}
201
+ return @alignment_lines_by_line[line_number] if @alignment_lines_by_line.key?(line_number)
202
+
203
+ lines = alignment_line_ranges(line_number).flatten.uniq.sort.freeze
204
+
205
+ lines.each { |line| @alignment_lines_by_line[line] = lines }
206
+ end
207
+
208
+ def alignment_line_ranges(line_number)
209
+ last_line = processed_source.lines.length
210
+
211
+ [
212
+ relevant_lines(line_number.downto(1), definition_boundary_lines) do |line|
213
+ !aligned_comment_lines.include?(line)
214
+ end,
215
+ relevant_lines(line_number.upto(last_line), definition_boundary_lines) do |line|
216
+ !aligned_comment_lines.include?(line)
217
+ end
218
+ ]
219
+ end
220
+
221
+ def definition_boundary_lines
222
+ @definition_boundary_lines ||= begin
223
+ nodes = processed_source.ast&.each_node(:any_def) || []
224
+
225
+ nodes.each_with_object(Set.new) do |node, lines|
226
+ lines << node.first_line << node.last_line
227
+ end
228
+ end
229
+ end
230
+
231
+ def relevant_lines(line_range, boundary_lines = [])
177
232
  result = []
178
- original_line_indent = processed_source.line_indentation(line_range.first)
233
+ original_line = line_range.first
234
+ original_line_indent = processed_source.line_indentation(original_line)
179
235
  relevant_line_indent_at_level = true
180
236
 
181
237
  line_range.each do |line_number|
182
238
  current_line_indent = processed_source.line_indentation(line_number)
183
239
  blank_line = processed_source.lines[line_number - 1].blank?
184
240
 
185
- if (current_line_indent < original_line_indent && !blank_line) ||
241
+ if (line_number != original_line && boundary_lines.include?(line_number)) ||
242
+ (current_line_indent < original_line_indent && !blank_line) ||
186
243
  (relevant_line_indent_at_level && blank_line)
187
244
  break
188
245
  end
189
246
 
190
- result << line_number if assignment_lines.include?(line_number) &&
247
+ result << line_number if yield(line_number) &&
191
248
  current_line_indent == original_line_indent
192
249
 
193
250
  unless blank_line
@@ -214,6 +271,5 @@ module RuboCop
214
271
  asgn_tokens.reject { |t| eqls_to_ignore.include?(t.begin_pos) }
215
272
  end
216
273
  end
217
- # rubocop:enable Metrics/ModuleLength
218
274
  end
219
275
  end
@@ -116,14 +116,13 @@ module RuboCop
116
116
  end
117
117
  end
118
118
 
119
- # rubocop:disable Metrics/ParameterLists
119
+ # rubocop:disable-next Metrics/ParameterLists
120
120
  def final_pos(src, pos, increment, continuations, newlines, whitespace)
121
121
  pos = move_pos(src, pos, increment, true, /[ \t]/)
122
122
  pos = move_pos_str(src, pos, increment, continuations, "\\\n")
123
123
  pos = move_pos(src, pos, increment, newlines, /\n/)
124
124
  move_pos(src, pos, increment, whitespace, /\s/)
125
125
  end
126
- # rubocop:enable Metrics/ParameterLists
127
126
 
128
127
  def move_pos(src, pos, step, condition, regexp)
129
128
  offset = step == -1 ? -1 : 0
@@ -35,8 +35,14 @@ module RuboCop
35
35
  condition.each_node.any?(&:lvasgn_type?)
36
36
  end
37
37
 
38
+ # The rendered modifier form is compared against the bare maximum, not
39
+ # `acceptable_line_length?`: `Layout/LineLength`'s exemptions describe
40
+ # long lines the user tolerates, not permission to manufacture new ones,
41
+ # so collapsing to modifier form must never push a line past the maximum.
38
42
  def modifier_fits_on_single_line?(node)
39
- acceptable_line_length?(line_in_modifier_form(node), node.first_line)
43
+ return true unless max_line_length
44
+
45
+ line_length(line_in_modifier_form(node)) <= max_line_length
40
46
  end
41
47
 
42
48
  def line_in_modifier_form(node)
@@ -46,12 +52,12 @@ module RuboCop
46
52
  "#{code_before}#{to_modifier_form(node)}#{code_after(node)}"
47
53
  end
48
54
 
49
- # Rather than comparing the rendered modifier form against the bare
50
- # maximum, ask the question `Layout/LineLength` would: a line the user's
51
- # configuration exempts (`Layout/LineLength` disabled at that line, an
52
- # allowed pattern, an allowed cop directive, an allowed URI) fits by
53
- # definition. This keeps every modifier cop consistent with
54
- # `Layout/LineLength` instead of each reimplementing part of its policy.
55
+ # Whether an existing line is acceptable to `Layout/LineLength`,
56
+ # exemptions (the cop disabled at that line, an allowed pattern, an
57
+ # allowed cop directive, an allowed URI) included. Only for judging
58
+ # lines already in the source as too long - see
59
+ # `modifier_fits_on_single_line?` for why the exemptions must not apply
60
+ # when deciding whether a modifier line may be created.
55
61
  def acceptable_line_length?(line, line_number)
56
62
  return true unless max_line_length
57
63
  return true if line_length(line) <= max_line_length
@@ -4,7 +4,7 @@ module RuboCop
4
4
  module Cop
5
5
  # Common methods shared by Style/TrailingCommaInArguments,
6
6
  # Style/TrailingCommaInArrayLiteral and Style/TrailingCommaInHashLiteral
7
- # rubocop:disable Metrics/ModuleLength
7
+ # rubocop:disable-next Metrics/ModuleLength
8
8
  module TrailingComma
9
9
  include ConfigurableEnforcedStyle
10
10
  include RangeHelp
@@ -95,7 +95,7 @@ module RuboCop
95
95
  node.multiline? && !allowed_multiline_argument?(node)
96
96
  end
97
97
 
98
- # rubocop:disable Metrics/AbcSize
98
+ # rubocop:disable-next Metrics/AbcSize
99
99
  def method_name_and_arguments_on_same_line?(node)
100
100
  return false if !node.call_type? || node.last_line != node.last_argument.last_line
101
101
  return true if node.last_argument.hash_type? && node.last_argument.braces?
@@ -104,7 +104,6 @@ module RuboCop
104
104
 
105
105
  line == node.last_argument.last_line
106
106
  end
107
- # rubocop:enable Metrics/AbcSize
108
107
 
109
108
  # A single argument with the closing bracket on the same line as the end
110
109
  # of the argument is not considered multiline, even if the argument
@@ -223,6 +222,5 @@ module RuboCop
223
222
  false
224
223
  end
225
224
  end
226
- # rubocop:enable Metrics/ModuleLength
227
225
  end
228
226
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RuboCop
4
- module Cop # rubocop:disable Style/Documentation
4
+ module Cop # rubocop:disable Style/Documentation -- a namespace that only autoloads the mixins below
5
5
  # Autoloads mixin modules included by cops. Mixins are autoloaded to reduce the number of
6
6
  # requires because they're used only when the relevant cop class is loaded.
7
7
 
@@ -14,7 +14,7 @@ module RuboCop
14
14
  autoload :AllowedReceivers, "#{__dir__}/mixin/allowed_receivers"
15
15
  autoload :ForbiddenIdentifiers, "#{__dir__}/mixin/forbidden_identifiers"
16
16
  autoload :ForbiddenPattern, "#{__dir__}/mixin/forbidden_pattern"
17
- autoload :AutoCorrector, "#{__dir__}/mixin/auto_corrector" # rubocop:todo Naming/InclusiveLanguage
17
+ autoload :AutoCorrector, "#{__dir__}/mixin/auto_corrector" # rubocop:todo Naming/InclusiveLanguage -- the file is named `auto_corrector.rb`
18
18
  autoload :CheckAssignment, "#{__dir__}/mixin/check_assignment"
19
19
  autoload :CheckLineBreakable, "#{__dir__}/mixin/check_line_breakable"
20
20
  autoload :CheckSingleLineSuitability, "#{__dir__}/mixin/check_single_line_suitability"
@@ -41,6 +41,10 @@ module RuboCop
41
41
  autoload :HashAlignmentStyles, "#{__dir__}/mixin/hash_alignment_styles"
42
42
  autoload :HashSubset, "#{__dir__}/mixin/hash_subset"
43
43
  autoload :HashTransformMethod, "#{__dir__}/mixin/hash_transform_method"
44
+ # Deprecated aliases of `AllowedMethods` and `AllowedPattern`, defined in those files.
45
+ autoload :IgnoredMethods, "#{__dir__}/mixin/allowed_methods"
46
+ autoload :IgnoredPattern, "#{__dir__}/mixin/allowed_pattern"
47
+ autoload :IndexedMethodArity, "#{__dir__}/mixin/indexed_method_arity"
44
48
  autoload :IntegerNode, "#{__dir__}/mixin/integer_node"
45
49
  autoload :Interpolation, "#{__dir__}/mixin/interpolation"
46
50
  autoload :LineLengthHelp, "#{__dir__}/mixin/line_length_help"
@@ -33,6 +33,7 @@ module RuboCop
33
33
  node.each_descendant(:lvar, :lvasgn) do |lvar|
34
34
  lvar_location = lvar.loc.name
35
35
  next unless lvar_location.source == arg.source
36
+ next if shadowed?(lvar, arg.source, node)
36
37
 
37
38
  corrector.replace(lvar_location, 'other')
38
39
  end
@@ -47,6 +48,21 @@ module RuboCop
47
48
 
48
49
  !/\A[[:word:]]/.match?(name) || OP_LIKE_METHODS.include?(name)
49
50
  end
51
+
52
+ # A reference is shadowed when an enclosing block within the method redeclares the
53
+ # parameter name (as a block parameter or block-local). Such a reference points to
54
+ # the block's variable, not the operator's parameter, so it must not be renamed.
55
+ def shadowed?(node, name, def_node)
56
+ node.each_ancestor(:block).any? do |block|
57
+ def_node.source_range.contains?(block.source_range) && redeclares?(block, name)
58
+ end
59
+ end
60
+
61
+ def redeclares?(block, name)
62
+ block.arguments.any? do |argument|
63
+ argument.respond_to?(:name) && argument.name.to_s == name
64
+ end
65
+ end
50
66
  end
51
67
  end
52
68
  end
@@ -62,7 +62,10 @@ module RuboCop
62
62
  MSG = 'Use %<style>s block forwarding.'
63
63
 
64
64
  def self.autocorrect_incompatible_with
65
- [Lint::AmbiguousOperator, Style::ArgumentsForwarding, Style::ExplicitBlockArgument]
65
+ [
66
+ Lint::AmbiguousOperator, Style::ArgumentsForwarding,
67
+ Style::ExplicitBlockArgument, Style::MethodDefParentheses
68
+ ]
66
69
  end
67
70
 
68
71
  def on_def(node)
@@ -38,7 +38,7 @@ module RuboCop
38
38
  class BlockParameterName < Base
39
39
  include UncommunicativeName
40
40
 
41
- def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler, InternalAffairs/ItblockHandler
41
+ def on_block(node) # rubocop:disable InternalAffairs/NumblockHandler, InternalAffairs/ItblockHandler -- there are no parameter names to check
42
42
  return unless node.arguments?
43
43
 
44
44
  check(node, node.arguments)
@@ -167,7 +167,7 @@ module RuboCop
167
167
  PATTERN
168
168
 
169
169
  # rubocop:disable Metrics/AbcSize
170
- # rubocop:disable Metrics/MethodLength
170
+ # rubocop:disable-next Metrics/MethodLength
171
171
  def on_or_asgn(node)
172
172
  lhs = node.lhs
173
173
  return unless lhs.ivasgn_type?
@@ -192,7 +192,6 @@ module RuboCop
192
192
  corrector.replace(lhs.loc.name, "@#{suggested_var}")
193
193
  end
194
194
  end
195
- # rubocop:enable Metrics/MethodLength
196
195
  # rubocop:enable Metrics/AbcSize
197
196
 
198
197
  # @!method defined_memoized?(node, ivar)
@@ -203,7 +202,7 @@ module RuboCop
203
202
  $(ivasgn %1 _))
204
203
  PATTERN
205
204
 
206
- # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
205
+ # rubocop:disable-next Metrics/AbcSize, Metrics/MethodLength
207
206
  def on_defined?(node)
208
207
  arg = node.first_argument
209
208
  return false unless arg.ivar_type?
@@ -233,7 +232,6 @@ module RuboCop
233
232
  end
234
233
  end
235
234
  end
236
- # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
237
235
 
238
236
  private
239
237
 
@@ -105,6 +105,10 @@ module RuboCop
105
105
 
106
106
  MSG = 'Use %<style>s for method names.'
107
107
  MSG_FORBIDDEN = '`%<identifier>s` is forbidden, use another method name instead.'
108
+ RESTRICT_ON_SEND = %i[
109
+ define_method define_singleton_method new define alias_method
110
+ attr attr_reader attr_writer attr_accessor
111
+ ].freeze
108
112
 
109
113
  OPERATOR_METHODS = %i[| ^ & <=> == === =~ > >= < <= << >> + - * /
110
114
  % ** ~ +@ -@ !@ ~@ [] []= ! != !~ `].to_set.freeze
@@ -209,7 +213,7 @@ module RuboCop
209
213
  forbidden_identifier?(name) || forbidden_pattern?(name)
210
214
  end
211
215
 
212
- # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
216
+ # rubocop:disable-next Metrics/MethodLength, Metrics/AbcSize
213
217
  def register_forbidden_name(node)
214
218
  if node.any_def_type?
215
219
  name_node = node.loc.name
@@ -227,7 +231,6 @@ module RuboCop
227
231
  message = format(MSG_FORBIDDEN, identifier: method_name)
228
232
  add_offense(name_node, message: message)
229
233
  end
230
- # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
231
234
 
232
235
  def attr_name(name_item)
233
236
  sym_name(name_item) || str_name(name_item)
@@ -118,7 +118,7 @@ module RuboCop
118
118
 
119
119
  # Returns the reassignment node once the exception variable is reassigned (a truthy
120
120
  # signal to stop correcting later references), or `nil` when no reassignment is found.
121
- # rubocop:disable Metrics/MethodLength
121
+ # rubocop:disable-next Metrics/MethodLength
122
122
  def correct_node(corrector, node, offending_name, preferred_name)
123
123
  return unless node
124
124
 
@@ -141,7 +141,6 @@ module RuboCop
141
141
  end
142
142
  nil
143
143
  end
144
- # rubocop:enable Metrics/MethodLength
145
144
 
146
145
  # If the exception variable is reassigned, that assignment needs to be corrected.
147
146
  # Further `lvar` nodes will not be corrected though since they now refer to a
@@ -86,9 +86,19 @@ module RuboCop
86
86
 
87
87
  NO_LOCATION = PseudoSourceRange.new(1, 0, '', 0, 0).freeze
88
88
 
89
+ # @api public
90
+ #
91
+ # @!attribute [r] justification
92
+ #
93
+ # @return [String, nil]
94
+ # the reason given on the directive that suppressed this offense
95
+ # (the text after `--`), or `nil` when the offense is not suppressed
96
+ # or the directive carries no reason
97
+ attr_reader :justification
98
+
89
99
  # @api private
90
100
  def initialize(severity, location, message, cop_name, # rubocop:disable Metrics/ParameterLists
91
- status = :uncorrected, corrector = nil)
101
+ status = :uncorrected, corrector = nil, justification: nil)
92
102
  @severity = RuboCop::Cop::Severity.new(severity)
93
103
  @location = location
94
104
 
@@ -101,15 +111,16 @@ module RuboCop
101
111
  @cop_name = cop_name.freeze
102
112
  @status = status
103
113
  @corrector = corrector
114
+ @justification = justification.freeze
104
115
  freeze
105
116
  end
106
117
 
107
118
  def marshal_dump
108
- [@severity, @location, @message, @cop_name, @status]
119
+ [@severity, @location, @message, @cop_name, @status, @justification]
109
120
  end
110
121
 
111
122
  def marshal_load(array)
112
- @severity, @location, @message, @cop_name, @status = array
123
+ @severity, @location, @message, @cop_name, @status, @justification = array
113
124
  @line = @location.line
114
125
  @column = @location.column
115
126
  end
@@ -121,8 +132,10 @@ module RuboCop
121
132
  # @return [Boolean]
122
133
  # whether this offense can be automatically corrected via autocorrect.
123
134
  # This includes todo comments, for example when requested with `--disable-uncorrectable`.
135
+ # An offense suppressed by a directive comment is not correctable -
136
+ # autocorrect will not touch it.
124
137
  def correctable?
125
- @status != :unsupported
138
+ @status != :unsupported && @status != :disabled
126
139
  end
127
140
 
128
141
  # @api public
@@ -223,6 +236,16 @@ module RuboCop
223
236
  column + 1
224
237
  end
225
238
 
239
+ # @api private
240
+ #
241
+ # The minimum value of `real_column` is 1, so the minimum value of
242
+ # `real_last_column` is also 1. A non-zero `last_column` is used as is,
243
+ # because the 0-based end-exclusive column is the same as the 1-based
244
+ # column of the last character.
245
+ def real_last_column
246
+ last_column.zero? ? 1 : last_column
247
+ end
248
+
226
249
  # @api public
227
250
  #
228
251
  # @return [Boolean]
@@ -23,8 +23,8 @@ module RuboCop
23
23
  global.without_department(:Test).cops
24
24
  end
25
25
 
26
- def self.qualified_cop_name(name, origin, warn: true)
27
- global.qualified_cop_name(name, origin, warn: warn)
26
+ def self.qualified_cop_name(name, origin, warn: true, correct_namespace: true)
27
+ global.qualified_cop_name(name, origin, warn: warn, correct_namespace: correct_namespace)
28
28
  end
29
29
 
30
30
  # Changes momentarily the global registry
@@ -171,11 +171,19 @@ module RuboCop
171
171
  # @note Emits a warning if the provided name has an incorrect namespace
172
172
  #
173
173
  # @return [String] Qualified cop name
174
- def qualified_cop_name(name, path, warn: true)
174
+ def qualified_cop_name(name, path, warn: true, correct_namespace: true)
175
175
  badge = Badge.parse(name)
176
176
  print_department_missing_warning(name, path) if warn && department_missing?(badge, name)
177
177
  return name if registered?(badge)
178
+ # A name qualified with the wrong department is returned as is when
179
+ # namespace correction is not wanted, so the caller can surface the
180
+ # mistake instead of silently acting on the corrected name.
181
+ return name if badge.qualified? && !correct_namespace
178
182
 
183
+ resolve_cop_name(badge, name, path, warn)
184
+ end
185
+
186
+ def resolve_cop_name(badge, name, path, warn)
179
187
  potential_badges = qualify_badge(badge)
180
188
 
181
189
  case potential_badges.size
@@ -272,6 +280,12 @@ module RuboCop
272
280
  config.enabled_new_cop?(cop_name)
273
281
  end
274
282
 
283
+ # Preview cops are opt-in and stay silent otherwise, so unlike pending cops
284
+ # they are never reported as needing a decision.
285
+ def enabled_preview_cop?(cop_cfg, config)
286
+ cop_cfg.fetch('Enabled') == 'preview' && config.preview?(@options)
287
+ end
288
+
275
289
  def names
276
290
  clear_enrollment_queue
277
291
  @cops_by_badge.keys.map(&:to_s)
@@ -325,10 +339,33 @@ module RuboCop
325
339
  cop ? [cop] : cops_for_department(directive)
326
340
  end
327
341
 
342
+ # Loads all cops that are registered for lazy loading. Useful when lazily registered cops
343
+ # must not outlive the current global registry, e.g. before a temporary global registry is
344
+ # discarded in tests.
345
+ #
346
+ # @api private
347
+ def load_all_lazy_cops
348
+ # Take a snapshot because loading a cop can load (and thereby register)
349
+ # another lazy-loaded cop, e.g. its superclass.
350
+ badges = @cops_by_badge.keys
351
+
352
+ badges.each do |badge|
353
+ load_lazy_cop(badge) if @cops_by_badge[badge].is_a?(String)
354
+ end
355
+ end
356
+
328
357
  def freeze
329
358
  clear_enrollment_queue
330
359
  load_all_lazy_cops
331
360
  unqualified_cop_names # build cache
361
+
362
+ # Freeze the structural collections as well, so that a cop class defined after
363
+ # the freeze fails fast at its `enlist`/`lazy_load` call site instead of corrupting
364
+ # the registry and failing much later.
365
+ @cops_by_badge.freeze
366
+ @departments.freeze
367
+ @enrollment_queue.freeze
368
+
332
369
  super
333
370
  end
334
371
 
@@ -389,7 +426,9 @@ module RuboCop
389
426
  # caching which expects cop names or cop classes as keys.
390
427
  cfg = config.for_cop(cop_name)
391
428
 
392
- cop_enabled = cfg.fetch('Enabled') == true || enabled_pending_cop?(cfg, config, cop_name)
429
+ cop_enabled = cfg.fetch('Enabled') == true ||
430
+ enabled_pending_cop?(cfg, config, cop_name) ||
431
+ enabled_preview_cop?(cfg, config)
393
432
 
394
433
  if options.fetch(:safe, false)
395
434
  cop_enabled && cfg.fetch('Safe', true)
@@ -398,13 +437,6 @@ module RuboCop
398
437
  end
399
438
  end
400
439
 
401
- def load_all_lazy_cops
402
- # Take a snapshot because loading a cop can load (and thereby register)
403
- # another lazy-loaded cop, e.g. its superclass.
404
- badges = @cops_by_badge.keys
405
- badges.each { |badge| load_lazy_cop(badge) if @cops_by_badge[badge].is_a?(String) }
406
- end
407
-
408
440
  # @return [Class, nil] the loaded cop class, or nil if the cop excluded
409
441
  # itself from the registry while being loaded
410
442
  def load_lazy_cop(badge)
@@ -21,6 +21,18 @@ module RuboCop
21
21
  # any of `:info`, `:refactor`, `:convention`, `:warning`, `:error` or `:fatal`.
22
22
  attr_reader :name
23
23
 
24
+ # The lowest severity that makes a run fail: `--fail-level` when given,
25
+ # otherwise `AllCops: FailLevel`. `autocorrect` is a pseudo level on the
26
+ # command line that gates on corrections instead, so it leaves the
27
+ # threshold at the configured one.
28
+ def self.minimum_to_fail(options, config)
29
+ name = options[:fail_level]
30
+ if name.nil? || name == :autocorrect
31
+ name = (config&.for_all_cops&.[]('FailLevel') || :refactor).to_sym
32
+ end
33
+ new(name)
34
+ end
35
+
24
36
  def self.name_from_code(code)
25
37
  name = code.to_sym
26
38
  CODE_TABLE[name] || name