leftovers 0.6.0 → 0.7.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 (78) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -3
  3. data/docs/Configuration.md +82 -18
  4. data/leftovers.gemspec +1 -1
  5. data/lib/config/actionmailer.yml +11 -11
  6. data/lib/config/activesupport.yml +1 -1
  7. data/lib/config/rails.yml +1 -1
  8. data/lib/config/railties.yml +11 -0
  9. data/lib/config/ruby.yml +72 -0
  10. data/lib/leftovers/ast/node.rb +16 -11
  11. data/lib/leftovers/config.rb +1 -24
  12. data/lib/leftovers/config_loader/argument_position_schema.rb +11 -0
  13. data/lib/leftovers/config_loader/argumentless_transform_schema.rb +21 -0
  14. data/lib/leftovers/config_loader/attribute.rb +30 -0
  15. data/lib/leftovers/config_loader/document_schema.rb +21 -0
  16. data/lib/leftovers/config_loader/dynamic_schema.rb +17 -0
  17. data/lib/leftovers/config_loader/has_argument_schema.rb +13 -0
  18. data/lib/leftovers/config_loader/has_value_schema.rb +18 -0
  19. data/lib/leftovers/config_loader/keep_test_only_schema.rb +13 -0
  20. data/lib/leftovers/config_loader/node.rb +106 -0
  21. data/lib/leftovers/config_loader/object_schema.rb +189 -0
  22. data/lib/leftovers/config_loader/privacy_processor_schema.rb +12 -0
  23. data/lib/leftovers/config_loader/privacy_schema.rb +15 -0
  24. data/lib/leftovers/config_loader/require_schema.rb +11 -0
  25. data/lib/leftovers/config_loader/rule_pattern_schema.rb +18 -0
  26. data/lib/leftovers/config_loader/scalar_argument_schema.rb +14 -0
  27. data/lib/leftovers/config_loader/scalar_value_schema.rb +14 -0
  28. data/lib/leftovers/config_loader/schema.rb +21 -0
  29. data/lib/leftovers/config_loader/string_enum_schema.rb +62 -0
  30. data/lib/leftovers/config_loader/string_pattern_schema.rb +14 -0
  31. data/lib/leftovers/config_loader/string_schema.rb +14 -0
  32. data/lib/leftovers/config_loader/string_value_processor_schema.rb +11 -0
  33. data/lib/leftovers/config_loader/suggester.rb +22 -0
  34. data/lib/leftovers/config_loader/transform_schema.rb +28 -0
  35. data/lib/leftovers/config_loader/true_schema.rb +18 -0
  36. data/lib/leftovers/config_loader/value_matcher_schema.rb +18 -0
  37. data/lib/leftovers/config_loader/value_or_array_schema.rb +64 -0
  38. data/lib/leftovers/config_loader/value_processor_schema.rb +14 -0
  39. data/lib/leftovers/config_loader/value_type_schema.rb +17 -0
  40. data/lib/leftovers/config_loader.rb +82 -0
  41. data/lib/leftovers/definition_node.rb +6 -17
  42. data/lib/leftovers/definition_node_set.rb +11 -0
  43. data/lib/leftovers/definition_to_add.rb +31 -0
  44. data/lib/leftovers/dynamic_processors/call.rb +4 -3
  45. data/lib/leftovers/dynamic_processors/call_definition.rb +14 -7
  46. data/lib/leftovers/dynamic_processors/definition.rb +8 -3
  47. data/lib/leftovers/dynamic_processors/set_default_privacy.rb +18 -0
  48. data/lib/leftovers/dynamic_processors/set_privacy.rb +23 -0
  49. data/lib/leftovers/dynamic_processors.rb +2 -0
  50. data/lib/leftovers/file.rb +5 -1
  51. data/lib/leftovers/file_collector.rb +44 -17
  52. data/lib/leftovers/matcher_builders/node.rb +4 -0
  53. data/lib/leftovers/matcher_builders/node_privacy.rb +13 -0
  54. data/lib/leftovers/matcher_builders/node_type.rb +4 -4
  55. data/lib/leftovers/matcher_builders/node_value.rb +1 -1
  56. data/lib/leftovers/matcher_builders/string_pattern.rb +14 -5
  57. data/lib/leftovers/matcher_builders.rb +1 -0
  58. data/lib/leftovers/matchers/node_privacy.rb +19 -0
  59. data/lib/leftovers/matchers.rb +1 -0
  60. data/lib/leftovers/merged_config.rb +18 -34
  61. data/lib/leftovers/processor_builders/add_prefix.rb +1 -1
  62. data/lib/leftovers/processor_builders/add_suffix.rb +1 -1
  63. data/lib/leftovers/processor_builders/dynamic.rb +50 -16
  64. data/lib/leftovers/processor_builders/transform.rb +2 -2
  65. data/lib/leftovers/processor_builders/transform_set.rb +8 -8
  66. data/lib/leftovers/value_processors/each_for_definition_set.rb +2 -5
  67. data/lib/leftovers/value_processors/each_positional_argument.rb +1 -1
  68. data/lib/leftovers/value_processors/return_definition_node.rb +14 -0
  69. data/lib/leftovers/value_processors/{return_string.rb → return_sym.rb} +1 -1
  70. data/lib/leftovers/value_processors.rb +2 -2
  71. data/lib/leftovers/version.rb +1 -1
  72. data/lib/leftovers.rb +23 -14
  73. metadata +54 -22
  74. data/lib/config/actioncable.yml +0 -4
  75. data/lib/leftovers/config_validator/error_processor.rb +0 -196
  76. data/lib/leftovers/config_validator/schema_hash.rb +0 -551
  77. data/lib/leftovers/config_validator.rb +0 -61
  78. data/lib/leftovers/value_processors/return_definition.rb +0 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 32e8f2762f7f513145ea799b64a059c7228dd7e9a4e08c2762abe92aad1370b1
