leftovers 0.6.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (235) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +51 -3
  3. data/README.md +8 -7
  4. data/docs/Configuration.md +241 -105
  5. data/docs/Custom-Precompilers.md +44 -0
  6. data/leftovers.gemspec +3 -2
  7. data/lib/config/actioncable.yml +36 -4
  8. data/lib/config/actionmailbox.yml +28 -0
  9. data/lib/config/actionmailer.yml +92 -16
  10. data/lib/config/actionpack.yml +130 -32
  11. data/lib/config/actiontext.yml +56 -0
  12. data/lib/config/actionview.yml +194 -44
  13. data/lib/config/activejob.yml +15 -8
  14. data/lib/config/activemodel.yml +175 -18
  15. data/lib/config/activerecord.yml +397 -86
  16. data/lib/config/activestorage.yml +26 -0
  17. data/lib/config/activesupport.yml +168 -25
  18. data/lib/config/haml.yml +4 -2
  19. data/lib/config/leftovers.yml +48 -0
  20. data/lib/config/rails.yml +8 -4
  21. data/lib/config/railties.yml +18 -0
  22. data/lib/config/ruby.yml +473 -57
  23. data/lib/config/slim.yml +4 -2
  24. data/lib/config/test-unit.yml +8 -0
  25. data/lib/leftovers/ast/array_node.rb +12 -0
  26. data/lib/leftovers/ast/block_node.rb +12 -0
  27. data/lib/leftovers/ast/builder.rb +24 -5
  28. data/lib/leftovers/ast/casgn_node.rb +20 -0
  29. data/lib/leftovers/ast/const_node.rb +15 -0
  30. data/lib/leftovers/ast/def_node.rb +15 -0
  31. data/lib/leftovers/ast/defs_node.rb +15 -0
  32. data/lib/leftovers/ast/false_node.rb +24 -0
  33. data/lib/leftovers/ast/has_arguments.rb +31 -0
  34. data/lib/leftovers/ast/hash_node.rb +17 -0
  35. data/lib/leftovers/ast/module_node.rb +16 -0
  36. data/lib/leftovers/ast/nil_node.rb +23 -0
  37. data/lib/leftovers/ast/node.rb +39 -91
  38. data/lib/leftovers/ast/numeric_node.rb +22 -0
  39. data/lib/leftovers/ast/send_node.rb +25 -0
  40. data/lib/leftovers/ast/str_node.rb +24 -0
  41. data/lib/leftovers/ast/sym_node.rb +25 -0
  42. data/lib/leftovers/ast/true_node.rb +24 -0
  43. data/lib/leftovers/ast/var_node.rb +14 -0
  44. data/lib/leftovers/ast/vasgn_node.rb +20 -0
  45. data/lib/leftovers/ast.rb +18 -0
  46. data/lib/leftovers/cli.rb +12 -1
  47. data/lib/leftovers/collector.rb +2 -1
  48. data/lib/leftovers/comparable_instance.rb +18 -0
  49. data/lib/leftovers/config.rb +3 -42
  50. data/lib/leftovers/config_loader/argument_position_schema.rb +13 -0
  51. data/lib/leftovers/config_loader/argumentless_transform_schema.rb +21 -0
  52. data/lib/leftovers/config_loader/array_schema.rb +53 -0
  53. data/lib/leftovers/config_loader/attribute.rb +56 -0
  54. data/lib/leftovers/config_loader/built_in_precompiler_schema.rb +13 -0
  55. data/lib/leftovers/config_loader/document_schema.rb +49 -0
  56. data/lib/leftovers/config_loader/dynamic_schema.rb +18 -0
  57. data/lib/leftovers/config_loader/has_argument_schema.rb +13 -0
  58. data/lib/leftovers/config_loader/has_value_schema.rb +22 -0
  59. data/lib/leftovers/config_loader/inherit_schema_attributes.rb +22 -0
  60. data/lib/leftovers/config_loader/keep_test_only_schema.rb +13 -0
  61. data/lib/leftovers/config_loader/keyword_argument_schema.rb +13 -0
  62. data/lib/leftovers/config_loader/node.rb +106 -0
  63. data/lib/leftovers/config_loader/object_schema.rb +117 -0
  64. data/lib/leftovers/config_loader/precompile_schema.rb +12 -0
  65. data/lib/leftovers/config_loader/precompiler_schema.rb +11 -0
  66. data/lib/leftovers/config_loader/privacy_processor_schema.rb +10 -0
  67. data/lib/leftovers/config_loader/privacy_schema.rb +15 -0
  68. data/lib/leftovers/config_loader/regexp_schema.rb +27 -0
  69. data/lib/leftovers/config_loader/require_schema.rb +11 -0
  70. data/lib/leftovers/config_loader/rule_pattern_schema.rb +20 -0
  71. data/lib/leftovers/config_loader/scalar_argument_schema.rb +14 -0
  72. data/lib/leftovers/config_loader/scalar_value_schema.rb +22 -0
  73. data/lib/leftovers/config_loader/schema.rb +33 -0
  74. data/lib/leftovers/config_loader/string_enum_schema.rb +62 -0
  75. data/lib/leftovers/config_loader/string_pattern_schema.rb +14 -0
  76. data/lib/leftovers/config_loader/string_schema.rb +14 -0
  77. data/lib/leftovers/config_loader/string_value_processor_schema.rb +11 -0
  78. data/lib/leftovers/config_loader/suggester.rb +22 -0
  79. data/lib/leftovers/config_loader/transform_schema.rb +32 -0
  80. data/lib/leftovers/config_loader/true_schema.rb +18 -0
  81. data/lib/leftovers/config_loader/value_matcher_condition_schema.rb +13 -0
  82. data/lib/leftovers/config_loader/value_matcher_schema.rb +21 -0
  83. data/lib/leftovers/config_loader/value_or_array_schema.rb +34 -0
  84. data/lib/leftovers/config_loader/value_or_object_schema.rb +40 -0
  85. data/lib/leftovers/config_loader/value_processor_schema.rb +14 -0
  86. data/lib/leftovers/config_loader/value_type_schema.rb +17 -0
  87. data/lib/leftovers/config_loader.rb +93 -0
  88. data/lib/leftovers/definition_collection.rb +37 -0
  89. data/lib/leftovers/definition_node.rb +6 -17
  90. data/lib/leftovers/definition_node_set.rb +19 -0
  91. data/lib/leftovers/definition_to_add.rb +31 -0
  92. data/lib/leftovers/file.rb +13 -55
  93. data/lib/leftovers/file_collector/comments_processor.rb +57 -0
  94. data/lib/leftovers/file_collector/node_processor.rb +131 -0
  95. data/lib/leftovers/file_collector.rb +62 -202
  96. data/lib/leftovers/file_list.rb +3 -2
  97. data/lib/leftovers/matcher_builders/and.rb +26 -9
  98. data/lib/leftovers/matcher_builders/and_not.rb +7 -5
  99. data/lib/leftovers/matcher_builders/name.rb +18 -17
  100. data/lib/leftovers/matcher_builders/node.rb +60 -30
  101. data/lib/leftovers/matcher_builders/node_has_argument.rb +48 -52
  102. data/lib/leftovers/matcher_builders/node_has_keyword_argument.rb +16 -11
  103. data/lib/leftovers/matcher_builders/node_has_positional_argument.rb +29 -15
  104. data/lib/leftovers/matcher_builders/node_pair_key.rb +16 -0
  105. data/lib/leftovers/matcher_builders/node_privacy.rb +13 -0
  106. data/lib/leftovers/matcher_builders/node_type.rb +11 -11
  107. data/lib/leftovers/matcher_builders/node_value.rb +44 -25
  108. data/lib/leftovers/matcher_builders/or.rb +64 -49
  109. data/lib/leftovers/matcher_builders/path.rb +3 -1
  110. data/lib/leftovers/matcher_builders/string_pattern.rb +14 -5
  111. data/lib/leftovers/matcher_builders.rb +2 -1
  112. data/lib/leftovers/matchers/all.rb +4 -0
  113. data/lib/leftovers/matchers/and.rb +4 -0
  114. data/lib/leftovers/matchers/any.rb +2 -0
  115. data/lib/leftovers/matchers/node_has_any_keyword_argument.rb +7 -4
  116. data/lib/leftovers/matchers/node_has_any_positional_argument_with_value.rb +5 -4
  117. data/lib/leftovers/matchers/node_has_positional_argument.rb +5 -1
  118. data/lib/leftovers/matchers/node_has_positional_argument_with_value.rb +6 -1
  119. data/lib/leftovers/matchers/node_has_receiver.rb +4 -0
  120. data/lib/leftovers/matchers/node_is_proc.rb +13 -0
  121. data/lib/leftovers/matchers/node_name.rb +9 -3
  122. data/lib/leftovers/matchers/node_pair_key.rb +23 -0
  123. data/lib/leftovers/matchers/node_pair_value.rb +7 -3
  124. data/lib/leftovers/matchers/node_path.rb +7 -3
  125. data/lib/leftovers/matchers/node_privacy.rb +23 -0
  126. data/lib/leftovers/matchers/node_scalar_value.rb +6 -1
  127. data/lib/leftovers/matchers/node_type.rb +7 -3
  128. data/lib/leftovers/matchers/not.rb +2 -0
  129. data/lib/leftovers/matchers/or.rb +2 -0
  130. data/lib/leftovers/matchers/path.rb +21 -0
  131. data/lib/leftovers/matchers.rb +4 -1
  132. data/lib/leftovers/merged_config.rb +40 -75
  133. data/lib/leftovers/parser.rb +7 -4
  134. data/lib/leftovers/precompilers/erb.rb +22 -0
  135. data/lib/leftovers/precompilers/haml.rb +15 -0
  136. data/lib/leftovers/precompilers/json.rb +27 -0
  137. data/lib/leftovers/precompilers/precompiler.rb +28 -0
  138. data/lib/leftovers/precompilers/slim.rb +15 -0
  139. data/lib/leftovers/precompilers/yaml.rb +75 -0
  140. data/lib/leftovers/precompilers.rb +50 -0
  141. data/lib/leftovers/processor_builders/action.rb +69 -42
  142. data/lib/leftovers/processor_builders/add_prefix.rb +18 -10
  143. data/lib/leftovers/processor_builders/add_suffix.rb +18 -10
  144. data/lib/leftovers/processor_builders/argument.rb +28 -14
  145. data/lib/leftovers/processor_builders/dynamic.rb +57 -17
  146. data/lib/leftovers/processor_builders/each.rb +83 -11
  147. data/lib/leftovers/processor_builders/itself.rb +2 -2
  148. data/lib/leftovers/processor_builders/keyword.rb +9 -9
  149. data/lib/leftovers/processor_builders/keyword_argument.rb +4 -2
  150. data/lib/leftovers/processor_builders/receiver.rb +13 -0
  151. data/lib/leftovers/processor_builders/transform.rb +55 -44
  152. data/lib/leftovers/processor_builders/transform_chain.rb +16 -8
  153. data/lib/leftovers/processor_builders/transform_set.rb +16 -32
  154. data/lib/leftovers/processor_builders/value.rb +4 -4
  155. data/lib/leftovers/processor_builders.rb +1 -3
  156. data/lib/leftovers/processors/add_call.rb +14 -0
  157. data/lib/leftovers/processors/add_definition_node.rb +16 -0
  158. data/lib/leftovers/processors/add_dynamic_prefix.rb +29 -0
  159. data/lib/leftovers/processors/add_dynamic_suffix.rb +29 -0
  160. data/lib/leftovers/{value_processors → processors}/add_prefix.rb +7 -3
  161. data/lib/leftovers/{value_processors → processors}/add_suffix.rb +7 -3
  162. data/lib/leftovers/processors/append_sym.rb +13 -0
  163. data/lib/leftovers/{value_processors → processors}/camelize.rb +7 -3
  164. data/lib/leftovers/{value_processors → processors}/capitalize.rb +7 -3
  165. data/lib/leftovers/{value_processors → processors}/deconstantize.rb +7 -3
  166. data/lib/leftovers/{value_processors → processors}/delete_after.rb +9 -5
  167. data/lib/leftovers/processors/delete_after_last.rb +26 -0
  168. data/lib/leftovers/processors/delete_before.rb +27 -0
  169. data/lib/leftovers/processors/delete_before_last.rb +27 -0
  170. data/lib/leftovers/{value_processors → processors}/delete_prefix.rb +7 -3
  171. data/lib/leftovers/{value_processors → processors}/delete_suffix.rb +7 -3
  172. data/lib/leftovers/{value_processors → processors}/demodulize.rb +7 -3
  173. data/lib/leftovers/{value_processors → processors}/downcase.rb +7 -3
  174. data/lib/leftovers/processors/each.rb +25 -0
  175. data/lib/leftovers/processors/each_for_definition_set.rb +33 -0
  176. data/lib/leftovers/processors/each_keyword.rb +29 -0
  177. data/lib/leftovers/processors/each_keyword_argument.rb +29 -0
  178. data/lib/leftovers/processors/each_positional_argument.rb +27 -0
  179. data/lib/leftovers/processors/each_positional_argument_from.rb +30 -0
  180. data/lib/leftovers/processors/eval.rb +16 -0
  181. data/lib/leftovers/processors/itself.rb +21 -0
  182. data/lib/leftovers/{value_processors → processors}/keyword_argument.rb +9 -11
  183. data/lib/leftovers/processors/match_current_node.rb +26 -0
  184. data/lib/leftovers/processors/match_matched_node.rb +26 -0
  185. data/lib/leftovers/{value_processors → processors}/parameterize.rb +7 -3
  186. data/lib/leftovers/{value_processors → processors}/placeholder.rb +5 -4
  187. data/lib/leftovers/{value_processors → processors}/pluralize.rb +7 -3
  188. data/lib/leftovers/{value_processors → processors}/positional_argument.rb +8 -6
  189. data/lib/leftovers/processors/receiver.rb +24 -0
  190. data/lib/leftovers/{value_processors → processors}/replace_value.rb +7 -3
  191. data/lib/leftovers/processors/set_default_privacy.rb +21 -0
  192. data/lib/leftovers/processors/set_privacy.rb +23 -0
  193. data/lib/leftovers/{value_processors → processors}/singularize.rb +7 -3
  194. data/lib/leftovers/{value_processors → processors}/split.rb +8 -4
  195. data/lib/leftovers/{value_processors → processors}/swapcase.rb +7 -3
  196. data/lib/leftovers/{value_processors → processors}/titleize.rb +7 -3
  197. data/lib/leftovers/{value_processors → processors}/underscore.rb +7 -3
  198. data/lib/leftovers/{value_processors → processors}/upcase.rb +7 -3
  199. data/lib/leftovers/processors.rb +49 -0
  200. data/lib/leftovers/rake_task.rb +1 -1
  201. data/lib/leftovers/version.rb +1 -1
  202. data/lib/leftovers.rb +55 -20
  203. metadata +159 -72
  204. data/lib/leftovers/config_validator/error_processor.rb +0 -196
  205. data/lib/leftovers/config_validator/schema_hash.rb +0 -551
  206. data/lib/leftovers/config_validator.rb +0 -61
  207. data/lib/leftovers/dynamic_processors/call.rb +0 -21
  208. data/lib/leftovers/dynamic_processors/call_definition.rb +0 -27
  209. data/lib/leftovers/dynamic_processors/definition.rb +0 -22
  210. data/lib/leftovers/dynamic_processors/each.rb +0 -19
  211. data/lib/leftovers/dynamic_processors/null.rb +0 -9
  212. data/lib/leftovers/dynamic_processors.rb +0 -11
  213. data/lib/leftovers/erb.rb +0 -20
  214. data/lib/leftovers/haml.rb +0 -21
  215. data/lib/leftovers/json.rb +0 -28
  216. data/lib/leftovers/matcher_builders/node_pair_name.rb +0 -18
  217. data/lib/leftovers/matchers/predicate.rb +0 -19
  218. data/lib/leftovers/processor_builders/each_action.rb +0 -51
  219. data/lib/leftovers/processor_builders/each_dynamic.rb +0 -54
  220. data/lib/leftovers/processor_builders/each_for_definition_set.rb +0 -36
  221. data/lib/leftovers/slim.rb +0 -21
  222. data/lib/leftovers/value_processors/add_dynamic_prefix.rb +0 -31
  223. data/lib/leftovers/value_processors/add_dynamic_suffix.rb +0 -31
  224. data/lib/leftovers/value_processors/delete_before.rb +0 -22
  225. data/lib/leftovers/value_processors/each.rb +0 -21
  226. data/lib/leftovers/value_processors/each_for_definition_set.rb +0 -29
  227. data/lib/leftovers/value_processors/each_keyword.rb +0 -27
  228. data/lib/leftovers/value_processors/each_keyword_argument.rb +0 -27
  229. data/lib/leftovers/value_processors/each_positional_argument.rb +0 -24
  230. data/lib/leftovers/value_processors/itself.rb +0 -17
  231. data/lib/leftovers/value_processors/keyword.rb +0 -32
  232. data/lib/leftovers/value_processors/return_definition.rb +0 -22
  233. data/lib/leftovers/value_processors/return_string.rb +0 -14
  234. data/lib/leftovers/value_processors.rb +0 -40
  235. data/lib/leftovers/yaml.rb +0 -73
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class ConfigLoader
5
+ class Schema
6
+ class << self
7
+ def error(node, requirement)
8
+ node.error = "#{node.name_}must #{requirement}"
9
+
10
+ false
11
+ end
12
+
13
+ def validate(node)
14
+ node.valid?
15
+ end
16
+
17
+ def to_ruby(node)
18
+ node.to_ruby
19
+ end
20
+
21
+ def ===(other) # leftovers:test_only
22
+ # :nocov:
23
+ if other.is_a?(Module)
24
+ self >= other
25
+ else
26
+ other.is_a?(self)
27
+ end
28
+ # :nocov:
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class ConfigLoader
5
+ class StringEnumSchema < Schema
6
+ class << self
7
+ def value(value, aliases: nil)
8
+ values << value
9
+ Leftovers.each_or_self(aliases) do |alias_name|
10
+ self.aliases[alias_name] = value
11
+ end
12
+ end
13
+
14
+ def aliases
15
+ @aliases ||= {}
16
+ end
17
+
18
+ def aliases_for(value)
19
+ aliases.select { |_k, v| v == value }.keys
20
+ end
21
+
22
+ def values
23
+ @values ||= []
24
+ end
25
+
26
+ def each_value(&block)
27
+ @values.each(&block)
28
+ end
29
+
30
+ def to_ruby(node)
31
+ aliases[node.to_sym] || node.to_sym
32
+ end
33
+
34
+ def validate(node)
35
+ if node.string?
36
+ node.error = error_message_with_suggestions(node) unless valid_value?(node.to_sym)
37
+ else
38
+ error(node, 'be a string')
39
+ end
40
+
41
+ super
42
+ end
43
+
44
+ private
45
+
46
+ def valid_value?(val)
47
+ values.include?(val) || aliases.key?(val)
48
+ end
49
+
50
+ def suggester
51
+ @suggester ||= Suggester.new(values)
52
+ end
53
+
54
+ def error_message_with_suggestions(node)
55
+ suggestions = suggester.suggest(node.to_ruby)
56
+
57
+ "unrecognized value #{node} for #{node.name}\nDid you mean: #{suggestions.join(', ')}"
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class ConfigLoader
5
+ class StringPatternSchema < ValueOrObjectSchema
6
+ attribute :match, RegexpSchema, aliases: :matches, require_group: :matcher
7
+ attribute :has_prefix, StringSchema, require_group: :matcher
8
+ attribute :has_suffix, StringSchema, require_group: :matcher
9
+ attribute :unless, ValueOrArraySchema[StringPatternSchema], require_group: :matcher
10
+
11
+ self.or_value_schema = StringSchema
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class ConfigLoader
5
+ class StringSchema < Schema
6
+ class << self
7
+ def validate(node)
8
+ error(node, 'be a string') unless node.string?
9
+ super
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class ConfigLoader
5
+ class StringValueProcessorSchema < ValueOrObjectSchema
6
+ inherit_attributes_from ValueProcessorSchema
7
+
8
+ self.or_value_schema = StringSchema
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class ConfigLoader
5
+ class Suggester
6
+ def initialize(words)
7
+ @words = words
8
+ @did_you_mean = ::DidYouMean::SpellChecker.new(dictionary: words) if defined?(::DidYouMean)
9
+ end
10
+
11
+ def suggest(word)
12
+ suggestions = did_you_mean.correct(word) if did_you_mean
13
+ suggestions = words if !suggestions || suggestions.empty?
14
+ suggestions
15
+ end
16
+
17
+ private
18
+
19
+ attr_reader :words, :did_you_mean
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class ConfigLoader
5
+ class TransformSchema < ValueOrObjectSchema
6
+ ArgumentlessTransformSchema.each_value do |transform|
7
+ attribute(
8
+ transform, TrueSchema,
9
+ aliases: ArgumentlessTransformSchema.aliases_for(transform),
10
+ require_group: :processor
11
+ )
12
+ end
13
+
14
+ attribute :add_prefix, ValueOrArraySchema[StringValueProcessorSchema],
15
+ require_group: :processor
16
+ attribute :add_suffix, ValueOrArraySchema[StringValueProcessorSchema],
17
+ require_group: :processor
18
+
19
+ attribute :split, StringSchema, require_group: :processor
20
+ attribute :delete_prefix, ValueOrArraySchema[StringSchema], require_group: :processor
21
+ attribute :delete_suffix, ValueOrArraySchema[StringSchema], require_group: :processor
22
+ attribute :delete_before, ValueOrArraySchema[StringSchema], require_group: :processor
23
+ attribute :delete_before_last, ValueOrArraySchema[StringSchema], require_group: :processor
24
+ attribute :delete_after, ValueOrArraySchema[StringSchema], require_group: :processor
25
+ attribute :delete_after_last, ValueOrArraySchema[StringSchema], require_group: :processor
26
+ attribute :transforms, ValueOrArraySchema[TransformSchema], require_group: :processor,
27
+ aliases: :transform
28
+
29
+ self.or_value_schema = ArgumentlessTransformSchema
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class ConfigLoader
5
+ class TrueSchema < Schema
6
+ class << self
7
+ def validate(node)
8
+ error(node, 'be true') unless to_ruby(node)
9
+ super
10
+ end
11
+
12
+ def to_ruby(node)
13
+ node.to_ruby == true || node.to_ruby == 'true'
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class ConfigLoader
5
+ class ValueMatcherConditionSchema < ObjectSchema
6
+ attribute :has_arguments, ValueOrArraySchema[HasArgumentSchema], aliases: :has_argument
7
+ attribute :has_receiver, ValueOrArraySchema[HasValueSchema]
8
+ attribute :unless, ValueOrArraySchema[ValueMatcherConditionSchema]
9
+ attribute :all, ArraySchema[ValueMatcherConditionSchema]
10
+ attribute :any, ArraySchema[ValueMatcherConditionSchema]
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class ConfigLoader
5
+ class ValueMatcherSchema < ValueOrObjectSchema
6
+ attribute :arguments, ValueOrArraySchema[ArgumentPositionSchema], aliases: :argument,
7
+ require_group: :matcher
8
+ attribute :keywords, ValueOrArraySchema[StringPatternSchema], aliases: :keyword,
9
+ require_group: :matcher
10
+ attribute :itself, TrueSchema, require_group: :matcher
11
+ attribute :nested, ValueOrArraySchema[ValueMatcherSchema]
12
+ attribute :value, ValueOrArraySchema[StringSchema], require_group: :matcher, aliases: :values
13
+ attribute :receiver, TrueSchema, require_group: :matcher
14
+ attribute :recursive, TrueSchema
15
+
16
+ inherit_attributes_from ValueMatcherConditionSchema
17
+
18
+ self.or_value_schema = ScalarArgumentSchema
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class ConfigLoader
5
+ class ValueOrArraySchema < ArraySchema
6
+ def validate(node)
7
+ if node.array?
8
+ validate_length(node) && validate_values(node)
9
+ else
10
+ validate_or_schema(node)
11
+ end
12
+ end
13
+
14
+ def to_ruby(node)
15
+ if node.array?
16
+ Leftovers.unwrap_array(super)
17
+ else
18
+ value_schema.to_ruby(node)
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def validate_or_schema(node)
25
+ value_schema.validate(node)
26
+ return true if node.valid?
27
+
28
+ node.error += ' or an array'
29
+
30
+ false
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class ConfigLoader
5
+ class ValueOrObjectSchema < ObjectSchema
6
+ class << self
7
+ attr_accessor :or_value_schema
8
+
9
+ def validate(node)
10
+ if node.hash?
11
+ super(node)
12
+ else
13
+ validate_or_value_schema(node)
14
+ end
15
+ end
16
+
17
+ def to_ruby(node)
18
+ if node.hash?
19
+ super
20
+ else
21
+ or_value_schema.to_ruby(node)
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def validate_or_value_schema(node)
28
+ or_value_schema.validate(node)
29
+ return true if node.valid?
30
+
31
+ if node.string? && attribute_for_key(node)
32
+ node.error = "#{node.name_}#{node.to_sym} must be a hash key"
33
+ else
34
+ node.error += " or a hash with any of #{suggestions.join(', ')}"
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class ConfigLoader
5
+ class ValueProcessorSchema < ValueOrObjectSchema
6
+ inherit_attributes_from ValueMatcherSchema
7
+
8
+ attribute :transforms, ValueOrArraySchema[TransformSchema], aliases: :transform
9
+ inherit_attributes_from TransformSchema, require_group: nil, except: :transforms
10
+
11
+ self.or_value_schema = ScalarArgumentSchema
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class ConfigLoader
5
+ class ValueTypeSchema < StringEnumSchema
6
+ value :String
7
+ value :Symbol
8
+ value :Integer
9
+ value :Float
10
+ value :Array
11
+ value :Hash
12
+ value :Proc
13
+ value :Method
14
+ value :Constant
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,93 @@
1
+ # frozen-string-literal: true
2
+
3
+ require 'yaml'
4
+
5
+ module Leftovers
6
+ class ConfigLoader
7
+ autoload(:ArgumentlessTransformSchema, "#{__dir__}/config_loader/argumentless_transform_schema")
8
+ autoload(:ArgumentPositionSchema, "#{__dir__}/config_loader/argument_position_schema")
9
+ autoload(:ArraySchema, "#{__dir__}/config_loader/array_schema")
10
+ autoload(:Attribute, "#{__dir__}/config_loader/attribute")
11
+ autoload(:BuiltInPrecompilerSchema, "#{__dir__}/config_loader/built_in_precompiler_schema")
12
+ autoload(:DocumentSchema, "#{__dir__}/config_loader/document_schema")
13
+ autoload(:DynamicSchema, "#{__dir__}/config_loader/dynamic_schema")
14
+ autoload(:HasArgumentSchema, "#{__dir__}/config_loader/has_argument_schema")
15
+ autoload(:HasValueSchema, "#{__dir__}/config_loader/has_value_schema")
16
+ autoload(:InheritSchemaAttributes, "#{__dir__}/config_loader/inherit_schema_attributes")
17
+ autoload(:KeepTestOnlySchema, "#{__dir__}/config_loader/keep_test_only_schema")
18
+ autoload(:KeywordArgumentSchema, "#{__dir__}/config_loader/keyword_argument_schema")
19
+ autoload(:Node, "#{__dir__}/config_loader/node")
20
+ autoload(:ObjectSchema, "#{__dir__}/config_loader/object_schema")
21
+ autoload(:PrecompilerSchema, "#{__dir__}/config_loader/precompiler_schema")
22
+ autoload(:PrecompileSchema, "#{__dir__}/config_loader/precompile_schema")
23
+ autoload(:PrivacyProcessorSchema, "#{__dir__}/config_loader/privacy_processor_schema")
24
+ autoload(:PrivacySchema, "#{__dir__}/config_loader/privacy_schema")
25
+ autoload(:RegexpSchema, "#{__dir__}/config_loader/regexp_schema")
26
+ autoload(:RequireSchema, "#{__dir__}/config_loader/require_schema")
27
+ autoload(:RulePatternSchema, "#{__dir__}/config_loader/rule_pattern_schema")
28
+ autoload(:ScalarArgumentSchema, "#{__dir__}/config_loader/scalar_argument_schema")
29
+ autoload(:ScalarValueSchema, "#{__dir__}/config_loader/scalar_value_schema")
30
+ autoload(:Schema, "#{__dir__}/config_loader/schema")
31
+ autoload(:StringEnumSchema, "#{__dir__}/config_loader/string_enum_schema")
32
+ autoload(:StringPatternSchema, "#{__dir__}/config_loader/string_pattern_schema")
33
+ autoload(:StringSchema, "#{__dir__}/config_loader/string_schema")
34
+ autoload(:StringValueProcessorSchema, "#{__dir__}/config_loader/string_value_processor_schema")
35
+ autoload(:Suggester, "#{__dir__}/config_loader/suggester")
36
+ autoload(:TransformSchema, "#{__dir__}/config_loader/transform_schema")
37
+ autoload(:TrueSchema, "#{__dir__}/config_loader/true_schema")
38
+ autoload(
39
+ :ValueMatcherConditionSchema,
40
+ "#{__dir__}/config_loader/value_matcher_condition_schema"
41
+ )
42
+ autoload(:ValueMatcherSchema, "#{__dir__}/config_loader/value_matcher_schema")
43
+ autoload(:ValueOrArraySchema, "#{__dir__}/config_loader/value_or_array_schema")
44
+ autoload(:ValueOrObjectSchema, "#{__dir__}/config_loader/value_or_object_schema")
45
+ autoload(:ValueProcessorSchema, "#{__dir__}/config_loader/value_processor_schema")
46
+ autoload(:ValueTypeSchema, "#{__dir__}/config_loader/value_type_schema")
47
+
48
+ def self.load(name, path: nil, content: nil)
49
+ new(name, path: path, content: content).load
50
+ end
51
+
52
+ attr_reader :name
53
+
54
+ def initialize(name, path: nil, content: nil)
55
+ @name = name
56
+ @path = path
57
+ @content = content
58
+ end
59
+
60
+ def load
61
+ document = ::Leftovers::ConfigLoader::Node.new(parse, file)
62
+ DocumentSchema.validate(document)
63
+
64
+ all_errors = document.all_errors
65
+ return DocumentSchema.to_ruby(document) if all_errors.empty?
66
+
67
+ Leftovers.error(all_errors.join("\n"))
68
+ end
69
+
70
+ private
71
+
72
+ def path
73
+ @path ||= ::File.expand_path("../config/#{name}.yml", __dir__)
74
+ end
75
+
76
+ def file
77
+ @file ||= ::Leftovers::File.new(path)
78
+ end
79
+
80
+ def content
81
+ @content ||= file.exist? ? file.read : ''
82
+ end
83
+
84
+ def parse
85
+ parsed = Psych.parse(content)
86
+ parsed ||= Psych.parse('{}')
87
+ parsed.children.first
88
+ rescue ::Psych::SyntaxError => e
89
+ message = [e.problem, e.context].compact.join(' ')
90
+ Leftovers.error "Config SyntaxError: #{file.relative_path}:#{e.line}:#{e.column} #{message}"
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class DefinitionCollection
5
+ def initialize
6
+ @definitions_to_add = {}
7
+ @definition_sets_to_add = []
8
+ end
9
+
10
+ def add_definition_node(definition_node)
11
+ add(definition_node, loc: definition_node.loc)
12
+ end
13
+
14
+ def add(node, name: node.name, loc: node.loc.name)
15
+ @definitions_to_add[name] = ::Leftovers::DefinitionToAdd.new(node, name: name, location: loc)
16
+ end
17
+
18
+ def add_definition_set(definition_node_set)
19
+ @definition_sets_to_add << definition_node_set.definitions.map do |definition_node|
20
+ ::Leftovers::DefinitionToAdd.new(definition_node, location: definition_node.loc)
21
+ end
22
+ end
23
+
24
+ def set_privacy(name, to)
25
+ @definitions_to_add[name]&.privacy = to
26
+ end
27
+
28
+ def to_definitions(file_collector)
29
+ @definitions_to_add.each_value.map { |d| d.to_definition(file_collector) } +
30
+ @definition_sets_to_add.map do |definition_set|
31
+ next if definition_set.any? { |d| d.keep?(file_collector) }
32
+
33
+ ::Leftovers::DefinitionSet.new(definition_set.map { |d| d.to_definition(file_collector) })
34
+ end
35
+ end
36
+ end
37
+ end
@@ -1,19 +1,15 @@
1
1
  # frozen-string-literal: true
