rubocop-callbacksystems 0.1.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 (182) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +78 -0
  4. data/config/default.yml +590 -0
  5. data/docs/cops.md +111 -0
  6. data/lib/rubocop/callbacksystems/autocorrection/batch.rb +135 -0
  7. data/lib/rubocop/callbacksystems/autocorrection/comment_rescue.rb +112 -0
  8. data/lib/rubocop/callbacksystems/autocorrection/rehearsal.rb +65 -0
  9. data/lib/rubocop/callbacksystems/autocorrection/rewrite_permit.rb +14 -0
  10. data/lib/rubocop/callbacksystems/class_structure/builder_assignment.rb +48 -0
  11. data/lib/rubocop/callbacksystems/class_structure/class_body.rb +50 -0
  12. data/lib/rubocop/callbacksystems/class_structure/divergence.rb +31 -0
  13. data/lib/rubocop/callbacksystems/class_structure/node_visibility.rb +82 -0
  14. data/lib/rubocop/callbacksystems/class_structure/reference_order.rb +36 -0
  15. data/lib/rubocop/callbacksystems/class_structure/statement_rank.rb +84 -0
  16. data/lib/rubocop/callbacksystems/class_structure/statement_run.rb +42 -0
  17. data/lib/rubocop/callbacksystems/class_structure/visibility.rb +84 -0
  18. data/lib/rubocop/callbacksystems/cops_document.rb +78 -0
  19. data/lib/rubocop/callbacksystems/execution/deferred_local_variables.rb +138 -0
  20. data/lib/rubocop/callbacksystems/execution/discarded_expression.rb +45 -0
  21. data/lib/rubocop/callbacksystems/execution/eager_evaluation_path.rb +73 -0
  22. data/lib/rubocop/callbacksystems/execution/immediate.rb +71 -0
  23. data/lib/rubocop/callbacksystems/execution/local_variable_occurrences.rb +112 -0
  24. data/lib/rubocop/callbacksystems/hashes/key_transform_detection.rb +108 -0
  25. data/lib/rubocop/callbacksystems/hashes/keyword_options.rb +37 -0
  26. data/lib/rubocop/callbacksystems/helpers/bodies.rb +150 -0
  27. data/lib/rubocop/callbacksystems/helpers/builders.rb +103 -0
  28. data/lib/rubocop/callbacksystems/helpers/comments.rb +56 -0
  29. data/lib/rubocop/callbacksystems/helpers/corrections.rb +15 -0
  30. data/lib/rubocop/callbacksystems/helpers/methods.rb +46 -0
  31. data/lib/rubocop/callbacksystems/helpers/names.rb +65 -0
  32. data/lib/rubocop/callbacksystems/helpers/node_types.rb +154 -0
  33. data/lib/rubocop/callbacksystems/helpers/rails.rb +52 -0
  34. data/lib/rubocop/callbacksystems/helpers/ranges.rb +107 -0
  35. data/lib/rubocop/callbacksystems/helpers/recursion.rb +29 -0
  36. data/lib/rubocop/callbacksystems/helpers/variables.rb +44 -0
  37. data/lib/rubocop/callbacksystems/helpers/visibility.rb +121 -0
  38. data/lib/rubocop/callbacksystems/helpers.rb +43 -0
  39. data/lib/rubocop/callbacksystems/methods/calls.rb +38 -0
  40. data/lib/rubocop/callbacksystems/methods/definitions.rb +218 -0
  41. data/lib/rubocop/callbacksystems/methods/delegate_macro.rb +144 -0
  42. data/lib/rubocop/callbacksystems/methods/delegation_target.rb +55 -0
  43. data/lib/rubocop/callbacksystems/methods/domain.rb +77 -0
  44. data/lib/rubocop/callbacksystems/methods/implicit_invocations.rb +17 -0
  45. data/lib/rubocop/callbacksystems/methods/macro_references.rb +238 -0
  46. data/lib/rubocop/callbacksystems/methods/reference_evidence.rb +74 -0
  47. data/lib/rubocop/callbacksystems/methods/siblings.rb +24 -0
  48. data/lib/rubocop/callbacksystems/methods/statement_definitions.rb +68 -0
  49. data/lib/rubocop/callbacksystems/offense.rb +13 -0
  50. data/lib/rubocop/callbacksystems/plugin.rb +27 -0
  51. data/lib/rubocop/callbacksystems/project_index/cache.rb +16 -0
  52. data/lib/rubocop/callbacksystems/project_index/confinement_cache.rb +40 -0
  53. data/lib/rubocop/callbacksystems/project_index/constant_references.rb +74 -0
  54. data/lib/rubocop/callbacksystems/project_index/corrections.rb +35 -0
  55. data/lib/rubocop/callbacksystems/project_index/coverage.rb +56 -0
  56. data/lib/rubocop/callbacksystems/project_index/diagnostics.rb +60 -0
  57. data/lib/rubocop/callbacksystems/project_index/freshness.rb +104 -0
  58. data/lib/rubocop/callbacksystems/project_index/loader.rb +9 -0
  59. data/lib/rubocop/callbacksystems/project_index/location.rb +29 -0
  60. data/lib/rubocop/callbacksystems/project_index/nested_class_confinement.rb +297 -0
  61. data/lib/rubocop/callbacksystems/project_index/nested_class_method_dispatch.rb +50 -0
  62. data/lib/rubocop/callbacksystems/project_index/reading.rb +129 -0
  63. data/lib/rubocop/callbacksystems/project_index/source_file.rb +59 -0
  64. data/lib/rubocop/callbacksystems/project_index/source_file_match.rb +57 -0
  65. data/lib/rubocop/callbacksystems/project_index/support.rb +46 -0
  66. data/lib/rubocop/callbacksystems/source/comment_blocks.rb +43 -0
  67. data/lib/rubocop/callbacksystems/source/comments.rb +141 -0
  68. data/lib/rubocop/callbacksystems/source/file_ast.rb +15 -0
  69. data/lib/rubocop/callbacksystems/source/files_checksum.rb +43 -0
  70. data/lib/rubocop/callbacksystems/source/single_line_call.rb +181 -0
  71. data/lib/rubocop/callbacksystems/source/statement_with_comments.rb +131 -0
  72. data/lib/rubocop/callbacksystems/testing/cop_helpers.rb +42 -0
  73. data/lib/rubocop/callbacksystems/testing/fixture_call.rb +30 -0
  74. data/lib/rubocop/callbacksystems/testing/fixture_names.rb +62 -0
  75. data/lib/rubocop/callbacksystems/testing/path_mapping.rb +104 -0
  76. data/lib/rubocop/cop/callbacksystems/application_controller_method_definition.rb +44 -0
  77. data/lib/rubocop/cop/callbacksystems/assert_with_expected_argument.rb +60 -0
  78. data/lib/rubocop/cop/callbacksystems/base.rb +134 -0
  79. data/lib/rubocop/cop/callbacksystems/body_order.rb +478 -0
  80. data/lib/rubocop/cop/callbacksystems/builder_method_parentheses.rb +74 -0
  81. data/lib/rubocop/cop/callbacksystems/collapse_multiline_expression.rb +140 -0
  82. data/lib/rubocop/cop/callbacksystems/comment_block_length.rb +137 -0
  83. data/lib/rubocop/cop/callbacksystems/complex_conditional.rb +75 -0
  84. data/lib/rubocop/cop/callbacksystems/controller_test_response_assertion.rb +105 -0
  85. data/lib/rubocop/cop/callbacksystems/controller_test_response_first_assertion.rb +123 -0
  86. data/lib/rubocop/cop/callbacksystems/data_clump.rb +339 -0
  87. data/lib/rubocop/cop/callbacksystems/declarative_method_naming.rb +350 -0
  88. data/lib/rubocop/cop/callbacksystems/delegate_requires_private_option.rb +81 -0
  89. data/lib/rubocop/cop/callbacksystems/eager_loading_scope_naming.rb +386 -0
  90. data/lib/rubocop/cop/callbacksystems/early_return.rb +215 -0
  91. data/lib/rubocop/cop/callbacksystems/empty_line_before_method.rb +168 -0
  92. data/lib/rubocop/cop/callbacksystems/empty_line_between_sections.rb +169 -0
  93. data/lib/rubocop/cop/callbacksystems/empty_private_section.rb +107 -0
  94. data/lib/rubocop/cop/callbacksystems/expanded_empty_class_or_module.rb +71 -0
  95. data/lib/rubocop/cop/callbacksystems/inline_memoized_computation.rb +110 -0
  96. data/lib/rubocop/cop/callbacksystems/job_enqueue_methods.rb +93 -0
  97. data/lib/rubocop/cop/callbacksystems/max_safe_navigation_depth.rb +118 -0
  98. data/lib/rubocop/cop/callbacksystems/method_invocation_order.rb +261 -0
  99. data/lib/rubocop/cop/callbacksystems/nested_class_order.rb +255 -0
  100. data/lib/rubocop/cop/callbacksystems/no_abbreviations.rb +197 -0
  101. data/lib/rubocop/cop/callbacksystems/no_anemic_delegation.rb +101 -0
  102. data/lib/rubocop/cop/callbacksystems/no_anemic_record.rb +309 -0
  103. data/lib/rubocop/cop/callbacksystems/no_assert_select.rb +31 -0
  104. data/lib/rubocop/cop/callbacksystems/no_bang_method_without_counterpart.rb +451 -0
  105. data/lib/rubocop/cop/callbacksystems/no_call_method.rb +73 -0
  106. data/lib/rubocop/cop/callbacksystems/no_comments_in_test_class_body.rb +159 -0
  107. data/lib/rubocop/cop/callbacksystems/no_consecutive_appends.rb +261 -0
  108. data/lib/rubocop/cop/callbacksystems/no_custom_route_actions.rb +124 -0
  109. data/lib/rubocop/cop/callbacksystems/no_direct_eager_loading.rb +90 -0
  110. data/lib/rubocop/cop/callbacksystems/no_each_with_early_return.rb +58 -0
  111. data/lib/rubocop/cop/callbacksystems/no_explicit_public_modifier.rb +81 -0
  112. data/lib/rubocop/cop/callbacksystems/no_hash_with_default_block.rb +68 -0
  113. data/lib/rubocop/cop/callbacksystems/no_local_variable_return.rb +173 -0
  114. data/lib/rubocop/cop/callbacksystems/no_manual_accumulation.rb +188 -0
  115. data/lib/rubocop/cop/callbacksystems/no_mixed_memoization.rb +145 -0
  116. data/lib/rubocop/cop/callbacksystems/no_nested_modules_in_classes.rb +78 -0
  117. data/lib/rubocop/cop/callbacksystems/no_nil_at_end_of_method.rb +74 -0
  118. data/lib/rubocop/cop/callbacksystems/no_redundant_validation_name.rb +37 -0
  119. data/lib/rubocop/cop/callbacksystems/no_redundant_wrapper_method.rb +161 -0
  120. data/lib/rubocop/cop/callbacksystems/no_section_divider_comments.rb +105 -0
  121. data/lib/rubocop/cop/callbacksystems/no_send_in_tests.rb +75 -0
  122. data/lib/rubocop/cop/callbacksystems/no_service_objects.rb +64 -0
  123. data/lib/rubocop/cop/callbacksystems/no_single_letter_names.rb +47 -0
  124. data/lib/rubocop/cop/callbacksystems/no_singleton_class_in_modules.rb +43 -0
  125. data/lib/rubocop/cop/callbacksystems/no_tap_collection_building.rb +173 -0
  126. data/lib/rubocop/cop/callbacksystems/no_turbo_stream_in_controllers.rb +52 -0
  127. data/lib/rubocop/cop/callbacksystems/no_typographic_clutter.rb +159 -0
  128. data/lib/rubocop/cop/callbacksystems/no_writes_in_get_actions.rb +149 -0
  129. data/lib/rubocop/cop/callbacksystems/ordered_mixin_arguments.rb +78 -0
  130. data/lib/rubocop/cop/callbacksystems/plural_controller_names.rb +103 -0
  131. data/lib/rubocop/cop/callbacksystems/prefer_attr_reader_over_instance_variable.rb +86 -0
  132. data/lib/rubocop/cop/callbacksystems/prefer_backslash_continuation.rb +478 -0
  133. data/lib/rubocop/cop/callbacksystems/prefer_class_for_state.rb +532 -0
  134. data/lib/rubocop/cop/callbacksystems/prefer_class_new_for_empty_nested_class.rb +247 -0
  135. data/lib/rubocop/cop/callbacksystems/prefer_class_over_builder_block.rb +124 -0
  136. data/lib/rubocop/cop/callbacksystems/prefer_default_argument.rb +225 -0
  137. data/lib/rubocop/cop/callbacksystems/prefer_delegate.rb +242 -0
  138. data/lib/rubocop/cop/callbacksystems/prefer_delegate_over_instance_variable_assignment.rb +175 -0
  139. data/lib/rubocop/cop/callbacksystems/prefer_excluding.rb +204 -0
  140. data/lib/rubocop/cop/callbacksystems/prefer_extract_associated.rb +54 -0
  141. data/lib/rubocop/cop/callbacksystems/prefer_it_block_parameter.rb +156 -0
  142. data/lib/rubocop/cop/callbacksystems/prefer_many.rb +57 -0
  143. data/lib/rubocop/cop/callbacksystems/prefer_method_over_lambda.rb +211 -0
  144. data/lib/rubocop/cop/callbacksystems/prefer_method_over_variable.rb +172 -0
  145. data/lib/rubocop/cop/callbacksystems/prefer_module_for_static_class.rb +286 -0
  146. data/lib/rubocop/cop/callbacksystems/prefer_ordinal_array_access.rb +136 -0
  147. data/lib/rubocop/cop/callbacksystems/prefer_positive_wrap.rb +265 -0
  148. data/lib/rubocop/cop/callbacksystems/prefer_squish.rb +47 -0
  149. data/lib/rubocop/cop/callbacksystems/prefer_stringify_keys.rb +24 -0
  150. data/lib/rubocop/cop/callbacksystems/prefer_symbolize_keys.rb +24 -0
  151. data/lib/rubocop/cop/callbacksystems/prefer_turbo_page_refresh_broadcasts.rb +40 -0
  152. data/lib/rubocop/cop/callbacksystems/private_constants_in_private_section.rb +160 -0
  153. data/lib/rubocop/cop/callbacksystems/private_delegate_placement.rb +342 -0
  154. data/lib/rubocop/cop/callbacksystems/private_methods_in_private_section.rb +70 -0
  155. data/lib/rubocop/cop/callbacksystems/private_nested_class_method_visibility.rb +269 -0
  156. data/lib/rubocop/cop/callbacksystems/private_nested_classes.rb +94 -0
  157. data/lib/rubocop/cop/callbacksystems/public_methods_must_have_tests.rb +190 -0
  158. data/lib/rubocop/cop/callbacksystems/redundant_concern_extend.rb +157 -0
  159. data/lib/rubocop/cop/callbacksystems/redundant_constant_freeze.rb +57 -0
  160. data/lib/rubocop/cop/callbacksystems/redundant_constant_namespace.rb +134 -0
  161. data/lib/rubocop/cop/callbacksystems/reflow_comments.rb +133 -0
  162. data/lib/rubocop/cop/callbacksystems/repeated_fixture_in_tests.rb +106 -0
  163. data/lib/rubocop/cop/callbacksystems/restricted_controller_actions.rb +85 -0
  164. data/lib/rubocop/cop/callbacksystems/routes_module_scope.rb +336 -0
  165. data/lib/rubocop/cop/callbacksystems/single_line_setup_block.rb +107 -0
  166. data/lib/rubocop/cop/callbacksystems/single_singleton_class.rb +49 -0
  167. data/lib/rubocop/cop/callbacksystems/single_top_level_class_or_module.rb +160 -0
  168. data/lib/rubocop/cop/callbacksystems/single_use_fixture_variable.rb +211 -0
  169. data/lib/rubocop/cop/callbacksystems/single_use_setup_variable.rb +684 -0
  170. data/lib/rubocop/cop/callbacksystems/singular_scope_names.rb +47 -0
  171. data/lib/rubocop/cop/callbacksystems/space_inside_percent_literal.rb +73 -0
  172. data/lib/rubocop/cop/callbacksystems/system_test_browser_driver.rb +30 -0
  173. data/lib/rubocop/cop/callbacksystems/test_method_definition.rb +86 -0
  174. data/lib/rubocop/cop/callbacksystems/test_method_order.rb +319 -0
  175. data/lib/rubocop/cop/callbacksystems/too_many_instance_variables.rb +78 -0
  176. data/lib/rubocop/cop/callbacksystems/too_many_local_variables.rb +77 -0
  177. data/lib/rubocop/cop/callbacksystems/too_many_validation_guards.rb +84 -0
  178. data/lib/rubocop/cop/callbacksystems/unnecessary_local_variable.rb +176 -0
  179. data/lib/rubocop/cop/callbacksystems/unused_private_method_in_nested_class.rb +203 -0
  180. data/lib/rubocop-callbacksystems.rb +21 -0
  181. data/rubocop.yml +685 -0
  182. metadata +337 -0
