leftovers 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -3
  3. data/docs/Configuration.md +82 -18
  4. data/leftovers.gemspec +1 -1
  5. data/lib/config/actionmailer.yml +11 -11
  6. data/lib/config/activesupport.yml +1 -1
  7. data/lib/config/rails.yml +1 -1
  8. data/lib/config/railties.yml +11 -0
  9. data/lib/config/ruby.yml +72 -0
  10. data/lib/leftovers/ast/node.rb +16 -11
  11. data/lib/leftovers/config.rb +1 -24
  12. data/lib/leftovers/config_loader/argument_position_schema.rb +11 -0
  13. data/lib/leftovers/config_loader/argumentless_transform_schema.rb +21 -0
  14. data/lib/leftovers/config_loader/attribute.rb +30 -0
  15. data/lib/leftovers/config_loader/document_schema.rb +21 -0
  16. data/lib/leftovers/config_loader/dynamic_schema.rb +17 -0
  17. data/lib/leftovers/config_loader/has_argument_schema.rb +13 -0
  18. data/lib/leftovers/config_loader/has_value_schema.rb +18 -0
  19. data/lib/leftovers/config_loader/keep_test_only_schema.rb +13 -0
  20. data/lib/leftovers/config_loader/node.rb +106 -0
  21. data/lib/leftovers/config_loader/object_schema.rb +189 -0
  22. data/lib/leftovers/config_loader/privacy_processor_schema.rb +12 -0
  23. data/lib/leftovers/config_loader/privacy_schema.rb +15 -0
  24. data/lib/leftovers/config_loader/require_schema.rb +11 -0
  25. data/lib/leftovers/config_loader/rule_pattern_schema.rb +18 -0
  26. data/lib/leftovers/config_loader/scalar_argument_schema.rb +14 -0
  27. data/lib/leftovers/config_loader/scalar_value_schema.rb +14 -0
  28. data/lib/leftovers/config_loader/schema.rb +21 -0
  29. data/lib/leftovers/config_loader/string_enum_schema.rb +62 -0
  30. data/lib/leftovers/config_loader/string_pattern_schema.rb +14 -0
  31. data/lib/leftovers/config_loader/string_schema.rb +14 -0
  32. data/lib/leftovers/config_loader/string_value_processor_schema.rb +11 -0
  33. data/lib/leftovers/config_loader/suggester.rb +22 -0
  34. data/lib/leftovers/config_loader/transform_schema.rb +28 -0
  35. data/lib/leftovers/config_loader/true_schema.rb +18 -0
  36. data/lib/leftovers/config_loader/value_matcher_schema.rb +18 -0
  37. data/lib/leftovers/config_loader/value_or_array_schema.rb +64 -0
  38. data/lib/leftovers/config_loader/value_processor_schema.rb +14 -0
  39. data/lib/leftovers/config_loader/value_type_schema.rb +17 -0
  40. data/lib/leftovers/config_loader.rb +82 -0
  41. data/lib/leftovers/definition_node.rb +6 -17
  42. data/lib/leftovers/definition_node_set.rb +11 -0
  43. data/lib/leftovers/definition_to_add.rb +31 -0
  44. data/lib/leftovers/dynamic_processors/call.rb +4 -3
  45. data/lib/leftovers/dynamic_processors/call_definition.rb +14 -7
  46. data/lib/leftovers/dynamic_processors/definition.rb +8 -3
  47. data/lib/leftovers/dynamic_processors/set_default_privacy.rb +18 -0
  48. data/lib/leftovers/dynamic_processors/set_privacy.rb +23 -0
  49. data/lib/leftovers/dynamic_processors.rb +2 -0
  50. data/lib/leftovers/file.rb +5 -1
  51. data/lib/leftovers/file_collector.rb +44 -17
  52. data/lib/leftovers/matcher_builders/node.rb +4 -0
  53. data/lib/leftovers/matcher_builders/node_privacy.rb +13 -0
  54. data/lib/leftovers/matcher_builders/node_type.rb +4 -4
  55. data/lib/leftovers/matcher_builders/node_value.rb +1 -1
  56. data/lib/leftovers/matcher_builders/string_pattern.rb +14 -5
  57. data/lib/leftovers/matcher_builders.rb +1 -0
  58. data/lib/leftovers/matchers/node_privacy.rb +19 -0
  59. data/lib/leftovers/matchers.rb +1 -0
  60. data/lib/leftovers/merged_config.rb +18 -34
  61. data/lib/leftovers/processor_builders/add_prefix.rb +1 -1
  62. data/lib/leftovers/processor_builders/add_suffix.rb +1 -1
  63. data/lib/leftovers/processor_builders/dynamic.rb +50 -16
  64. data/lib/leftovers/processor_builders/transform.rb +2 -2
  65. data/lib/leftovers/processor_builders/transform_set.rb +8 -8
  66. data/lib/leftovers/value_processors/each_for_definition_set.rb +2 -5
  67. data/lib/leftovers/value_processors/each_positional_argument.rb +1 -1
  68. data/lib/leftovers/value_processors/return_definition_node.rb +14 -0
  69. data/lib/leftovers/value_processors/{return_string.rb → return_sym.rb} +1 -1
  70. data/lib/leftovers/value_processors.rb +2 -2
  71. data/lib/leftovers/version.rb +1 -1
  72. data/lib/leftovers.rb +23 -14
  73. metadata +54 -22
  74. data/lib/config/actioncable.yml +0 -4
  75. data/lib/leftovers/config_validator/error_processor.rb +0 -196
  76. data/lib/leftovers/config_validator/schema_hash.rb +0 -551
  77. data/lib/leftovers/config_validator.rb +0 -61
  78. data/lib/leftovers/value_processors/return_definition.rb +0 -22
