leftovers 0.5.4 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -1
  3. data/README.md +21 -1
  4. data/docs/Configuration.md +188 -20
  5. data/leftovers.gemspec +8 -5
  6. data/lib/config/actionmailer.yml +11 -11
  7. data/lib/config/actionpack.yml +11 -0
  8. data/lib/config/activesupport.yml +1 -1
  9. data/lib/config/rails.yml +1 -1
  10. data/lib/config/railties.yml +11 -0
  11. data/lib/config/ruby.yml +79 -0
  12. data/lib/leftovers/ast/node.rb +16 -11
  13. data/lib/leftovers/collector.rb +3 -1
  14. data/lib/leftovers/config.rb +9 -28
  15. data/lib/leftovers/config_loader/argument_position_schema.rb +11 -0
  16. data/lib/leftovers/config_loader/argumentless_transform_schema.rb +21 -0
  17. data/lib/leftovers/config_loader/attribute.rb +30 -0
  18. data/lib/leftovers/config_loader/document_schema.rb +21 -0
  19. data/lib/leftovers/config_loader/dynamic_schema.rb +17 -0
  20. data/lib/leftovers/config_loader/has_argument_schema.rb +13 -0
  21. data/lib/leftovers/config_loader/has_value_schema.rb +18 -0
  22. data/lib/leftovers/config_loader/keep_test_only_schema.rb +13 -0
  23. data/lib/leftovers/config_loader/node.rb +106 -0
  24. data/lib/leftovers/config_loader/object_schema.rb +189 -0
  25. data/lib/leftovers/config_loader/privacy_processor_schema.rb +12 -0
  26. data/lib/leftovers/config_loader/privacy_schema.rb +15 -0
  27. data/lib/leftovers/config_loader/require_schema.rb +11 -0
  28. data/lib/leftovers/config_loader/rule_pattern_schema.rb +18 -0
  29. data/lib/leftovers/config_loader/scalar_argument_schema.rb +14 -0
  30. data/lib/leftovers/config_loader/scalar_value_schema.rb +14 -0
  31. data/lib/leftovers/config_loader/schema.rb +21 -0
  32. data/lib/leftovers/config_loader/string_enum_schema.rb +62 -0
  33. data/lib/leftovers/config_loader/string_pattern_schema.rb +14 -0
  34. data/lib/leftovers/config_loader/string_schema.rb +14 -0
  35. data/lib/leftovers/config_loader/string_value_processor_schema.rb +11 -0
  36. data/lib/leftovers/config_loader/suggester.rb +22 -0
  37. data/lib/leftovers/config_loader/transform_schema.rb +28 -0
  38. data/lib/leftovers/config_loader/true_schema.rb +18 -0
  39. data/lib/leftovers/config_loader/value_matcher_schema.rb +18 -0
  40. data/lib/leftovers/config_loader/value_or_array_schema.rb +64 -0
  41. data/lib/leftovers/config_loader/value_processor_schema.rb +14 -0
  42. data/lib/leftovers/config_loader/value_type_schema.rb +17 -0
  43. data/lib/leftovers/config_loader.rb +82 -0
  44. data/lib/leftovers/definition.rb +1 -1
  45. data/lib/leftovers/definition_node.rb +6 -17
  46. data/lib/leftovers/definition_node_set.rb +11 -0
  47. data/lib/leftovers/definition_to_add.rb +31 -0
  48. data/lib/leftovers/dynamic_processors/call.rb +4 -7
  49. data/lib/leftovers/dynamic_processors/call_definition.rb +14 -11
  50. data/lib/leftovers/dynamic_processors/definition.rb +8 -7
  51. data/lib/leftovers/dynamic_processors/set_default_privacy.rb +18 -0
  52. data/lib/leftovers/dynamic_processors/set_privacy.rb +23 -0
  53. data/lib/leftovers/dynamic_processors.rb +2 -0
  54. data/lib/leftovers/file.rb +57 -11
  55. data/lib/leftovers/file_collector.rb +77 -19
  56. data/lib/leftovers/json.rb +28 -0
  57. data/lib/leftovers/matcher_builders/document.rb +13 -0
  58. data/lib/leftovers/matcher_builders/node.rb +7 -1
  59. data/lib/leftovers/matcher_builders/node_has_argument.rb +3 -4
  60. data/lib/leftovers/matcher_builders/node_has_keyword_argument.rb +1 -1
  61. data/lib/leftovers/matcher_builders/node_has_positional_argument.rb +1 -1
  62. data/lib/leftovers/matcher_builders/node_privacy.rb +13 -0
  63. data/lib/leftovers/matcher_builders/node_type.rb +4 -4
  64. data/lib/leftovers/matcher_builders/node_value.rb +1 -1
  65. data/lib/leftovers/matcher_builders/string_pattern.rb +14 -5
  66. data/lib/leftovers/matcher_builders.rb +2 -0
  67. data/lib/leftovers/matchers/all.rb +0 -4
  68. data/lib/leftovers/matchers/and.rb +0 -4
  69. data/lib/leftovers/matchers/any.rb +0 -4
  70. data/lib/leftovers/matchers/node_has_any_keyword_argument.rb +1 -7
  71. data/lib/leftovers/matchers/node_has_any_positional_argument_with_value.rb +1 -7
  72. data/lib/leftovers/matchers/node_has_positional_argument_with_value.rb +0 -4
  73. data/lib/leftovers/matchers/node_name.rb +0 -4
  74. data/lib/leftovers/matchers/node_pair_value.rb +0 -4
  75. data/lib/leftovers/matchers/node_path.rb +0 -4
  76. data/lib/leftovers/matchers/node_privacy.rb +19 -0
  77. data/lib/leftovers/matchers/node_scalar_value.rb +0 -4
  78. data/lib/leftovers/matchers/node_type.rb +0 -4
  79. data/lib/leftovers/matchers/not.rb +0 -4
  80. data/lib/leftovers/matchers/or.rb +0 -4
  81. data/lib/leftovers/matchers.rb +1 -0
  82. data/lib/leftovers/merged_config.rb +25 -23
  83. data/lib/leftovers/processor_builders/add_prefix.rb +1 -1
  84. data/lib/leftovers/processor_builders/add_suffix.rb +1 -1
  85. data/lib/leftovers/processor_builders/dynamic.rb +51 -16
  86. data/lib/leftovers/processor_builders/transform.rb +2 -2
  87. data/lib/leftovers/processor_builders/transform_set.rb +8 -8
  88. data/lib/leftovers/todo_reporter.rb +10 -35
  89. data/lib/leftovers/value_processors/delete_prefix.rb +0 -6
  90. data/lib/leftovers/value_processors/delete_suffix.rb +0 -6
  91. data/lib/leftovers/value_processors/each_for_definition_set.rb +2 -5
  92. data/lib/leftovers/value_processors/each_positional_argument.rb +1 -1
  93. data/lib/leftovers/value_processors/keyword.rb +0 -4
  94. data/lib/leftovers/value_processors/keyword_argument.rb +0 -4
  95. data/lib/leftovers/value_processors/return_definition_node.rb +14 -0
  96. data/lib/leftovers/value_processors/{return_string.rb → return_sym.rb} +1 -1
  97. data/lib/leftovers/value_processors.rb +2 -2
  98. data/lib/leftovers/version.rb +1 -1
  99. data/lib/leftovers/yaml.rb +73 -0
  100. data/lib/leftovers.rb +29 -21
  101. metadata +85 -36
  102. data/lib/config/actioncable.yml +0 -4
  103. data/lib/leftovers/backports.rb +0 -40
  104. data/lib/leftovers/config_validator/error_processor.rb +0 -196
  105. data/lib/leftovers/config_validator/schema_hash.rb +0 -530
  106. data/lib/leftovers/config_validator.rb +0 -60
  107. data/lib/leftovers/value_processors/return_definition.rb +0 -26
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.5.4
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-09 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
@@ -112,44 +126,58 @@ dependencies:
112
126
  name: rubocop
