leftovers 0.8.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (196) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +34 -0
  3. data/README.md +7 -7
  4. data/docs/Configuration.md +169 -38
  5. data/docs/Custom-Precompilers.md +6 -0
  6. data/leftovers.gemspec +2 -1
  7. data/lib/config/actioncable.yml +36 -0
  8. data/lib/config/actionmailbox.yml +31 -0
  9. data/lib/config/actionmailer.yml +91 -12
  10. data/lib/config/actionpack.yml +139 -35
  11. data/lib/config/actiontext.yml +56 -0
  12. data/lib/config/actionview.yml +194 -44
  13. data/lib/config/activejob.yml +16 -10
  14. data/lib/config/activemodel.yml +195 -27
  15. data/lib/config/activerecord.yml +436 -88
  16. data/lib/config/activestorage.yml +26 -0
  17. data/lib/config/activesupport.yml +177 -24
  18. data/lib/config/leftovers.yml +48 -0
  19. data/lib/config/rails.yml +7 -3
  20. data/lib/config/railties.yml +7 -0
  21. data/lib/config/ruby.yml +438 -83
  22. data/lib/config/test-unit.yml +8 -0
  23. data/lib/leftovers/ast/array_node.rb +12 -0
  24. data/lib/leftovers/ast/block_node.rb +12 -0
  25. data/lib/leftovers/ast/builder.rb +24 -5
  26. data/lib/leftovers/ast/casgn_node.rb +20 -0
  27. data/lib/leftovers/ast/const_node.rb +15 -0
  28. data/lib/leftovers/ast/def_node.rb +15 -0
  29. data/lib/leftovers/ast/defs_node.rb +15 -0
  30. data/lib/leftovers/ast/false_node.rb +24 -0
  31. data/lib/leftovers/ast/has_arguments.rb +31 -0
  32. data/lib/leftovers/ast/hash_node.rb +17 -0
  33. data/lib/leftovers/ast/module_node.rb +16 -0
  34. data/lib/leftovers/ast/nil_node.rb +23 -0
  35. data/lib/leftovers/ast/node.rb +33 -90
  36. data/lib/leftovers/ast/numeric_node.rb +22 -0
  37. data/lib/leftovers/ast/send_node.rb +25 -0
  38. data/lib/leftovers/ast/str_node.rb +24 -0
  39. data/lib/leftovers/ast/sym_node.rb +25 -0
  40. data/lib/leftovers/ast/true_node.rb +24 -0
  41. data/lib/leftovers/ast/var_node.rb +14 -0
  42. data/lib/leftovers/ast/vasgn_node.rb +20 -0
  43. data/lib/leftovers/ast.rb +18 -0
  44. data/lib/leftovers/cli.rb +7 -1
  45. data/lib/leftovers/comparable_instance.rb +18 -0
  46. data/lib/leftovers/config_loader/argument_position_schema.rb +3 -1
  47. data/lib/leftovers/config_loader/array_schema.rb +53 -0
  48. data/lib/leftovers/config_loader/document_schema.rb +3 -2
  49. data/lib/leftovers/config_loader/dynamic_schema.rb +1 -0
  50. data/lib/leftovers/config_loader/has_receiver_schema.rb +15 -0
  51. data/lib/leftovers/config_loader/has_value_schema.rb +5 -1
  52. data/lib/leftovers/config_loader/keyword_argument_schema.rb +13 -0
  53. data/lib/leftovers/config_loader/regexp_schema.rb +27 -0
  54. data/lib/leftovers/config_loader/rule_pattern_schema.rb +3 -1
  55. data/lib/leftovers/config_loader/scalar_value_schema.rb +8 -0
  56. data/lib/leftovers/config_loader/schema.rb +10 -0
  57. data/lib/leftovers/config_loader/string_enum_schema.rb +1 -1
  58. data/lib/leftovers/config_loader/string_pattern_schema.rb +1 -1
  59. data/lib/leftovers/config_loader/transform_schema.rb +12 -6
  60. data/lib/leftovers/config_loader/value_matcher_condition_schema.rb +13 -0
  61. data/lib/leftovers/config_loader/value_matcher_schema.rb +4 -1
  62. data/lib/leftovers/config_loader/value_or_array_schema.rb +2 -34
  63. data/lib/leftovers/config_loader/value_processor_schema.rb +2 -2
  64. data/lib/leftovers/config_loader.rb +12 -4
  65. data/lib/leftovers/definition_collection.rb +37 -0
  66. data/lib/leftovers/definition_node.rb +8 -14
  67. data/lib/leftovers/definition_node_set.rb +10 -2
  68. data/lib/leftovers/file.rb +1 -1
  69. data/lib/leftovers/file_collector/comments_processor.rb +1 -1
  70. data/lib/leftovers/file_collector/node_processor.rb +7 -7
  71. data/lib/leftovers/file_collector.rb +26 -32
  72. data/lib/leftovers/file_list.rb +3 -2
  73. data/lib/leftovers/matcher_builders/and.rb +26 -9
  74. data/lib/leftovers/matcher_builders/node.rb +32 -20
  75. data/lib/leftovers/matcher_builders/node_has_keyword_argument.rb +3 -1
  76. data/lib/leftovers/matcher_builders/node_has_receiver.rb +12 -3
  77. data/lib/leftovers/matcher_builders/node_pair_key.rb +16 -0
  78. data/lib/leftovers/matcher_builders/node_type.rb +9 -9
  79. data/lib/leftovers/matcher_builders/node_value.rb +25 -9
  80. data/lib/leftovers/matcher_builders/or.rb +22 -7
  81. data/lib/leftovers/matcher_builders/path.rb +3 -1
  82. data/lib/leftovers/matcher_builders.rb +1 -1
  83. data/lib/leftovers/matchers/all.rb +4 -0
  84. data/lib/leftovers/matchers/and.rb +4 -0
  85. data/lib/leftovers/matchers/any.rb +2 -0
  86. data/lib/leftovers/matchers/node_has_any_keyword_argument.rb +7 -4
  87. data/lib/leftovers/matchers/node_has_any_positional_argument_with_value.rb +5 -4
  88. data/lib/leftovers/matchers/node_has_any_receiver.rb +13 -0
  89. data/lib/leftovers/matchers/node_has_positional_argument.rb +5 -1
  90. data/lib/leftovers/matchers/node_has_positional_argument_with_value.rb +6 -1
  91. data/lib/leftovers/matchers/node_has_receiver.rb +4 -0
  92. data/lib/leftovers/matchers/node_is_proc.rb +13 -0
  93. data/lib/leftovers/matchers/node_name.rb +9 -3
  94. data/lib/leftovers/matchers/node_pair_key.rb +23 -0
  95. data/lib/leftovers/matchers/node_pair_value.rb +7 -3
  96. data/lib/leftovers/matchers/node_path.rb +7 -3
  97. data/lib/leftovers/matchers/node_privacy.rb +7 -3
  98. data/lib/leftovers/matchers/node_scalar_value.rb +6 -1
  99. data/lib/leftovers/matchers/node_type.rb +7 -3
  100. data/lib/leftovers/matchers/not.rb +2 -0
  101. data/lib/leftovers/matchers/or.rb +2 -0
  102. data/lib/leftovers/matchers/path.rb +21 -0
  103. data/lib/leftovers/matchers.rb +4 -1
  104. data/lib/leftovers/merged_config.rb +26 -25
  105. data/lib/leftovers/parser.rb +7 -4
  106. data/lib/leftovers/precompilers.rb +5 -5
  107. data/lib/leftovers/processor_builders/action.rb +55 -37
  108. data/lib/leftovers/processor_builders/add_prefix.rb +18 -10
  109. data/lib/leftovers/processor_builders/add_suffix.rb +18 -10
  110. data/lib/leftovers/processor_builders/argument.rb +28 -11
  111. data/lib/leftovers/processor_builders/dynamic.rb +37 -31
  112. data/lib/leftovers/processor_builders/each.rb +82 -10
  113. data/lib/leftovers/processor_builders/itself.rb +2 -2
  114. data/lib/leftovers/processor_builders/keyword.rb +7 -6
  115. data/lib/leftovers/processor_builders/keyword_argument.rb +4 -2
  116. data/lib/leftovers/processor_builders/receiver.rb +13 -0
  117. data/lib/leftovers/processor_builders/transform.rb +55 -44
  118. data/lib/leftovers/processor_builders/transform_chain.rb +1 -1
  119. data/lib/leftovers/processor_builders/transform_set.rb +9 -29
  120. data/lib/leftovers/processor_builders/value.rb +4 -4
  121. data/lib/leftovers/processor_builders.rb +1 -3
  122. data/lib/leftovers/processors/add_call.rb +14 -0
  123. data/lib/leftovers/processors/add_definition_node.rb +16 -0
  124. data/lib/leftovers/processors/add_dynamic_prefix.rb +29 -0
  125. data/lib/leftovers/processors/add_dynamic_suffix.rb +29 -0
  126. data/lib/leftovers/{value_processors → processors}/add_prefix.rb +7 -3
  127. data/lib/leftovers/{value_processors → processors}/add_suffix.rb +7 -3
  128. data/lib/leftovers/processors/append_sym.rb +13 -0
  129. data/lib/leftovers/{value_processors → processors}/camelize.rb +7 -3
  130. data/lib/leftovers/{value_processors → processors}/capitalize.rb +7 -3
  131. data/lib/leftovers/{value_processors → processors}/deconstantize.rb +7 -3
  132. data/lib/leftovers/{value_processors → processors}/delete_after.rb +9 -5
  133. data/lib/leftovers/processors/delete_after_last.rb +26 -0
  134. data/lib/leftovers/processors/delete_before.rb +27 -0
  135. data/lib/leftovers/processors/delete_before_last.rb +27 -0
  136. data/lib/leftovers/{value_processors → processors}/delete_prefix.rb +7 -3
  137. data/lib/leftovers/{value_processors → processors}/delete_suffix.rb +7 -3
  138. data/lib/leftovers/{value_processors → processors}/demodulize.rb +7 -3
  139. data/lib/leftovers/{value_processors → processors}/downcase.rb +7 -3
  140. data/lib/leftovers/processors/each.rb +25 -0
  141. data/lib/leftovers/processors/each_for_definition_set.rb +33 -0
  142. data/lib/leftovers/processors/each_keyword.rb +29 -0
  143. data/lib/leftovers/processors/each_keyword_argument.rb +29 -0
  144. data/lib/leftovers/processors/each_positional_argument.rb +27 -0
  145. data/lib/leftovers/processors/each_positional_argument_from.rb +30 -0
  146. data/lib/leftovers/processors/eval.rb +16 -0
  147. data/lib/leftovers/processors/itself.rb +21 -0
  148. data/lib/leftovers/processors/keyword_argument.rb +30 -0
  149. data/lib/leftovers/processors/match_current_node.rb +26 -0
  150. data/lib/leftovers/processors/match_matched_node.rb +26 -0
  151. data/lib/leftovers/{value_processors → processors}/parameterize.rb +7 -3
  152. data/lib/leftovers/{value_processors → processors}/placeholder.rb +5 -4
  153. data/lib/leftovers/{value_processors → processors}/pluralize.rb +7 -3
  154. data/lib/leftovers/{value_processors → processors}/positional_argument.rb +8 -6
  155. data/lib/leftovers/processors/receiver.rb +24 -0
  156. data/lib/leftovers/{value_processors → processors}/replace_value.rb +7 -3
  157. data/lib/leftovers/processors/set_default_privacy.rb +21 -0
  158. data/lib/leftovers/processors/set_privacy.rb +23 -0
  159. data/lib/leftovers/{value_processors → processors}/singularize.rb +7 -3
  160. data/lib/leftovers/{value_processors → processors}/split.rb +8 -4
  161. data/lib/leftovers/{value_processors → processors}/swapcase.rb +7 -3
  162. data/lib/leftovers/{value_processors → processors}/titleize.rb +7 -3
  163. data/lib/leftovers/{value_processors → processors}/underscore.rb +7 -3
  164. data/lib/leftovers/{value_processors → processors}/upcase.rb +7 -3
  165. data/lib/leftovers/processors.rb +49 -0
  166. data/lib/leftovers/reporter.rb +2 -2
  167. data/lib/leftovers/version.rb +1 -1
  168. data/lib/leftovers.rb +3 -12
  169. metadata +99 -52
  170. data/lib/leftovers/dynamic_processors/call.rb +0 -22
  171. data/lib/leftovers/dynamic_processors/call_definition.rb +0 -34
  172. data/lib/leftovers/dynamic_processors/definition.rb +0 -27
  173. data/lib/leftovers/dynamic_processors/each.rb +0 -19
  174. data/lib/leftovers/dynamic_processors/null.rb +0 -9
  175. data/lib/leftovers/dynamic_processors/set_default_privacy.rb +0 -18
  176. data/lib/leftovers/dynamic_processors/set_privacy.rb +0 -23
  177. data/lib/leftovers/dynamic_processors.rb +0 -13
  178. data/lib/leftovers/matcher_builders/node_pair_name.rb +0 -18
  179. data/lib/leftovers/matchers/predicate.rb +0 -19
  180. data/lib/leftovers/processor_builders/each_action.rb +0 -51
  181. data/lib/leftovers/processor_builders/each_dynamic.rb +0 -50
  182. data/lib/leftovers/processor_builders/each_for_definition_set.rb +0 -40
  183. data/lib/leftovers/value_processors/add_dynamic_prefix.rb +0 -24
  184. data/lib/leftovers/value_processors/add_dynamic_suffix.rb +0 -24
  185. data/lib/leftovers/value_processors/delete_before.rb +0 -22
  186. data/lib/leftovers/value_processors/each.rb +0 -21
  187. data/lib/leftovers/value_processors/each_for_definition_set.rb +0 -23
  188. data/lib/leftovers/value_processors/each_keyword.rb +0 -27
  189. data/lib/leftovers/value_processors/each_keyword_argument.rb +0 -27
  190. data/lib/leftovers/value_processors/each_positional_argument.rb +0 -25
  191. data/lib/leftovers/value_processors/itself.rb +0 -17
  192. data/lib/leftovers/value_processors/keyword.rb +0 -28
  193. data/lib/leftovers/value_processors/keyword_argument.rb +0 -28
  194. data/lib/leftovers/value_processors/return_definition_node.rb +0 -14
  195. data/lib/leftovers/value_processors/return_sym.rb +0 -14
  196. data/lib/leftovers/value_processors.rb +0 -40
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c2e0c74dad85b7b571608a7207f006fe14d5748e1a155470185112b80a7b80a3
4
- data.tar.gz: 68f3d83b310f640e127b961e6ac2ece795a7b9e2a6de961a1b42498916e092d7
3
+ metadata.gz: 16d46e25de2c0e4f243f396b910e3eb61e6342dd626fcceb9f30bd3734196d7b
4
+ data.tar.gz: e8c6c55c70e25167126fa2fa5ac3037f41a37b9ae8415f10b86cfea183436be1
5
5
  SHA512:
