leftovers 0.7.0 → 0.8.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 (88) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/README.md +1 -0
  4. data/docs/Configuration.md +20 -57
  5. data/docs/Custom-Precompilers.md +38 -0
  6. data/lib/config/actionpack.yml +5 -3
  7. data/lib/config/haml.yml +4 -2
  8. data/lib/config/ruby.yml +4 -15
  9. data/lib/config/slim.yml +4 -2
  10. data/lib/leftovers/cli.rb +5 -0
  11. data/lib/leftovers/collector.rb +2 -1
  12. data/lib/leftovers/config.rb +2 -18
  13. data/lib/leftovers/config_loader/argument_position_schema.rb +2 -2
  14. data/lib/leftovers/config_loader/attribute.rb +36 -10
  15. data/lib/leftovers/config_loader/built_in_precompiler_schema.rb +13 -0
  16. data/lib/leftovers/config_loader/document_schema.rb +32 -5
  17. data/lib/leftovers/config_loader/has_argument_schema.rb +2 -2
  18. data/lib/leftovers/config_loader/has_value_schema.rb +2 -2
  19. data/lib/leftovers/config_loader/inherit_schema_attributes.rb +22 -0
  20. data/lib/leftovers/config_loader/keep_test_only_schema.rb +2 -2
  21. data/lib/leftovers/config_loader/object_schema.rb +33 -105
  22. data/lib/leftovers/config_loader/precompile_schema.rb +12 -0
  23. data/lib/leftovers/config_loader/precompiler_schema.rb +11 -0
  24. data/lib/leftovers/config_loader/privacy_processor_schema.rb +0 -2
  25. data/lib/leftovers/config_loader/require_schema.rb +3 -3
  26. data/lib/leftovers/config_loader/schema.rb +2 -0
  27. data/lib/leftovers/config_loader/string_pattern_schema.rb +2 -2
  28. data/lib/leftovers/config_loader/string_value_processor_schema.rb +2 -2
  29. data/lib/leftovers/config_loader/transform_schema.rb +4 -6
  30. data/lib/leftovers/config_loader/value_matcher_schema.rb +2 -2
  31. data/lib/leftovers/config_loader/value_or_array_schema.rb +5 -3
  32. data/lib/leftovers/config_loader/value_or_object_schema.rb +40 -0
  33. data/lib/leftovers/config_loader/value_processor_schema.rb +2 -2
  34. data/lib/leftovers/config_loader.rb +5 -1
  35. data/lib/leftovers/file.rb +7 -53
  36. data/lib/leftovers/file_collector/comments_processor.rb +57 -0
  37. data/lib/leftovers/file_collector/node_processor.rb +131 -0
  38. data/lib/leftovers/file_collector.rb +42 -203
  39. data/lib/leftovers/matcher_builders/and_not.rb +7 -5
  40. data/lib/leftovers/matcher_builders/name.rb +18 -17
  41. data/lib/leftovers/matcher_builders/node.rb +48 -34
  42. data/lib/leftovers/matcher_builders/node_has_argument.rb +48 -52
  43. data/lib/leftovers/matcher_builders/node_has_keyword_argument.rb +13 -10
  44. data/lib/leftovers/matcher_builders/node_has_positional_argument.rb +29 -15
  45. data/lib/leftovers/matcher_builders/node_type.rb +1 -1
  46. data/lib/leftovers/matcher_builders/node_value.rb +27 -22
  47. data/lib/leftovers/matcher_builders/or.rb +50 -50
  48. data/lib/leftovers/matcher_builders/string_pattern.rb +1 -1
  49. data/lib/leftovers/merged_config.rb +3 -23
  50. data/lib/leftovers/precompilers/erb.rb +22 -0
  51. data/lib/leftovers/precompilers/haml.rb +15 -0
  52. data/lib/leftovers/precompilers/json.rb +27 -0
  53. data/lib/leftovers/precompilers/precompiler.rb +28 -0
  54. data/lib/leftovers/precompilers/slim.rb +15 -0
  55. data/lib/leftovers/precompilers/yaml.rb +75 -0
  56. data/lib/leftovers/precompilers.rb +50 -0
  57. data/lib/leftovers/processor_builders/action.rb +48 -39
  58. data/lib/leftovers/processor_builders/add_prefix.rb +1 -1
  59. data/lib/leftovers/processor_builders/add_suffix.rb +1 -1
  60. data/lib/leftovers/processor_builders/argument.rb +8 -11
  61. data/lib/leftovers/processor_builders/dynamic.rb +5 -5
  62. data/lib/leftovers/processor_builders/each.rb +2 -2
  63. data/lib/leftovers/processor_builders/each_action.rb +33 -33
  64. data/lib/leftovers/processor_builders/each_dynamic.rb +4 -8
  65. data/lib/leftovers/processor_builders/each_for_definition_set.rb +25 -21
  66. data/lib/leftovers/processor_builders/keyword.rb +3 -4
  67. data/lib/leftovers/processor_builders/transform.rb +2 -2
  68. data/lib/leftovers/processor_builders/transform_chain.rb +16 -8
  69. data/lib/leftovers/processor_builders/transform_set.rb +32 -28
  70. data/lib/leftovers/rake_task.rb +1 -1
  71. data/lib/leftovers/value_processors/add_dynamic_prefix.rb +3 -10
  72. data/lib/leftovers/value_processors/add_dynamic_suffix.rb +3 -10
  73. data/lib/leftovers/value_processors/each.rb +1 -1
  74. data/lib/leftovers/value_processors/each_for_definition_set.rb +2 -5
  75. data/lib/leftovers/value_processors/each_keyword.rb +1 -1
  76. data/lib/leftovers/value_processors/each_keyword_argument.rb +1 -1
  77. data/lib/leftovers/value_processors/each_positional_argument.rb +2 -1
  78. data/lib/leftovers/value_processors/keyword.rb +3 -7
  79. data/lib/leftovers/value_processors/keyword_argument.rb +2 -6
  80. data/lib/leftovers/value_processors/split.rb +2 -2
  81. data/lib/leftovers/version.rb +1 -1
  82. data/lib/leftovers.rb +41 -6
  83. metadata +17 -7
  84. data/lib/leftovers/erb.rb +0 -20
  85. data/lib/leftovers/haml.rb +0 -21
  86. data/lib/leftovers/json.rb +0 -28
  87. data/lib/leftovers/slim.rb +0 -21
  88. data/lib/leftovers/yaml.rb +0 -73
