leftovers 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (144) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +23 -0
  3. data/README.md +28 -45
  4. data/docs/Configuration.md +598 -0
  5. data/exe/leftovers +1 -1
  6. data/leftovers.gemspec +9 -6
  7. data/lib/config/attr_encrypted.yml +3 -4
  8. data/lib/config/audited.yml +9 -4
  9. data/lib/config/datagrid.yml +1 -1
  10. data/lib/config/flipper.yml +1 -3
  11. data/lib/config/graphql.yml +15 -13
  12. data/lib/config/okcomputer.yml +1 -3
  13. data/lib/config/parser.yml +89 -91
  14. data/lib/config/rails.yml +125 -107
  15. data/lib/config/redcarpet.yml +35 -38
  16. data/lib/config/rollbar.yml +1 -3
  17. data/lib/config/rspec.yml +18 -10
  18. data/lib/config/ruby.yml +40 -50
  19. data/lib/config/selenium-webdriver.yml +19 -21
  20. data/lib/config/sidekiq.yml +4 -8
  21. data/lib/config/will_paginate.yml +12 -14
  22. data/lib/leftovers.rb +38 -26
  23. data/lib/leftovers/ast.rb +8 -0
  24. data/lib/leftovers/ast/builder.rb +4 -4
  25. data/lib/leftovers/ast/node.rb +50 -77
  26. data/lib/leftovers/backports.rb +27 -23
  27. data/lib/leftovers/cli.rb +0 -3
  28. data/lib/leftovers/collector.rb +4 -8
  29. data/lib/leftovers/config.rb +19 -25
  30. data/lib/leftovers/config_validator.rb +60 -0
  31. data/lib/leftovers/config_validator/error_processor.rb +196 -0
  32. data/lib/leftovers/config_validator/schema_hash.rb +495 -0
  33. data/lib/leftovers/definition.rb +11 -36
  34. data/lib/leftovers/definition_set.rb +7 -17
  35. data/lib/leftovers/dynamic_processors.rb +11 -0
  36. data/lib/leftovers/dynamic_processors/call.rb +25 -0
  37. data/lib/leftovers/dynamic_processors/call_definition.rb +31 -0
  38. data/lib/leftovers/dynamic_processors/definition.rb +26 -0
  39. data/lib/leftovers/dynamic_processors/each.rb +19 -0
  40. data/lib/leftovers/dynamic_processors/null.rb +9 -0
  41. data/lib/leftovers/erb.rb +2 -2
  42. data/lib/leftovers/file.rb +3 -5
  43. data/lib/leftovers/file_collector.rb +65 -49
  44. data/lib/leftovers/file_list.rb +0 -1
  45. data/lib/leftovers/haml.rb +1 -1
  46. data/lib/leftovers/matcher_builders.rb +24 -0
  47. data/lib/leftovers/matcher_builders/and.rb +19 -0
  48. data/lib/leftovers/matcher_builders/and_not.rb +14 -0
  49. data/lib/leftovers/matcher_builders/argument_node_value.rb +21 -0
  50. data/lib/leftovers/matcher_builders/name.rb +29 -0
  51. data/lib/leftovers/matcher_builders/node.rb +40 -0
  52. data/lib/leftovers/matcher_builders/node_has_argument.rb +71 -0
  53. data/lib/leftovers/matcher_builders/node_has_keyword_argument.rb +22 -0
  54. data/lib/leftovers/matcher_builders/node_has_positional_argument.rb +24 -0
  55. data/lib/leftovers/matcher_builders/node_name.rb +15 -0
  56. data/lib/leftovers/matcher_builders/node_pair_name.rb +18 -0
  57. data/lib/leftovers/matcher_builders/node_pair_value.rb +16 -0
  58. data/lib/leftovers/matcher_builders/node_path.rb +14 -0
  59. data/lib/leftovers/matcher_builders/node_type.rb +28 -0
  60. data/lib/leftovers/matcher_builders/or.rb +73 -0
  61. data/lib/leftovers/matcher_builders/path.rb +15 -0
  62. data/lib/leftovers/matcher_builders/string.rb +11 -0
  63. data/lib/leftovers/matcher_builders/string_pattern.rb +19 -0
  64. data/lib/leftovers/matcher_builders/unless.rb +13 -0
  65. data/lib/leftovers/matchers.rb +26 -0
  66. data/lib/leftovers/matchers/all.rb +25 -0
  67. data/lib/leftovers/matchers/and.rb +24 -0
  68. data/lib/leftovers/matchers/any.rb +27 -0
  69. data/lib/leftovers/matchers/node_has_any_keyword_argument.rb +28 -0
  70. data/lib/leftovers/matchers/node_has_any_positional_argument_with_value.rb +25 -0
  71. data/lib/leftovers/matchers/node_has_positional_argument.rb +23 -0
  72. data/lib/leftovers/matchers/node_has_positional_argument_with_value.rb +25 -0
  73. data/lib/leftovers/matchers/node_name.rb +23 -0
  74. data/lib/leftovers/matchers/node_pair_value.rb +23 -0
  75. data/lib/leftovers/matchers/node_path.rb +23 -0
  76. data/lib/leftovers/matchers/node_scalar_value.rb +25 -0
  77. data/lib/leftovers/matchers/node_type.rb +23 -0
  78. data/lib/leftovers/matchers/not.rb +23 -0
  79. data/lib/leftovers/matchers/or.rb +26 -0
  80. data/lib/leftovers/merged_config.rb +13 -8
  81. data/lib/leftovers/parser.rb +1 -4
  82. data/lib/leftovers/processor_builders.rb +22 -0
  83. data/lib/leftovers/processor_builders/action.rb +63 -0
  84. data/lib/leftovers/processor_builders/add_prefix.rb +20 -0
  85. data/lib/leftovers/processor_builders/add_suffix.rb +20 -0
  86. data/lib/leftovers/processor_builders/argument.rb +25 -0
  87. data/lib/leftovers/processor_builders/dynamic.rb +27 -0
  88. data/lib/leftovers/processor_builders/each.rb +36 -0
  89. data/lib/leftovers/processor_builders/each_action.rb +51 -0
  90. data/lib/leftovers/processor_builders/each_dynamic.rb +54 -0
  91. data/lib/leftovers/processor_builders/each_for_definition_set.rb +36 -0
  92. data/lib/leftovers/processor_builders/itself.rb +13 -0
  93. data/lib/leftovers/processor_builders/keyword.rb +24 -0
  94. data/lib/leftovers/processor_builders/keyword_argument.rb +14 -0
  95. data/lib/leftovers/processor_builders/transform.rb +55 -0
  96. data/lib/leftovers/processor_builders/transform_chain.rb +24 -0
  97. data/lib/leftovers/processor_builders/transform_set.rb +47 -0
  98. data/lib/leftovers/processor_builders/value.rb +13 -0
  99. data/lib/leftovers/rake_task.rb +1 -1
  100. data/lib/leftovers/reporter.rb +1 -1
  101. data/lib/leftovers/value_processors.rb +40 -0
  102. data/lib/leftovers/value_processors/add_dynamic_prefix.rb +31 -0
  103. data/lib/leftovers/value_processors/add_dynamic_suffix.rb +31 -0
  104. data/lib/leftovers/value_processors/add_prefix.rb +20 -0
  105. data/lib/leftovers/value_processors/add_suffix.rb +20 -0
  106. data/lib/leftovers/value_processors/camelize.rb +24 -0
  107. data/lib/leftovers/value_processors/capitalize.rb +19 -0
  108. data/lib/leftovers/value_processors/deconstantize.rb +24 -0
  109. data/lib/leftovers/value_processors/delete_after.rb +22 -0
  110. data/lib/leftovers/value_processors/delete_before.rb +22 -0
  111. data/lib/leftovers/value_processors/delete_prefix.rb +26 -0
  112. data/lib/leftovers/value_processors/delete_suffix.rb +26 -0
  113. data/lib/leftovers/value_processors/demodulize.rb +24 -0
  114. data/lib/leftovers/value_processors/downcase.rb +19 -0
  115. data/lib/leftovers/value_processors/each.rb +21 -0
  116. data/lib/leftovers/value_processors/each_for_definition_set.rb +33 -0
  117. data/lib/leftovers/value_processors/each_keyword.rb +27 -0
  118. data/lib/leftovers/value_processors/each_keyword_argument.rb +27 -0
  119. data/lib/leftovers/value_processors/each_positional_argument.rb +24 -0
  120. data/lib/leftovers/value_processors/itself.rb +17 -0
  121. data/lib/leftovers/value_processors/keyword.rb +36 -0
  122. data/lib/leftovers/value_processors/keyword_argument.rb +36 -0
  123. data/lib/leftovers/value_processors/parameterize.rb +24 -0
  124. data/lib/leftovers/value_processors/placeholder.rb +18 -0
  125. data/lib/leftovers/value_processors/pluralize.rb +24 -0
  126. data/lib/leftovers/value_processors/positional_argument.rb +26 -0
  127. data/lib/leftovers/value_processors/replace_value.rb +18 -0
  128. data/lib/leftovers/value_processors/return_definition.rb +24 -0
  129. data/lib/leftovers/value_processors/return_string.rb +14 -0
  130. data/lib/leftovers/value_processors/singularize.rb +24 -0
  131. data/lib/leftovers/value_processors/split.rb +22 -0
  132. data/lib/leftovers/value_processors/swapcase.rb +19 -0
  133. data/lib/leftovers/value_processors/titleize.rb +24 -0
  134. data/lib/leftovers/value_processors/underscore.rb +24 -0
  135. data/lib/leftovers/value_processors/upcase.rb +19 -0
  136. data/lib/leftovers/version.rb +1 -1
  137. metadata +143 -24
  138. data/lib/leftovers/argument_rule.rb +0 -229
  139. data/lib/leftovers/core_ext.rb +0 -15
  140. data/lib/leftovers/hash_rule.rb +0 -42
  141. data/lib/leftovers/name_rule.rb +0 -98
  142. data/lib/leftovers/rule.rb +0 -82
  143. data/lib/leftovers/transform_rule.rb +0 -169
  144. data/lib/leftovers/value_rule.rb +0 -57