113
127
  requirement: !ruby/object:Gem::Requirement
114
128
  requirements:
115
- - - "~>"
129
+ - - ">="
116
130
  - !ruby/object:Gem::Version
117
- version: 0.93.1
131
+ version: '0'
118
132
  type: :development
119
133
  prerelease: false
120
134
  version_requirements: !ruby/object:Gem::Requirement
121
135
  requirements:
122
- - - "~>"
136
+ - - ">="
123
137
  - !ruby/object:Gem::Version
124
- version: 0.93.1
138
+ version: '0'
125
139
  - !ruby/object:Gem::Dependency
126
140
  name: rubocop-performance
127
141
  requirement: !ruby/object:Gem::Requirement
128
142
  requirements:
129
- - - "~>"
143
+ - - ">="
130
144
  - !ruby/object:Gem::Version
131
- version: 1.8.1
145
+ version: '0'
132
146
  type: :development
133
147
  prerelease: false
134
148
  version_requirements: !ruby/object:Gem::Requirement
135
149
  requirements:
136
- - - "~>"
150
+ - - ">="
137
151
  - !ruby/object:Gem::Version
138
- version: 1.8.1
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: rubocop-rake
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
139
167
  - !ruby/object:Gem::Dependency
140
168
  name: rubocop-rspec