6
- metadata.gz: c57c64254cc2092e38b8decfd7bde0a021d66a7c3f563dc3e1f5a68b91c4bfc7b16a8490e5437b3da942071d41d2c35c247e1e51739064e14fdfcc6653b192b3
7
- data.tar.gz: b129119436c793987c89b032d5936b10ca935c7fc5398e7a2843665bbfec28ccaacd0a0090c8cd37c5172b6892f4291455aef40df6bae67727d25ac47fd871a3
6
+ metadata.gz: 609975369757068764cc179848f973aa6579dcf422a36ad54a7e7697cb257b1ec1043c3da8b106741869d1a0f113e4aa95bf824c7dca1c9766b05db90cddb7a8
7
+ data.tar.gz: c74f1643e44ad2f87490f8f2745c35286f746881bcac839c43bc0400863c0733a5246c5cf4d4b5be88d1501512aa6fb35debc637404262ee0902766e28a87b86
data/CHANGELOG.md CHANGED
@@ -1,3 +1,37 @@
1
+ # v0.11.0
2
+ - Fixed an issue with active_record's `before_save` with multiple callbacks #18, #17 - thanks @palexvs for raising the issue and creating a pr
3
+ - Due to this pr, i reviewed everything else that i think calls `ActiveSupport::Callbacks.set_callback`, and ensured they all:
4
+ - can have multiple args if relevant
5
+ - accept single values and array values for the if/unless args
6
+ - don't eval strings, that's not been a rails feature for a while
7
+ - Fix active_model & active_record validation methods to more comprehensively handle all the keys that could be given symbols of method names, instead of only the documented ones
8
+
9
+ # v0.10.0
10
+ - Fixed an issue with t.belongs_to (within the migration generated by rails active_storage:install - thanks @veganstraightedge)
11
+ - this was two issues:
12
+ 1. it was raising an error because the DefinitionNode didn't act enough like an AST::Node, now it does
13
+ 2. this should never have been defining anything anyway as the activerecord method was being assumed to be used, now if there's an explicit receiver for belongs_to/has_many etc, don't consider them the active record association methods.
14
+
15
+ - now `has_receiver: true` and `has_receiver: false/nil` act differently, they refer to the presence or absence of any receiver, instead of the receiver being literally true or false or nil.
16
+ - to have the previous behaviour, use the new `has_receiver: { literal: true }` or `literal: false` or `literal: null`
17
+
18
+ # v0.9.0
19
+ - Automatically test the config examples in the documentation, and fix the errors
20
+ - simplify the `type: Proc` matcher
21
+ - Update FastIgnore dependency, make fewer filesystem calls
22
+ - Comprehensively describe all of ruby core and rails
23
+ This required/revealed a number of additions to the config
24
+ - Improve the performance of large config files by squash the config matching more
25
+ - Add `names:` and `has_arguments:` to `has_value:`.
26
+ - Fix error when positional `has_arguments:`/`has_value: at:` checks a node without arguments
27
+ - Add `eval` as a processing type, alongside `calls:` and `defines:`, this will process allow processing literal calls to instance_eval etc.
28
+ - Allow calling or defining based on the `receiver:`
29
+ - `all: []` & `any: []` arguments to dynamic/keep/test_only
30
+ - add `arguments: 1+` or `has_arguments: { at: 1+, has_value: true }` to match arguments from that position onward
31
+ - allow `has_arguments:` and `has_receiver:` (and `unless:` and `all:` and `any:` of those) to go within `calls:`,`defines:`,`set_privacy:`,`add_prefix:`,`add_suffix:` for cases like the `delegate prefix: true` vs `delegate prefix: :value` without having to redefine everything.
32
+ - allow `has_arguments.at` and `arguments:` to have a `type:` to distinguish between e.g. symbol keys and string keys.
33
+ - Add a way to test custom precompilers with --view-compiled [PATH_PATTERNS...]
34
+
1
35
  # v0.8.0
