leftovers 0.5.5 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (144) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +40 -2
  3. data/README.md +22 -1
  4. data/docs/Configuration.md +173 -42
  5. data/docs/Custom-Precompilers.md +38 -0
  6. data/leftovers.gemspec +8 -5
  7. data/lib/config/actionmailer.yml +11 -11
  8. data/lib/config/actionpack.yml +5 -3
  9. data/lib/config/activesupport.yml +1 -1
  10. data/lib/config/haml.yml +4 -2
  11. data/lib/config/rails.yml +1 -1
  12. data/lib/config/railties.yml +11 -0
  13. data/lib/config/ruby.yml +76 -8
  14. data/lib/config/slim.yml +4 -2
  15. data/lib/leftovers/ast/node.rb +16 -11
  16. data/lib/leftovers/cli.rb +5 -0
  17. data/lib/leftovers/collector.rb +5 -2
  18. data/lib/leftovers/config.rb +3 -38
  19. data/lib/leftovers/config_loader/argument_position_schema.rb +11 -0
  20. data/lib/leftovers/config_loader/argumentless_transform_schema.rb +21 -0
  21. data/lib/leftovers/config_loader/attribute.rb +56 -0
  22. data/lib/leftovers/config_loader/built_in_precompiler_schema.rb +13 -0
  23. data/lib/leftovers/config_loader/document_schema.rb +48 -0
  24. data/lib/leftovers/config_loader/dynamic_schema.rb +17 -0
  25. data/lib/leftovers/config_loader/has_argument_schema.rb +13 -0
  26. data/lib/leftovers/config_loader/has_value_schema.rb +18 -0
  27. data/lib/leftovers/config_loader/inherit_schema_attributes.rb +22 -0
  28. data/lib/leftovers/config_loader/keep_test_only_schema.rb +13 -0
  29. data/lib/leftovers/config_loader/node.rb +106 -0
  30. data/lib/leftovers/config_loader/object_schema.rb +117 -0
  31. data/lib/leftovers/config_loader/precompile_schema.rb +12 -0
  32. data/lib/leftovers/config_loader/precompiler_schema.rb +11 -0
  33. data/lib/leftovers/config_loader/privacy_processor_schema.rb +10 -0
  34. data/lib/leftovers/config_loader/privacy_schema.rb +15 -0
  35. data/lib/leftovers/config_loader/require_schema.rb +11 -0
  36. data/lib/leftovers/config_loader/rule_pattern_schema.rb +18 -0
  37. data/lib/leftovers/config_loader/scalar_argument_schema.rb +14 -0
  38. data/lib/leftovers/config_loader/scalar_value_schema.rb +14 -0
  39. data/lib/leftovers/config_loader/schema.rb +23 -0
  40. data/lib/leftovers/config_loader/string_enum_schema.rb +62 -0
  41. data/lib/leftovers/config_loader/string_pattern_schema.rb +14 -0
  42. data/lib/leftovers/config_loader/string_schema.rb +14 -0
  43. data/lib/leftovers/config_loader/string_value_processor_schema.rb +11 -0
  44. data/lib/leftovers/config_loader/suggester.rb +22 -0
  45. data/lib/leftovers/config_loader/transform_schema.rb +26 -0
  46. data/lib/leftovers/config_loader/true_schema.rb +18 -0
  47. data/lib/leftovers/config_loader/value_matcher_schema.rb +18 -0
  48. data/lib/leftovers/config_loader/value_or_array_schema.rb +66 -0
  49. data/lib/leftovers/config_loader/value_or_object_schema.rb +40 -0
  50. data/lib/leftovers/config_loader/value_processor_schema.rb +14 -0
  51. data/lib/leftovers/config_loader/value_type_schema.rb +17 -0
  52. data/lib/leftovers/config_loader.rb +86 -0
  53. data/lib/leftovers/definition.rb +1 -1
  54. data/lib/leftovers/definition_node.rb +6 -17
  55. data/lib/leftovers/definition_node_set.rb +11 -0
  56. data/lib/leftovers/definition_to_add.rb +31 -0
  57. data/lib/leftovers/dynamic_processors/call.rb +4 -7
  58. data/lib/leftovers/dynamic_processors/call_definition.rb +14 -11
  59. data/lib/leftovers/dynamic_processors/definition.rb +8 -7
  60. data/lib/leftovers/dynamic_processors/set_default_privacy.rb +18 -0
  61. data/lib/leftovers/dynamic_processors/set_privacy.rb +23 -0
  62. data/lib/leftovers/dynamic_processors.rb +2 -0
  63. data/lib/leftovers/file.rb +12 -12
  64. data/lib/leftovers/file_collector/comments_processor.rb +57 -0
  65. data/lib/leftovers/file_collector/node_processor.rb +131 -0
  66. data/lib/leftovers/file_collector.rb +66 -169
  67. data/lib/leftovers/matcher_builders/and_not.rb +7 -5
  68. data/lib/leftovers/matcher_builders/document.rb +13 -0
  69. data/lib/leftovers/matcher_builders/name.rb +18 -17
  70. data/lib/leftovers/matcher_builders/node.rb +48 -28
  71. data/lib/leftovers/matcher_builders/node_has_argument.rb +48 -53
  72. data/lib/leftovers/matcher_builders/node_has_keyword_argument.rb +13 -10
  73. data/lib/leftovers/matcher_builders/node_has_positional_argument.rb +29 -15
  74. data/lib/leftovers/matcher_builders/node_privacy.rb +13 -0
  75. data/lib/leftovers/matcher_builders/node_type.rb +4 -4
  76. data/lib/leftovers/matcher_builders/node_value.rb +28 -23
  77. data/lib/leftovers/matcher_builders/or.rb +50 -50
  78. data/lib/leftovers/matcher_builders/string_pattern.rb +14 -5
  79. data/lib/leftovers/matcher_builders.rb +2 -0
  80. data/lib/leftovers/matchers/all.rb +0 -4
  81. data/lib/leftovers/matchers/and.rb +0 -4
  82. data/lib/leftovers/matchers/any.rb +0 -4
  83. data/lib/leftovers/matchers/node_has_any_keyword_argument.rb +1 -7
  84. data/lib/leftovers/matchers/node_has_any_positional_argument_with_value.rb +1 -7
  85. data/lib/leftovers/matchers/node_has_positional_argument_with_value.rb +0 -4
  86. data/lib/leftovers/matchers/node_name.rb +0 -4
  87. data/lib/leftovers/matchers/node_pair_value.rb +0 -4
  88. data/lib/leftovers/matchers/node_path.rb +0 -4
  89. data/lib/leftovers/matchers/node_privacy.rb +19 -0
  90. data/lib/leftovers/matchers/node_scalar_value.rb +0 -4
  91. data/lib/leftovers/matchers/node_type.rb +0 -4
  92. data/lib/leftovers/matchers/not.rb +0 -4
  93. data/lib/leftovers/matchers/or.rb +0 -4
  94. data/lib/leftovers/matchers.rb +1 -0
  95. data/lib/leftovers/merged_config.rb +15 -33
  96. data/lib/leftovers/precompilers/erb.rb +22 -0
  97. data/lib/leftovers/precompilers/haml.rb +15 -0
  98. data/lib/leftovers/precompilers/json.rb +27 -0
  99. data/lib/leftovers/precompilers/precompiler.rb +28 -0
  100. data/lib/leftovers/precompilers/slim.rb +15 -0
  101. data/lib/leftovers/precompilers/yaml.rb +75 -0
  102. data/lib/leftovers/precompilers.rb +50 -0
  103. data/lib/leftovers/processor_builders/action.rb +48 -39
  104. data/lib/leftovers/processor_builders/add_prefix.rb +2 -2
  105. data/lib/leftovers/processor_builders/add_suffix.rb +2 -2
  106. data/lib/leftovers/processor_builders/argument.rb +8 -11
  107. data/lib/leftovers/processor_builders/dynamic.rb +51 -16
  108. data/lib/leftovers/processor_builders/each.rb +2 -2
  109. data/lib/leftovers/processor_builders/each_action.rb +33 -33
  110. data/lib/leftovers/processor_builders/each_dynamic.rb +4 -8
  111. data/lib/leftovers/processor_builders/each_for_definition_set.rb +25 -21
  112. data/lib/leftovers/processor_builders/keyword.rb +3 -4
  113. data/lib/leftovers/processor_builders/transform.rb +4 -4
  114. data/lib/leftovers/processor_builders/transform_chain.rb +16 -8
  115. data/lib/leftovers/processor_builders/transform_set.rb +32 -28
  116. data/lib/leftovers/rake_task.rb +1 -1
  117. data/lib/leftovers/todo_reporter.rb +10 -35
  118. data/lib/leftovers/value_processors/add_dynamic_prefix.rb +3 -10
  119. data/lib/leftovers/value_processors/add_dynamic_suffix.rb +3 -10
  120. data/lib/leftovers/value_processors/delete_prefix.rb +0 -6
  121. data/lib/leftovers/value_processors/delete_suffix.rb +0 -6
  122. data/lib/leftovers/value_processors/each.rb +1 -1
  123. data/lib/leftovers/value_processors/each_for_definition_set.rb +4 -10
  124. data/lib/leftovers/value_processors/each_keyword.rb +1 -1
  125. data/lib/leftovers/value_processors/each_keyword_argument.rb +1 -1
  126. data/lib/leftovers/value_processors/each_positional_argument.rb +3 -2
  127. data/lib/leftovers/value_processors/keyword.rb +3 -11
  128. data/lib/leftovers/value_processors/keyword_argument.rb +2 -10
  129. data/lib/leftovers/value_processors/return_definition_node.rb +14 -0
  130. data/lib/leftovers/value_processors/{return_string.rb → return_sym.rb} +1 -1
  131. data/lib/leftovers/value_processors/split.rb +2 -2
  132. data/lib/leftovers/value_processors.rb +2 -2
  133. data/lib/leftovers/version.rb +1 -1
  134. data/lib/leftovers.rb +66 -23
  135. metadata +98 -39
  136. data/lib/config/actioncable.yml +0 -4
  137. data/lib/leftovers/backports.rb +0 -40
  138. data/lib/leftovers/config_validator/error_processor.rb +0 -196
  139. data/lib/leftovers/config_validator/schema_hash.rb +0 -530
  140. data/lib/leftovers/config_validator.rb +0 -60
  141. data/lib/leftovers/erb.rb +0 -20
  142. data/lib/leftovers/haml.rb +0 -21
  143. data/lib/leftovers/slim.rb +0 -21
  144. data/lib/leftovers/value_processors/return_definition.rb +0 -26
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0d697aa7197a87a0e3cc99124031957ab4cc602c89afd6d0369be3fffdef3ba0
4
- data.tar.gz: c782e42dc2b5916160213fe22a7eb3c1560930c7e21f6f72489f10d0a03ff612
3
+ metadata.gz: c2e0c74dad85b7b571608a7207f006fe14d5748e1a155470185112b80a7b80a3
4
+ data.tar.gz: 68f3d83b310f640e127b961e6ac2ece795a7b9e2a6de961a1b42498916e092d7
5
5
  SHA512:
6
- metadata.gz: c63edb11d4ed98ab23402f4a7ace623a6a364a5f39218076a5713034879fd98ed90fe024badaca2ac26562e94bbd0fde690f932e185de88a93bff1dca3fb0ce4
7
- data.tar.gz: daae5206e9b217ce77201347c504255834aba552a8566c04ecfd224105577197c9d62415f7dc799727842c136d9e2c00e2fe90de8115c95fd4c176068cbcb313
6
+ metadata.gz: c57c64254cc2092e38b8decfd7bde0a021d66a7c3f563dc3e1f5a68b91c4bfc7b16a8490e5437b3da942071d41d2c35c247e1e51739064e14fdfcc6653b192b3
7
+ data.tar.gz: b129119436c793987c89b032d5936b10ca935c7fc5398e7a2843665bbfec28ccaacd0a0090c8cd37c5172b6892f4291455aef40df6bae67727d25ac47fd871a3
data/CHANGELOG.md CHANGED
@@ -1,7 +1,45 @@
1
- # 0.5.5
1
+ # v0.8.0
2
+ - Allow custom precompilers
3
+ ```yml
4
+ require: './path/to/my_precompiler'
5
+ precompile:
6
+ - paths: '*.myCustomFormat'
7
+ format: { custom: 'MyPrecompiler' }
8
+ ```
9
+ the built in precompilers have moved into this system too, with `format: haml` etc. `haml_paths` etc are now deprecated
10
+ - a lot of refactoring, which revealed some edge cases i was handling
11
+ - collect a call to :my_method= with receiver&.my_method ||= (and += etc)
12
+ - if `add_prefix:` or `add_suffix:` points to another argument for a name that we can't use because it's a variable, it now just don't return the value, rather than returning the value but without the affix
13
+
14
+ # v0.7.0
15
+ - Rewrite the config parser/validation
16
+ - to provide clearer error messages with line numbers and everything
17
+ - to allow removing the json_schemer dependency with its 4 further dependencies
18
+ - Allow `match:` to be used with `has_prefix:` and/or `has_suffix:`. There's not a good use for this but it was easier than encoding 'this can't be used with that' logic especially for it.
19
+ - Add the possibility to quiet the `requires:` config, like:
20
+ ```yml
21
+ requires:
22
+ - 'active_support/inflections'
23
+ - quiet: './config/initializers/inflections'
24
+ ```
25
+ - consider all the public methods in rails custom generators to be used, this required some new features:
26
+ - add filtering methods/constants by public/protected/private
27
+ - add the possibility to set the privacy of methods and constants with method calls (`set_privacy:`, and `set_default_privacy:`)
28
+ - add `Method` and `Constant` as options for the `type:` filter
29
+ - add type filtering to dynamic.
30
+ - check `def self.whatever` as a definition, i didn't realise i wasn't checking this.
31
+
32
+ # v0.6.0
33
+ - drop ruby 2.4 support, allowing for some performance improvements
34
+ - Add ability to parse JSON and YAML files
35
+ - Add magic comment that points to a particular dynamic rule
36
+ - repeated calls to --write-todo won't have ordering differences
37
+ - fix issue with --write-todo and unused methods defined in test files
38
+
39
+ # v0.5.5
2
40
  - Fix rails resource/resources method signatures