@@ -2,93 +2,49 @@
2
2
 
3
3
  module Leftovers
4
4
  class ConfigLoader
5
- class ObjectSchema < Schema # rubocop:disable Metrics/ClassLength
5
+ class ObjectSchema < Schema
6
6
  class << self
7
7
  def inherit_attributes_from(schema, require_group: true, except: nil)
8
- attributes_and_schemas_to_inherit_from << schema
9
-
10
- inherit_except[schema] = Leftovers.each_or_self(except)
11
-
12
- return if require_group
13
-
14
- skip_require_group << schema
8
+ attributes_and_schemas_to_inherit_from << InheritSchemaAttributes.new(
9
+ schema, require_group: require_group, except: except
10
+ )
15
11
  end
16
12
 
17
13
  def attributes
18
- nonexcluded_attributes = attributes_and_schemas_to_inherit_from.map do |attr_or_schema|
19
- attr_or_schema.attributes.dup.tap do |attributes_copy|
20
- inherit_except[attr_or_schema]&.each { |e| attributes_copy.delete(e) }
21
- end
22
- end
23
-
24
- nonexcluded_attributes.reduce { |a, e| a.merge(e) { raise 'Duplicate attributes' } }
14
+ attributes_and_schemas_to_inherit_from.flat_map(&:attributes)
25
15
  end
26
16
 
27
- def aliases
28
- attributes_and_schemas_to_inherit_from.map(&:aliases)
29
- .reduce { |a, e| a.merge(e) { raise 'Duplicate aliases' } }
17
+ def attribute(name, value_schema, aliases: nil, require_group: nil, suggest: true)
18
+ attributes_and_schemas_to_inherit_from << Attribute.new(
19
+ name, value_schema,
20
+ aliases: aliases, require_group: require_group, suggest: suggest
21
+ )
30
22
  end
31
23
 
32
24
  def require_groups