data/docs/cops.md ADDED
@@ -0,0 +1,111 @@
1
+ # Cops
2
+
3
+ <!-- Generated by `bin/docs`. Do not edit by hand. -->
4
+
5
+ Every cop lives under the `Callbacksystems/` namespace and ships enabled. Each one links to its source, where an `@example` block contrasts the code it rejects with the code it asks for, and `config/default.yml` holds its options and default scope.
6
+
7
+ | Cop | Autocorrect | Description |
8
+ |---|---|---|
9
+ | [`Callbacksystems/ApplicationControllerMethodDefinition`](../lib/rubocop/cop/callbacksystems/application_controller_method_definition.rb) | | Prohibits defining methods directly in ApplicationController. |
10
+ | [`Callbacksystems/AssertWithExpectedArgument`](../lib/rubocop/cop/callbacksystems/assert_with_expected_argument.rb) | | Flags a two-argument `assert` whose second argument is not a failure message. |
11
+ | [`Callbacksystems/BodyOrder`](../lib/rubocop/cop/callbacksystems/body_order.rb) | yes | Orders a class body: mixins, constants, class declarations, state declarations, associations, delegates, macros, methods, nested classes. |
12
+ | [`Callbacksystems/BuilderMethodParentheses`](../lib/rubocop/cop/callbacksystems/builder_method_parentheses.rb) | yes | Requires parentheses on builder method calls that take arguments. |
13
+ | [`Callbacksystems/CollapseMultilineExpression`](../lib/rubocop/cop/callbacksystems/collapse_multiline_expression.rb) | yes | Collapses multiline expressions that fit on a single line. |
14
+ | [`Callbacksystems/CommentBlockLength`](../lib/rubocop/cop/callbacksystems/comment_block_length.rb) | | Limits how many lines a comment block takes. |
15
+ | [`Callbacksystems/ComplexConditional`](../lib/rubocop/cop/callbacksystems/complex_conditional.rb) | | Limits boolean operators in a conditional, so predicates get extracted. |
16
+ | [`Callbacksystems/ControllerTestResponseAssertion`](../lib/rubocop/cop/callbacksystems/controller_test_response_assertion.rb) | | Requires every controller test that makes a request to assert the response. |
17
+ | [`Callbacksystems/ControllerTestResponseFirstAssertion`](../lib/rubocop/cop/callbacksystems/controller_test_response_first_assertion.rb) | | Requires the response assertion to come first after a request in controller tests. |
18
+ | [`Callbacksystems/DataClump`](../lib/rubocop/cop/callbacksystems/data_clump.rb) | | Detects parameter names that travel together across private methods and belong in an object of their own. |
19
+ | [`Callbacksystems/DeclarativeMethodNaming`](../lib/rubocop/cop/callbacksystems/declarative_method_naming.rb) | | Requires a value-returning method to be named for the value, not the action. |
20
+ | [`Callbacksystems/DelegateRequiresPrivateOption`](../lib/rubocop/cop/callbacksystems/delegate_requires_private_option.rb) | yes | Requires `private: true` on a `delegate` that stands in the private section. |
21
+ | [`Callbacksystems/EagerLoadingScopeNaming`](../lib/rubocop/cop/callbacksystems/eager_loading_scope_naming.rb) | | Reserves `with_*` for eager loading scopes and requires specific association names. |
22
+ | [`Callbacksystems/EarlyReturn`](../lib/rubocop/cop/callbacksystems/early_return.rb) | | Allows a single guard clause on the first line as the only early exit. |
23
+ | [`Callbacksystems/EmptyLineBeforeMethod`](../lib/rubocop/cop/callbacksystems/empty_line_before_method.rb) | yes | Requires an empty line before a method definition. |
24
+ | [`Callbacksystems/EmptyLineBetweenSections`](../lib/rubocop/cop/callbacksystems/empty_line_between_sections.rb) | yes | Requires a blank line between two adjacent statements of different sections of a class body. |
25
+ | [`Callbacksystems/EmptyPrivateSection`](../lib/rubocop/cop/callbacksystems/empty_private_section.rb) | yes | Flags a `private` keyword that declares an empty section. |
26
+ | [`Callbacksystems/ExpandedEmptyClassOrModule`](../lib/rubocop/cop/callbacksystems/expanded_empty_class_or_module.rb) | yes | Requires an empty class or module to keep its `end` on a line of its own. |
27
+ | [`Callbacksystems/InlineMemoizedComputation`](../lib/rubocop/cop/callbacksystems/inline_memoized_computation.rb) | | Requires the computation to be inlined in the method that memoizes it. |
28
+ | [`Callbacksystems/JobEnqueueMethods`](../lib/rubocop/cop/callbacksystems/job_enqueue_methods.rb) | | Requires a method that enqueues a job to carry the `_later` suffix. |
29
+ | [`Callbacksystems/MaxSafeNavigationDepth`](../lib/rubocop/cop/callbacksystems/max_safe_navigation_depth.rb) | | Limits the depth of a chain of safe navigation calls. |
30
+ | [`Callbacksystems/MethodInvocationOrder`](../lib/rubocop/cop/callbacksystems/method_invocation_order.rb) | yes | Requires methods to be ordered by invocation, each caller before its callees. |
31
+ | [`Callbacksystems/NestedClassOrder`](../lib/rubocop/cop/callbacksystems/nested_class_order.rb) | yes | Requires nested classes to be ordered by reference, each before the ones it names. |
32
+ | [`Callbacksystems/NoAbbreviations`](../lib/rubocop/cop/callbacksystems/no_abbreviations.rb) | | Requires full words in declared names, including CamelCase, while preserving Ruby and Rails vocabulary. |
33
+ | [`Callbacksystems/NoAnemicDelegation`](../lib/rubocop/cop/callbacksystems/no_anemic_delegation.rb) | | Flags a private method that only delegates to a freshly built object. |
34
+ | [`Callbacksystems/NoAnemicRecord`](../lib/rubocop/cop/callbacksystems/no_anemic_record.rb) | | Detects a hash literal of several fields read across methods, which reads better as a class. |
35
+ | [`Callbacksystems/NoAssertSelect`](../lib/rubocop/cop/callbacksystems/no_assert_select.rb) | | Prohibits `assert_select` in tests. |
36
+ | [`Callbacksystems/NoBangMethodWithoutCounterpart`](../lib/rubocop/cop/callbacksystems/no_bang_method_without_counterpart.rb) | | Prohibits a bang method without a non-bang counterpart. |
37
+ | [`Callbacksystems/NoCallMethod`](../lib/rubocop/cop/callbacksystems/no_call_method.rb) | | Prohibits defining a method named `call`, except for Rack middleware endpoints. |
38
+ | [`Callbacksystems/NoCommentsInTestClassBody`](../lib/rubocop/cop/callbacksystems/no_comments_in_test_class_body.rb) | | Prohibits comments in the direct body of a test class. |
39
+ | [`Callbacksystems/NoConsecutiveAppends`](../lib/rubocop/cop/callbacksystems/no_consecutive_appends.rb) | yes | Collapses consecutive appends to one collection into a single `push`. |
40
+ | [`Callbacksystems/NoCustomRouteActions`](../lib/rubocop/cop/callbacksystems/no_custom_route_actions.rb) | | Keeps routes on the standard resource actions. |
41
+ | [`Callbacksystems/NoDirectEagerLoading`](../lib/rubocop/cop/callbacksystems/no_direct_eager_loading.rb) | | Keeps `preload`, `eager_load`, and `includes` inside `app/models` behind named scopes. |
42
+ | [`Callbacksystems/NoEachWithEarlyReturn`](../lib/rubocop/cop/callbacksystems/no_each_with_early_return.rb) | | Prefers `find` over an `each` block with a conditional early return. |
43
+ | [`Callbacksystems/NoExplicitPublicModifier`](../lib/rubocop/cop/callbacksystems/no_explicit_public_modifier.rb) | yes | Prohibits the explicit `public` modifier. |
44
+ | [`Callbacksystems/NoHashWithDefaultBlock`](../lib/rubocop/cop/callbacksystems/no_hash_with_default_block.rb) | | Prefers declarative grouping over `Hash.new` with a default block. |
45
+ | [`Callbacksystems/NoLocalVariableReturn`](../lib/rubocop/cop/callbacksystems/no_local_variable_return.rb) | yes | Prohibits returning a local variable as the last statement of a method. |
46
+ | [`Callbacksystems/NoManualAccumulation`](../lib/rubocop/cop/callbacksystems/no_manual_accumulation.rb) | | Prefers declarative collection methods over filling an empty array or hash inside `each`. |
47
+ | [`Callbacksystems/NoMixedMemoization`](../lib/rubocop/cop/callbacksystems/no_mixed_memoization.rb) | | Prohibits mixing memoization with other statements in the same method. |
48
+ | [`Callbacksystems/NoNestedModulesInClasses`](../lib/rubocop/cop/callbacksystems/no_nested_modules_in_classes.rb) | | Prohibits a module nested inside a class. |
49
+ | [`Callbacksystems/NoNilAtEndOfMethod`](../lib/rubocop/cop/callbacksystems/no_nil_at_end_of_method.rb) | | Prohibits a trailing `nil` at the end of a method. |
50
+ | [`Callbacksystems/NoRedundantValidationName`](../lib/rubocop/cop/callbacksystems/no_redundant_validation_name.rb) | | Requires a validation callback to name its condition without repeating `valid` or `validate`. |
51
+ | [`Callbacksystems/NoRedundantWrapperMethod`](../lib/rubocop/cop/callbacksystems/no_redundant_wrapper_method.rb) | | Flags a private method that only forwards to another call. |
52
+ | [`Callbacksystems/NoSectionDividerComments`](../lib/rubocop/cop/callbacksystems/no_section_divider_comments.rb) | yes | Prohibits ASCII-art section divider comments. |
53
+ | [`Callbacksystems/NoSendInTests`](../lib/rubocop/cop/callbacksystems/no_send_in_tests.rb) | | Prohibits `send` and `__send__` in tests. |
54
+ | [`Callbacksystems/NoServiceObjects`](../lib/rubocop/cop/callbacksystems/no_service_objects.rb) | | Prohibits service object directories under `app/`. |
55
+ | [`Callbacksystems/NoSingleLetterNames`](../lib/rubocop/cop/callbacksystems/no_single_letter_names.rb) | | Prohibits single-letter variable, block argument, and parameter names. |
56
+ | [`Callbacksystems/NoSingletonClassInModules`](../lib/rubocop/cop/callbacksystems/no_singleton_class_in_modules.rb) | | Prefers `extend self` over `class << self` in a module. |
57
+ | [`Callbacksystems/NoTapCollectionBuilding`](../lib/rubocop/cop/callbacksystems/no_tap_collection_building.rb) | | Prohibits building a collection imperatively with `tap`. |
58
+ | [`Callbacksystems/NoTurboStreamInControllers`](../lib/rubocop/cop/callbacksystems/no_turbo_stream_in_controllers.rb) | | Keeps Turbo Stream markup out of controllers. |
59
+ | [`Callbacksystems/NoTypographicClutter`](../lib/rubocop/cop/callbacksystems/no_typographic_clutter.rb) | yes | Prohibits typographic punctuation and double-hyphen dashes in comments, and invisible characters in comments and strings. |
60
+ | [`Callbacksystems/NoWritesInGetActions`](../lib/rubocop/cop/callbacksystems/no_writes_in_get_actions.rb) | | Keeps GET actions free of writes and enqueued side effects. |
61
+ | [`Callbacksystems/OrderedMixinArguments`](../lib/rubocop/cop/callbacksystems/ordered_mixin_arguments.rb) | yes | Requires mixin arguments to be sorted alphabetically. |
62
+ | [`Callbacksystems/PluralControllerNames`](../lib/rubocop/cop/callbacksystems/plural_controller_names.rb) | | Requires controller names to be plural. |
63
+ | [`Callbacksystems/PreferAttrReaderOverInstanceVariable`](../lib/rubocop/cop/callbacksystems/prefer_attr_reader_over_instance_variable.rb) | | Prefers an `attr_reader` over reading an instance variable assigned in `initialize`. |
64
+ | [`Callbacksystems/PreferBackslashContinuation`](../lib/rubocop/cop/callbacksystems/prefer_backslash_continuation.rb) | yes | Prefers backslash continuation over parentheses for a multiline call that cannot fit on one line. |
65
+ | [`Callbacksystems/PreferClassForState`](../lib/rubocop/cop/callbacksystems/prefer_class_for_state.rb) | | Detects a value threaded through many methods that reads better as class state. |
66
+ | [`Callbacksystems/PreferClassNewForEmptyNestedClass`](../lib/rubocop/cop/callbacksystems/prefer_class_new_for_empty_nested_class.rb) | yes | Prefers a `Class.new` constant over a nested class with no body. |
67
+ | [`Callbacksystems/PreferClassOverBuilderBlock`](../lib/rubocop/cop/callbacksystems/prefer_class_over_builder_block.rb) | yes | Prefers a class over a `Data.define`, `Struct.new`, or `Class.new` given a block. |
68
+ | [`Callbacksystems/PreferDefaultArgument`](../lib/rubocop/cop/callbacksystems/prefer_default_argument.rb) | | Prefers a default in the signature over a fallback assigned at the top of the method. |
69
+ | [`Callbacksystems/PreferDelegate`](../lib/rubocop/cop/callbacksystems/prefer_delegate.rb) | yes | Prefers `delegate` over a method that only forwards to a same-named method. |
70
+ | [`Callbacksystems/PreferDelegateOverInstanceVariableAssignment`](../lib/rubocop/cop/callbacksystems/prefer_delegate_over_instance_variable_assignment.rb) | | Prefers `delegate` over an `initialize` assignment that mirrors a method call. |
71
+ | [`Callbacksystems/PreferExcluding`](../lib/rubocop/cop/callbacksystems/prefer_excluding.rb) | yes | Prefers `excluding` for collection subtraction and suggests it for record-ID exclusions. |
72
+ | [`Callbacksystems/PreferExtractAssociated`](../lib/rubocop/cop/callbacksystems/prefer_extract_associated.rb) | yes | Prefers `extract_associated` over preloading and collecting the same association in a model. |
73
+ | [`Callbacksystems/PreferItBlockParameter`](../lib/rubocop/cop/callbacksystems/prefer_it_block_parameter.rb) | yes | Prefers `it` over a single named parameter in a single-line block. |
74
+ | [`Callbacksystems/PreferMany`](../lib/rubocop/cop/callbacksystems/prefer_many.rb) | yes | Prefers `many?` over comparing `size` with one. |
75
+ | [`Callbacksystems/PreferMethodOverLambda`](../lib/rubocop/cop/callbacksystems/prefer_method_over_lambda.rb) | | Prefers a method over a lambda or proc held in a local that captures nothing from its method. |
76
+ | [`Callbacksystems/PreferMethodOverVariable`](../lib/rubocop/cop/callbacksystems/prefer_method_over_variable.rb) | | Prefers a method over a local variable that repeats the name it calls. |
77
+ | [`Callbacksystems/PreferModuleForStaticClass`](../lib/rubocop/cop/callbacksystems/prefer_module_for_static_class.rb) | | Prefers a module with `extend self` over a class holding only class-level code. |
78
+ | [`Callbacksystems/PreferOrdinalArrayAccess`](../lib/rubocop/cop/callbacksystems/prefer_ordinal_array_access.rb) | yes | Prefers an ordinal method such as `first` over a numeric array index. |
79
+ | [`Callbacksystems/PreferPositiveWrap`](../lib/rubocop/cop/callbacksystems/prefer_positive_wrap.rb) | yes | Prefers wrapping the happy path in `if` over a leading negative guard. |
80
+ | [`Callbacksystems/PreferSquish`](../lib/rubocop/cop/callbacksystems/prefer_squish.rb) | yes | Prefers `squish` over stripping and collapsing whitespace by hand. |
81
+ | [`Callbacksystems/PreferStringifyKeys`](../lib/rubocop/cop/callbacksystems/prefer_stringify_keys.rb) | yes | Prefers `stringify_keys` over `transform_keys(&:to_s)`. |
82
+ | [`Callbacksystems/PreferSymbolizeKeys`](../lib/rubocop/cop/callbacksystems/prefer_symbolize_keys.rb) | yes | Prefers `symbolize_keys` over `transform_keys(&:to_sym)`. |
83
+ | [`Callbacksystems/PreferTurboPageRefreshBroadcasts`](../lib/rubocop/cop/callbacksystems/prefer_turbo_page_refresh_broadcasts.rb) | | Prefers Turbo page refreshes over targeted stream broadcasts. |
84
+ | [`Callbacksystems/PrivateConstantsInPrivateSection`](../lib/rubocop/cop/callbacksystems/private_constants_in_private_section.rb) | | Requires a constant that serves the implementation to live in the private section. |
85
+ | [`Callbacksystems/PrivateDelegatePlacement`](../lib/rubocop/cop/callbacksystems/private_delegate_placement.rb) | yes | Requires a `delegate ... private: true` to sit in the private section. |
86
+ | [`Callbacksystems/PrivateMethodsInPrivateSection`](../lib/rubocop/cop/callbacksystems/private_methods_in_private_section.rb) | | Requires a private method to be defined in the private section, not marked afterwards. |
87
+ | [`Callbacksystems/PrivateNestedClassMethodVisibility`](../lib/rubocop/cop/callbacksystems/private_nested_class_method_visibility.rb) | | Requires a method in a nested class placed below `private` to be private when nothing outside calls it. |
88
+ | [`Callbacksystems/PrivateNestedClasses`](../lib/rubocop/cop/callbacksystems/private_nested_classes.rb) | | Requires a nested class to be declared in the private section. |
89
+ | [`Callbacksystems/PublicMethodsMustHaveTests`](../lib/rubocop/cop/callbacksystems/public_methods_must_have_tests.rb) | | Requires every public method to have a test. |
90
+ | [`Callbacksystems/RedundantConcernExtend`](../lib/rubocop/cop/callbacksystems/redundant_concern_extend.rb) | yes | Flags an unnecessary `extend ActiveSupport::Concern`. |
91
+ | [`Callbacksystems/RedundantConstantFreeze`](../lib/rubocop/cop/callbacksystems/redundant_constant_freeze.rb) | yes | Flags a `freeze` on a constant assignment. |
92
+ | [`Callbacksystems/RedundantConstantNamespace`](../lib/rubocop/cop/callbacksystems/redundant_constant_namespace.rb) | yes | Flags a constant reference that repeats the namespace it is written inside. |
93
+ | [`Callbacksystems/ReflowComments`](../lib/rubocop/cop/callbacksystems/reflow_comments.rb) | yes | Refills a comment block wrapped short of the maximum line length. |
94
+ | [`Callbacksystems/RepeatedFixtureInTests`](../lib/rubocop/cop/callbacksystems/repeated_fixture_in_tests.rb) | | Requires a fixture used by several tests to move to `setup`. |
95
+ | [`Callbacksystems/RestrictedControllerActions`](../lib/rubocop/cop/callbacksystems/restricted_controller_actions.rb) | | Restricts a controller to the seven standard Rails actions. |
96
+ | [`Callbacksystems/RoutesModuleScope`](../lib/rubocop/cop/callbacksystems/routes_module_scope.rb) | yes | Requires repeated `module:` options in routes to be extracted to a scope block. |
97
+ | [`Callbacksystems/SingleLineSetupBlock`](../lib/rubocop/cop/callbacksystems/single_line_setup_block.rb) | yes | Requires braces for a single-line `setup` or `teardown` block. |
98
+ | [`Callbacksystems/SingleSingletonClass`](../lib/rubocop/cop/callbacksystems/single_singleton_class.rb) | | Requires class-level methods to live in a single `class << self` section. |
99
+ | [`Callbacksystems/SingleTopLevelClassOrModule`](../lib/rubocop/cop/callbacksystems/single_top_level_class_or_module.rb) | | Prohibits more than one top-level class or module per file. |
100
+ | [`Callbacksystems/SingleUseFixtureVariable`](../lib/rubocop/cop/callbacksystems/single_use_fixture_variable.rb) | yes | Requires a fixture used once to be inlined. |
101
+ | [`Callbacksystems/SingleUseSetupVariable`](../lib/rubocop/cop/callbacksystems/single_use_setup_variable.rb) | yes | Requires a setup variable used by at most one test to be inlined. |
102
+ | [`Callbacksystems/SingularScopeNames`](../lib/rubocop/cop/callbacksystems/singular_scope_names.rb) | | Requires scope names to be singular unless they use a `with_` prefix. |
103
+ | [`Callbacksystems/SpaceInsidePercentLiteral`](../lib/rubocop/cop/callbacksystems/space_inside_percent_literal.rb) | yes | Requires a space inside the delimiters of a percent literal. |
104
+ | [`Callbacksystems/SystemTestBrowserDriver`](../lib/rubocop/cop/callbacksystems/system_test_browser_driver.rb) | | Keeps system tests on a real browser driver. |
105
+ | [`Callbacksystems/TestMethodDefinition`](../lib/rubocop/cop/callbacksystems/test_method_definition.rb) | | Requires `test` and block syntax over `def test_*` and setup method definitions. |
106
+ | [`Callbacksystems/TestMethodOrder`](../lib/rubocop/cop/callbacksystems/test_method_order.rb) | yes | Requires tests to follow the method order of the file they cover. |
107
+ | [`Callbacksystems/TooManyInstanceVariables`](../lib/rubocop/cop/callbacksystems/too_many_instance_variables.rb) | | Limits instance variable assignments in a private method. |
108
+ | [`Callbacksystems/TooManyLocalVariables`](../lib/rubocop/cop/callbacksystems/too_many_local_variables.rb) | | Limits local variable assignments in a method. |
109
+ | [`Callbacksystems/TooManyValidationGuards`](../lib/rubocop/cop/callbacksystems/too_many_validation_guards.rb) | | Limits the validation guards standing at the start of a method. |
110
+ | [`Callbacksystems/UnnecessaryLocalVariable`](../lib/rubocop/cop/callbacksystems/unnecessary_local_variable.rb) | yes | Flags a local variable that aliases a method call already reading as a name. |
111
+ | [`Callbacksystems/UnusedPrivateMethodInNestedClass`](../lib/rubocop/cop/callbacksystems/unused_private_method_in_nested_class.rb) | | Flags an unused private method in a nested class placed below `private`. |
@@ -0,0 +1,135 @@
1
+ # Corrections from one cop rehearsed together. The common path parses the rewritten file once. When preserving comments
2
+ # fails, every entry must have a safe form and their exact aggregate must pass a second rehearsal. A batch is atomic
3
+ # because its entries may depend on each other in ways syntax and comment checks cannot see.
4
+ class RuboCop::Callbacksystems::Autocorrection::Batch
5
+ BYPASS_DEPTH = :rubocop_callbacksystems_correction_batch_bypass_depth
6
+
7
+ class << self
8
+ # The audit reads what a correction does on its own, so a cop that declines can be told from one held back.
9
+ def bypassing
10
+ Thread.current.thread_variable_set(BYPASS_DEPTH, bypass_depth + 1)
11
+ yield
12
+ ensure
13
+ Thread.current.thread_variable_set(BYPASS_DEPTH, bypass_depth - 1)
14
+ end
15
+
16
+ def bypassed?
17
+ bypass_depth.positive?
18
+ end
19
+
20
+ private
21
+ def bypass_depth
22
+ Thread.current.thread_variable_get(BYPASS_DEPTH).to_i
23
+ end
24
+ end
25
+
26
+ def initialize(entries, processed_source)
27
+ @entries = entries
28
+ @processed_source = processed_source
29
+ end
30
+
31
+ def correction_for(entry)
32
+ corrections[entry]
33
+ end
34
+
35
+ private
36
+ attr_reader :entries, :processed_source
37
+
38
+ def corrections
39
+ self.class.bypassed? ? bypassed_corrections : accepted_corrections
40
+ end
41
+
42
+ def bypassed_corrections
43
+ @bypassed_corrections ||= selected_corrections
44
+ end
45
+
46
+ def selected_corrections
47
+ Selection.new(entries, processed_source).corrections
48
+ end
49
+
50
+ def accepted_corrections
51
+ @accepted_corrections ||= selected_corrections
52
+ end
53
+
54
+ class Selection
55
+ attr_reader :corrections
56
+
57
+ def initialize(entries, processed_source)
58
+ @entries = entries
59
+ @processed_source = processed_source
60
+ @corrections = {}.compare_by_identity
61
+ selected.each { |entry, correction| corrections[entry] = correction }
62
+ end
63
+
64
+ private
65
+ attr_reader :entries, :processed_source
66
+
67
+ def selected
68
+ if accepts?(as_written) then as_written
69
+ elsif rescued_corrections_accepted? then rescued
70
+ else []
71
+ end
72
+ end
73
+
74
+ def accepts?(candidates)
75
+ rehearsal = RuboCop::Callbacksystems::Autocorrection::Rehearsal.new \
76
+ combined_correction(candidates), processed_source
77
+ RuboCop::Callbacksystems::Autocorrection::Batch.bypassed? || rehearsal.empty? ||
78
+ (rehearsal.parses? && (rewrites_comments? || rehearsal.keeps_comments?))
79
+ rescue Parser::ClobberingError
80
+ false
81
+ end
82
+
83
+ def combined_correction(candidates)
84
+ ->(corrector) { candidates.each { it.last.call(corrector) } }
85
+ end
86
+
87
+ def rewrites_comments?
88
+ entries.all? { it.respond_to?(:rewrites_comments?) && it.rewrites_comments? }
89
+ end
90
+
91
+ def as_written
92
+ @as_written ||= entries.map { [ it, it.correction ] }
93
+ end
94
+
95
+ def rescued_corrections_accepted?
96
+ !rewrites_comments? && rescued && accepts?(rescued)
97
+ end
98
+
99
+ def rescued
100
+ @rescued ||= RehearsedCandidates.new(entries, processed_source).to_a
101
+ end
102
+
103
+ class RehearsedCandidates
104
+ def initialize(entries, processed_source)
105
+ @entries = entries
106
+ @processed_source = processed_source
107
+ end
108
+
109
+ def to_a
110
+ candidates if candidates.size == entries.size
111
+ end
112
+
113
+ private
114
+ attr_reader :entries, :processed_source
115
+
116
+ def candidates
117
+ @candidates ||= entries.lazy.map { candidate_for(it) }.take_while(&:last).to_a
118
+ end
119
+
120
+ def candidate_for(entry)
121
+ [ entry, preserving_comments_in(entry) ]
122
+ end
123
+
124
+ def preserving_comments_in(entry)
125
+ comment_rescue_for(entry).preserving(entry.correction)
126
+ end
127
+
128
+ def comment_rescue_for(entry)
129
+ RuboCop::Callbacksystems::Autocorrection::CommentRescue.new \
130
+ RuboCop::Callbacksystems::Autocorrection::Rehearsal.new(entry.correction, processed_source),
131
+ processed_source
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,112 @@
1
+ # The edits of a rehearsed correction with the comments they swallowed written back in: trailing the rewritten line they
2
+ # were on, or standing on lines of their own where the code around them went away.
3
+ class RuboCop::Callbacksystems::Autocorrection::CommentRescue
4
+ def initialize(rehearsal, processed_source)
5
+ @rehearsal = rehearsal
6
+ @processed_source = processed_source
7
+ end
8
+
9
+ def preserving(original_correction)
10
+ replacements.none?(&:rescues?) ? original_correction : correction
11
+ end
12
+
13
+ def correction
14
+ if replacements.any?(&:rescues?) && replacements.none?(&:rescues_tooling?)
15
+ ->(corrector) { replacements.each { corrector.replace(it.range, it.rescued_text) } }
16
+ end
17
+ end
18
+
19
+ private
20
+ attr_reader :rehearsal, :processed_source
21
+
22
+ def replacements
23
+ @replacements ||= rehearsal.as_replacements.map do |range, text|
24
+ Replacement.new(range, text, source_comments)
25
+ end
26
+ end
27
+
28
+ def source_comments
29
+ @source_comments ||= RuboCop::Callbacksystems::Source::Comments.for(processed_source)
30
+ end
31
+
32
+ class Replacement
33
+ include RuboCop::Callbacksystems::Helpers
34
+
35
+ attr_reader :range
36
+
37
+ def initialize(range, text, source_comments)
38
+ @range = range
39
+ @text = text
40
+ @source_comments = source_comments
41
+ end
42
+
43
+ def rescues?
44
+ comments.any?
45
+ end
46
+
47
+ def rescues_tooling?
48
+ comments.any? { tooling_comment?(it) }
49
+ end
50
+
51
+ def rescued_text
52
+ if comments.empty? then text
53
+ elsif text.empty? then standing_lines
54
+ else trailing_text
55
+ end
56
+ end
57
+
58
+ private
59
+ attr_reader :text, :source_comments
60
+
61
+ def comments
62
+ @comments ||= source_comments.within(range).reject { text.include?(it.text) }
63
+ end
64
+
65
+ def standing_lines
66
+ comments.map.with_index { |comment, index| index.zero? ? opening_line_for(comment) : own_line_for(comment) }
67
+ .join + closing
68
+ end
69
+
70
+ def opening_line_for(comment)
71
+ before = range.begin.source_line[0...range.begin.column]
72
+ if before.strip.present? then " #{comment.text}"
73
+ elsif range.begin.column.zero? then own_line_for(comment).delete_prefix("\n")
74
+ else comment.text
75
+ end
76
+ end
77
+
78
+ def own_line_for(comment)
79
+ "\n#{line_indentation_of(comment)}#{comment.text}"
80
+ end
81
+
82
+ # A comment that trailed code takes the indentation of its line, not the column it sat at.
83
+ def line_indentation_of(comment)
84
+ comment.source_range.source_line[/\A[ \t]*/]
85
+ end
86
+
87
+ def closing
88
+ after = range.end.source_line[range.end.column..]
89
+ after.strip.empty? ? "" : "\n#{" " * range.end.column}"
90
+ end
91
+
92
+ def trailing_text
93
+ "#{opened(text.chomp)}#{trailing_below_first}#{standing}#{"\n" if text.end_with?("\n")}"
94
+ end
95
+
96
+ def opened(body)
97
+ body.sub(/$/) { on_first_line.map { " #{it.text}" }.join }
98
+ end
99
+
100
+ def on_first_line
101
+ comments.select { it.loc.line == range.line && !own_line_comment?(it) }
102
+ end
103
+
104
+ def trailing_below_first
105
+ comments.reject { it.loc.line == range.line || own_line_comment?(it) }.map { " #{it.text}" }.join
106
+ end
107
+
108
+ def standing
109
+ comments.select { own_line_comment?(it) }.map { own_line_for(it) }.join
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,65 @@
1
+ require "prism"
2
+
3
+ # A correction run on a corrector of its own, so what it would do to the source can be read before it is offered.
4
+ class RuboCop::Callbacksystems::Autocorrection::Rehearsal
5
+ delegate :empty?, :as_replacements, to: :corrector
6
+
7
+ def initialize(correction, processed_source)
8
+ @correction = correction
9
+ @processed_source = processed_source
10
+ end
11
+
12
+ def parses?
13
+ prism_parser? ? parsed_rewrite.success? : processed_rewrite.valid_syntax?
14
+ end
15
+
16
+ def keeps_comments?
17
+ comment_counts.all? { |text, count| rewritten_comment_counts.fetch(text, 0) >= count }
18
+ end
19
+
20
+ private
21
+ attr_reader :correction, :processed_source
22
+
23
+ def prism_parser?
24
+ processed_source.parser_engine == :parser_prism
25
+ end
26
+
27
+ def parsed_rewrite
28
+ @parsed_rewrite ||= Prism.parse \
29
+ rewritten,
30
+ filepath: processed_source.path,
31
+ version: processed_source.ruby_version.to_s
32
+ end
33
+
34
+ def rewritten
35
+ @rewritten ||= corrector.rewrite
36
+ end
37
+
38
+ def corrector
39
+ @corrector ||= RuboCop::Cop::Corrector.new(processed_source).tap { correction.call(it) }
40
+ end
41
+
42
+ def processed_rewrite
43
+ @processed_rewrite ||= RuboCop::ProcessedSource.new \
44
+ rewritten,
45
+ processed_source.ruby_version,
46
+ processed_source.path,
47
+ parser_engine: processed_source.parser_engine
48
+ end
49
+
50
+ def comment_counts
51
+ @comment_counts ||= processed_source.comments.map(&:text).tally
52
+ end
53
+
54
+ def rewritten_comment_counts
55
+ @rewritten_comment_counts ||= rewritten_comment_texts.tally
56
+ end
57
+
58
+ def rewritten_comment_texts
59
+ if prism_parser?
60
+ parsed_rewrite.comments.map { it.location.slice }
61
+ else
62
+ processed_rewrite.comments.map(&:text)
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,14 @@
1
+ # The single rewrite a pass may spend. A statement carrying a body travels with everything written inside it, so a
2
+ # second rewrite reaching into that same text would clobber it, and the pass that follows takes the next one.
3
+ class RuboCop::Callbacksystems::Autocorrection::RewritePermit
4
+ def initialize(granted: true)
5
+ @granted = granted
6
+ end
7
+
8
+ def claim
9
+ granted.tap { @granted = false }
10
+ end
11
+
12
+ private
13
+ attr_reader :granted
14
+ end
@@ -0,0 +1,48 @@
1
+ # A constant assignment whose expression uses one of Ruby's root class or module builders.
2
+ class RuboCop::Callbacksystems::ClassStructure::BuilderAssignment
3
+ include RuboCop::Callbacksystems::Helpers
4
+
5
+ CLASS_BUILDERS = { Data: :define, Struct: :new, Class: :new }
6
+ MODULE_BUILDERS = { Module: :new }
7
+
8
+ def initialize(node)
9
+ @node = node
10
+ end
11
+
12
+ def builds_class_with_body?
13
+ builds_class? && block_with_body?
14
+ end
15
+
16
+ def builds_class?
17
+ builds?(CLASS_BUILDERS)
18
+ end
19
+
20
+ def builds_module_with_body?
21
+ builds_module? && block_with_body?
22
+ end
23
+
24
+ def builds_module?
25
+ builds?(MODULE_BUILDERS)
26
+ end
27
+
28
+ private
29
+ attr_reader :node
30
+
31
+ def builds?(builders)
32
+ builder_named_in?(builders)
33
+ end
34
+
35
+ def builder_named_in?(builders)
36
+ builder_call&.receiver.then do |receiver|
37
+ core_constant?(receiver) && builders[receiver.short_name] == builder_call.method_name
38
+ end
39
+ end
40
+
41
+ def builder_call
42
+ @builder_call ||= call_of(node.expression) if node&.casgn_type?
43
+ end
44
+
45
+ def block_with_body?
46
+ any_block_type?(node.expression) && node.expression.body.present?
47
+ end
48
+ end
@@ -0,0 +1,50 @@
1
+ class RuboCop::Callbacksystems::ClassStructure::ClassBody
2
+ include RuboCop::Callbacksystems::Helpers
3
+
4
+ def initialize(body)
5
+ @body = body
6
+ end
7
+
8
+ def public_method_nodes
9
+ public_children.select(&:def_type?)
10
+ end
11
+
12
+ def public_children
13
+ each_child_with_visibility.filter_map { |child, level| child if level == :public }
14
+ end
15
+
16
+ def each_child_with_visibility
17
+ if block_given?
18
+ visibility.each_statement { |child, level| yield child, level }
19
+ else
20
+ visibility.each_statement
21
+ end
22
+ end
23
+
24
+ def private_method_nodes
25
+ private_children.select(&:def_type?)
26
+ end
27
+
28
+ def private_nested_classes
29
+ private_children.select(&:class_type?)
30
+ end
31
+
32
+ def in_private_section?(node)
33
+ visibility.level_at(node) == :private
34
+ end
35
+
36
+ def private_modifier
37
+ statements_in(body).find { visibility_modifier_of(it) == :private }
38
+ end
39
+
40
+ private
41
+ attr_reader :body
42
+
43
+ def visibility
44
+ @visibility ||= RuboCop::Callbacksystems::ClassStructure::Visibility.for(body)
45
+ end
46
+
47
+ def private_children
48
+ each_child_with_visibility.filter_map { |child, level| child if level == :private }
49
+ end
50
+ end
@@ -0,0 +1,31 @@
1
+ # The first place a sequence of names departs from the order expected of it, read as the index, the name the order
2
+ # expects there and the name found instead.
3
+ class RuboCop::Callbacksystems::ClassStructure::Divergence
4
+ def initialize(names, from:)
5
+ @names = names
6
+ @order = from
7
+ end
8
+
9
+ def found?
10
+ index.present?
11
+ end
12
+
13
+ def index
14
+ @index ||= names.each_index.find { names[it] != order[it] } if comparable?
15
+ end
16
+
17
+ def expected
18
+ order[index]
19
+ end
20
+
21
+ def actual
22
+ names[index]
23
+ end
24
+
25
+ private
26
+ attr_reader :names, :order
27
+
28
+ def comparable?
29
+ names.size == order.size && names.tally == order.tally
30
+ end
31
+ end
@@ -0,0 +1,82 @@
1
+ class RuboCop::Callbacksystems::ClassStructure::NodeVisibility
2
+ include RuboCop::Callbacksystems::Helpers
3
+
4
+ def initialize(node)
5
+ @node = node
6
+ end
7
+
8
+ def public?
9
+ level == :public
10
+ end
11
+
12
+ def level
13
+ level_of_wrapping_modifier || explicitly_assigned_level || default_level
14
+ end
15
+
16
+ def enclosing_body
17
+ visibility_owner&.body&.then { it if it.type?(:begin, :kwbegin) }
18
+ end
19
+
20
+ def enclosing_definition
21
+ node.each_ancestor(:class, :module, :sclass).first
22
+ end
23
+
24
+ def level_in(body)
25
+ RuboCop::Callbacksystems::ClassStructure::Visibility.for(body).level_at(node)
26
+ end
27
+
28
+ def private?
29
+ level == :private
30
+ end
31
+
32
+ def protected?
33
+ level == :protected
34
+ end
35
+
36
+ def private_non_predicate?
37
+ level != :public && !node.predicate_method?
38
+ end
39
+
40
+ private
41
+ attr_reader :node
42
+
43
+ def level_of_wrapping_modifier
44
+ visibility_applied_to(node.parent, node)
45
+ end
46
+
47
+ def explicitly_assigned_level
48
+ assignment_bodies.filter_map do |body|
49
+ RuboCop::Callbacksystems::ClassStructure::Visibility.for(body).assignment_after \
50
+ node, singleton: node.defs_type? || body.equal?(singleton_owner_body)
51
+ end.max_by(&:position)&.level
52
+ end
53
+
54
+ def assignment_bodies
55
+ [ enclosing_body, singleton_owner_body ].compact.uniq(&:object_id)
56
+ end
57
+
58
+ def singleton_owner_body
59
+ singleton_class&.each_ancestor&.find { visibility_owner?(it) }&.body
60
+ end
61
+
62
+ def singleton_class
63
+ @singleton_class ||= visibility_owner if visibility_owner&.sclass_type? &&
64
+ visibility_owner.children.first.self_type?
65
+ end
66
+
67
+ def visibility_owner
68
+ @visibility_owner ||= node.each_ancestor.find { visibility_owner?(it) }
69
+ end
70
+
71
+ def visibility_owner?(candidate)
72
+ candidate.type?(:class, :module, :sclass) || any_block_type?(candidate)
73
+ end
74
+
75
+ def default_level
76
+ if !node.defs_type? && enclosing_body
77
+ level_in(enclosing_body)
78
+ else
79
+ :public
80
+ end
81
+ end
82
+ end