@@ -0,0 +1,8 @@
1
+ # frozen-string-literal: true
2
+
3
+ module Leftovers
4
+ module AST
5
+ autoload(:Builder, "#{__dir__}/ast/builder")
6
+ autoload(:Node, "#{__dir__}/ast/node")
7
+ end
8
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'node'
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
@@ -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
- # TODO: move file to loc.
25
- def file
26
- @memo[:file]
20
+ def second
21
+ children[1]
27
22
  end
28
23
 
29
- def file=(value)
30
- @memo[:file] = value
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 to_scalar_value # rubocop:disable Metrics/MethodLength
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&.to_s || to_scalar_value.to_s || ''
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 # rubocop:disable Metrics/MethodLength
80
- @memo[:arguments] ||= case type
81
- when :send, :csend then children.drop(2)
82
- when :casgn then [children[2]]
83
- when :ivasgn, :cvasgn, :gvasgn then [children[1]]
84
- else
85
- # :nocov: # these are all the nodes with collect_rules
86
- raise "Not argument node (#{type})"
87
- # :nocov:
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[:positional_arguments] ||= kwargs ? arguments[0...-1] : arguments
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
- last_arg = arguments[-1]&.unwrap_freeze
104
- @memo[:kwargs] = (last_arg if last_arg&.type == :hash)
105
- end
106
- end
117
+ @memo[:kwargs] = begin
118
+ args = arguments
119
+ next unless args
107
120
 
