rubocop 1.88.2 → 1.90.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 (227) hide show
  1. checksums.yaml +4 -4
  2. data/config/default.yml +139 -16
  3. data/exe/rubocop +1 -1
  4. data/lib/rubocop/cached_data.rb +7 -2
  5. data/lib/rubocop/cli/command/execute_runner.rb +31 -0
  6. data/lib/rubocop/cli.rb +2 -4
  7. data/lib/rubocop/comment_config/directive_range.rb +32 -0
  8. data/lib/rubocop/comment_config/disable_next.rb +97 -0
  9. data/lib/rubocop/comment_config.rb +81 -49
  10. data/lib/rubocop/config.rb +76 -5
  11. data/lib/rubocop/config_loader.rb +1 -2
  12. data/lib/rubocop/config_loader_resolver.rb +1 -2
  13. data/lib/rubocop/config_validator.rb +39 -3
  14. data/lib/rubocop/cop/autocorrect_logic.rb +8 -0
  15. data/lib/rubocop/cop/badge.rb +8 -0
  16. data/lib/rubocop/cop/base.rb +40 -6
  17. data/lib/rubocop/cop/bundler.rb +19 -0
  18. data/lib/rubocop/cop/corrector.rb +4 -4
  19. data/lib/rubocop/cop/correctors/alignment_corrector.rb +55 -5
  20. data/lib/rubocop/cop/gemspec.rb +22 -0
  21. data/lib/rubocop/cop/generator/registration_injector.rb +188 -0
  22. data/lib/rubocop/cop/generator.rb +4 -0
  23. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -2
  24. data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_walker.rb +1 -2
  25. data/lib/rubocop/cop/layout/block_alignment.rb +1 -2
  26. data/lib/rubocop/cop/layout/class_structure.rb +108 -26
  27. data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -2
  28. data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +63 -5
  29. data/lib/rubocop/cop/layout/end_alignment.rb +1 -2
  30. data/lib/rubocop/cop/layout/extra_spacing.rb +105 -3
  31. data/lib/rubocop/cop/layout/first_argument_indentation.rb +21 -1
  32. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +1 -1
  33. data/lib/rubocop/cop/layout/indentation_width.rb +3 -1
  34. data/lib/rubocop/cop/layout/leading_comment_space.rb +27 -0
  35. data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -2
  36. data/lib/rubocop/cop/layout/line_length.rb +84 -12
  37. data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -2
  38. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +12 -2
  39. data/lib/rubocop/cop/layout/redundant_line_break.rb +77 -0
  40. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +1 -2
  41. data/lib/rubocop/cop/layout/space_around_operators.rb +7 -0
  42. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +31 -34
  43. data/lib/rubocop/cop/layout.rb +114 -0
  44. data/lib/rubocop/cop/lazy_loader.rb +41 -0
  45. data/lib/rubocop/cop/lint/ambiguous_assignment.rb +9 -7
  46. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +71 -0
  47. data/lib/rubocop/cop/lint/ambiguous_range.rb +1 -2
  48. data/lib/rubocop/cop/lint/argument_mismatch.rb +89 -0
  49. data/lib/rubocop/cop/lint/constant_reassignment.rb +18 -21
  50. data/lib/rubocop/cop/lint/constant_resolution.rb +25 -0
  51. data/lib/rubocop/cop/lint/cop_directive_syntax.rb +84 -8
  52. data/lib/rubocop/cop/lint/deprecated_reference.rb +194 -0
  53. data/lib/rubocop/cop/lint/duplicate_methods.rb +300 -22
  54. data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -2
  55. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -2
  56. data/lib/rubocop/cop/lint/inherit_exception.rb +53 -7
  57. data/lib/rubocop/cop/lint/interpolation_check.rb +1 -2
  58. data/lib/rubocop/cop/lint/literal_as_condition.rb +8 -6
  59. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +4 -7
  60. data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +25 -12
  61. data/lib/rubocop/cop/lint/missing_super.rb +31 -1
  62. data/lib/rubocop/cop/lint/name_typo.rb +270 -0
  63. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +15 -4
  64. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +98 -19
  65. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +47 -7
  66. data/lib/rubocop/cop/lint/redundant_require_statement.rb +1 -2
  67. data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +1 -2
  68. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +1 -2
  69. data/lib/rubocop/cop/lint/redundant_type_conversion.rb +1 -2
  70. data/lib/rubocop/cop/lint/redundant_with_index.rb +1 -2
  71. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +8 -2
  72. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +2 -4
  73. data/lib/rubocop/cop/lint/super_argument_mismatch.rb +179 -0
  74. data/lib/rubocop/cop/lint/suppressed_exception_in_number_conversion.rb +1 -2
  75. data/lib/rubocop/cop/lint/to_enum_arguments.rb +38 -3
  76. data/lib/rubocop/cop/lint/unreachable_code.rb +1 -2
  77. data/lib/rubocop/cop/lint/unused_private_method.rb +234 -0
  78. data/lib/rubocop/cop/lint/useless_access_modifier.rb +1 -2
  79. data/lib/rubocop/cop/lint/useless_assignment.rb +1 -2
  80. data/lib/rubocop/cop/lint/useless_constant_scoping.rb +36 -0
  81. data/lib/rubocop/cop/lint/useless_method_definition.rb +1 -1
  82. data/lib/rubocop/cop/lint/useless_rescue.rb +1 -2
  83. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +2 -0
  84. data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +61 -7
  85. data/lib/rubocop/cop/lint/void.rb +18 -8
  86. data/lib/rubocop/cop/lint.rb +178 -0
  87. data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -2
  88. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
  89. data/lib/rubocop/cop/metrics.rb +31 -0
  90. data/lib/rubocop/cop/migration/department_name.rb +1 -6
  91. data/lib/rubocop/cop/migration.rb +13 -0
  92. data/lib/rubocop/cop/mixin/check_line_breakable.rb +23 -5
  93. data/lib/rubocop/cop/mixin/comments_help.rb +1 -2
  94. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +1 -2
  95. data/lib/rubocop/cop/mixin/endless_method_rewriter.rb +13 -5
  96. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +23 -6
  97. data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +1 -2
  98. data/lib/rubocop/cop/mixin/hash_subset.rb +1 -2
  99. data/lib/rubocop/cop/mixin/indexed_method_arity.rb +94 -0
  100. data/lib/rubocop/cop/mixin/line_length_help.rb +7 -1
  101. data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +51 -6
  102. data/lib/rubocop/cop/mixin/project_index_help.rb +140 -0
  103. data/lib/rubocop/cop/mixin/range_help.rb +1 -2
  104. data/lib/rubocop/cop/mixin/reparsed_equivalence.rb +171 -0
  105. data/lib/rubocop/cop/mixin/statement_modifier.rb +46 -4
  106. data/lib/rubocop/cop/mixin/trailing_comma.rb +2 -4
  107. data/lib/rubocop/cop/mixin.rb +82 -77
  108. data/lib/rubocop/cop/naming/accessor_method_name.rb +24 -0
  109. data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +16 -0
  110. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +2 -4
  111. data/lib/rubocop/cop/naming/method_name.rb +5 -2
  112. data/lib/rubocop/cop/naming/predicate_prefix.rb +33 -5
  113. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +1 -2
  114. data/lib/rubocop/cop/naming/variable_number.rb +3 -1
  115. data/lib/rubocop/cop/naming.rb +31 -0
  116. data/lib/rubocop/cop/offense.rb +37 -10
  117. data/lib/rubocop/cop/registry.rb +180 -46
  118. data/lib/rubocop/cop/security.rb +19 -0
  119. data/lib/rubocop/cop/style/accessor_grouping.rb +1 -2
  120. data/lib/rubocop/cop/style/arguments_forwarding.rb +3 -6
  121. data/lib/rubocop/cop/style/array_first_last.rb +1 -2
  122. data/lib/rubocop/cop/style/array_intersect.rb +24 -5
  123. data/lib/rubocop/cop/style/bitwise_predicate.rb +1 -2
  124. data/lib/rubocop/cop/style/block_delimiters.rb +3 -6
  125. data/lib/rubocop/cop/style/case_like_if.rb +2 -4
  126. data/lib/rubocop/cop/style/class_and_module_children.rb +79 -20
  127. data/lib/rubocop/cop/style/combinable_loops.rb +1 -2
  128. data/lib/rubocop/cop/style/concat_array_literals.rb +1 -2
  129. data/lib/rubocop/cop/style/conditional_assignment.rb +23 -2
  130. data/lib/rubocop/cop/style/constant_visibility.rb +1 -2
  131. data/lib/rubocop/cop/style/copyright.rb +5 -1
  132. data/lib/rubocop/cop/style/directive_scope.rb +171 -0
  133. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +76 -12
  134. data/lib/rubocop/cop/style/documentation.rb +47 -0
  135. data/lib/rubocop/cop/style/empty_case_condition.rb +1 -2
  136. data/lib/rubocop/cop/style/endless_method.rb +0 -10
  137. data/lib/rubocop/cop/style/format_string_token.rb +1 -2
  138. data/lib/rubocop/cop/style/guard_clause.rb +1 -2
  139. data/lib/rubocop/cop/style/hash_each_methods.rb +1 -2
  140. data/lib/rubocop/cop/style/hash_syntax.rb +1 -2
  141. data/lib/rubocop/cop/style/identical_conditional_branches.rb +2 -4
  142. data/lib/rubocop/cop/style/if_inside_else.rb +1 -2
  143. data/lib/rubocop/cop/style/if_unless_modifier.rb +8 -50
  144. data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +1 -2
  145. data/lib/rubocop/cop/style/lambda.rb +4 -0
  146. data/lib/rubocop/cop/style/map_to_hash.rb +1 -2
  147. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +22 -7
  148. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +1 -2
  149. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +30 -0
  150. data/lib/rubocop/cop/style/multiline_if_then.rb +7 -1
  151. data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -2
  152. data/lib/rubocop/cop/style/multiple_comparison.rb +33 -22
  153. data/lib/rubocop/cop/style/mutable_constant.rb +5 -0
  154. data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -2
  155. data/lib/rubocop/cop/style/negative_array_index.rb +3 -3
  156. data/lib/rubocop/cop/style/nil_comparison.rb +1 -2
  157. data/lib/rubocop/cop/style/operator_method_call.rb +1 -2
  158. data/lib/rubocop/cop/style/parallel_assignment.rb +1 -2
  159. data/lib/rubocop/cop/style/redundant_assignment.rb +12 -2
  160. data/lib/rubocop/cop/style/redundant_condition.rb +2 -4
  161. data/lib/rubocop/cop/style/redundant_constant_base.rb +37 -1
  162. data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +1 -2
  163. data/lib/rubocop/cop/style/redundant_each.rb +1 -2
  164. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +9 -0
  165. data/lib/rubocop/cop/style/redundant_format.rb +14 -7
  166. data/lib/rubocop/cop/style/redundant_line_continuation.rb +78 -135
  167. data/lib/rubocop/cop/style/redundant_parentheses.rb +65 -67
  168. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +1 -2
  169. data/lib/rubocop/cop/style/redundant_return.rb +1 -2
  170. data/lib/rubocop/cop/style/redundant_self_assignment.rb +1 -2
  171. data/lib/rubocop/cop/style/redundant_string_escape.rb +1 -2
  172. data/lib/rubocop/cop/style/rescue_modifier.rb +1 -2
  173. data/lib/rubocop/cop/style/safe_navigation.rb +11 -2
  174. data/lib/rubocop/cop/style/sample.rb +11 -6
  175. data/lib/rubocop/cop/style/select_by_regexp.rb +1 -2
  176. data/lib/rubocop/cop/style/semicolon.rb +2 -4
  177. data/lib/rubocop/cop/style/single_line_do_end_block.rb +1 -2
  178. data/lib/rubocop/cop/style/sole_nested_conditional.rb +21 -5
  179. data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +2 -0
  180. data/lib/rubocop/cop/style/static_class.rb +21 -0
  181. data/lib/rubocop/cop/style/string_concatenation.rb +18 -5
  182. data/lib/rubocop/cop/style/super_arguments.rb +1 -2
  183. data/lib/rubocop/cop/style/symbol_proc.rb +1 -2
  184. data/lib/rubocop/cop/style/time_now.rb +41 -0
  185. data/lib/rubocop/cop/style/yoda_condition.rb +1 -2
  186. data/lib/rubocop/cop/style.rb +312 -0
  187. data/lib/rubocop/cop/team.rb +59 -6
  188. data/lib/rubocop/cop/util.rb +2 -4
  189. data/lib/rubocop/cop/variable_force/variable.rb +19 -8
  190. data/lib/rubocop/cops_documentation_generator.rb +4 -7
  191. data/lib/rubocop/directive_comment.rb +39 -3
  192. data/lib/rubocop/feature_loader.rb +0 -6
  193. data/lib/rubocop/formatter/emacs_style_formatter.rb +3 -1
  194. data/lib/rubocop/formatter/html_formatter.rb +2 -4
  195. data/lib/rubocop/formatter/json_formatter.rb +11 -6
  196. data/lib/rubocop/formatter/junit_formatter.rb +26 -9
  197. data/lib/rubocop/formatter/offense_count_formatter.rb +1 -2
  198. data/lib/rubocop/formatter/simple_text_formatter.rb +4 -3
  199. data/lib/rubocop/formatter/tap_formatter.rb +3 -1
  200. data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -2
  201. data/lib/rubocop/lockfile.rb +18 -0
  202. data/lib/rubocop/lsp/diagnostic.rb +4 -8
  203. data/lib/rubocop/lsp/routes.rb +89 -22
  204. data/lib/rubocop/lsp/runtime.rb +4 -0
  205. data/lib/rubocop/lsp/server.rb +4 -0
  206. data/lib/rubocop/lsp/stdin_runner.rb +20 -0
  207. data/lib/rubocop/mcp/server.rb +1 -2
  208. data/lib/rubocop/options.rb +10 -6
  209. data/lib/rubocop/path_util.rb +1 -2
  210. data/lib/rubocop/pending_cops_reporter.rb +1 -6
  211. data/lib/rubocop/plugin/configuration_integrator.rb +6 -3
  212. data/lib/rubocop/project_index_loader.rb +16 -0
  213. data/lib/rubocop/rake_task.rb +1 -2
  214. data/lib/rubocop/result_cache.rb +6 -4
  215. data/lib/rubocop/rspec/expect_offense.rb +2 -4
  216. data/lib/rubocop/rspec/shared_contexts.rb +16 -2
  217. data/lib/rubocop/runner.rb +71 -43
  218. data/lib/rubocop/server/cache.rb +11 -7
  219. data/lib/rubocop/server/cli.rb +2 -4
  220. data/lib/rubocop/server.rb +14 -0
  221. data/lib/rubocop/target_finder.rb +4 -1
  222. data/lib/rubocop/target_ruby.rb +1 -1
  223. data/lib/rubocop/todo_audit.rb +111 -0
  224. data/lib/rubocop/version.rb +3 -5
  225. data/lib/rubocop.rb +20 -626
  226. data/lib/ruby_lsp/rubocop/addon.rb +1 -2
  227. metadata +28 -5