33
- (attributes_and_schemas_to_inherit_from - skip_require_group)
34
- .map(&:require_groups).each_with_object({}) do |require_groups, hash|
35
- require_groups.each do |group, keys|
36
- hash[group] ||= []
37
- hash[group] += keys
38
- end
39
- end
40
- end
41
-
42
- attr_accessor :or_schema
43
-
44
- def attribute(name, value_schema, aliases: nil, require_group: nil)
45
- attributes_and_schemas_to_inherit_from << Attribute.new(
46
- name,
47
- value_schema,
48
- aliases: aliases,
49
- require_group: require_group
50
- )
25
+ attributes.group_by(&:require_group).tap { |rg| rg.delete(nil) }.values
51
26
  end
52
27
 
53
28
  def validate(node)
54
29
  if node.hash?
55
30
  validate_attributes(node)
56
- elsif or_schema
57
- validate_or_schema(node)
58
31
  else
59
- validate_is_hash(node)
32
+ error(node, 'be a hash')
33
+
34
+ node.valid?
60
35
  end
61
36
  end
62
37
 
63
38
  def to_ruby(node)
64
- if node.hash?
65
- node.pairs.map { |(key, value)| pair_to_ruby(key, value) }.to_h
66
- else
67
- or_schema.to_ruby(node)
68
- end
39
+ node.pairs.map { |(key, value)| attribute_for_key(key).to_ruby(value) }.to_h
69
40
  end
70
41
 
71
42
  private
72
43
 
73
- def inherit_except
74
- @inherit_except ||= {}
75
- end
76
-
77
- def skip_require_group
78
- @skip_require_group ||= []
79
- end
80
-
81
44
  def attributes_and_schemas_to_inherit_from
82
45
  @attributes_and_schemas_to_inherit_from ||= []
83
46
  end
84
47
 
85
- def pair_to_ruby(key, value)
86
- key_sym = key.to_sym
87
- key_sym = aliases[key_sym] || key_sym
88
- key_sym = :unless_arg if key_sym == :unless
89
- [key_sym, schema_for_attribute(key).to_ruby(value)]
90
- end
91
-
92
48
  def validate_attributes(node)
93
49
  validate_attribute_keys(node) && validate_required_keys(node)
94
50
  validate_alias_uniqueness_of_keys(node)
@@ -97,20 +53,8 @@ module Leftovers
97
53
  node.children.all?(&:valid?)
98
54
  end
99
55
 
100
- def validate_or_schema(node)
101
- or_schema.validate(node)
102
- return true if node.valid?
103
-
104
- if node.string? && valid_keys.include?(node.to_sym)
105
- node.error = "#{node.name_}#{node.to_sym} must be a hash key"
106
- else
107
- node.error += " or a hash with any of #{attributes.keys.join(', ')}"
108
- end
109
- end
110
-
111
- def validate_is_hash(node)
112
- error(node, 'be a hash')
113
- node.valid?
56
+ def attribute_for_key(node)
57
+ attributes.find { |attr| attr.name?(node) }
114
58
  end
115
59
 
116
60
  def validate_attribute_keys(node)
@@ -118,52 +62,45 @@ module Leftovers
118
62
  node.keys.all?(&:valid?)
119
63
  end
120
64
 
121
- def valid_keys
122
- attributes.keys + aliases.keys
123
- end
124
-
125
65
  def validate_alias_uniqueness_of_keys(node)
126
66
  node.keys.select(&:valid?)
127
- .group_by { |key| aliases[key.to_sym] || key.to_sym }
128
- .each_value do |keys|
129
- next unless keys.length > 1
67
+ .group_by { |key| attribute_for_key(key) }
68
+ .each_value { |keys| error_message_for_non_unique_keys(node, keys) if keys.length > 1 }
130
69
 
131
- error_message_for_non_unique_keys(node, keys)
132
- end
70
+ node.valid?
133
71
  end
134
72
 
135
73
  def error_message_for_non_unique_keys(node, keys)
136
- keys.each do |key|
137
- key.error = "#{node.name_}must only use one of #{keys.uniq.join(' or ')}"
138
- end
74
+ keys.each { |k| k.error = "#{node.name_}must only use one of #{keys.uniq.join(' or ')}" }
139
75
  end
