rubocop 1.88.2 → 1.89.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 (103) hide show
  1. checksums.yaml +4 -4
  2. data/config/default.yml +67 -11
  3. data/lib/rubocop/comment_config.rb +35 -19
  4. data/lib/rubocop/config.rb +53 -0
  5. data/lib/rubocop/config_validator.rb +38 -1
  6. data/lib/rubocop/cop/badge.rb +8 -0
  7. data/lib/rubocop/cop/base.rb +6 -4
  8. data/lib/rubocop/cop/bundler.rb +19 -0
  9. data/lib/rubocop/cop/corrector.rb +1 -1
  10. data/lib/rubocop/cop/correctors/alignment_corrector.rb +55 -5
  11. data/lib/rubocop/cop/gemspec.rb +22 -0
  12. data/lib/rubocop/cop/generator/registration_injector.rb +188 -0
  13. data/lib/rubocop/cop/generator.rb +4 -0
  14. data/lib/rubocop/cop/layout/class_structure.rb +8 -2
  15. data/lib/rubocop/cop/layout/first_array_element_indentation.rb +1 -1
  16. data/lib/rubocop/cop/layout/indentation_width.rb +3 -1
  17. data/lib/rubocop/cop/layout/leading_comment_space.rb +27 -0
  18. data/lib/rubocop/cop/layout/line_length.rb +85 -12
  19. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +12 -2
  20. data/lib/rubocop/cop/layout/redundant_line_break.rb +77 -0
  21. data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +33 -34
  22. data/lib/rubocop/cop/layout.rb +114 -0
  23. data/lib/rubocop/cop/lazy_loader.rb +41 -0
  24. data/lib/rubocop/cop/lint/ambiguous_assignment.rb +9 -7
  25. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +71 -0
  26. data/lib/rubocop/cop/lint/constant_reassignment.rb +1 -10
  27. data/lib/rubocop/cop/lint/constant_resolution.rb +25 -0
  28. data/lib/rubocop/cop/lint/deprecated_reference.rb +185 -0
  29. data/lib/rubocop/cop/lint/duplicate_methods.rb +202 -22
  30. data/lib/rubocop/cop/lint/inherit_exception.rb +53 -7
  31. data/lib/rubocop/cop/lint/literal_as_condition.rb +5 -0
  32. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
  33. data/lib/rubocop/cop/lint/missing_super.rb +31 -1
  34. data/lib/rubocop/cop/lint/name_typo.rb +223 -0
  35. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +0 -4
  36. data/lib/rubocop/cop/lint/safe_navigation_chain.rb +7 -0
  37. data/lib/rubocop/cop/lint/to_enum_arguments.rb +37 -1
  38. data/lib/rubocop/cop/lint/unused_private_method.rb +157 -0
  39. data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +2 -0
  40. data/lib/rubocop/cop/lint/void.rb +17 -6
  41. data/lib/rubocop/cop/lint.rb +176 -0
  42. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
  43. data/lib/rubocop/cop/metrics.rb +31 -0
  44. data/lib/rubocop/cop/migration/department_name.rb +0 -4
  45. data/lib/rubocop/cop/migration.rb +13 -0
  46. data/lib/rubocop/cop/mixin/check_line_breakable.rb +23 -5
  47. data/lib/rubocop/cop/mixin/endless_method_rewriter.rb +13 -5
  48. data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +23 -6
  49. data/lib/rubocop/cop/mixin/project_index_help.rb +140 -0
  50. data/lib/rubocop/cop/mixin/reparsed_equivalence.rb +171 -0
  51. data/lib/rubocop/cop/mixin/statement_modifier.rb +42 -6
  52. data/lib/rubocop/cop/mixin.rb +78 -77
  53. data/lib/rubocop/cop/naming/accessor_method_name.rb +24 -0
  54. data/lib/rubocop/cop/naming/predicate_prefix.rb +33 -5
  55. data/lib/rubocop/cop/naming/variable_number.rb +3 -1
  56. data/lib/rubocop/cop/naming.rb +31 -0
  57. data/lib/rubocop/cop/offense.rb +10 -6
  58. data/lib/rubocop/cop/registry.rb +153 -43
  59. data/lib/rubocop/cop/security.rb +19 -0
  60. data/lib/rubocop/cop/style/array_intersect.rb +24 -5
  61. data/lib/rubocop/cop/style/class_and_module_children.rb +78 -18
  62. data/lib/rubocop/cop/style/conditional_assignment.rb +22 -0
  63. data/lib/rubocop/cop/style/copyright.rb +6 -1
  64. data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +41 -3
  65. data/lib/rubocop/cop/style/documentation.rb +47 -0
  66. data/lib/rubocop/cop/style/endless_method.rb +0 -10
  67. data/lib/rubocop/cop/style/if_unless_modifier.rb +7 -48
  68. data/lib/rubocop/cop/style/lambda.rb +4 -0
  69. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +20 -3
  70. data/lib/rubocop/cop/style/missing_respond_to_missing.rb +30 -0
  71. data/lib/rubocop/cop/style/multiline_if_then.rb +7 -1
  72. data/lib/rubocop/cop/style/multiple_comparison.rb +33 -22
  73. data/lib/rubocop/cop/style/mutable_constant.rb +5 -0
  74. data/lib/rubocop/cop/style/negative_array_index.rb +3 -1
  75. data/lib/rubocop/cop/style/redundant_assignment.rb +11 -0
  76. data/lib/rubocop/cop/style/redundant_constant_base.rb +37 -1
  77. data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +9 -0
  78. data/lib/rubocop/cop/style/redundant_format.rb +12 -3
  79. data/lib/rubocop/cop/style/redundant_line_continuation.rb +78 -135
  80. data/lib/rubocop/cop/style/redundant_parentheses.rb +63 -63
  81. data/lib/rubocop/cop/style/safe_navigation.rb +10 -0
  82. data/lib/rubocop/cop/style/sole_nested_conditional.rb +20 -3
  83. data/lib/rubocop/cop/style/static_class.rb +21 -0
  84. data/lib/rubocop/cop/style.rb +310 -0
  85. data/lib/rubocop/cop/team.rb +48 -3
  86. data/lib/rubocop/cop/variable_force/variable.rb +18 -6
  87. data/lib/rubocop/cops_documentation_generator.rb +1 -1
  88. data/lib/rubocop/directive_comment.rb +2 -0
  89. data/lib/rubocop/feature_loader.rb +0 -6
  90. data/lib/rubocop/lsp/routes.rb +41 -3
  91. data/lib/rubocop/lsp/runtime.rb +4 -0
  92. data/lib/rubocop/lsp/server.rb +4 -0
  93. data/lib/rubocop/lsp/stdin_runner.rb +20 -0
  94. data/lib/rubocop/pending_cops_reporter.rb +1 -6
  95. data/lib/rubocop/project_index_loader.rb +16 -0
  96. data/lib/rubocop/result_cache.rb +6 -4
  97. data/lib/rubocop/rspec/shared_contexts.rb +14 -2
  98. data/lib/rubocop/runner.rb +45 -20
  99. data/lib/rubocop/server/cache.rb +10 -5
  100. data/lib/rubocop/target_ruby.rb +1 -1
  101. data/lib/rubocop/version.rb +1 -1
  102. data/lib/rubocop.rb +17 -626
  103. metadata +18 -3