2
36
  - Allow custom precompilers
3
37
  ```yml
data/README.md CHANGED
@@ -15,7 +15,7 @@ Code that never gets executed is code that you shouldn't need to maintain
15
15
 
16
16
  Leftovers will use static analysis to find these bits of code for you.
17
17
 
18
- It's aware of how some gems call methods for you, including (still somewhat incomplete) support for rails.
18
+ It's aware of how some gems call methods for you, including support for much of rails.
19
19
 
20
20
  ## Features
21
21
 
@@ -141,21 +141,21 @@ This would consider `puts` and `warn` to both have been called
141
141
  To mark a dynamic call for literal hash and array values without enumerating everything in the comment again, use `leftovers:dynamic:` on the same line as the beginning of the array or hash
142
142
 
143
143
  ```ruby
144
- [ # leftovers:dynamic:call_login
144
+ [ # leftovers:dynamic:call_attributes
145
145
  :user,
146
146
  :admin
147
- ].each { |method| send("#{method}_login") }
147
+ ].map { |method| send("#{method}_attributes") }
148
148
  ```
149
149
 
150
150
  with the following configuration matching the `name: value` to the `leftovers:dynamic:process_name`
151
151
 
152
152
  ```yaml
153
153
  dynamic:
154
- name: call_login
154
+ name: call_attributes
155
155
  arguments: '*'