140
76
 
141
77
  def validate_recognized_key(key, node)
142
- return true if valid_keys.include?(key.to_sym)
78
+ return true if attribute_for_key(key)
143
79
 
144
80
  suggestions = suggestions_for_unrecognized_key(key, node)
145
81
  did_you_mean = "\nDid you mean: #{suggestions.join(', ')}" unless suggestions.empty?
146
- for_name = " for #{node.name}" if node.name
147
-
148
- key.error = "unrecognized key #{key}#{for_name}#{did_you_mean}"
82
+ key.error = "unrecognized key #{key}#{" for #{node.name}" if node.name}#{did_you_mean}"
149
83
 
150
84
  false
151
85
  end
152
86
 
153
87
  def suggester
154
- @suggester ||= Suggester.new(attributes.keys)
88
+ @suggester ||= Suggester.new(suggestions)
155
89
  end
156
90
 
157
91
  def suggestions_for_unrecognized_key(key, node)
158
- existing_keys = node.keys.flat_map { |k| [k.to_sym, aliases[k.to_sym]] }.compact
159
- suggester.suggest(key.to_ruby) - existing_keys
92
+ suggester.suggest(key.to_ruby) - node.keys.map { |k| attribute_for_key(k)&.name }.compact
93
+ end
94
+
95
+ def suggestions(attributes = self.attributes)
96
+ attributes.select(&:suggest?).map(&:name)
160
97
  end
161
98
 
162
99
  def validate_required_keys(node)
163
- missing_groups = require_groups.map do |_name, group|
164
- next if node.keys.any? { |key| group.include?(key.to_sym) }
100
+ missing_groups = require_groups.map do |group|
101
+ next if node.keys.any? { |key| group.any? { |attr| attr.name?(key) } }
165
102
 
166
- "include at least one of #{(attributes.keys & group).join(', ')}"
103
+ "include at least one of #{suggestions(group).join(', ')}"
167
104
  end.compact
168
105
 
169
106
  error(node, missing_groups.join(' and ')) unless missing_groups.empty?
@@ -171,17 +108,8 @@ module Leftovers
171
108
  node.valid?
172
109
  end
173
110
 
174
- def schema_for_attribute(key)
175
- key_sym = key.to_sym
176
- attributes[key_sym] || attributes.fetch(aliases[key_sym])
177
- end
178
-
179
111
  def validate_valid_attribute_values(node)
180
- node.pairs.each do |(key, value)|
181
- next unless key.valid?
182
-
183
- schema_for_attribute(key).validate(value)
184
- end
112
+ node.pairs.each { |(k, v)| attribute_for_key(k).validate_value(v) if k.valid? }
185
113
  end
186
114
  end
187
115
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class ConfigLoader
5
+ class PrecompileSchema < ObjectSchema
6
+ attribute :paths, ValueOrArraySchema[StringSchema],
7
+ aliases: %i{path include_paths include_path}, require_group: :paths
8
+
9
+ attribute :format, PrecompilerSchema, require_group: :precompiler
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Leftovers
4
+ class ConfigLoader
5
+ class PrecompilerSchema < ValueOrObjectSchema
6
+ attribute :custom, StringSchema, require_group: :custom
7
+
8
+ self.or_value_schema = BuiltInPrecompilerSchema
9
+ end
10
+ end
11
+ end
@@ -5,8 +5,6 @@ module Leftovers
5
5
  class PrivacyProcessorSchema < ObjectSchema
6
6
  inherit_attributes_from ValueProcessorSchema
7
7
  attribute :to, PrivacySchema, require_group: :privacy_setting
8
-
9
- self.or_schema = nil
10
8
  end
11
9
  end
12
10
  end
@@ -2,10 +2,10 @@
2
2
 
3
3
  module Leftovers
4
4
  class ConfigLoader
5
- class RequireSchema < ObjectSchema
6
- attribute :quiet, StringSchema, aliases: :name, require_group: :quiet
5
+ class RequireSchema < ValueOrObjectSchema
6
+ attribute :quiet, StringSchema, require_group: :quiet
7
7
 
8
- self.or_schema = StringSchema
8
+ self.or_value_schema = StringSchema
9
9
  end