@@ -6,7 +6,7 @@ module Leftovers
6
6
  def self.build(argument, then_processor)
7
7
  case argument
8
8
  when ::Hash
9
- dynamic_prefix = ::Leftovers::ProcessorBuilders::Action.build(argument, :call)
9
+ dynamic_prefix = ::Leftovers::ProcessorBuilders::Action.build(argument, :sym)
10
10
  ::Leftovers::ValueProcessors::AddDynamicPrefix.new(dynamic_prefix, then_processor)
11
11
  when ::String
12
12
  ::Leftovers::ValueProcessors::AddPrefix.new(argument, then_processor)
@@ -6,7 +6,7 @@ module Leftovers
6
6
  def self.build(argument, then_processor)
7
7
  case argument
8
8
  when ::Hash
9
- dynamic_suffix = ::Leftovers::ProcessorBuilders::Action.build(argument, :call)
9
+ dynamic_suffix = ::Leftovers::ProcessorBuilders::Action.build(argument, :sym)
10
10
  ::Leftovers::ValueProcessors::AddDynamicSuffix.new(dynamic_suffix, then_processor)
11
11
  when ::String
12
12
  ::Leftovers::ValueProcessors::AddSuffix.new(argument, then_processor)
@@ -3,23 +3,57 @@
3
3
  module Leftovers
4
4
  module ProcessorBuilders
5
5
  module Dynamic