141
169
  requirement: !ruby/object:Gem::Requirement
142
170
  requirements:
143
- - - "~>"
171
+ - - ">="
144
172
  - !ruby/object:Gem::Version
145
- version: 1.44.1
173
+ version: '0'
146
174
  type: :development
147
175
  prerelease: false
148
176
  version_requirements: !ruby/object:Gem::Requirement
149
177
  requirements:
150
- - - "~>"
178
+ - - ">="
151
179
  - !ruby/object:Gem::Version
152
- version: 1.44.1
180
+ version: '0'
153
181
  - !ruby/object:Gem::Dependency
154
182
  name: simplecov
155
183
  requirement: !ruby/object:Gem::Requirement
@@ -248,20 +276,6 @@ dependencies:
248
276
  - - ">="
249
277
  - !ruby/object:Gem::Version
250
278
  version: 0.15.1
251
- - !ruby/object:Gem::Dependency
252
- name: json_schemer
253
- requirement: !ruby/object:Gem::Requirement
254
- requirements:
255
- - - ">="
256
- - !ruby/object:Gem::Version
257
- version: '0'
258
- type: :runtime
259
- prerelease: false
260
- version_requirements: !ruby/object:Gem::Requirement
261
- requirements:
262
- - - ">="
263
- - !ruby/object:Gem::Version
264
- version: '0'
265
279
  - !ruby/object:Gem::Dependency
266
280
  name: parallel
267
281
  requirement: !ruby/object:Gem::Requirement
@@ -306,7 +320,6 @@ files:
306
320
  - exe/leftovers
307
321
  - leftovers.gemspec
308
322
  - lib/.DS_Store
309
- - lib/config/actioncable.yml
310
323
  - lib/config/actionmailer.yml
311
324
  - lib/config/actionpack.yml
312
325
  - lib/config/actionview.yml
@@ -329,6 +342,7 @@ files:
329
342
  - lib/config/pry.yml
330
343
  - lib/config/rack.yml
331
344
  - lib/config/rails.yml
345
+ - lib/config/railties.yml
332
346
  - lib/config/rake.yml
333
347
  - lib/config/redcarpet.yml
334
348
  - lib/config/rollbar.yml
@@ -343,30 +357,61 @@ files:
343
357
  - lib/leftovers/ast.rb
344
358
  - lib/leftovers/ast/builder.rb
345
359
  - lib/leftovers/ast/node.rb
346
- - lib/leftovers/backports.rb
347
360
  - lib/leftovers/cli.rb
348
361
  - lib/leftovers/collector.rb
349
362
  - lib/leftovers/config.rb
350
- - lib/leftovers/config_validator.rb
351
- - lib/leftovers/config_validator/error_processor.rb
352
- - 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
353
392
  - lib/leftovers/definition.rb
354
393
  - lib/leftovers/definition_node.rb
394
+ - lib/leftovers/definition_node_set.rb
355
395
  - lib/leftovers/definition_set.rb
396
+ - lib/leftovers/definition_to_add.rb
356
397
  - lib/leftovers/dynamic_processors.rb
357
398
  - lib/leftovers/dynamic_processors/call.rb
358
399
  - lib/leftovers/dynamic_processors/call_definition.rb
359
400
  - lib/leftovers/dynamic_processors/definition.rb
