leftovers 0.3.0 → 0.4.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 +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
|