3
41
 
4
- # 0.5.4
42
+ # v0.5.4
5
43
  - Add support for slim templates #13 - thanks @veganstraightedge
6
44
  - fix the #how-to-resolve link #11 - thanks @veganstraightedge
7
45
 
data/README.md CHANGED
@@ -129,7 +129,7 @@ To do this for all definitions of this name, instead of adding a comment, add th
129
129
 
130
130
  ### `# leftovers:call`
131
131
  _aliases `leftovers:calls`_
132
- To mark a dynamic call that doesn't use literal values, use `leftovers:call` with the method name listed
132
+ To mark a call that doesn't use literal values, use `leftovers:call` with the method name listed
133
133
  ```ruby
134
134
  method = [:puts, :warn].sample # leftovers:call puts, warn
135
135
  send(method, 'text')
@@ -137,6 +137,26 @@ send(method, 'text')
137
137
 
138
138
  This would consider `puts` and `warn` to both have been called
139
139
 
140
+ ### `# leftovers:dynamic:*`
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
+
143
+ ```ruby
144
+ [ # leftovers:dynamic:call_login
145
+ :user,
146
+ :admin
147
+ ].each { |method| send("#{method}_login") }
148
+ ```
149
+
150
+ with the following configuration matching the `name: value` to the `leftovers:dynamic:process_name`
151
+
152
+ ```yaml
153
+ dynamic:
154
+ name: call_login
155
+ arguments: '*'
156
+ add_suffix: '_login'
157
+ ```
158
+ This would consider `user_login` and `admin_login` to both have been called.
159
+
140
160
  ## Configuration file