4
- data.tar.gz: 9134e7d5c66bcbb25bb5fba15f5b1bb661ce18972cf91e179f165af52f955662
3
+ metadata.gz: f27830ef42bcbcec33a78126a3b47582fa394714e1d137e802cd5ab166e35df5
4
+ data.tar.gz: a111ed33a8345fe8dc5d43cb92206d52cbc47a03bc8e961baee8558d677542b6
5
5
  SHA512:
6
- metadata.gz: e361dc15e0a3496dadf81f91d356183631b1ad9f0b44951f976785622aa8550ccd0d8a6632064ab646a65231c4b772236cf1136b9267ceb81c59217d36bb4f78
7
- data.tar.gz: d82fd190746370c9ead45a27e5a660f81aafadf58736afd644d5fafad816daa450f25eebcf30d18875b185ab7d76b3215a696ed35bb75ad33509a474cff87736
6
+ metadata.gz: e14c6c1b74d4c13ebcbb4d1184d50257d6aacaf05e8e6708282633f61ea1988374156880d66bb26a037bf4b67b58381246f12357bdaa99ff9248db620d94c152
7
+ data.tar.gz: 34e766e6ca2374858ee6da35e924287641bc4441d8f642e4d08285a0066185aa865724567b90f91de34b17f340f3f182e9b3f326c5fc63bf6abc414c0dc058b3
data/CHANGELOG.md CHANGED
@@ -1,14 +1,32 @@
1
- # 0.6.0
1
+ # v0.7.0
2
+ - Rewrite the config parser/validation
3
+ - to provide clearer error messages with line numbers and everything
4
+ - to allow removing the json_schemer dependency with its 4 further dependencies
5
+ - 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.
6
+ - Add the possibility to quiet the `requires:` config, like:
7
+ ```yml
8
+ requires:
9
+ - 'active_support/inflections'
10
+ - quiet: './config/initializers/inflections'
11
+ ```
12
+ - consider all the public methods in rails custom generators to be used, this required some new features:
13
+ - add filtering methods/constants by public/protected/private
14
+ - add the possibility to set the privacy of methods and constants with method calls (`set_privacy:`, and `set_default_privacy:`)
15
+ - add `Method` and `Constant` as options for the `type:` filter
16
+ - add type filtering to dynamic.
17
+ - check `def self.whatever` as a definition, i didn't realise i wasn't checking this.
18
+
19
+ # v0.6.0
2
20
  - drop ruby 2.4 support, allowing for some performance improvements