@@ -0,0 +1,178 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # Cops for the `Lint` department. The department's cops are registered for lazy loading
6
+ # and their files are loaded on demand.
7
+ module Lint
8
+ extend LazyLoader
9
+
10
+ register_cop :AmbiguousAssignment, "#{__dir__}/lint/ambiguous_assignment"
11
+ register_cop :AmbiguousBlockAssociation, "#{__dir__}/lint/ambiguous_block_association"
12
+ register_cop :AmbiguousOperator, "#{__dir__}/lint/ambiguous_operator"
13
+ register_cop :AmbiguousOperatorPrecedence, "#{__dir__}/lint/ambiguous_operator_precedence"
14
+ register_cop :AmbiguousRange, "#{__dir__}/lint/ambiguous_range"
15
+ register_cop :AmbiguousRegexpLiteral, "#{__dir__}/lint/ambiguous_regexp_literal"
16
+ register_cop :ArgumentMismatch, "#{__dir__}/lint/argument_mismatch"
17
+ register_cop :ArrayLiteralInRegexp, "#{__dir__}/lint/array_literal_in_regexp"
18
+ register_cop :AssignmentInCondition, "#{__dir__}/lint/assignment_in_condition"
19
+ register_cop :BigDecimalNew, "#{__dir__}/lint/big_decimal_new"
20
+ register_cop :BinaryOperatorWithIdenticalOperands, "#{__dir__}/lint/binary_operator_with_identical_operands"
21
+ register_cop :BooleanSymbol, "#{__dir__}/lint/boolean_symbol"
22
+ register_cop :CircularArgumentReference, "#{__dir__}/lint/circular_argument_reference"
23
+ register_cop :ConstantDefinitionInBlock, "#{__dir__}/lint/constant_definition_in_block"
24
+ register_cop :ConstantOverwrittenInRescue, "#{__dir__}/lint/constant_overwritten_in_rescue"
25
+ register_cop :ConstantReassignment, "#{__dir__}/lint/constant_reassignment"
26
+ register_cop :ConstantResolution, "#{__dir__}/lint/constant_resolution"
27
+ register_cop :CopDirectiveSyntax, "#{__dir__}/lint/cop_directive_syntax"
28
+ register_cop :DataDefineOverride, "#{__dir__}/lint/data_define_override"
29
+ register_cop :Debugger, "#{__dir__}/lint/debugger"
30
+ register_cop :DeprecatedClassMethods, "#{__dir__}/lint/deprecated_class_methods"
31
+ register_cop :DeprecatedConstants, "#{__dir__}/lint/deprecated_constants"
32
+ register_cop :DeprecatedOpenSSLConstant, "#{__dir__}/lint/deprecated_open_ssl_constant"
33
+ register_cop :DeprecatedReference, "#{__dir__}/lint/deprecated_reference"
34
+ register_cop :DisjunctiveAssignmentInConstructor, "#{__dir__}/lint/disjunctive_assignment_in_constructor"
35
+ register_cop :DuplicateBranch, "#{__dir__}/lint/duplicate_branch"
36
+ register_cop :DuplicateCaseCondition, "#{__dir__}/lint/duplicate_case_condition"
37
+ register_cop :DuplicateElsifCondition, "#{__dir__}/lint/duplicate_elsif_condition"
38
+ register_cop :DuplicateHashKey, "#{__dir__}/lint/duplicate_hash_key"
39
+ register_cop :DuplicateMagicComment, "#{__dir__}/lint/duplicate_magic_comment"
40
+ register_cop :DuplicateMatchPattern, "#{__dir__}/lint/duplicate_match_pattern"
41
+ register_cop :DuplicateMethods, "#{__dir__}/lint/duplicate_methods"
42
+ register_cop :DuplicateRegexpCharacterClassElement, "#{__dir__}/lint/duplicate_regexp_character_class_element"
43
+ register_cop :DuplicateRequire, "#{__dir__}/lint/duplicate_require"
44
+ register_cop :DuplicateRescueException, "#{__dir__}/lint/duplicate_rescue_exception"
45
+ register_cop :DuplicateSetElement, "#{__dir__}/lint/duplicate_set_element"
46
+ register_cop :EachWithObjectArgument, "#{__dir__}/lint/each_with_object_argument"
47
+ register_cop :ElseLayout, "#{__dir__}/lint/else_layout"
48
+ register_cop :EmptyBlock, "#{__dir__}/lint/empty_block"
49
+ register_cop :EmptyClass, "#{__dir__}/lint/empty_class"
50
+ register_cop :EmptyConditionalBody, "#{__dir__}/lint/empty_conditional_body"
51
+ register_cop :EmptyEnsure, "#{__dir__}/lint/empty_ensure"
52
+ register_cop :EmptyExpression, "#{__dir__}/lint/empty_expression"
53
+ register_cop :EmptyFile, "#{__dir__}/lint/empty_file"
54
+ register_cop :EmptyInPattern, "#{__dir__}/lint/empty_in_pattern"
55
+ register_cop :EmptyInterpolation, "#{__dir__}/lint/empty_interpolation"
56
+ register_cop :EmptyWhen, "#{__dir__}/lint/empty_when"
57
+ register_cop :EnsureReturn, "#{__dir__}/lint/ensure_return"
58
+ register_cop :SharedMutableDefault, "#{__dir__}/lint/shared_mutable_default"
59
+ register_cop :ErbNewArguments, "#{__dir__}/lint/erb_new_arguments"
60
+ register_cop :FlipFlop, "#{__dir__}/lint/flip_flop"
61
+ register_cop :FloatComparison, "#{__dir__}/lint/float_comparison"
62
+ register_cop :FloatOutOfRange, "#{__dir__}/lint/float_out_of_range"
63
+ register_cop :FormatParameterMismatch, "#{__dir__}/lint/format_parameter_mismatch"
64
+ register_cop :HashCompareByIdentity, "#{__dir__}/lint/hash_compare_by_identity"
65
+ register_cop :HashNewWithKeywordArgumentsAsDefault, "#{__dir__}/lint/hash_new_with_keyword_arguments_as_default"
66
+ register_cop :HeredocMethodCallPosition, "#{__dir__}/lint/heredoc_method_call_position"
67
+ register_cop :IdentityComparison, "#{__dir__}/lint/identity_comparison"
68
+ register_cop :ImplicitStringConcatenation, "#{__dir__}/lint/implicit_string_concatenation"
69
+ register_cop :IncompatibleIoSelectWithFiberScheduler, "#{__dir__}/lint/incompatible_io_select_with_fiber_scheduler"
70
+ register_cop :IneffectiveAccessModifier, "#{__dir__}/lint/ineffective_access_modifier"
71
+ register_cop :InheritException, "#{__dir__}/lint/inherit_exception"
72
+ register_cop :InterpolationCheck, "#{__dir__}/lint/interpolation_check"
73
+ register_cop :ItWithoutArgumentsInBlock, "#{__dir__}/lint/it_without_arguments_in_block"
74
+ register_cop :LambdaWithoutLiteralBlock, "#{__dir__}/lint/lambda_without_literal_block"
75
+ register_cop :LiteralAsCondition, "#{__dir__}/lint/literal_as_condition"
76
+ register_cop :LiteralAssignmentInCondition, "#{__dir__}/lint/literal_assignment_in_condition"
77
+ register_cop :LiteralInInterpolation, "#{__dir__}/lint/literal_in_interpolation"
78
+ register_cop :Loop, "#{__dir__}/lint/loop"
79
+ register_cop :MissingCopEnableDirective, "#{__dir__}/lint/missing_cop_enable_directive"
80
+ register_cop :MissingSuper, "#{__dir__}/lint/missing_super"
81
+ register_cop :MixedCaseRange, "#{__dir__}/lint/mixed_case_range"
82
+ register_cop :MixedRegexpCaptureTypes, "#{__dir__}/lint/mixed_regexp_capture_types"
83
+ register_cop :MultipleComparison, "#{__dir__}/lint/multiple_comparison"
84
+ register_cop :NameTypo, "#{__dir__}/lint/name_typo"
85
+ register_cop :NestedMethodDefinition, "#{__dir__}/lint/nested_method_definition"
86
+ register_cop :NestedPercentLiteral, "#{__dir__}/lint/nested_percent_literal"
87
+ register_cop :NextWithoutAccumulator, "#{__dir__}/lint/next_without_accumulator"
88
+ register_cop :NoReturnInBeginEndBlocks, "#{__dir__}/lint/no_return_in_begin_end_blocks"
89
+ register_cop :NonAtomicFileOperation, "#{__dir__}/lint/non_atomic_file_operation"
90
+ register_cop :NonDeterministicRequireOrder, "#{__dir__}/lint/non_deterministic_require_order"
91
+ register_cop :NonLocalExitFromIterator, "#{__dir__}/lint/non_local_exit_from_iterator"
92
+ register_cop :NumberConversion, "#{__dir__}/lint/number_conversion"
93
+ register_cop :NumberedParameterAssignment, "#{__dir__}/lint/numbered_parameter_assignment"
94
+ register_cop :NumericOperationWithConstantResult, "#{__dir__}/lint/numeric_operation_with_constant_result"
95
+ register_cop :OrAssignmentToConstant, "#{__dir__}/lint/or_assignment_to_constant"
96
+ register_cop :OrderedMagicComments, "#{__dir__}/lint/ordered_magic_comments"
97
+ register_cop :OutOfRangeRegexpRef, "#{__dir__}/lint/out_of_range_regexp_ref"
98
+ register_cop :ParenthesesAsGroupedExpression, "#{__dir__}/lint/parentheses_as_grouped_expression"
99
+ register_cop :PercentStringArray, "#{__dir__}/lint/percent_string_array"
100
+ register_cop :PercentSymbolArray, "#{__dir__}/lint/percent_symbol_array"
101
+ register_cop :RaiseException, "#{__dir__}/lint/raise_exception"
102
+ register_cop :RandOne, "#{__dir__}/lint/rand_one"
103
+ register_cop :RedundantCopDisableDirective, "#{__dir__}/lint/redundant_cop_disable_directive"
104
+ register_cop :RedundantCopEnableDirective, "#{__dir__}/lint/redundant_cop_enable_directive"
105
+ register_cop :RedundantDirGlobSort, "#{__dir__}/lint/redundant_dir_glob_sort"
106
+ register_cop :RedundantRegexpQuantifiers, "#{__dir__}/lint/redundant_regexp_quantifiers"
107
+ register_cop :RedundantRequireStatement, "#{__dir__}/lint/redundant_require_statement"
108
+ register_cop :RedundantSafeNavigation, "#{__dir__}/lint/redundant_safe_navigation"
109
+ register_cop :RedundantSplatExpansion, "#{__dir__}/lint/redundant_splat_expansion"
110
+ register_cop :RedundantStringCoercion, "#{__dir__}/lint/redundant_string_coercion"
111
+ register_cop :RedundantTypeConversion, "#{__dir__}/lint/redundant_type_conversion"
112
+ register_cop :RedundantWithIndex, "#{__dir__}/lint/redundant_with_index"
113
+ register_cop :RedundantWithObject, "#{__dir__}/lint/redundant_with_object"
114
+ register_cop :RefinementImportMethods, "#{__dir__}/lint/refinement_import_methods"
115
+ register_cop :RegexpAsCondition, "#{__dir__}/lint/regexp_as_condition"
116
+ register_cop :RequireParentheses, "#{__dir__}/lint/require_parentheses"
117
+ register_cop :RequireRangeParentheses, "#{__dir__}/lint/require_range_parentheses"
118
+ register_cop :RequireRelativeSelfPath, "#{__dir__}/lint/require_relative_self_path"
119
+ register_cop :RescueException, "#{__dir__}/lint/rescue_exception"
120
+ register_cop :RescueType, "#{__dir__}/lint/rescue_type"
121
+ register_cop :ReturnInVoidContext, "#{__dir__}/lint/return_in_void_context"
122
+ register_cop :SafeNavigationConsistency, "#{__dir__}/lint/safe_navigation_consistency"
123
+ register_cop :SafeNavigationChain, "#{__dir__}/lint/safe_navigation_chain"
124
+ register_cop :SafeNavigationWithEmpty, "#{__dir__}/lint/safe_navigation_with_empty"
125
+ register_cop :ScriptPermission, "#{__dir__}/lint/script_permission"
126
+ register_cop :SelfAssignment, "#{__dir__}/lint/self_assignment"
127
+ register_cop :SendWithMixinArgument, "#{__dir__}/lint/send_with_mixin_argument"
128
+ register_cop :ShadowedArgument, "#{__dir__}/lint/shadowed_argument"
129
+ register_cop :ShadowedException, "#{__dir__}/lint/shadowed_exception"
130
+ register_cop :ShadowingOuterLocalVariable, "#{__dir__}/lint/shadowing_outer_local_variable"
131
+ register_cop :StructNewOverride, "#{__dir__}/lint/struct_new_override"
132
+ register_cop :SuperArgumentMismatch, "#{__dir__}/lint/super_argument_mismatch"
133
+ register_cop :SuppressedException, "#{__dir__}/lint/suppressed_exception"
134
+ register_cop :SuppressedExceptionInNumberConversion, "#{__dir__}/lint/suppressed_exception_in_number_conversion"
135
+ register_cop :SymbolConversion, "#{__dir__}/lint/symbol_conversion"
136
+ register_cop :Syntax, "#{__dir__}/lint/syntax"
137
+ register_cop :ToEnumArguments, "#{__dir__}/lint/to_enum_arguments"
138
+ register_cop :ToJSON, "#{__dir__}/lint/to_json"
139
+ register_cop :TopLevelReturnWithArgument, "#{__dir__}/lint/top_level_return_with_argument"
140
+ register_cop :TrailingCommaInAttributeDeclaration, "#{__dir__}/lint/trailing_comma_in_attribute_declaration"
141
+ register_cop :TripleQuotes, "#{__dir__}/lint/triple_quotes"
142
+ register_cop :UnderscorePrefixedVariableName, "#{__dir__}/lint/underscore_prefixed_variable_name"
143
+ register_cop :UnescapedBracketInRegexp, "#{__dir__}/lint/unescaped_bracket_in_regexp"
144
+ register_cop :UnexpectedBlockArity, "#{__dir__}/lint/unexpected_block_arity"
145
+ register_cop :UnifiedInteger, "#{__dir__}/lint/unified_integer"
146
+ register_cop :UnmodifiedReduceAccumulator, "#{__dir__}/lint/unmodified_reduce_accumulator"
147
+ register_cop :UnreachableCode, "#{__dir__}/lint/unreachable_code"
148
+ register_cop :UnreachableLoop, "#{__dir__}/lint/unreachable_loop"
149
+ register_cop :UnreachablePatternBranch, "#{__dir__}/lint/unreachable_pattern_branch"
150
+ register_cop :UnusedBlockArgument, "#{__dir__}/lint/unused_block_argument"
151
+ register_cop :UnusedMethodArgument, "#{__dir__}/lint/unused_method_argument"
152
+ register_cop :UnusedPrivateMethod, "#{__dir__}/lint/unused_private_method"
153
+ register_cop :UriEscapeUnescape, "#{__dir__}/lint/uri_escape_unescape"
154
+ register_cop :UriRegexp, "#{__dir__}/lint/uri_regexp"
155
+ register_cop :UselessAccessModifier, "#{__dir__}/lint/useless_access_modifier"
156
+ register_cop :UselessAssignment, "#{__dir__}/lint/useless_assignment"
157
+ register_cop :UselessConstantScoping, "#{__dir__}/lint/useless_constant_scoping"
158
+ register_cop :UselessDefaultValueArgument, "#{__dir__}/lint/useless_default_value_argument"
159
+ register_cop :UselessDefined, "#{__dir__}/lint/useless_defined"
160
+ register_cop :UselessElseWithoutRescue, "#{__dir__}/lint/useless_else_without_rescue"
161
+ register_cop :UselessMethodDefinition, "#{__dir__}/lint/useless_method_definition"
162
+ register_cop :UselessNumericOperation, "#{__dir__}/lint/useless_numeric_operation"
163
+ register_cop :UselessOr, "#{__dir__}/lint/useless_or"
164
+ register_cop :UselessRescue, "#{__dir__}/lint/useless_rescue"
165
+ register_cop :UselessRuby2Keywords, "#{__dir__}/lint/useless_ruby2_keywords"
166
+ register_cop :UselessSetterCall, "#{__dir__}/lint/useless_setter_call"
167
+ register_cop :UselessTimes, "#{__dir__}/lint/useless_times"
168
+ register_cop :Void, "#{__dir__}/lint/void"
169
+
170
+ autoload :UnusedArgument, "#{__dir__}/mixin/unused_argument"
171
+
172
+ # Utility classes for `Lint` department cops.
173
+ module Utils
174
+ autoload :NilReceiverChecker, "#{__dir__}/lint/utils/nil_receiver_checker"
175
+ end
176
+ end
177
+ end
178
+ end
@@ -49,7 +49,7 @@ module RuboCop
49
49
 