6
- def self.build(dynamic_rules) # rubocop:disable Metrics/MethodLength
7
- ::Leftovers::ProcessorBuilders::EachDynamic.each_or_self(dynamic_rules) do |dynamic|
8
- call = ::Leftovers::ProcessorBuilders::Action.build(dynamic.delete(:call), :call)
9
- define = ::Leftovers::ProcessorBuilders::Action.build(dynamic.delete(:define), :define)
10
- matcher = ::Leftovers::MatcherBuilders::Node.build(**dynamic)
11
-
12
- # this nonsense saves a method call and array instantiation per method
13
- if call && define
14
- ::Leftovers::DynamicProcessors::CallDefinition.new(matcher, call, define)
15
- elsif define
16
- ::Leftovers::DynamicProcessors::Definition.new(matcher, define)
17
- elsif call
18
- ::Leftovers::DynamicProcessors::Call.new(matcher, call)
19
- # :nocov:
6
+ class << self
7
+ def build(dynamic_rules)
8
+ ::Leftovers::ProcessorBuilders::EachDynamic.each_or_self(dynamic_rules) do |dynamic|
9
+ build_processors(**dynamic)
10
+ end
11
+ end
12
+
13
+ private
14
+
15
+ def build_processors(
16
+ call: nil, define: nil, set_privacy: nil, set_default_privacy: nil, **matcher_rules
17
+ )
18
+ matcher = ::Leftovers::MatcherBuilders::Node.build(**matcher_rules)
19
+
20
+ ::Leftovers::ProcessorBuilders::EachDynamic.build([
21
+ build_call_define_processor(matcher, call, define),
22
+ build_set_privacy_processor(matcher, set_privacy),
23
+ build_set_default_privacy_processor(matcher, set_default_privacy)
24
+ ])
25
+ end
26
+
27
+ def build_action(processor_rules, return_type:)
28
+ ::Leftovers::ProcessorBuilders::Action.build(processor_rules, return_type)
29
+ end
30
+
31
+ def build_set_privacy_processor(matcher, set_privacy)
32
+ ::Leftovers::ProcessorBuilders::EachDynamic.each_or_self(set_privacy) do |action_values|
33
+ to = action_values.delete(:to)
34
+ action = build_action(action_values, return_type: :sym)
35
+
36
+ ::Leftovers::DynamicProcessors::SetPrivacy.new(matcher, action, to)
37
+ end
38
+ end
39
+
40
+ def build_set_default_privacy_processor(matcher, set_default_privacy)
41
+ ::Leftovers::DynamicProcessors::SetDefaultPrivacy.new(matcher, set_default_privacy)
42
+ end
43
+
44
+ def build_call_define_processor(matcher, call, define) # rubocop:disable Metrics/MethodLength
45
+ call_action = build_action(call, return_type: :sym)
46
+ define_action = build_action(define, return_type: :definition_node)
47
+
48
+ if call_action && define_action
49
+ # this nonsense saves a method call and array instantiation per method
50
+ ::Leftovers::DynamicProcessors::CallDefinition.new(matcher, call_action, define_action)
51
+ elsif define_action
52
+ ::Leftovers::DynamicProcessors::Definition.new(matcher, define_action)
53
+ elsif call_action
54
+ ::Leftovers::DynamicProcessors::Call.new(matcher, call_action)
20
55
  else
21
- raise
22
- # :nocov:
56
+ ::Leftovers::DynamicProcessors::Null
23
57
  end
24
58
  end
25
59
  end
@@ -19,9 +19,9 @@ module Leftovers
19
19
  ::Leftovers::ValueProcessors::Pluralize.new(then_processor)
20
20
  when 'singularize'
21
21
  ::Leftovers::ValueProcessors::Singularize.new(then_processor)
22
- when 'camelize', 'camelcase'
22
+ when 'camelize'
23
23
  ::Leftovers::ValueProcessors::Camelize.new(then_processor)
24
- when 'titleize', 'titlecase'
24
+ when 'titleize'
25
25
  ::Leftovers::ValueProcessors::Titleize.new(then_processor)
26
26
  when 'demodulize'
27
27
  ::Leftovers::ValueProcessors::Demodulize.new(then_processor)
@@ -21,24 +21,24 @@ module Leftovers
21
21
 
22
22
  def self.each_builder(action)
23
23
  case action
24
- when :call
24
+ when :sym
25
25
  ::Leftovers::ProcessorBuilders::Each
26
- when :define
26
+ when :definition_node
27
27
  ::Leftovers::ProcessorBuilders::EachForDefinitionSet
28
28
  # :nocov:
29
- else raise
29
+ else raise "Unknown action #{action}"
30
30
  # :nocov:
31
31
  end
32
32
  end
33
33
 
34
34
  def self.build_final(action)
35
35
  case action
36
- when :call
37
- ::Leftovers::ValueProcessors::ReturnString
38
- when :define
39
- ::Leftovers::ValueProcessors::ReturnDefinition
36
+ when :sym
37
+ ::Leftovers::ValueProcessors::ReturnSym
38
+ when :definition_node
39
+ ::Leftovers::ValueProcessors::ReturnDefinitionNode
40
40
  # :nocov:
41
- else raise
41
+ else raise "Unknown action #{action}"
42
42
  # :nocov:
43
43
  end
44
44
  end
@@ -11,10 +11,7 @@ module Leftovers
11
11
 
12
12
  def process(str, node, method_node)
13
13
  definitions = @then_processors.map do |then_processor|
