leftovers 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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