leftovers 0.3.0 → 0.4.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 +23 -0
- data/README.md +28 -45
- data/docs/Configuration.md +598 -0
- data/exe/leftovers +1 -1
- data/leftovers.gemspec +9 -6
- data/lib/config/attr_encrypted.yml +3 -4
- data/lib/config/audited.yml +9 -4
- data/lib/config/datagrid.yml +1 -1
- data/lib/config/flipper.yml +1 -3
- data/lib/config/graphql.yml +15 -13
- data/lib/config/okcomputer.yml +1 -3
- data/lib/config/parser.yml +89 -91
- data/lib/config/rails.yml +125 -107
- data/lib/config/redcarpet.yml +35 -38
- data/lib/config/rollbar.yml +1 -3
- data/lib/config/rspec.yml +18 -10
- data/lib/config/ruby.yml +40 -50
- data/lib/config/selenium-webdriver.yml +19 -21
- data/lib/config/sidekiq.yml +4 -8
- data/lib/config/will_paginate.yml +12 -14
- data/lib/leftovers.rb +38 -26
- data/lib/leftovers/ast.rb +8 -0
- data/lib/leftovers/ast/builder.rb +4 -4
- data/lib/leftovers/ast/node.rb +50 -77
- data/lib/leftovers/backports.rb +27 -23
- data/lib/leftovers/cli.rb +0 -3
- data/lib/leftovers/collector.rb +4 -8
- data/lib/leftovers/config.rb +19 -25
- data/lib/leftovers/config_validator.rb +60 -0
- data/lib/leftovers/config_validator/error_processor.rb +196 -0
- data/lib/leftovers/config_validator/schema_hash.rb +495 -0
- data/lib/leftovers/definition.rb +11 -36
- data/lib/leftovers/definition_set.rb +7 -17
- data/lib/leftovers/dynamic_processors.rb +11 -0
- data/lib/leftovers/dynamic_processors/call.rb +25 -0
- data/lib/leftovers/dynamic_processors/call_definition.rb +31 -0
- data/lib/leftovers/dynamic_processors/definition.rb +26 -0
- data/lib/leftovers/dynamic_processors/each.rb +19 -0
- data/lib/leftovers/dynamic_processors/null.rb +9 -0
- data/lib/leftovers/erb.rb +2 -2
- data/lib/leftovers/file.rb +3 -5
- data/lib/leftovers/file_collector.rb +65 -49
- data/lib/leftovers/file_list.rb +0 -1
- data/lib/leftovers/haml.rb +1 -1
- data/lib/leftovers/matcher_builders.rb +24 -0
- data/lib/leftovers/matcher_builders/and.rb +19 -0
- data/lib/leftovers/matcher_builders/and_not.rb +14 -0
- data/lib/leftovers/matcher_builders/argument_node_value.rb +21 -0
- data/lib/leftovers/matcher_builders/name.rb +29 -0
- data/lib/leftovers/matcher_builders/node.rb +40 -0
- data/lib/leftovers/matcher_builders/node_has_argument.rb +71 -0
- data/lib/leftovers/matcher_builders/node_has_keyword_argument.rb +22 -0
- data/lib/leftovers/matcher_builders/node_has_positional_argument.rb +24 -0
- data/lib/leftovers/matcher_builders/node_name.rb +15 -0
- data/lib/leftovers/matcher_builders/node_pair_name.rb +18 -0
- data/lib/leftovers/matcher_builders/node_pair_value.rb +16 -0
- data/lib/leftovers/matcher_builders/node_path.rb +14 -0
- data/lib/leftovers/matcher_builders/node_type.rb +28 -0
- data/lib/leftovers/matcher_builders/or.rb +73 -0
- data/lib/leftovers/matcher_builders/path.rb +15 -0
- data/lib/leftovers/matcher_builders/string.rb +11 -0
- data/lib/leftovers/matcher_builders/string_pattern.rb +19 -0
- data/lib/leftovers/matcher_builders/unless.rb +13 -0
- data/lib/leftovers/matchers.rb +26 -0
- data/lib/leftovers/matchers/all.rb +25 -0
- data/lib/leftovers/matchers/and.rb +24 -0
- data/lib/leftovers/matchers/any.rb +27 -0
- data/lib/leftovers/matchers/node_has_any_keyword_argument.rb +28 -0
- data/lib/leftovers/matchers/node_has_any_positional_argument_with_value.rb +25 -0
- data/lib/leftovers/matchers/node_has_positional_argument.rb +23 -0
- data/lib/leftovers/matchers/node_has_positional_argument_with_value.rb +25 -0
- data/lib/leftovers/matchers/node_name.rb +23 -0
- data/lib/leftovers/matchers/node_pair_value.rb +23 -0
- data/lib/leftovers/matchers/node_path.rb +23 -0
- data/lib/leftovers/matchers/node_scalar_value.rb +25 -0
- data/lib/leftovers/matchers/node_type.rb +23 -0
- data/lib/leftovers/matchers/not.rb +23 -0
- data/lib/leftovers/matchers/or.rb +26 -0
- data/lib/leftovers/merged_config.rb +13 -8
- data/lib/leftovers/parser.rb +1 -4
- data/lib/leftovers/processor_builders.rb +22 -0
- data/lib/leftovers/processor_builders/action.rb +63 -0
- data/lib/leftovers/processor_builders/add_prefix.rb +20 -0
- data/lib/leftovers/processor_builders/add_suffix.rb +20 -0
- data/lib/leftovers/processor_builders/argument.rb +25 -0
- data/lib/leftovers/processor_builders/dynamic.rb +27 -0
- data/lib/leftovers/processor_builders/each.rb +36 -0
- data/lib/leftovers/processor_builders/each_action.rb +51 -0
- data/lib/leftovers/processor_builders/each_dynamic.rb +54 -0
- data/lib/leftovers/processor_builders/each_for_definition_set.rb +36 -0
- data/lib/leftovers/processor_builders/itself.rb +13 -0
- data/lib/leftovers/processor_builders/keyword.rb +24 -0
- data/lib/leftovers/processor_builders/keyword_argument.rb +14 -0
- data/lib/leftovers/processor_builders/transform.rb +55 -0
- data/lib/leftovers/processor_builders/transform_chain.rb +24 -0
- data/lib/leftovers/processor_builders/transform_set.rb +47 -0
- data/lib/leftovers/processor_builders/value.rb +13 -0
- data/lib/leftovers/rake_task.rb +1 -1
- data/lib/leftovers/reporter.rb +1 -1
- data/lib/leftovers/value_processors.rb +40 -0
- data/lib/leftovers/value_processors/add_dynamic_prefix.rb +31 -0
- data/lib/leftovers/value_processors/add_dynamic_suffix.rb +31 -0
- data/lib/leftovers/value_processors/add_prefix.rb +20 -0
- data/lib/leftovers/value_processors/add_suffix.rb +20 -0
- data/lib/leftovers/value_processors/camelize.rb +24 -0
- data/lib/leftovers/value_processors/capitalize.rb +19 -0
- data/lib/leftovers/value_processors/deconstantize.rb +24 -0
- data/lib/leftovers/value_processors/delete_after.rb +22 -0
- data/lib/leftovers/value_processors/delete_before.rb +22 -0
- data/lib/leftovers/value_processors/delete_prefix.rb +26 -0
- data/lib/leftovers/value_processors/delete_suffix.rb +26 -0
- data/lib/leftovers/value_processors/demodulize.rb +24 -0
- data/lib/leftovers/value_processors/downcase.rb +19 -0
- data/lib/leftovers/value_processors/each.rb +21 -0
- data/lib/leftovers/value_processors/each_for_definition_set.rb +33 -0
- data/lib/leftovers/value_processors/each_keyword.rb +27 -0
- data/lib/leftovers/value_processors/each_keyword_argument.rb +27 -0
- data/lib/leftovers/value_processors/each_positional_argument.rb +24 -0
- data/lib/leftovers/value_processors/itself.rb +17 -0
- data/lib/leftovers/value_processors/keyword.rb +36 -0
- data/lib/leftovers/value_processors/keyword_argument.rb +36 -0
- data/lib/leftovers/value_processors/parameterize.rb +24 -0
- data/lib/leftovers/value_processors/placeholder.rb +18 -0
- data/lib/leftovers/value_processors/pluralize.rb +24 -0
- data/lib/leftovers/value_processors/positional_argument.rb +26 -0
- data/lib/leftovers/value_processors/replace_value.rb +18 -0
- data/lib/leftovers/value_processors/return_definition.rb +24 -0
- data/lib/leftovers/value_processors/return_string.rb +14 -0
- data/lib/leftovers/value_processors/singularize.rb +24 -0
- data/lib/leftovers/value_processors/split.rb +22 -0
- data/lib/leftovers/value_processors/swapcase.rb +19 -0
- data/lib/leftovers/value_processors/titleize.rb +24 -0
- data/lib/leftovers/value_processors/underscore.rb +24 -0
- data/lib/leftovers/value_processors/upcase.rb +19 -0
- data/lib/leftovers/version.rb +1 -1
- metadata +143 -24
- data/lib/leftovers/argument_rule.rb +0 -229
- data/lib/leftovers/core_ext.rb +0 -15
- data/lib/leftovers/hash_rule.rb +0 -42
- data/lib/leftovers/name_rule.rb +0 -98
- data/lib/leftovers/rule.rb +0 -82
- data/lib/leftovers/transform_rule.rb +0 -169
- data/lib/leftovers/value_rule.rb +0 -57
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
require 'parser'
|
|
4
4
|
|
|
5
5
|
module Leftovers
|
|
6
6
|
module AST
|
|
@@ -9,12 +9,12 @@ module Leftovers
|
|
|
9
9
|
#
|
|
10
10
|
# @return [Node] the generated node
|
|
11
11
|
|
|
12
|
-
def n(type, children, source_map)
|
|
13
|
-
Leftovers::AST::Node.new(type, children, location: source_map)
|
|
12
|
+
def n(type, children, source_map) # leftovers:keep
|
|
13
|
+
::Leftovers::AST::Node.new(type, children, location: source_map)
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
# Don't complain about invalid strings
|
|
17
|
-
def string_value(token)
|
|
17
|
+
def string_value(token) # leftovers:keep
|
|
18
18
|
value(token)
|
|
19
19
|
end
|
|
20
20
|
end
|
data/lib/leftovers/ast/node.rb
CHANGED
|
@@ -4,11 +4,7 @@ require 'parser'
|
|
|
4
4
|
|
|
5
5
|
module Leftovers
|
|
6
6
|
module AST
|
|
7
|
-
class Node < Parser::AST::Node # rubocop:disable Metrics/ClassLength
|
|
8
|
-
# :nocov:
|
|
9
|
-
using ::Leftovers::SetCaseEq if defined?(::Leftovers::SetCaseEq)
|
|
10
|
-
# :nocov:
|
|
11
|
-
|
|
7
|
+
class Node < ::Parser::AST::Node # rubocop:disable Metrics/ClassLength
|
|
12
8
|
def initialize(type, children = [], properties = {})
|
|
13
9
|
# ::AST::Node#initialize freezes itself.
|
|
14
10
|
# so can't use normal memoizations
|
|
@@ -21,25 +17,31 @@ module Leftovers
|
|
|
21
17
|
children.first
|
|
22
18
|
end
|
|
23
19
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
@memo[:file]
|
|
20
|
+
def second
|
|
21
|
+
children[1]
|
|
27
22
|
end
|
|
28
23
|
|
|
29
|
-
def
|
|
30
|
-
@memo[:
|
|
24
|
+
def path
|
|
25
|
+
@memo[:path] ||= loc.expression.source_buffer.name.to_s
|
|
31
26
|
end
|
|
32
27
|
|
|
33
|
-
def test
|
|
28
|
+
def test?
|
|
34
29
|
@memo[:test]
|
|
35
30
|
end
|
|
36
|
-
alias_method :test?, :test
|
|
37
31
|
|
|
38
32
|
def test=(value)
|
|
39
33
|
@memo[:test] = value
|
|
40
34
|
end
|
|
41
35
|
|
|
42
|
-
def
|
|
36
|
+
def keep_line=(value)
|
|
37
|
+
@memo[:keep_line] = value
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def keep_line?
|
|
41
|
+
@memo[:keep_line]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def to_scalar_value
|
|
43
45
|
case type
|
|
44
46
|
when :sym, :int, :float, :str
|
|
45
47
|
first
|
|
@@ -61,7 +63,7 @@ module Leftovers
|
|
|
61
63
|
end
|
|
62
64
|
|
|
63
65
|
def to_s
|
|
64
|
-
@memo[:to_s] ||= name
|
|
66
|
+
@memo[:to_s] ||= name ? name.to_s : to_scalar_value.to_s
|
|
65
67
|
end
|
|
66
68
|
|
|
67
69
|
def to_sym
|
|
@@ -76,20 +78,32 @@ module Leftovers
|
|
|
76
78
|
type == :str || type == :sym
|
|
77
79
|
end
|
|
78
80
|
|
|
79
|
-
def arguments
|
|
80
|
-
@memo
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
81
|
+
def arguments
|
|
82
|
+
@memo.fetch(:arguments) do
|
|
83
|
+
@memo[:arguments] = case type
|
|
84
|
+
when :send, :csend then children.drop(2)
|
|
85
|
+
when :casgn then assign_arguments(children[2])
|
|
86
|
+
when :ivasgn, :cvasgn, :gvasgn then assign_arguments(second)
|
|
87
|
+
when :array then children
|
|
88
|
+
when :hash then [self]
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def assign_arguments(arguments_list)
|
|
94
|
+
arguments_list = arguments_list.unwrap_freeze
|
|
95
|
+
case arguments_list.type
|
|
96
|
+
when :array
|
|
97
|
+
arguments_list.children
|
|
98
|
+
when :hash, :str, :sym
|
|
99
|
+
[arguments_list]
|
|
88
100
|
end
|
|
89
101
|
end
|
|
90
102
|
|
|
91
103
|
def positional_arguments
|
|
92
|
-
@memo
|
|
104
|
+
@memo.fetch(:positional_arguments) do
|
|
105
|
+
@memo[:positional_arguments] = kwargs ? arguments[0...-1] : arguments
|
|
106
|
+
end
|
|
93
107
|
end
|
|
94
108
|
|
|
95
109
|
def unwrap_freeze
|
|
@@ -100,69 +114,28 @@ module Leftovers
|
|
|
100
114
|
|
|
101
115
|
def kwargs
|
|
102
116
|
@memo.fetch(:kwargs) do
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
end
|
|
117
|
+
@memo[:kwargs] = begin
|
|
118
|
+
args = arguments
|
|
119
|
+
next unless args
|
|
107
120
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
def values
|
|
113
|
-
# :nocov:
|
|
114
|
-
@memo[:kwargs] ||= case type
|
|
115
|
-
# :nocov:
|
|
116
|
-
when :hash then each_pair.map { |_, v| v }
|
|
117
|
-
when :array then children
|
|
118
|
-
end
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
def values_at_match(matcher)
|
|
122
|
-
each_pair.with_object([]) do |(key, value), values|
|
|
123
|
-
values << value if matcher === key.to_sym
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
def positional_arguments_at(positions)
|
|
128
|
-
positional_arguments.values_at(*positions).compact
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
def each_pair
|
|
132
|
-
return enum_for(:each_pair) unless block_given?
|
|
133
|
-
|
|
134
|
-
children.each do |pair|
|
|
135
|
-
yield(*pair.children) if pair.type == :pair
|
|
121
|
+
last_arg = args[-1]
|
|
122
|
+
last_arg if last_arg && last_arg.type == :hash
|
|
123
|
+
end
|
|
136
124
|
end
|
|
137
125
|
end
|
|
138
126
|
|
|
139
|
-
def name
|
|
127
|
+
def name
|
|
140
128
|
@memo[:name] ||= case type
|
|
141
129
|
when :send, :csend, :casgn, :const
|
|
142
|
-
|
|
143
|
-
when :def, :ivasgn, :ivar, :gvar, :cvar, :gvasgn, :cvasgn
|
|
130
|
+
second
|
|
131
|
+
when :def, :ivasgn, :ivar, :gvar, :cvar, :gvasgn, :cvasgn, :sym
|
|
144
132
|
first
|
|
145
|
-
when :
|
|
133
|
+
when :str
|
|
134
|
+
first.to_sym
|
|
135
|
+
when :module, :class, :pair
|
|
146
136
|
first.name
|
|
147
137
|
end
|
|
148
138
|
end
|
|
149
|
-
|
|
150
|
-
def [](index) # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
|
|
151
|
-
# :nocov:
|
|
152
|
-
case type
|
|
153
|
-
# :nocov:
|
|
154
|
-
when :send, :csend, :casgn, :cvasgn, :ivasgn, :gvasgn
|
|
155
|
-
index.is_a?(Integer) ? arguments[index - 1] : kwargs && kwargs[index]
|
|
156
|
-
when :hash
|
|
157
|
-
each_pair do |key, value|
|
|
158
|
-
next unless key.string_or_symbol?
|
|
159
|
-
|
|
160
|
-
return value if key.to_sym == index
|
|
161
|
-
end
|
|
162
|
-
|
|
163
|
-
nil
|
|
164
|
-
end
|
|
165
|
-
end
|
|
166
139
|
end
|
|
167
140
|
end
|
|
168
141
|
end
|
data/lib/leftovers/backports.rb
CHANGED
|
@@ -1,34 +1,38 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Leftovers
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
4
|
+
module Backports
|
|
5
|
+
ruby_version = Gem::Version.new(RUBY_VERSION)
|
|
6
|
+
|
|
7
|
+
unless ruby_version >= Gem::Version.new('2.5')
|
|
8
|
+
require 'set'
|
|
9
|
+
module SetCaseEq
|
|
10
|
+
refine ::Set do
|
|
11
|
+
def ===(value)
|
|
12
|
+
include?(value)
|
|
13
|
+
end
|
|
11
14
|
end
|
|
12
15
|
end
|
|
13
|
-
end
|
|
14
|
-
module StringDeletePrefixSuffix
|
|
15
|
-
refine ::String do
|
|
16
|
-
def delete_prefix!(str)
|
|
17
|
-
slice!(0..(str.length - 1)) if start_with?(str)
|
|
18
|
-
self
|
|
19
|
-
end
|
|
20
16
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
17
|
+
module StringDeletePrefixSuffix
|
|
18
|
+
refine ::String do
|
|
19
|
+
def delete_prefix!(str)
|
|
20
|
+
slice!(0..(str.length - 1)) if start_with?(str)
|
|
21
|
+
self
|
|
22
|
+
end
|
|
25
23
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
def delete_suffix!(str)
|
|
25
|
+
slice!(-str.length..-1) if end_with?(str)
|
|
26
|
+
self
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def delete_prefix(str)
|
|
30
|
+
dup.delete_prefix!(str)
|
|
31
|
+
end
|
|
29
32
|
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
def delete_suffix(str)
|
|
34
|
+
dup.delete_suffix!(str)
|
|
35
|
+
end
|
|
32
36
|
end
|
|
33
37
|
end
|
|
34
38
|
end
|
data/lib/leftovers/cli.rb
CHANGED
data/lib/leftovers/collector.rb
CHANGED
|
@@ -3,16 +3,12 @@
|
|
|
3
3
|
require 'fast_ignore'
|
|
4
4
|
require 'set'
|
|
5
5
|
require 'parallel'
|
|
6
|
-
require_relative 'file_collector'
|
|
7
|
-
require_relative 'file_list'
|
|
8
6
|
|
|
9
7
|
module Leftovers
|
|
10
8
|
class Collector
|
|
11
|
-
attr_reader :calls
|
|
12
|
-
attr_reader :test_calls
|
|
13
|
-
attr_reader :definitions
|
|
9
|
+
attr_reader :calls, :test_calls, :definitions
|
|
14
10
|
|
|
15
|
-
def initialize
|
|
11
|
+
def initialize
|
|
16
12
|
@calls = []
|
|
17
13
|
@test_calls = []
|
|
18
14
|
@definitions = []
|
|
@@ -38,7 +34,7 @@ module Leftovers
|
|
|
38
34
|
end
|
|
39
35
|
|
|
40
36
|
def collect_file(file)
|
|
41
|
-
file_collector = Leftovers::FileCollector.new(file.ruby, file)
|
|
37
|
+
file_collector = ::Leftovers::FileCollector.new(file.ruby, file)
|
|
42
38
|
file_collector.collect
|
|
43
39
|
|
|
44
40
|
file_collector.to_h
|
|
@@ -50,7 +46,7 @@ module Leftovers
|
|
|
50
46
|
)
|
|
51
47
|
end
|
|
52
48
|
|
|
53
|
-
def finish_file(_, _, result)
|
|
49
|
+
def finish_file(_, _, result)
|
|
54
50
|
@count += 1
|
|
55
51
|
@count_calls += result[:calls].length
|
|
56
52
|
@count_definitions += result[:definitions].length
|
data/lib/leftovers/config.rb
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'yaml'
|
|
4
|
-
require_relative 'rule'
|
|
5
4
|
|
|
6
5
|
module Leftovers
|
|
7
6
|
class Config
|
|
8
7
|
# :nocov:
|
|
9
|
-
using ::Leftovers::SetCaseEq if defined?(::Leftovers::SetCaseEq)
|
|
8
|
+
using ::Leftovers::Backports::SetCaseEq if defined?(::Leftovers::Backports::SetCaseEq)
|
|
10
9
|
# :nocov:
|
|
11
10
|
|
|
12
11
|
attr_reader :name
|
|
@@ -33,11 +32,16 @@ module Leftovers
|
|
|
33
32
|
@test_paths ||= Array(yaml[:test_paths])
|
|
34
33
|
end
|
|
35
34
|
|
|
36
|
-
def
|
|
37
|
-
@
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
def dynamic
|
|
36
|
+
@dynamic ||= ::Leftovers::ProcessorBuilders::Dynamic.build(yaml[:dynamic])
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def keep
|
|
40
|
+
@keep ||= ::Leftovers::MatcherBuilders::Node.build(yaml[:keep])
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def requires
|
|
44
|
+
@requires ||= Array(yaml[:requires])
|
|
41
45
|
end
|
|
42
46
|
|
|
43
47
|
private
|
|
@@ -50,31 +54,21 @@ module Leftovers
|
|
|
50
54
|
@path ||= ::File.expand_path("../config/#{name}.yml", __dir__)
|
|
51
55
|
end
|
|
52
56
|
|
|
53
|
-
def yaml
|
|
57
|
+
def yaml
|
|
58
|
+
@yaml ||= ::Leftovers::ConfigValidator.validate_and_process!(parse_yaml, path)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def parse_yaml
|
|
54
62
|
# :nocov:
|
|
55
|
-
|
|
56
|
-
Psych.safe_load(content,
|
|
63
|
+
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.6')
|
|
64
|
+
Psych.safe_load(content, filename: path) || {}
|
|
57
65
|
else
|
|
58
|
-
|
|
66
|
+
Psych.safe_load(content, [], [], false, path) || {}
|
|
59
67
|
end
|
|
60
68
|
# :nocov:
|
|
61
69
|
rescue ::Psych::SyntaxError => e
|
|
62
70
|
warn "\e[31mConfig SyntaxError: #{e.message}\e[0m"
|
|
63
71
|
Leftovers.exit 1
|
|
64
72
|
end
|
|
65
|
-
|
|
66
|
-
# :nocov:
|
|
67
|
-
def symbolize_names!(obj) # rubocop:disable Metrics/MethodLength
|
|
68
|
-
case obj
|
|
69
|
-
when Hash
|
|
70
|
-
obj.keys.each do |key| # rubocop:disable Style/HashEachMethods # each_key never finishes.
|
|
71
|
-
obj[key.to_sym] = symbolize_names!(obj.delete(key))
|
|
72
|
-
end
|
|
73
|
-
when Array
|
|
74
|
-
obj.map! { |ea| symbolize_names!(ea) }
|
|
75
|
-
end
|
|
76
|
-
obj
|
|
77
|
-
end
|
|
78
|
-
# :nocov:
|
|
79
73
|
end
|
|
80
74
|
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
require 'json_schemer'
|
|
4
|
+
|
|
5
|
+
module Leftovers
|
|
6
|
+
module ConfigValidator
|
|
7
|
+
autoload(:ErrorProcessor, "#{__dir__}/config_validator/error_processor")
|
|
8
|
+
autoload(:SCHEMA_HASH, "#{__dir__}/config_validator/schema_hash")
|
|
9
|
+
|
|
10
|
+
def self.default_schema
|
|
11
|
+
@default_schema ||= ::JSONSchemer.schema(::Leftovers::ConfigValidator::SCHEMA_HASH)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.validate(obj, validator = default_schema)
|
|
15
|
+
validator.validate(obj)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.validate_and_process!(yaml, path)
|
|
19
|
+
errors = validate(yaml)
|
|
20
|
+
print_validation_errors_and_exit(errors, path) unless errors.first.nil?
|
|
21
|
+
post_process!(yaml)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.print_validation_errors_and_exit(errors, path)
|
|
25
|
+
::Leftovers::ConfigValidator::ErrorProcessor.process(errors).each do |message|
|
|
26
|
+
warn "\e[31mConfig SchemaError: (#{path}): #{message}\e[0m"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
::Leftovers.exit 1
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.post_process!(obj)
|
|
33
|
+
case obj
|
|
34
|
+
when Hash
|
|
35
|
+
obj.keys.each do |key| # rubocop:disable Style/HashEachMethods # each_key never finishes.
|
|
36
|
+
obj[symbolize_name(key)] = post_process!(obj.delete(key))
|
|
37
|
+
end
|
|
38
|
+
when Array
|
|
39
|
+
obj.map! { |ea| post_process!(ea) }
|
|
40
|
+
end
|
|
41
|
+
obj
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.symbolize_name(name) # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
|
|
45
|
+
case name
|
|
46
|
+
when 'matches' then :match
|
|
47
|
+
when 'defines' then :define
|
|
48
|
+
when 'calls' then :call
|
|
49
|
+
when 'name' then :names
|
|
50
|
+
when 'keyword' then :keywords
|
|
51
|
+
when 'argument' then :arguments
|
|
52
|
+
when 'has_argument' then :has_arguments
|
|
53
|
+
when 'path' then :paths
|
|
54
|
+
when 'unless' then :unless_arg
|
|
55
|
+
when 'require' then :requires
|
|
56
|
+
else name.to_sym
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|