14
- processed = then_processor.process(str, node, method_node)
15
- return if processed == :keep # rubocop:disable Lint/NonLocalExitFromIterator
16
-
17
- processed
14
+ then_processor.process(str, node, method_node)
18
15
  end
19
16
 
20
17
  definitions.flatten!
@@ -22,7 +19,7 @@ module Leftovers
22
19
 
23
20
  return definitions.first if definitions.length <= 1
24
21
 
25
- ::Leftovers::DefinitionSet.new(definitions)
22
+ ::Leftovers::DefinitionNodeSet.new(definitions)
26
23
  end
27
24
  end
28
25
  end
@@ -14,7 +14,7 @@ module Leftovers
14
14
  return unless positional_arguments
15
15
 
16
16
  positional_arguments.map do |argument_node|
17
- str = argument_node.to_s if argument_node.string_or_symbol?
17
+ str = argument_node.to_s if argument_node.string_or_symbol_or_def?
18
18
 
19
19
  @then_processor.process(str, argument_node, method_node)
20
20
  end
@@ -0,0 +1,14 @@
1
+ # frozen-string-literal: true
2
+
3
+ module Leftovers
4
+ module ValueProcessors
5
+ module ReturnDefinitionNode
6
+ def self.process(str, node, _method_node)
7
+ return unless str
8
+ return if str.empty?
9
+
10
+ Leftovers::DefinitionNode.new(node, name: str.to_sym)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Leftovers
4
4
  module ValueProcessors
5
- module ReturnString
5
+ module ReturnSym
6
6
  def self.process(str, _node, _method_node)
7
7
  return unless str
8
8
  return if str.empty?
@@ -28,8 +28,8 @@ module Leftovers
28
28
  autoload(:Pluralize, "#{__dir__}/value_processors/pluralize")
29
29
  autoload(:PositionalArgument, "#{__dir__}/value_processors/positional_argument")
30
30
  autoload(:ReplaceValue, "#{__dir__}/value_processors/replace_value")
31
- autoload(:ReturnDefinition, "#{__dir__}/value_processors/return_definition")
32
- autoload(:ReturnString, "#{__dir__}/value_processors/return_string")
31
+ autoload(:ReturnDefinitionNode, "#{__dir__}/value_processors/return_definition_node")
32
+ autoload(:ReturnSym, "#{__dir__}/value_processors/return_sym")
33
33
  autoload(:Singularize, "#{__dir__}/value_processors/singularize")
34
34
  autoload(:Split, "#{__dir__}/value_processors/split")
35
35
  autoload(:Swapcase, "#{__dir__}/value_processors/swapcase")
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Leftovers
4
- VERSION = '0.6.0'
4
+ VERSION = '0.7.0'
5
5
  end
data/lib/leftovers.rb CHANGED
@@ -6,11 +6,13 @@ module Leftovers # rubocop:disable Metrics/ModuleLength
6
6
  autoload(:AST, "#{__dir__}/leftovers/ast")
7
7
  autoload(:CLI, "#{__dir__}/leftovers/cli")
8
8
  autoload(:Collector, "#{__dir__}/leftovers/collector")
9
- autoload(:ConfigValidator, "#{__dir__}/leftovers/config_validator")
9
+ autoload(:ConfigLoader, "#{__dir__}/leftovers/config_loader")
10
10
  autoload(:Config, "#{__dir__}/leftovers/config")
11
+ autoload(:Definition, "#{__dir__}/leftovers/definition")
11
12
  autoload(:DefinitionNode, "#{__dir__}/leftovers/definition_node")
13
+ autoload(:DefinitionNodeSet, "#{__dir__}/leftovers/definition_node_set")
12
14
  autoload(:DefinitionSet, "#{__dir__}/leftovers/definition_set")
13
- autoload(:Definition, "#{__dir__}/leftovers/definition")
15
+ autoload(:DefinitionToAdd, "#{__dir__}/leftovers/definition_to_add")
14
16
  autoload(:ERB, "#{__dir__}/leftovers/erb")
15
17
  autoload(:FileCollector, "#{__dir__}/leftovers/file_collector")
16
18
  autoload(:FileList, "#{__dir__}/leftovers/file_list")
@@ -31,6 +33,19 @@ module Leftovers # rubocop:disable Metrics/ModuleLength
31
33
  autoload(:ValueProcessors, "#{__dir__}/leftovers/value_processors")