156
- add_suffix: '_login'
156
+ add_suffix: '_attributes'
157
157
  ```
158
- This would consider `user_login` and `admin_login` to both have been called.
158
+ This would consider `user_attributes` and `admin_attributes` to both have been called.
159
159
 
160
160
  ## Configuration file
161
161
 
@@ -201,7 +201,7 @@ To install this gem onto your local machine, run `bundle exec rake install`.
201
201
 
202
202
  Bug reports and pull requests are welcome on GitHub at https://github.com/robotdana/leftovers.
203
203
 
204
- I especially encourage issues and improvements to the default config, whether expanding the existing config/*.yml (rails.yml is particularly incomplete) or adding new gems.
204
+ I especially encourage issues and improvements to the default config, whether expanding the existing config/*.yml or adding new gems.
205
205
  The file should be named `[rubygems name].yml` and its structure is identical to the [project config](#configuration)
206
206
 
207
207
  ## License
@@ -99,10 +99,10 @@ Define any precompilers and the paths they affect.
99
99
 
100
100
  `paths:` are defined using the [.gitignore pattern format](https://git-scm.com/docs/gitignore#_pattern_format)
101
101
 
102
- `format:` must be one of the predefined precompilers (erb, haml, [json](#format-json), slim, [yaml](#format-yaml)), or `custom:` with the name of a [custom precompiler]('../Custom-Precompilers.md) module.
102
+ `format:` must be one of the predefined precompilers (erb, haml, [json](#format-json), slim, [yaml](#format-yaml)), or `custom:` with the name of a [custom precompiler](https://github.com/robotdana/leftovers/blob/main/docs/Custom-Precompilers.md) module.
103
103
  (use [`require:`](#requires) to have leftovers load its file)
104
104
 
105
- See [Custom precompilers]('../Custom-Precompilers.md) for more details on the custom precompiler class
105
+ See [Custom precompilers](https://github.com/robotdana/leftovers/blob/main/docs/Custom-Precompilers.md) for more details on the custom precompiler class
106
106
 
107
107
  Arrays are not necessary for single values.
108
108
 
@@ -113,7 +113,7 @@ and renders the structure of the yaml document as arguments for the [`document:t
113
113
 