3
21
  - Add ability to parse JSON and YAML files
4
22
  - Add magic comment that points to a particular dynamic rule
5
23
  - repeated calls to --write-todo won't have ordering differences
6
24
  - fix issue with --write-todo and unused methods defined in test files
7
25
 
8
- # 0.5.5
26
+ # v0.5.5
9
27
  - Fix rails resource/resources method signatures
10
28
 
11
- # 0.5.4
29
+ # v0.5.4
12
30
  - Add support for slim templates #13 - thanks @veganstraightedge
13
31
  - fix the #how-to-resolve link #11 - thanks @veganstraightedge
14
32
 
@@ -59,12 +59,17 @@ List filenames/paths that you want to include
59
59
  Unlike other `paths:` configuration, each entry is **not** the gitignore pattern format.
60
60
  Instead it is strings that can be passed directly to ruby's `require` method (relative paths should start with `./`).
61
61
 
62
- Missing files/gems will be a warning, but not a LoadError.
62
+ ```yml
63
+ require: ./config/initializers/my_other_inflections_file
64
+ ```
63
65
 
64
- By default, the default [`gems: active_support`]() config `require: activesupport` and `gems: rails` will `require: ./config/initializers/inflections`
66
+ Missing files/gems will be a warning, but not a LoadError.
67
+ To avoid seeing the warning if the file isn't there use `quiet:`.
65
68
 
66
69
  ```yml
67
- require: ./config/initializers/my_other_inflections_file
70
+ requires:
71
+ - 'active_support/inflections' # will warn if it's missing
72
+ - quiet: './config/initializers/inflections' # will say nothing
68
73
  ```
69
74
 
70
75
  Arrays are not necessary for single values