50
50
  private
51
51
 
52
- # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
52
+ # rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
53
53
  def complexity_score_for(node)
54
54
  case node.type
55
55
  when :case
@@ -74,7 +74,6 @@ module RuboCop
74
74
  super
75
75
  end
76
76
  end
77
- # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
78
77
 
79
78
  def simple_in_pattern?(in_pattern_node)
80
79
  # `in_pattern_node.children[1]` is the guard (`if`/`unless`), or `nil`.
@@ -189,7 +189,7 @@ module RuboCop
189
189
  def source_from_node_with_heredoc(node)
190
190
  last_line = -1
191
191
  node.each_descendant do |descendant|
192
- next unless descendant.source
192
+ next if descendant.loc.nil? || descendant.source_range.nil?
193
193
 
194
194
  descendant_last_line =
195
195
  if heredoc_node?(descendant)
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # Cops for the `Metrics` department. The department's cops are registered for lazy loading
6
+ # and their files are loaded on demand.
7
+ module Metrics
8
+ extend LazyLoader
9
+
10
+ register_cop :CyclomaticComplexity, "#{__dir__}/metrics/cyclomatic_complexity"
11
+ register_cop :AbcSize, "#{__dir__}/metrics/abc_size"
12
+ register_cop :BlockLength, "#{__dir__}/metrics/block_length"
13
+ register_cop :BlockNesting, "#{__dir__}/metrics/block_nesting"
14
+ register_cop :ClassLength, "#{__dir__}/metrics/class_length"
15
+ register_cop :CollectionLiteralLength, "#{__dir__}/metrics/collection_literal_length"
16
+ register_cop :MethodLength, "#{__dir__}/metrics/method_length"
17
+ register_cop :ModuleLength, "#{__dir__}/metrics/module_length"
18
+ register_cop :ParameterLists, "#{__dir__}/metrics/parameter_lists"
19
+ register_cop :PerceivedComplexity, "#{__dir__}/metrics/perceived_complexity"
20
+
21
+ # Utility classes for `Metrics` department cops.
22
+ module Utils
23
+ autoload :AbcSizeCalculator, "#{__dir__}/metrics/utils/abc_size_calculator"
24
+ autoload :CodeLengthCalculator, "#{__dir__}/metrics/utils/code_length_calculator"
25
+ autoload :IteratingBlock, "#{__dir__}/metrics/utils/iterating_block"
26
+ autoload :RepeatedAttributeDiscount, "#{__dir__}/metrics/utils/repeated_attribute_discount"
27
+ autoload :RepeatedCsendDiscount, "#{__dir__}/metrics/utils/repeated_csend_discount"
28
+ end
29
+ end
30
+ end
31
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Lint/RedundantCopDisableDirective needs to be disabled so as
4
4
  # to be able to provide examples of rubocop:disable comments.
