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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/README.md +1 -0
- data/docs/Configuration.md +20 -57
- data/docs/Custom-Precompilers.md +38 -0
- data/lib/config/actionpack.yml +5 -3
- data/lib/config/haml.yml +4 -2
- data/lib/config/ruby.yml +4 -15
- data/lib/config/slim.yml +4 -2
- data/lib/leftovers/cli.rb +5 -0
- data/lib/leftovers/collector.rb +2 -1
- data/lib/leftovers/config.rb +2 -18
- data/lib/leftovers/config_loader/argument_position_schema.rb +2 -2
- data/lib/leftovers/config_loader/attribute.rb +36 -10
- data/lib/leftovers/config_loader/built_in_precompiler_schema.rb +13 -0
- data/lib/leftovers/config_loader/document_schema.rb +32 -5
- data/lib/leftovers/config_loader/has_argument_schema.rb +2 -2
- data/lib/leftovers/config_loader/has_value_schema.rb +2 -2
- data/lib/leftovers/config_loader/inherit_schema_attributes.rb +22 -0
- data/lib/leftovers/config_loader/keep_test_only_schema.rb +2 -2
- data/lib/leftovers/config_loader/object_schema.rb +33 -105
- data/lib/leftovers/config_loader/precompile_schema.rb +12 -0
- data/lib/leftovers/config_loader/precompiler_schema.rb +11 -0
- data/lib/leftovers/config_loader/privacy_processor_schema.rb +0 -2
- data/lib/leftovers/config_loader/require_schema.rb +3 -3
- data/lib/leftovers/config_loader/schema.rb +2 -0
- data/lib/leftovers/config_loader/string_pattern_schema.rb +2 -2
- data/lib/leftovers/config_loader/string_value_processor_schema.rb +2 -2
- data/lib/leftovers/config_loader/transform_schema.rb +4 -6
- data/lib/leftovers/config_loader/value_matcher_schema.rb +2 -2
- data/lib/leftovers/config_loader/value_or_array_schema.rb +5 -3
- data/lib/leftovers/config_loader/value_or_object_schema.rb +40 -0
- data/lib/leftovers/config_loader/value_processor_schema.rb +2 -2
- data/lib/leftovers/config_loader.rb +5 -1
- data/lib/leftovers/file.rb +7 -53
- data/lib/leftovers/file_collector/comments_processor.rb +57 -0
- data/lib/leftovers/file_collector/node_processor.rb +131 -0
- data/lib/leftovers/file_collector.rb +42 -203
- data/lib/leftovers/matcher_builders/and_not.rb +7 -5
- data/lib/leftovers/matcher_builders/name.rb +18 -17
- data/lib/leftovers/matcher_builders/node.rb +48 -34
- data/lib/leftovers/matcher_builders/node_has_argument.rb +48 -52
- data/lib/leftovers/matcher_builders/node_has_keyword_argument.rb +13 -10
- data/lib/leftovers/matcher_builders/node_has_positional_argument.rb +29 -15
- data/lib/leftovers/matcher_builders/node_type.rb +1 -1
- data/lib/leftovers/matcher_builders/node_value.rb +27 -22
- data/lib/leftovers/matcher_builders/or.rb +50 -50
- data/lib/leftovers/matcher_builders/string_pattern.rb +1 -1
- data/lib/leftovers/merged_config.rb +3 -23
- data/lib/leftovers/precompilers/erb.rb +22 -0
- data/lib/leftovers/precompilers/haml.rb +15 -0
- data/lib/leftovers/precompilers/json.rb +27 -0
- data/lib/leftovers/precompilers/precompiler.rb +28 -0
- data/lib/leftovers/precompilers/slim.rb +15 -0
- data/lib/leftovers/precompilers/yaml.rb +75 -0
- data/lib/leftovers/precompilers.rb +50 -0
- data/lib/leftovers/processor_builders/action.rb +48 -39
- data/lib/leftovers/processor_builders/add_prefix.rb +1 -1
- data/lib/leftovers/processor_builders/add_suffix.rb +1 -1
- data/lib/leftovers/processor_builders/argument.rb +8 -11
- data/lib/leftovers/processor_builders/dynamic.rb +5 -5
- data/lib/leftovers/processor_builders/each.rb +2 -2
- data/lib/leftovers/processor_builders/each_action.rb +33 -33
- data/lib/leftovers/processor_builders/each_dynamic.rb +4 -8
- data/lib/leftovers/processor_builders/each_for_definition_set.rb +25 -21
- data/lib/leftovers/processor_builders/keyword.rb +3 -4
- data/lib/leftovers/processor_builders/transform.rb +2 -2
- data/lib/leftovers/processor_builders/transform_chain.rb +16 -8
- data/lib/leftovers/processor_builders/transform_set.rb +32 -28
- data/lib/leftovers/rake_task.rb +1 -1
- data/lib/leftovers/value_processors/add_dynamic_prefix.rb +3 -10
- data/lib/leftovers/value_processors/add_dynamic_suffix.rb +3 -10
- data/lib/leftovers/value_processors/each.rb +1 -1
- data/lib/leftovers/value_processors/each_for_definition_set.rb +2 -5
- data/lib/leftovers/value_processors/each_keyword.rb +1 -1
- data/lib/leftovers/value_processors/each_keyword_argument.rb +1 -1
- data/lib/leftovers/value_processors/each_positional_argument.rb +2 -1
- data/lib/leftovers/value_processors/keyword.rb +3 -7
- data/lib/leftovers/value_processors/keyword_argument.rb +2 -6
- data/lib/leftovers/value_processors/split.rb +2 -2
- data/lib/leftovers/version.rb +1 -1
- data/lib/leftovers.rb +41 -6
- metadata +17 -7
- data/lib/leftovers/erb.rb +0 -20
- data/lib/leftovers/haml.rb +0 -21
- data/lib/leftovers/json.rb +0 -28
- data/lib/leftovers/slim.rb +0 -21
- data/lib/leftovers/yaml.rb +0 -73
@@ -3,71 +3,67 @@
|
|
3
3
|
module Leftovers
|
4
4
|
module MatcherBuilders
|
5
5
|
module NodeHasArgument
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
::
|
11
|
-
|
12
|
-
::
|
13
|
-
|
14
|
-
build_from_hash(**pat)
|
15
|
-
# :nocov:
|
16
|
-
else
|
17
|
-
raise
|
6
|
+
class << self
|
7
|
+
def build(patterns)
|
8
|
+
::Leftovers::MatcherBuilders::Or.each_or_self(patterns) do |pat|
|
9
|
+
case pat
|
10
|
+
when ::String
|
11
|
+
::Leftovers::MatcherBuilders::NodeHasKeywordArgument.build(pat, nil)
|
12
|
+
when ::Integer
|
13
|
+
::Leftovers::MatcherBuilders::NodeHasPositionalArgument.build(pat, nil)
|
14
|
+
when ::Hash then build_from_hash(**pat)
|
18
15
|
# :nocov:
|
16
|
+
else raise Leftovers::UnexpectedCase, "Unhandled value #{pat.inspect}"
|
17
|
+
# :nocov:
|
18
|
+
end
|
19
19
|
end
|
20
20
|
end
|
21
|
-
end
|
22
21
|
|
23
|
-
|
24
|
-
keys = []
|
25
|
-
positions = []
|
22
|
+
private
|
26
23
|
|
27
|
-
|
28
|
-
|
29
|
-
when '*', ::Integer
|
30
|
-
positions << k
|
31
|
-
when ::String, ::Hash
|
32
|
-
keys << k
|
33
|
-
# :nocov:
|
34
|
-
else raise
|
35
|
-
# :nocov:
|
36
|
-
end
|
37
|
-
end
|
24
|
+
def build_from_hash(at: nil, has_value: nil, unless_arg: nil)
|
25
|
+
value_matcher = ::Leftovers::MatcherBuilders::NodeValue.build(has_value)
|
38
26
|
|
39
|
-
|
40
|
-
|
27
|
+
::Leftovers::MatcherBuilders::AndNot.build(
|
28
|
+
build_argument_matcher(value_matcher, **separate_argument_types(at)),
|
29
|
+
::Leftovers::MatcherBuilders::NodeHasArgument.build(unless_arg)
|
30
|
+
)
|
31
|
+
end
|
41
32
|
|
42
|
-
|
43
|
-
|
33
|
+
def separate_argument_types(at)
|
34
|
+
groups = ::Leftovers.each_or_self(at).group_by do |index|
|
35
|
+
case index
|
36
|
+
when '*', ::Integer then :positions
|
37
|
+
when ::String, ::Hash then :keys
|
38
|
+
# :nocov:
|
39
|
+
else raise Leftovers::UnexpectedCase, "Unhandled value #{index.inspect}"
|
40
|
+
# :nocov:
|
41
|
+
end
|
42
|
+
end
|
44
43
|
|
45
|
-
|
46
|
-
|
47
|
-
has_value: nil,
|
48
|
-
unless_arg: nil
|
49
|
-
)
|
50
|
-
keys, positions = separate_argument_types(at)
|
44
|
+
groups.transform_values { |v| Leftovers.unwrap_array(v) }
|
45
|
+
end
|
51
46
|
|
52
|
-
|
53
|
-
matcher = if (keys && positions) || (!keys && !positions)
|
54
|
-
::Leftovers::MatcherBuilders::Or.build([
|
55
|
-
::Leftovers::MatcherBuilders::NodeHasPositionalArgument.build(positions, value_matcher),
|
56
|
-
::Leftovers::MatcherBuilders::NodeHasKeywordArgument.build(keys, value_matcher)
|
57
|
-
])
|
58
|
-
elsif keys
|
47
|
+
def build_has_keyword_argument(keys, value_matcher)
|
59
48
|
::Leftovers::MatcherBuilders::NodeHasKeywordArgument.build(keys, value_matcher)
|
60
|
-
|
49
|
+
end
|
50
|
+
|
51
|
+
def build_has_positional_argument(positions, value_matcher)
|
61
52
|
::Leftovers::MatcherBuilders::NodeHasPositionalArgument.build(positions, value_matcher)
|
62
|
-
# :nocov:
|
63
|
-
else
|
64
|
-
raise
|
65
|
-
# :nocov:
|
66
53
|
end
|
67
54
|
|
68
|
-
|
69
|
-
|
70
|
-
|
55
|
+
def build_argument_matcher(value_matcher, keys: nil, positions: nil)
|
56
|
+
if keys && !positions
|
57
|
+
build_has_keyword_argument(keys, value_matcher)
|
58
|
+
elsif positions && !keys
|
59
|
+
build_has_positional_argument(positions, value_matcher)
|
60
|
+
else
|
61
|
+
::Leftovers::MatcherBuilders::Or.build([
|
62
|
+
build_has_positional_argument(positions, value_matcher),
|
63
|
+
build_has_keyword_argument(keys, value_matcher)
|
64
|
+
])
|
65
|
+
end
|
66
|
+
end
|
71
67
|
end
|
72
68
|
end
|
73
69
|
end
|
@@ -4,21 +4,24 @@ module Leftovers
|
|
4
4
|
module MatcherBuilders
|
5
5
|
module NodeHasKeywordArgument
|
6
6
|
class << self
|
7
|
-
def build(keywords, value_matcher)
|
7
|
+
def build(keywords, value_matcher)
|
8
8
|
value_matcher = ::Leftovers::MatcherBuilders::NodePairValue.build(value_matcher)
|
9
|
-
keyword_matcher =
|
9
|
+
keyword_matcher = build_keyword_matcher(keywords)
|
10
|
+
pair_matcher = ::Leftovers::MatcherBuilders::And.build([keyword_matcher, value_matcher])
|
11
|
+
|
12
|
+
return unless pair_matcher
|
13
|
+
|
14
|
+
::Leftovers::Matchers::NodeHasAnyKeywordArgument.new(pair_matcher)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def build_keyword_matcher(keywords)
|
20
|
+
if ::Leftovers.each_or_self(keywords).include?('**')
|
10
21
|
::Leftovers::Matchers::NodeType.new(:pair)
|
11
22
|
else
|
12
23
|
::Leftovers::MatcherBuilders::NodePairName.build(keywords)
|
13
24
|
end
|
14
|
-
|
15
|
-
pair_matcher = ::Leftovers::MatcherBuilders::And.build([
|
16
|
-
keyword_matcher, value_matcher
|
17
|
-
])
|
18
|
-
|
19
|
-
return nil unless pair_matcher
|
20
|
-
|
21
|
-
::Leftovers::Matchers::NodeHasAnyKeywordArgument.new(pair_matcher)
|
22
25
|
end
|
23
26
|
end
|
24
27
|
end
|
@@ -4,22 +4,36 @@ module Leftovers
|
|
4
4
|
module MatcherBuilders
|
5
5
|
module NodeHasPositionalArgument
|
6
6
|
class << self
|
7
|
-
def build(positions, value_matcher)
|
8
|
-
if positions && value_matcher
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
else
|
13
|
-
::Leftovers::Matchers::NodeHasPositionalArgumentWithValue.new(pos, value_matcher)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
elsif positions
|
17
|
-
pos = 0 if ::Leftovers.each_or_self(positions).include?('*')
|
18
|
-
pos ||= ::Leftovers.each_or_self(positions).min
|
19
|
-
|
20
|
-
::Leftovers::Matchers::NodeHasPositionalArgument.new(pos)
|
7
|
+
def build(positions, value_matcher)
|
8
|
+
if positions && !all_positions?(positions) && value_matcher
|
9
|
+
build_has_positional_value_matcher(positions, value_matcher)
|
10
|
+
elsif positions && !value_matcher
|
11
|
+
build_has_position_matcher(positions)
|
21
12
|
elsif value_matcher
|
22
|
-
|
13
|
+
build_has_any_positional_value_matcher(value_matcher)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def all_positions?(positions)
|
20
|
+
::Leftovers.each_or_self(positions).include?('*')
|
21
|
+
end
|
22
|
+
|
23
|
+
def build_has_position_matcher(positions)
|
24
|
+
position = 0 if all_positions?(positions)
|
25
|
+
position ||= ::Leftovers.each_or_self(positions).min
|
26
|
+
|
27
|
+
::Leftovers::Matchers::NodeHasPositionalArgument.new(position)
|
28
|
+
end
|
29
|
+
|
30
|
+
def build_has_any_positional_value_matcher(value_matcher)
|
31
|
+
::Leftovers::Matchers::NodeHasAnyPositionalArgumentWithValue.new(value_matcher)
|
32
|
+
end
|
33
|
+
|
34
|
+
def build_has_positional_value_matcher(positions, value_matcher)
|
35
|
+
::Leftovers::MatcherBuilders::Or.each_or_self(positions) do |position|
|
36
|
+
::Leftovers::Matchers::NodeHasPositionalArgumentWithValue.new(position, value_matcher)
|
23
37
|
end
|
24
38
|
end
|
25
39
|
end
|
@@ -19,7 +19,7 @@ module Leftovers
|
|
19
19
|
when 'Constant'
|
20
20
|
::Leftovers::Matchers::NodeType.new(Set[:const, :class, :module, :casgn])
|
21
21
|
# :nocov:
|
22
|
-
else raise "
|
22
|
+
else raise Leftovers::UnexpectedCase, "Unhandled value #{type.inspect}"
|
23
23
|
# :nocov:
|
24
24
|
end
|
25
25
|
end
|
@@ -4,17 +4,15 @@ module Leftovers
|
|
4
4
|
module MatcherBuilders
|
5
5
|
module NodeValue
|
6
6
|
class << self
|
7
|
-
def build(
|
8
|
-
::Leftovers::MatcherBuilders::Or.each_or_self(
|
9
|
-
case
|
7
|
+
def build(patterns)
|
8
|
+
::Leftovers::MatcherBuilders::Or.each_or_self(patterns) do |pattern|
|
9
|
+
case pattern
|
10
10
|
when ::Integer, ::Float, true, false, nil
|
11
|
-
::Leftovers::Matchers::NodeScalarValue.new(
|
12
|
-
when ::String
|
13
|
-
|
14
|
-
when ::Hash
|
15
|
-
build_from_hash(**pat)
|
11
|
+
::Leftovers::Matchers::NodeScalarValue.new(pattern)
|
12
|
+
when ::String then ::Leftovers::MatcherBuilders::NodeName.build(pattern)
|
13
|
+
when ::Hash then build_from_hash(**pattern)
|
16
14
|
# :nocov:
|
17
|
-
else raise
|
15
|
+
else raise Leftovers::UnexpectedCase, "Unhandled value #{pattern.inspect}"
|
18
16
|
# :nocov:
|
19
17
|
end
|
20
18
|
end
|
@@ -22,27 +20,34 @@ module Leftovers
|
|
22
20
|
|
23
21
|
private
|
24
22
|
|
25
|
-
def
|
23
|
+
def build_node_name(match, has_prefix, has_suffix)
|
24
|
+
::Leftovers::MatcherBuilders::NodeName.build(
|
25
|
+
match: match, has_prefix: has_prefix, has_suffix: has_suffix
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
def build_unless(unless_arg)
|
30
|
+
return unless unless_arg
|
31
|
+
|
32
|
+
::Leftovers::MatcherBuilders::Unless.build(
|
33
|
+
::Leftovers::MatcherBuilders::NodeValue.build(unless_arg)
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
def build_from_hash( # rubocop:disable Metrics/ParameterLists
|
26
38
|
at: nil, has_value: nil,
|
27
39
|
match: nil, has_prefix: nil, has_suffix: nil,
|
28
40
|
type: nil,
|
29
41
|
has_receiver: nil,
|
30
42
|
unless_arg: nil
|
31
43
|
)
|
32
|
-
|
33
|
-
::Leftovers::MatcherBuilders::NodeHasArgument.build(
|
34
|
-
|
35
|
-
),
|
36
|
-
::Leftovers::MatcherBuilders::NodeName.build(
|
37
|
-
match: match, has_prefix: has_prefix, has_suffix: has_suffix
|
38
|
-
),
|
44
|
+
::Leftovers::MatcherBuilders::And.build([
|
45
|
+
::Leftovers::MatcherBuilders::NodeHasArgument.build(at: at, has_value: has_value),
|
46
|
+
build_node_name(match, has_prefix, has_suffix),
|
39
47
|
::Leftovers::MatcherBuilders::NodeType.build(type),
|
40
|
-
::Leftovers::MatcherBuilders::NodeHasReceiver.build(has_receiver)
|
48
|
+
::Leftovers::MatcherBuilders::NodeHasReceiver.build(has_receiver),
|
49
|
+
build_unless(unless_arg)
|
41
50
|
])
|
42
|
-
|
43
|
-
::Leftovers::MatcherBuilders::AndNot.build(
|
44
|
-
matcher, ::Leftovers::MatcherBuilders::NodeValue.build(unless_arg)
|
45
|
-
)
|
46
51
|
end
|
47
52
|
end
|
48
53
|
end
|
@@ -5,68 +5,68 @@ require 'set'
|
|
5
5
|
module Leftovers
|
6
6
|
module MatcherBuilders
|
7
7
|
module Or
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
class << self
|
9
|
+
def each_or_self(value, &block)
|
10
|
+
case value
|
11
|
+
when nil then nil
|
12
|
+
when Array then build(value.map(&block))
|
13
|
+
else build([yield(value)])
|
14
|
+
end
|
13
15
|
end
|
14
|
-
end
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
17
|
+
def build(matchers)
|
18
|
+
matchers = compact(matchers)
|
19
|
+
case matchers.length
|
20
|
+
# :nocov:
|
21
|
+
when 0 then nil
|
22
|
+
# :nocov:
|
23
|
+
when 1 then matchers.first
|
24
|
+
when 2 then ::Leftovers::Matchers::Or.new(matchers.first, matchers[1])
|
25
|
+
else ::Leftovers::Matchers::Any.new(matchers.dup)
|
26
|
+
end
|
25
27
|
end
|
26
|
-
end
|
27
28
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
29
|
+
private
|
30
|
+
|
31
|
+
def flatten(value)
|
32
|
+
case value
|
33
|
+
when ::Leftovers::Matchers::Or
|
34
|
+
[*flatten(value.lhs), *flatten(value.rhs)]
|
35
|
+
when ::Leftovers::Matchers::Any
|
36
|
+
flatten(value.matchers)
|
37
|
+
when Array
|
38
|
+
value.flat_map { |v| flatten(v) }
|
39
|
+
else
|
40
|
+
value
|
41
|
+
end
|
40
42
|
end
|
41
|
-
end
|
42
43
|
|
43
|
-
|
44
|
-
|
44
|
+
def group_by_compactable(matchers)
|
45
|
+
groups = matchers.group_by do |matcher|
|
46
|
+
case matcher
|
47
|
+
when ::Integer, ::Symbol then :set
|
48
|
+
when ::Regexp then :regexp
|
49
|
+
else :uncompactable
|
50
|
+
end
|
51
|
+
end
|
45
52
|
|
46
|
-
|
47
|
-
|
48
|
-
uncompactable = []
|
53
|
+
groups.transform_values { |v| Leftovers.unwrap_array(v) }
|
54
|
+
end
|
49
55
|
|
50
|
-
|
56
|
+
def build_grouped(set: nil, regexp: nil, uncompactable: nil)
|
57
|
+
set = set.to_set if set.is_a?(Array)
|
58
|
+
regexp = Regexp.union(regexp) if regexp.is_a?(Array)
|
51
59
|
|
52
|
-
|
53
|
-
case matcher
|
54
|
-
when nil then nil
|
55
|
-
when ::Integer, ::Symbol then set << matcher
|
56
|
-
# when ::Set then set.merge(matcher) # may not be necessary
|
57
|
-
when ::Regexp then regexps << matcher
|
58
|
-
else uncompactable << matcher
|
59
|
-
end
|
60
|
+
[set, regexp].concat(Array(uncompactable)).compact
|
60
61
|
end
|
61
62
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
Regexp.union(regexps)
|
67
|
-
end
|
63
|
+
def compact(matchers)
|
64
|
+
matchers = flatten(matchers)
|
65
|
+
|
66
|
+
return matchers if matchers.length <= 1
|
68
67
|
|
69
|
-
|
68
|
+
build_grouped(**group_by_compactable(matchers))
|
69
|
+
end
|
70
70
|
end
|
71
71
|
end
|
72
72
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module Leftovers
|
4
4
|
module MatcherBuilders
|
5
5
|
module StringPattern
|
6
|
-
def self.build(match: nil, has_prefix: nil, has_suffix: nil) # rubocop:disable Metrics
|
6
|
+
def self.build(match: nil, has_prefix: nil, has_suffix: nil) # rubocop:disable Metrics
|
7
7
|
has_prefix = ::Regexp.escape(has_prefix) if has_prefix
|
8
8
|
has_suffix = ::Regexp.escape(has_suffix) if has_suffix
|
9
9
|
|
@@ -39,11 +39,7 @@ module Leftovers
|
|
39
39
|
@exclude_paths
|
40
40
|
@include_paths
|
41
41
|
@test_paths
|
42
|
-
@
|
43
|
-
@slim_paths
|
44
|
-
@yaml_paths
|
45
|
-
@json_paths
|
46
|
-
@erb_paths
|
42
|
+
@precompilers
|
47
43
|
@dynamic
|
48
44
|
@keep
|
49
45
|
@test_only
|
@@ -67,24 +63,8 @@ module Leftovers
|
|
67
63
|
@test_paths ||= Leftovers::MatcherBuilders::Path.build(@configs.flat_map(&:test_paths))
|
68
64
|
end
|
69
65
|
|
70
|
-
def
|
71
|
-
@
|
72
|
-
end
|
73
|
-
|
74
|
-
def slim_paths
|
75
|
-
@slim_paths ||= Leftovers::MatcherBuilders::Path.build(@configs.flat_map(&:slim_paths))
|
76
|
-
end
|
77
|
-
|
78
|
-
def yaml_paths
|
79
|
-
@yaml_paths ||= Leftovers::MatcherBuilders::Path.build(@configs.flat_map(&:yaml_paths))
|
80
|
-
end
|
81
|
-
|
82
|
-
def json_paths
|
83
|
-
@json_paths ||= Leftovers::MatcherBuilders::Path.build(@configs.flat_map(&:json_paths))
|
84
|
-
end
|
85
|
-
|
86
|
-
def erb_paths
|
87
|
-
@erb_paths ||= Leftovers::MatcherBuilders::Path.build(@configs.flat_map(&:erb_paths))
|
66
|
+
def precompilers
|
67
|
+
@precompilers ||= Leftovers::Precompilers.build(@configs.flat_map(&:precompile))
|
88
68
|
end
|
89
69
|
|
90
70
|
def dynamic
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
module Leftovers
|
6
|
+
module Precompilers
|
7
|
+
class ERB < ::ERB::Compiler
|
8
|
+
def self.precompile(erb)
|
9
|
+
@compiler ||= new('-')
|
10
|
+
@compiler.compile(erb).first
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_insert_cmd(out, content) # leftovers:keep
|
14
|
+
out.push("\n#{content}\n")
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_put_cmd(out, _content) # leftovers:keep
|
18
|
+
out.push("\n")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'haml'
|
4
|
+
|
5
|
+
module Leftovers
|
6
|
+
module Precompilers
|
7
|
+
module Haml
|
8
|
+
def self.precompile(haml)
|
9
|
+
::Haml::Engine.new(haml).precompiled
|
10
|
+
rescue ::Haml::SyntaxError => e
|
11
|
+
raise Leftovers::PrecompileError.new(e.message, line: e.line)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Leftovers
|
6
|
+
module Precompilers
|
7
|
+
module JSON
|
8
|
+
class << self
|
9
|
+
def precompile(json)
|
10
|
+
"__leftovers_document(#{to_ruby_argument(::JSON.parse(json))})"
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def to_ruby_argument(value)
|
16
|
+
ruby = value.inspect
|
17
|
+
return ruby unless value.is_a?(Array)
|
18
|
+
|
19
|
+
ruby.delete_prefix!('[')
|
20
|
+
ruby.delete_suffix!(']')
|
21
|
+
|
22
|
+
ruby
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Leftovers
|
6
|
+
module Precompilers
|
7
|
+
class Precompiler
|
8
|
+
def initialize(precompiler, matcher)
|
9
|
+
@precompiler = precompiler
|
10
|
+
@matcher = matcher
|
11
|
+
end
|
12
|
+
|
13
|
+
def precompile(content, file)
|
14
|
+
return unless @matcher === file.relative_path
|
15
|
+
|
16
|
+
begin
|
17
|
+
@precompiler.precompile(content)
|
18
|
+
rescue Leftovers::PrecompileError => e
|
19
|
+
e.warn(path: file.relative_path)
|
20
|
+
''
|
21
|
+
rescue StandardError => e
|
22
|
+
Leftovers.warn "#{e.class}: #{file.relative_path} #{e.message}"
|
23
|
+
''
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'slim'
|
4
|
+
|
5
|
+
module Leftovers
|
6
|
+
module Precompilers
|
7
|
+
module Slim
|
8
|
+
def self.precompile(file)
|
9
|
+
::Slim::Engine.new(file: file).call(file)
|
10
|
+
rescue ::Slim::Parser::SyntaxError => e
|
11
|
+
raise Leftovers::PrecompileError.new(e.error, line: e.lineno, column: e.column)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module Leftovers
|
6
|
+
module Precompilers
|
7
|
+
module YAML
|
8
|
+
class Builder < ::Psych::TreeBuilder
|
9
|
+
def initialize
|
10
|
+
@constants = []
|
11
|
+
|
12
|
+
super
|
13
|
+
end
|
14
|
+
|
15
|
+
def add_constant_for_tag(tag, value = nil)
|
16
|
+
match = %r{\A!ruby/[^:]*(?::(.*))?\z}.match(tag)
|
17
|
+
return unless match
|
18
|
+
|
19
|
+
@constants << (match[1] || value)
|
20
|
+
end
|
21
|
+
|
22
|
+
def start_mapping(_anchor, tag, *rest) # leftovers:keep
|
23
|
+
add_constant_for_tag(tag)
|
24
|
+
tag = nil
|
25
|
+
|
26
|
+
super
|
27
|
+
end
|
28
|
+
|
29
|
+
def start_sequence(_anchor, tag, *rest) # leftovers:keep
|
30
|
+
add_constant_for_tag(tag)
|
31
|
+
tag = nil
|
32
|
+
|
33
|
+
super
|
34
|
+
end
|
35
|
+
|
36
|
+
def scalar(value, _anchor, tag, *rest) # leftovers:keep
|
37
|
+
add_constant_for_tag(tag, value)
|
38
|
+
tag = nil
|
39
|
+
|
40
|
+
super
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_ruby_file
|
44
|
+
<<~FILE
|
45
|
+
__leftovers_document(#{to_ruby_argument(root.to_ruby.first)})
|
46
|
+
#{@constants.join("\n")}
|
47
|
+
FILE
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def to_ruby_argument(value)
|
53
|
+
ruby = value.inspect
|
54
|
+
return ruby unless value.is_a?(Array)
|
55
|
+
|
56
|
+
ruby.delete_prefix!('[')
|
57
|
+
ruby.delete_suffix!(']')
|
58
|
+
|
59
|
+
ruby
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.precompile(yaml)
|
64
|
+
builder = ::Leftovers::Precompilers::YAML::Builder.new
|
65
|
+
parser = ::Psych::Parser.new(builder)
|
66
|
+
parser.parse(yaml)
|
67
|
+
|
68
|
+
builder.to_ruby_file
|
69
|
+
rescue ::Psych::SyntaxError => e
|
70
|
+
message = [e.problem, e.context].compact.join(' ')
|
71
|
+
raise ::Leftovers::PrecompileError.new(message, line: e.line, column: e.column)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|