32
34
  autoload(:VERSION, "#{__dir__}/leftovers/version")
33
35
 
36
+ MEMOIZED_IVARS = %i{
37
+ @config
38
+ @collector
39
+ @reporter
40
+ @leftovers
41
+ @try_require_cache
42
+ @stdout
43
+ @stderr
44
+ @parallel
45
+ @pwd
46
+ @progress
47
+ }.freeze
48
+
34
49
  class << self
35
50
  attr_accessor :parallel, :progress
36
51
  attr_writer :reporter
@@ -82,16 +97,10 @@ module Leftovers # rubocop:disable Metrics/ModuleLength
82
97
  reporter.report(only_test: only_test, none: none)
83
98
  end
84
99
 
85
- def reset # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
86
- remove_instance_variable(:@config) if defined?(@config)
87
- remove_instance_variable(:@collector) if defined?(@collector)
88
- remove_instance_variable(:@reporter) if defined?(@reporter)
89
- remove_instance_variable(:@leftovers) if defined?(@leftovers)
90
- remove_instance_variable(:@try_require_cache) if defined?(@try_require_cache)
91
- remove_instance_variable(:@stdout) if defined?(@stdout)
92
- remove_instance_variable(:@stderr) if defined?(@stderr)
93
- remove_instance_variable(:@parallel) if defined?(@parallel)
94
- remove_instance_variable(:@pwd) if defined?(@pwd)
100
+ def reset
101
+ MEMOIZED_IVARS.each do |ivar|
102
+ remove_instance_variable(ivar) if instance_variable_get(ivar)
103
+ end
95
104
  end
96
105
 
97
106
  def resolution_instructions_link
@@ -103,7 +112,7 @@ module Leftovers # rubocop:disable Metrics/ModuleLength
103
112
  end
104
113
 
105
114
  def error(message)
106
- warn(message)
115
+ warn("\e[31m#{message}\e[0m")
107
116
  exit 1
108
117
  end
109
118
 
@@ -137,7 +146,7 @@ module Leftovers # rubocop:disable Metrics/ModuleLength
137
146
 
138
147
  case value
139
148
  when nil then nil
140
- when Array then value.each(&block)
149
+ when Array then value.each { |i| each_or_self(i, &block) }
141
150
  else yield(value)
142
151
  end
143
152
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: leftovers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dana Sherson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-02-11 00:00:00.000000000 Z
11
+ date: 2022-02-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '2.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: did_you_mean
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: haml
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -262,20 +276,6 @@ dependencies:
262
276
  - - ">="
263
277
  - !ruby/object:Gem::Version
264
278
  version: 0.15.1
265
- - !ruby/object:Gem::Dependency
266
- name: json_schemer
267
- requirement: !ruby/object:Gem::Requirement
268
- requirements:
269
- - - ">="
270
- - !ruby/object:Gem::Version
271
- version: '0'
272
- type: :runtime
273
- prerelease: false
274
- version_requirements: !ruby/object:Gem::Requirement
275
- requirements:
276
- - - ">="
277
- - !ruby/object:Gem::Version
278
- version: '0'
279
279
  - !ruby/object:Gem::Dependency
280
280
  name: parallel
281
281
  requirement: !ruby/object:Gem::Requirement
@@ -320,7 +320,6 @@ files:
320
320
  - exe/leftovers
321
321
  - leftovers.gemspec
322
322
  - lib/.DS_Store
323
- - lib/config/actioncable.yml
324
323
  - lib/config/actionmailer.yml
325
324
  - lib/config/actionpack.yml
326
325
  - lib/config/actionview.yml
@@ -343,6 +342,7 @@ files:
343
342
  - lib/config/pry.yml
344
343
  - lib/config/rack.yml
345
344
  - lib/config/rails.yml
345
+ - lib/config/railties.yml
346
346
  - lib/config/rake.yml
347
347
  - lib/config/redcarpet.yml
348
348
  - lib/config/rollbar.yml
@@ -360,18 +360,48 @@ files:
360
360
  - lib/leftovers/cli.rb
361
361
  - lib/leftovers/collector.rb
362
362
  - lib/leftovers/config.rb