10
10
  end
11
11
  end
@@ -6,6 +6,8 @@ module Leftovers
6
6
  class << self
7
7
  def error(node, requirement)
8
8
  node.error = "#{node.name_}must #{requirement}"
9
+
10
+ false
9
11
  end
10
12
 
11
13
  def validate(node)
@@ -2,13 +2,13 @@
2
2
 
3
3
  module Leftovers
4
4
  class ConfigLoader
5
- class StringPatternSchema < ObjectSchema
5
+ class StringPatternSchema < ValueOrObjectSchema
6
6
  attribute :match, StringSchema, aliases: :matches, require_group: :matcher
7
7
  attribute :has_prefix, StringSchema, require_group: :matcher
8
8
  attribute :has_suffix, StringSchema, require_group: :matcher
9
9
  attribute :unless, ValueOrArraySchema[StringPatternSchema], require_group: :matcher
10
10
 
11
- self.or_schema = StringSchema
11
+ self.or_value_schema = StringSchema
12
12
  end
13
13
  end
14
14
  end
@@ -2,10 +2,10 @@
2
2
 
3
3
  module Leftovers
4
4
  class ConfigLoader
5
- class StringValueProcessorSchema < ObjectSchema
5
+ class StringValueProcessorSchema < ValueOrObjectSchema
6
6
  inherit_attributes_from ValueProcessorSchema
7
7
 
8
- self.or_schema = StringSchema
8
+ self.or_value_schema = StringSchema
9
9
  end
10
10
  end
11
11
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Leftovers
4
4
  class ConfigLoader
5
- class TransformSchema < ObjectSchema
5
+ class TransformSchema < ValueOrObjectSchema
6
6
  ArgumentlessTransformSchema.each_value do |transform|
7
7
  attribute(
8
8
  transform, TrueSchema,
@@ -11,10 +11,8 @@ module Leftovers
11
11
  )
12
12
  end
13
13
 
14
- attribute :add_prefix, ValueOrArraySchema[StringValueProcessorSchema],
15
- require_group: :processor
16
- attribute :add_suffix, ValueOrArraySchema[StringValueProcessorSchema],
17
- require_group: :processor
14
+ attribute :add_prefix, StringValueProcessorSchema, require_group: :processor
15
+ attribute :add_suffix, StringValueProcessorSchema, require_group: :processor
18
16
 
19
17
  attribute :split, StringSchema, require_group: :processor
20
18
  attribute :delete_prefix, StringSchema, require_group: :processor
@@ -22,7 +20,7 @@ module Leftovers
22
20
  attribute :delete_before, StringSchema, require_group: :processor
23
21
  attribute :delete_after, StringSchema, require_group: :processor
24
22
 
25
- self.or_schema = ArgumentlessTransformSchema
23
+ self.or_value_schema = ArgumentlessTransformSchema
26
24
  end
27
25
  end
28
26
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Leftovers
4
4
  class ConfigLoader
5
- class ValueMatcherSchema < ObjectSchema
5
+ class ValueMatcherSchema < ValueOrObjectSchema
6
6
  attribute :arguments, ValueOrArraySchema[ArgumentPositionSchema], aliases: :argument,
7
7
  require_group: :matcher
8
8
  attribute :keywords, ValueOrArraySchema[StringPatternSchema], aliases: :keyword,
@@ -12,7 +12,7 @@ module Leftovers
12
12
  attribute :value, StringSchema, require_group: :matcher
13
13
  attribute :recursive, TrueSchema
14
14
 
15
- self.or_schema = ScalarArgumentSchema
15
+ self.or_value_schema = ScalarArgumentSchema
16
16
  end
17
17
  end
18
18
  end
@@ -27,9 +27,11 @@ module Leftovers
27
27
 
28
28
  def to_ruby(node)
29
29
  if node.array?
30
- node.children.map do |value|
31
- value_schema.to_ruby(value)
32
- end
30
+ Leftovers.unwrap_array(
31
+ node.children.map do |value|
32
+ value_schema.to_ruby(value)
33
+ end
34
+ )
33
35
  else
34
36
  value_schema.to_ruby(node)
35
37
  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
@@ -2,13 +2,13 @@
2
2
 