@@ -0,0 +1,176 @@
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 :ArrayLiteralInRegexp, "#{__dir__}/lint/array_literal_in_regexp"
17
+ register_cop :AssignmentInCondition, "#{__dir__}/lint/assignment_in_condition"
18
+ register_cop :BigDecimalNew, "#{__dir__}/lint/big_decimal_new"
19
+ register_cop :BinaryOperatorWithIdenticalOperands, "#{__dir__}/lint/binary_operator_with_identical_operands"
20
+ register_cop :BooleanSymbol, "#{__dir__}/lint/boolean_symbol"
21
+ register_cop :CircularArgumentReference, "#{__dir__}/lint/circular_argument_reference"
22
+ register_cop :ConstantDefinitionInBlock, "#{__dir__}/lint/constant_definition_in_block"
23
+ register_cop :ConstantOverwrittenInRescue, "#{__dir__}/lint/constant_overwritten_in_rescue"
24
+ register_cop :ConstantReassignment, "#{__dir__}/lint/constant_reassignment"
25
+ register_cop :ConstantResolution, "#{__dir__}/lint/constant_resolution"
26
+ register_cop :CopDirectiveSyntax, "#{__dir__}/lint/cop_directive_syntax"
27
+ register_cop :DataDefineOverride, "#{__dir__}/lint/data_define_override"
28
+ register_cop :Debugger, "#{__dir__}/lint/debugger"
29
+ register_cop :DeprecatedClassMethods, "#{__dir__}/lint/deprecated_class_methods"
30
+ register_cop :DeprecatedConstants, "#{__dir__}/lint/deprecated_constants"
31
+ register_cop :DeprecatedOpenSSLConstant, "#{__dir__}/lint/deprecated_open_ssl_constant"
32
+ register_cop :DeprecatedReference, "#{__dir__}/lint/deprecated_reference"
33
+ register_cop :DisjunctiveAssignmentInConstructor, "#{__dir__}/lint/disjunctive_assignment_in_constructor"
34
+ register_cop :DuplicateBranch, "#{__dir__}/lint/duplicate_branch"
35
+ register_cop :DuplicateCaseCondition, "#{__dir__}/lint/duplicate_case_condition"
36
+ register_cop :DuplicateElsifCondition, "#{__dir__}/lint/duplicate_elsif_condition"
37
+ register_cop :DuplicateHashKey, "#{__dir__}/lint/duplicate_hash_key"
38
+ register_cop :DuplicateMagicComment, "#{__dir__}/lint/duplicate_magic_comment"
39
+ register_cop :DuplicateMatchPattern, "#{__dir__}/lint/duplicate_match_pattern"
40
+ register_cop :DuplicateMethods, "#{__dir__}/lint/duplicate_methods"
41
+ register_cop :DuplicateRegexpCharacterClassElement, "#{__dir__}/lint/duplicate_regexp_character_class_element"
42
+ register_cop :DuplicateRequire, "#{__dir__}/lint/duplicate_require"
43
+ register_cop :DuplicateRescueException, "#{__dir__}/lint/duplicate_rescue_exception"
44
+ register_cop :DuplicateSetElement, "#{__dir__}/lint/duplicate_set_element"
45
+ register_cop :EachWithObjectArgument, "#{__dir__}/lint/each_with_object_argument"
46
+ register_cop :ElseLayout, "#{__dir__}/lint/else_layout"
47
+ register_cop :EmptyBlock, "#{__dir__}/lint/empty_block"
48
+ register_cop :EmptyClass, "#{__dir__}/lint/empty_class"
49
+ register_cop :EmptyConditionalBody, "#{__dir__}/lint/empty_conditional_body"
50
+ register_cop :EmptyEnsure, "#{__dir__}/lint/empty_ensure"
51
+ register_cop :EmptyExpression, "#{__dir__}/lint/empty_expression"
52
+ register_cop :EmptyFile, "#{__dir__}/lint/empty_file"
53
+ register_cop :EmptyInPattern, "#{__dir__}/lint/empty_in_pattern"
54
+ register_cop :EmptyInterpolation, "#{__dir__}/lint/empty_interpolation"
55
+ register_cop :EmptyWhen, "#{__dir__}/lint/empty_when"
56
+ register_cop :EnsureReturn, "#{__dir__}/lint/ensure_return"
57
+ register_cop :SharedMutableDefault, "#{__dir__}/lint/shared_mutable_default"
58
+ register_cop :ErbNewArguments, "#{__dir__}/lint/erb_new_arguments"
59
+ register_cop :FlipFlop, "#{__dir__}/lint/flip_flop"
60
+ register_cop :FloatComparison, "#{__dir__}/lint/float_comparison"
61
+ register_cop :FloatOutOfRange, "#{__dir__}/lint/float_out_of_range"
62
+ register_cop :FormatParameterMismatch, "#{__dir__}/lint/format_parameter_mismatch"
63
+ register_cop :HashCompareByIdentity, "#{__dir__}/lint/hash_compare_by_identity"
64
+ register_cop :HashNewWithKeywordArgumentsAsDefault, "#{__dir__}/lint/hash_new_with_keyword_arguments_as_default"
65
+ register_cop :HeredocMethodCallPosition, "#{__dir__}/lint/heredoc_method_call_position"
66
+ register_cop :IdentityComparison, "#{__dir__}/lint/identity_comparison"
67
+ register_cop :ImplicitStringConcatenation, "#{__dir__}/lint/implicit_string_concatenation"
68
+ register_cop :IncompatibleIoSelectWithFiberScheduler, "#{__dir__}/lint/incompatible_io_select_with_fiber_scheduler"
69
+ register_cop :IneffectiveAccessModifier, "#{__dir__}/lint/ineffective_access_modifier"
70
+ register_cop :InheritException, "#{__dir__}/lint/inherit_exception"
71
+ register_cop :InterpolationCheck, "#{__dir__}/lint/interpolation_check"
72
+ register_cop :ItWithoutArgumentsInBlock, "#{__dir__}/lint/it_without_arguments_in_block"
73
+ register_cop :LambdaWithoutLiteralBlock, "#{__dir__}/lint/lambda_without_literal_block"
74
+ register_cop :LiteralAsCondition, "#{__dir__}/lint/literal_as_condition"
75
+ register_cop :LiteralAssignmentInCondition, "#{__dir__}/lint/literal_assignment_in_condition"
76
+ register_cop :LiteralInInterpolation, "#{__dir__}/lint/literal_in_interpolation"
77
+ register_cop :Loop, "#{__dir__}/lint/loop"
78
+ register_cop :MissingCopEnableDirective, "#{__dir__}/lint/missing_cop_enable_directive"
79
+ register_cop :MissingSuper, "#{__dir__}/lint/missing_super"
80
+ register_cop :MixedCaseRange, "#{__dir__}/lint/mixed_case_range"
81
+ register_cop :MixedRegexpCaptureTypes, "#{__dir__}/lint/mixed_regexp_capture_types"
82
+ register_cop :MultipleComparison, "#{__dir__}/lint/multiple_comparison"
83
+ register_cop :NameTypo, "#{__dir__}/lint/name_typo"
84
+ register_cop :NestedMethodDefinition, "#{__dir__}/lint/nested_method_definition"
85
+ register_cop :NestedPercentLiteral, "#{__dir__}/lint/nested_percent_literal"
86
+ register_cop :NextWithoutAccumulator, "#{__dir__}/lint/next_without_accumulator"
87
+ register_cop :NoReturnInBeginEndBlocks, "#{__dir__}/lint/no_return_in_begin_end_blocks"
88
+ register_cop :NonAtomicFileOperation, "#{__dir__}/lint/non_atomic_file_operation"
89
+ register_cop :NonDeterministicRequireOrder, "#{__dir__}/lint/non_deterministic_require_order"
90
+ register_cop :NonLocalExitFromIterator, "#{__dir__}/lint/non_local_exit_from_iterator"
91
+ register_cop :NumberConversion, "#{__dir__}/lint/number_conversion"
92
+ register_cop :NumberedParameterAssignment, "#{__dir__}/lint/numbered_parameter_assignment"
93
+ register_cop :NumericOperationWithConstantResult, "#{__dir__}/lint/numeric_operation_with_constant_result"
94
+ register_cop :OrAssignmentToConstant, "#{__dir__}/lint/or_assignment_to_constant"
95
+ register_cop :OrderedMagicComments, "#{__dir__}/lint/ordered_magic_comments"
96
+ register_cop :OutOfRangeRegexpRef, "#{__dir__}/lint/out_of_range_regexp_ref"
97
+ register_cop :ParenthesesAsGroupedExpression, "#{__dir__}/lint/parentheses_as_grouped_expression"
98
+ register_cop :PercentStringArray, "#{__dir__}/lint/percent_string_array"
99
+ register_cop :PercentSymbolArray, "#{__dir__}/lint/percent_symbol_array"
100
+ register_cop :RaiseException, "#{__dir__}/lint/raise_exception"
101
+ register_cop :RandOne, "#{__dir__}/lint/rand_one"
102
+ register_cop :RedundantCopDisableDirective, "#{__dir__}/lint/redundant_cop_disable_directive"
103
+ register_cop :RedundantCopEnableDirective, "#{__dir__}/lint/redundant_cop_enable_directive"
104
+ register_cop :RedundantDirGlobSort, "#{__dir__}/lint/redundant_dir_glob_sort"
105
+ register_cop :RedundantRegexpQuantifiers, "#{__dir__}/lint/redundant_regexp_quantifiers"
106
+ register_cop :RedundantRequireStatement, "#{__dir__}/lint/redundant_require_statement"
107
+ register_cop :RedundantSafeNavigation, "#{__dir__}/lint/redundant_safe_navigation"
108
+ register_cop :RedundantSplatExpansion, "#{__dir__}/lint/redundant_splat_expansion"
109
+ register_cop :RedundantStringCoercion, "#{__dir__}/lint/redundant_string_coercion"
110
+ register_cop :RedundantTypeConversion, "#{__dir__}/lint/redundant_type_conversion"
111
+ register_cop :RedundantWithIndex, "#{__dir__}/lint/redundant_with_index"
112
+ register_cop :RedundantWithObject, "#{__dir__}/lint/redundant_with_object"
113
+ register_cop :RefinementImportMethods, "#{__dir__}/lint/refinement_import_methods"
114
+ register_cop :RegexpAsCondition, "#{__dir__}/lint/regexp_as_condition"
115
+ register_cop :RequireParentheses, "#{__dir__}/lint/require_parentheses"
116
+ register_cop :RequireRangeParentheses, "#{__dir__}/lint/require_range_parentheses"
117
+ register_cop :RequireRelativeSelfPath, "#{__dir__}/lint/require_relative_self_path"
118
+ register_cop :RescueException, "#{__dir__}/lint/rescue_exception"
119
+ register_cop :RescueType, "#{__dir__}/lint/rescue_type"
120
+ register_cop :ReturnInVoidContext, "#{__dir__}/lint/return_in_void_context"
121
+ register_cop :SafeNavigationConsistency, "#{__dir__}/lint/safe_navigation_consistency"
122
+ register_cop :SafeNavigationChain, "#{__dir__}/lint/safe_navigation_chain"
123
+ register_cop :SafeNavigationWithEmpty, "#{__dir__}/lint/safe_navigation_with_empty"
124
+ register_cop :ScriptPermission, "#{__dir__}/lint/script_permission"
125
+ register_cop :SelfAssignment, "#{__dir__}/lint/self_assignment"
126
+ register_cop :SendWithMixinArgument, "#{__dir__}/lint/send_with_mixin_argument"
127
+ register_cop :ShadowedArgument, "#{__dir__}/lint/shadowed_argument"
128
+ register_cop :ShadowedException, "#{__dir__}/lint/shadowed_exception"
129
+ register_cop :ShadowingOuterLocalVariable, "#{__dir__}/lint/shadowing_outer_local_variable"
130
+ register_cop :StructNewOverride, "#{__dir__}/lint/struct_new_override"
131
+ register_cop :SuppressedException, "#{__dir__}/lint/suppressed_exception"
132
+ register_cop :SuppressedExceptionInNumberConversion, "#{__dir__}/lint/suppressed_exception_in_number_conversion"
133
+ register_cop :SymbolConversion, "#{__dir__}/lint/symbol_conversion"
134
+ register_cop :Syntax, "#{__dir__}/lint/syntax"
135
+ register_cop :ToEnumArguments, "#{__dir__}/lint/to_enum_arguments"
136
+ register_cop :ToJSON, "#{__dir__}/lint/to_json"
137
+ register_cop :TopLevelReturnWithArgument, "#{__dir__}/lint/top_level_return_with_argument"
138
+ register_cop :TrailingCommaInAttributeDeclaration, "#{__dir__}/lint/trailing_comma_in_attribute_declaration"
139
+ register_cop :TripleQuotes, "#{__dir__}/lint/triple_quotes"
140
+ register_cop :UnderscorePrefixedVariableName, "#{__dir__}/lint/underscore_prefixed_variable_name"
141
+ register_cop :UnescapedBracketInRegexp, "#{__dir__}/lint/unescaped_bracket_in_regexp"
142
+ register_cop :UnexpectedBlockArity, "#{__dir__}/lint/unexpected_block_arity"
143
+ register_cop :UnifiedInteger, "#{__dir__}/lint/unified_integer"
144
+ register_cop :UnmodifiedReduceAccumulator, "#{__dir__}/lint/unmodified_reduce_accumulator"
145
+ register_cop :UnreachableCode, "#{__dir__}/lint/unreachable_code"
146
+ register_cop :UnreachableLoop, "#{__dir__}/lint/unreachable_loop"
147
+ register_cop :UnreachablePatternBranch, "#{__dir__}/lint/unreachable_pattern_branch"
148
+ register_cop :UnusedBlockArgument, "#{__dir__}/lint/unused_block_argument"
149
+ register_cop :UnusedMethodArgument, "#{__dir__}/lint/unused_method_argument"
150
+ register_cop :UnusedPrivateMethod, "#{__dir__}/lint/unused_private_method"
151
+ register_cop :UriEscapeUnescape, "#{__dir__}/lint/uri_escape_unescape"
152
+ register_cop :UriRegexp, "#{__dir__}/lint/uri_regexp"
153
+ register_cop :UselessAccessModifier, "#{__dir__}/lint/useless_access_modifier"
154
+ register_cop :UselessAssignment, "#{__dir__}/lint/useless_assignment"
155
+ register_cop :UselessConstantScoping, "#{__dir__}/lint/useless_constant_scoping"
156
+ register_cop :UselessDefaultValueArgument, "#{__dir__}/lint/useless_default_value_argument"
157
+ register_cop :UselessDefined, "#{__dir__}/lint/useless_defined"
158
+ register_cop :UselessElseWithoutRescue, "#{__dir__}/lint/useless_else_without_rescue"
159
+ register_cop :UselessMethodDefinition, "#{__dir__}/lint/useless_method_definition"
160
+ register_cop :UselessNumericOperation, "#{__dir__}/lint/useless_numeric_operation"
161
+ register_cop :UselessOr, "#{__dir__}/lint/useless_or"
162
+ register_cop :UselessRescue, "#{__dir__}/lint/useless_rescue"
163
+ register_cop :UselessRuby2Keywords, "#{__dir__}/lint/useless_ruby2_keywords"
164
+ register_cop :UselessSetterCall, "#{__dir__}/lint/useless_setter_call"
165
+ register_cop :UselessTimes, "#{__dir__}/lint/useless_times"
166
+ register_cop :Void, "#{__dir__}/lint/void"
167
+
168
+ autoload :UnusedArgument, "#{__dir__}/mixin/unused_argument"
169
+
170
+ # Utility classes for `Lint` department cops.
171
+ module Utils
172
+ autoload :NilReceiverChecker, "#{__dir__}/lint/utils/nil_receiver_checker"
173
+ end
174
+ end
175
+ end
176
+ end
@@ -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
@@ -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)
@@ -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
@@ -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)
@@ -17,6 +17,14 @@ module RuboCop
17
17
  # remains after stripping `file://` from a `file:///C:/...` URI.