5
- # rubocop:disable Lint/RedundantCopDisableDirective
5
+ # rubocop:disable-next Lint/RedundantCopDisableDirective
6
6
  module RuboCop
7
7
  module Cop
8
8
  module Migration
@@ -50,10 +50,6 @@ module RuboCop
50
50
 
51
51
  private
52
52
 
53
- def disable_comment_offset
54
- Regexp.last_match(1).length
55
- end
56
-
57
53
  def check_cop_name(name, comment, offset)
58
54
  start = comment.source_range.begin_pos + offset
59
55
  range = range_between(start, start + name.length)
@@ -89,4 +85,3 @@ module RuboCop
89
85
  end
90
86
  end
91
87
  end
92
- # rubocop:enable Lint/RedundantCopDisableDirective
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # Cops for the `Migration` department. The department's cops are registered for lazy loading
6
+ # and their files are loaded on demand.
7
+ module Migration
8
+ extend LazyLoader
9
+
10
+ register_cop :DepartmentName, "#{__dir__}/migration/department_name"
11
+ end
12
+ end
13
+ end
@@ -61,11 +61,13 @@ module RuboCop
61
61
  # @api private
62
62
  def extract_breakable_node_from_elements(node, elements, max)
63
63
  return unless breakable_collection?(node, elements)