3
3
  module Leftovers
4
4
  class ConfigLoader
5
- class ValueProcessorSchema < ObjectSchema
5
+ class ValueProcessorSchema < ValueOrObjectSchema
6
6
  inherit_attributes_from ValueMatcherSchema
7
7
 
8
8
  attribute :transforms, ValueOrArraySchema[TransformSchema]
9
9
  inherit_attributes_from TransformSchema, require_group: nil
10
10
 
11
- self.or_schema = ScalarArgumentSchema
11
+ self.or_value_schema = ScalarArgumentSchema
12
12
  end
13
13
  end
14
14
  end
@@ -1,20 +1,23 @@
1
1
  # frozen-string-literal: true
2
2
 
3
3
  require 'yaml'
4
- require 'leftovers'
5
4
 
6
5
  module Leftovers
7
6
  class ConfigLoader
8
7
  autoload(:ArgumentPositionSchema, "#{__dir__}/config_loader/argument_position_schema")
9
8
  autoload(:ArgumentlessTransformSchema, "#{__dir__}/config_loader/argumentless_transform_schema")
10
9
  autoload(:Attribute, "#{__dir__}/config_loader/attribute")
10
+ autoload(:BuiltInPrecompilerSchema, "#{__dir__}/config_loader/built_in_precompiler_schema")
11
11
  autoload(:DocumentSchema, "#{__dir__}/config_loader/document_schema")
12
12
  autoload(:DynamicSchema, "#{__dir__}/config_loader/dynamic_schema")
13
+ autoload(:InheritSchemaAttributes, "#{__dir__}/config_loader/inherit_schema_attributes")
13
14
  autoload(:HasArgumentSchema, "#{__dir__}/config_loader/has_argument_schema")
14
15
  autoload(:HasValueSchema, "#{__dir__}/config_loader/has_value_schema")
15
16
  autoload(:KeepTestOnlySchema, "#{__dir__}/config_loader/keep_test_only_schema")
16
17
  autoload(:Node, "#{__dir__}/config_loader/node")
17
18
  autoload(:ObjectSchema, "#{__dir__}/config_loader/object_schema")
19
+ autoload(:PrecompileSchema, "#{__dir__}/config_loader/precompile_schema")
20
+ autoload(:PrecompilerSchema, "#{__dir__}/config_loader/precompiler_schema")
18
21
  autoload(:PrivacyProcessorSchema, "#{__dir__}/config_loader/privacy_processor_schema")
19
22
  autoload(:PrivacySchema, "#{__dir__}/config_loader/privacy_schema")
20
23
  autoload(:RequireSchema, "#{__dir__}/config_loader/require_schema")
@@ -31,6 +34,7 @@ module Leftovers
31
34
  autoload(:TrueSchema, "#{__dir__}/config_loader/true_schema")
32
35
  autoload(:ValueMatcherSchema, "#{__dir__}/config_loader/value_matcher_schema")
33
36
  autoload(:ValueOrArraySchema, "#{__dir__}/config_loader/value_or_array_schema")
37
+ autoload(:ValueOrObjectSchema, "#{__dir__}/config_loader/value_or_object_schema")
34
38
  autoload(:ValueProcessorSchema, "#{__dir__}/config_loader/value_processor_schema")
35
39
  autoload(:ValueTypeSchema, "#{__dir__}/config_loader/value_type_schema")
36
40
 
@@ -18,62 +18,16 @@ module Leftovers
18
18
  @test = Leftovers.config.test_paths.allowed?(relative_path)
19
19
  end
20
20
 
21
- def ruby # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
22
- precompiled = []
23
- precompile = false
21
+ def ruby
22
+ read = self.read
24
23
 