18
18
  WINDOWS_DRIVE_PREFIX = %r{\A/(?=[A-Za-z]:[/\\])}.freeze
19
19
 
20
+ class << self
21
+ # The signature is a property of the index, not of the cop, and computing
22
+ # it stats every indexed file, so all cops sharing an index share one
23
+ # computation. A single-entry cache (instead of a hash keyed by index)
24
+ # avoids retaining stale graphs in long-lived processes.
25
+ attr_accessor :cached_index_signature
26
+ end
27
+
20
28
  def external_dependency_checksum
21
29
  return nil unless project_index
22
30
 
@@ -27,7 +35,139 @@ module RuboCop
27
35
 
28
36
  private
29
37
 
38
+ # Returns the definitions among `definitions` that live in a file other than the
39
+ # one being inspected, ordered by path and line. Definitions without a `file://`
40
+ # URI (e.g. Rubydex's built-in declarations) are ignored.
41
+ def definitions_in_other_files(definitions)
42
+ current = processed_source.file_path
43
+
44
+ definitions
45
+ .select { |definition| definition.location.uri.start_with?(FILE_URI_PREFIX) }
46
+ .reject { |definition| File.identical?(definition.location.to_file_path, current) }
47
+ .sort_by do |definition|
48
+ [definition.location.to_file_path,
49
+ definition.location.start_line]
50
+ end
51
+ end
52
+
53
+ def prior_definition_in_other_file(definitions)
54
+ definitions_in_other_files(definitions).first
55
+ end
56
+
57
+ # Resolves a constant node the way Ruby does: the first segment through
58
+ # the lexical nesting and every following segment inside the previous
59
+ # one. (Qualified names cannot be passed to `resolve_constant` as a
60
+ # whole, since it only applies the nesting to the full name. Later
61
+ # segments use `find_member` — the namespace and its ancestors — since
62
+ # `resolve_constant` cannot take an already-resolved namespace as the
63
+ # scope, only names as they appear in source.)
64
+ def resolve_constant_in_index(const_node)
65
+ segments = const_node.const_name.split('::')
66
+ nesting = const_node.absolute? ? [] : lexical_nesting_of(const_node)
67
+
68
+ declaration = project_index.resolve_constant(segments.first, nesting)
69
+ segments.drop(1).each do |segment|
70
+ return nil unless declaration.is_a?(Rubydex::Namespace)
71
+
72
+ declaration = declaration.find_member(segment)
73
+ end
74
+
75
+ declaration
76
+ end
77
+
78
+ # The lexical nesting the node's constants resolve through, outermost
79
+ # first. Only scopes whose *body* contains the node count: a class or
80
+ # module's identifier and superclass expression are evaluated before its
81
+ # scope exists, so ancestors reached through them are excluded.
82
+ def lexical_nesting_of(node)
83
+ nesting = []
84
+ child = node
85
+
86
+ node.each_ancestor do |ancestor|
87
+ if ancestor.type?(:class, :module) && child.equal?(ancestor.body)
88
+ nesting << ancestor.identifier.const_name
89
+ end
90
+ child = ancestor
91
+ end
92
+
93
+ nesting.reverse
94
+ end
95
+
96
+ # The declaration of `declaration`'s singleton class, or nil when no
97
+ # singleton method is defined on it anywhere in the project.
98
+ def indexed_singleton_of(declaration)
99
+ project_index["#{declaration.name}::<#{declaration.name.split('::').last}>"]
100
+ end
101
+
102
+ # A namespace without any singleton method has no singleton-class
103
+ # declaration of its own, so the lookup starts from the first ancestor
104
+ # that has one; its `find_member` covers the rest of the chain.
105
+ def indexed_singleton_member(namespace, member_name)
106
+ namespace.ancestors.each do |ancestor|
107
+ singleton = indexed_singleton_of(ancestor)
108
+ return singleton.find_member(member_name) if singleton
109
+ end
110
+
111
+ nil
112
+ end
113
+
114
+ # Whether an ancestor of `scope` other than `scope` itself defines
115
+ # `member_name`.
116
+ def inherited_index_member?(scope, member_name)
117
+ scope.ancestors.any? do |ancestor|
118
+ ancestor.name != scope.name && ancestor.member(member_name)
119
+ end
120
+ end
121
+
122
+ # Whether every link of the declaration's ancestry is resolved in the
123
+ # index: no definition of any ancestor has an unresolved superclass or
124
+ # mixin reference. Unresolved links silently vanish from `ancestors`,
125
+ # so this is the completeness check that must pass before reasoning
126
+ # about what an ancestry does or does not define. `extend` mixins only
127
+ # affect the singleton class; pass `ignore_extend: true` when reasoning
128
+ # about instance-side ancestry only.
129
+ def fully_resolved_index_ancestry?(declaration, ignore_extend: false)
130
+ declaration.ancestors.all? do |ancestor|
131
+ ancestor.definitions.all? do |definition|
132
+ resolved_superclass_reference?(definition) &&
133
+ resolved_mixin_references?(definition, ignore_extend: ignore_extend)
134
+ end
135
+ end
136
+ end
137
+
138
+ def resolved_superclass_reference?(definition)
139
+ return true unless definition.is_a?(Rubydex::ClassDefinition)
140
+
141
+ !definition.superclass.is_a?(Rubydex::UnresolvedConstantReference)
142
+ end
143
+
144
+ def resolved_mixin_references?(definition, ignore_extend: false)
145
+ return true unless definition.respond_to?(:mixins)
146
+
147
+ definition.mixins.none? do |mixin|
148
+ next false if ignore_extend && mixin.is_a?(Rubydex::Extend)
149
+
150
+ mixin.constant_reference.is_a?(Rubydex::UnresolvedConstantReference)
151
+ end
152
+ end
153
+
154
+ def same_file?(path, other)
155
+ return true if File.identical?(path, other)
156
+
157
+ normalized = [path, other].map { |p| File.expand_path(p).tr('\\', '/') }
158
+ normalized.uniq.one? || (Platform.windows? && normalized[0].casecmp?(normalized[1]))
159
+ end
160
+
30
161
  def project_index_signature
162
+ index, signature = ProjectIndexHelp.cached_index_signature
163
+ return signature if index.equal?(project_index)
164
+
165
+ compute_project_index_signature.tap do |computed|
166
+ ProjectIndexHelp.cached_index_signature = [project_index, computed]
167
+ end
168
+ end
169
+
170
+ def compute_project_index_signature
31
171
  project_index.documents.filter_map do |doc|
32
172
  uri = doc.uri
33
173
  next if uri == BUILTIN_DOCUMENT_URI