@@ -213,10 +218,12 @@ Each entry can be a string (an exact match for a method, constant, or variable n
213
218
  or the properties from `names:`
214
219
  - [`has_prefix:`](#has_prefix)
215
220
  - [`has_suffix:`](#has_suffix)
216
- - [`matches:`](#matches) (can't be used in the same entry as `has_prefix:` or `has_suffix:`)
221
+ - [`matches:`](#matches)
217
222
  - [`paths:`](#paths)
218
223
  - [`has_arguments:`](#has_arguments)
219
224
  - [`has_receiver:`](#has_receiver)
225
+ - [`type:`](#type)
226
+ - [`privacy:`](#privacy)
220
227
  - [`unless`](#unless)
221
228
 
222
229
  Arrays are not necessary for single values
@@ -242,7 +249,7 @@ Each entry can be a string (an exact match for a method, constant, or variable n
242
249
  or the properties from `names:`
243
250
  - [`has_prefix:`](#has_prefix)
244
251
  - [`has_suffix:`](#has_suffix)
245
- - [`matches:`](#matches) (can't be used in the same entry as `has_prefix:` or `has_suffix:`)
252
+ - [`matches:`](#matches)
246
253
  - [`paths:`](#paths)
247
254
  - [`has_arguments:`](#has_arguments)
248
255
  - [`unless`](#unless)
@@ -277,9 +284,11 @@ Each entry must have at least one of the following properties to restrict which
277
284
  - [`unless:`](#unless)
278
285
  - [`document: true`](#document-true)
279
286
 
280
- And must have one or both of
287
+ And must have at least one of
281
288
  - ['calls:`](#calls-defines)
282
289
  - [`defines:`](#calls-defines)
290
+ - [`set_privacy:](#set-privacy)
291
+ - [`set_default_privacy:`](#set-default-privacy)
283
292
 
284
293
  Arrays are not necessary for single values.
285
294
 
@@ -305,7 +314,7 @@ This is a list of methods/constants/variables, and can be used in [`dynamic:`](#
305
314
  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:
306
315
  - [`has_prefix:`](#has_prefix)
307
316
  - [`has_suffix:`](#has_suffix)
308
- - [`matches:`](#matches) (this can't be used in the same entry as `has_prefix:` or `has_suffix:`)
317
+ - [`matches:`](#matches)
309
318
 
310
319
  Arrays are not necessary for single values
311
320
 
@@ -402,7 +411,7 @@ and consider it to have created methods like `can_build_house?` and `can_drive_c
402
411
  ## `calls:`, `defines:`
403
412
  _aliases `call:`, `define:`_
404
413
 
405
- At least one of these must be used in each entry in [`dynamic:`](#dynamic)
414
+ These may be used as entries in [`dynamic:`](#dynamic)
406
415
 
407
416
  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.
408
417
 
@@ -454,6 +463,43 @@ dynamic:
454
463
  calls: 1
455
464
  ```
456
465
 
466
+ ## `set_privacy:`
467
+
468
+ Set privacy has the same requirements as [`calls:` & `defines:`](#calls-defines).
469
+
470
+ additional it requires a `to:` with one of either `private`, `public`, or `protected`.
471
+
472
+ For example, from the ruby config:
473
+ ```yml
474
+ dynamic:
475
+ name: private_class_method
476
+ has_argument: 0
477
+ set_privacy:
478
+ argument: '*'
479
+ to: private
480
+ ```
481
+
482
+ which sets all methods named by the arguments to the privacy_class_method method to private.
483
+
484
+ these methods could then be filtered using the [`privacy:`](#privacy) method in another [`dynamic:`](#dynamic) or [`keep:`](#keep) rule.
485
+
486
+ Leftovers limits this to only affect methods defined in the same file.
487
+
488
+ ## `set_default_privacy:`
489
+
490
+ 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))
491
+
492
+ For example, from the default ruby config:
493
+ ```yml
494
+ dynamic:
495
+ name: private
496
+ unless:
497
+ has_argument: 0
498
+ set_default_privacy: private
499
+ ```
500
+
501
+ these methods could then be filtered using the [`privacy:`](#privacy) method in another [`dynamic:`](#dynamic) or [`keep:`](#keep) rule.
502
+
457
503
  ## `arguments:`
458
504
  _alias `argument:`_
459
505
 
@@ -522,7 +568,7 @@ Each entry can be any of:
522
568
  - or have at least one of the following properties to match the keyword/hash key string or symbol:
523
569
  - [`has_prefix:`](#has_prefix)
524
570
  - [`has_suffix:`](#has_suffix)
525
- - [`matches:`](#matches) (this can't be used in the same entry as `has_prefix:` or `has_suffix:`)
571
+ - [`matches:`](#matches)
526
572
 
527
573
  Arrays are not necessary for single values
528
574
 
@@ -533,10 +579,10 @@ filter [`arguments:`](#arguments), [`has_arguments:`](#has_arguments), and [`key
533
579
  Each entry can be one of
534
580
  - `true`, `false`, `nil`, or an Integer. matches the literal value
535
581
  - a String. matches the literal string or symbol value
536
- - or have at least one of the following properties to match a string or symbol:
582
+ - or have at least one of the following properties to match the name:
537
583
  - [`has_prefix:`](#has_prefix)
538
584
  - [`has_suffix:`](#has_suffix)
539
- - [`matches:`](#matches) (this can't be used in the same entry as `has_prefix:` or `has_suffix:`)
585
+ - [`matches:`](#matches)
540
586
  - or have at least one of the following properties to match within an array or hash:
541
587
  - [`at`](#at)
542
588
  - [`has_value`](#has_value_has_receiver)
@@ -545,17 +591,35 @@ Each entry can be one of
545
591
  - or have the following property to match the receiver
546
592
  - [`has_receiver`](#has_value_has_receiver)
547
593
 
594
+ ## `privacy:`
595
+
596
+ filter [`dynamic:`](#dynamic) and [`keep:`](#keep) by method/constant privacy
597
+
598
+ e.g.
599
+
600
+ ```yml
601
+ keep:
602
+ - path: '**/generators/**/*_generator.rb'
603
+ privacy: public
604
+ type: Method
605
+ ```
606
+
607
+ considers all public methods defined in rails generators to be called.
608
+
548
609
  ## `type:`
549
610
 
550
- Filter [`has_value`](#has_value_has_receiver), by the argument/assigned value type
611
+ Filter by the literal type
551
612
 
552
613
  Each entry can be one of
553
- - `'String'`
554
- - `'Symbol'`
555
- - `'Integer'`
556
- - `'Float'`
557
- - `'Array'`
558
- - `'Hash'`
614
+ - `'String'` a literal string, defined with "" or '' (not String.new)
615
+ - `'Symbol'` a literal symbol
616
+ - `'Integer'` a literal integer
617
+ - `'Float'` a literal float
618
+ - `'Array'` a literal array defined with [] (not Array.new)
619
+ - `'Hash'` a literal hash, defined with {} (not Hash.new)
620
+ - `'Proc'` a literal proc/lambda, defined with lambda {}, proc {}, or -> {} (not Proc.new)
621
+ - `'Method'` a method call or definition defined with def, (not define_method {})
622
+ - `'Constant'` a constant assignment, or a literal module or class defined with keywords, (not Module/Class.new)
559
623
 
560
624
  Arrays are not necessary for single values
561
625
 
data/leftovers.gemspec CHANGED
@@ -35,6 +35,7 @@ Gem::Specification.new do |spec|
35
35
  spec.add_development_dependency 'activesupport'
36
36
  spec.add_development_dependency 'benchmark-ips'
37
37
  spec.add_development_dependency 'bundler', '~> 2.0'
38
+ spec.add_development_dependency 'did_you_mean'
38
39
  spec.add_development_dependency 'haml'
39
40
  spec.add_development_dependency 'pry', '~> 0.1'
40
41
  spec.add_development_dependency 'rake', '>= 13'
@@ -51,7 +52,6 @@ Gem::Specification.new do |spec|
51
52
 
52
53
  spec.add_development_dependency 'spellr', '>= 0.8.1'
53
54
  spec.add_dependency 'fast_ignore', '>= 0.15.1'
54
- spec.add_dependency 'json_schemer'
55
55
  spec.add_dependency 'parallel'
56
56
  spec.add_dependency 'parser'
57
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]
@@ -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/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
+
data/lib/config/ruby.yml CHANGED
@@ -98,3 +98,75 @@ dynamic:
98
98
  - instance_variable_set
99
99
  - class_variable_set
100
100
  defines: 0
101
+
102
+ # Module
103
+ - name: public
104
+ unless:
105
+ has_argument: 0
106
+ set_default_privacy: public
107
+
108
+ - name:
109
+ - public
110
+ - public_class_method
111
+ - public_constant
112
+ has_argument: 0
113
+ set_privacy:
114
+ argument: '*'
115
+ to: public
116
+
117
+ - name:
118
+ - public
119
+ - public_class_method
120
+ has_argument: 0
121
+ unless:
122
+ has_argument: 1
123
+ set_privacy:
124
+ argument: 0
125
+ nested:
126
+ argument: '*'
127
+ to: public
128
+
129
+ - name: protected
130
+ unless:
131
+ has_argument: 0
132
+ set_default_privacy: protected
133
+
134
+ - name: protected
135
+ has_argument: 0
136
+ set_privacy:
137
+ argument: '*'
138
+ to: protected
139
+
140
+ - name: protected
141
+ has_argument: 0
142
+ unless:
143
+ has_argument: 1
144
+ set_privacy:
145
+ argument: 0
146
+ nested:
147
+ argument: '*'
148
+ to: protected
149
+
150
+ - name: private
151
+ unless:
152
+ has_argument: 0
153
+ set_default_privacy: private
154
+
155
+ - name:
156
+ - private
157
+ - private_class_method
158
+ - private_constant
159
+ has_argument: 0
160
+ set_privacy:
161
+ argument: '*'
162
+ to: private
163
+
164
+ - name: private
165
+ has_argument: 0
166
+ unless:
167
+ has_argument: 1
168
+ set_privacy:
169
+ argument: 0
170
+ nested:
171
+ argument: '*'
172
+ to: private
@@ -25,14 +25,6 @@ module Leftovers
25
25
  @memo[:path] ||= loc.expression.source_buffer.name.to_s
26
26
  end
27
27
 
28
- def test_line?
29
- @memo[:test_line]
30
- end
31
-
32
- def test_line=(value)
33
- @memo[:test_line] = value
34
- end
35
-
36
28
  def keep_line=(value)
37
29
  @memo[:keep_line] = value
38
30
  end
@@ -41,6 +33,14 @@ module Leftovers
41
33
  @memo[:keep_line]
42
34
  end
43
35
 
36
+ def privacy=(value)
37
+ @memo[:privacy] = value
38
+ end
39
+
40
+ def privacy
41
+ @memo[:privacy] || :public
42
+ end
43
+
44
44
  def to_scalar_value
45
45
  case type
46
46
  when :sym, :int, :float, :str
@@ -58,7 +58,8 @@ module Leftovers
58
58
  case type
59
59
  when :sym, :int, :float, :str, :true, :false, :nil
60
60
  true
61
- else false
61
+ else
62
+ false
62
63
  end
63
64
  end
64
65
 
@@ -78,6 +79,10 @@ module Leftovers
78
79
  type == :str || type == :sym
79
80
  end
80
81
 
82
+ def string_or_symbol_or_def?
83
+ type == :str || type == :sym || type == :def || type == :defs
84
+ end
85
+
81
86
  def proc?
82
87
  return unless type == :block
83
88
 
@@ -140,9 +145,9 @@ module Leftovers
140
145
 
141
146
  def name
142
147
  @memo[:name] ||= case type
143
- when :send, :csend, :casgn, :const
148
+ when :send, :csend, :casgn, :const, :defs
144
149
  second
145
- when :def, :ivasgn, :ivar, :gvar, :cvar, :gvasgn, :cvasgn, :sym
150
+ when :def, :ivasgn, :ivar, :gvar, :cvar, :gvasgn, :cvasgn, :sym, :lvar
146
151
  first
147
152
  when :str
148
153
  first.to_sym
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'yaml'
4
-
5
3
  module Leftovers
6
4
  class Config
7
5
  attr_reader :name
@@ -66,29 +64,8 @@ module Leftovers
66
64
 
67
65
  private
68
66
 
69
- def content
70
- @content ||= ::File.exist?(path) ? ::File.read(path) : ''
71
- end
72
-
73
- def path
74
- @path ||= ::File.expand_path("../config/#{name}.yml", __dir__)
75
- end
76
-
77
67
  def yaml
78
- @yaml ||= ::Leftovers::ConfigValidator.validate_and_process!(parse_yaml, path)
79
- end
80
-
81
- def parse_yaml
82
- # :nocov:
83
- if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.6')
84
- Psych.safe_load(content, filename: path) || {}
85
- else
86
- Psych.safe_load(content, [], [], false, path) || {}
87
- end
88
- # :nocov:
89
- rescue ::Psych::SyntaxError => e
90
- warn "\e[31mConfig SyntaxError: #{e.message}\e[0m"
91
- Leftovers.exit 1
68
+ @yaml ||= ::Leftovers::ConfigLoader.load(name, path: @path, content: @content)
92
69
  end
93
70
  end
94
71
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class ConfigLoader
5
+ class ArgumentPositionSchema < ObjectSchema
6
+ inherit_attributes_from StringPatternSchema
7
+
8
+ self.or_schema = ScalarArgumentSchema
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class ConfigLoader
5
+ class ArgumentlessTransformSchema < StringEnumSchema
6
+ value :original
7
+ value :pluralize
8
+ value :singularize
9
+ value :camelize, aliases: :camelcase
10
+ value :underscore
11
+ value :titleize, aliases: :titlecase
12
+ value :demodulize
13
+ value :deconstantize
14
+ value :parameterize
15
+ value :downcase
16
+ value :upcase
17
+ value :capitalize
18
+ value :swapcase
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class ConfigLoader
5
+ class Attribute
6
+ def initialize(name, value_schema, aliases: nil, require_group: nil)
7
+ @name = name
8
+ @value_schema = value_schema
9
+ @aliases = aliases
10
+ @require_group = require_group
11
+ end
12
+
13
+ def attributes
14
+ { @name => @value_schema }
15
+ end
16
+
17
+ def aliases
18
+ ::Leftovers.each_or_self(@aliases).map do |aka|
19
+ [aka, @name]
20
+ end.to_h
21
+ end
22
+
23
+ def require_groups
24
+ return {} unless @require_group
25
+
26
+ { @require_group => [@name, *::Leftovers.each_or_self(@aliases)] }
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class ConfigLoader
5
+ class DocumentSchema < ObjectSchema
6
+ attribute :include_paths, ValueOrArraySchema[StringSchema], aliases: :include_path
7
+ attribute :exclude_paths, ValueOrArraySchema[StringSchema], aliases: :exclude_path
8
+ attribute :test_paths, ValueOrArraySchema[StringSchema], aliases: :test_path
9
+ attribute :haml_paths, ValueOrArraySchema[StringSchema], aliases: :haml_path
10
+ attribute :slim_paths, ValueOrArraySchema[StringSchema], aliases: :slim_path
11
+ attribute :yaml_paths, ValueOrArraySchema[StringSchema], aliases: :yaml_path
12
+ attribute :json_paths, ValueOrArraySchema[StringSchema], aliases: :json_path
13
+ attribute :erb_paths, ValueOrArraySchema[StringSchema], aliases: :erb_path
14
+ attribute :requires, ValueOrArraySchema[RequireSchema], aliases: :require
15
+ attribute :gems, ValueOrArraySchema[StringSchema], aliases: :gem
16
+ attribute :keep, ValueOrArraySchema[KeepTestOnlySchema]
17
+ attribute :test_only, ValueOrArraySchema[KeepTestOnlySchema]
18
+ attribute :dynamic, ValueOrArraySchema[DynamicSchema]
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class ConfigLoader
5
+ class DynamicSchema < ObjectSchema
6
+ inherit_attributes_from RulePatternSchema
7
+
8
+ attribute :call, ValueOrArraySchema[ValueProcessorSchema], aliases: :calls,
9
+ require_group: :processor
10
+ attribute :define, ValueOrArraySchema[ValueProcessorSchema], aliases: :defines,
11
+ require_group: :processor
12
+ attribute :set_privacy, ValueOrArraySchema[PrivacyProcessorSchema],
13
+ require_group: :processor
14
+ attribute :set_default_privacy, PrivacySchema, require_group: :processor
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class ConfigLoader
5
+ class HasArgumentSchema < ObjectSchema
6
+ attribute :at, ValueOrArraySchema[ArgumentPositionSchema], require_group: :matcher
7
+ attribute :has_value, ValueOrArraySchema[HasValueSchema], require_group: :matcher
8
+ attribute :unless, ValueOrArraySchema[HasArgumentSchema], require_group: :matcher
9
+
10
+ self.or_schema = ScalarArgumentSchema
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class ConfigLoader
5
+ class HasValueSchema < ObjectSchema
6
+ inherit_attributes_from StringPatternSchema, except: :unless
7
+
8
+ attribute :at, ValueOrArraySchema[ArgumentPositionSchema], require_group: :matcher
9
+ attribute :has_value, ValueOrArraySchema[HasValueSchema], require_group: :matcher
10
+
11
+ attribute :has_receiver, ValueOrArraySchema[HasValueSchema], require_group: :matcher
12
+ attribute :type, ValueOrArraySchema[ValueTypeSchema], require_group: :matcher
13
+ attribute :unless, ValueOrArraySchema[HasValueSchema], require_group: :matcher
14
+
15
+ self.or_schema = ScalarValueSchema
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class ConfigLoader
5
+ class KeepTestOnlySchema < ObjectSchema
6
+ inherit_attributes_from StringPatternSchema, except: :unless
7
+ inherit_attributes_from RulePatternSchema, except: :unless
8
+ attribute :unless, ValueOrArraySchema[KeepTestOnlySchema], require_group: :matcher
9
+
10
+ self.or_schema = StringSchema
11
+ end
12
+ end
13
+ end