64
- return if safe_to_ignore?(node)
65
64
 
65
+ # Check the cheap conditions first, `safe_to_ignore?` may traverse all elements of
66
+ # a containing collection.
66
67
  line = processed_source.lines[node.first_line - 1]
68
+ return if max && line.length <= max
67
69
  return if processed_source.line_with_comment?(node.loc.line)
68
- return if line.length <= max
70
+ return if safe_to_ignore?(node)
69
71
 
70
72
  extract_first_element_over_column_limit(node, elements, max)
71
73
  end
@@ -173,20 +175,36 @@ module RuboCop
173
175
  node.each_ancestor.find do |ancestor|
174
176
  if ancestor.type?(:hash, :array) &&
175
177
  breakable_collection?(ancestor, ancestor.children)
176
- return children_could_be_broken_up?(ancestor.children)
178
+ return children_could_be_broken_up?(ancestor, ancestor.children)
177
179
  end
178
180
 
179
181
  next unless ancestor.call_type?
180
182
 
181
183
  args = process_args(ancestor.arguments)
182
- return children_could_be_broken_up?(args) if breakable_collection?(ancestor, args)
184
+ if breakable_collection?(ancestor, args)
185
+ return children_could_be_broken_up?(ancestor, args)
186
+ end
183
187
  end