2
2
 
3
- # To give to matchers before creating a Definition
4
-
5
3
  module Leftovers
6
4
  class DefinitionNode
7
- attr_reader :path, :name
5
+ attr_reader :name, :loc, :node
8
6
 
9
- def initialize(name, path)
7
+ def initialize(node, name:, location: node.loc.expression)
8
+ @node = node
10
9
  @name = name
11
- @path = path
12
-
13
- freeze
10
+ @loc = location
14
11
  end
15
12
 
16
- # these are the methods checked by things in lib/leftovers/matchers
17
13
  def kwargs
18
14
  nil
19
15
  end
@@ -22,15 +18,8 @@ module Leftovers
22
18
  nil
23
19
  end
24
20
 
25
- # these two i'm not sure are possible with the current config flags
26
- # :nocov:
27
- def scalar?
28
- false
29
- end
30
-
31
- def type
32
- :leftovers_definition
21
+ def path
22
+ node.path
33
23
  end
34
- # :nocov:
35
24
  end
36
25
  end
@@ -0,0 +1,19 @@
1
+ # frozen-string-literal: true
2
+
3
+ module Leftovers
4
+ class DefinitionNodeSet
5
+ attr_reader :definitions
6
+
7
+ def initialize
8
+ @definitions = []
9
+ end
10
+
11
+ def add_definition_node(definition_node)
12
+ @definitions << definition_node
13
+ end
14
+
15
+ def add_definition_set(definition_node_set)
16
+ @definitions.concat(definition_node_set.definitions)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,31 @@
1
+ # frozen-string-literal: true
2
+
3
+ module Leftovers
4
+ class DefinitionToAdd
5
+ attr_reader :node, :name, :location
6
+
7
+ def initialize(node, name: node.name, location: node.loc.name)
8
+ @node = node
9
+ @name = name
10
+ @location = location
11
+ end
12
+
13
+ def privacy=(value)
14
+ @node.privacy = value
15
+ end
16
+
17
+ def keep?(file_collector)
18
+ @keep ||= file_collector.keep_line?(location.line) || ::Leftovers.config.keep === node
19
+ end
20
+
21
+ def test?(file_collector)
22
+ file_collector.test_line?(location.line) || ::Leftovers.config.test_only === node
23
+ end
24
+
25
+ def to_definition(file_collector)
26
+ return if keep?(file_collector)
27
+
28
+ Leftovers::Definition.new(name, location: location, test: test?(file_collector))
29
+ end
30
+ end
31
+ end
@@ -5,71 +5,29 @@ require 'pathname'
5
5
  module Leftovers