25
- if haml?
26
- precompiled << ::Leftovers::Haml.precompile(read, self)
27
- precompile = true
28
- end
29
-
30
- if json?
31
- precompiled << ::Leftovers::JSON.precompile(read, self)
32
- precompile = true
33
- end
34
-
35
- if erb?
36
- precompiled << ::Leftovers::ERB.precompile(read, self)
37
- precompile = true
38
- end
39
-
40
- if slim?
41
- precompiled << ::Leftovers::Slim.precompile(read, self)
42
- precompile = true
43
- end
44
-
45
- if yaml?
46
- precompiled << ::Leftovers::YAML.precompile(read, self)
47
- precompile = true
48
- end
49
-
50
- if precompile
51
- precompiled.join("\n")
52
- else
53
- read
54
- end
55
- end
56
-
57
- private
58
-
59
- def erb?
60
- Leftovers.config.erb_paths.allowed?(relative_path)
61
- end
24
+ precompiled = ::Leftovers.config.precompilers.map do |precompiler|
25
+ precompiler.precompile(read, self)
26
+ end.compact
62
27
 
63
- def haml?
64
- Leftovers.config.haml_paths.allowed?(relative_path)
65
- end
66
-
67
- def yaml?
68
- Leftovers.config.yaml_paths.allowed?(relative_path)
69
- end
70
-
71
- def json?
72
- Leftovers.config.json_paths.allowed?(relative_path)
73
- end
28
+ return read if precompiled.empty?
74
29
 
75
- def slim?
76
- Leftovers.config.slim_paths.allowed?(relative_path)
30
+ precompiled.join("\n")
77
31
  end
78
32
  end
79
33
  end
@@ -0,0 +1,57 @@
1
+ # frozen-string-literal: true
2
+
3
+ module Leftovers
4
+ class FileCollector
5
+ module CommentsProcessor
6
+ METHOD_NAME_RE = /[[:alpha:]_][[:alnum:]_]*\b[?!=]?/.freeze
7
+ NON_ALNUM_METHOD_NAME_RE = Regexp.union(%w{
8
+ []= [] ** ~ +@ -@ * / % + - >> << &
9
+ ^ | <=> <= >= < > === == != =~ !~ !
10
+ }.map { |op| /#{Regexp.escape(op)}/ })
11
+ CONSTANT_NAME_RE = /[[:upper:]][[:alnum:]_]*\b/.freeze
12
+ NAME_RE = Regexp.union(METHOD_NAME_RE, NON_ALNUM_METHOD_NAME_RE, CONSTANT_NAME_RE)
13
+ NAME_LIST_RE = /#{NAME_RE}(?:[, :]+#{NAME_RE})*/.freeze
14
+ LEFTOVERS_CALL_RE = /\bleftovers:call(?:s|e(?:d|rs?))? (#{NAME_LIST_RE})/.freeze
15
+ LEFTOVERS_ALLOW_RE = /\bleftovers:(?:keeps?|skip(?:s|ped|)|allow(?:s|ed|))\b/.freeze
16
+ LEFTOVERS_TEST_RE = /\bleftovers:(?:for_tests?|tests?|testing|test_only)\b/.freeze
17
+ LEFTOVERS_DYNAMIC_RE = /\bleftovers:dynamic[: ](#{NAME_LIST_RE})/.freeze
18
+
19
+ class << self
20
+ def process(comments, collector)
21
+ comments.each do |comment|
22
+ process_leftovers_keep_comment(comment, collector)
23
+ process_leftovers_test_comment(comment, collector)
24
+ process_leftovers_dynamic_comment(comment, collector)
25
+ process_leftovers_call_comment(comment, collector)
26
+ end
27
+ end
28
+
29
+ def process_leftovers_keep_comment(comment, collector)
30
+ return unless comment.text.match?(LEFTOVERS_ALLOW_RE)
31
+
32
+ collector.allow_lines << comment.loc.line
33
+ end
34
+
35
+ def process_leftovers_test_comment(comment, collector)
36
+ return unless comment.text.match?(LEFTOVERS_TEST_RE)
37
+
38
+ collector.test_lines << comment.loc.line
39
+ end
40
+
41
+ def process_leftovers_dynamic_comment(comment, collector)
42
+ match = comment.text.match(LEFTOVERS_DYNAMIC_RE)
43
+ return unless match
44
+
45
+ collector.dynamic_lines[comment.loc.line] = match[1].scan(NAME_RE)
46
+ end
47
+
48
+ def process_leftovers_call_comment(comment, collector)
49
+ match = comment.text.match(LEFTOVERS_CALL_RE)
50
+ return unless match
51
+
52
+ match[1].scan(NAME_RE).each { |s| collector.add_call(s.to_sym) }
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end