184
188
 
185
189
  false
186
190
  end
187
191
 
188
192
  # @api private
189
- def children_could_be_broken_up?(children)
193
+ # The result depends only on the given node, but the check may traverse all children of
194
+ # a large collection and is repeated for each contained element, so memoize it per node.
195
+ def children_could_be_broken_up?(node, children)
196
+ if @check_line_breakable_processed_source != processed_source
197
+ @check_line_breakable_processed_source = processed_source
198
+ @children_could_be_broken_up_cache = {}.compare_by_identity
199
+ end
200
+
201
+ @children_could_be_broken_up_cache.fetch(node) do
202
+ @children_could_be_broken_up_cache[node] = compute_children_could_be_broken_up?(children)
203
+ end
204
+ end
205
+
206
+ # @api private
207
+ def compute_children_could_be_broken_up?(children)
190
208
  return false if all_on_same_line?(children)
191
209
 
192
210
  last_seen_line = -1
@@ -64,7 +64,7 @@ module RuboCop
64
64
  # Returns the end line of a node, which might be a comment and not part of the AST
65
65
  # End line is considered either the line at which another node starts, or
66
66
  # the line at which the parent node ends.
67
- # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
67
+ # rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
68
68
  def find_end_line(node)
69
69
  if node.if_type?
70
70
  if node.else?