363
- - lib/leftovers/config_validator.rb
364
- - lib/leftovers/config_validator/error_processor.rb
365
- - lib/leftovers/config_validator/schema_hash.rb
363
+ - lib/leftovers/config_loader.rb
364
+ - lib/leftovers/config_loader/argument_position_schema.rb
365
+ - lib/leftovers/config_loader/argumentless_transform_schema.rb
366
+ - lib/leftovers/config_loader/attribute.rb
367
+ - lib/leftovers/config_loader/document_schema.rb
368
+ - lib/leftovers/config_loader/dynamic_schema.rb
369
+ - lib/leftovers/config_loader/has_argument_schema.rb
370
+ - lib/leftovers/config_loader/has_value_schema.rb
371
+ - lib/leftovers/config_loader/keep_test_only_schema.rb
372
+ - lib/leftovers/config_loader/node.rb
373
+ - lib/leftovers/config_loader/object_schema.rb
374
+ - lib/leftovers/config_loader/privacy_processor_schema.rb
375
+ - lib/leftovers/config_loader/privacy_schema.rb
376
+ - lib/leftovers/config_loader/require_schema.rb
377
+ - lib/leftovers/config_loader/rule_pattern_schema.rb
378
+ - lib/leftovers/config_loader/scalar_argument_schema.rb
379
+ - lib/leftovers/config_loader/scalar_value_schema.rb
380
+ - lib/leftovers/config_loader/schema.rb
381
+ - lib/leftovers/config_loader/string_enum_schema.rb
382
+ - lib/leftovers/config_loader/string_pattern_schema.rb
383
+ - lib/leftovers/config_loader/string_schema.rb
384
+ - lib/leftovers/config_loader/string_value_processor_schema.rb
385
+ - lib/leftovers/config_loader/suggester.rb
386
+ - lib/leftovers/config_loader/transform_schema.rb
387
+ - lib/leftovers/config_loader/true_schema.rb
388
+ - lib/leftovers/config_loader/value_matcher_schema.rb
389
+ - lib/leftovers/config_loader/value_or_array_schema.rb
390
+ - lib/leftovers/config_loader/value_processor_schema.rb
391
+ - lib/leftovers/config_loader/value_type_schema.rb
366
392
  - lib/leftovers/definition.rb
367
393
  - lib/leftovers/definition_node.rb
394
+ - lib/leftovers/definition_node_set.rb
368
395
  - lib/leftovers/definition_set.rb
396
+ - lib/leftovers/definition_to_add.rb
369
397
  - lib/leftovers/dynamic_processors.rb
370
398
  - lib/leftovers/dynamic_processors/call.rb
371
399
  - lib/leftovers/dynamic_processors/call_definition.rb
372
400
  - lib/leftovers/dynamic_processors/definition.rb
373
401
  - lib/leftovers/dynamic_processors/each.rb
374
402
  - lib/leftovers/dynamic_processors/null.rb
403
+ - lib/leftovers/dynamic_processors/set_default_privacy.rb
404
+ - lib/leftovers/dynamic_processors/set_privacy.rb
375
405
  - lib/leftovers/erb.rb
376
406
  - lib/leftovers/file.rb
377
407
  - lib/leftovers/file_collector.rb
@@ -392,6 +422,7 @@ files:
392
422
  - lib/leftovers/matcher_builders/node_pair_name.rb
393
423
  - lib/leftovers/matcher_builders/node_pair_value.rb
394
424
  - lib/leftovers/matcher_builders/node_path.rb
425
+ - lib/leftovers/matcher_builders/node_privacy.rb
395
426
  - lib/leftovers/matcher_builders/node_type.rb
396
427
  - lib/leftovers/matcher_builders/node_value.rb
397
428
  - lib/leftovers/matcher_builders/or.rb
@@ -411,6 +442,7 @@ files:
411
442
  - lib/leftovers/matchers/node_name.rb
412
443
  - lib/leftovers/matchers/node_pair_value.rb
413
444
  - lib/leftovers/matchers/node_path.rb
445
+ - lib/leftovers/matchers/node_privacy.rb
414
446
  - lib/leftovers/matchers/node_scalar_value.rb
415
447
  - lib/leftovers/matchers/node_type.rb
416
448
  - lib/leftovers/matchers/not.rb