141
161
 
142
162
  The configuration is read from `.leftovers.yml` in your project root.
@@ -146,6 +166,7 @@ Its presence is optional and all of these settings are optional.
146
166
  - [`exclude_paths:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#exclude_paths)
147
167
  - [`test_paths:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#test_paths)
148
168
  - [`requires:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#requires)
169
+ - [`precompile:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#precompile)
149
170
  - [`gems:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#gems)
150
171
  - [`keep:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#keep)
151
172
  - [`test_only:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#test_only)
@@ -6,9 +6,7 @@ Its presence is optional and all of these settings are optional.
6
6
  - [`include_paths:`](#include_paths)
7
7
  - [`exclude_paths:`](#exclude_paths)
8
8
  - [`test_paths:`](#test_paths)
9
- - [`haml_paths:`](#haml_paths)
10
- - [`slim_paths:`](#slim_paths)
11
- - [`erb_paths:`](#erb_paths)
9
+ - [`precompile:`](#precompile)
12
10
  - [`requires:`](#requires)
13
11
  - [`gems:`](#gems)
14
12
  - [`keep:`](#keep)
@@ -57,12 +55,17 @@ List filenames/paths that you want to include
57
55
  Unlike other `paths:` configuration, each entry is **not** the gitignore pattern format.
58
56
  Instead it is strings that can be passed directly to ruby's `require` method (relative paths should start with `./`).
59
57
 
60
- Missing files/gems will be a warning, but not a LoadError.
58
+ ```yml
59
+ require: ./config/initializers/my_other_inflections_file
60
+ ```
61
61
 
62
- By default, the default [`gems: active_support`]() config `require: activesupport` and `gems: rails` will `require: ./config/initializers/inflections`
62
+ Missing files/gems will be a warning, but not a LoadError.
63
+ To avoid seeing the warning if the file isn't there use `quiet:`.
63
64
 
64
65
  ```yml
65
- require: ./config/initializers/my_other_inflections_file
66
+ requires:
67
+ - 'active_support/inflections' # will warn if it's missing
68
+ - quiet: './config/initializers/inflections' # will say nothing
66
69
  ```
67
70
 
68
71
  Arrays are not necessary for single values
@@ -81,41 +84,78 @@ test_paths:
81
84
 
82
85
  Arrays are not necessary for single values
83
86
 
84
- ## `haml_paths:`
85
-
86
- list filenames/paths of test directories that are in the haml format
87
- Defined using the [.gitignore pattern format](https://git-scm.com/docs/gitignore#_pattern_format)
87
+ ## `precompile:`
88
88
 
89
89
  ```yml
90
- haml_paths:
91
- - '*.haml'
90
+ require: './path/my_project/my_precompiler'
91
+ precompile:
92
+ - paths: '*.myCustomFormat'
93
+ format: { custom: 'MyProject::MyPrecompiler' }
94
+ - paths: '*.my.json'
95
+ format: json
92
96
  ```
93
97
 
94
- Arrays are not necessary for single values. `*.haml` is recognized by default
98
+ Define any precompilers and the paths they affect.
95
99
 
96
- ## `slim_paths:`
100
+ `paths:` are defined using the [.gitignore pattern format](https://git-scm.com/docs/gitignore#_pattern_format)
97
101
 
98
- list filenames/paths of test directories that are in the slim format
99
- Defined using the [.gitignore pattern format](https://git-scm.com/docs/gitignore#_pattern_format)
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.
103
+ (use [`require:`](#requires) to have leftovers load its file)
104
+
105
+ See [Custom precompilers]('../Custom-Precompilers.md) for more details on the custom precompiler class
106
+
107
+ Arrays are not necessary for single values.
108
+
109
+ ### `format: yaml`
110
+
111
+ The yaml precompiler considers yaml tags like `!ruby/class 'MyClass'` to be a call to `MyClass`.
112
+ and renders the structure of the yaml document as arguments for the [`document:true`](#document-true) rule.
113
+
114
+ so you could, e.g. read the class name out of a yaml document like:
100
115
 
101
116
  ```yml
102
- slim_paths:
103
- - '*.slim'
117
+ class_name: MyClass
104
118
  ```
105
119
 
106
- Arrays are not necessary for single values. `*.slim` is recognized by default
120
+ with config like:
107
121
 
108
- ## `erb_paths:`
122
+ ```yml
123
+ include_paths:
124
+ - 'config/*.yml'
109
125
 
110
- list filenames/paths of test directories that are in the erb format
111
- Defined using the [.gitignore pattern format](https://git-scm.com/docs/gitignore#_pattern_format)
126
+ dynamic:
127
+ document: true
128
+ path: config/*.yml
129
+ calls:
130
+ argument: class_name
131
+ ```
132
+
133
+ [`nested:`](#nested) may be useful for more complex yaml structures
134
+
135
+ ### `format: json`
136
+
137
+ The json precompiler renders the structure of the json document as arguments for the [`document:true`](#document-true) rule.
138
+
139
+ so you could, e.g. read the class name out of a json document like:
140
+
141
+ ```json
142
+ { "class_name": "MyClass" }
143
+ ```
144
+
145
+ with config like:
112
146
 
113
147
  ```yml
114
- erb_paths:
115
- - '*.erb'
148
+ include_paths:
149
+ - 'config/*.json'
150
+
151
+ dynamic:
152
+ document: true
153
+ path: config/*.json
154
+ calls:
155
+ argument: class_name
116
156
  ```
117
157
 
118
- Arrays are not necessary for single values. `*.erb` is recognized by default
158
+ [`nested:`](#nested) may be useful for more complex json structures
119
159
 
120
160
  ## `gems:`
121
161
  _alias `gem:`_
@@ -141,10 +181,12 @@ Each entry can be a string (an exact match for a method, constant, or variable n
141
181
  or the properties from `names:`
142
182
  - [`has_prefix:`](#has_prefix)
143
183
  - [`has_suffix:`](#has_suffix)
144
- - [`matches:`](#matches) (can't be used in the same entry as `has_prefix:` or `has_suffix:`)
184
+ - [`matches:`](#matches)
145
185
  - [`paths:`](#paths)
146
186
  - [`has_arguments:`](#has_arguments)
147
187
  - [`has_receiver:`](#has_receiver)
188
+ - [`type:`](#type)
189
+ - [`privacy:`](#privacy)
148
190
  - [`unless`](#unless)
149
191
 
150
192
  Arrays are not necessary for single values
@@ -170,7 +212,7 @@ Each entry can be a string (an exact match for a method, constant, or variable n
170
212
  or the properties from `names:`
171
213
  - [`has_prefix:`](#has_prefix)
172
214
  - [`has_suffix:`](#has_suffix)
173
- - [`matches:`](#matches) (can't be used in the same entry as `has_prefix:` or `has_suffix:`)
215
+ - [`matches:`](#matches)
174
216
  - [`paths:`](#paths)
175
217
  - [`has_arguments:`](#has_arguments)
176
218
  - [`unless`](#unless)
@@ -202,11 +244,14 @@ Each entry must have at least one of the following properties to restrict which
202
244
  - [`paths:`](#paths)
203
245
  - [`has_arguments:`](#has_arguments)
204
246
  - [`has_receiver:`](#has_receiver)
205
- - [`unless`](#unless)
247
+ - [`unless:`](#unless)
248
+ - [`document: true`](#document-true)
206
249
 
207
- And must have one or both of
250
+ And must have at least one of
208
251
  - ['calls:`](#calls-defines)
209
252
  - [`defines:`](#calls-defines)
253
+ - [`set_privacy:](#set-privacy)
254
+ - [`set_default_privacy:`](#set-default-privacy)
210
255
 
211
256
  Arrays are not necessary for single values.
212
257
 
@@ -232,7 +277,7 @@ This is a list of methods/constants/variables, and can be used in [`dynamic:`](#
232
277
  Each entry can be a string (an exact match for a method, constant, or variable name that includes the sigil), or have at least one of the following properties:
233
278
  - [`has_prefix:`](#has_prefix)
234
279
  - [`has_suffix:`](#has_suffix)
235
- - [`matches:`](#matches) (this can't be used in the same entry as `has_prefix:` or `has_suffix:`)
280
+ - [`matches:`](#matches)
236
281
 
237
282
  Arrays are not necessary for single values
238
283
 
@@ -299,10 +344,37 @@ keep:
299
344
  path: /app/helpers
300
345
  ```
301
346
 
347
+ ## `document: true`
348
+
349
+ Instructs to consider the whole document. this is useful when parsing [YAML](#yaml-paths) or [JSON](#json-paths) config files for various values.
350
+
351
+ e.g.
352
+
353
+ ```yml
354
+ includes: /config/roles.yml
355
+ dynamic:
356
+ - document: true
357
+ path: /config/roles.yml
358
+ defines:
359
+ arguments: '*'
360
+ add_suffix: '?'
361
+ add_prefix: can_
362
+ ```
363
+
364
+ will parse "config/roles.yml"
365
+ ```yml
366
+ - build_house
367
+ - drive_car
368
+ ```
369
+
370
+ and consider it to have created methods like `can_build_house?` and `can_drive_car?`
371
+
372
+ [`nested:`](#nested) may be useful for more complex data structures
373
+
302
374
  ## `calls:`, `defines:`
303
375
  _aliases `call:`, `define:`_
304
376
 
305
- At least one of these must be used in each entry in [`dynamic:`](#dynamic)
377
+ These may be used as entries in [`dynamic:`](#dynamic)
306
378
 
307
379
  This is a list of values that are called or defined dynamically by the matched method, or eventually after being assigned to the the matched constant or variable.
308
380
 
@@ -354,6 +426,43 @@ dynamic:
354
426
  calls: 1
355
427
  ```
356
428
 
429
+ ## `set_privacy:`
430
+
431
+ Set privacy has the same requirements as [`calls:` & `defines:`](#calls-defines).
432
+
433
+ additional it requires a `to:` with one of either `private`, `public`, or `protected`.
434
+
435
+ For example, from the ruby config:
436
+ ```yml
437
+ dynamic:
438
+ name: private_class_method
439
+ has_argument: 0
440
+ set_privacy:
441
+ argument: '*'
442
+ to: private
443
+ ```
444
+
445
+ which sets all methods named by the arguments to the privacy_class_method method to private.
446
+
447
+ these methods could then be filtered using the [`privacy:`](#privacy) method in another [`dynamic:`](#dynamic) or [`keep:`](#keep) rule.
448
+
449
+ Leftovers limits this to only affect methods defined in the same file.
450
+
451
+ ## `set_default_privacy:`
452
+
453
+ This must be one of `public`, `private`, or `protected` and will set all subsequent method definitions in this file to that default privacy (unless its then overridden by [`set_privacy`](#set_privacy))
454
+
455
+ For example, from the default ruby config:
456
+ ```yml
457
+ dynamic:
458
+ name: private
459
+ unless:
460
+ has_argument: 0
461
+ set_default_privacy: private
462
+ ```
463
+
464
+ these methods could then be filtered using the [`privacy:`](#privacy) method in another [`dynamic:`](#dynamic) or [`keep:`](#keep) rule.
465
+
357
466
  ## `arguments:`
358
467
  _alias `argument:`_
359
468
 
@@ -366,7 +475,9 @@ It can have any of these properties:
366
475
  - [`at:`](#at)
367
476
  - [`has_value:`](#has_value_has_receiver)
368
477
 
369
- 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
478
+ 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
+
480
+ Positional arguments are zero indexed
370
481
 
371
482
  ## `has_arguments:`
372
483
  _alias `has_argument:`_
@@ -384,6 +495,8 @@ It can have any of these properties:
384
495
 
385
496
  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
386
497
 
498
+ Positional arguments are zero indexed
499
+
387
500
  ## `keywords:`
388
501
  When the keyword argument **keywords** are the thing being called.
389
502
 
@@ -418,7 +531,7 @@ Each entry can be any of:
418
531
  - or have at least one of the following properties to match the keyword/hash key string or symbol:
419
532
  - [`has_prefix:`](#has_prefix)
420
533
  - [`has_suffix:`](#has_suffix)
421
- - [`matches:`](#matches) (this can't be used in the same entry as `has_prefix:` or `has_suffix:`)
534
+ - [`matches:`](#matches)
422
535
 
423
536
  Arrays are not necessary for single values
424
537
 
@@ -429,10 +542,10 @@ filter [`arguments:`](#arguments), [`has_arguments:`](#has_arguments), and [`key
429
542
  Each entry can be one of
430
543
  - `true`, `false`, `nil`, or an Integer. matches the literal value
431
544
  - a String. matches the literal string or symbol value
432
- - or have at least one of the following properties to match a string or symbol:
545
+ - or have at least one of the following properties to match the name:
433
546
  - [`has_prefix:`](#has_prefix)
434
547
  - [`has_suffix:`](#has_suffix)
435
- - [`matches:`](#matches) (this can't be used in the same entry as `has_prefix:` or `has_suffix:`)
548
+ - [`matches:`](#matches)
436
549
  - or have at least one of the following properties to match within an array or hash:
437
550
  - [`at`](#at)
438
551
  - [`has_value`](#has_value_has_receiver)
@@ -441,17 +554,35 @@ Each entry can be one of
441
554
  - or have the following property to match the receiver
442
555
  - [`has_receiver`](#has_value_has_receiver)
443
556
 
557
+ ## `privacy:`
558
+
559
+ filter [`dynamic:`](#dynamic) and [`keep:`](#keep) by method/constant privacy
560
+
561
+ e.g.
562
+
563
+ ```yml
564
+ keep:
565
+ - path: '**/generators/**/*_generator.rb'
566
+ privacy: public
567
+ type: Method
568
+ ```
569
+
570
+ considers all public methods defined in rails generators to be called.
571
+
444
572
  ## `type:`
445
573
 
446
- Filter [`has_value`](#has_value_has_receiver), by the argument/assigned value type
574
+ Filter by the literal type
447
575
 
448
576
  Each entry can be one of
449
- - `'String'`
450
- - `'Symbol'`
451
- - `'Integer'`
452
- - `'Float'`
453
- - `'Array'`
454
- - `'Hash'`
577
+ - `'String'` a literal string, defined with "" or '' (not String.new)
578
+ - `'Symbol'` a literal symbol
579
+ - `'Integer'` a literal integer
580
+ - `'Float'` a literal float
581
+ - `'Array'` a literal array defined with [] (not Array.new)
582
+ - `'Hash'` a literal hash, defined with {} (not Hash.new)
583
+ - `'Proc'` a literal proc/lambda, defined with lambda {}, proc {}, or -> {} (not Proc.new)
584
+ - `'Method'` a method call or definition defined with def, (not define_method {})
585
+ - `'Constant'` a constant assignment, or a literal module or class defined with keywords, (not Module/Class.new)
455
586
 
456
587
  Arrays are not necessary for single values
457
588
 
@@ -0,0 +1,38 @@
1
+ # Custom Precompilers
2
+
3
+ In addition to the built in precompilers, it's possible to add a custom precompiler
4
+
5
+ It must be a class or module with a singleton method `precompile`. take a string of whatever code it likes, and return a string of valid ruby.
6
+
7
+ ```ruby
8
+ require 'not_ruby' # require the gem that does the actual transformation
9
+
10
+ module MyNotRubyPrecompiler
11
+ def self.precompile(not_ruby_content)
12
+ # not_ruby_content is a string of (hopefully) valid precompilable code
13
+ NotRuby::Parser.parse(not_ruby_content).to_ruby # output a string of valid ruby
14
+ end
15
+ end
16
+ ```
17
+
18
+ See the [build in precompilers](https://github.com/robotdana/leftovers/tree/main/lib/precompilers) for other examples.
19
+
20
+ To configure the precompiler to be used by leftovers, add something similar to this to the `.leftovers.yml` file
21
+
22
+ ```yml
23
+ include_paths:
24
+ - 'lib/**/*.not_rb'
25
+ require: './path/to/my_not_ruby_precompiler'
26
+ precompile:
27
+ - paths: '*.not_rb'
28
+ format: { custom: MyNotRubyPrecompiler }
29
+ ```
30
+
31
+ Ensure any necessary extension patterns are added to to [`include_paths:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#include_paths) for those particular files you wish to check.
32
+
33
+ Require the custom precompiler using [`require:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#requires)
34
+
35
+ Define which paths use the custom precompiler using [`precompile:`](https://github.com/robotdana/leftovers/tree/main/docs/Configuration.md#precompile),
36
+ reference the name of the precompiler with `format: { custom: MyNotRubyPrecompiler }`
37
+
38
+ If the `precompile` method raises any errors while precompiling, a warning will be printed to stderr and the file will be skipped
data/leftovers.gemspec CHANGED
@@ -17,7 +17,9 @@ Gem::Specification.new do |spec|
17
17
  spec.metadata['homepage_uri'] = spec.homepage
18
18
  spec.metadata['source_code_uri'] = 'http://github.com/robotdana/leftovers'
19
19
  spec.metadata['changelog_uri'] = 'http://github.com/robotdana/leftovers/blob/main/CHANGELOG.md'
20
- spec.required_ruby_version = '>= 2.4.0'
20
+
21
+ spec.metadata['rubygems_mfa_required'] = 'true'
22
+ spec.required_ruby_version = '>= 2.5.0'
21
23
 
22
24
  spec.files = Dir.glob('{lib,exe,docs}/**/{*,.*}') + %w{
23
25
  CHANGELOG.md
@@ -33,13 +35,15 @@ Gem::Specification.new do |spec|
33
35
  spec.add_development_dependency 'activesupport'
34
36
  spec.add_development_dependency 'benchmark-ips'
35
37
  spec.add_development_dependency 'bundler', '~> 2.0'
38
+ spec.add_development_dependency 'did_you_mean'
36
39
  spec.add_development_dependency 'haml'
37
40
  spec.add_development_dependency 'pry', '~> 0.1'
38
41
  spec.add_development_dependency 'rake', '>= 13'
39
42
  spec.add_development_dependency 'rspec', '~> 3.0'
40
- spec.add_development_dependency 'rubocop', '~> 0.93.1'
41
- spec.add_development_dependency 'rubocop-performance', '~> 1.8.1'
42
- spec.add_development_dependency 'rubocop-rspec', '~> 1.44.1'
43
+ spec.add_development_dependency 'rubocop'
44
+ spec.add_development_dependency 'rubocop-performance'
45
+ spec.add_development_dependency 'rubocop-rake'
46
+ spec.add_development_dependency 'rubocop-rspec'
43
47
  spec.add_development_dependency 'simplecov', '>= 0.18.5'
44
48
  spec.add_development_dependency 'simplecov-console'
45
49
  spec.add_development_dependency 'slim'
@@ -48,7 +52,6 @@ Gem::Specification.new do |spec|
48
52
 
49
53
  spec.add_development_dependency 'spellr', '>= 0.8.1'
50
54
  spec.add_dependency 'fast_ignore', '>= 0.15.1'
51
- spec.add_dependency 'json_schemer'
52
55
  spec.add_dependency 'parallel'
53
56
  spec.add_dependency 'parser'
54
57
  end
@@ -9,14 +9,14 @@ keep:
9
9
  - delivered_email
10
10
 
11
11
  dynamic:
12
- names:
13
- - deliver_now
14
- - deliver_later
15
- calls:
16
- value:
17
- deliver
18
- names:
19
- - before_action
20
- - after_action
21
- - around_action
22
- calls: ['*', if, unless]
12
+ - names:
13
+ - deliver_now
14
+ - deliver_later
15
+ calls:
16
+ value:
17
+ deliver
18
+ - names:
19
+ - before_action
20
+ - after_action
21
+ - around_action
22
+ calls: ['*', if, unless]
@@ -7,9 +7,11 @@ include_paths:
7
7
  - '*.rjs'
8
8
  - '*.rhtml'
9
9
 
10
- erb_paths:
11
- - '*.rjs'
12
- - '*.rhtml'
10
+ precompile:
11
+ - paths:
12
+ - '*.rjs'
13
+ - '*.rhtml'
14
+ format: erb
13
15
 
14
16
  keep:
15
17
  - ssl_configured? # ApplicationController
@@ -2,7 +2,7 @@ requires:
2
2
  - 'active_support'
3
3
  - 'active_support/core_ext/string'
4
4
  - 'active_support/inflections'
5
- - './config/initializers/inflections'
5
+ - quiet: './config/initializers/inflections'
6
6
 
7
7
  # THIS IS INCOMPLETE (you can help by expanding it)
8
8
  # rails is _really complicated_ and has a lot of magic which calls methods for you.
data/lib/config/haml.yml CHANGED
@@ -1,4 +1,6 @@
1
1
  include_paths:
2
2
  - '*.haml'
3
- haml_paths:
4
- - '*.haml'
3
+ requires: 'haml'
4
+ precompile:
5
+ format: haml
6
+ paths: '*.haml'
data/lib/config/rails.yml CHANGED
@@ -3,7 +3,6 @@
3
3
  # some is currently impossible to handle (with_options).
4
4
  # Some is just corners of rails I haven't hit yet.
5
5
  gems:
6
- - actioncable
7
6
  - actionmailer
8
7
  - actionpack
9
8
  - actionview
@@ -11,6 +10,7 @@ gems:
11
10
  - activemodel
12
11
  - activerecord
13
12
  - activesupport
13
+ - railties
14
14
 
15
15
  keep:
16
16
  - default_url_options # called by url_for, unsure what gem does
@@ -0,0 +1,11 @@
1
+ keep:
2
+ - # https://guides.rubyonrails.org/generators.html#generators-lookup
3
+ path: '**/generators/**/*_generator.rb'
4
+ # "When a generator is invoked, each public method in the generator is executed sequentially in
5
+ # the order that it is defined When a generator is invoked, each public method in the generator
6
+ # is executed sequentially in the order that it is defined"
7
+ #
8
+ # https://guides.rubyonrails.org/generators.html
9
+ privacy: public
10
+ type: Method
11
+