leftovers 0.6.0 → 0.7.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.
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