@@ -89,7 +89,6 @@ module RuboCop
89
89
  end
90
90
  end || node.loc.end.line
91
91
  end
92
- # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
93
92
  end
94
93
  end
95
94
  end
@@ -25,7 +25,7 @@ module RuboCop
25
25
  end
26
26
  private_constant :SYMBOL_TO_STRING_CACHE
27
27
 
28
- # rubocop:disable Metrics
28
+ # rubocop:disable-next Metrics
29
29
  def style_detected(detected)
30
30
  return if no_acceptable_style?
31
31
 
@@ -51,7 +51,6 @@ module RuboCop
51
51
  config_to_allow_offenses[style_parameter_name] = updated_list.first
52
52
  end
53
53
  end
54
- # rubocop:enable Metrics
55
54
 
56
55
  def no_acceptable_style?
57
56
  config_to_allow_offenses['Enabled'] == false
@@ -5,20 +5,28 @@ module RuboCop
5
5
  # Common functionality for rewriting endless methods to normal method definitions
6
6
  module EndlessMethodRewriter
7
7
  def correct_to_multiline(corrector, node)
8
- replacement = <<~RUBY.strip
9
- def #{node.method_name}#{arguments(node)}
10
- #{node.body.source}
11
- end
12
- RUBY
8
+ replacement = [
9
+ "def #{receiver(node)}#{node.method_name}#{arguments(node)}",
10
+ "#{indent(node, offset: configured_indentation_width)}#{node.body.source}",
11
+ "#{indent(node)}end"
12
+ ].join("\n")
13
13
 