360
401
  - lib/leftovers/dynamic_processors/each.rb
361
402
  - lib/leftovers/dynamic_processors/null.rb
403
+ - lib/leftovers/dynamic_processors/set_default_privacy.rb
404
+ - lib/leftovers/dynamic_processors/set_privacy.rb
362
405
  - lib/leftovers/erb.rb
363
406
  - lib/leftovers/file.rb
364
407
  - lib/leftovers/file_collector.rb
365
408
  - lib/leftovers/file_list.rb
366
409
  - lib/leftovers/haml.rb
410
+ - lib/leftovers/json.rb
367
411
  - lib/leftovers/matcher_builders.rb
368
412
  - lib/leftovers/matcher_builders/and.rb
369
413
  - lib/leftovers/matcher_builders/and_not.rb
414
+ - lib/leftovers/matcher_builders/document.rb
370
415
  - lib/leftovers/matcher_builders/name.rb
371
416
  - lib/leftovers/matcher_builders/node.rb
372
417
  - lib/leftovers/matcher_builders/node_has_argument.rb
@@ -377,6 +422,7 @@ files:
377
422
  - lib/leftovers/matcher_builders/node_pair_name.rb
378
423
  - lib/leftovers/matcher_builders/node_pair_value.rb
379
424
  - lib/leftovers/matcher_builders/node_path.rb
425
+ - lib/leftovers/matcher_builders/node_privacy.rb
380
426
  - lib/leftovers/matcher_builders/node_type.rb
381
427
  - lib/leftovers/matcher_builders/node_value.rb
382
428
  - lib/leftovers/matcher_builders/or.rb
@@ -396,6 +442,7 @@ files:
396
442
  - lib/leftovers/matchers/node_name.rb
397
443
  - lib/leftovers/matchers/node_pair_value.rb
398
444
  - lib/leftovers/matchers/node_path.rb
445
+ - lib/leftovers/matchers/node_privacy.rb
399
446
  - lib/leftovers/matchers/node_scalar_value.rb
400
447
  - lib/leftovers/matchers/node_type.rb
401
448
  - lib/leftovers/matchers/not.rb
@@ -451,8 +498,8 @@ files:
451
498
  - lib/leftovers/value_processors/pluralize.rb
452
499
  - lib/leftovers/value_processors/positional_argument.rb
453
500
  - lib/leftovers/value_processors/replace_value.rb
454
- - lib/leftovers/value_processors/return_definition.rb
455
- - lib/leftovers/value_processors/return_string.rb
501
+ - lib/leftovers/value_processors/return_definition_node.rb
502
+ - lib/leftovers/value_processors/return_sym.rb
456
503
  - lib/leftovers/value_processors/singularize.rb
457
504
  - lib/leftovers/value_processors/split.rb
458
505
  - lib/leftovers/value_processors/swapcase.rb
@@ -460,6 +507,7 @@ files:
460
507
  - lib/leftovers/value_processors/underscore.rb
461
508
  - lib/leftovers/value_processors/upcase.rb
462
509
  - lib/leftovers/version.rb
510
+ - lib/leftovers/yaml.rb
463
511
  homepage: http://github.com/robotdana/leftovers
464
512
  licenses:
465
513
  - MIT
@@ -467,6 +515,7 @@ metadata:
467
515
  homepage_uri: http://github.com/robotdana/leftovers
468
516
  source_code_uri: http://github.com/robotdana/leftovers
469
517
  changelog_uri: http://github.com/robotdana/leftovers/blob/main/CHANGELOG.md
518
+ rubygems_mfa_required: 'true'
470
519
  post_install_message:
471
520
  rdoc_options: []
472
521
  require_paths:
@@ -475,7 +524,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
475
524
  requirements:
476
525
  - - ">="
477
526
  - !ruby/object:Gem::Version
478
- version: 2.4.0
527
+ version: 2.5.0
479
528
  required_rubygems_version: !ruby/object:Gem::Requirement
480
529
  requirements:
481
530
  - - ">="
@@ -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,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Leftovers
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
14
- end
15
- end
16
-
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
23
-
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
32
-
33
- def delete_suffix(str)
34
- dup.delete_suffix!(str)
35
- end
36
- end
37
- end
38
- end
39
- end
40
- end
@@ -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