From 767c38ffef2d85e77c8c84cd7a368ce1b189340d Mon Sep 17 00:00:00 2001 From: karan-palan Date: Thu, 3 Jul 2025 04:08:17 +0530 Subject: [PATCH 1/4] feat(alterschema): [linter] create rule to remove additional items when items is an objects Signed-off-by: karan-palan --- src/extension/alterschema/alterschema.cc | 2 + .../linter/dangling_additional_items.h | 30 +++++++ .../alterschema_lint_2019_09_test.cc | 47 +++++++++- .../alterschema_lint_draft4_test.cc | 86 +++++++++++++++++++ .../alterschema_lint_draft6_test.cc | 42 +++++++++ .../alterschema_lint_draft7_test.cc | 48 +++++++++++ 6 files changed, 253 insertions(+), 2 deletions(-) create mode 100644 src/extension/alterschema/linter/dangling_additional_items.h diff --git a/src/extension/alterschema/alterschema.cc b/src/extension/alterschema/alterschema.cc index a455c1e2a..f790ae1b2 100644 --- a/src/extension/alterschema/alterschema.cc +++ b/src/extension/alterschema/alterschema.cc @@ -52,6 +52,7 @@ static auto every_item_is_boolean(const T &container) -> bool { #include "linter/content_media_type_without_encoding.h" #include "linter/content_schema_default.h" #include "linter/content_schema_without_media_type.h" +#include "linter/dangling_additional_items.h" #include "linter/dependencies_default.h" #include "linter/dependencies_property_tautology.h" #include "linter/dependent_required_default.h" @@ -112,6 +113,7 @@ auto add(SchemaTransformer &bundle, const AlterSchemaMode mode) bundle.add(); bundle.add(); bundle.add(); + bundle.add(); bundle.add(); bundle.add(); diff --git a/src/extension/alterschema/linter/dangling_additional_items.h b/src/extension/alterschema/linter/dangling_additional_items.h new file mode 100644 index 000000000..7c9145a6d --- /dev/null +++ b/src/extension/alterschema/linter/dangling_additional_items.h @@ -0,0 +1,30 @@ +class DanglingAdditionalItems final : public SchemaTransformRule { +public: + DanglingAdditionalItems() + : SchemaTransformRule{ + "dangling_additional_items", + "`additionalItems` is ignored when `items` is an object"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::core::JSON &schema, + const sourcemeta::core::JSON &, + const sourcemeta::core::Vocabularies &vocabularies, + const sourcemeta::core::SchemaFrame &, + const sourcemeta::core::SchemaFrame::Location &, + const sourcemeta::core::SchemaWalker &, + const sourcemeta::core::SchemaResolver &) const + -> sourcemeta::core::SchemaTransformRule::Result override { + return contains_any( + vocabularies, + {"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("items") && + schema.defines("additionalItems") && schema.at("items").is_object(); + } + + auto transform(JSON &schema) const -> void override { + schema.erase("additionalItems"); + } +}; diff --git a/test/alterschema/alterschema_lint_2019_09_test.cc b/test/alterschema/alterschema_lint_2019_09_test.cc index f62c8122f..613f9c1c7 100644 --- a/test/alterschema/alterschema_lint_2019_09_test.cc +++ b/test/alterschema/alterschema_lint_2019_09_test.cc @@ -1661,8 +1661,7 @@ TEST(AlterSchema_lint_2019_09, unnecessary_allof_ref_wrapper_5) { sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "https://json-schema.org/draft/2019-09/schema", "allOf": [ - { - "type": "integer", + { "type": "integer", "$ref": "https://example.com" } ] @@ -1680,3 +1679,47 @@ TEST(AlterSchema_lint_2019_09, unnecessary_allof_ref_wrapper_5) { EXPECT_EQ(document, expected); } + +TEST(AlterSchema_lint_2019_09, dangling_additional_items_1) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "items": { + "type": "number" + }, + "additionalItems": false + })JSON"); + + LINT_AND_FIX_FOR_READABILITY(document); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "items": { + "type": "number" + } + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_2019_09, dangling_additional_items_2) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "items": { + "unevaluatedProperties": false + }, + "additionalItems": { + "type": "string" + } + })JSON"); + + LINT_AND_FIX_FOR_READABILITY(document); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "items": { + "unevaluatedProperties": false + } + })JSON"); + + EXPECT_EQ(document, expected); +} diff --git a/test/alterschema/alterschema_lint_draft4_test.cc b/test/alterschema/alterschema_lint_draft4_test.cc index 8f5c58a10..4e1787afd 100644 --- a/test/alterschema/alterschema_lint_draft4_test.cc +++ b/test/alterschema/alterschema_lint_draft4_test.cc @@ -761,3 +761,89 @@ TEST(AlterSchema_lint_draft4, unnecessary_allof_ref_wrapper_1) { EXPECT_EQ(document, expected); } + +TEST(AlterSchema_lint_draft4, dangling_additional_items_1) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-04/schema#", + "items": { + "type": "number" + }, + "additionalItems": false + })JSON"); + + LINT_AND_FIX_FOR_READABILITY(document); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-04/schema#", + "items": { + "type": "number" + } + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_draft4, dangling_additional_items_2) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "array", + "items": { + "type": "string" + }, + "additionalItems": { + "type": "boolean" + } + })JSON"); + + LINT_AND_FIX_FOR_READABILITY(document); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "array", + "items": { + "type": "string" + } + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_draft4, dangling_additional_items_no_change_array_items) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-04/schema#", + "items": [ + { "type": "string" }, + { "type": "number" } + ], + "additionalItems": false + })JSON"); + + LINT_AND_FIX_FOR_READABILITY(document); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-04/schema#", + "items": [ + { "type": "string" }, + { "type": "number" } + ], + "additionalItems": false + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_draft4, dangling_additional_items_no_change_no_items) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-04/schema#", + "additionalItems": false + })JSON"); + + LINT_AND_FIX_FOR_READABILITY(document); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-04/schema#", + "additionalItems": false + })JSON"); + + EXPECT_EQ(document, expected); +} diff --git a/test/alterschema/alterschema_lint_draft6_test.cc b/test/alterschema/alterschema_lint_draft6_test.cc index 0ba428f53..e580c943f 100644 --- a/test/alterschema/alterschema_lint_draft6_test.cc +++ b/test/alterschema/alterschema_lint_draft6_test.cc @@ -1112,3 +1112,45 @@ TEST(AlterSchema_lint_draft6, unnecessary_allof_ref_wrapper_1) { EXPECT_EQ(document, expected); } + +TEST(AlterSchema_lint_draft6, dangling_additional_items_1) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-06/schema#", + "items": { + "type": "number" + }, + "additionalItems": false + })JSON"); + + LINT_AND_FIX_FOR_READABILITY(document); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-06/schema#", + "items": { + "type": "number" + } + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_draft6, dangling_additional_items_2) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-06/schema#", + "items": { + "const": "foo" + }, + "additionalItems": true + })JSON"); + + LINT_AND_FIX_FOR_READABILITY(document); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-06/schema#", + "items": { + "const": "foo" + } + })JSON"); + + EXPECT_EQ(document, expected); +} diff --git a/test/alterschema/alterschema_lint_draft7_test.cc b/test/alterschema/alterschema_lint_draft7_test.cc index 4bb0daf28..41ae9e1d7 100644 --- a/test/alterschema/alterschema_lint_draft7_test.cc +++ b/test/alterschema/alterschema_lint_draft7_test.cc @@ -1208,3 +1208,51 @@ TEST(AlterSchema_lint_draft7, unnecessary_allof_ref_wrapper_1) { EXPECT_EQ(document, expected); } + +TEST(AlterSchema_lint_draft7, dangling_additional_items_1) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "items": { + "type": "number" + }, + "additionalItems": false + })JSON"); + + LINT_AND_FIX_FOR_READABILITY(document); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "items": { + "type": "number" + } + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_draft7, dangling_additional_items_2) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "array", + "items": { + "if": { "type": "string" }, + "then": { "minLength": 1 } + }, + "additionalItems": { + "type": "number" + } + })JSON"); + + LINT_AND_FIX_FOR_READABILITY(document); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "array", + "items": { + "if": { "type": "string" }, + "then": { "minLength": 1 } + } + })JSON"); + + EXPECT_EQ(document, expected); +} From bb302445e49e9d2ef2f5a069b2d45653a7e8984f Mon Sep 17 00:00:00 2001 From: karan-palan Date: Tue, 8 Jul 2025 23:42:54 +0530 Subject: [PATCH 2/4] Update linter: add tests for draft 3, rename rule, update tests, and undo unintended change Signed-off-by: karan-palan --- src/extension/alterschema/CMakeLists.txt | 1 + src/extension/alterschema/alterschema.cc | 4 +- ...h => additional_items_with_schema_items.h} | 13 ++--- .../alterschema_lint_2019_09_test.cc | 7 +-- .../alterschema_lint_draft3_test.cc | 44 ++++++++++++++++ .../alterschema_lint_draft4_test.cc | 51 +++++++++++++++++-- .../alterschema_lint_draft6_test.cc | 4 +- .../alterschema_lint_draft7_test.cc | 4 +- 8 files changed, 109 insertions(+), 19 deletions(-) rename src/extension/alterschema/linter/{dangling_additional_items.h => additional_items_with_schema_items.h} (68%) diff --git a/src/extension/alterschema/CMakeLists.txt b/src/extension/alterschema/CMakeLists.txt index 3685bd864..dc7079710 100644 --- a/src/extension/alterschema/CMakeLists.txt +++ b/src/extension/alterschema/CMakeLists.txt @@ -46,6 +46,7 @@ sourcemeta_library(NAMESPACE sourcemeta PROJECT core NAME alterschema linter/unsatisfiable_min_properties.h linter/content_media_type_without_encoding.h linter/content_schema_without_media_type.h + linter/additional_items_with_schema_items.h linter/non_applicable_type_specific_keywords.h linter/unnecessary_allof_ref_wrapper.h linter/duplicate_allof_branches.h diff --git a/src/extension/alterschema/alterschema.cc b/src/extension/alterschema/alterschema.cc index f790ae1b2..f984cbaaa 100644 --- a/src/extension/alterschema/alterschema.cc +++ b/src/extension/alterschema/alterschema.cc @@ -47,12 +47,12 @@ static auto every_item_is_boolean(const T &container) -> bool { #include "canonicalizer/type_union_implicit.h" // Linter +#include "linter/additional_items_with_schema_items.h" #include "linter/additional_properties_default.h" #include "linter/const_with_type.h" #include "linter/content_media_type_without_encoding.h" #include "linter/content_schema_default.h" #include "linter/content_schema_without_media_type.h" -#include "linter/dangling_additional_items.h" #include "linter/dependencies_default.h" #include "linter/dependencies_property_tautology.h" #include "linter/dependent_required_default.h" @@ -113,7 +113,7 @@ auto add(SchemaTransformer &bundle, const AlterSchemaMode mode) bundle.add(); bundle.add(); bundle.add(); - bundle.add(); + bundle.add(); bundle.add(); bundle.add(); diff --git a/src/extension/alterschema/linter/dangling_additional_items.h b/src/extension/alterschema/linter/additional_items_with_schema_items.h similarity index 68% rename from src/extension/alterschema/linter/dangling_additional_items.h rename to src/extension/alterschema/linter/additional_items_with_schema_items.h index 7c9145a6d..b06b28f53 100644 --- a/src/extension/alterschema/linter/dangling_additional_items.h +++ b/src/extension/alterschema/linter/additional_items_with_schema_items.h @@ -1,9 +1,9 @@ -class DanglingAdditionalItems final : public SchemaTransformRule { +class AdditionalItemsWithSchemaItems final : public SchemaTransformRule { public: - DanglingAdditionalItems() - : SchemaTransformRule{ - "dangling_additional_items", - "`additionalItems` is ignored when `items` is an object"} {}; + AdditionalItemsWithSchemaItems() + : SchemaTransformRule{"additional_items_with_schema_items", + "The `additionalItems` keyword is ignored when the " + "`items` keyword is set to a schema"} {}; [[nodiscard]] auto condition(const sourcemeta::core::JSON &schema, @@ -19,7 +19,8 @@ class DanglingAdditionalItems final : public SchemaTransformRule { {"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-04/schema#", + "http://json-schema.org/draft-03/schema#"}) && schema.is_object() && schema.defines("items") && schema.defines("additionalItems") && schema.at("items").is_object(); } diff --git a/test/alterschema/alterschema_lint_2019_09_test.cc b/test/alterschema/alterschema_lint_2019_09_test.cc index 613f9c1c7..ccf2eede1 100644 --- a/test/alterschema/alterschema_lint_2019_09_test.cc +++ b/test/alterschema/alterschema_lint_2019_09_test.cc @@ -1661,7 +1661,8 @@ TEST(AlterSchema_lint_2019_09, unnecessary_allof_ref_wrapper_5) { sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "https://json-schema.org/draft/2019-09/schema", "allOf": [ - { "type": "integer", + { + "type": "integer", "$ref": "https://example.com" } ] @@ -1680,7 +1681,7 @@ TEST(AlterSchema_lint_2019_09, unnecessary_allof_ref_wrapper_5) { EXPECT_EQ(document, expected); } -TEST(AlterSchema_lint_2019_09, dangling_additional_items_1) { +TEST(AlterSchema_lint_2019_09, additional_items_with_schema_items_1) { sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "https://json-schema.org/draft/2019-09/schema", "items": { @@ -1701,7 +1702,7 @@ TEST(AlterSchema_lint_2019_09, dangling_additional_items_1) { EXPECT_EQ(document, expected); } -TEST(AlterSchema_lint_2019_09, dangling_additional_items_2) { +TEST(AlterSchema_lint_2019_09, additional_items_with_schema_items_2) { sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "https://json-schema.org/draft/2019-09/schema", "items": { diff --git a/test/alterschema/alterschema_lint_draft3_test.cc b/test/alterschema/alterschema_lint_draft3_test.cc index 4ac3a83b3..7fad029be 100644 --- a/test/alterschema/alterschema_lint_draft3_test.cc +++ b/test/alterschema/alterschema_lint_draft3_test.cc @@ -579,3 +579,47 @@ TEST(AlterSchema_lint_draft3, equal_numeric_bounds_to_enum_2) { EXPECT_EQ(document, expected); } + +TEST(AlterSchema_lint_draft3, additional_items_with_schema_items_1) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-03/schema#", + "items": { + "type": "number" + }, + "additionalItems": false + })JSON"); + + LINT_AND_FIX_FOR_READABILITY(document); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-03/schema#", + "items": { + "type": "number" + } + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_draft3, additional_items_with_schema_items_2) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-03/schema#", + "items": { + "type": "string" + }, + "additionalItems": { + "type": "boolean" + } + })JSON"); + + LINT_AND_FIX_FOR_READABILITY(document); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-03/schema#", + "items": { + "type": "string" + } + })JSON"); + + EXPECT_EQ(document, expected); +} diff --git a/test/alterschema/alterschema_lint_draft4_test.cc b/test/alterschema/alterschema_lint_draft4_test.cc index 4e1787afd..88fd766f5 100644 --- a/test/alterschema/alterschema_lint_draft4_test.cc +++ b/test/alterschema/alterschema_lint_draft4_test.cc @@ -762,7 +762,7 @@ TEST(AlterSchema_lint_draft4, unnecessary_allof_ref_wrapper_1) { EXPECT_EQ(document, expected); } -TEST(AlterSchema_lint_draft4, dangling_additional_items_1) { +TEST(AlterSchema_lint_draft4, additional_items_with_schema_items_1) { sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "http://json-schema.org/draft-04/schema#", "items": { @@ -783,7 +783,7 @@ TEST(AlterSchema_lint_draft4, dangling_additional_items_1) { EXPECT_EQ(document, expected); } -TEST(AlterSchema_lint_draft4, dangling_additional_items_2) { +TEST(AlterSchema_lint_draft4, additional_items_with_schema_items_2) { sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "http://json-schema.org/draft-04/schema#", "type": "array", @@ -808,7 +808,8 @@ TEST(AlterSchema_lint_draft4, dangling_additional_items_2) { EXPECT_EQ(document, expected); } -TEST(AlterSchema_lint_draft4, dangling_additional_items_no_change_array_items) { +TEST(AlterSchema_lint_draft4, + additional_items_with_schema_items_no_change_array_items) { sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "http://json-schema.org/draft-04/schema#", "items": [ @@ -832,7 +833,8 @@ TEST(AlterSchema_lint_draft4, dangling_additional_items_no_change_array_items) { EXPECT_EQ(document, expected); } -TEST(AlterSchema_lint_draft4, dangling_additional_items_no_change_no_items) { +TEST(AlterSchema_lint_draft4, + additional_items_with_schema_items_no_change_no_items) { sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "http://json-schema.org/draft-04/schema#", "additionalItems": false @@ -847,3 +849,44 @@ TEST(AlterSchema_lint_draft4, dangling_additional_items_no_change_no_items) { EXPECT_EQ(document, expected); } + +TEST(AlterSchema_lint_draft4, + additional_items_with_schema_items_no_change_boolean_items_true) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-04/schema#", + "items": true, + "additionalItems": false + })JSON"); + + LINT_AND_FIX_FOR_READABILITY(document); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-04/schema#", + "additionalItems": false + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_draft4, + additional_items_with_schema_items_no_change_boolean_items_false) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-04/schema#", + "items": false, + "additionalItems": { + "type": "string" + } + })JSON"); + + LINT_AND_FIX_FOR_READABILITY(document); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-04/schema#", + "items": false, + "additionalItems": { + "type": "string" + } + })JSON"); + + EXPECT_EQ(document, expected); +} diff --git a/test/alterschema/alterschema_lint_draft6_test.cc b/test/alterschema/alterschema_lint_draft6_test.cc index e580c943f..964b5c749 100644 --- a/test/alterschema/alterschema_lint_draft6_test.cc +++ b/test/alterschema/alterschema_lint_draft6_test.cc @@ -1113,7 +1113,7 @@ TEST(AlterSchema_lint_draft6, unnecessary_allof_ref_wrapper_1) { EXPECT_EQ(document, expected); } -TEST(AlterSchema_lint_draft6, dangling_additional_items_1) { +TEST(AlterSchema_lint_draft6, additional_items_with_schema_items_1) { sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "http://json-schema.org/draft-06/schema#", "items": { @@ -1134,7 +1134,7 @@ TEST(AlterSchema_lint_draft6, dangling_additional_items_1) { EXPECT_EQ(document, expected); } -TEST(AlterSchema_lint_draft6, dangling_additional_items_2) { +TEST(AlterSchema_lint_draft6, additional_items_with_schema_items_2) { sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "http://json-schema.org/draft-06/schema#", "items": { diff --git a/test/alterschema/alterschema_lint_draft7_test.cc b/test/alterschema/alterschema_lint_draft7_test.cc index 41ae9e1d7..82f23df72 100644 --- a/test/alterschema/alterschema_lint_draft7_test.cc +++ b/test/alterschema/alterschema_lint_draft7_test.cc @@ -1209,7 +1209,7 @@ TEST(AlterSchema_lint_draft7, unnecessary_allof_ref_wrapper_1) { EXPECT_EQ(document, expected); } -TEST(AlterSchema_lint_draft7, dangling_additional_items_1) { +TEST(AlterSchema_lint_draft7, additional_items_with_schema_items_1) { sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "http://json-schema.org/draft-07/schema#", "items": { @@ -1230,7 +1230,7 @@ TEST(AlterSchema_lint_draft7, dangling_additional_items_1) { EXPECT_EQ(document, expected); } -TEST(AlterSchema_lint_draft7, dangling_additional_items_2) { +TEST(AlterSchema_lint_draft7, additional_items_with_schema_items_2) { sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "http://json-schema.org/draft-07/schema#", "type": "array", From f600c3b946f69d44182ed93bfdb7bde09dbafb05 Mon Sep 17 00:00:00 2001 From: karan-palan Date: Wed, 9 Jul 2025 00:40:05 +0530 Subject: [PATCH 3/4] fix(alterschema): [linter] add missing boolean test cases for all drafts Signed-off-by: karan-palan --- .../additional_items_with_schema_items.h | 2 +- .../alterschema_lint_2019_09_test.cc | 64 ++++++++++++++++++- .../alterschema_lint_draft3_test.cc | 61 ++++++++++++++++++ .../alterschema_lint_draft4_test.cc | 12 ++-- .../alterschema_lint_draft6_test.cc | 61 ++++++++++++++++++ .../alterschema_lint_draft7_test.cc | 61 ++++++++++++++++++ 6 files changed, 250 insertions(+), 11 deletions(-) diff --git a/src/extension/alterschema/linter/additional_items_with_schema_items.h b/src/extension/alterschema/linter/additional_items_with_schema_items.h index b06b28f53..595a0da75 100644 --- a/src/extension/alterschema/linter/additional_items_with_schema_items.h +++ b/src/extension/alterschema/linter/additional_items_with_schema_items.h @@ -22,7 +22,7 @@ class AdditionalItemsWithSchemaItems final : public SchemaTransformRule { "http://json-schema.org/draft-04/schema#", "http://json-schema.org/draft-03/schema#"}) && schema.is_object() && schema.defines("items") && - schema.defines("additionalItems") && schema.at("items").is_object(); + schema.defines("additionalItems") && is_schema(schema.at("items")); } auto transform(JSON &schema) const -> void override { diff --git a/test/alterschema/alterschema_lint_2019_09_test.cc b/test/alterschema/alterschema_lint_2019_09_test.cc index ccf2eede1..b7f9b0ed5 100644 --- a/test/alterschema/alterschema_lint_2019_09_test.cc +++ b/test/alterschema/alterschema_lint_2019_09_test.cc @@ -1661,8 +1661,7 @@ TEST(AlterSchema_lint_2019_09, unnecessary_allof_ref_wrapper_5) { sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "https://json-schema.org/draft/2019-09/schema", "allOf": [ - { - "type": "integer", + { "type": "integer", "$ref": "https://example.com" } ] @@ -1724,3 +1723,64 @@ TEST(AlterSchema_lint_2019_09, additional_items_with_schema_items_2) { EXPECT_EQ(document, expected); } + +TEST(AlterSchema_lint_2019_09, + additional_items_with_schema_items_boolean_items_true) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "items": true, + "additionalItems": false + })JSON"); + + LINT_AND_FIX_FOR_READABILITY(document); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema" + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_2019_09, + additional_items_with_schema_items_boolean_items_false) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "items": false, + "additionalItems": { + "type": "string" + } + })JSON"); + + LINT_AND_FIX_FOR_READABILITY(document); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "items": false + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_2019_09, additional_items_with_schema_items_array_items) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "items": [ + { "type": "string" }, + { "type": "number" } + ], + "additionalItems": false + })JSON"); + + LINT_AND_FIX_FOR_READABILITY(document); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "items": [ + { "type": "string" }, + { "type": "number" } + ], + "additionalItems": false + })JSON"); + + EXPECT_EQ(document, expected); +} diff --git a/test/alterschema/alterschema_lint_draft3_test.cc b/test/alterschema/alterschema_lint_draft3_test.cc index 7fad029be..1ced95b6f 100644 --- a/test/alterschema/alterschema_lint_draft3_test.cc +++ b/test/alterschema/alterschema_lint_draft3_test.cc @@ -623,3 +623,64 @@ TEST(AlterSchema_lint_draft3, additional_items_with_schema_items_2) { EXPECT_EQ(document, expected); } + +TEST(AlterSchema_lint_draft3, + additional_items_with_schema_items_boolean_items_true) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-03/schema#", + "items": true, + "additionalItems": false + })JSON"); + + LINT_AND_FIX_FOR_READABILITY(document); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-03/schema#" + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_draft3, + additional_items_with_schema_items_boolean_items_false) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-03/schema#", + "items": false, + "additionalItems": { + "type": "string" + } + })JSON"); + + LINT_AND_FIX_FOR_READABILITY(document); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-03/schema#", + "items": false + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_draft3, additional_items_with_schema_items_array_items) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-03/schema#", + "items": [ + { "type": "string" }, + { "type": "number" } + ], + "additionalItems": false + })JSON"); + + LINT_AND_FIX_FOR_READABILITY(document); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-03/schema#", + "items": [ + { "type": "string" }, + { "type": "number" } + ], + "additionalItems": false + })JSON"); + + EXPECT_EQ(document, expected); +} diff --git a/test/alterschema/alterschema_lint_draft4_test.cc b/test/alterschema/alterschema_lint_draft4_test.cc index 88fd766f5..112bd4661 100644 --- a/test/alterschema/alterschema_lint_draft4_test.cc +++ b/test/alterschema/alterschema_lint_draft4_test.cc @@ -851,7 +851,7 @@ TEST(AlterSchema_lint_draft4, } TEST(AlterSchema_lint_draft4, - additional_items_with_schema_items_no_change_boolean_items_true) { + additional_items_with_schema_items_boolean_items_true) { sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "http://json-schema.org/draft-04/schema#", "items": true, @@ -861,15 +861,14 @@ TEST(AlterSchema_lint_draft4, LINT_AND_FIX_FOR_READABILITY(document); const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-04/schema#", - "additionalItems": false + "$schema": "http://json-schema.org/draft-04/schema#" })JSON"); EXPECT_EQ(document, expected); } TEST(AlterSchema_lint_draft4, - additional_items_with_schema_items_no_change_boolean_items_false) { + additional_items_with_schema_items_boolean_items_false) { sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "http://json-schema.org/draft-04/schema#", "items": false, @@ -882,10 +881,7 @@ TEST(AlterSchema_lint_draft4, const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ "$schema": "http://json-schema.org/draft-04/schema#", - "items": false, - "additionalItems": { - "type": "string" - } + "items": false })JSON"); EXPECT_EQ(document, expected); diff --git a/test/alterschema/alterschema_lint_draft6_test.cc b/test/alterschema/alterschema_lint_draft6_test.cc index 964b5c749..8d8311c70 100644 --- a/test/alterschema/alterschema_lint_draft6_test.cc +++ b/test/alterschema/alterschema_lint_draft6_test.cc @@ -1154,3 +1154,64 @@ TEST(AlterSchema_lint_draft6, additional_items_with_schema_items_2) { EXPECT_EQ(document, expected); } + +TEST(AlterSchema_lint_draft6, + additional_items_with_schema_items_boolean_items_true) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-06/schema#", + "items": true, + "additionalItems": false + })JSON"); + + LINT_AND_FIX_FOR_READABILITY(document); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-06/schema#" + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_draft6, + additional_items_with_schema_items_boolean_items_false) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-06/schema#", + "items": false, + "additionalItems": { + "type": "string" + } + })JSON"); + + LINT_AND_FIX_FOR_READABILITY(document); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-06/schema#", + "items": false + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_draft6, additional_items_with_schema_items_array_items) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-06/schema#", + "items": [ + { "type": "string" }, + { "type": "number" } + ], + "additionalItems": false + })JSON"); + + LINT_AND_FIX_FOR_READABILITY(document); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-06/schema#", + "items": [ + { "type": "string" }, + { "type": "number" } + ], + "additionalItems": false + })JSON"); + + EXPECT_EQ(document, expected); +} diff --git a/test/alterschema/alterschema_lint_draft7_test.cc b/test/alterschema/alterschema_lint_draft7_test.cc index 82f23df72..b859707b1 100644 --- a/test/alterschema/alterschema_lint_draft7_test.cc +++ b/test/alterschema/alterschema_lint_draft7_test.cc @@ -1256,3 +1256,64 @@ TEST(AlterSchema_lint_draft7, additional_items_with_schema_items_2) { EXPECT_EQ(document, expected); } + +TEST(AlterSchema_lint_draft7, + additional_items_with_schema_items_boolean_items_true) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "items": true, + "additionalItems": false + })JSON"); + + LINT_AND_FIX_FOR_READABILITY(document); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#" + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_draft7, + additional_items_with_schema_items_boolean_items_false) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "items": false, + "additionalItems": { + "type": "string" + } + })JSON"); + + LINT_AND_FIX_FOR_READABILITY(document); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "items": false + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_draft7, additional_items_with_schema_items_array_items) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "items": [ + { "type": "string" }, + { "type": "number" } + ], + "additionalItems": false + })JSON"); + + LINT_AND_FIX_FOR_READABILITY(document); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "items": [ + { "type": "string" }, + { "type": "number" } + ], + "additionalItems": false + })JSON"); + + EXPECT_EQ(document, expected); +} From 440710757a638d8726f005f550d26efea73d8a53 Mon Sep 17 00:00:00 2001 From: karan-palan Date: Wed, 9 Jul 2025 04:20:52 +0530 Subject: [PATCH 4/4] chore: [linter]undo unintended change Signed-off-by: karan-palan --- test/alterschema/alterschema_lint_2019_09_test.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/alterschema/alterschema_lint_2019_09_test.cc b/test/alterschema/alterschema_lint_2019_09_test.cc index ca1492ee0..b4fdd367c 100644 --- a/test/alterschema/alterschema_lint_2019_09_test.cc +++ b/test/alterschema/alterschema_lint_2019_09_test.cc @@ -1661,7 +1661,8 @@ TEST(AlterSchema_lint_2019_09, unnecessary_allof_ref_wrapper_5) { sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "https://json-schema.org/draft/2019-09/schema", "allOf": [ - { "type": "integer", + { + "type": "integer", "$ref": "https://example.com" } ]