14
14
  corrector.replace(node, replacement)
15
15
  end
16
16
 
17
17
  private
18
18
 
19
+ def receiver(node)
20
+ node.receiver ? "#{node.receiver.source}#{node.loc.operator.source}" : ''
21
+ end
22
+
19
23
  def arguments(node, missing = '')
20
24
  node.arguments.any? ? node.arguments.source : missing
21
25
  end
26
+
27
+ def configured_indentation_width
28
+ cop_config['IndentationWidth'] || config.for_cop('Layout/IndentationWidth')['Width'] || 2
29
+ end
22
30
  end
23
31
  end
24
32
  end
@@ -96,20 +96,37 @@ module RuboCop
96
96
  end
97
97
 
98
98
  def hash_rocket_delta(first_pair, current_pair)
99
- first_pair.loc.column + max_key_width(first_pair.parent) + 1 -
100
- current_pair.loc.operator.column
99
+ target_operator_column(first_pair) - current_pair.loc.operator.column
101
100
  end
102
101
 
103
102
  def value_delta(first_pair, current_pair)
104
- correct_value_column = first_pair.key.loc.column +
105
- max_key_width(first_pair.parent) +
106
- max_delimiter_width(first_pair.parent)
103
+ correct_value_column = target_operator_column(first_pair) +
104
+ max_delimiter_width(first_pair.parent) - 1
107
105
 
108
106
  current_pair.value_omission? ? 0 : correct_value_column - current_pair.value.loc.column
109
107
  end
110
108
 
109
+ # The column the separator should land on: the shared key margin
110
+ # plus the widest single-line key, or, if larger, a multiline key's
111
+ # own last-line end column. The latter can't be measured from a
112
+ # multiline key's (newline-including) source length, so it's a
113
+ # separate candidate rather than folded into `max_key_width`.
114
+ def target_operator_column(first_pair)
115
+ hash_node = first_pair.parent
116
+ candidates = multiline_key_end_columns(hash_node)
117
+
118
+ key_width = max_key_width(hash_node)
119
+ candidates << (first_pair.loc.column + key_width + 1) if key_width.positive?
120
+
121
+ candidates.max
122
+ end
123
+
124
+ def multiline_key_end_columns(hash_node)
125
+ hash_node.keys.reject(&:single_line?).map { |key| key.source_range.end.column + 1 }
126
+ end
127
+
111
128
  def max_key_width(hash_node)
112
- hash_node.keys.map { |key| key.source.length }.max
129
+ hash_node.keys.select(&:single_line?).map { |key| key.source.length }.max || 0
113
130
  end
114
131
 
115
132
  def max_delimiter_width(hash_node)
@@ -117,7 +117,7 @@ module RuboCop
117
117
  use_modifier_form_without_parenthesized_method_call?(method_dispatch_node)
118
118
  end
119
119
 
120
- # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
120
+ # rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
121
121
  def def_node_that_require_parentheses(node)
122
122
  last_pair = node.parent.pairs.last
123
123
  return unless last_pair.key.source == last_pair.value.source
@@ -131,7 +131,6 @@ module RuboCop
131
131
 
132
132
  DefNode.new(def_node) unless def_node && def_node.arguments.empty?
133
133
  end
134
- # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
135
134
 
136
135
  def find_ancestor_method_dispatch_node(node)
137
136
  return unless (ancestor = node.parent.parent)
@@ -5,7 +5,7 @@ module RuboCop
5
5
  # Common functionality for Style/HashExcept and Style/HashSlice cops.
6
6
  # It registers an offense on methods with blocks that are equivalent
7
7
  # to Hash#except or Hash#slice.
8
- # rubocop:disable Metrics/ModuleLength
8
+ # rubocop:disable-next Metrics/ModuleLength
9
9
  module HashSubset
10
10
  include RangeHelp
11
11
  extend NodePattern::Macros
@@ -206,6 +206,5 @@ module RuboCop
206
206
  range_between(node.loc.selector.begin_pos, node.parent.loc.end.end_pos)
207
207
  end
208
208
  end
209
- # rubocop:enable Metrics/ModuleLength
210
209
  end
211
210
  end
@@ -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