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