Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add redundancy rules for keyword that won't apply to given types #211

Merged
merged 2 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions src/linter/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,98 @@ noa_library(NAMESPACE sourcemeta PROJECT alterschema NAME linter
redundant/content_media_type_without_encoding.h
redundant/content_schema_default.h
redundant/content_schema_without_media_type.h
redundant/drop_non_array_keywords_applicator_2019_09.h
redundant/drop_non_array_keywords_applicator_2020_12.h
redundant/drop_non_array_keywords_content_2019_09.h
redundant/drop_non_array_keywords_content_2020_12.h
redundant/drop_non_array_keywords_draft0.h
redundant/drop_non_array_keywords_draft1.h
redundant/drop_non_array_keywords_draft2.h
redundant/drop_non_array_keywords_draft3.h
redundant/drop_non_array_keywords_draft4.h
redundant/drop_non_array_keywords_draft6.h
redundant/drop_non_array_keywords_draft7.h
redundant/drop_non_array_keywords_format_2019_09.h
redundant/drop_non_array_keywords_format_2020_12.h
redundant/drop_non_array_keywords_unevaluated_2020_12.h
redundant/drop_non_array_keywords_validation_2019_09.h
redundant/drop_non_array_keywords_validation_2020_12.h
redundant/drop_non_boolean_keywords_applicator_2019_09.h
redundant/drop_non_boolean_keywords_applicator_2020_12.h
redundant/drop_non_boolean_keywords_content_2019_09.h
redundant/drop_non_boolean_keywords_content_2020_12.h
redundant/drop_non_boolean_keywords_draft0.h
redundant/drop_non_boolean_keywords_draft1.h
redundant/drop_non_boolean_keywords_draft2.h
redundant/drop_non_boolean_keywords_draft3.h
redundant/drop_non_boolean_keywords_draft4.h
redundant/drop_non_boolean_keywords_draft6.h
redundant/drop_non_boolean_keywords_draft7.h
redundant/drop_non_boolean_keywords_format_2019_09.h
redundant/drop_non_boolean_keywords_format_2020_12.h
redundant/drop_non_boolean_keywords_unevaluated_2020_12.h
redundant/drop_non_boolean_keywords_validation_2019_09.h
redundant/drop_non_boolean_keywords_validation_2020_12.h
redundant/drop_non_null_keywords_applicator_2019_09.h
redundant/drop_non_null_keywords_applicator_2020_12.h
redundant/drop_non_null_keywords_content_2019_09.h
redundant/drop_non_null_keywords_content_2020_12.h
redundant/drop_non_null_keywords_draft0.h
redundant/drop_non_null_keywords_draft1.h
redundant/drop_non_null_keywords_draft2.h
redundant/drop_non_null_keywords_draft3.h
redundant/drop_non_null_keywords_draft4.h
redundant/drop_non_null_keywords_draft6.h
redundant/drop_non_null_keywords_draft7.h
redundant/drop_non_null_keywords_format_2019_09.h
redundant/drop_non_null_keywords_format_2020_12.h
redundant/drop_non_null_keywords_unevaluated_2020_12.h
redundant/drop_non_null_keywords_validation_2019_09.h
redundant/drop_non_null_keywords_validation_2020_12.h
redundant/drop_non_numeric_keywords_applicator_2019_09.h
redundant/drop_non_numeric_keywords_applicator_2020_12.h
redundant/drop_non_numeric_keywords_content_2019_09.h
redundant/drop_non_numeric_keywords_content_2020_12.h
redundant/drop_non_numeric_keywords_draft0.h
redundant/drop_non_numeric_keywords_draft1.h
redundant/drop_non_numeric_keywords_draft2.h
redundant/drop_non_numeric_keywords_draft3.h
redundant/drop_non_numeric_keywords_draft4.h
redundant/drop_non_numeric_keywords_draft6.h
redundant/drop_non_numeric_keywords_draft7.h
redundant/drop_non_numeric_keywords_format_2019_09.h
redundant/drop_non_numeric_keywords_format_2020_12.h
redundant/drop_non_numeric_keywords_unevaluated_2020_12.h
redundant/drop_non_numeric_keywords_validation_2019_09.h
redundant/drop_non_numeric_keywords_validation_2020_12.h
redundant/drop_non_object_keywords_applicator_2019_09.h
redundant/drop_non_object_keywords_applicator_2020_12.h
redundant/drop_non_object_keywords_content_2019_09.h
redundant/drop_non_object_keywords_content_2020_12.h
redundant/drop_non_object_keywords_draft0.h
redundant/drop_non_object_keywords_draft1.h
redundant/drop_non_object_keywords_draft2.h
redundant/drop_non_object_keywords_draft3.h
redundant/drop_non_object_keywords_draft4.h
redundant/drop_non_object_keywords_draft6.h
redundant/drop_non_object_keywords_draft7.h
redundant/drop_non_object_keywords_format_2019_09.h
redundant/drop_non_object_keywords_format_2020_12.h
redundant/drop_non_object_keywords_unevaluated_2020_12.h
redundant/drop_non_object_keywords_validation_2019_09.h
redundant/drop_non_object_keywords_validation_2020_12.h
redundant/drop_non_string_keywords_applicator_2019_09.h
redundant/drop_non_string_keywords_applicator_2020_12.h
redundant/drop_non_string_keywords_draft0.h
redundant/drop_non_string_keywords_draft1.h
redundant/drop_non_string_keywords_draft2.h
redundant/drop_non_string_keywords_draft3.h
redundant/drop_non_string_keywords_draft4.h
redundant/drop_non_string_keywords_draft6.h
redundant/drop_non_string_keywords_draft7.h
redundant/drop_non_string_keywords_unevaluated_2020_12.h
redundant/drop_non_string_keywords_validation_2019_09.h
redundant/drop_non_string_keywords_validation_2020_12.h
redundant/duplicate_allof_branches.h
redundant/duplicate_anyof_branches.h
redundant/else_without_if.h
Expand Down
194 changes: 194 additions & 0 deletions src/linter/linter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ auto contains_any(const T &container, const T &values) -> bool {
[&values](const auto &element) { return values.contains(element); });
}