@@ -466,8 +498,8 @@ files:
466
498
  - lib/leftovers/value_processors/pluralize.rb
467
499
  - lib/leftovers/value_processors/positional_argument.rb
468
500
  - lib/leftovers/value_processors/replace_value.rb
469
- - lib/leftovers/value_processors/return_definition.rb
470
- - lib/leftovers/value_processors/return_string.rb
501
+ - lib/leftovers/value_processors/return_definition_node.rb
502
+ - lib/leftovers/value_processors/return_sym.rb
471
503
  - lib/leftovers/value_processors/singularize.rb
472
504
  - lib/leftovers/value_processors/split.rb
473
505
  - lib/leftovers/value_processors/swapcase.rb
@@ -1,4 +0,0 @@
1
- # THIS IS INCOMPLETE (you can help by expanding it)
2
- # rails is _really complicated_ and has a lot of magic which calls methods for you.
3
- # some is currently impossible to handle (with_options).
4
- # Some is just corners of rails I haven't hit yet.
@@ -1,196 +0,0 @@
1
- # frozen-string-literal: true
2
-
3
- ::Leftovers.try_require 'did_you_mean'
4
-
5
- module Leftovers
6
- module ConfigValidator
7
- module ErrorProcessor # rubocop:disable Metrics/ModuleLength
8
- LENGTH_TYPE = %w{minItems minLength minProperties}.freeze
9
- TYPE_TYPE = %w{null string boolean integer number array object}.freeze
10
- VALUE_TYPE = %w{enum const}.freeze
11
- REQUIRED_TYPE = %w{required}.freeze
12
-
13
- class << self
14
- def process(errors) # rubocop:disable Metrics/MethodLength, Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity, Metrics/AbcSize
15
- error_data_pointers = []
16
- errors = group_errors(errors)
17
- errors.flat_map do |data_pointer, error_group| # rubocop:disable Metrics/BlockLength
18
- next if error_data_pointers.find { |x| x.start_with?(data_pointer) }
19
-
20
- # original_error_group = error_group.dup
21
- length_errors = error_group.select { |x| LENGTH_TYPE.include?(x['type']) }
22
- value_errors = error_group.select { |x| VALUE_TYPE.include?(x['type']) }
23
- type_errors = error_group.select { |x| TYPE_TYPE.include?(x['type']) }
24
- required_errors = error_group.select { |x| REQUIRED_TYPE.include?(x['type']) }
25
- messages = []
26
-
27
- if !type_errors.empty? && (error_group - type_errors).empty?
28
- error_group -= type_errors
29
- error_data_pointers << data_pointer
30
- any_of = group_by_same_any_of(type_errors)
31
- if any_of.length == 1
32
- was_class = to_json_type(type_errors.first['data'])
33
- error_types = type_errors.map { |x| x['type'] }
34
-
35
- messages << <<~MESSAGE.chomp
36
- #{data_pointer}: must be #{an to_sentence(error_types, 'or')} (was #{an was_class})
37
- MESSAGE
38
- # :nocov:
39
- else
40
- nil
41
- # :nocov:
42
- end
43
- elsif !required_errors.empty? && error_group.first['data'].is_a?(Hash)
44
- error_data_pointers << data_pointer
45
- group_by_same_any_of(required_errors).each do |_any_of_key, any_of_value|
46
- required_keywords = any_of_value.flat_map { |x| x['details']['missing_keys'] }
47
- error_group -= any_of_value
48
- if any_of_value.length > 1
49
- messages << <<~MESSAGE
50
- #{data_pointer}: requires at least one of these keywords: #{to_sentence(required_keywords, 'or')}
51
- MESSAGE
52
-
53
- # :nocov:
54
- else
55
- nil
56
- # :nocov:
57
- # messages << "#{data_pointer}: requires keyword: #{required_keywords.first}"
58
- end
59
- end
60
- elsif !length_errors.empty?
61
- error_data_pointers << data_pointer
62
- messages << "#{data_pointer}: can't be empty"
63
- end
64
-
65
- error_group.each do |error| # rubocop:disable Metrics/BlockLength
66
- type = error['type']
67
- case type
68
- when 'schema'
69
- error_data_pointers << data_pointer
70
- parent_pointer = parent(data_pointer)
71
- if ::File.basename(error['schema_pointer']) == 'additionalProperties'
72
- keyword = tail(data_pointer)
73
- parent_schema_pointer = parent(error['schema_pointer'])
74
- actual_keywords = schema_hash_dig(parent_schema_pointer)['properties'].keys
75
- corrections = did_you_mean(keyword, actual_keywords)
76
-
77
- messages << <<~MESSAGE.chomp
78
- #{parent_pointer}: invalid property keyword: #{keyword}
79
- Valid keywords: #{to_sentence actual_keywords}
80
- #{"Did you mean? #{to_sentence corrections, 'or'}" unless corrections.empty?}
81
- MESSAGE
82
- # :nocov:
83
- else
84
- nil
85
- # :nocov:
86
- end
87
- when 'enum'
88
- next if error['data'].is_a?(Hash)
89
-
90
- error_data_pointers << data_pointer
91
- given_value = error['data']
92
- valid_values = value_errors.first['schema']['enum']
93
- corrections = did_you_mean(given_value, valid_values)
94
- messages << <<~MESSAGE
95
- #{data_pointer}: can't be: #{given_value}
96
- Valid values: #{to_sentence valid_values, 'or'}
97
- #{"Did you mean? #{to_sentence corrections, 'or'}" unless corrections.empty?}
98
- MESSAGE
99
- when 'not'
100
- next unless error['data'].is_a?(Hash)
101
-
102
- error_data_pointers << data_pointer
103
- if error['schema']['required']
104
- invalid_combinations = error['schema']['required'] & error['data'].keys
105
- messages << <<~MESSAGE
106
- #{data_pointer}: use only one of: #{to_sentence invalid_combinations, 'or'}
107
- MESSAGE
108
- # :nocov:
109
- else
110
- end
111
- else
112
- end
113
- # :nocov:
114
- end
115
-
116
- if messages.empty?
117
- error_data_pointers << data_pointer
118
- "#{data_pointer} is invalid"
119
- else
120
- messages
121
- end
122
- end.compact.map(&:strip)
123
- end
124
-
125
- private
126
-
127
- def did_you_mean(word, dictionary)
128
- # :nocov:
129
- if defined?(::DidYouMean::SpellChecker)
130
- ::DidYouMean::SpellChecker.new(dictionary: dictionary).correct(word)
131
- else
132
- []
133
- end
134
- # :nocov:
135
- end
136
-
137
- def schema_hash_dig(schema_pointer)
138
- ::Leftovers::ConfigValidator::SCHEMA_HASH.dig(
139
- *schema_pointer.split('/').drop(1).map { |x| x.match?(/\A\d+\z/) ? x.to_i : x }
140
- )
141
- end
142
-
143
- def parent(pointer)
144
- ::File.dirname(pointer)
145
- end
146
-
147
- def tail(pointer)
148
- ::File.basename(pointer)
149
- end
150
-
151
- def to_json_type(value)
152
- case value
153
- when Hash then 'object'
154
- when Float then 'number'
155
- when true, false then 'boolean'
156
- when nil then 'null'
157
- else value.class.name.downcase
158
- end
159
- end
160
-
161
- def an(str)
162
- case str[0]
163
- # when nil then ""
164
- when 'a', 'e', 'i', 'o', 'u' then "an #{str}"
165
- else "a #{str}"
166
- end
167
- end
168
-
169
- def to_sentence(ary, join_word = 'and')
170
- case ary.length
171
- when 1 then ary.first
172
- when 2 then ary.join(" #{join_word} ")
173
- else
174
- ary = ary.dup
175
- last = ary.pop(2)
176
- [*ary, last.join(", #{join_word} ")].join(', ')
177
- end
178
- end
179
-
180
- def group_errors(errors)
181
- errors = errors.map do |x|
182
- x.delete('root_schema')
183
- x
184
- end
185
- errors.group_by { |x| x['data_pointer'] }.sort.reverse.to_h
186
- end
187
-
188
- def group_by_same_any_of(errors)
189
- errors.group_by do |x|
190
- x['schema_pointer'].match?(%r{/anyOf/\d+$}) && parent(parent(x['schema_pointer']))
191
- end
192
- end
193
- end
194
- end
195
- end
196
- end