diff --git a/DEPENDENCIES b/DEPENDENCIES index 1ef6de2d..fdbbfe5a 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -2,4 +2,4 @@ vendorpull https://github.com/sourcemeta/vendorpull dea311b5bfb53b6926a414026795 noa https://github.com/sourcemeta/noa 7e26abce7a4e31e86a16ef2851702a56773ca527 jsontoolkit https://github.com/sourcemeta/jsontoolkit 3ef19daf7ca042544239111c701a51232f3f5576 hydra https://github.com/sourcemeta/hydra 3c53d3fdef79e9ba603d48470a508cc45472a0dc -alterschema https://github.com/sourcemeta/alterschema a31722f04ae2d7e57f2fe5bbb0613670866c0840 +alterschema https://github.com/sourcemeta/alterschema 744cf03a950b681a61f1f4cf6a7bb55bc52836c9 diff --git a/vendor/alterschema/CMakeLists.txt b/vendor/alterschema/CMakeLists.txt index 6d7c064a..ac8608d8 100644 --- a/vendor/alterschema/CMakeLists.txt +++ b/vendor/alterschema/CMakeLists.txt @@ -70,4 +70,12 @@ if(ALTERSCHEMA_TESTS) if(ALTERSCHEMA_LINTER) add_subdirectory(test/linter) endif() + + if(PROJECT_IS_TOP_LEVEL) + # Otherwise we need the child project to link + # against the sanitizers too. + if(NOT ALTERSCHEMA_ADDRESS_SANITIZER AND NOT ALTERSCHEMA_UNDEFINED_SANITIZER) + add_subdirectory(test/packaging) + endif() + endif() endif() diff --git a/vendor/alterschema/src/engine/include/sourcemeta/alterschema/engine_rule.h b/vendor/alterschema/src/engine/include/sourcemeta/alterschema/engine_rule.h index 24ddafa2..0de7aef7 100644 --- a/vendor/alterschema/src/engine/include/sourcemeta/alterschema/engine_rule.h +++ b/vendor/alterschema/src/engine/include/sourcemeta/alterschema/engine_rule.h @@ -30,7 +30,7 @@ namespace sourcemeta::alterschema { /// /// class MyRule final : public sourcemeta::alterschema::Rule { /// public: -/// MyRule() : sourcemeta::alterschema::Rule("my_rule") {}; +/// MyRule() : sourcemeta::alterschema::Rule("my_rule", "My rule") {}; /// /// [[nodiscard]] auto condition(const sourcemeta::jsontoolkit::JSON &schema, /// const std::string &dialect, @@ -50,7 +50,7 @@ namespace sourcemeta::alterschema { class SOURCEMETA_ALTERSCHEMA_ENGINE_EXPORT Rule { public: /// Create a transformation rule. Each rule must have a unique name. - Rule(std::string &&name, std::string &&message = "Condition matched"); + Rule(std::string &&name, std::string &&message); // Necessary to wrap rules on smart pointers virtual ~Rule() = default; diff --git a/vendor/alterschema/src/linter/CMakeLists.txt b/vendor/alterschema/src/linter/CMakeLists.txt index 37a83127..20339378 100644 --- a/vendor/alterschema/src/linter/CMakeLists.txt +++ b/vendor/alterschema/src/linter/CMakeLists.txt @@ -1,29 +1,161 @@ noa_library(NAMESPACE sourcemeta PROJECT alterschema NAME linter FOLDER "AlterSchema/Linter" SOURCES linter.cc - # Modernize - modernize/enum_to_const.h - # Antipattern antipattern/const_with_type.h + antipattern/duplicate_enum_values.h + antipattern/duplicate_required_values.h + antipattern/exclusive_maximum_number_and_maximum.h + antipattern/exclusive_minimum_number_and_minimum.h antipattern/enum_with_type.h # Simplify + simplify/dependencies_property_tautology.h + simplify/dependent_required_tautology.h + simplify/equal_numeric_bounds_to_enum.h + simplify/maximum_real_for_integer.h + simplify/minimum_real_for_integer.h simplify/single_type_array.h + # Syntax Sugar + syntax_sugar/enum_to_const.h + + # Desugar + desugar/boolean_true.h + desugar/const_as_enum.h + desugar/exclusive_maximum_integer_to_maximum.h + desugar/exclusive_minimum_integer_to_minimum.h + desugar/type_array_to_any_of_2020_12.h + desugar/type_boolean_as_enum.h + desugar/type_null_as_enum.h + # Redundant redundant/additional_properties_default.h - redundant/content_media_type_without_encoding.h redundant/content_schema_default.h - redundant/content_schema_without_media_type.h - redundant/else_without_if.h + redundant/dependencies_default.h + redundant/dependent_required_default.h redundant/items_array_default.h redundant/items_schema_default.h - redundant/max_contains_without_contains.h - redundant/min_contains_without_contains.h - redundant/then_without_if.h + redundant/pattern_properties_default.h + redundant/properties_default.h redundant/unevaluated_items_default.h - redundant/unevaluated_properties_default.h) + redundant/unevaluated_properties_default.h + redundant/unsatisfiable_max_contains.h + redundant/unsatisfiable_min_properties.h + + # Implicit + implicit/max_contains_covered_by_max_items.h + implicit/min_items_given_min_contains.h + implicit/min_items_implicit.h + implicit/min_length_implicit.h + implicit/min_properties_covered_by_required.h + implicit/min_properties_implicit.h + implicit/multiple_of_implicit.h + implicit/properties_implicit.h + implicit/type_union_implicit.h + + # Superfluous + superfluous/content_media_type_without_encoding.h + superfluous/content_schema_without_media_type.h + superfluous/drop_non_array_keywords_applicator_2019_09.h + superfluous/drop_non_array_keywords_applicator_2020_12.h + superfluous/drop_non_array_keywords_content_2019_09.h + superfluous/drop_non_array_keywords_content_2020_12.h + superfluous/drop_non_array_keywords_draft0.h + superfluous/drop_non_array_keywords_draft1.h + superfluous/drop_non_array_keywords_draft2.h + superfluous/drop_non_array_keywords_draft3.h + superfluous/drop_non_array_keywords_draft4.h + superfluous/drop_non_array_keywords_draft6.h + superfluous/drop_non_array_keywords_draft7.h + superfluous/drop_non_array_keywords_format_2019_09.h + superfluous/drop_non_array_keywords_format_2020_12.h + superfluous/drop_non_array_keywords_unevaluated_2020_12.h + superfluous/drop_non_array_keywords_validation_2019_09.h + superfluous/drop_non_array_keywords_validation_2020_12.h + superfluous/drop_non_boolean_keywords_applicator_2019_09.h + superfluous/drop_non_boolean_keywords_applicator_2020_12.h + superfluous/drop_non_boolean_keywords_content_2019_09.h + superfluous/drop_non_boolean_keywords_content_2020_12.h + superfluous/drop_non_boolean_keywords_draft0.h + superfluous/drop_non_boolean_keywords_draft1.h + superfluous/drop_non_boolean_keywords_draft2.h + superfluous/drop_non_boolean_keywords_draft3.h + superfluous/drop_non_boolean_keywords_draft4.h + superfluous/drop_non_boolean_keywords_draft6.h + superfluous/drop_non_boolean_keywords_draft7.h + superfluous/drop_non_boolean_keywords_format_2019_09.h + superfluous/drop_non_boolean_keywords_format_2020_12.h + superfluous/drop_non_boolean_keywords_unevaluated_2020_12.h + superfluous/drop_non_boolean_keywords_validation_2019_09.h + superfluous/drop_non_boolean_keywords_validation_2020_12.h + superfluous/drop_non_null_keywords_applicator_2019_09.h + superfluous/drop_non_null_keywords_applicator_2020_12.h + superfluous/drop_non_null_keywords_content_2019_09.h + superfluous/drop_non_null_keywords_content_2020_12.h + superfluous/drop_non_null_keywords_draft0.h + superfluous/drop_non_null_keywords_draft1.h + superfluous/drop_non_null_keywords_draft2.h + superfluous/drop_non_null_keywords_draft3.h + superfluous/drop_non_null_keywords_draft4.h + superfluous/drop_non_null_keywords_draft6.h + superfluous/drop_non_null_keywords_draft7.h + superfluous/drop_non_null_keywords_format_2019_09.h + superfluous/drop_non_null_keywords_format_2020_12.h + superfluous/drop_non_null_keywords_unevaluated_2020_12.h + superfluous/drop_non_null_keywords_validation_2019_09.h + superfluous/drop_non_null_keywords_validation_2020_12.h + superfluous/drop_non_numeric_keywords_applicator_2019_09.h + superfluous/drop_non_numeric_keywords_applicator_2020_12.h + superfluous/drop_non_numeric_keywords_content_2019_09.h + superfluous/drop_non_numeric_keywords_content_2020_12.h + superfluous/drop_non_numeric_keywords_draft0.h + superfluous/drop_non_numeric_keywords_draft1.h + superfluous/drop_non_numeric_keywords_draft2.h + superfluous/drop_non_numeric_keywords_draft3.h + superfluous/drop_non_numeric_keywords_draft4.h + superfluous/drop_non_numeric_keywords_draft6.h + superfluous/drop_non_numeric_keywords_draft7.h + superfluous/drop_non_numeric_keywords_format_2019_09.h + superfluous/drop_non_numeric_keywords_format_2020_12.h + superfluous/drop_non_numeric_keywords_unevaluated_2020_12.h + superfluous/drop_non_numeric_keywords_validation_2019_09.h + superfluous/drop_non_numeric_keywords_validation_2020_12.h + superfluous/drop_non_object_keywords_applicator_2019_09.h + superfluous/drop_non_object_keywords_applicator_2020_12.h + superfluous/drop_non_object_keywords_content_2019_09.h + superfluous/drop_non_object_keywords_content_2020_12.h + superfluous/drop_non_object_keywords_draft0.h + superfluous/drop_non_object_keywords_draft1.h + superfluous/drop_non_object_keywords_draft2.h + superfluous/drop_non_object_keywords_draft3.h + superfluous/drop_non_object_keywords_draft4.h + superfluous/drop_non_object_keywords_draft6.h + superfluous/drop_non_object_keywords_draft7.h + superfluous/drop_non_object_keywords_format_2019_09.h + superfluous/drop_non_object_keywords_format_2020_12.h + superfluous/drop_non_object_keywords_unevaluated_2020_12.h + superfluous/drop_non_object_keywords_validation_2019_09.h + superfluous/drop_non_object_keywords_validation_2020_12.h + superfluous/drop_non_string_keywords_applicator_2019_09.h + superfluous/drop_non_string_keywords_applicator_2020_12.h + superfluous/drop_non_string_keywords_draft0.h + superfluous/drop_non_string_keywords_draft1.h + superfluous/drop_non_string_keywords_draft2.h + superfluous/drop_non_string_keywords_draft3.h + superfluous/drop_non_string_keywords_draft4.h + superfluous/drop_non_string_keywords_draft6.h + superfluous/drop_non_string_keywords_draft7.h + superfluous/drop_non_string_keywords_unevaluated_2020_12.h + superfluous/drop_non_string_keywords_validation_2019_09.h + superfluous/drop_non_string_keywords_validation_2020_12.h + superfluous/duplicate_allof_branches.h + superfluous/duplicate_anyof_branches.h + superfluous/else_without_if.h + superfluous/if_without_then_else.h + superfluous/max_contains_without_contains.h + superfluous/min_contains_without_contains.h + superfluous/then_without_if.h) if(ALTERSCHEMA_INSTALL) noa_library_install(NAMESPACE sourcemeta PROJECT alterschema NAME linter) diff --git a/vendor/alterschema/src/linter/antipattern/duplicate_enum_values.h b/vendor/alterschema/src/linter/antipattern/duplicate_enum_values.h new file mode 100644 index 00000000..4030ea27 --- /dev/null +++ b/vendor/alterschema/src/linter/antipattern/duplicate_enum_values.h @@ -0,0 +1,33 @@ +class DuplicateEnumValues final : public Rule { +public: + DuplicateEnumValues() + : Rule{"duplicate_enum_values", "Setting duplicate values in `enum` is " + "considered an anti-pattern"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/validation", + "https://json-schema.org/draft/2019-09/vocab/validation", + "http://json-schema.org/draft-07/schema#", + "http://json-schema.org/draft-06/schema#", + "http://json-schema.org/draft-04/schema#", + "http://json-schema.org/draft-03/schema#", + "http://json-schema.org/draft-02/hyper-schema#", + "http://json-schema.org/draft-01/hyper-schema#"}) && + schema.is_object() && schema.defines("enum") && + schema.at("enum").is_array() && !schema.at("enum").unique(); + } + + auto transform(Transformer &transformer) const -> void override { + auto collection = transformer.schema().at("enum"); + std::sort(collection.as_array().begin(), collection.as_array().end()); + auto last = + std::unique(collection.as_array().begin(), collection.as_array().end()); + collection.erase(last, collection.as_array().end()); + transformer.replace({"enum"}, std::move(collection)); + } +}; diff --git a/vendor/alterschema/src/linter/antipattern/duplicate_required_values.h b/vendor/alterschema/src/linter/antipattern/duplicate_required_values.h new file mode 100644 index 00000000..358612df --- /dev/null +++ b/vendor/alterschema/src/linter/antipattern/duplicate_required_values.h @@ -0,0 +1,31 @@ +class DuplicateRequiredValues final : public Rule { +public: + DuplicateRequiredValues() + : Rule{"duplicate_required_values", + "Setting duplicate values in `required` is considered an " + "anti-pattern"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/validation", + "https://json-schema.org/draft/2019-09/vocab/validation", + "http://json-schema.org/draft-07/schema#", + "http://json-schema.org/draft-06/schema#", + "http://json-schema.org/draft-04/schema#"}) && + schema.is_object() && schema.defines("required") && + schema.at("required").is_array() && !schema.at("required").unique(); + } + + auto transform(Transformer &transformer) const -> void override { + auto collection = transformer.schema().at("required"); + std::sort(collection.as_array().begin(), collection.as_array().end()); + auto last = + std::unique(collection.as_array().begin(), collection.as_array().end()); + collection.erase(last, collection.as_array().end()); + transformer.replace({"required"}, std::move(collection)); + } +}; diff --git a/vendor/alterschema/src/linter/antipattern/enum_with_type.h b/vendor/alterschema/src/linter/antipattern/enum_with_type.h index 002969f2..27453017 100644 --- a/vendor/alterschema/src/linter/antipattern/enum_with_type.h +++ b/vendor/alterschema/src/linter/antipattern/enum_with_type.h @@ -21,7 +21,34 @@ class EnumWithType final : public Rule { "http://json-schema.org/draft-02/hyper-schema#", "http://json-schema.org/draft-01/hyper-schema#"}) && schema.is_object() && schema.defines("type") && - schema.defines("enum"); + schema.defines("enum") && + + // Guard against cases where not all of the enumeration members + // match the desired type, in which case the type is adding + // an extra constraint and cannot be safely removed + schema.at("type").is_string() && schema.at("enum").is_array() && + std::all_of(schema.at("enum").as_array().cbegin(), + schema.at("enum").as_array().cend(), + [&schema](const auto &item) { + const auto &type{schema.at("type").to_string()}; + if (type == "object") { + return item.is_object(); + } else if (type == "array") { + return item.is_array(); + } else if (type == "string") { + return item.is_string(); + } else if (type == "boolean") { + return item.is_boolean(); + } else if (type == "null") { + return item.is_null(); + } else if (type == "number") { + return item.is_number(); + } else if (type == "integer") { + return item.is_integer(); + } else { + return false; + } + }); } auto transform(Transformer &transformer) const -> void override { diff --git a/vendor/alterschema/src/linter/antipattern/exclusive_maximum_number_and_maximum.h b/vendor/alterschema/src/linter/antipattern/exclusive_maximum_number_and_maximum.h new file mode 100644 index 00000000..972af984 --- /dev/null +++ b/vendor/alterschema/src/linter/antipattern/exclusive_maximum_number_and_maximum.h @@ -0,0 +1,32 @@ +class ExclusiveMaximumNumberAndMaximum final : public Rule { +public: + ExclusiveMaximumNumberAndMaximum() + : Rule{"exclusive_maximum_number_and_maximum", + "Setting both `exclusiveMaximum` and `maximum` at the same time " + "is considered an anti-pattern. You should choose one"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/validation", + "https://json-schema.org/draft/2019-09/vocab/validation", + "http://json-schema.org/draft-07/schema#", + "http://json-schema.org/draft-06/schema#"}) && + schema.is_object() && schema.defines("maximum") && + schema.defines("exclusiveMaximum") && + schema.at("maximum").is_number() && + schema.at("exclusiveMaximum").is_number(); + } + + auto transform(Transformer &transformer) const -> void override { + if (transformer.schema().at("maximum") < + transformer.schema().at("exclusiveMaximum")) { + transformer.erase("exclusiveMaximum"); + } else { + transformer.erase("maximum"); + } + } +}; diff --git a/vendor/alterschema/src/linter/antipattern/exclusive_minimum_number_and_minimum.h b/vendor/alterschema/src/linter/antipattern/exclusive_minimum_number_and_minimum.h new file mode 100644 index 00000000..440b24fc --- /dev/null +++ b/vendor/alterschema/src/linter/antipattern/exclusive_minimum_number_and_minimum.h @@ -0,0 +1,32 @@ +class ExclusiveMinimumNumberAndMinimum final : public Rule { +public: + ExclusiveMinimumNumberAndMinimum() + : Rule{"exclusive_minimum_number_and_minimum", + "Setting both `exclusiveMinimum` and `minimum` at the same time " + "is considered an anti-pattern. You should choose one"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/validation", + "https://json-schema.org/draft/2019-09/vocab/validation", + "http://json-schema.org/draft-07/schema#", + "http://json-schema.org/draft-06/schema#"}) && + schema.is_object() && schema.defines("minimum") && + schema.defines("exclusiveMinimum") && + schema.at("minimum").is_number() && + schema.at("exclusiveMinimum").is_number(); + } + + auto transform(Transformer &transformer) const -> void override { + if (transformer.schema().at("exclusiveMinimum") < + transformer.schema().at("minimum")) { + transformer.erase("exclusiveMinimum"); + } else { + transformer.erase("minimum"); + } + } +}; diff --git a/vendor/alterschema/src/linter/desugar/boolean_true.h b/vendor/alterschema/src/linter/desugar/boolean_true.h new file mode 100644 index 00000000..b78ca0a9 --- /dev/null +++ b/vendor/alterschema/src/linter/desugar/boolean_true.h @@ -0,0 +1,18 @@ +class BooleanTrue final : public Rule { +public: + BooleanTrue() + : Rule{"boolean_true", + "The boolean schema `true` is syntax sugar for the empty schema"} { + }; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return schema.is_boolean() && schema.to_boolean(); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.replace(sourcemeta::jsontoolkit::JSON::make_object()); + } +}; diff --git a/vendor/alterschema/src/linter/desugar/const_as_enum.h b/vendor/alterschema/src/linter/desugar/const_as_enum.h new file mode 100644 index 00000000..2545ecaf --- /dev/null +++ b/vendor/alterschema/src/linter/desugar/const_as_enum.h @@ -0,0 +1,29 @@ +class ConstAsEnum final : public Rule { +public: + ConstAsEnum() + : Rule{"const_as_enum", "Setting `const` is syntax sugar for an " + "enumeration of a single value"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/validation", + "https://json-schema.org/draft/2019-09/vocab/validation", + "http://json-schema.org/draft-07/schema#", + "http://json-schema.org/draft-06/schema#"}) && + schema.is_object() && schema.defines("const") && + !schema.defines("enum"); + } + + auto transform(sourcemeta::alterschema::Transformer &transformer) const + -> void override { + sourcemeta::jsontoolkit::JSON values = + sourcemeta::jsontoolkit::JSON::make_array(); + values.push_back(transformer.schema().at("const")); + transformer.assign("enum", values); + transformer.erase("const"); + } +}; diff --git a/vendor/alterschema/src/linter/desugar/exclusive_maximum_integer_to_maximum.h b/vendor/alterschema/src/linter/desugar/exclusive_maximum_integer_to_maximum.h new file mode 100644 index 00000000..c2d139b7 --- /dev/null +++ b/vendor/alterschema/src/linter/desugar/exclusive_maximum_integer_to_maximum.h @@ -0,0 +1,39 @@ +class ExclusiveMaximumIntegerToMaximum final : public Rule { +public: + ExclusiveMaximumIntegerToMaximum() + : Rule("exclusive_maximum_integer_to_maximum", + "Setting `exclusiveMaximum` when `type` is `integer` is syntax " + "sugar for `maximum`") {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/validation", + "https://json-schema.org/draft/2019-09/vocab/validation", + "http://json-schema.org/draft-07/schema#", + "http://json-schema.org/draft-06/schema#"}) && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "integer" && + schema.defines("exclusiveMaximum") && + schema.at("exclusiveMaximum").is_number() && + !schema.defines("maximum"); + } + + auto transform(Transformer &transformer) const -> void override { + if (transformer.schema().at("exclusiveMaximum").is_integer()) { + auto new_maximum = transformer.schema().at("exclusiveMaximum"); + new_maximum += sourcemeta::jsontoolkit::JSON{-1}; + transformer.assign("maximum", new_maximum); + transformer.erase("exclusiveMaximum"); + } else { + const auto current{transformer.schema().at("exclusiveMaximum").to_real()}; + const auto new_value{static_cast(std::floor(current))}; + transformer.assign("maximum", sourcemeta::jsontoolkit::JSON{new_value}); + transformer.erase("exclusiveMaximum"); + } + } +}; diff --git a/vendor/alterschema/src/linter/desugar/exclusive_minimum_integer_to_minimum.h b/vendor/alterschema/src/linter/desugar/exclusive_minimum_integer_to_minimum.h new file mode 100644 index 00000000..d1b37f03 --- /dev/null +++ b/vendor/alterschema/src/linter/desugar/exclusive_minimum_integer_to_minimum.h @@ -0,0 +1,39 @@ +class ExclusiveMinimumIntegerToMinimum final : public Rule { +public: + ExclusiveMinimumIntegerToMinimum() + : Rule("exclusive_minimum_integer_to_minimum", + "Setting `exclusiveMinimum` when `type` is `integer` is syntax " + "sugar for `minimum`") {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/validation", + "https://json-schema.org/draft/2019-09/vocab/validation", + "http://json-schema.org/draft-07/schema#", + "http://json-schema.org/draft-06/schema#"}) && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "integer" && + schema.defines("exclusiveMinimum") && + schema.at("exclusiveMinimum").is_number() && + !schema.defines("minimum"); + } + + auto transform(Transformer &transformer) const -> void override { + if (transformer.schema().at("exclusiveMinimum").is_integer()) { + auto new_minimum = transformer.schema().at("exclusiveMinimum"); + new_minimum += sourcemeta::jsontoolkit::JSON{1}; + transformer.assign("minimum", new_minimum); + transformer.erase("exclusiveMinimum"); + } else { + const auto current{transformer.schema().at("exclusiveMinimum").to_real()}; + const auto new_value{static_cast(std::ceil(current))}; + transformer.assign("minimum", sourcemeta::jsontoolkit::JSON{new_value}); + transformer.erase("exclusiveMinimum"); + } + } +}; diff --git a/vendor/alterschema/src/linter/desugar/type_array_to_any_of_2020_12.h b/vendor/alterschema/src/linter/desugar/type_array_to_any_of_2020_12.h new file mode 100644 index 00000000..f59891c1 --- /dev/null +++ b/vendor/alterschema/src/linter/desugar/type_array_to_any_of_2020_12.h @@ -0,0 +1,47 @@ +class TypeArrayToAnyOf_2020_12 final : public Rule { +public: + TypeArrayToAnyOf_2020_12() + : Rule{"type_array_to_any_of_2020_12", + "Setting `type` to more than one choice is syntax sugar to " + "`anyOf` over the corresponding types"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/validation", + "https://json-schema.org/draft/2020-12/vocab/applicator"}) && + schema.is_object() && schema.defines("type") && + schema.at("type").is_array() && + // Non type-specific applicators can leads to invalid schemas + !schema.defines("$defs") && !schema.defines("$ref") && + !schema.defines("if") && !schema.defines("then") && + !schema.defines("else") && !schema.defines("allOf") && + !schema.defines("oneOf") && !schema.defines("anyOf"); + } + + auto transform(sourcemeta::alterschema::Transformer &transformer) const + -> void override { + const std::set keep{"$schema", "$id", "$anchor", + "$dynamicAnchor", "$vocabulary"}; + auto disjunctors{sourcemeta::jsontoolkit::JSON::make_array()}; + for (const auto &type : transformer.schema().at("type").as_array()) { + auto copy = transformer.schema(); + copy.erase_keys(keep.cbegin(), keep.cend()); + copy.assign("type", type); + disjunctors.push_back(std::move(copy)); + } + + auto result{sourcemeta::jsontoolkit::JSON::make_object()}; + for (const auto &keyword : keep) { + if (transformer.schema().defines(keyword)) { + result.assign(keyword, transformer.schema().at(keyword)); + } + } + + result.assign("anyOf", std::move(disjunctors)); + transformer.replace(std::move(result)); + } +}; diff --git a/vendor/alterschema/src/linter/desugar/type_boolean_as_enum.h b/vendor/alterschema/src/linter/desugar/type_boolean_as_enum.h new file mode 100644 index 00000000..d3693c6c --- /dev/null +++ b/vendor/alterschema/src/linter/desugar/type_boolean_as_enum.h @@ -0,0 +1,35 @@ +class TypeBooleanAsEnum final : public Rule { +public: + TypeBooleanAsEnum() + : Rule{"type_boolean_as_enum", + "Setting `type` to `boolean` is syntax sugar for an enumeration " + "of two values: `false` and `true`"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/validation", + "https://json-schema.org/draft/2019-09/vocab/validation", + "http://json-schema.org/draft-07/schema#", + "http://json-schema.org/draft-06/schema#", + "http://json-schema.org/draft-04/schema#", + "http://json-schema.org/draft-03/schema#", + "http://json-schema.org/draft-02/hyper-schema#", + "http://json-schema.org/draft-01/hyper-schema#"}) && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "boolean" && + !schema.defines("enum") && !schema.defines("const"); + } + + auto transform(Transformer &transformer) const -> void override { + auto choices = sourcemeta::jsontoolkit::JSON::make_array(); + choices.push_back(sourcemeta::jsontoolkit::JSON{false}); + choices.push_back(sourcemeta::jsontoolkit::JSON{true}); + transformer.assign("enum", choices); + transformer.erase("type"); + } +}; diff --git a/vendor/alterschema/src/linter/desugar/type_null_as_enum.h b/vendor/alterschema/src/linter/desugar/type_null_as_enum.h new file mode 100644 index 00000000..e2c6aa3e --- /dev/null +++ b/vendor/alterschema/src/linter/desugar/type_null_as_enum.h @@ -0,0 +1,34 @@ +class TypeNullAsEnum final : public Rule { +public: + TypeNullAsEnum() + : Rule{"type_null_as_enum", + "Setting `type` to `null` is syntax sugar for an enumeration " + "of a single value: `null`"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/validation", + "https://json-schema.org/draft/2019-09/vocab/validation", + "http://json-schema.org/draft-07/schema#", + "http://json-schema.org/draft-06/schema#", + "http://json-schema.org/draft-04/schema#", + "http://json-schema.org/draft-03/schema#", + "http://json-schema.org/draft-02/hyper-schema#", + "http://json-schema.org/draft-01/hyper-schema#"}) && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "null" && !schema.defines("enum") && + !schema.defines("const"); + } + + auto transform(Transformer &transformer) const -> void override { + auto choices = sourcemeta::jsontoolkit::JSON::make_array(); + choices.push_back(sourcemeta::jsontoolkit::JSON{nullptr}); + transformer.assign("enum", choices); + transformer.erase("type"); + } +}; diff --git a/vendor/alterschema/src/linter/implicit/max_contains_covered_by_max_items.h b/vendor/alterschema/src/linter/implicit/max_contains_covered_by_max_items.h new file mode 100644 index 00000000..40ccef77 --- /dev/null +++ b/vendor/alterschema/src/linter/implicit/max_contains_covered_by_max_items.h @@ -0,0 +1,27 @@ +class MaxContainsCoveredByMaxItems final : public Rule { +public: + MaxContainsCoveredByMaxItems() + : Rule{"max_contains_covered_by_max_items", + "Setting the `maxContains` keyword to a number greater than or " + "equal to the array upper bound does not add any further " + "constraint"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/validation", + "https://json-schema.org/draft/2019-09/vocab/validation"}) && + schema.is_object() && schema.defines("maxContains") && + schema.at("maxContains").is_integer() && + schema.defines("maxItems") && schema.at("maxItems").is_integer() && + schema.at("maxContains").to_integer() > + schema.at("maxItems").to_integer(); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.assign("maxContains", transformer.schema().at("maxItems")); + } +}; diff --git a/vendor/alterschema/src/linter/implicit/min_items_given_min_contains.h b/vendor/alterschema/src/linter/implicit/min_items_given_min_contains.h new file mode 100644 index 00000000..9e9ad51a --- /dev/null +++ b/vendor/alterschema/src/linter/implicit/min_items_given_min_contains.h @@ -0,0 +1,33 @@ +class MinItemsGivenMinContains final : public sourcemeta::alterschema::Rule { +public: + MinItemsGivenMinContains() + : Rule{"min_items_given_min_contains", + "Every array has a minimum size of zero items but may be affected " + "by `minContains`"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/validation", + "https://json-schema.org/draft/2019-09/vocab/validation"}) && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "array" && + !schema.defines("minItems"); + } + + auto transform(Transformer &transformer) const -> void override { + if (transformer.schema().defines("contains") && + transformer.schema().defines("minContains") && + transformer.schema().at("minContains").is_integer()) { + transformer.assign( + "minItems", sourcemeta::jsontoolkit::JSON{ + transformer.schema().at("minContains").to_integer()}); + } else { + transformer.assign("minItems", sourcemeta::jsontoolkit::JSON{0}); + } + } +}; diff --git a/vendor/alterschema/src/linter/implicit/min_items_implicit.h b/vendor/alterschema/src/linter/implicit/min_items_implicit.h new file mode 100644 index 00000000..6eebbded --- /dev/null +++ b/vendor/alterschema/src/linter/implicit/min_items_implicit.h @@ -0,0 +1,27 @@ +class MinItemsImplicit final : public Rule { +public: + MinItemsImplicit() + : Rule{"min_items_implicit", + "Every array has a minimum size of zero items"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any(vocabularies, + {"http://json-schema.org/draft-07/schema#", + "http://json-schema.org/draft-06/schema#", + "http://json-schema.org/draft-04/schema#", + "http://json-schema.org/draft-03/schema#", + "http://json-schema.org/draft-02/hyper-schema#", + "http://json-schema.org/draft-01/hyper-schema#"}) && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "array" && + !schema.defines("minItems"); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.assign("minItems", sourcemeta::jsontoolkit::JSON{0}); + } +}; diff --git a/vendor/alterschema/src/linter/implicit/min_length_implicit.h b/vendor/alterschema/src/linter/implicit/min_length_implicit.h new file mode 100644 index 00000000..4744f343 --- /dev/null +++ b/vendor/alterschema/src/linter/implicit/min_length_implicit.h @@ -0,0 +1,30 @@ +class MinLengthImplicit final : public sourcemeta::alterschema::Rule { +public: + MinLengthImplicit() + : Rule{"min_length_implicit", + "Every string has a minimum length of zero characters"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/validation", + "https://json-schema.org/draft/2019-09/vocab/validation", + "http://json-schema.org/draft-07/schema#", + "http://json-schema.org/draft-06/schema#", + "http://json-schema.org/draft-04/schema#", + "http://json-schema.org/draft-03/schema#", + "http://json-schema.org/draft-02/hyper-schema#", + "http://json-schema.org/draft-01/hyper-schema#"}) && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "string" && + !schema.defines("minLength"); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.assign("minLength", sourcemeta::jsontoolkit::JSON{0}); + } +}; diff --git a/vendor/alterschema/src/linter/implicit/min_properties_covered_by_required.h b/vendor/alterschema/src/linter/implicit/min_properties_covered_by_required.h new file mode 100644 index 00000000..c9e138fa --- /dev/null +++ b/vendor/alterschema/src/linter/implicit/min_properties_covered_by_required.h @@ -0,0 +1,33 @@ +class MinPropertiesCoveredByRequired final : public Rule { +public: + MinPropertiesCoveredByRequired() + : Rule{"min_properties_covered_by_required", + "Setting `minProperties` to a number less than `required` does " + "not add any further constraint"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/validation", + "https://json-schema.org/draft/2019-09/vocab/validation", + "http://json-schema.org/draft-07/schema#", + "http://json-schema.org/draft-06/schema#", + "http://json-schema.org/draft-04/schema#"}) && + schema.is_object() && schema.defines("minProperties") && + schema.at("minProperties").is_integer() && + schema.defines("required") && schema.at("required").is_array() && + schema.at("required").unique() && + schema.at("required").size() > + static_cast( + schema.at("minProperties").to_integer()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.assign("minProperties", + sourcemeta::jsontoolkit::JSON{ + transformer.schema().at("required").size()}); + } +}; diff --git a/vendor/alterschema/src/linter/implicit/min_properties_implicit.h b/vendor/alterschema/src/linter/implicit/min_properties_implicit.h new file mode 100644 index 00000000..776ba6eb --- /dev/null +++ b/vendor/alterschema/src/linter/implicit/min_properties_implicit.h @@ -0,0 +1,35 @@ +class MinPropertiesImplicit final : public Rule { +public: + MinPropertiesImplicit() + : Rule{"min_properties_implicit", + "The `minProperties` keyword has a logical default of 0 or the " + "size of `required`"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/validation", + "https://json-schema.org/draft/2019-09/vocab/validation", + "http://json-schema.org/draft-07/schema#", + "http://json-schema.org/draft-06/schema#", + "http://json-schema.org/draft-04/schema#"}) && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "object" && + !schema.defines("minProperties"); + } + + auto transform(Transformer &transformer) const -> void override { + if (transformer.schema().defines("required") && + transformer.schema().at("required").is_array()) { + transformer.assign("minProperties", + sourcemeta::jsontoolkit::JSON{ + transformer.schema().at("required").size()}); + } else { + transformer.assign("minProperties", sourcemeta::jsontoolkit::JSON{0}); + } + } +}; diff --git a/vendor/alterschema/src/linter/implicit/multiple_of_implicit.h b/vendor/alterschema/src/linter/implicit/multiple_of_implicit.h new file mode 100644 index 00000000..9b36253d --- /dev/null +++ b/vendor/alterschema/src/linter/implicit/multiple_of_implicit.h @@ -0,0 +1,28 @@ +class MultipleOfImplicit final : public Rule { +public: + MultipleOfImplicit() + : Rule{"multiple_of_implicit", + "The unit of `multipleOf` is the integer 1"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/validation", + "https://json-schema.org/draft/2019-09/vocab/validation", + "http://json-schema.org/draft-07/schema#", + "http://json-schema.org/draft-06/schema#", + "http://json-schema.org/draft-04/schema#"}) && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + (schema.at("type").to_string() == "integer" || + schema.at("type").to_string() == "number") && + !schema.defines("multipleOf"); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.assign("multipleOf", sourcemeta::jsontoolkit::JSON{1}); + } +}; diff --git a/vendor/alterschema/src/linter/implicit/properties_implicit.h b/vendor/alterschema/src/linter/implicit/properties_implicit.h new file mode 100644 index 00000000..4980cfe7 --- /dev/null +++ b/vendor/alterschema/src/linter/implicit/properties_implicit.h @@ -0,0 +1,36 @@ +class PropertiesImplicit final : public sourcemeta::alterschema::Rule { +public: + PropertiesImplicit() + : Rule{"properties_implicit", "Every object has an implicit `properties` " + "that consists of the empty object"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return ((vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/applicator")) || + (vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/validation") && + vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/applicator")) || + contains_any(vocabularies, + {"http://json-schema.org/draft-07/schema#", + "http://json-schema.org/draft-06/schema#", + "http://json-schema.org/draft-04/schema#", + "http://json-schema.org/draft-03/schema#", + "http://json-schema.org/draft-02/hyper-schema#", + "http://json-schema.org/draft-01/hyper-schema#"})) && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "object" && + !schema.defines("properties"); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.assign("properties", + sourcemeta::jsontoolkit::JSON::make_object()); + } +}; diff --git a/vendor/alterschema/src/linter/implicit/type_union_implicit.h b/vendor/alterschema/src/linter/implicit/type_union_implicit.h new file mode 100644 index 00000000..d9c16d41 --- /dev/null +++ b/vendor/alterschema/src/linter/implicit/type_union_implicit.h @@ -0,0 +1,133 @@ +class TypeUnionImplicit final : public sourcemeta::alterschema::Rule { +public: + TypeUnionImplicit() + : Rule{"type_union_implicit", + "Not setting `type` is equivalent to accepting any type"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + if (!schema.is_object()) { + return false; + } + + if (contains_any(vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/validation", + "https://json-schema.org/draft/2019-09/vocab/validation", + "http://json-schema.org/draft-07/schema#", + "http://json-schema.org/draft-06/schema#", + "http://json-schema.org/draft-04/schema#", + "http://json-schema.org/draft-03/schema#", + "http://json-schema.org/draft-02/hyper-schema#", + "http://json-schema.org/draft-01/hyper-schema#", + "http://json-schema.org/draft-00/hyper-schema#"})) { + if (schema.defines("type")) { + return false; + } + + // Don't apply if we don't have the necessary vocabularies + } else { + return false; + } + + if (vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/core") && + schema.defines_any({"$ref", "$dynamicRef"})) { + return false; + } + + if (vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/applicator") && + schema.defines_any( + {"anyOf", "oneOf", "allOf", "if", "then", "else", "not"})) { + return false; + } + + if (vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.defines_any({"enum", "const"})) { + return false; + } + + if (vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/core") && + schema.defines_any({"$ref", "$recursiveRef"})) { + return false; + } + + if (vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/applicator") && + schema.defines_any( + {"anyOf", "oneOf", "allOf", "if", "then", "else", "not"})) { + return false; + } + + if (vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/validation") && + schema.defines_any({"enum", "const"})) { + return false; + } + + if (vocabularies.contains("http://json-schema.org/draft-07/schema#") && + schema.defines_any({"$ref", "enum", "const", "anyOf", "oneOf", "allOf", + "if", "then", "else", "not"})) { + return false; + } + + if (vocabularies.contains("http://json-schema.org/draft-06/schema#") && + schema.defines_any( + {"$ref", "enum", "const", "anyOf", "oneOf", "allOf", "not"})) { + return false; + } + + if (vocabularies.contains("http://json-schema.org/draft-04/schema#") && + schema.defines_any( + {"$ref", "enum", "anyOf", "oneOf", "allOf", "not"})) { + return false; + } + + if (vocabularies.contains("http://json-schema.org/draft-03/schema#") && + schema.defines_any({"$ref", "enum", "disallow", "extends"})) { + return false; + } + + if (vocabularies.contains( + "http://json-schema.org/draft-02/hyper-schema#") && + schema.defines_any({"enum", "disallow", "extends"})) { + return false; + } + + if (vocabularies.contains( + "http://json-schema.org/draft-01/hyper-schema#") && + schema.defines_any({"enum", "disallow", "extends"})) { + return false; + } + + if (vocabularies.contains( + "http://json-schema.org/draft-00/hyper-schema#") && + schema.defines_any({"enum", "disallow", "extends"})) { + return false; + } + + return true; + } + + auto transform(sourcemeta::alterschema::Transformer &transformer) const + -> void override { + auto types{sourcemeta::jsontoolkit::JSON::make_array()}; + + // All possible JSON Schema types + // See + // https://json-schema.org/draft/2020-12/json-schema-validation.html#rfc.section.6.1.1 + types.push_back(sourcemeta::jsontoolkit::JSON{"null"}); + types.push_back(sourcemeta::jsontoolkit::JSON{"boolean"}); + types.push_back(sourcemeta::jsontoolkit::JSON{"object"}); + types.push_back(sourcemeta::jsontoolkit::JSON{"array"}); + types.push_back(sourcemeta::jsontoolkit::JSON{"string"}); + types.push_back(sourcemeta::jsontoolkit::JSON{"number"}); + types.push_back(sourcemeta::jsontoolkit::JSON{"integer"}); + + transformer.assign("type", std::move(types)); + } +}; diff --git a/vendor/alterschema/src/linter/include/sourcemeta/alterschema/linter.h b/vendor/alterschema/src/linter/include/sourcemeta/alterschema/linter.h index 22f4b52d..97379e9b 100644 --- a/vendor/alterschema/src/linter/include/sourcemeta/alterschema/linter.h +++ b/vendor/alterschema/src/linter/include/sourcemeta/alterschema/linter.h @@ -16,20 +16,41 @@ namespace sourcemeta::alterschema { +// TODO: Revise the category names to make incompatibilities more obvious + /// @ingroup linter /// The category of a built-in transformation rule enum class LinterCategory { - /// Rules that make use of newer features within the same dialect - Modernize, - - /// Rules that detect common anti-patterns + /// Rules that detect clear anti-patterns that should not be happening on the + /// first place AntiPattern, - /// Rules that simplify the given schema + /// Rules that simplify the given schema for both human readability and + /// performance Simplify, - /// Rules that remove schema redundancies - Redundant + /// Rules that take advantage of syntax sugar to improve human readability of + /// a schema. As its name implies, this category is incompatible with + /// `Desugar`. + SyntaxSugar, + + /// Rules that simplify keywords that are syntax sugar to other keywords, + /// potentially decreasing human readability in favor of explicitness + /// As its name implies, this category is incompatible with `SyntaxSugar`. + Desugar, + + /// Rules that remove schema redundancies that do not contribute to the + /// schema. + /// This category is incompatible with `Implicit` + Redundant, + + /// Rules that surface implicit constraints. This category is incompatible + /// with `Redundant` + Implicit, + + /// Rules that remove keywords that are superfluous and take no effect on the + /// given schema + Superfluous }; /// @ingroup linter @@ -42,7 +63,7 @@ enum class LinterCategory { /// sourcemeta::alterschema::Bundle bundle; /// /// sourcemeta::alterschema::add(bundle, -/// sourcemeta::alterschema::LinterCategory::Modernize); +/// sourcemeta::alterschema::LinterCategory::SyntaxSugar); /// /// auto schema = sourcemeta::jsontoolkit::parse(R"JSON({ /// "$schema": "https://json-schema.org/draft/2020-12/schema", diff --git a/vendor/alterschema/src/linter/linter.cc b/vendor/alterschema/src/linter/linter.cc index 62a1cfa6..517da21b 100644 --- a/vendor/alterschema/src/linter/linter.cc +++ b/vendor/alterschema/src/linter/linter.cc @@ -3,8 +3,9 @@ #include // assert // For built-in rules -#include // std::any_of -#include // std::cbegin, std::cend +#include +#include +#include namespace sourcemeta::alterschema { template auto contains_any(const T &container, const T &values) -> bool { @@ -13,55 +14,327 @@ auto contains_any(const T &container, const T &values) -> bool { [&values](const auto &element) { return values.contains(element); }); } -// Modernize -#include "modernize/enum_to_const.h" +template auto every_item_is_null(const T &container) -> bool { + return std::all_of(std::cbegin(container), std::cend(container), + [](const auto &element) { return element.is_null(); }); +} + +template auto every_item_is_boolean(const T &container) -> bool { + return std::all_of(std::cbegin(container), std::cend(container), + [](const auto &element) { return element.is_boolean(); }); +} + // AntiPattern #include "antipattern/const_with_type.h" +#include "antipattern/duplicate_enum_values.h" +#include "antipattern/duplicate_required_values.h" #include "antipattern/enum_with_type.h" +#include "antipattern/exclusive_maximum_number_and_maximum.h" +#include "antipattern/exclusive_minimum_number_and_minimum.h" // Simplify +#include "simplify/dependencies_property_tautology.h" +#include "simplify/dependent_required_tautology.h" +#include "simplify/equal_numeric_bounds_to_enum.h" +#include "simplify/maximum_real_for_integer.h" +#include "simplify/minimum_real_for_integer.h" #include "simplify/single_type_array.h" +// Syntax sugar +#include "syntax_sugar/enum_to_const.h" +// Desugar +#include "desugar/boolean_true.h" +#include "desugar/const_as_enum.h" +#include "desugar/exclusive_maximum_integer_to_maximum.h" +#include "desugar/exclusive_minimum_integer_to_minimum.h" +#include "desugar/type_array_to_any_of_2020_12.h" +#include "desugar/type_boolean_as_enum.h" +#include "desugar/type_null_as_enum.h" + // Redundant #include "redundant/additional_properties_default.h" -#include "redundant/content_media_type_without_encoding.h" #include "redundant/content_schema_default.h" -#include "redundant/content_schema_without_media_type.h" -#include "redundant/else_without_if.h" +#include "redundant/dependencies_default.h" +#include "redundant/dependent_required_default.h" #include "redundant/items_array_default.h" #include "redundant/items_schema_default.h" -#include "redundant/max_contains_without_contains.h" -#include "redundant/min_contains_without_contains.h" -#include "redundant/then_without_if.h" +#include "redundant/pattern_properties_default.h" +#include "redundant/properties_default.h" #include "redundant/unevaluated_items_default.h" #include "redundant/unevaluated_properties_default.h" +#include "redundant/unsatisfiable_max_contains.h" +#include "redundant/unsatisfiable_min_properties.h" +// Implicit +#include "implicit/max_contains_covered_by_max_items.h" +#include "implicit/min_items_given_min_contains.h" +#include "implicit/min_items_implicit.h" +#include "implicit/min_length_implicit.h" +#include "implicit/min_properties_covered_by_required.h" +#include "implicit/min_properties_implicit.h" +#include "implicit/multiple_of_implicit.h" +#include "implicit/properties_implicit.h" +#include "implicit/type_union_implicit.h" +// Superfluous +#include "superfluous/content_media_type_without_encoding.h" +#include "superfluous/content_schema_without_media_type.h" +#include "superfluous/drop_non_array_keywords_applicator_2019_09.h" +#include "superfluous/drop_non_array_keywords_applicator_2020_12.h" +#include "superfluous/drop_non_array_keywords_content_2019_09.h" +#include "superfluous/drop_non_array_keywords_content_2020_12.h" +#include "superfluous/drop_non_array_keywords_draft0.h" +#include "superfluous/drop_non_array_keywords_draft1.h" +#include "superfluous/drop_non_array_keywords_draft2.h" +#include "superfluous/drop_non_array_keywords_draft3.h" +#include "superfluous/drop_non_array_keywords_draft4.h" +#include "superfluous/drop_non_array_keywords_draft6.h" +#include "superfluous/drop_non_array_keywords_draft7.h" +#include "superfluous/drop_non_array_keywords_format_2019_09.h" +#include "superfluous/drop_non_array_keywords_format_2020_12.h" +#include "superfluous/drop_non_array_keywords_unevaluated_2020_12.h" +#include "superfluous/drop_non_array_keywords_validation_2019_09.h" +#include "superfluous/drop_non_array_keywords_validation_2020_12.h" +#include "superfluous/drop_non_boolean_keywords_applicator_2019_09.h" +#include "superfluous/drop_non_boolean_keywords_applicator_2020_12.h" +#include "superfluous/drop_non_boolean_keywords_content_2019_09.h" +#include "superfluous/drop_non_boolean_keywords_content_2020_12.h" +#include "superfluous/drop_non_boolean_keywords_draft0.h" +#include "superfluous/drop_non_boolean_keywords_draft1.h" +#include "superfluous/drop_non_boolean_keywords_draft2.h" +#include "superfluous/drop_non_boolean_keywords_draft3.h" +#include "superfluous/drop_non_boolean_keywords_draft4.h" +#include "superfluous/drop_non_boolean_keywords_draft6.h" +#include "superfluous/drop_non_boolean_keywords_draft7.h" +#include "superfluous/drop_non_boolean_keywords_format_2019_09.h" +#include "superfluous/drop_non_boolean_keywords_format_2020_12.h" +#include "superfluous/drop_non_boolean_keywords_unevaluated_2020_12.h" +#include "superfluous/drop_non_boolean_keywords_validation_2019_09.h" +#include "superfluous/drop_non_boolean_keywords_validation_2020_12.h" +#include "superfluous/drop_non_null_keywords_applicator_2019_09.h" +#include "superfluous/drop_non_null_keywords_applicator_2020_12.h" +#include "superfluous/drop_non_null_keywords_content_2019_09.h" +#include "superfluous/drop_non_null_keywords_content_2020_12.h" +#include "superfluous/drop_non_null_keywords_draft0.h" +#include "superfluous/drop_non_null_keywords_draft1.h" +#include "superfluous/drop_non_null_keywords_draft2.h" +#include "superfluous/drop_non_null_keywords_draft3.h" +#include "superfluous/drop_non_null_keywords_draft4.h" +#include "superfluous/drop_non_null_keywords_draft6.h" +#include "superfluous/drop_non_null_keywords_draft7.h" +#include "superfluous/drop_non_null_keywords_format_2019_09.h" +#include "superfluous/drop_non_null_keywords_format_2020_12.h" +#include "superfluous/drop_non_null_keywords_unevaluated_2020_12.h" +#include "superfluous/drop_non_null_keywords_validation_2019_09.h" +#include "superfluous/drop_non_null_keywords_validation_2020_12.h" +#include "superfluous/drop_non_numeric_keywords_applicator_2019_09.h" +#include "superfluous/drop_non_numeric_keywords_applicator_2020_12.h" +#include "superfluous/drop_non_numeric_keywords_content_2019_09.h" +#include "superfluous/drop_non_numeric_keywords_content_2020_12.h" +#include "superfluous/drop_non_numeric_keywords_draft0.h" +#include "superfluous/drop_non_numeric_keywords_draft1.h" +#include "superfluous/drop_non_numeric_keywords_draft2.h" +#include "superfluous/drop_non_numeric_keywords_draft3.h" +#include "superfluous/drop_non_numeric_keywords_draft4.h" +#include "superfluous/drop_non_numeric_keywords_draft6.h" +#include "superfluous/drop_non_numeric_keywords_draft7.h" +#include "superfluous/drop_non_numeric_keywords_format_2019_09.h" +#include "superfluous/drop_non_numeric_keywords_format_2020_12.h" +#include "superfluous/drop_non_numeric_keywords_unevaluated_2020_12.h" +#include "superfluous/drop_non_numeric_keywords_validation_2019_09.h" +#include "superfluous/drop_non_numeric_keywords_validation_2020_12.h" +#include "superfluous/drop_non_object_keywords_applicator_2019_09.h" +#include "superfluous/drop_non_object_keywords_applicator_2020_12.h" +#include "superfluous/drop_non_object_keywords_content_2019_09.h" +#include "superfluous/drop_non_object_keywords_content_2020_12.h" +#include "superfluous/drop_non_object_keywords_draft0.h" +#include "superfluous/drop_non_object_keywords_draft1.h" +#include "superfluous/drop_non_object_keywords_draft2.h" +#include "superfluous/drop_non_object_keywords_draft3.h" +#include "superfluous/drop_non_object_keywords_draft4.h" +#include "superfluous/drop_non_object_keywords_draft6.h" +#include "superfluous/drop_non_object_keywords_draft7.h" +#include "superfluous/drop_non_object_keywords_format_2019_09.h" +#include "superfluous/drop_non_object_keywords_format_2020_12.h" +#include "superfluous/drop_non_object_keywords_unevaluated_2020_12.h" +#include "superfluous/drop_non_object_keywords_validation_2019_09.h" +#include "superfluous/drop_non_object_keywords_validation_2020_12.h" +#include "superfluous/drop_non_string_keywords_applicator_2019_09.h" +#include "superfluous/drop_non_string_keywords_applicator_2020_12.h" +#include "superfluous/drop_non_string_keywords_draft0.h" +#include "superfluous/drop_non_string_keywords_draft1.h" +#include "superfluous/drop_non_string_keywords_draft2.h" +#include "superfluous/drop_non_string_keywords_draft3.h" +#include "superfluous/drop_non_string_keywords_draft4.h" +#include "superfluous/drop_non_string_keywords_draft6.h" +#include "superfluous/drop_non_string_keywords_draft7.h" +#include "superfluous/drop_non_string_keywords_unevaluated_2020_12.h" +#include "superfluous/drop_non_string_keywords_validation_2019_09.h" +#include "superfluous/drop_non_string_keywords_validation_2020_12.h" +#include "superfluous/duplicate_allof_branches.h" +#include "superfluous/duplicate_anyof_branches.h" +#include "superfluous/else_without_if.h" +#include "superfluous/if_without_then_else.h" +#include "superfluous/max_contains_without_contains.h" +#include "superfluous/min_contains_without_contains.h" +#include "superfluous/then_without_if.h" } // namespace sourcemeta::alterschema namespace sourcemeta::alterschema { auto add(Bundle &bundle, const LinterCategory category) -> void { switch (category) { - case LinterCategory::Modernize: - bundle.add(); - break; case LinterCategory::AntiPattern: bundle.add(); + bundle.add(); + bundle.add(); bundle.add(); + bundle.add(); + bundle.add(); break; case LinterCategory::Simplify: + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); bundle.add(); break; + case LinterCategory::SyntaxSugar: + bundle.add(); + break; + case LinterCategory::Desugar: + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + break; case LinterCategory::Redundant: bundle.add(); - bundle.add(); bundle.add(); - bundle.add(); - bundle.add(); + bundle.add(); + bundle.add(); bundle.add(); bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + break; + case LinterCategory::Implicit: + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + break; + case LinterCategory::Superfluous: + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); + bundle.add(); bundle.add(); bundle.add(); bundle.add(); - bundle.add(); - bundle.add(); break; default: // We should never get here diff --git a/vendor/alterschema/src/linter/redundant/dependencies_default.h b/vendor/alterschema/src/linter/redundant/dependencies_default.h new file mode 100644 index 00000000..426cab05 --- /dev/null +++ b/vendor/alterschema/src/linter/redundant/dependencies_default.h @@ -0,0 +1,25 @@ +class DependenciesDefault final : public Rule { +public: + DependenciesDefault() + : Rule{"dependencies_default", + "Setting the `dependencies` keyword to an empty object " + "does not add any further constraint"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any(vocabularies, + {"http://json-schema.org/draft-07/schema#", + "http://json-schema.org/draft-06/schema#", + "http://json-schema.org/draft-04/schema#", + "http://json-schema.org/draft-03/schema#"}) && + schema.is_object() && schema.defines("dependencies") && + schema.at("dependencies").is_object() && + schema.at("dependencies").empty(); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase("dependencies"); + } +}; diff --git a/vendor/alterschema/src/linter/redundant/dependent_required_default.h b/vendor/alterschema/src/linter/redundant/dependent_required_default.h new file mode 100644 index 00000000..bd9fe37a --- /dev/null +++ b/vendor/alterschema/src/linter/redundant/dependent_required_default.h @@ -0,0 +1,24 @@ +class DependentRequiredDefault final : public Rule { +public: + DependentRequiredDefault() + : Rule{"dependent_required_default", + "Setting the `dependentRequired` keyword to an empty object " + "does not add any further constraint"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/validation", + "https://json-schema.org/draft/2019-09/vocab/validation"}) && + schema.is_object() && schema.defines("dependentRequired") && + schema.at("dependentRequired").is_object() && + schema.at("dependentRequired").empty(); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase("dependentRequired"); + } +}; diff --git a/vendor/alterschema/src/linter/redundant/pattern_properties_default.h b/vendor/alterschema/src/linter/redundant/pattern_properties_default.h new file mode 100644 index 00000000..71ae3226 --- /dev/null +++ b/vendor/alterschema/src/linter/redundant/pattern_properties_default.h @@ -0,0 +1,28 @@ +class PatternPropertiesDefault final : public Rule { +public: + PatternPropertiesDefault() + : Rule{"pattern_properties_default", + "Setting the `patternProperties` keyword to the empty object " + "does not add any further constraint"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/applicator", + "https://json-schema.org/draft/2019-09/vocab/applicator", + "http://json-schema.org/draft-07/schema#", + "http://json-schema.org/draft-06/schema#", + "http://json-schema.org/draft-04/schema#", + "http://json-schema.org/draft-03/schema#"}) && + schema.is_object() && schema.defines("patternProperties") && + schema.at("patternProperties").is_object() && + schema.at("patternProperties").empty(); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase("patternProperties"); + } +}; diff --git a/vendor/alterschema/src/linter/redundant/properties_default.h b/vendor/alterschema/src/linter/redundant/properties_default.h new file mode 100644 index 00000000..99b7015a --- /dev/null +++ b/vendor/alterschema/src/linter/redundant/properties_default.h @@ -0,0 +1,30 @@ +class PropertiesDefault final : public Rule { +public: + PropertiesDefault() + : Rule{"properties_default", + "Setting the `properties` keyword to the empty object " + "does not add any further constraint"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/applicator", + "https://json-schema.org/draft/2019-09/vocab/applicator", + "http://json-schema.org/draft-07/schema#", + "http://json-schema.org/draft-06/schema#", + "http://json-schema.org/draft-04/schema#", + "http://json-schema.org/draft-03/schema#", + "http://json-schema.org/draft-02/hyper-schema#", + "http://json-schema.org/draft-01/hyper-schema#"}) && + schema.is_object() && schema.defines("properties") && + schema.at("properties").is_object() && + schema.at("properties").empty(); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase("properties"); + } +}; diff --git a/vendor/alterschema/src/linter/redundant/unsatisfiable_max_contains.h b/vendor/alterschema/src/linter/redundant/unsatisfiable_max_contains.h new file mode 100644 index 00000000..9987784b --- /dev/null +++ b/vendor/alterschema/src/linter/redundant/unsatisfiable_max_contains.h @@ -0,0 +1,27 @@ +class UnsatisfiableMaxContains final : public Rule { +public: + UnsatisfiableMaxContains() + : Rule{"unsatisfiable_max_contains", + "Setting the `maxContains` keyword to a number greater than or " + "equal to the array upper bound does not add any further " + "constraint"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/validation", + "https://json-schema.org/draft/2019-09/vocab/validation"}) && + schema.is_object() && schema.defines("maxContains") && + schema.at("maxContains").is_integer() && + schema.defines("maxItems") && schema.at("maxItems").is_integer() && + schema.at("maxContains").to_integer() >= + schema.at("maxItems").to_integer(); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase("maxContains"); + } +}; diff --git a/vendor/alterschema/src/linter/redundant/unsatisfiable_min_properties.h b/vendor/alterschema/src/linter/redundant/unsatisfiable_min_properties.h new file mode 100644 index 00000000..a4460d00 --- /dev/null +++ b/vendor/alterschema/src/linter/redundant/unsatisfiable_min_properties.h @@ -0,0 +1,31 @@ +class UnsatisfiableMinProperties final : public Rule { +public: + UnsatisfiableMinProperties() + : Rule{"unsatisfiable_min_properties", + "Setting `minProperties` to a number less than `required` does " + "not add any further constraint"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/validation", + "https://json-schema.org/draft/2019-09/vocab/validation", + "http://json-schema.org/draft-07/schema#", + "http://json-schema.org/draft-06/schema#", + "http://json-schema.org/draft-04/schema#"}) && + schema.is_object() && schema.defines("minProperties") && + schema.at("minProperties").is_integer() && + schema.defines("required") && schema.at("required").is_array() && + schema.at("required").unique() && + schema.at("required").size() >= + static_cast( + schema.at("minProperties").to_integer()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase("minProperties"); + } +}; diff --git a/vendor/alterschema/src/linter/simplify/dependencies_property_tautology.h b/vendor/alterschema/src/linter/simplify/dependencies_property_tautology.h new file mode 100644 index 00000000..0a46c0db --- /dev/null +++ b/vendor/alterschema/src/linter/simplify/dependencies_property_tautology.h @@ -0,0 +1,73 @@ +class DependenciesPropertyTautology final : public Rule { +public: + DependenciesPropertyTautology() + : Rule{"dependencies_property_tautology", + "Defining requirements for a property using `dependencies` " + "that is already marked as required is an unnecessarily complex " + "use of `dependencies`"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any(vocabularies, + {"http://json-schema.org/draft-07/schema#", + "http://json-schema.org/draft-06/schema#", + "http://json-schema.org/draft-04/schema#", + "http://json-schema.org/draft-03/schema#"}) && + schema.is_object() && schema.defines("dependencies") && + schema.at("dependencies").is_object() && + schema.defines("required") && schema.at("required").is_array() && + std::any_of(schema.at("required").as_array().cbegin(), + schema.at("required").as_array().cend(), + [&schema](const auto &element) { + return element.is_string() && + schema.at("dependencies") + .defines(element.to_string()) && + (schema.at("dependencies") + .at(element.to_string()) + .is_array() || + schema.at("dependencies") + .at(element.to_string()) + .is_string()); + }); + } + + auto transform(Transformer &transformer) const -> void override { + auto requirements{transformer.schema().at("required")}; + while (true) { + bool match{false}; + const auto copy{requirements}; + for (const auto &element : copy.as_array()) { + if (!element.is_string() || !transformer.schema() + .at("dependencies") + .defines(element.to_string())) { + continue; + } + + const auto &dependents{ + transformer.schema().at("dependencies").at(element.to_string())}; + if (dependents.is_array()) { + for (const auto &dependent : dependents.as_array()) { + if (dependent.is_string()) { + match = true; + requirements.push_back(dependent); + } + } + + transformer.erase({"dependencies"}, element.to_string()); + } else if (dependents.is_string()) { + match = true; + requirements.push_back(dependents); + transformer.erase({"dependencies"}, element.to_string()); + } + } + + if (!match) { + break; + } + } + + transformer.assign("required", requirements); + } +}; diff --git a/vendor/alterschema/src/linter/simplify/dependent_required_tautology.h b/vendor/alterschema/src/linter/simplify/dependent_required_tautology.h new file mode 100644 index 00000000..a1d93075 --- /dev/null +++ b/vendor/alterschema/src/linter/simplify/dependent_required_tautology.h @@ -0,0 +1,63 @@ +class DependentRequiredTautology final : public Rule { +public: + DependentRequiredTautology() + : Rule{"dependent_required_tautology", + "Defining requirements for a property using `dependentRequired` " + "that is already marked as required is an unnecessarily complex " + "use of `dependentRequired`"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/validation", + "https://json-schema.org/draft/2019-09/vocab/validation"}) && + schema.is_object() && schema.defines("dependentRequired") && + schema.at("dependentRequired").is_object() && + schema.defines("required") && schema.at("required").is_array() && + std::any_of(schema.at("required").as_array().cbegin(), + schema.at("required").as_array().cend(), + [&schema](const auto &element) { + return element.is_string() && + schema.at("dependentRequired") + .defines(element.to_string()); + }); + } + + auto transform(Transformer &transformer) const -> void override { + auto requirements{transformer.schema().at("required")}; + while (true) { + bool match{false}; + const auto copy{requirements}; + for (const auto &element : copy.as_array()) { + if (!element.is_string() || !transformer.schema() + .at("dependentRequired") + .defines(element.to_string())) { + continue; + } + + const auto &dependents{transformer.schema() + .at("dependentRequired") + .at(element.to_string())}; + if (dependents.is_array()) { + for (const auto &dependent : dependents.as_array()) { + if (dependent.is_string()) { + match = true; + requirements.push_back(dependent); + } + } + + transformer.erase({"dependentRequired"}, element.to_string()); + } + } + + if (!match) { + break; + } + } + + transformer.assign("required", requirements); + } +}; diff --git a/vendor/alterschema/src/linter/simplify/equal_numeric_bounds_to_enum.h b/vendor/alterschema/src/linter/simplify/equal_numeric_bounds_to_enum.h new file mode 100644 index 00000000..f1f0a78f --- /dev/null +++ b/vendor/alterschema/src/linter/simplify/equal_numeric_bounds_to_enum.h @@ -0,0 +1,41 @@ +class EqualNumericBoundsToEnum final : public Rule { +public: + EqualNumericBoundsToEnum() + : Rule{"equal_numeric_bounds_to_enum", + "Setting `minimum` and `maximum` to the same number only leaves " + "one possible value"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/validation", + "https://json-schema.org/draft/2019-09/vocab/validation", + "http://json-schema.org/draft-07/schema#", + "http://json-schema.org/draft-06/schema#", + "http://json-schema.org/draft-04/schema#", + "http://json-schema.org/draft-03/schema#", + "http://json-schema.org/draft-02/hyper-schema#", + "http://json-schema.org/draft-01/hyper-schema#"}) && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + (schema.at("type").to_string() == "integer" || + schema.at("type").to_string() == "number") && + schema.defines("minimum") && schema.at("minimum").is_number() && + schema.defines("maximum") && schema.at("maximum").is_number() && + schema.at("minimum") == schema.at("maximum"); + } + + auto transform(sourcemeta::alterschema::Transformer &transformer) const + -> void override { + sourcemeta::jsontoolkit::JSON values = + sourcemeta::jsontoolkit::JSON::make_array(); + values.push_back(transformer.schema().at("minimum")); + transformer.assign("enum", std::move(values)); + transformer.erase("type"); + transformer.erase("minimum"); + transformer.erase("maximum"); + } +}; diff --git a/vendor/alterschema/src/linter/simplify/maximum_real_for_integer.h b/vendor/alterschema/src/linter/simplify/maximum_real_for_integer.h new file mode 100644 index 00000000..1c8cf32c --- /dev/null +++ b/vendor/alterschema/src/linter/simplify/maximum_real_for_integer.h @@ -0,0 +1,34 @@ +class MaximumRealForInteger final : public Rule { +public: + MaximumRealForInteger() + : Rule{"maximum_real_for_integer", + "If an instance is guaranteed to be an integer, setting a real " + "number upper bound is the same as a floor of that upper bound"} { + }; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/validation", + "https://json-schema.org/draft/2019-09/vocab/validation", + "http://json-schema.org/draft-07/schema#", + "http://json-schema.org/draft-06/schema#", + "http://json-schema.org/draft-04/schema#", + "http://json-schema.org/draft-03/schema#", + "http://json-schema.org/draft-02/hyper-schema#", + "http://json-schema.org/draft-01/hyper-schema#"}) && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "integer" && + schema.defines("maximum") && schema.at("maximum").is_real(); + } + + auto transform(Transformer &transformer) const -> void override { + const auto current{transformer.schema().at("maximum").to_real()}; + const auto new_value{static_cast(std::floor(current))}; + transformer.assign("maximum", sourcemeta::jsontoolkit::JSON{new_value}); + } +}; diff --git a/vendor/alterschema/src/linter/simplify/minimum_real_for_integer.h b/vendor/alterschema/src/linter/simplify/minimum_real_for_integer.h new file mode 100644 index 00000000..0c7c33d9 --- /dev/null +++ b/vendor/alterschema/src/linter/simplify/minimum_real_for_integer.h @@ -0,0 +1,33 @@ +class MinimumRealForInteger final : public Rule { +public: + MinimumRealForInteger() + : Rule{"minimum_real_for_integer", + "If an instance is guaranteed to be an integer, setting a real " + "number lower bound is the same as a ceil of that lower bound"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/validation", + "https://json-schema.org/draft/2019-09/vocab/validation", + "http://json-schema.org/draft-07/schema#", + "http://json-schema.org/draft-06/schema#", + "http://json-schema.org/draft-04/schema#", + "http://json-schema.org/draft-03/schema#", + "http://json-schema.org/draft-02/hyper-schema#", + "http://json-schema.org/draft-01/hyper-schema#"}) && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "integer" && + schema.defines("minimum") && schema.at("minimum").is_real(); + } + + auto transform(Transformer &transformer) const -> void override { + const auto current{transformer.schema().at("minimum").to_real()}; + const auto new_value{static_cast(std::ceil(current))}; + transformer.assign("minimum", sourcemeta::jsontoolkit::JSON{new_value}); + } +}; diff --git a/vendor/alterschema/src/linter/redundant/content_media_type_without_encoding.h b/vendor/alterschema/src/linter/superfluous/content_media_type_without_encoding.h similarity index 100% rename from vendor/alterschema/src/linter/redundant/content_media_type_without_encoding.h rename to vendor/alterschema/src/linter/superfluous/content_media_type_without_encoding.h diff --git a/vendor/alterschema/src/linter/redundant/content_schema_without_media_type.h b/vendor/alterschema/src/linter/superfluous/content_schema_without_media_type.h similarity index 100% rename from vendor/alterschema/src/linter/redundant/content_schema_without_media_type.h rename to vendor/alterschema/src/linter/superfluous/content_schema_without_media_type.h diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_applicator_2019_09.h b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_applicator_2019_09.h new file mode 100644 index 00000000..b243195d --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_applicator_2019_09.h @@ -0,0 +1,30 @@ +class DropNonArrayKeywordsApplicator_2019_09 final : public Rule { +public: + DropNonArrayKeywordsApplicator_2019_09() + : Rule{"drop_non_array_keywords_applicator_2019_09", + "Keywords that don't apply to arrays will never match if the " + "instance is guaranteed to be an array"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "array" && + vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/applicator") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "properties", "patternProperties", "additionalProperties", + "dependentSchemas", "propertyNames", "unevaluatedProperties"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_applicator_2020_12.h b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_applicator_2020_12.h new file mode 100644 index 00000000..05b08022 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_applicator_2020_12.h @@ -0,0 +1,30 @@ +class DropNonArrayKeywordsApplicator_2020_12 final : public Rule { +public: + DropNonArrayKeywordsApplicator_2020_12() + : Rule{"drop_non_array_keywords_applicator_2020_12", + "Keywords that don't apply to arrays will never match if the " + "instance is guaranteed to be an array"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "array" && + vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/applicator") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"properties", "patternProperties", + "additionalProperties", + "dependentSchemas", "propertyNames"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_content_2019_09.h b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_content_2019_09.h new file mode 100644 index 00000000..75fc7a21 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_content_2019_09.h @@ -0,0 +1,29 @@ +class DropNonArrayKeywordsContent_2019_09 final : public Rule { +public: + DropNonArrayKeywordsContent_2019_09() + : Rule{"drop_non_array_keywords_content_2019_09", + "Keywords that don't apply to arrays will never match if the " + "instance is guaranteed to be an array"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "array" && + vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/content") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"contentEncoding", "contentMediaType", + "contentSchema"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_content_2020_12.h b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_content_2020_12.h new file mode 100644 index 00000000..a2f82639 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_content_2020_12.h @@ -0,0 +1,29 @@ +class DropNonArrayKeywordsContent_2020_12 final : public Rule { +public: + DropNonArrayKeywordsContent_2020_12() + : Rule{"drop_non_array_keywords_content_2020_12", + "Keywords that don't apply to arrays will never match if the " + "instance is guaranteed to be an array"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "array" && + vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/content") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"contentEncoding", "contentMediaType", + "contentSchema"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_draft0.h b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_draft0.h new file mode 100644 index 00000000..98c74606 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_draft0.h @@ -0,0 +1,30 @@ +class DropNonArrayKeywords_Draft0 final : public Rule { +public: + DropNonArrayKeywords_Draft0() + : Rule{"drop_non_array_keywords_draft0", + "Keywords that don't apply to arrays will never match if the " + "instance is guaranteed to be an array"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "http://json-schema.org/draft-00/hyper-schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "array" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "maxDecimal", "maximum", "maximumCanEqual", "minimum", + "minimumCanEqual", "maxLength", "minLength", "pattern", + "requires", "optional", "properties", "additionalProperties", + "contentEncoding", "format"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_draft1.h b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_draft1.h new file mode 100644 index 00000000..a44e7101 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_draft1.h @@ -0,0 +1,30 @@ +class DropNonArrayKeywords_Draft1 final : public Rule { +public: + DropNonArrayKeywords_Draft1() + : Rule{"drop_non_array_keywords_draft1", + "Keywords that don't apply to arrays will never match if the " + "instance is guaranteed to be an array"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "http://json-schema.org/draft-01/hyper-schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "array" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "maxDecimal", "maximum", "maximumCanEqual", "minimum", + "minimumCanEqual", "maxLength", "minLength", "pattern", + "requires", "optional", "properties", "additionalProperties", + "contentEncoding", "format"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_draft2.h b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_draft2.h new file mode 100644 index 00000000..425b9f00 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_draft2.h @@ -0,0 +1,31 @@ +class DropNonArrayKeywords_Draft2 final : public Rule { +public: + DropNonArrayKeywords_Draft2() + : Rule{"drop_non_array_keywords_draft2", + "Keywords that don't apply to arrays will never match if the " + "instance is guaranteed to be an array"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "http://json-schema.org/draft-02/hyper-schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "array" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "properties", "optional", "additionalProperties", + "requires", "minimum", "maximum", + "minimumCanEqual", "maximumCanEqual", "pattern", + "maxLength", "minLength", "format", + "contentEncoding", "divisibleBy"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_draft3.h b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_draft3.h new file mode 100644 index 00000000..7599fe8a --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_draft3.h @@ -0,0 +1,30 @@ +class DropNonArrayKeywords_Draft3 final : public Rule { +public: + DropNonArrayKeywords_Draft3() + : Rule{"drop_non_array_keywords_draft3", + "Keywords that don't apply to arrays will never match if the " + "instance is guaranteed to be an array"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains("http://json-schema.org/draft-03/schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "array" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "properties", "patternProperties", "additionalProperties", + "required", "dependencies", "minimum", + "maximum", "exclusiveMinimum", "exclusiveMaximum", + "pattern", "minLength", "maxLength", + "format", "divisibleBy"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_draft4.h b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_draft4.h new file mode 100644 index 00000000..913a945b --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_draft4.h @@ -0,0 +1,33 @@ +class DropNonArrayKeywords_Draft4 final : public Rule { +public: + DropNonArrayKeywords_Draft4() + : Rule{"drop_non_array_keywords_draft4", + "Keywords that don't apply to arrays will never match if the " + "instance is guaranteed to be an array"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains("http://json-schema.org/draft-04/schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "array" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "multipleOf", "maximum", + "exclusiveMaximum", "minimum", + "exclusiveMinimum", "maxLength", + "minLength", "pattern", + "maxProperties", "minProperties", + "required", "properties", + "patternProperties", "additionalProperties", + "dependencies", "format"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_draft6.h b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_draft6.h new file mode 100644 index 00000000..5fc0ae4a --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_draft6.h @@ -0,0 +1,41 @@ +class DropNonArrayKeywords_Draft6 final : public Rule { +public: + DropNonArrayKeywords_Draft6() + : Rule{"drop_non_array_keywords_draft6", + "Keywords that don't apply to arrays will never match if the " + "instance is guaranteed to be an array"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains("http://json-schema.org/draft-06/schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "array" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"multipleOf", + "maximum", + "exclusiveMaximum", + "minimum", + "exclusiveMinimum", + "maxLength", + "minLength", + "pattern", + "maxProperties", + "minProperties", + "required", + "properties", + "patternProperties", + "additionalProperties", + "propertyNames", + "dependencies", + "format"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_draft7.h b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_draft7.h new file mode 100644 index 00000000..58c9dbda --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_draft7.h @@ -0,0 +1,43 @@ +class DropNonArrayKeywords_Draft7 final : public Rule { +public: + DropNonArrayKeywords_Draft7() + : Rule{"drop_non_array_keywords_draft7", + "Keywords that don't apply to arrays will never match if the " + "instance is guaranteed to be an array"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains("http://json-schema.org/draft-07/schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "array" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"multipleOf", + "maximum", + "exclusiveMaximum", + "minimum", + "exclusiveMinimum", + "maxLength", + "minLength", + "pattern", + "contentEncoding", + "contentMediaType", + "maxProperties", + "minProperties", + "required", + "properties", + "patternProperties", + "additionalProperties", + "propertyNames", + "dependencies", + "format"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_format_2019_09.h b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_format_2019_09.h new file mode 100644 index 00000000..92d34bb8 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_format_2019_09.h @@ -0,0 +1,28 @@ +class DropNonArrayKeywordsFormat_2019_09 final : public Rule { +public: + DropNonArrayKeywordsFormat_2019_09() + : Rule{"drop_non_array_keywords_format_2019_09", + "Keywords that don't apply to arrays will never match if the " + "instance is guaranteed to be an array"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "array" && + vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/format") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"format"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_format_2020_12.h b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_format_2020_12.h new file mode 100644 index 00000000..4aea0954 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_format_2020_12.h @@ -0,0 +1,30 @@ +class DropNonArrayKeywordsFormat_2020_12 final : public Rule { +public: + DropNonArrayKeywordsFormat_2020_12() + : Rule{"drop_non_array_keywords_format_2020_12", + "Keywords that don't apply to arrays will never match if the " + "instance is guaranteed to be an array"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "array" && + (vocabularies.contains("https://json-schema.org/draft/2020-12/vocab/" + "format-annotation") || + vocabularies.contains("https://json-schema.org/draft/2020-12/vocab/" + "format-assertion")) && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"format"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_unevaluated_2020_12.h b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_unevaluated_2020_12.h new file mode 100644 index 00000000..e3ae17ab --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_unevaluated_2020_12.h @@ -0,0 +1,28 @@ +class DropNonArrayKeywordsUnevaluated_2020_12 final : public Rule { +public: + DropNonArrayKeywordsUnevaluated_2020_12() + : Rule{"drop_non_array_keywords_unevaluated_2020_12", + "Keywords that don't apply to arrays will never match if the " + "instance is guaranteed to be an array"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "array" && + vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/unevaluated") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"unevaluatedProperties"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_validation_2019_09.h b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_validation_2019_09.h new file mode 100644 index 00000000..dcdcab1c --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_validation_2019_09.h @@ -0,0 +1,29 @@ +class DropNonArrayKeywordsValidation_2019_09 final : public Rule { +public: + DropNonArrayKeywordsValidation_2019_09() + : Rule{"drop_non_array_keywords_validation_2019_09", + "Keywords that don't apply to arrays will never match if the " + "instance is guaranteed to be an array"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "array" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "minLength", "maxLength", "pattern", "maximum", + "exclusiveMinimum", "multipleOf", "exclusiveMaximum", "minimum", + "dependentRequired", "minProperties", "maxProperties", "required"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_validation_2020_12.h b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_validation_2020_12.h new file mode 100644 index 00000000..58ecce51 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_array_keywords_validation_2020_12.h @@ -0,0 +1,29 @@ +class DropNonArrayKeywordsValidation_2020_12 final : public Rule { +public: + DropNonArrayKeywordsValidation_2020_12() + : Rule{"drop_non_array_keywords_validation_2020_12", + "Keywords that don't apply to arrays will never match if the " + "instance is guaranteed to be an array"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "array" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "minLength", "maxLength", "pattern", "maximum", + "exclusiveMinimum", "multipleOf", "exclusiveMaximum", "minimum", + "dependentRequired", "minProperties", "maxProperties", "required"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_applicator_2019_09.h b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_applicator_2019_09.h new file mode 100644 index 00000000..d26cb0f9 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_applicator_2019_09.h @@ -0,0 +1,39 @@ +class DropNonBooleanKeywordsApplicator_2019_09 final : public Rule { +public: + DropNonBooleanKeywordsApplicator_2019_09() + : Rule{"drop_non_boolean_keywords_applicator_2019_09", + "Keywords that don't apply to booleans will never match if the " + "instance is guaranteed to be a boolean"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/validation") && + schema.is_object() && + ((schema.defines("type") && schema.at("type").is_string() && + schema.at("type").to_string() == "boolean") || + (schema.defines("enum") && schema.at("enum").is_array() && + every_item_is_boolean(schema.at("enum").as_array()))) && + vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/applicator") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"properties", + "patternProperties", + "additionalProperties", + "dependentSchemas", + "propertyNames", + "additionalItems", + "contains", + "items", + "unevaluatedProperties", + "unevaluatedItems"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_applicator_2020_12.h b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_applicator_2020_12.h new file mode 100644 index 00000000..ae03d392 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_applicator_2020_12.h @@ -0,0 +1,37 @@ +class DropNonBooleanKeywordsApplicator_2020_12 final : public Rule { +public: + DropNonBooleanKeywordsApplicator_2020_12() + : Rule{"drop_non_boolean_keywords_applicator_2020_12", + "Keywords that don't apply to booleans will never match if the " + "instance is guaranteed to be a boolean"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.is_object() && + ((schema.defines("type") && schema.at("type").is_string() && + schema.at("type").to_string() == "boolean") || + (schema.defines("enum") && schema.at("enum").is_array() && + every_item_is_boolean(schema.at("enum").as_array()))) && + vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/applicator") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"properties", + "patternProperties", + "additionalProperties", + "dependentSchemas", + "propertyNames", + "prefixItems", + "contains", + "items"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_content_2019_09.h b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_content_2019_09.h new file mode 100644 index 00000000..33fe367a --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_content_2019_09.h @@ -0,0 +1,31 @@ +class DropNonBooleanKeywordsContent_2019_09 final : public Rule { +public: + DropNonBooleanKeywordsContent_2019_09() + : Rule{"drop_non_boolean_keywords_content_2019_09", + "Keywords that don't apply to booleans will never match if the " + "instance is guaranteed to be a boolean"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/validation") && + schema.is_object() && + ((schema.defines("type") && schema.at("type").is_string() && + schema.at("type").to_string() == "boolean") || + (schema.defines("enum") && schema.at("enum").is_array() && + every_item_is_boolean(schema.at("enum").as_array()))) && + vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/content") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"contentEncoding", "contentMediaType", + "contentSchema"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_content_2020_12.h b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_content_2020_12.h new file mode 100644 index 00000000..bf1b98f4 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_content_2020_12.h @@ -0,0 +1,31 @@ +class DropNonBooleanKeywordsContent_2020_12 final : public Rule { +public: + DropNonBooleanKeywordsContent_2020_12() + : Rule{"drop_non_boolean_keywords_content_2020_12", + "Keywords that don't apply to booleans will never match if the " + "instance is guaranteed to be a boolean"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.is_object() && + ((schema.defines("type") && schema.at("type").is_string() && + schema.at("type").to_string() == "boolean") || + (schema.defines("enum") && schema.at("enum").is_array() && + every_item_is_boolean(schema.at("enum").as_array()))) && + vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/content") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"contentEncoding", "contentMediaType", + "contentSchema"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_draft0.h b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_draft0.h new file mode 100644 index 00000000..91323ddb --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_draft0.h @@ -0,0 +1,30 @@ +class DropNonBooleanKeywords_Draft0 final : public Rule { +public: + DropNonBooleanKeywords_Draft0() + : Rule{"drop_non_boolean_keywords_draft0", + "Keywords that don't apply to booleans will never match if the " + "instance is guaranteed to be a boolean"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "http://json-schema.org/draft-00/hyper-schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "boolean" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "properties", "items", "optional", "additionalProperties", + "requires", "minimum", "maximum", "minimumCanEqual", + "maximumCanEqual", "minItems", "maxItems", "maxLength", + "minLength", "format", "contentEncoding", "maxDecimal"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_draft1.h b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_draft1.h new file mode 100644 index 00000000..e9a88483 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_draft1.h @@ -0,0 +1,30 @@ +class DropNonBooleanKeywords_Draft1 final : public Rule { +public: + DropNonBooleanKeywords_Draft1() + : Rule{"drop_non_boolean_keywords_draft1", + "Keywords that don't apply to booleans will never match if the " + "instance is guaranteed to be a boolean"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "http://json-schema.org/draft-01/hyper-schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "boolean" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "properties", "items", "optional", "additionalProperties", + "requires", "minimum", "maximum", "minimumCanEqual", + "maximumCanEqual", "minItems", "maxItems", "maxLength", + "minLength", "format", "contentEncoding", "maxDecimal"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_draft2.h b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_draft2.h new file mode 100644 index 00000000..09f1a277 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_draft2.h @@ -0,0 +1,31 @@ +class DropNonBooleanKeywords_Draft2 final : public Rule { +public: + DropNonBooleanKeywords_Draft2() + : Rule{"drop_non_boolean_keywords_draft2", + "Keywords that don't apply to booleans will never match if the " + "instance is guaranteed to be a boolean"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "http://json-schema.org/draft-02/hyper-schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "boolean" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "properties", "items", "optional", "additionalProperties", + "requires", "minimum", "maximum", "minimumCanEqual", + "maximumCanEqual", "minItems", "maxItems", "uniqueItems", + "pattern", "maxLength", "minLength", "format", + "contentEncoding", "divisibleBy"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_draft3.h b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_draft3.h new file mode 100644 index 00000000..97a78774 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_draft3.h @@ -0,0 +1,43 @@ +class DropNonBooleanKeywords_Draft3 final : public Rule { +public: + DropNonBooleanKeywords_Draft3() + : Rule{"drop_non_boolean_keywords_draft3", + "Keywords that don't apply to booleans will never match if the " + "instance is guaranteed to be a boolean"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains("http://json-schema.org/draft-03/schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "boolean" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"properties", + "patternProperties", + "additionalProperties", + "items", + "additionalItems", + "required", + "dependencies", + "minimum", + "maximum", + "exclusiveMinimum", + "exclusiveMaximum", + "minItems", + "maxItems", + "uniqueItems", + "pattern", + "minLength", + "maxLength", + "format", + "divisibleBy"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_draft4.h b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_draft4.h new file mode 100644 index 00000000..6840ec55 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_draft4.h @@ -0,0 +1,45 @@ +class DropNonBooleanKeywords_Draft4 final : public Rule { +public: + DropNonBooleanKeywords_Draft4() + : Rule{"drop_non_boolean_keywords_draft4", + "Keywords that don't apply to booleans will never match if the " + "instance is guaranteed to be a boolean"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains("http://json-schema.org/draft-04/schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "boolean" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"multipleOf", + "maximum", + "exclusiveMaximum", + "minimum", + "exclusiveMinimum", + "maxLength", + "minLength", + "pattern", + "additionalItems", + "items", + "maxItems", + "minItems", + "uniqueItems", + "maxProperties", + "minProperties", + "required", + "properties", + "patternProperties", + "additionalProperties", + "dependencies", + "format"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_draft6.h b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_draft6.h new file mode 100644 index 00000000..94de1115 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_draft6.h @@ -0,0 +1,47 @@ +class DropNonBooleanKeywords_Draft6 final : public Rule { +public: + DropNonBooleanKeywords_Draft6() + : Rule{"drop_non_boolean_keywords_draft6", + "Keywords that don't apply to booleans will never match if the " + "instance is guaranteed to be a boolean"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains("http://json-schema.org/draft-06/schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "boolean" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"multipleOf", + "maximum", + "exclusiveMaximum", + "minimum", + "exclusiveMinimum", + "maxLength", + "minLength", + "pattern", + "additionalItems", + "items", + "contains", + "maxItems", + "minItems", + "uniqueItems", + "maxProperties", + "minProperties", + "required", + "properties", + "patternProperties", + "additionalProperties", + "propertyNames", + "dependencies", + "format"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_draft7.h b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_draft7.h new file mode 100644 index 00000000..c66f5502 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_draft7.h @@ -0,0 +1,49 @@ +class DropNonBooleanKeywords_Draft7 final : public Rule { +public: + DropNonBooleanKeywords_Draft7() + : Rule{"drop_non_boolean_keywords_draft7", + "Keywords that don't apply to booleans will never match if the " + "instance is guaranteed to be a boolean"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains("http://json-schema.org/draft-07/schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "boolean" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"multipleOf", + "maximum", + "exclusiveMaximum", + "minimum", + "exclusiveMinimum", + "maxLength", + "minLength", + "pattern", + "contentEncoding", + "contentMediaType", + "additionalItems", + "items", + "contains", + "maxItems", + "minItems", + "uniqueItems", + "maxProperties", + "minProperties", + "required", + "properties", + "patternProperties", + "additionalProperties", + "propertyNames", + "dependencies", + "format"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_format_2019_09.h b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_format_2019_09.h new file mode 100644 index 00000000..3e1d6814 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_format_2019_09.h @@ -0,0 +1,30 @@ +class DropNonBooleanKeywordsFormat_2019_09 final : public Rule { +public: + DropNonBooleanKeywordsFormat_2019_09() + : Rule{"drop_non_boolean_keywords_format_2019_09", + "Keywords that don't apply to booleans will never match if the " + "instance is guaranteed to be a boolean"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/validation") && + schema.is_object() && + ((schema.defines("type") && schema.at("type").is_string() && + schema.at("type").to_string() == "boolean") || + (schema.defines("enum") && schema.at("enum").is_array() && + every_item_is_boolean(schema.at("enum").as_array()))) && + vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/format") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"format"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_format_2020_12.h b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_format_2020_12.h new file mode 100644 index 00000000..fc938145 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_format_2020_12.h @@ -0,0 +1,32 @@ +class DropNonBooleanKeywordsFormat_2020_12 final : public Rule { +public: + DropNonBooleanKeywordsFormat_2020_12() + : Rule{"drop_non_boolean_keywords_format_2020_12", + "Keywords that don't apply to booleans will never match if the " + "instance is guaranteed to be a boolean"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.is_object() && + ((schema.defines("type") && schema.at("type").is_string() && + schema.at("type").to_string() == "boolean") || + (schema.defines("enum") && schema.at("enum").is_array() && + every_item_is_boolean(schema.at("enum").as_array()))) && + (vocabularies.contains("https://json-schema.org/draft/2020-12/vocab/" + "format-annotation") || + vocabularies.contains("https://json-schema.org/draft/2020-12/vocab/" + "format-assertion")) && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"format"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_unevaluated_2020_12.h b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_unevaluated_2020_12.h new file mode 100644 index 00000000..a2e2b3ab --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_unevaluated_2020_12.h @@ -0,0 +1,31 @@ +class DropNonBooleanKeywordsUnevaluated_2020_12 final : public Rule { +public: + DropNonBooleanKeywordsUnevaluated_2020_12() + : Rule{"drop_non_boolean_keywords_unevaluated_2020_12", + "Keywords that don't apply to booleans will never match if the " + "instance is guaranteed to be a boolean"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.is_object() && + ((schema.defines("type") && schema.at("type").is_string() && + schema.at("type").to_string() == "boolean") || + (schema.defines("enum") && schema.at("enum").is_array() && + every_item_is_boolean(schema.at("enum").as_array()))) && + vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/unevaluated") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"unevaluatedItems", + "unevaluatedProperties"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_validation_2019_09.h b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_validation_2019_09.h new file mode 100644 index 00000000..072b8e88 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_validation_2019_09.h @@ -0,0 +1,35 @@ +class DropNonBooleanKeywordsValidation_2019_09 final : public Rule { +public: + DropNonBooleanKeywordsValidation_2019_09() + : Rule{"drop_non_boolean_keywords_validation_2019_09", + "Keywords that don't apply to booleans will never match if the " + "instance is guaranteed to be a boolean"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/validation") && + schema.is_object() && + ((schema.defines("type") && schema.at("type").is_string() && + schema.at("type").to_string() == "boolean") || + (schema.defines("enum") && schema.at("enum").is_array() && + every_item_is_boolean(schema.at("enum").as_array()))) && + vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/validation") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "minLength", "maxLength", "pattern", "maximum", + "exclusiveMinimum", "multipleOf", "exclusiveMaximum", "minimum", + "dependentRequired", "minProperties", "maxProperties", "required", + "minItems", "maxItems", "minContains", "maxContains", + "uniqueItems"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_validation_2020_12.h b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_validation_2020_12.h new file mode 100644 index 00000000..e3d5b81b --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_boolean_keywords_validation_2020_12.h @@ -0,0 +1,35 @@ +class DropNonBooleanKeywordsValidation_2020_12 final : public Rule { +public: + DropNonBooleanKeywordsValidation_2020_12() + : Rule{"drop_non_boolean_keywords_validation_2020_12", + "Keywords that don't apply to booleans will never match if the " + "instance is guaranteed to be a boolean"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.is_object() && + ((schema.defines("type") && schema.at("type").is_string() && + schema.at("type").to_string() == "boolean") || + (schema.defines("enum") && schema.at("enum").is_array() && + every_item_is_boolean(schema.at("enum").as_array()))) && + vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "minLength", "maxLength", "pattern", "maximum", + "exclusiveMinimum", "multipleOf", "exclusiveMaximum", "minimum", + "dependentRequired", "minProperties", "maxProperties", "required", + "minItems", "maxItems", "minContains", "maxContains", + "uniqueItems"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_applicator_2019_09.h b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_applicator_2019_09.h new file mode 100644 index 00000000..b6279f44 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_applicator_2019_09.h @@ -0,0 +1,39 @@ +class DropNonNullKeywordsApplicator_2019_09 final : public Rule { +public: + DropNonNullKeywordsApplicator_2019_09() + : Rule{"drop_non_null_keywords_applicator_2019_09", + "Keywords that don't apply to null values will never match if the " + "instance is guaranteed to be null"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/validation") && + schema.is_object() && + ((schema.defines("type") && schema.at("type").is_string() && + schema.at("type").to_string() == "null") || + (schema.defines("enum") && schema.at("enum").is_array() && + every_item_is_null(schema.at("enum").as_array()))) && + vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/applicator") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"properties", + "patternProperties", + "additionalProperties", + "dependentSchemas", + "propertyNames", + "additionalItems", + "contains", + "items", + "unevaluatedProperties", + "unevaluatedItems"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_applicator_2020_12.h b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_applicator_2020_12.h new file mode 100644 index 00000000..f6958e0d --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_applicator_2020_12.h @@ -0,0 +1,37 @@ +class DropNonNullKeywordsApplicator_2020_12 final : public Rule { +public: + DropNonNullKeywordsApplicator_2020_12() + : Rule{"drop_non_null_keywords_applicator_2020_12", + "Keywords that don't apply to null values will never match if the " + "instance is guaranteed to be null"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.is_object() && + ((schema.defines("type") && schema.at("type").is_string() && + schema.at("type").to_string() == "null") || + (schema.defines("enum") && schema.at("enum").is_array() && + every_item_is_null(schema.at("enum").as_array()))) && + vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/applicator") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"properties", + "patternProperties", + "additionalProperties", + "dependentSchemas", + "propertyNames", + "prefixItems", + "contains", + "items"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_content_2019_09.h b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_content_2019_09.h new file mode 100644 index 00000000..9343c036 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_content_2019_09.h @@ -0,0 +1,31 @@ +class DropNonNullKeywordsContent_2019_09 final : public Rule { +public: + DropNonNullKeywordsContent_2019_09() + : Rule{"drop_non_null_keywords_content_2019_09", + "Keywords that don't apply to null values will never match if the " + "instance is guaranteed to be null"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/validation") && + schema.is_object() && + ((schema.defines("type") && schema.at("type").is_string() && + schema.at("type").to_string() == "null") || + (schema.defines("enum") && schema.at("enum").is_array() && + every_item_is_null(schema.at("enum").as_array()))) && + vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/content") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"contentEncoding", "contentMediaType", + "contentSchema"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_content_2020_12.h b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_content_2020_12.h new file mode 100644 index 00000000..61538b19 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_content_2020_12.h @@ -0,0 +1,31 @@ +class DropNonNullKeywordsContent_2020_12 final : public Rule { +public: + DropNonNullKeywordsContent_2020_12() + : Rule{"drop_non_null_keywords_content_2020_12", + "Keywords that don't apply to null values will never match if the " + "instance is guaranteed to be null"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.is_object() && + ((schema.defines("type") && schema.at("type").is_string() && + schema.at("type").to_string() == "null") || + (schema.defines("enum") && schema.at("enum").is_array() && + every_item_is_null(schema.at("enum").as_array()))) && + vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/content") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"contentEncoding", "contentMediaType", + "contentSchema"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_draft0.h b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_draft0.h new file mode 100644 index 00000000..366d193a --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_draft0.h @@ -0,0 +1,30 @@ +class DropNonNullKeywords_Draft0 final : public Rule { +public: + DropNonNullKeywords_Draft0() + : Rule{"drop_non_null_keywords_draft0", + "Keywords that don't apply to null values will never match if the " + "instance is guaranteed to be null"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "http://json-schema.org/draft-00/hyper-schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "null" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "properties", "items", "optional", "additionalProperties", + "requires", "minimum", "maximum", "minimumCanEqual", + "maximumCanEqual", "minItems", "maxItems", "maxLength", + "minLength", "format", "contentEncoding", "maxDecimal"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_draft1.h b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_draft1.h new file mode 100644 index 00000000..8b2a85d2 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_draft1.h @@ -0,0 +1,30 @@ +class DropNonNullKeywords_Draft1 final : public Rule { +public: + DropNonNullKeywords_Draft1() + : Rule{"drop_non_null_keywords_draft1", + "Keywords that don't apply to null values will never match if the " + "instance is guaranteed to be null"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "http://json-schema.org/draft-01/hyper-schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "null" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "properties", "items", "optional", "additionalProperties", + "requires", "minimum", "maximum", "minimumCanEqual", + "maximumCanEqual", "minItems", "maxItems", "maxLength", + "minLength", "format", "contentEncoding", "maxDecimal"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_draft2.h b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_draft2.h new file mode 100644 index 00000000..f06acf88 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_draft2.h @@ -0,0 +1,31 @@ +class DropNonNullKeywords_Draft2 final : public Rule { +public: + DropNonNullKeywords_Draft2() + : Rule{"drop_non_null_keywords_draft2", + "Keywords that don't apply to null values will never match if the " + "instance is guaranteed to be null"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "http://json-schema.org/draft-02/hyper-schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "null" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "properties", "items", "optional", "additionalProperties", + "requires", "minimum", "maximum", "minimumCanEqual", + "maximumCanEqual", "minItems", "maxItems", "uniqueItems", + "pattern", "maxLength", "minLength", "format", + "contentEncoding", "divisibleBy"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_draft3.h b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_draft3.h new file mode 100644 index 00000000..ffb36cfb --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_draft3.h @@ -0,0 +1,43 @@ +class DropNonNullKeywords_Draft3 final : public Rule { +public: + DropNonNullKeywords_Draft3() + : Rule{"drop_non_null_keywords_draft3", + "Keywords that don't apply to null values will never match if the " + "instance is guaranteed to be null"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains("http://json-schema.org/draft-03/schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "null" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"properties", + "patternProperties", + "additionalProperties", + "items", + "additionalItems", + "required", + "dependencies", + "minimum", + "maximum", + "exclusiveMinimum", + "exclusiveMaximum", + "minItems", + "maxItems", + "uniqueItems", + "pattern", + "minLength", + "maxLength", + "format", + "divisibleBy"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_draft4.h b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_draft4.h new file mode 100644 index 00000000..8aed21e0 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_draft4.h @@ -0,0 +1,45 @@ +class DropNonNullKeywords_Draft4 final : public Rule { +public: + DropNonNullKeywords_Draft4() + : Rule{"drop_non_null_keywords_draft4", + "Keywords that don't apply to null values will never match if the " + "instance is guaranteed to be null"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains("http://json-schema.org/draft-04/schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "null" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"multipleOf", + "maximum", + "exclusiveMaximum", + "minimum", + "exclusiveMinimum", + "maxLength", + "minLength", + "pattern", + "additionalItems", + "items", + "maxItems", + "minItems", + "uniqueItems", + "maxProperties", + "minProperties", + "required", + "properties", + "patternProperties", + "additionalProperties", + "dependencies", + "format"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_draft6.h b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_draft6.h new file mode 100644 index 00000000..2be83a88 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_draft6.h @@ -0,0 +1,47 @@ +class DropNonNullKeywords_Draft6 final : public Rule { +public: + DropNonNullKeywords_Draft6() + : Rule{"drop_non_null_keywords_draft6", + "Keywords that don't apply to null values will never match if the " + "instance is guaranteed to be null"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains("http://json-schema.org/draft-06/schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "null" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"multipleOf", + "maximum", + "exclusiveMaximum", + "minimum", + "exclusiveMinimum", + "maxLength", + "minLength", + "pattern", + "additionalItems", + "items", + "contains", + "maxItems", + "minItems", + "uniqueItems", + "maxProperties", + "minProperties", + "required", + "properties", + "patternProperties", + "additionalProperties", + "propertyNames", + "dependencies", + "format"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_draft7.h b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_draft7.h new file mode 100644 index 00000000..a025d450 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_draft7.h @@ -0,0 +1,49 @@ +class DropNonNullKeywords_Draft7 final : public Rule { +public: + DropNonNullKeywords_Draft7() + : Rule{"drop_non_null_keywords_draft7", + "Keywords that don't apply to null values will never match if the " + "instance is guaranteed to be null"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains("http://json-schema.org/draft-07/schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "null" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"multipleOf", + "maximum", + "exclusiveMaximum", + "minimum", + "exclusiveMinimum", + "maxLength", + "minLength", + "pattern", + "contentEncoding", + "contentMediaType", + "additionalItems", + "items", + "contains", + "maxItems", + "minItems", + "uniqueItems", + "maxProperties", + "minProperties", + "required", + "properties", + "patternProperties", + "additionalProperties", + "propertyNames", + "dependencies", + "format"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_format_2019_09.h b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_format_2019_09.h new file mode 100644 index 00000000..28592fca --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_format_2019_09.h @@ -0,0 +1,30 @@ +class DropNonNullKeywordsFormat_2019_09 final : public Rule { +public: + DropNonNullKeywordsFormat_2019_09() + : Rule{"drop_non_null_keywords_format_2019_09", + "Keywords that don't apply to null values will never match if the " + "instance is guaranteed to be null"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/validation") && + schema.is_object() && + ((schema.defines("type") && schema.at("type").is_string() && + schema.at("type").to_string() == "null") || + (schema.defines("enum") && schema.at("enum").is_array() && + every_item_is_null(schema.at("enum").as_array()))) && + vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/format") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"format"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_format_2020_12.h b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_format_2020_12.h new file mode 100644 index 00000000..de26f8d1 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_format_2020_12.h @@ -0,0 +1,32 @@ +class DropNonNullKeywordsFormat_2020_12 final : public Rule { +public: + DropNonNullKeywordsFormat_2020_12() + : Rule{"drop_non_null_keywords_format_2020_12", + "Keywords that don't apply to null values will never match if the " + "instance is guaranteed to be null"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.is_object() && + ((schema.defines("type") && schema.at("type").is_string() && + schema.at("type").to_string() == "null") || + (schema.defines("enum") && schema.at("enum").is_array() && + every_item_is_null(schema.at("enum").as_array()))) && + (vocabularies.contains("https://json-schema.org/draft/2020-12/vocab/" + "format-annotation") || + vocabularies.contains("https://json-schema.org/draft/2020-12/vocab/" + "format-assertion")) && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"format"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_unevaluated_2020_12.h b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_unevaluated_2020_12.h new file mode 100644 index 00000000..de425389 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_unevaluated_2020_12.h @@ -0,0 +1,31 @@ +class DropNonNullKeywordsUnevaluated_2020_12 final : public Rule { +public: + DropNonNullKeywordsUnevaluated_2020_12() + : Rule{"drop_non_null_keywords_unevaluated_2020_12", + "Keywords that don't apply to null values will never match if the " + "instance is guaranteed to be null"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.is_object() && + ((schema.defines("type") && schema.at("type").is_string() && + schema.at("type").to_string() == "null") || + (schema.defines("enum") && schema.at("enum").is_array() && + every_item_is_null(schema.at("enum").as_array()))) && + vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/unevaluated") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"unevaluatedItems", + "unevaluatedProperties"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_validation_2019_09.h b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_validation_2019_09.h new file mode 100644 index 00000000..b35331f7 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_validation_2019_09.h @@ -0,0 +1,35 @@ +class DropNonNullKeywordsValidation_2019_09 final : public Rule { +public: + DropNonNullKeywordsValidation_2019_09() + : Rule{"drop_non_null_keywords_validation_2019_09", + "Keywords that don't apply to null values will never match if the " + "instance is guaranteed to be null"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/validation") && + schema.is_object() && + ((schema.defines("type") && schema.at("type").is_string() && + schema.at("type").to_string() == "null") || + (schema.defines("enum") && schema.at("enum").is_array() && + every_item_is_null(schema.at("enum").as_array()))) && + vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/validation") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "minLength", "maxLength", "pattern", "maximum", + "exclusiveMinimum", "multipleOf", "exclusiveMaximum", "minimum", + "dependentRequired", "minProperties", "maxProperties", "required", + "minItems", "maxItems", "minContains", "maxContains", + "uniqueItems"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_validation_2020_12.h b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_validation_2020_12.h new file mode 100644 index 00000000..be528a4c --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_null_keywords_validation_2020_12.h @@ -0,0 +1,35 @@ +class DropNonNullKeywordsValidation_2020_12 final : public Rule { +public: + DropNonNullKeywordsValidation_2020_12() + : Rule{"drop_non_null_keywords_validation_2020_12", + "Keywords that don't apply to null values will never match if the " + "instance is guaranteed to be null"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.is_object() && + ((schema.defines("type") && schema.at("type").is_string() && + schema.at("type").to_string() == "null") || + (schema.defines("enum") && schema.at("enum").is_array() && + every_item_is_null(schema.at("enum").as_array()))) && + vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "minLength", "maxLength", "pattern", "maximum", + "exclusiveMinimum", "multipleOf", "exclusiveMaximum", "minimum", + "dependentRequired", "minProperties", "maxProperties", "required", + "minItems", "maxItems", "minContains", "maxContains", + "uniqueItems"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_applicator_2019_09.h b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_applicator_2019_09.h new file mode 100644 index 00000000..6827d611 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_applicator_2019_09.h @@ -0,0 +1,38 @@ +class DropNonNumericKeywordsApplicator_2019_09 final : public Rule { +public: + DropNonNumericKeywordsApplicator_2019_09() + : Rule{"drop_non_numeric_keywords_applicator_2019_09", + "Keywords that don't apply to numbers will never match if the " + "instance is guaranteed to be a number"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + (schema.at("type").to_string() == "integer" || + schema.at("type").to_string() == "number") && + vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/applicator") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"properties", + "patternProperties", + "additionalProperties", + "dependentSchemas", + "propertyNames", + "additionalItems", + "contains", + "items", + "unevaluatedProperties", + "unevaluatedItems"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_applicator_2020_12.h b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_applicator_2020_12.h new file mode 100644 index 00000000..e475d118 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_applicator_2020_12.h @@ -0,0 +1,36 @@ +class DropNonNumericKeywordsApplicator_2020_12 final : public Rule { +public: + DropNonNumericKeywordsApplicator_2020_12() + : Rule{"drop_non_numeric_keywords_applicator_2020_12", + "Keywords that don't apply to numbers will never match if the " + "instance is guaranteed to be a number"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + (schema.at("type").to_string() == "integer" || + schema.at("type").to_string() == "number") && + vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/applicator") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"properties", + "patternProperties", + "additionalProperties", + "dependentSchemas", + "propertyNames", + "prefixItems", + "contains", + "items"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_content_2019_09.h b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_content_2019_09.h new file mode 100644 index 00000000..db6bac22 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_content_2019_09.h @@ -0,0 +1,30 @@ +class DropNonNumericKeywordsContent_2019_09 final : public Rule { +public: + DropNonNumericKeywordsContent_2019_09() + : Rule{"drop_non_numeric_keywords_content_2019_09", + "Keywords that don't apply to numbers will never match if the " + "instance is guaranteed to be a number"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + (schema.at("type").to_string() == "integer" || + schema.at("type").to_string() == "number") && + vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/content") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"contentEncoding", "contentMediaType", + "contentSchema"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_content_2020_12.h b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_content_2020_12.h new file mode 100644 index 00000000..40f01943 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_content_2020_12.h @@ -0,0 +1,30 @@ +class DropNonNumericKeywordsContent_2020_12 final : public Rule { +public: + DropNonNumericKeywordsContent_2020_12() + : Rule{"drop_non_numeric_keywords_content_2020_12", + "Keywords that don't apply to numbers will never match if the " + "instance is guaranteed to be a number"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + (schema.at("type").to_string() == "integer" || + schema.at("type").to_string() == "number") && + vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/content") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"contentEncoding", "contentMediaType", + "contentSchema"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_draft0.h b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_draft0.h new file mode 100644 index 00000000..b8ac5461 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_draft0.h @@ -0,0 +1,30 @@ +class DropNonNumericKeywords_Draft0 final : public Rule { +public: + DropNonNumericKeywords_Draft0() + : Rule{"drop_non_numeric_keywords_draft0", + "Keywords that don't apply to numbers will never match if the " + "instance is guaranteed to be a number"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "http://json-schema.org/draft-00/hyper-schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + (schema.at("type").to_string() == "number" || + schema.at("type").to_string() == "integer") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "properties", "items", "optional", "additionalProperties", + "requires", "minItems", "maxItems", "maxLength", + "minLength", "format", "contentEncoding"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_draft1.h b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_draft1.h new file mode 100644 index 00000000..f27f5849 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_draft1.h @@ -0,0 +1,30 @@ +class DropNonNumericKeywords_Draft1 final : public Rule { +public: + DropNonNumericKeywords_Draft1() + : Rule{"drop_non_numeric_keywords_draft1", + "Keywords that don't apply to numbers will never match if the " + "instance is guaranteed to be a number"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "http://json-schema.org/draft-01/hyper-schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + (schema.at("type").to_string() == "number" || + schema.at("type").to_string() == "integer") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "properties", "items", "optional", "additionalProperties", + "requires", "minItems", "maxItems", "maxLength", + "minLength", "format", "contentEncoding"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_draft2.h b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_draft2.h new file mode 100644 index 00000000..4b14b7b4 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_draft2.h @@ -0,0 +1,31 @@ +class DropNonNumericKeywords_Draft2 final : public Rule { +public: + DropNonNumericKeywords_Draft2() + : Rule{"drop_non_numeric_keywords_draft2", + "Keywords that don't apply to numbers will never match if the " + "instance is guaranteed to be a number"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "http://json-schema.org/draft-02/hyper-schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + (schema.at("type").to_string() == "number" || + schema.at("type").to_string() == "integer") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "properties", "items", "optional", "additionalProperties", + "requires", "minItems", "maxItems", "uniqueItems", + "pattern", "maxLength", "minLength", "format", + "contentEncoding"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_draft3.h b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_draft3.h new file mode 100644 index 00000000..82e02ca3 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_draft3.h @@ -0,0 +1,39 @@ +class DropNonNumericKeywords_Draft3 final : public Rule { +public: + DropNonNumericKeywords_Draft3() + : Rule{"drop_non_numeric_keywords_draft3", + "Keywords that don't apply to numbers will never match if the " + "instance is guaranteed to be a number"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains("http://json-schema.org/draft-03/schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + (schema.at("type").to_string() == "number" || + schema.at("type").to_string() == "integer") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"properties", + "patternProperties", + "additionalProperties", + "items", + "additionalItems", + "required", + "dependencies", + "minItems", + "maxItems", + "uniqueItems", + "pattern", + "minLength", + "maxLength", + "format"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_draft4.h b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_draft4.h new file mode 100644 index 00000000..10b0bfd2 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_draft4.h @@ -0,0 +1,41 @@ +class DropNonNumericKeywords_Draft4 final : public Rule { +public: + DropNonNumericKeywords_Draft4() + : Rule{"drop_non_numeric_keywords_draft4", + "Keywords that don't apply to numbers will never match if the " + "instance is guaranteed to be a number"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains("http://json-schema.org/draft-04/schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + (schema.at("type").to_string() == "number" || + schema.at("type").to_string() == "integer") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"maxLength", + "minLength", + "pattern", + "additionalItems", + "items", + "maxItems", + "minItems", + "uniqueItems", + "maxProperties", + "minProperties", + "required", + "properties", + "patternProperties", + "additionalProperties", + "dependencies", + "format"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_draft6.h b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_draft6.h new file mode 100644 index 00000000..6fc50293 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_draft6.h @@ -0,0 +1,43 @@ +class DropNonNumericKeywords_Draft6 final : public Rule { +public: + DropNonNumericKeywords_Draft6() + : Rule{"drop_non_numeric_keywords_draft6", + "Keywords that don't apply to numbers will never match if the " + "instance is guaranteed to be a number"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains("http://json-schema.org/draft-06/schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + (schema.at("type").to_string() == "number" || + schema.at("type").to_string() == "integer") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"maxLength", + "minLength", + "pattern", + "additionalItems", + "items", + "contains", + "maxItems", + "minItems", + "uniqueItems", + "maxProperties", + "minProperties", + "required", + "properties", + "patternProperties", + "additionalProperties", + "propertyNames", + "dependencies", + "format"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_draft7.h b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_draft7.h new file mode 100644 index 00000000..befe1741 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_draft7.h @@ -0,0 +1,45 @@ +class DropNonNumericKeywords_Draft7 final : public Rule { +public: + DropNonNumericKeywords_Draft7() + : Rule{"drop_non_numeric_keywords_draft7", + "Keywords that don't apply to numbers will never match if the " + "instance is guaranteed to be a number"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains("http://json-schema.org/draft-07/schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + (schema.at("type").to_string() == "number" || + schema.at("type").to_string() == "integer") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"maxLength", + "minLength", + "pattern", + "contentEncoding", + "contentMediaType", + "additionalItems", + "items", + "contains", + "maxItems", + "minItems", + "uniqueItems", + "maxProperties", + "minProperties", + "required", + "properties", + "patternProperties", + "additionalProperties", + "propertyNames", + "dependencies", + "format"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_format_2019_09.h b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_format_2019_09.h new file mode 100644 index 00000000..1dc81458 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_format_2019_09.h @@ -0,0 +1,29 @@ +class DropNonNumericKeywordsFormat_2019_09 final : public Rule { +public: + DropNonNumericKeywordsFormat_2019_09() + : Rule{"drop_non_numeric_keywords_format_2019_09", + "Keywords that don't apply to numbers will never match if the " + "instance is guaranteed to be a number"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + (schema.at("type").to_string() == "integer" || + schema.at("type").to_string() == "number") && + vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/format") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"format"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_format_2020_12.h b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_format_2020_12.h new file mode 100644 index 00000000..1fbe3433 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_format_2020_12.h @@ -0,0 +1,31 @@ +class DropNonNumericKeywordsFormat_2020_12 final : public Rule { +public: + DropNonNumericKeywordsFormat_2020_12() + : Rule{"drop_non_numeric_keywords_format_2020_12", + "Keywords that don't apply to numbers will never match if the " + "instance is guaranteed to be a number"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + (schema.at("type").to_string() == "integer" || + schema.at("type").to_string() == "number") && + (vocabularies.contains("https://json-schema.org/draft/2020-12/vocab/" + "format-annotation") || + vocabularies.contains("https://json-schema.org/draft/2020-12/vocab/" + "format-assertion")) && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"format"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_unevaluated_2020_12.h b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_unevaluated_2020_12.h new file mode 100644 index 00000000..919ff864 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_unevaluated_2020_12.h @@ -0,0 +1,30 @@ +class DropNonNumericKeywordsUnevaluated_2020_12 final : public Rule { +public: + DropNonNumericKeywordsUnevaluated_2020_12() + : Rule{"drop_non_numeric_keywords_unevaluated_2020_12", + "Keywords that don't apply to numbers will never match if the " + "instance is guaranteed to be a number"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + (schema.at("type").to_string() == "integer" || + schema.at("type").to_string() == "number") && + vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/unevaluated") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"unevaluatedItems", + "unevaluatedProperties"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_validation_2019_09.h b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_validation_2019_09.h new file mode 100644 index 00000000..7d6f186e --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_validation_2019_09.h @@ -0,0 +1,30 @@ +class DropNonNumericKeywordsValidation_2019_09 final : public Rule { +public: + DropNonNumericKeywordsValidation_2019_09() + : Rule{"drop_non_numeric_keywords_validation_2019_09", + "Keywords that don't apply to numbers will never match if the " + "instance is guaranteed to be a number"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + (schema.at("type").to_string() == "integer" || + schema.at("type").to_string() == "number") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "minLength", "maxLength", "pattern", "dependentRequired", + "minProperties", "maxProperties", "required", "minItems", + "maxItems", "minContains", "maxContains", "uniqueItems"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_validation_2020_12.h b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_validation_2020_12.h new file mode 100644 index 00000000..c74e72b7 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_numeric_keywords_validation_2020_12.h @@ -0,0 +1,30 @@ +class DropNonNumericKeywordsValidation_2020_12 final : public Rule { +public: + DropNonNumericKeywordsValidation_2020_12() + : Rule{"drop_non_numeric_keywords_validation_2020_12", + "Keywords that don't apply to numbers will never match if the " + "instance is guaranteed to be a number"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + (schema.at("type").to_string() == "integer" || + schema.at("type").to_string() == "number") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "minLength", "maxLength", "pattern", "dependentRequired", + "minProperties", "maxProperties", "required", "minItems", + "maxItems", "minContains", "maxContains", "uniqueItems"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_applicator_2019_09.h b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_applicator_2019_09.h new file mode 100644 index 00000000..59e255ec --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_applicator_2019_09.h @@ -0,0 +1,29 @@ +class DropNonObjectKeywordsApplicator_2019_09 final : public Rule { +public: + DropNonObjectKeywordsApplicator_2019_09() + : Rule{"drop_non_object_keywords_applicator_2019_09", + "Keywords that don't apply to objects will never match if the " + "instance is guaranteed to be an object"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "object" && + vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/applicator") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"additionalItems", "contains", "items", + "unevaluatedItems"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_applicator_2020_12.h b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_applicator_2020_12.h new file mode 100644 index 00000000..212d009c --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_applicator_2020_12.h @@ -0,0 +1,28 @@ +class DropNonObjectKeywordsApplicator_2020_12 final : public Rule { +public: + DropNonObjectKeywordsApplicator_2020_12() + : Rule{"drop_non_object_keywords_applicator_2020_12", + "Keywords that don't apply to objects will never match if the " + "instance is guaranteed to be an object"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "object" && + vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/applicator") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"prefixItems", "contains", "items"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_content_2019_09.h b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_content_2019_09.h new file mode 100644 index 00000000..eb73b34e --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_content_2019_09.h @@ -0,0 +1,29 @@ +class DropNonObjectKeywordsContent_2019_09 final : public Rule { +public: + DropNonObjectKeywordsContent_2019_09() + : Rule{"drop_non_object_keywords_content_2019_09", + "Keywords that don't apply to objects will never match if the " + "instance is guaranteed to be an object"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "object" && + vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/content") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"contentEncoding", "contentMediaType", + "contentSchema"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_content_2020_12.h b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_content_2020_12.h new file mode 100644 index 00000000..70d24855 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_content_2020_12.h @@ -0,0 +1,29 @@ +class DropNonObjectKeywordsContent_2020_12 final : public Rule { +public: + DropNonObjectKeywordsContent_2020_12() + : Rule{"drop_non_object_keywords_content_2020_12", + "Keywords that don't apply to objects will never match if the " + "instance is guaranteed to be an object"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "object" && + vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/content") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"contentEncoding", "contentMediaType", + "contentSchema"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_draft0.h b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_draft0.h new file mode 100644 index 00000000..67f4e467 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_draft0.h @@ -0,0 +1,29 @@ +class DropNonObjectKeywords_Draft0 final : public Rule { +public: + DropNonObjectKeywords_Draft0() + : Rule{"drop_non_object_keywords_draft0", + "Keywords that don't apply to objects will never match if the " + "instance is guaranteed to be an object"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "http://json-schema.org/draft-00/hyper-schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "object" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "items", "minimum", "maximum", "minimumCanEqual", + "maximumCanEqual", "minItems", "maxItems", "maxLength", + "minLength", "format", "contentEncoding", "maxDecimal"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_draft1.h b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_draft1.h new file mode 100644 index 00000000..56e84caf --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_draft1.h @@ -0,0 +1,29 @@ +class DropNonObjectKeywords_Draft1 final : public Rule { +public: + DropNonObjectKeywords_Draft1() + : Rule{"drop_non_object_keywords_draft1", + "Keywords that don't apply to objects will never match if the " + "instance is guaranteed to be an object"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "http://json-schema.org/draft-01/hyper-schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "object" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "items", "minimum", "maximum", "minimumCanEqual", + "maximumCanEqual", "minItems", "maxItems", "maxLength", + "minLength", "format", "contentEncoding", "maxDecimal"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_draft2.h b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_draft2.h new file mode 100644 index 00000000..0c21be20 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_draft2.h @@ -0,0 +1,29 @@ +class DropNonObjectKeywords_Draft2 final : public Rule { +public: + DropNonObjectKeywords_Draft2() + : Rule{"drop_non_object_keywords_draft2", + "Keywords that don't apply to objects will never match if the " + "instance is guaranteed to be an object"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "http://json-schema.org/draft-02/hyper-schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "object" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "items", "minimum", "maximum", "minimumCanEqual", + "maximumCanEqual", "minItems", "maxItems", "maxLength", + "minLength", "format", "contentEncoding", "maxDecimal"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_draft3.h b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_draft3.h new file mode 100644 index 00000000..d33ecb31 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_draft3.h @@ -0,0 +1,29 @@ +class DropNonObjectKeywords_Draft3 final : public Rule { +public: + DropNonObjectKeywords_Draft3() + : Rule{"drop_non_object_keywords_draft3", + "Keywords that don't apply to objects will never match if the " + "instance is guaranteed to be an object"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains("http://json-schema.org/draft-03/schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "object" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "items", "additionalItems", "required", "minimum", + "maximum", "exclusiveMinimum", "exclusiveMaximum", "minItems", + "maxItems", "uniqueItems", "pattern", "minLength", + "maxLength", "format", "divisibleBy"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_draft4.h b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_draft4.h new file mode 100644 index 00000000..55ecaeac --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_draft4.h @@ -0,0 +1,29 @@ +class DropNonObjectKeywords_Draft4 final : public Rule { +public: + DropNonObjectKeywords_Draft4() + : Rule{"drop_non_object_keywords_draft4", + "Keywords that don't apply to objects will never match if the " + "instance is guaranteed to be an object"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains("http://json-schema.org/draft-04/schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "object" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "multipleOf", "maximum", "exclusiveMaximum", "minimum", + "exclusiveMinimum", "maxLength", "minLength", "pattern", + "additionalItems", "items", "maxItems", "minItems", + "uniqueItems", "format"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_draft6.h b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_draft6.h new file mode 100644 index 00000000..22942ef4 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_draft6.h @@ -0,0 +1,30 @@ +class DropNonObjectKeywords_Draft6 final : public Rule { +public: + DropNonObjectKeywords_Draft6() + : Rule{"drop_non_object_keywords_draft6", + "Keywords that don't apply to objects will never match if the " + "instance is guaranteed to be an object"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains("http://json-schema.org/draft-06/schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "object" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "multipleOf", "maximum", "exclusiveMaximum", + "minimum", "exclusiveMinimum", "maxLength", + "minLength", "pattern", "additionalItems", + "items", "contains", "maxItems", + "minItems", "uniqueItems", "format"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_draft7.h b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_draft7.h new file mode 100644 index 00000000..3e0db712 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_draft7.h @@ -0,0 +1,41 @@ +class DropNonObjectKeywords_Draft7 final : public Rule { +public: + DropNonObjectKeywords_Draft7() + : Rule{"drop_non_object_keywords_draft7", + "Keywords that don't apply to objects will never match if the " + "instance is guaranteed to be an object"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains("http://json-schema.org/draft-07/schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "object" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"multipleOf", + "maximum", + "exclusiveMaximum", + "minimum", + "exclusiveMinimum", + "maxLength", + "minLength", + "pattern", + "contentEncoding", + "contentMediaType", + "additionalItems", + "items", + "contains", + "maxItems", + "minItems", + "uniqueItems", + "format"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_format_2019_09.h b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_format_2019_09.h new file mode 100644 index 00000000..3ac69735 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_format_2019_09.h @@ -0,0 +1,28 @@ +class DropNonObjectKeywordsFormat_2019_09 final : public Rule { +public: + DropNonObjectKeywordsFormat_2019_09() + : Rule{"drop_non_object_keywords_format_2019_09", + "Keywords that don't apply to objects will never match if the " + "instance is guaranteed to be an object"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "object" && + vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/format") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"format"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_format_2020_12.h b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_format_2020_12.h new file mode 100644 index 00000000..8ab84ed6 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_format_2020_12.h @@ -0,0 +1,30 @@ +class DropNonObjectKeywordsFormat_2020_12 final : public Rule { +public: + DropNonObjectKeywordsFormat_2020_12() + : Rule{"drop_non_object_keywords_format_2020_12", + "Keywords that don't apply to objects will never match if the " + "instance is guaranteed to be an object"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "object" && + (vocabularies.contains("https://json-schema.org/draft/2020-12/vocab/" + "format-annotation") || + vocabularies.contains("https://json-schema.org/draft/2020-12/vocab/" + "format-assertion")) && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"format"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_unevaluated_2020_12.h b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_unevaluated_2020_12.h new file mode 100644 index 00000000..a4861255 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_unevaluated_2020_12.h @@ -0,0 +1,28 @@ +class DropNonObjectKeywordsUnevaluated_2020_12 final : public Rule { +public: + DropNonObjectKeywordsUnevaluated_2020_12() + : Rule{"drop_non_object_keywords_unevaluated_2020_12", + "Keywords that don't apply to objects will never match if the " + "instance is guaranteed to be an object"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "object" && + vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/unevaluated") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"unevaluatedItems"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_validation_2019_09.h b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_validation_2019_09.h new file mode 100644 index 00000000..d41cff03 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_validation_2019_09.h @@ -0,0 +1,30 @@ +class DropNonObjectKeywordsValidation_2019_09 final : public Rule { +public: + DropNonObjectKeywordsValidation_2019_09() + : Rule{"drop_non_object_keywords_validation_2019_09", + "Keywords that don't apply to objects will never match if the " + "instance is guaranteed to be an object"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "object" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "minLength", "maxLength", "pattern", "maximum", + "exclusiveMinimum", "multipleOf", "exclusiveMaximum", "minimum", + "minItems", "maxItems", "minContains", "maxContains", + "uniqueItems"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_validation_2020_12.h b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_validation_2020_12.h new file mode 100644 index 00000000..90dc4961 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_object_keywords_validation_2020_12.h @@ -0,0 +1,30 @@ +class DropNonObjectKeywordsValidation_2020_12 final : public Rule { +public: + DropNonObjectKeywordsValidation_2020_12() + : Rule{"drop_non_object_keywords_validation_2020_12", + "Keywords that don't apply to objects will never match if the " + "instance is guaranteed to be an object"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "object" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "minLength", "maxLength", "pattern", "maximum", + "exclusiveMinimum", "multipleOf", "exclusiveMaximum", "minimum", + "minItems", "maxItems", "minContains", "maxContains", + "uniqueItems"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_applicator_2019_09.h b/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_applicator_2019_09.h new file mode 100644 index 00000000..71337836 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_applicator_2019_09.h @@ -0,0 +1,37 @@ +class DropNonStringKeywordsApplicator_2019_09 final : public Rule { +public: + DropNonStringKeywordsApplicator_2019_09() + : Rule{"drop_non_string_keywords_applicator_2019_09", + "Keywords that don't apply to strings will never match if the " + "instance is guaranteed to be a string"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "string" && + vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/applicator") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"properties", + "patternProperties", + "additionalProperties", + "dependentSchemas", + "propertyNames", + "additionalItems", + "contains", + "items", + "unevaluatedProperties", + "unevaluatedItems"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_applicator_2020_12.h b/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_applicator_2020_12.h new file mode 100644 index 00000000..0f6c4e71 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_applicator_2020_12.h @@ -0,0 +1,35 @@ +class DropNonStringKeywordsApplicator_2020_12 final : public Rule { +public: + DropNonStringKeywordsApplicator_2020_12() + : Rule{"drop_non_string_keywords_applicator_2020_12", + "Keywords that don't apply to strings will never match if the " + "instance is guaranteed to be a string"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "string" && + vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/applicator") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"properties", + "patternProperties", + "additionalProperties", + "dependentSchemas", + "propertyNames", + "prefixItems", + "contains", + "items"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_draft0.h b/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_draft0.h new file mode 100644 index 00000000..db7309e4 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_draft0.h @@ -0,0 +1,29 @@ +class DropNonStringKeywords_Draft0 final : public Rule { +public: + DropNonStringKeywords_Draft0() + : Rule{"drop_non_string_keywords_draft0", + "Keywords that don't apply to strings will never match if the " + "instance is guaranteed to be a string"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "http://json-schema.org/draft-00/hyper-schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "string" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "properties", "items", "optional", "additionalProperties", + "requires", "minimum", "maximum", "minimumCanEqual", + "maximumCanEqual", "minItems", "maxItems", "maxDecimal"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_draft1.h b/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_draft1.h new file mode 100644 index 00000000..d8099ee3 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_draft1.h @@ -0,0 +1,29 @@ +class DropNonStringKeywords_Draft1 final : public Rule { +public: + DropNonStringKeywords_Draft1() + : Rule{"drop_non_string_keywords_draft1", + "Keywords that don't apply to strings will never match if the " + "instance is guaranteed to be a string"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "http://json-schema.org/draft-01/hyper-schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "string" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "properties", "items", "optional", "additionalProperties", + "requires", "minimum", "maximum", "minimumCanEqual", + "maximumCanEqual", "minItems", "maxItems", "maxDecimal"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_draft2.h b/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_draft2.h new file mode 100644 index 00000000..7b85ec25 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_draft2.h @@ -0,0 +1,30 @@ +class DropNonStringKeywords_Draft2 final : public Rule { +public: + DropNonStringKeywords_Draft2() + : Rule{"drop_non_string_keywords_draft2", + "Keywords that don't apply to strings will never match if the " + "instance is guaranteed to be a string"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "http://json-schema.org/draft-02/hyper-schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "string" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "properties", "items", "optional", "additionalProperties", + "requires", "minimum", "maximum", "minimumCanEqual", + "maximumCanEqual", "minItems", "maxItems", "uniqueItems", + "divisibleBy"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_draft3.h b/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_draft3.h new file mode 100644 index 00000000..16b33761 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_draft3.h @@ -0,0 +1,39 @@ +class DropNonStringKeywords_Draft3 final : public Rule { +public: + DropNonStringKeywords_Draft3() + : Rule{"drop_non_string_keywords_draft3", + "Keywords that don't apply to strings will never match if the " + "instance is guaranteed to be a string"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains("http://json-schema.org/draft-03/schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "string" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"properties", + "patternProperties", + "additionalProperties", + "items", + "additionalItems", + "required", + "dependencies", + "minimum", + "maximum", + "exclusiveMinimum", + "exclusiveMaximum", + "minItems", + "maxItems", + "uniqueItems", + "divisibleBy"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_draft4.h b/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_draft4.h new file mode 100644 index 00000000..aacd47be --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_draft4.h @@ -0,0 +1,41 @@ +class DropNonStringKeywords_Draft4 final : public Rule { +public: + DropNonStringKeywords_Draft4() + : Rule{"drop_non_string_keywords_draft4", + "Keywords that don't apply to strings will never match if the " + "instance is guaranteed to be a string"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains("http://json-schema.org/draft-04/schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "string" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"multipleOf", + "maximum", + "exclusiveMaximum", + "minimum", + "exclusiveMinimum", + "additionalItems", + "items", + "maxItems", + "minItems", + "uniqueItems", + "maxProperties", + "minProperties", + "required", + "properties", + "patternProperties", + "additionalProperties", + "dependencies"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_draft6.h b/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_draft6.h new file mode 100644 index 00000000..e3e9f036 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_draft6.h @@ -0,0 +1,43 @@ +class DropNonStringKeywords_Draft6 final : public Rule { +public: + DropNonStringKeywords_Draft6() + : Rule{"drop_non_string_keywords_draft6", + "Keywords that don't apply to strings will never match if the " + "instance is guaranteed to be a string"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains("http://json-schema.org/draft-06/schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "string" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"multipleOf", + "maximum", + "exclusiveMaximum", + "minimum", + "exclusiveMinimum", + "additionalItems", + "items", + "contains", + "maxItems", + "minItems", + "uniqueItems", + "maxProperties", + "minProperties", + "required", + "properties", + "patternProperties", + "additionalProperties", + "propertyNames", + "dependencies"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_draft7.h b/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_draft7.h new file mode 100644 index 00000000..5eff1fc2 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_draft7.h @@ -0,0 +1,43 @@ +class DropNonStringKeywords_Draft7 final : public Rule { +public: + DropNonStringKeywords_Draft7() + : Rule{"drop_non_string_keywords_draft7", + "Keywords that don't apply to strings will never match if the " + "instance is guaranteed to be a string"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains("http://json-schema.org/draft-07/schema#") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "string" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"multipleOf", + "maximum", + "exclusiveMaximum", + "minimum", + "exclusiveMinimum", + "additionalItems", + "items", + "contains", + "maxItems", + "minItems", + "uniqueItems", + "maxProperties", + "minProperties", + "required", + "properties", + "patternProperties", + "additionalProperties", + "propertyNames", + "dependencies"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_unevaluated_2020_12.h b/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_unevaluated_2020_12.h new file mode 100644 index 00000000..2d7495f5 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_unevaluated_2020_12.h @@ -0,0 +1,29 @@ +class DropNonStringKeywordsUnevaluated_2020_12 final : public Rule { +public: + DropNonStringKeywordsUnevaluated_2020_12() + : Rule{"drop_non_string_keywords_unevaluated_2020_12", + "Keywords that don't apply to strings will never match if the " + "instance is guaranteed to be a string"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "string" && + vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/unevaluated") && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{"unevaluatedItems", + "unevaluatedProperties"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_validation_2019_09.h b/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_validation_2019_09.h new file mode 100644 index 00000000..0d69e75a --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_validation_2019_09.h @@ -0,0 +1,30 @@ +class DropNonStringKeywordsValidation_2019_09 final : public Rule { +public: + DropNonStringKeywordsValidation_2019_09() + : Rule{"drop_non_string_keywords_validation_2019_09", + "Keywords that don't apply to strings will never match if the " + "instance is guaranteed to be a string"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2019-09/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "string" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "maximum", "exclusiveMinimum", "multipleOf", "exclusiveMaximum", + "minimum", "dependentRequired", "minProperties", "maxProperties", + "required", "minItems", "maxItems", "minContains", + "maxContains", "uniqueItems"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_validation_2020_12.h b/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_validation_2020_12.h new file mode 100644 index 00000000..1caa459e --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/drop_non_string_keywords_validation_2020_12.h @@ -0,0 +1,30 @@ +class DropNonStringKeywordsValidation_2020_12 final : public Rule { +public: + DropNonStringKeywordsValidation_2020_12() + : Rule{"drop_non_string_keywords_validation_2020_12", + "Keywords that don't apply to strings will never match if the " + "instance is guaranteed to be a string"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return vocabularies.contains( + "https://json-schema.org/draft/2020-12/vocab/validation") && + schema.is_object() && schema.defines("type") && + schema.at("type").is_string() && + schema.at("type").to_string() == "string" && + schema.defines_any(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase_keys(this->BLACKLIST.cbegin(), this->BLACKLIST.cend()); + } + +private: + const std::set BLACKLIST{ + "maximum", "exclusiveMinimum", "multipleOf", "exclusiveMaximum", + "minimum", "dependentRequired", "minProperties", "maxProperties", + "required", "minItems", "maxItems", "minContains", + "maxContains", "uniqueItems"}; +}; diff --git a/vendor/alterschema/src/linter/superfluous/duplicate_allof_branches.h b/vendor/alterschema/src/linter/superfluous/duplicate_allof_branches.h new file mode 100644 index 00000000..66a82a8a --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/duplicate_allof_branches.h @@ -0,0 +1,33 @@ +class DuplicateAllOfBranches final : public Rule { +public: + DuplicateAllOfBranches() + : Rule{"duplicate_allof_branches", + "Setting duplicate subschemas in `allOf` is redundant, as it " + "produces " + "unnecessary additional validation that is guaranteed to not " + "affect the validation result"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/applicator", + "https://json-schema.org/draft/2019-09/vocab/applicator", + "http://json-schema.org/draft-07/schema#", + "http://json-schema.org/draft-06/schema#", + "http://json-schema.org/draft-04/schema#"}) && + schema.is_object() && schema.defines("allOf") && + schema.at("allOf").is_array() && !schema.at("allOf").unique(); + } + + auto transform(Transformer &transformer) const -> void override { + auto collection = transformer.schema().at("allOf"); + std::sort(collection.as_array().begin(), collection.as_array().end()); + auto last = + std::unique(collection.as_array().begin(), collection.as_array().end()); + collection.erase(last, collection.as_array().end()); + transformer.replace({"allOf"}, std::move(collection)); + } +}; diff --git a/vendor/alterschema/src/linter/superfluous/duplicate_anyof_branches.h b/vendor/alterschema/src/linter/superfluous/duplicate_anyof_branches.h new file mode 100644 index 00000000..c9b9a54b --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/duplicate_anyof_branches.h @@ -0,0 +1,33 @@ +class DuplicateAnyOfBranches final : public Rule { +public: + DuplicateAnyOfBranches() + : Rule{"duplicate_anyof_branches", + "Setting duplicate subschemas in `anyOf` is redundant, as it " + "produces " + "unnecessary additional validation that is guaranteed to not " + "affect the validation result"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/applicator", + "https://json-schema.org/draft/2019-09/vocab/applicator", + "http://json-schema.org/draft-07/schema#", + "http://json-schema.org/draft-06/schema#", + "http://json-schema.org/draft-04/schema#"}) && + schema.is_object() && schema.defines("anyOf") && + schema.at("anyOf").is_array() && !schema.at("anyOf").unique(); + } + + auto transform(Transformer &transformer) const -> void override { + auto collection = transformer.schema().at("anyOf"); + std::sort(collection.as_array().begin(), collection.as_array().end()); + auto last = + std::unique(collection.as_array().begin(), collection.as_array().end()); + collection.erase(last, collection.as_array().end()); + transformer.replace({"anyOf"}, std::move(collection)); + } +}; diff --git a/vendor/alterschema/src/linter/redundant/else_without_if.h b/vendor/alterschema/src/linter/superfluous/else_without_if.h similarity index 100% rename from vendor/alterschema/src/linter/redundant/else_without_if.h rename to vendor/alterschema/src/linter/superfluous/else_without_if.h diff --git a/vendor/alterschema/src/linter/superfluous/if_without_then_else.h b/vendor/alterschema/src/linter/superfluous/if_without_then_else.h new file mode 100644 index 00000000..5a9735a3 --- /dev/null +++ b/vendor/alterschema/src/linter/superfluous/if_without_then_else.h @@ -0,0 +1,24 @@ +class IfWithoutThenElse final : public Rule { +public: + IfWithoutThenElse() + : Rule{"if_without_then_else", + "The `if` keyword is meaningless " + "without the presence of the `then` or `else` keywords"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/applicator", + "https://json-schema.org/draft/2019-09/vocab/applicator", + "http://json-schema.org/draft-07/schema#"}) && + schema.is_object() && schema.defines("if") && + !schema.defines("then") && !schema.defines("else"); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase("if"); + } +}; diff --git a/vendor/alterschema/src/linter/redundant/max_contains_without_contains.h b/vendor/alterschema/src/linter/superfluous/max_contains_without_contains.h similarity index 100% rename from vendor/alterschema/src/linter/redundant/max_contains_without_contains.h rename to vendor/alterschema/src/linter/superfluous/max_contains_without_contains.h diff --git a/vendor/alterschema/src/linter/redundant/min_contains_without_contains.h b/vendor/alterschema/src/linter/superfluous/min_contains_without_contains.h similarity index 100% rename from vendor/alterschema/src/linter/redundant/min_contains_without_contains.h rename to vendor/alterschema/src/linter/superfluous/min_contains_without_contains.h diff --git a/vendor/alterschema/src/linter/redundant/then_without_if.h b/vendor/alterschema/src/linter/superfluous/then_without_if.h similarity index 100% rename from vendor/alterschema/src/linter/redundant/then_without_if.h rename to vendor/alterschema/src/linter/superfluous/then_without_if.h diff --git a/vendor/alterschema/src/linter/modernize/enum_to_const.h b/vendor/alterschema/src/linter/syntax_sugar/enum_to_const.h similarity index 100% rename from vendor/alterschema/src/linter/modernize/enum_to_const.h rename to vendor/alterschema/src/linter/syntax_sugar/enum_to_const.h