108
- def keys
109
- each_pair.map { |k, _| k }
110
- end
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 # rubocop:disable Metrics/MethodLength
127
+ def name
140
128
  @memo[:name] ||= case type
141
129
  when :send, :csend, :casgn, :const
142
- children[1]
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 :module, :class
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
@@ -1,34 +1,38 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Leftovers
4
- ruby_version = Gem::Version.new(RUBY_VERSION)
5
- unless ruby_version >= Gem::Version.new('2.5')
6
- require 'set'
7
- module SetCaseEq
8
- refine ::Set do
9
- def ===(value)
10
- include?(value)
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
- def delete_suffix!(str)
22
- slice!(-str.length..-1) if end_with?(str)
23
- self
24
- end
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
- def delete_prefix(str)
27
- dup.delete_prefix!(str)
28
- end
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
- def delete_suffix(str)
31
- dup.delete_suffix!(str)
33
+ def delete_suffix(str)
34
+ dup.delete_suffix!(str)
35
+ end
32
36
  end
33
37
  end
34
38
  end
@@ -1,9 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'optparse'
4
- require_relative '../leftovers'
5
- require_relative 'version'
6
-
7
4
  module Leftovers
8
5
  class CLI
9
6
  def initialize(argv: [], stdout: $stdout, stderr: $stderr)
@@ -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 # rubocop:disable Metrics/MethodLength
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) # rubocop:disable Metrics/MethodLength
49
+ def finish_file(_, _, result)
54
50
  @count += 1
55
51
  @count_calls += result[:calls].length
56
52
  @count_definitions += result[:definitions].length
@@ -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 rules
37
- @rules ||= Rule.wrap(yaml[:rules])
38
- rescue Leftovers::ConfigError => e
39
- warn "\e[31mConfig Error: (#{path}): #{e.message}\e[0m"
40
- Leftovers.exit 1
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 # rubocop:disable Metrics/MethodLength
57
+ def yaml
58
+ @yaml ||= ::Leftovers::ConfigValidator.validate_and_process!(parse_yaml, path)
59
+ end
60
+
61
+ def parse_yaml
54
62
  # :nocov:
55
- @yaml ||= if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.6')
56
- Psych.safe_load(content, symbolize_names: true, filename: path) || {}
63
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.6')
64
+ Psych.safe_load(content, filename: path) || {}
57
65
  else
58
- symbolize_names!(Psych.safe_load(content, [], [], false, path)) || {}
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