114
114
  so you could, e.g. read the class name out of a yaml document like:
115
115
 
116
- ```yml
116
+ ```
117
117
  class_name: MyClass
118
118
  ```
119
119
 
@@ -187,7 +187,9 @@ Each entry can be a string (an exact match for a method, constant, or variable n
187
187
  - [`has_receiver:`](#has_receiver)
188
188
  - [`type:`](#type)
189
189
  - [`privacy:`](#privacy)
190
- - [`unless`](#unless)
190
+ - [`unless:`](#unless)
191
+ - [`all:`](#any-all)
192
+ - [`any:`](#any-all)
191
193
 
192
194
  Arrays are not necessary for single values
193
195
 
@@ -198,7 +200,6 @@ keep:
198
200
  - ssl_configured?
199
201
  - has_suffix: Helper
200
202
  path: /app/helpers
201
- ...
202
203
  ```
203
204
 
204
205
  Alternatively, you can mark method/constants/variables in-place using [magic comments](https://github.com/robotdana/leftovers/tree/main/README.md#magic-comments).
@@ -215,7 +216,12 @@ Each entry can be a string (an exact match for a method, constant, or variable n
215
216
  - [`matches:`](#matches)
216
217
  - [`paths:`](#paths)
217
218
  - [`has_arguments:`](#has_arguments)
219
+ - [`has_receiver:`](#has_receiver)
220
+ - [`type:`](#type)
221
+ - [`privacy:`](#privacy)
218
222
  - [`unless`](#unless)
223
+ - [`all:`](#any-all)
224
+ - [`any:`](#any-all)
219
225
 
220
226
  Arrays are not necessary for single values
221
227
 
@@ -226,7 +232,6 @@ test_only:
226
232
  - ssl_configured?
227
233
  - has_suffix: Helper
228
234
  path: /app/helpers
229
- ...
230
235
  ```
231
236
 
232
237
  Alternatively, you can mark method/constants/variables in-place using [magic comments](https://github.com/robotdana/leftovers/tree/main/README.md#magic-comments).
@@ -241,17 +246,22 @@ Each entry must have at least one of the following properties to restrict which
241
246
  - [`has_prefix:`](#has_prefix)
242
247
  - [`has_suffix:`](#has_suffix)
243
248
  - [`matches:`](#matches)
249
+ - [`document: true`](#document-true)
244
250
  - [`paths:`](#paths)
245
251
  - [`has_arguments:`](#has_arguments)
246
252
  - [`has_receiver:`](#has_receiver)
253
+ - [`type:`](#type)
254
+ - [`privacy:`](#privacy)
247
255
  - [`unless:`](#unless)
248
- - [`document: true`](#document-true)
256
+ - [`all:`](#any-all)
257
+ - [`any:`](#any-all)
249
258
 
250
259
  And must have at least one of
251
260
  - ['calls:`](#calls-defines)
252
261
  - [`defines:`](#calls-defines)
253
262
  - [`set_privacy:](#set-privacy)
254
263
  - [`set_default_privacy:`](#set-default-privacy)
264
+ - [`eval:`](#eval)
255
265
 
256
266
  Arrays are not necessary for single values.
257
267
 
@@ -266,7 +276,6 @@ dynamic:
266
276
  calls:
267
277
  arguments: '*'
268
278
  add_prefix: '@'
269
- ...
270
279
  ```
271
280
 
272
281
  ## `names:`
@@ -289,7 +298,6 @@ keep:
289
298
  - names:
290
299
  has_suffix: Helper
291
300
  path: /app/helpers
292
- ...
293
301
  ```
294
302
 
295
303
  ## `has_prefix:`, `has_suffix:`
@@ -351,7 +359,7 @@ Instructs to consider the whole document. this is useful when parsing [YAML](#ya
351
359
  e.g.
352
360
 
353
361
  ```yml
354
- includes: /config/roles.yml
362
+ include_paths: /config/roles.yml
355
363
  dynamic:
356
364
  - document: true
357
365
  path: /config/roles.yml
@@ -362,7 +370,7 @@ dynamic:
362
370
  ```
363
371
 
364
372
  will parse "config/roles.yml"
365
- ```yml
373
+ ```
366
374
  - build_house
367
375
  - drive_car
368
376
  ```
@@ -393,8 +401,10 @@ also there may be any or all of these properties:
393
401
  - [`add_suffix:`](#add_prefix-add_suffix)
394
402
  - [`delete_prefix:`](#delete_prefix-delete_suffix)
395
403
  - [`delete_suffix:`](#delete_prefix-delete_suffix)
396
- - [`delete_before:`](#delete_before-delete_after)
397
- - [`delete_after:`](#delete_before-delete_after)
404
+ - [`delete_before:`](#delete_before-delete_after--delete_before_last-delete_after_last)
405
+ - [`delete_after:`](#delete_before-delete_after--delete_before_last-delete_after_last)
406
+ - [`delete_before_last:`](#delete_before-delete_after-delete_before_last-delete_after_last)
407
+ - [`delete_after_last:`](#delete_before-delete_after-delete_before_last-delete_after_last)
398
408
  - [`split:`](#split)
399
409
  - [`downcase:`](#downcase-upcase-capitalize-swapcase)
400
410
  - [`upcase:`](#downcase-upcase-capitalize-swapcase)
@@ -417,13 +427,13 @@ dynamic:
417
427
  - send
418
428
  calls:
419
429
  arguments:
420
- - 1
430
+ - 0
421
431
  ```
422
432
  is equivalent to:
423
433
  ```yml
424
434
  dynamic:
425
435
  name: send
426
- calls: 1
436
+ calls: 0
427
437
  ```
428
438
 
429
439
  ## `set_privacy:`
@@ -463,6 +473,27 @@ dynamic:
463
473
 
464
474
  these methods could then be filtered using the [`privacy:`](#privacy) method in another [`dynamic:`](#dynamic) or [`keep:`](#keep) rule.
465
475
 
476
+ ## `eval:`
477
+
478
+ Eval has the same requirements as [`calls:` & `defines:`](#calls-defines).
479
+
480
+ it parses a string or transformed string as ruby, using the same rules as the containing file
481
+ For example:
482
+
483
+ ```yml
484
+ dynamic:
485
+ name: eval_later
486
+ eval:
487
+ argument: my_ruby_string
488
+ ```
489
+
490
+ with the ruby:
491
+ ```ruby
492
+ eval_later(delay: 1000, my_ruby_string: "MyClass.puts 'shenanigans'")
493
+ ```
494
+
495
+ would consider `MyClass`, and `puts` to have been called.
496
+
466
497
  ## `arguments:`
467
498
  _alias `argument:`_
468
499
 
@@ -473,7 +504,7 @@ and when used in:
473
504
 
474
505
  It can have any of these properties:
475
506
  - [`at:`](#at)
476
- - [`has_value:`](#has_value_has_receiver)
507
+ - [`has_value:`](#has_value)
477
508
 
478
509
  Arrays are not necessary for single values and if the rule contains only `at:` it can be omitted, and the values moved up a level.
479
510
 
@@ -491,7 +522,7 @@ The method call/constant variable/assignment will be considered matching if it h
491
522
 
492
523
  It can have any of these properties:
493
524
  - [`at:`](#at)
494
- - [`has_value:`](#has_value_has_receiver)
525
+ - [`has_value:`](#has_value)
495
526
 
496
527
  Arrays are not necessary for single values and if the rule contains only `at:` it can be omitted, and the values moved up a level
497
528
 
@@ -503,11 +534,11 @@ When the keyword argument **keywords** are the thing being called.
503
534
  ```yml
504
535
  dynamic:
505
536
  - name: validates
506
- calls:
507
- - arguments: '*'
508
- - keywords: '**'
509
- camelize: true
510
- add_suffix: Validator
537
+ calls:
538
+ - arguments: '*'
539
+ - keywords: '**'
540
+ camelize: true
541
+ add_suffix: Validator
511
542
  ```
512
543
  ```ruby
513
544
  validates :first_name, :surname, presence: true
@@ -526,7 +557,9 @@ This can be used in:
526
557
  Each entry can be any of:
527
558
  - `'*'`: matches all positional arguments/array positions
528
559
  - `'**'`: matches all keyword arguments/hash positions
529
- - any positive Integer: matches the 1-indexed argument position/array position
560
+ - `1+`, `2+`, etc: matches all positional arguments/array elements at or greater than the 0-indexed position
561
+ - any Integer: matches the 0-indexed argument position/array position
562
+ - negative values match positions counting from the end, e.g. `-1` is the last item
530
563
  - any other String: matches the keyword argument or hash value, where the keyword/hash key string or symbol
531
564
  - or have at least one of the following properties to match the keyword/hash key string or symbol:
532
565
  - [`has_prefix:`](#has_prefix)
@@ -535,9 +568,44 @@ Each entry can be any of:
535
568
 
536
569
  Arrays are not necessary for single values
537
570
 
538
- ## `has_value:`, `has_receiver:`
571
+ ## `any:`, `all:`
572
+
573
+ filter by `any:` or `all:` of the argument filters
574
+
575
+ by default array values match any of the values,
576
+ and hash values are match all of the values
577
+
578
+ ```yml
579
+ dynamic:
580
+ name: my_method
581
+ has_receiver: MyReceiver
582
+ has_arguments:
583
+ - part_a
584
+ - part_b
585
+ calls: 0
586
+ ```
587
+
588
+ will match the first argument of anything named my_method, with the receiver MyReceiver that has the keyword argument part_a and/or part_b.
589
+
590
+ to avoid this default use `all:` and/or `any:`
591
+
592
+ ```yml
593
+ dynamic:
594
+ any:
595
+ - name: my_method
596
+ - has_receiver: MyReceiver
597
+ all:
598
+ - has_argument: part_a
599
+ - has_argument: part_b
600
+ calls: 0
601
+ ```
602
+
603
+ will match the first argument of anything named my_method or with the receiver MyReceiver, that have both the keyword arguments part_a and part_b
539
604
 
540
- filter [`arguments:`](#arguments), [`has_arguments:`](#has_arguments), and [`keywords:`](#keywords), by the argument/assigned/receiver value
605
+
606
+ ## `has_value:`
607
+
608
+ filter [`arguments:`](#arguments), [`has_arguments:`](#has_arguments), and [`keywords:`](#keywords), by the argument/assigned value
541
609
 
542
610
  Each entry can be one of
543
611
  - `true`, `false`, `nil`, or an Integer. matches the literal value
@@ -548,11 +616,33 @@ Each entry can be one of
548
616
  - [`matches:`](#matches)
549
617
  - or have at least one of the following properties to match within an array or hash:
550
618
  - [`at`](#at)
551
- - [`has_value`](#has_value_has_receiver)
619
+ - [`has_value`](#has_value)
552
620
  - or have the following property to match the value type
553
621
  - [`type`](#type)
554
622
  - or have the following property to match the receiver
555
- - [`has_receiver`](#has_value_has_receiver)
623
+ - [`has_receiver`](#has_receiver)
624
+
625
+ ## `has_receiver:`
626
+
627
+ filter [`dynamic:`](#dynamic), and [`keep:`](#keep), by the receiver presence or value
628
+
629
+ Each entry can be one of
630
+ - `true`, `false`, matches the presence of any receiver or not
631
+ - an Integer. matches the literal value
632
+ - a String. matches the literal string or symbol value
633
+ - or have at least one of the following properties to match the name:
634
+ - [`has_prefix:`](#has_prefix)
635
+ - [`has_suffix:`](#has_suffix)
636
+ - [`matches:`](#matches)
637
+ - or have at least one of the following properties to match the literal value or match within an array or hash:
638
+ - [`at`](#at)
639
+ - [`has_value`](#has_value)
640
+ - or have the following property to match the value type
641
+ - [`type`](#type)
642
+ - or have the following property to match the receiver of the receiver
643
+ - [`has_receiver`](#has_receiver)
644
+ - or have the following property to match a literal true, false, or nil value:
645
+ - `literal: true`, or `literal: false`, or `literal: nil`
556
646
 
557
647
  ## `privacy:`
558
648
 
@@ -606,7 +696,7 @@ e.g.
606
696
  dynamic:
607
697
  - names: my_method
608
698
  calls:
609
- argument: 2
699
+ argument: 1
610
700
  nested:
611
701
  argument: '*'
612
702
  nested:
@@ -643,6 +733,7 @@ The original method/constant/variable name will continue to be called/defined as
643
733
  This can be used in [`calls:`](#calls-defines) and [`defines:`](#calls-defines)
644
734
 
645
735
  ```yml
736
+ dynamic:
646
737
  - name:
647
738
  has_prefix: be_
648
739
  calls:
@@ -661,6 +752,7 @@ Will supply a literal string value method/constant/variable name itself as the t
661
752
  This can be used in [`calls:`](#calls-defines) and [`defines:`](#calls-defines).
662
753
 
663
754
  ```yml
755
+ dynamic:
664
756
  - name: perform_async
665
757
  calls:
666
758
  value: perform
@@ -683,8 +775,10 @@ Each entry can have a string that is an argumentless transform (e.g. capitalize)
683
775
  - [`add_suffix:`](#add_prefix-add_suffix)
684
776
  - [`delete_prefix:`](#delete_prefix-delete_suffix)
685
777
  - [`delete_suffix:`](#delete_prefix-delete_suffix)
686
- - [`delete_before:`](#delete_before-delete_after)
687
- - [`delete_after:`](#delete_before-delete_after)
778
+ - [`delete_before:`](#delete_before-delete_after-delete_before_last-delete_after_last)
779
+ - [`delete_after:`](#delete_before-delete_after-delete_before_last-delete_after_last)
780
+ - [`delete_before_last:`](#delete_before-delete_after-delete_before_last-delete_after_last)
781
+ - [`delete_after_last:`](#delete_before-delete_after-delete_before_last-delete_after_last)
688
782
  - [`split:`](#split)
689
783
  - [`downcase`](#downcase-upcase-capitalize-swapcase) or `downcase: true`
690
784
  - [`upcase`](#downcase-upcase-capitalize-swapcase) or `upcase: true`
@@ -699,26 +793,43 @@ Each entry can have a string that is an argumentless transform (e.g. capitalize)
699
793
  - [`deconstantize`](#pluralize-singularize-camelize-demodulize-deconstantize-parameterize-titleize-underscore) or `deconstantize: true`
700
794
  - [`titleize`](#pluralize-singularize-camelize-demodulize-deconstantize-parameterize-titleize-underscore) or `titleize: true`
701
795
  - [`parameterize`](#pluralize-singularize-camelize-demodulize-deconstantize-parameterize-titleize-underscore) or `parameterize: true`
796
+ - `transforms:`
702
797
 
703
798
  If any one of these `transforms:` entries are used, all count as being used. To have these be counted independently instead, create multiple entries in the `defines:` list.
704
799
 
705
800
  ```yml
801
+ dynamic:
706
802
  - name: attribute
707
- defines:
708
- - argument: 1
709
- transforms:
710
- - original # no transformation
711
- - add_suffix: '?'
712
- - add_suffix: '='
803
+ defines:
804
+ - argument: 0
805
+ transforms:
806
+ - original # no transformation
807
+ - add_suffix: '?'
808
+ - add_suffix: '='
713
809
  ```
714
810
  ```ruby
715
811
  attribute :first_name
716
812
  ```
717
813
  will count as a definition of `first_name`, `first_name=` and `first_name?`. `firstname=` wouldn't be reported on, even if only `first_name` and `first_name?` were used.
718
814
 
815
+ ```yml
816
+ dynamic:
817
+ - name: attr_accessor
818
+ defines:
819
+ - argument: '*'
820
+ - argument: '*'
821
+ transforms:
822
+ add_suffix: '='
823
+ ```
824
+ ```ruby
825
+ attr_accessor :first_name
826
+ ```
827
+ will count the calls to `first_name` and `first_name=` separately, with the understand it can be swapped to attr_reader or attr_writer if one or other isn't used.
828
+
719
829
  Arrays are not necessary for single values, and if there is just one set of transforms, the `transforms:` keyword can be omitted and everything moved up a level.
720
830
 
721
831
  ```yml
832
+ dynamic:
722
833
  - name: attr_writer
723
834
  defines:
724
835
  - argument: '*'
@@ -729,6 +840,21 @@ attr_writer :first_name, :surname
729
840
  ```
730
841
  will count as the definition of `first_name=`, and `surname=`
731
842
 
843
+ Multiple transform arguments will be applied sequentially
844
+ ```yml
845
+ dynamic:
846
+ - name: has_many
847
+ calls:
848
+ - argument: 0
849
+ singularize: true
850
+ camelize: true
851
+ split: '::'
852
+ ```
853
+ ```ruby
854
+ has_many :users
855
+ ```
856
+ counts as a call to `User`
857
+
732
858
  ## `original`
733
859
 
734
860
  Can be used in the [`transforms:`](#transforms) list, if used in a hash `true` can be used as a placeholder value
@@ -758,11 +884,16 @@ if multiple transform results are possible (from multiple entries), then all res
758
884
 
759
885
  Arrays are not necessary for single values
760
886
 
761
- ## `delete_before:`, `delete_after:`
887
+ ## `delete_before:`, `delete_after:`, `delete_before_last:`, `delete_after_last:`
762
888
 
763
889
  Can be used in the [`transforms:`](#transforms) list (or anywhere `transforms:` is able to be omitted).
764
890
 
765
- Each entry is a literal string, and _if present_ the string and everything before/after will be removed from the incoming value (if it's not present, this transform will continue to the next transform/result unmodified). if it's present multiple times then it will always be everything before/after the first substring match
891
+ Each entry is a literal string, and _if present_ the string and everything before/after will be removed from the incoming value (if it's not present, this transform will continue to the next transform/result unmodified).
892
+
893
+ - `delete_before:` will delete everything before and including the _first_ occurrence
894
+ - `delete_after:` will delete everything after and including the _first_ occurrence
895
+ - `delete_before_last:` will delete everything before and including the _last_ occurrence
896
+ - `delete_after_last:` will delete everything after and including the _last_ occurrence
766
897
 
767
898
  if multiple transform results are possible (from multiple entries), then all results will be used.
768
899
 
@@ -36,3 +36,9 @@ Define which paths use the custom precompiler using [`precompile:`](https://gith
36
36
  reference the name of the precompiler with `format: { custom: MyNotRubyPrecompiler }`
37
37
 
38
38
  If the `precompile` method raises any errors while precompiling, a warning will be printed to stderr and the file will be skipped
39
+
40
+ To test the output of the precompiler you can use the `--view-compiled` flag with a list of paths or path patterns, like so:
41
+
42
+ `bundle exec leftovers --view-compiled '*.not_rb'`
43
+
44
+
data/leftovers.gemspec CHANGED
@@ -44,6 +44,7 @@ Gem::Specification.new do |spec|
44
44
  spec.add_development_dependency 'rubocop-performance'
45
45
  spec.add_development_dependency 'rubocop-rake'
46
46
  spec.add_development_dependency 'rubocop-rspec'
47
+ spec.add_development_dependency 'ruby-prof'
47
48
  spec.add_development_dependency 'simplecov', '>= 0.18.5'
48
49
  spec.add_development_dependency 'simplecov-console'
49
50
  spec.add_development_dependency 'slim'
@@ -51,7 +52,7 @@ Gem::Specification.new do |spec|
51
52
  spec.add_development_dependency 'tty_string', '>= 0.2.1'
52
53
 
53
54
  spec.add_development_dependency 'spellr', '>= 0.8.1'
54
- spec.add_dependency 'fast_ignore', '>= 0.15.1'
55
+ spec.add_dependency 'fast_ignore', '>= 0.17.0'
55
56
  spec.add_dependency 'parallel'
56
57
  spec.add_dependency 'parser'
57
58
  end
@@ -0,0 +1,36 @@
1
+ # https://guides.rubyonrails.org/action_cable_overview.html
2
+ gems:
3
+ - activesupport
4
+ - actionpack
5
+
6
+ keep:
7
+ # https://guides.rubyonrails.org/action_cable_overview.html#server-side-components-channels-subscriptions
8
+ # https://api.rubyonrails.org/v7.0.2.2/classes/ActionCable/Channel/Base.html#method-i-subscribed
9
+ # it's for overriding
10
+ - subscribed
11
+ # https://api.rubyonrails.org/v7.0.2.2/classes/ActionCable/Channel/Base.html#method-i-unsubscribed
12
+ # it's for overriding
13
+ - unsubscribed
14
+
15
+ # https://api.rubyonrails.org/v7.0.2.2/classes/ActionCable/Channel/Base.html
16
+ - type: Method
17
+ privacy: public
18
+ path: /app/channels/**/*_channel.rb
19
+
20
+ - path: /app/channels/**/*_channel.rb
21
+ has_suffix: Channel
22
+
23
+
24
+ dynamic:
25
+ # https://guides.rubyonrails.org/action_cable_overview.html#connection-setup
26
+ # it's just attr_accessor
27
+ - names: identified_by
28
+ define:
29
+ - argument: '*'
30
+ transforms:
31
+ - original
32
+ - add_suffix: '='
33
+ call:
34
+ - argument: '*'
35
+ add_prefix: '@'
36
+
@@ -0,0 +1,31 @@
1
+ # https://guides.rubyonrails.org/action_mailbox_basics.html
2
+
3
+ gems:
4
+ - activesupport
5
+ - activerecord
6
+ - activestorage
7
+ - activejob
8
+ - actionpack
9
+
10
+ keep:
11
+ # https://api.rubyonrails.org/v7.0.2.2/classes/ActionMailbox/Base.html
12
+ # Overwrite in subclasses
13
+ - process
14
+
15
+ dynamic:
16
+ # https://api.rubyonrails.org/v7.0.2.2/classes/ActionMailbox/Base.html
17
+ - names: [before_processing, after_processing, around_processing]
18
+ calls:
19
+ - arguments: '*'
20
+ - arguments: [if, unless]
21
+ nested: '*'
22
+
23
+ # https://guides.rubyonrails.org/action_mailbox_basics.html#examples
24
+ # i'm guessing a lot about how this is supposed to work
25
+ - names: routing
26
+ calls:
27
+ arguments: '**'
28
+ camelize: true
29
+ add_suffix: Mailbox
30
+
31
+