template <typename T> 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 <typename T> 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(); });
}

// Modernize
#include "modernize/enum_to_const.h"
// AntiPattern
Expand All @@ -34,6 +44,98 @@ auto contains_any(const T &container, const T &values) -> bool {
#include "redundant/content_media_type_without_encoding.h"
#include "redundant/content_schema_default.h"
#include "redundant/content_schema_without_media_type.h"
#include "redundant/drop_non_array_keywords_applicator_2019_09.h"
#include "redundant/drop_non_array_keywords_applicator_2020_12.h"
#include "redundant/drop_non_array_keywords_content_2019_09.h"
#include "redundant/drop_non_array_keywords_content_2020_12.h"
#include "redundant/drop_non_array_keywords_draft0.h"
#include "redundant/drop_non_array_keywords_draft1.h"
#include "redundant/drop_non_array_keywords_draft2.h"
#include "redundant/drop_non_array_keywords_draft3.h"
#include "redundant/drop_non_array_keywords_draft4.h"
#include "redundant/drop_non_array_keywords_draft6.h"
#include "redundant/drop_non_array_keywords_draft7.h"
#include "redundant/drop_non_array_keywords_format_2019_09.h"
#include "redundant/drop_non_array_keywords_format_2020_12.h"
#include "redundant/drop_non_array_keywords_unevaluated_2020_12.h"
#include "redundant/drop_non_array_keywords_validation_2019_09.h"
#include "redundant/drop_non_array_keywords_validation_2020_12.h"
#include "redundant/drop_non_boolean_keywords_applicator_2019_09.h"
#include "redundant/drop_non_boolean_keywords_applicator_2020_12.h"
#include "redundant/drop_non_boolean_keywords_content_2019_09.h"
#include "redundant/drop_non_boolean_keywords_content_2020_12.h"
#include "redundant/drop_non_boolean_keywords_draft0.h"
#include "redundant/drop_non_boolean_keywords_draft1.h"
#include "redundant/drop_non_boolean_keywords_draft2.h"
#include "redundant/drop_non_boolean_keywords_draft3.h"
#include "redundant/drop_non_boolean_keywords_draft4.h"
#include "redundant/drop_non_boolean_keywords_draft6.h"
#include "redundant/drop_non_boolean_keywords_draft7.h"
#include "redundant/drop_non_boolean_keywords_format_2019_09.h"
#include "redundant/drop_non_boolean_keywords_format_2020_12.h"
#include "redundant/drop_non_boolean_keywords_unevaluated_2020_12.h"
#include "redundant/drop_non_boolean_keywords_validation_2019_09.h"
#include "redundant/drop_non_boolean_keywords_validation_2020_12.h"
#include "redundant/drop_non_null_keywords_applicator_2019_09.h"
#include "redundant/drop_non_null_keywords_applicator_2020_12.h"
#include "redundant/drop_non_null_keywords_content_2019_09.h"
#include "redundant/drop_non_null_keywords_content_2020_12.h"
#include "redundant/drop_non_null_keywords_draft0.h"
#include "redundant/drop_non_null_keywords_draft1.h"
#include "redundant/drop_non_null_keywords_draft2.h"
#include "redundant/drop_non_null_keywords_draft3.h"
#include "redundant/drop_non_null_keywords_draft4.h"
#include "redundant/drop_non_null_keywords_draft6.h"
#include "redundant/drop_non_null_keywords_draft7.h"
#include "redundant/drop_non_null_keywords_format_2019_09.h"
#include "redundant/drop_non_null_keywords_format_2020_12.h"
#include "redundant/drop_non_null_keywords_unevaluated_2020_12.h"
#include "redundant/drop_non_null_keywords_validation_2019_09.h"
#include "redundant/drop_non_null_keywords_validation_2020_12.h"
#include "redundant/drop_non_numeric_keywords_applicator_2019_09.h"
#include "redundant/drop_non_numeric_keywords_applicator_2020_12.h"
#include "redundant/drop_non_numeric_keywords_content_2019_09.h"
#include "redundant/drop_non_numeric_keywords_content_2020_12.h"
#include "redundant/drop_non_numeric_keywords_draft0.h"
#include "redundant/drop_non_numeric_keywords_draft1.h"
#include "redundant/drop_non_numeric_keywords_draft2.h"
#include "redundant/drop_non_numeric_keywords_draft3.h"
#include "redundant/drop_non_numeric_keywords_draft4.h"
#include "redundant/drop_non_numeric_keywords_draft6.h"
#include "redundant/drop_non_numeric_keywords_draft7.h"
#include "redundant/drop_non_numeric_keywords_format_2019_09.h"
#include "redundant/drop_non_numeric_keywords_format_2020_12.h"
#include "redundant/drop_non_numeric_keywords_unevaluated_2020_12.h"
#include "redundant/drop_non_numeric_keywords_validation_2019_09.h"
#include "redundant/drop_non_numeric_keywords_validation_2020_12.h"
#include "redundant/drop_non_object_keywords_applicator_2019_09.h"
#include "redundant/drop_non_object_keywords_applicator_2020_12.h"
#include "redundant/drop_non_object_keywords_content_2019_09.h"
#include "redundant/drop_non_object_keywords_content_2020_12.h"
#include "redundant/drop_non_object_keywords_draft0.h"
#include "redundant/drop_non_object_keywords_draft1.h"
#include "redundant/drop_non_object_keywords_draft2.h"
#include "redundant/drop_non_object_keywords_draft3.h"
#include "redundant/drop_non_object_keywords_draft4.h"
#include "redundant/drop_non_object_keywords_draft6.h"
#include "redundant/drop_non_object_keywords_draft7.h"
#include "redundant/drop_non_object_keywords_format_2019_09.h"
#include "redundant/drop_non_object_keywords_format_2020_12.h"
#include "redundant/drop_non_object_keywords_unevaluated_2020_12.h"
#include "redundant/drop_non_object_keywords_validation_2019_09.h"
#include "redundant/drop_non_object_keywords_validation_2020_12.h"
#include "redundant/drop_non_string_keywords_applicator_2019_09.h"
#include "redundant/drop_non_string_keywords_applicator_2020_12.h"
#include "redundant/drop_non_string_keywords_draft0.h"
#include "redundant/drop_non_string_keywords_draft1.h"
#include "redundant/drop_non_string_keywords_draft2.h"
#include "redundant/drop_non_string_keywords_draft3.h"
#include "redundant/drop_non_string_keywords_draft4.h"
#include "redundant/drop_non_string_keywords_draft6.h"
#include "redundant/drop_non_string_keywords_draft7.h"
#include "redundant/drop_non_string_keywords_unevaluated_2020_12.h"
#include "redundant/drop_non_string_keywords_validation_2019_09.h"
#include "redundant/drop_non_string_keywords_validation_2020_12.h"
#include "redundant/duplicate_allof_branches.h"
#include "redundant/duplicate_anyof_branches.h"
#include "redundant/else_without_if.h"
Expand Down Expand Up @@ -79,6 +181,98 @@ auto add(Bundle &bundle, const LinterCategory category) -> void {
bundle.add<ContentMediaTypeWithoutEncoding>();
bundle.add<ContentSchemaDefault>();
bundle.add<ContentSchemaWithoutMediaType>();
bundle.add<DropNonArrayKeywordsApplicator_2019_09>();
bundle.add<DropNonArrayKeywordsApplicator_2020_12>();
bundle.add<DropNonArrayKeywordsContent_2019_09>();
bundle.add<DropNonArrayKeywordsContent_2020_12>();
bundle.add<DropNonArrayKeywords_Draft0>();
bundle.add<DropNonArrayKeywords_Draft1>();
bundle.add<DropNonArrayKeywords_Draft2>();
bundle.add<DropNonArrayKeywords_Draft3>();
bundle.add<DropNonArrayKeywords_Draft4>();
bundle.add<DropNonArrayKeywords_Draft6>();
bundle.add<DropNonArrayKeywords_Draft7>();
bundle.add<DropNonArrayKeywordsFormat_2019_09>();
bundle.add<DropNonArrayKeywordsFormat_2020_12>();
bundle.add<DropNonArrayKeywordsUnevaluated_2020_12>();
bundle.add<DropNonArrayKeywordsValidation_2019_09>();
bundle.add<DropNonArrayKeywordsValidation_2020_12>();
bundle.add<DropNonBooleanKeywordsApplicator_2019_09>();
bundle.add<DropNonBooleanKeywordsApplicator_2020_12>();
bundle.add<DropNonBooleanKeywordsContent_2019_09>();
bundle.add<DropNonBooleanKeywordsContent_2020_12>();
bundle.add<DropNonBooleanKeywords_Draft0>();
bundle.add<DropNonBooleanKeywords_Draft1>();
bundle.add<DropNonBooleanKeywords_Draft2>();
bundle.add<DropNonBooleanKeywords_Draft3>();
bundle.add<DropNonBooleanKeywords_Draft4>();
bundle.add<DropNonBooleanKeywords_Draft6>();
bundle.add<DropNonBooleanKeywords_Draft7>();
bundle.add<DropNonBooleanKeywordsFormat_2019_09>();
bundle.add<DropNonBooleanKeywordsFormat_2020_12>();
bundle.add<DropNonBooleanKeywordsUnevaluated_2020_12>();
bundle.add<DropNonBooleanKeywordsValidation_2019_09>();
bundle.add<DropNonBooleanKeywordsValidation_2020_12>();
bundle.add<DropNonNullKeywordsApplicator_2019_09>();
bundle.add<DropNonNullKeywordsApplicator_2020_12>();
bundle.add<DropNonNullKeywordsContent_2019_09>();
bundle.add<DropNonNullKeywordsContent_2020_12>();
bundle.add<DropNonNullKeywords_Draft0>();
bundle.add<DropNonNullKeywords_Draft1>();
bundle.add<DropNonNullKeywords_Draft2>();
bundle.add<DropNonNullKeywords_Draft3>();
bundle.add<DropNonNullKeywords_Draft4>();
bundle.add<DropNonNullKeywords_Draft6>();
bundle.add<DropNonNullKeywords_Draft7>();
bundle.add<DropNonNullKeywordsFormat_2019_09>();
bundle.add<DropNonNullKeywordsFormat_2020_12>();
bundle.add<DropNonNullKeywordsUnevaluated_2020_12>();
bundle.add<DropNonNullKeywordsValidation_2019_09>();
bundle.add<DropNonNullKeywordsValidation_2020_12>();
bundle.add<DropNonNumericKeywordsApplicator_2019_09>();
bundle.add<DropNonNumericKeywordsApplicator_2020_12>();
bundle.add<DropNonNumericKeywordsContent_2019_09>();
bundle.add<DropNonNumericKeywordsContent_2020_12>();
bundle.add<DropNonNumericKeywords_Draft0>();
bundle.add<DropNonNumericKeywords_Draft1>();
bundle.add<DropNonNumericKeywords_Draft2>();
bundle.add<DropNonNumericKeywords_Draft3>();
bundle.add<DropNonNumericKeywords_Draft4>();
bundle.add<DropNonNumericKeywords_Draft6>();
bundle.add<DropNonNumericKeywords_Draft7>();
bundle.add<DropNonNumericKeywordsFormat_2019_09>();
bundle.add<DropNonNumericKeywordsFormat_2020_12>();
bundle.add<DropNonNumericKeywordsUnevaluated_2020_12>();
bundle.add<DropNonNumericKeywordsValidation_2019_09>();
bundle.add<DropNonNumericKeywordsValidation_2020_12>();
bundle.add<DropNonObjectKeywordsApplicator_2019_09>();
bundle.add<DropNonObjectKeywordsApplicator_2020_12>();
bundle.add<DropNonObjectKeywordsContent_2019_09>();
bundle.add<DropNonObjectKeywordsContent_2020_12>();
bundle.add<DropNonObjectKeywords_Draft0>();
bundle.add<DropNonObjectKeywords_Draft1>();
bundle.add<DropNonObjectKeywords_Draft2>();
bundle.add<DropNonObjectKeywords_Draft3>();
bundle.add<DropNonObjectKeywords_Draft4>();
bundle.add<DropNonObjectKeywords_Draft6>();
bundle.add<DropNonObjectKeywords_Draft7>();
bundle.add<DropNonObjectKeywordsFormat_2019_09>();
bundle.add<DropNonObjectKeywordsFormat_2020_12>();
bundle.add<DropNonObjectKeywordsUnevaluated_2020_12>();
bundle.add<DropNonObjectKeywordsValidation_2019_09>();
bundle.add<DropNonObjectKeywordsValidation_2020_12>();
bundle.add<DropNonStringKeywordsApplicator_2019_09>();
bundle.add<DropNonStringKeywordsApplicator_2020_12>();
bundle.add<DropNonStringKeywords_Draft0>();
bundle.add<DropNonStringKeywords_Draft1>();
bundle.add<DropNonStringKeywords_Draft2>();
bundle.add<DropNonStringKeywords_Draft3>();
bundle.add<DropNonStringKeywords_Draft4>();
bundle.add<DropNonStringKeywords_Draft6>();
bundle.add<DropNonStringKeywords_Draft7>();
bundle.add<DropNonStringKeywordsUnevaluated_2020_12>();
bundle.add<DropNonStringKeywordsValidation_2019_09>();
bundle.add<DropNonStringKeywordsValidation_2020_12>();
bundle.add<DuplicateAllOfBranches>();
bundle.add<DuplicateAnyOfBranches>();
bundle.add<ElseWithoutIf>();
Expand Down
30 changes: 30 additions & 0 deletions src/linter/redundant/drop_non_array_keywords_applicator_2019_09.h
Original file line number Diff line number Diff line change
@@ -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<std::string> &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<std::string> BLACKLIST{
"properties", "patternProperties", "additionalProperties",
"dependentSchemas", "propertyNames", "unevaluatedProperties"};
};
Loading