leftovers 0.5.2 → 0.6.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 +5 -5
- data/CHANGELOG.md +17 -0
- data/README.md +23 -3
- data/docs/Configuration.md +119 -2
- data/leftovers.gemspec +8 -4
- data/lib/.DS_Store +0 -0
- data/lib/config/actionpack.yml +11 -0
- data/lib/config/activesupport.yml +1 -0
- data/lib/config/ruby.yml +10 -0
- data/lib/config/slim.yml +4 -0
- data/lib/leftovers/collector.rb +3 -1
- data/lib/leftovers/config.rb +12 -4
- data/lib/leftovers/config_validator/schema_hash.rb +171 -149
- data/lib/leftovers/config_validator.rb +1 -0
- data/lib/leftovers/definition.rb +1 -1
- data/lib/leftovers/dynamic_processors/call.rb +0 -4
- data/lib/leftovers/dynamic_processors/call_definition.rb +0 -4
- data/lib/leftovers/dynamic_processors/definition.rb +0 -4
- data/lib/leftovers/erb.rb +1 -1
- data/lib/leftovers/file.rb +53 -5
- data/lib/leftovers/file_collector.rb +33 -2
- data/lib/leftovers/json.rb +28 -0
- data/lib/leftovers/matcher_builders/document.rb +13 -0
- data/lib/leftovers/matcher_builders/node.rb +3 -1
- data/lib/leftovers/matcher_builders/node_has_argument.rb +3 -4
- data/lib/leftovers/matcher_builders/node_has_keyword_argument.rb +1 -1
- data/lib/leftovers/matcher_builders/node_has_positional_argument.rb +1 -1
- data/lib/leftovers/matcher_builders.rb +1 -0
- data/lib/leftovers/matchers/all.rb +0 -4
- data/lib/leftovers/matchers/and.rb +0 -4
- data/lib/leftovers/matchers/any.rb +0 -4
- data/lib/leftovers/matchers/node_has_any_keyword_argument.rb +1 -7
- data/lib/leftovers/matchers/node_has_any_positional_argument_with_value.rb +1 -7
- data/lib/leftovers/matchers/node_has_positional_argument_with_value.rb +0 -4
- data/lib/leftovers/matchers/node_name.rb +0 -4
- data/lib/leftovers/matchers/node_pair_value.rb +0 -4
- data/lib/leftovers/matchers/node_path.rb +0 -4
- data/lib/leftovers/matchers/node_scalar_value.rb +0 -4
- data/lib/leftovers/matchers/node_type.rb +0 -4
- data/lib/leftovers/matchers/not.rb +0 -4
- data/lib/leftovers/matchers/or.rb +0 -4
- data/lib/leftovers/merged_config.rb +43 -9
- data/lib/leftovers/processor_builders/dynamic.rb +2 -1
- data/lib/leftovers/slim.rb +21 -0
- data/lib/leftovers/todo_reporter.rb +10 -35
- data/lib/leftovers/value_processors/camelize.rb +1 -1
- data/lib/leftovers/value_processors/deconstantize.rb +1 -1
- data/lib/leftovers/value_processors/delete_prefix.rb +0 -6
- data/lib/leftovers/value_processors/delete_suffix.rb +0 -6
- data/lib/leftovers/value_processors/demodulize.rb +1 -1
- data/lib/leftovers/value_processors/keyword.rb +0 -4
- data/lib/leftovers/value_processors/keyword_argument.rb +0 -4
- data/lib/leftovers/value_processors/parameterize.rb +1 -1
- data/lib/leftovers/value_processors/pluralize.rb +1 -1
- data/lib/leftovers/value_processors/return_definition.rb +0 -4
- data/lib/leftovers/value_processors/singularize.rb +1 -1
- data/lib/leftovers/value_processors/titleize.rb +1 -1
- data/lib/leftovers/value_processors/underscore.rb +1 -1
- data/lib/leftovers/version.rb +1 -1
- data/lib/leftovers/yaml.rb +73 -0
- data/lib/leftovers.rb +8 -8
- metadata +51 -18
- data/lib/leftovers/backports.rb +0 -40
@@ -10,7 +10,7 @@ module Leftovers
|
|
10
10
|
::Leftovers::MatcherBuilders::NodeName.build(pat)
|
11
11
|
when ::Hash
|
12
12
|
build_from_hash(**pat)
|
13
|
-
|
13
|
+
# :nocov:
|
14
14
|
else raise
|
15
15
|
# :nocov:
|
16
16
|
end
|
@@ -19,6 +19,7 @@ module Leftovers
|
|
19
19
|
|
20
20
|
def self.build_from_hash( # rubocop:disable Metrics/ParameterLists, Metrics/MethodLength
|
21
21
|
names: nil, match: nil, has_prefix: nil, has_suffix: nil,
|
22
|
+
document: false,
|
22
23
|
paths: nil,
|
23
24
|
has_arguments: nil,
|
24
25
|
has_receiver: nil,
|
@@ -29,6 +30,7 @@ module Leftovers
|
|
29
30
|
names,
|
30
31
|
{ match: match, has_prefix: has_prefix, has_suffix: has_suffix }.compact
|
31
32
|
]),
|
33
|
+
::Leftovers::MatcherBuilders::Document.build(document),
|
32
34
|
::Leftovers::MatcherBuilders::NodePath.build(paths),
|
33
35
|
::Leftovers::MatcherBuilders::NodeHasArgument.build(has_arguments),
|
34
36
|
::Leftovers::MatcherBuilders::NodeHasReceiver.build(has_receiver),
|
@@ -26,12 +26,10 @@ module Leftovers
|
|
26
26
|
|
27
27
|
::Leftovers.each_or_self(at) do |k|
|
28
28
|
case k
|
29
|
-
when '*'
|
29
|
+
when '*', ::Integer
|
30
30
|
positions << k
|
31
31
|
when ::String, ::Hash
|
32
32
|
keys << k
|
33
|
-
when ::Integer
|
34
|
-
positions << k
|
35
33
|
# :nocov:
|
36
34
|
else raise
|
37
35
|
# :nocov:
|
@@ -62,7 +60,8 @@ module Leftovers
|
|
62
60
|
elsif positions
|
63
61
|
::Leftovers::MatcherBuilders::NodeHasPositionalArgument.build(positions, value_matcher)
|
64
62
|
# :nocov:
|
65
|
-
else
|
63
|
+
else
|
64
|
+
raise
|
66
65
|
# :nocov:
|
67
66
|
end
|
68
67
|
|
@@ -6,7 +6,7 @@ module Leftovers
|
|
6
6
|
class << self
|
7
7
|
def build(keywords, value_matcher) # rubocop:disable Metrics/MethodLength
|
8
8
|
value_matcher = ::Leftovers::MatcherBuilders::NodePairValue.build(value_matcher)
|
9
|
-
keyword_matcher = if ::Leftovers.each_or_self(keywords).
|
9
|
+
keyword_matcher = if ::Leftovers.each_or_self(keywords).include?('**')
|
10
10
|
::Leftovers::Matchers::NodeType.new(:pair)
|
11
11
|
else
|
12
12
|
::Leftovers::MatcherBuilders::NodePairName.build(keywords)
|
@@ -14,7 +14,7 @@ module Leftovers
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
elsif positions
|
17
|
-
pos = 0 if ::Leftovers.each_or_self(positions).
|
17
|
+
pos = 0 if ::Leftovers.each_or_self(positions).include?('*')
|
18
18
|
pos ||= ::Leftovers.each_or_self(positions).min
|
19
19
|
|
20
20
|
::Leftovers::Matchers::NodeHasPositionalArgument.new(pos)
|
@@ -4,6 +4,7 @@ module Leftovers
|
|
4
4
|
module MatcherBuilders
|
5
5
|
autoload(:AndNot, "#{__dir__}/matcher_builders/and_not")
|
6
6
|
autoload(:And, "#{__dir__}/matcher_builders/and")
|
7
|
+
autoload(:Document, "#{__dir__}/matcher_builders/document")
|
7
8
|
autoload(:Name, "#{__dir__}/matcher_builders/name")
|
8
9
|
autoload(:Node, "#{__dir__}/matcher_builders/node")
|
9
10
|
autoload(:NodeHasArgument, "#{__dir__}/matcher_builders/node_has_argument")
|
@@ -3,10 +3,6 @@
|
|
3
3
|
module Leftovers
|
4
4
|
module Matchers
|
5
5
|
class NodeHasAnyKeywordArgument
|
6
|
-
# :nocov:
|
7
|
-
using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
|
8
|
-
# :nocov:
|
9
|
-
|
10
6
|
def initialize(pair_matcher)
|
11
7
|
@pair_matcher = pair_matcher
|
12
8
|
|
@@ -17,9 +13,7 @@ module Leftovers
|
|
17
13
|
kwargs = node.kwargs
|
18
14
|
return false unless kwargs
|
19
15
|
|
20
|
-
kwargs.children.any?
|
21
|
-
@pair_matcher === pair
|
22
|
-
end
|
16
|
+
kwargs.children.any?(@pair_matcher)
|
23
17
|
end
|
24
18
|
|
25
19
|
freeze
|
@@ -3,10 +3,6 @@
|
|
3
3
|
module Leftovers
|
4
4
|
module Matchers
|
5
5
|
class NodeHasAnyPositionalArgumentWithValue
|
6
|
-
# :nocov:
|
7
|
-
using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
|
8
|
-
# :nocov:
|
9
|
-
|
10
6
|
def initialize(matcher)
|
11
7
|
@matcher = matcher
|
12
8
|
|
@@ -17,9 +13,7 @@ module Leftovers
|
|
17
13
|
args = node.positional_arguments
|
18
14
|
return false unless args
|
19
15
|
|
20
|
-
args.any?
|
21
|
-
@matcher === value
|
22
|
-
end
|
16
|
+
args.any?(@matcher)
|
23
17
|
end
|
24
18
|
|
25
19
|
freeze
|
@@ -3,10 +3,6 @@
|
|
3
3
|
module Leftovers
|
4
4
|
module Matchers
|
5
5
|
class NodeHasPositionalArgumentWithValue
|
6
|
-
# :nocov:
|
7
|
-
using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
|
8
|
-
# :nocov:
|
9
|
-
|
10
6
|
def initialize(position, matcher)
|
11
7
|
@position = position
|
12
8
|
@matcher = matcher
|
@@ -4,7 +4,7 @@ require 'set'
|
|
4
4
|
require 'fast_ignore'
|
5
5
|
|
6
6
|
module Leftovers
|
7
|
-
class MergedConfig
|
7
|
+
class MergedConfig # rubocop:disable Metrics/ClassLength
|
8
8
|
def initialize(load_defaults: false)
|
9
9
|
@configs = []
|
10
10
|
@loaded_configs = Set.new
|
@@ -37,14 +37,24 @@ module Leftovers
|
|
37
37
|
Leftovers::Config.new(:'.leftovers_todo.yml', path: Leftovers.pwd + '.leftovers_todo.yml')
|
38
38
|
end
|
39
39
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
40
|
+
MEMOIZED_IVARS = %i{
|
41
|
+
@exclude_paths
|
42
|
+
@include_paths
|
43
|
+
@test_paths
|
44
|
+
@haml_paths
|
45
|
+
@slim_paths
|
46
|
+
@yaml_paths
|
47
|
+
@json_paths
|
48
|
+
@erb_paths
|
49
|
+
@dynamic
|
50
|
+
@keep
|
51
|
+
@test_only
|
52
|
+
}.freeze
|
53
|
+
|
54
|
+
def unmemoize
|
55
|
+
MEMOIZED_IVARS.each do |ivar|
|
56
|
+
remove_instance_variable(ivar) if instance_variable_get(ivar)
|
57
|
+
end
|
48
58
|
end
|
49
59
|
|
50
60
|
def exclude_paths
|
@@ -71,6 +81,30 @@ module Leftovers
|
|
71
81
|
)
|
72
82
|
end
|
73
83
|
|
84
|
+
def slim_paths
|
85
|
+
@slim_paths ||= FastIgnore.new(
|
86
|
+
include_rules: @configs.flat_map(&:slim_paths),
|
87
|
+
gitignore: false,
|
88
|
+
root: Leftovers.pwd
|
89
|
+
)
|
90
|
+
end
|
91
|
+
|
92
|
+
def yaml_paths
|
93
|
+
@yaml_paths ||= FastIgnore.new(
|
94
|
+
include_rules: @configs.flat_map(&:yaml_paths),
|
95
|
+
gitignore: false,
|
96
|
+
root: Leftovers.pwd
|
97
|
+
)
|
98
|
+
end
|
99
|
+
|
100
|
+
def json_paths
|
101
|
+
@json_paths ||= FastIgnore.new(
|
102
|
+
include_rules: @configs.flat_map(&:json_paths),
|
103
|
+
gitignore: false,
|
104
|
+
root: Leftovers.pwd
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
74
108
|
def erb_paths
|
75
109
|
@erb_paths ||= FastIgnore.new(
|
76
110
|
include_rules: @configs.flat_map(&:erb_paths),
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Leftovers
|
4
|
+
module Slim
|
5
|
+
module_function
|
6
|
+
|
7
|
+
def precompile(file, name)
|
8
|
+
return '' unless Leftovers.try_require('slim', message: <<~MESSAGE) # rubocop:disable Layout/EmptyLineAfterGuardClause
|
9
|
+
Skipped parsing #{name.relative_path}, because the slim gem was not available
|
10
|
+
`gem install slim`
|
11
|
+
MESSAGE
|
12
|
+
|
13
|
+
begin
|
14
|
+
::Slim::Engine.new(file: file).call(file)
|
15
|
+
rescue ::Slim::Parser::SyntaxError => e
|
16
|
+
Leftovers.warn "#{e.class}: \"#{e.error}\" #{name.relative_path}:#{e.lineno}:#{e.column}"
|
17
|
+
''
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -64,54 +64,29 @@ module Leftovers
|
|
64
64
|
end
|
65
65
|
|
66
66
|
def todo_data(only_test, none)
|
67
|
-
none_test = none.select(&:test?)
|
68
|
-
none_non_test = none.reject(&:test?)
|
69
67
|
[
|
70
|
-
|
71
|
-
|
68
|
+
list_data(
|
69
|
+
:test_only, 'Only directly called in tests', only_test
|
70
|
+
),
|
71
|
+
list_data(
|
72
|
+
:keep, 'Not directly called at all', none
|
73
|
+
)
|
72
74
|
].compact.join
|
73
75
|
end
|
74
76
|
|
75
|
-
def
|
77
|
+
def list_data(key, title, list)
|
76
78
|
return if list.empty?
|
77
79
|
|
78
80
|
<<~YML
|
79
|
-
|
80
|
-
|
81
|
-
YML
|
82
|
-
end
|
83
|
-
|
84
|
-
def keep_data(only_test, none_non_test)
|
85
|
-
return if only_test.empty? && none_non_test.empty?
|
86
|
-
|
87
|
-
<<~YML.chomp
|
88
|
-
keep:
|
89
|
-
#{keep_test_called_data(only_test)}#{keep_never_called_data(none_non_test)}
|
90
|
-
YML
|
91
|
-
end
|
92
|
-
|
93
|
-
def keep_test_called_data(list)
|
94
|
-
return if list.empty?
|
95
|
-
|
96
|
-
generate_list('Only directly called in tests:', list)
|
97
|
-
end
|
98
|
-
|
99
|
-
def keep_never_called_data(list)
|
100
|
-
return if list.empty?
|
101
|
-
|
102
|
-
generate_list('Not directly called at all:', list)
|
103
|
-
end
|
104
|
-
|
105
|
-
def generate_list(title, list)
|
106
|
-
<<~YML
|
107
|
-
# #{title}
|
81
|
+
#{key}:
|
82
|
+
# #{title}:
|
108
83
|
#{print_definition_list(list)}
|
109
84
|
|
110
85
|
YML
|
111
86
|
end
|
112
87
|
|
113
88
|
def print_definition_list(definition_list)
|
114
|
-
definition_list.map { |definition| print_definition(definition) }.join("\n")
|
89
|
+
definition_list.map { |definition| print_definition(definition) }.sort.join("\n")
|
115
90
|
end
|
116
91
|
|
117
92
|
def print_definition(definition)
|
@@ -16,7 +16,7 @@ module Leftovers
|
|
16
16
|
rescue NoMethodError
|
17
17
|
Leftovers.error <<~MESSAGE
|
18
18
|
Tried using the String#camelize method, but the activesupport gem was not available and/or not required
|
19
|
-
`gem install activesupport`, and/or add `requires: 'active_support/core_ext/string'` to your .leftovers.yml
|
19
|
+
`gem install activesupport`, and/or add `requires: ['active_support', 'active_support/core_ext/string']` to your .leftovers.yml
|
20
20
|
MESSAGE
|
21
21
|
end
|
22
22
|
end
|
@@ -16,7 +16,7 @@ module Leftovers
|
|
16
16
|
rescue NoMethodError
|
17
17
|
Leftovers.error <<~MESSAGE
|
18
18
|
Tried using the String#deconstantize method, but the activesupport gem was not available and/or not required
|
19
|
-
`gem install activesupport`, and/or add `requires: 'active_support/core_ext/string'` to your .leftovers.yml
|
19
|
+
`gem install activesupport`, and/or add `requires: ['active_support', 'active_support/core_ext/string']` to your .leftovers.yml
|
20
20
|
MESSAGE
|
21
21
|
end
|
22
22
|
end
|
@@ -3,12 +3,6 @@
|
|
3
3
|
module Leftovers
|
4
4
|
module ValueProcessors
|
5
5
|
class DeletePrefix
|
6
|
-
# :nocov:
|
7
|
-
if defined?(::Leftovers::Backports::StringDeletePrefixSuffix)
|
8
|
-
using ::Leftovers::Backports::StringDeletePrefixSuffix
|
9
|
-
end
|
10
|
-
# :nocov:
|
11
|
-
|
12
6
|
def initialize(prefix, then_processor)
|
13
7
|
@prefix = prefix
|
14
8
|
@then_processor = then_processor
|
@@ -3,12 +3,6 @@
|
|
3
3
|
module Leftovers
|
4
4
|
module ValueProcessors
|
5
5
|
class DeleteSuffix
|
6
|
-
# :nocov:
|
7
|
-
if defined?(::Leftovers::Backports::StringDeletePrefixSuffix)
|
8
|
-
using ::Leftovers::Backports::StringDeletePrefixSuffix
|
9
|
-
end
|
10
|
-
# :nocov:
|
11
|
-
|
12
6
|
def initialize(suffix, then_processor)
|
13
7
|
@suffix = suffix
|
14
8
|
@then_processor = then_processor
|
@@ -16,7 +16,7 @@ module Leftovers
|
|
16
16
|
rescue NoMethodError
|
17
17
|
Leftovers.error <<~MESSAGE
|
18
18
|
Tried using the String#demodulize method, but the activesupport gem was not available and/or not required
|
19
|
-
`gem install activesupport`, and/or add `requires: 'active_support/core_ext/string'` to your .leftovers.yml
|
19
|
+
`gem install activesupport`, and/or add `requires: ['active_support', 'active_support/core_ext/string']` to your .leftovers.yml
|
20
20
|
MESSAGE
|
21
21
|
end
|
22
22
|
end
|
@@ -3,10 +3,6 @@
|
|
3
3
|
module Leftovers
|
4
4
|
module ValueProcessors
|
5
5
|
class Keyword
|
6
|
-
# :nocov:
|
7
|
-
using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
|
8
|
-
# :nocov:
|
9
|
-
|
10
6
|
def initialize(matcher, then_processor)
|
11
7
|
@matcher = matcher
|
12
8
|
@then_processor = then_processor
|
@@ -3,10 +3,6 @@
|
|
3
3
|
module Leftovers
|
4
4
|
module ValueProcessors
|
5
5
|
class KeywordArgument
|
6
|
-
# :nocov:
|
7
|
-
using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
|
8
|
-
# :nocov:
|
9
|
-
|
10
6
|
def initialize(matcher, then_processor)
|
11
7
|
@matcher = matcher
|
12
8
|
@then_processor = then_processor
|
@@ -16,7 +16,7 @@ module Leftovers
|
|
16
16
|
rescue NoMethodError
|
17
17
|
Leftovers.error <<~MESSAGE
|
18
18
|
Tried using the String#parameterize method, but the activesupport gem was not available and/or not required
|
19
|
-
`gem install activesupport`, and/or add `requires: 'active_support/core_ext/string'` to your .leftovers.yml
|
19
|
+
`gem install activesupport`, and/or add `requires: ['active_support', 'active_support/core_ext/string']` to your .leftovers.yml
|
20
20
|
MESSAGE
|
21
21
|
end
|
22
22
|
end
|
@@ -16,7 +16,7 @@ module Leftovers
|
|
16
16
|
rescue NoMethodError
|
17
17
|
Leftovers.error <<~MESSAGE
|
18
18
|
Tried using the String#pluralize method, but the activesupport gem was not available and/or not required
|
19
|
-
`gem install activesupport`, and/or add `requires: 'active_support/core_ext/string'` to your .leftovers.yml
|
19
|
+
`gem install activesupport`, and/or add `requires: ['active_support', 'active_support/core_ext/string']` to your .leftovers.yml
|
20
20
|
MESSAGE
|
21
21
|
end
|
22
22
|
end
|
@@ -3,10 +3,6 @@
|
|
3
3
|
module Leftovers
|
4
4
|
module ValueProcessors
|
5
5
|
module ReturnDefinition
|
6
|
-
# :nocov:
|
7
|
-
using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
|
8
|
-
# :nocov:
|
9
|
-
|
10
6
|
def self.process(str, node, method_node)
|
11
7
|
return unless str
|
12
8
|
return if str.empty?
|
@@ -16,7 +16,7 @@ module Leftovers
|
|
16
16
|
rescue NoMethodError
|
17
17
|
Leftovers.error <<~MESSAGE
|
18
18
|
Tried using the String#singularize method, but the activesupport gem was not available and/or not required
|
19
|
-
`gem install activesupport`, and/or add `requires: 'active_support/core_ext/string'` to your .leftovers.yml
|
19
|
+
`gem install activesupport`, and/or add `requires: ['active_support', 'active_support/core_ext/string']` to your .leftovers.yml
|
20
20
|
MESSAGE
|
21
21
|
end
|
22
22
|
end
|
@@ -16,7 +16,7 @@ module Leftovers
|
|
16
16
|
rescue NoMethodError
|
17
17
|
Leftovers.error <<~MESSAGE
|
18
18
|
Tried using the String#titleize method, but the activesupport gem was not available and/or not required
|
19
|
-
`gem install activesupport`, and/or add `requires: 'active_support/core_ext/string'` to your .leftovers.yml
|
19
|
+
`gem install activesupport`, and/or add `requires: ['active_support', 'active_support/core_ext/string']` to your .leftovers.yml
|
20
20
|
MESSAGE
|
21
21
|
end
|
22
22
|
end
|
@@ -16,7 +16,7 @@ module Leftovers
|
|
16
16
|
rescue NoMethodError
|
17
17
|
Leftovers.error <<~MESSAGE
|
18
18
|
Tried using the String#underscore method, but the activesupport gem was not available and/or not required
|
19
|
-
`gem install activesupport`, and/or add `requires: 'active_support/core_ext/string'` to your .leftovers.yml
|
19
|
+
`gem install activesupport`, and/or add `requires: ['active_support', 'active_support/core_ext/string']` to your .leftovers.yml
|
20
20
|
MESSAGE
|
21
21
|
end
|
22
22
|
end
|
data/lib/leftovers/version.rb
CHANGED
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module Leftovers
|
6
|
+
module YAML
|
7
|
+
class Builder < ::Psych::TreeBuilder
|
8
|
+
def initialize
|
9
|
+
@constants = []
|
10
|
+
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
def add_constant_for_tag(tag, value = nil)
|
15
|
+
match = %r{\A!ruby/[^:]*(?::(.*))?\z}.match(tag)
|
16
|
+
return unless match
|
17
|
+
|
18
|
+
@constants << (match[1] || value)
|
19
|
+
end
|
20
|
+
|
21
|
+
def start_mapping(_anchor, tag, *rest) # leftovers:keep
|
22
|
+
add_constant_for_tag(tag)
|
23
|
+
tag = nil
|
24
|
+
|
25
|
+
super
|
26
|
+
end
|
27
|
+
|
28
|
+
def start_sequence(_anchor, tag, *rest) # leftovers:keep
|
29
|
+
add_constant_for_tag(tag)
|
30
|
+
tag = nil
|
31
|
+
|
32
|
+
super
|
33
|
+
end
|
34
|
+
|
35
|
+
def scalar(value, _anchor, tag, *rest) # leftovers:keep
|
36
|
+
add_constant_for_tag(tag, value)
|
37
|
+
tag = nil
|
38
|
+
|
39
|
+
super
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_ruby_file
|
43
|
+
<<~RUBY
|
44
|
+
__leftovers_document(#{to_ruby_argument(root.to_ruby.first)})
|
45
|
+
#{@constants.join("\n")}
|
46
|
+
RUBY
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def to_ruby_argument(value)
|
52
|
+
ruby = value.inspect
|
53
|
+
return ruby unless value.is_a?(Array)
|
54
|
+
|
55
|
+
ruby.delete_prefix!('[')
|
56
|
+
ruby.delete_suffix!(']')
|
57
|
+
|
58
|
+
ruby
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.precompile(yaml, name)
|
63
|
+
builder = ::Leftovers::YAML::Builder.new
|
64
|
+
parser = ::Psych::Parser.new(builder)
|
65
|
+
parser.parse(yaml, name.relative_path)
|
66
|
+
|
67
|
+
builder.to_ruby_file
|
68
|
+
rescue ::Psych::SyntaxError => e
|
69
|
+
Leftovers.warn "#{e.class}: #{e.message}"
|
70
|
+
''
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|