6
6
  class File < Pathname
7
7
  def relative_path
8
- @relative_path ||= relative_path_from(Leftovers.pwd)
8
+ @relative_path ||= begin
9
+ relative_path_from(Leftovers.pwd)
10
+ rescue ArgumentError
11
+ self
12
+ end
9
13
  end
10
14
 
11
15
  def test?
12
16
  return @test if defined?(@test)
13
17
 
14
- @test = Leftovers.config.test_paths.allowed?(relative_path)
18
+ @test = Leftovers.config.test_paths === relative_path
15
19
  end
16
20
 
17
- def ruby # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
18
- precompiled = []
19
- precompile = false
20
-
21
- if haml?
22
- precompiled << ::Leftovers::Haml.precompile(read, self)
23
- precompile = true
24
- end
25
-
26
- if json?
27
- precompiled << ::Leftovers::JSON.precompile(read, self)
28
- precompile = true
29
- end
21
+ def ruby
22
+ read = self.read
30
23
 
31
- if erb?
32
- precompiled << ::Leftovers::ERB.precompile(read, self)
33
- precompile = true
34
- end
24
+ precompiled = ::Leftovers.config.precompilers.map do |precompiler|
25
+ precompiler.precompile(read, self)
26
+ end.compact
35
27
 
36
- if slim?
37
- precompiled << ::Leftovers::Slim.precompile(read, self)
38
- precompile = true
39
- end
40
-
41
- if yaml?
42
- precompiled << ::Leftovers::YAML.precompile(read, self)
43
- precompile = true
44
- end
45
-
46
- if precompile
47
- precompiled.join("\n")
48
- else
49
- read
50
- end
51
- end
52
-
53
- private
54
-
55
- def erb?
56
- Leftovers.config.erb_paths.allowed?(relative_path)
57
- end
58
-
59
- def haml?
60
- Leftovers.config.haml_paths.allowed?(relative_path)
61
- end
62
-
63
- def yaml?
64
- Leftovers.config.yaml_paths.allowed?(relative_path)
65
- end
66
-
67
- def json?
68
- Leftovers.config.json_paths.allowed?(relative_path)
69
- end
28
+ return read if precompiled.empty?
70
29
 
71
- def slim?
72
- Leftovers.config.slim_paths.allowed?(relative_path)
30
+ precompiled.join("\n")
73
31
  end
74
32
  end
75
33
  end