From a8edf4c7e92dc0148035f900ef0ec2144340c888 Mon Sep 17 00:00:00 2001 From: karan-palan Date: Mon, 28 Jul 2025 02:11:02 +0530 Subject: [PATCH 01/10] create rule to add syntaxtical sugar when else or then is set to false Signed-off-by: karan-palan --- src/core/jsonschema/transformer.cc | 1 - src/extension/alterschema/CMakeLists.txt | 2 + src/extension/alterschema/alterschema.cc | 4 ++ src/extension/alterschema/linter/else_false.h | 38 +++++++++++++ src/extension/alterschema/linter/then_false.h | 29 ++++++++++ .../alterschema_lint_2019_09_test.cc | 56 +++++++++++++++++++ .../alterschema_lint_2020_12_test.cc | 56 +++++++++++++++++++ .../alterschema_lint_draft7_test.cc | 56 +++++++++++++++++++ 8 files changed, 241 insertions(+), 1 deletion(-) create mode 100644 src/extension/alterschema/linter/else_false.h create mode 100644 src/extension/alterschema/linter/then_false.h diff --git a/src/core/jsonschema/transformer.cc b/src/core/jsonschema/transformer.cc index e79cc7be9..20e98aab8 100644 --- a/src/core/jsonschema/transformer.cc +++ b/src/core/jsonschema/transformer.cc @@ -26,7 +26,6 @@ auto calculate_health_percentage(const std::size_t subschemas, -> std::uint8_t { assert(failed_subschemas <= subschemas); const auto result{100 - (failed_subschemas * 100 / subschemas)}; - assert(result >= 0); assert(result <= 100); return static_cast(result); } diff --git a/src/extension/alterschema/CMakeLists.txt b/src/extension/alterschema/CMakeLists.txt index 9bb24d580..55942e7d6 100644 --- a/src/extension/alterschema/CMakeLists.txt +++ b/src/extension/alterschema/CMakeLists.txt @@ -62,6 +62,8 @@ sourcemeta_library(NAMESPACE sourcemeta PROJECT core NAME alterschema linter/modern_official_dialect_with_empty_fragment.h linter/then_empty.h linter/else_empty.h + linter/else_false.h + linter/then_false.h linter/then_without_if.h linter/property_names_type_default.h linter/property_names_default.h) diff --git a/src/extension/alterschema/alterschema.cc b/src/extension/alterschema/alterschema.cc index 3312b4825..9d9627491 100644 --- a/src/extension/alterschema/alterschema.cc +++ b/src/extension/alterschema/alterschema.cc @@ -51,6 +51,7 @@ contains_any(const Vocabularies &container, #include "linter/duplicate_enum_values.h" #include "linter/duplicate_required_values.h" #include "linter/else_empty.h" +#include "linter/else_false.h" #include "linter/else_without_if.h" #include "linter/enum_to_const.h" #include "linter/enum_with_type.h" @@ -73,6 +74,7 @@ contains_any(const Vocabularies &container, #include "linter/property_names_type_default.h" #include "linter/single_type_array.h" #include "linter/then_empty.h" +#include "linter/then_false.h" #include "linter/then_without_if.h" #include "linter/unevaluated_items_default.h" #include "linter/unevaluated_properties_default.h" @@ -103,7 +105,9 @@ auto add(SchemaTransformer &bundle, const AlterSchemaMode mode) bundle.add(); bundle.add(); bundle.add(); + bundle.add(); bundle.add(); + bundle.add(); bundle.add(); bundle.add(); bundle.add(); diff --git a/src/extension/alterschema/linter/else_false.h b/src/extension/alterschema/linter/else_false.h new file mode 100644 index 000000000..a24d07ae0 --- /dev/null +++ b/src/extension/alterschema/linter/else_false.h @@ -0,0 +1,38 @@ +class ElseFalse final : public SchemaTransformRule { +public: + ElseFalse() + : SchemaTransformRule{"else_false", + "`if: S, else: false` collapses to just `S`"} {}; + + [[nodiscard]] auto + condition(const JSON &schema, const JSON &, const Vocabularies &vocabularies, + const SchemaFrame &, const SchemaFrame::Location &, + const SchemaWalker &, const SchemaResolver &) const + -> SchemaTransformRule::Result 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("else") && schema.at("else").is_boolean() && + !schema.at("else").to_boolean(); + } + + auto transform(JSON &schema) const -> void override { + const auto if_schema = schema.at("if"); + schema.erase("if"); + schema.erase("else"); + if (if_schema.is_object()) { + for (const auto &entry : if_schema.as_object()) { + if (!schema.defines(entry.first)) { + schema.assign(entry.first, entry.second); + } + } + } else if (if_schema.is_boolean()) { + if (if_schema.to_boolean()) { + } else { + } + } + } +}; diff --git a/src/extension/alterschema/linter/then_false.h b/src/extension/alterschema/linter/then_false.h new file mode 100644 index 000000000..f8cc3e3a2 --- /dev/null +++ b/src/extension/alterschema/linter/then_false.h @@ -0,0 +1,29 @@ +class ThenFalse final : public SchemaTransformRule { +public: + ThenFalse() + : SchemaTransformRule{ + "then_false", + "`if: S, then: false` is logically equivalent to `not: S`"} {}; + + [[nodiscard]] auto + condition(const JSON &schema, const JSON &, const Vocabularies &vocabularies, + const SchemaFrame &, const SchemaFrame::Location &, + const SchemaWalker &, const SchemaResolver &) const + -> SchemaTransformRule::Result 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.at("then").is_boolean() && + !schema.at("then").to_boolean(); + } + + auto transform(JSON &schema) const -> void override { + const auto if_schema = schema.at("if"); + schema.erase("if"); + schema.erase("then"); + schema.assign("not", if_schema); + } +}; diff --git a/test/alterschema/alterschema_lint_2019_09_test.cc b/test/alterschema/alterschema_lint_2019_09_test.cc index 171d82775..fd73835fe 100644 --- a/test/alterschema/alterschema_lint_2019_09_test.cc +++ b/test/alterschema/alterschema_lint_2019_09_test.cc @@ -2294,3 +2294,59 @@ TEST(AlterSchema_lint_2019_09, property_names_default_1) { EXPECT_EQ(document, expected); } + +TEST(AlterSchema_lint_2019_09, then_false_1) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "if": { + "properties": { + "flag": { + "const": true + } + } + }, + "then": 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", + "not": { + "properties": { + "flag": { + "const": true + } + } + } + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_2019_09, else_false_1) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "if": { + "properties": { + "flag": { + "const": true + } + } + }, + "else": 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", + "properties": { + "flag": { + "const": true + } + } + })JSON"); + + EXPECT_EQ(document, expected); +} \ No newline at end of file diff --git a/test/alterschema/alterschema_lint_2020_12_test.cc b/test/alterschema/alterschema_lint_2020_12_test.cc index bbad7d002..ff95509fa 100644 --- a/test/alterschema/alterschema_lint_2020_12_test.cc +++ b/test/alterschema/alterschema_lint_2020_12_test.cc @@ -2528,3 +2528,59 @@ TEST(AlterSchema_lint_2020_12, property_names_default_1) { EXPECT_EQ(document, expected); } + +TEST(AlterSchema_lint_2020_12, then_false_1) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "if": { + "properties": { + "flag": { + "const": true + } + } + }, + "then": 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/2020-12/schema", + "not": { + "properties": { + "flag": { + "const": true + } + } + } + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_2020_12, else_false_1) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "if": { + "properties": { + "flag": { + "const": true + } + } + }, + "else": 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/2020-12/schema", + "properties": { + "flag": { + "const": true + } + } + })JSON"); + + EXPECT_EQ(document, expected); +} \ No newline at end of file diff --git a/test/alterschema/alterschema_lint_draft7_test.cc b/test/alterschema/alterschema_lint_draft7_test.cc index 3a4268637..03fd0aa32 100644 --- a/test/alterschema/alterschema_lint_draft7_test.cc +++ b/test/alterschema/alterschema_lint_draft7_test.cc @@ -1718,3 +1718,59 @@ TEST(AlterSchema_lint_draft7, property_names_default_1) { EXPECT_EQ(document, expected); } + +TEST(AlterSchema_lint_draft7, then_false_1) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "if": { + "properties": { + "flag": { + "const": true + } + } + }, + "then": 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#", + "not": { + "properties": { + "flag": { + "const": true + } + } + } + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_draft7, else_false_1) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "if": { + "properties": { + "flag": { + "const": true + } + } + }, + "else": 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#", + "properties": { + "flag": { + "const": true + } + } + })JSON"); + + EXPECT_EQ(document, expected); +} From 43690c08a9d1dd6373d2d78490ecdb78fe2cd1bc Mon Sep 17 00:00:00 2001 From: karan-palan Date: Mon, 28 Jul 2025 03:53:06 +0530 Subject: [PATCH 02/10] add empty line at end of test file Signed-off-by: karan-palan --- test/alterschema/alterschema_lint_2019_09_test.cc | 2 +- test/alterschema/alterschema_lint_2020_12_test.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/alterschema/alterschema_lint_2019_09_test.cc b/test/alterschema/alterschema_lint_2019_09_test.cc index fd73835fe..88df307f9 100644 --- a/test/alterschema/alterschema_lint_2019_09_test.cc +++ b/test/alterschema/alterschema_lint_2019_09_test.cc @@ -2349,4 +2349,4 @@ TEST(AlterSchema_lint_2019_09, else_false_1) { })JSON"); EXPECT_EQ(document, expected); -} \ No newline at end of file +} diff --git a/test/alterschema/alterschema_lint_2020_12_test.cc b/test/alterschema/alterschema_lint_2020_12_test.cc index ff95509fa..afe688506 100644 --- a/test/alterschema/alterschema_lint_2020_12_test.cc +++ b/test/alterschema/alterschema_lint_2020_12_test.cc @@ -2583,4 +2583,4 @@ TEST(AlterSchema_lint_2020_12, else_false_1) { })JSON"); EXPECT_EQ(document, expected); -} \ No newline at end of file +} From 8da87549903460a47a0742154caa941d0c242801 Mon Sep 17 00:00:00 2001 From: karan-palan Date: Mon, 28 Jul 2025 15:31:55 +0530 Subject: [PATCH 03/10] undo change in transformer to check if tests pass Signed-off-by: karan-palan --- src/core/jsonschema/transformer.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/jsonschema/transformer.cc b/src/core/jsonschema/transformer.cc index 20e98aab8..e79cc7be9 100644 --- a/src/core/jsonschema/transformer.cc +++ b/src/core/jsonschema/transformer.cc @@ -26,6 +26,7 @@ auto calculate_health_percentage(const std::size_t subschemas, -> std::uint8_t { assert(failed_subschemas <= subschemas); const auto result{100 - (failed_subschemas * 100 / subschemas)}; + assert(result >= 0); assert(result <= 100); return static_cast(result); } From 75df3aa76311f5b9714f934c6d217895f42d0f97 Mon Sep 17 00:00:00 2001 From: karan-palan Date: Thu, 7 Aug 2025 00:27:39 +0530 Subject: [PATCH 04/10] chore: remove then else false Signed-off-by: karan-palan --- src/extension/alterschema/CMakeLists.txt | 1 - src/extension/alterschema/alterschema.cc | 2 -- .../alterschema_lint_2019_09_test.cc | 29 ------------------- .../alterschema_lint_2020_12_test.cc | 29 ------------------- .../alterschema_lint_draft7_test.cc | 29 ------------------- 5 files changed, 90 deletions(-) diff --git a/src/extension/alterschema/CMakeLists.txt b/src/extension/alterschema/CMakeLists.txt index fa266bb9e..fa97c0d04 100644 --- a/src/extension/alterschema/CMakeLists.txt +++ b/src/extension/alterschema/CMakeLists.txt @@ -63,7 +63,6 @@ sourcemeta_library(NAMESPACE sourcemeta PROJECT core NAME alterschema linter/then_empty.h linter/else_empty.h linter/else_false.h - linter/then_false.h linter/then_without_if.h linter/property_names_type_default.h linter/property_names_default.h diff --git a/src/extension/alterschema/alterschema.cc b/src/extension/alterschema/alterschema.cc index 69a3baa49..4aec7366a 100644 --- a/src/extension/alterschema/alterschema.cc +++ b/src/extension/alterschema/alterschema.cc @@ -76,7 +76,6 @@ contains_any(const Vocabularies &container, #include "linter/property_names_type_default.h" #include "linter/single_type_array.h" #include "linter/then_empty.h" -#include "linter/then_false.h" #include "linter/then_without_if.h" #include "linter/unevaluated_items_default.h" #include "linter/unevaluated_properties_default.h" @@ -107,7 +106,6 @@ auto add(SchemaTransformer &bundle, const AlterSchemaMode mode) bundle.add(); bundle.add(); bundle.add(); - bundle.add(); bundle.add(); bundle.add(); bundle.add(); diff --git a/test/alterschema/alterschema_lint_2019_09_test.cc b/test/alterschema/alterschema_lint_2019_09_test.cc index 75749d827..78a19a666 100644 --- a/test/alterschema/alterschema_lint_2019_09_test.cc +++ b/test/alterschema/alterschema_lint_2019_09_test.cc @@ -2350,35 +2350,6 @@ TEST(AlterSchema_lint_2019_09, non_applicable_type_specific_keywords_3) { EXPECT_EQ(document, expected); } -TEST(AlterSchema_lint_2019_09, then_false_1) { - sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "if": { - "properties": { - "flag": { - "const": true - } - } - }, - "then": 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", - "not": { - "properties": { - "flag": { - "const": true - } - } - } - })JSON"); - - EXPECT_EQ(document, expected); -} - TEST(AlterSchema_lint_2019_09, else_false_1) { sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "https://json-schema.org/draft/2019-09/schema", diff --git a/test/alterschema/alterschema_lint_2020_12_test.cc b/test/alterschema/alterschema_lint_2020_12_test.cc index f73dee8dc..400b66cd9 100644 --- a/test/alterschema/alterschema_lint_2020_12_test.cc +++ b/test/alterschema/alterschema_lint_2020_12_test.cc @@ -2584,35 +2584,6 @@ TEST(AlterSchema_lint_2020_12, non_applicable_type_specific_keywords_3) { EXPECT_EQ(document, expected); } -TEST(AlterSchema_lint_2020_12, then_false_1) { - sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "if": { - "properties": { - "flag": { - "const": true - } - } - }, - "then": 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/2020-12/schema", - "not": { - "properties": { - "flag": { - "const": true - } - } - } - })JSON"); - - EXPECT_EQ(document, expected); -} - TEST(AlterSchema_lint_2020_12, else_false_1) { sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "https://json-schema.org/draft/2020-12/schema", diff --git a/test/alterschema/alterschema_lint_draft7_test.cc b/test/alterschema/alterschema_lint_draft7_test.cc index 2cee8fda0..34499e72c 100644 --- a/test/alterschema/alterschema_lint_draft7_test.cc +++ b/test/alterschema/alterschema_lint_draft7_test.cc @@ -1891,35 +1891,6 @@ TEST(AlterSchema_lint_draft7, non_applicable_type_specific_keywords_3) { EXPECT_EQ(document, expected); } -TEST(AlterSchema_lint_draft7, then_false_1) { - sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ - "$schema": "http://json-schema.org/draft-07/schema#", - "if": { - "properties": { - "flag": { - "const": true - } - } - }, - "then": 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#", - "not": { - "properties": { - "flag": { - "const": true - } - } - } - })JSON"); - - EXPECT_EQ(document, expected); -} - TEST(AlterSchema_lint_draft7, else_false_1) { sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "http://json-schema.org/draft-07/schema#", From 515f4e92d7ee6f9622ff47bd9cd90a567866b971 Mon Sep 17 00:00:00 2001 From: karan-palan Date: Thu, 7 Aug 2025 00:32:03 +0530 Subject: [PATCH 05/10] remove then_false Signed-off-by: karan-palan --- src/extension/alterschema/linter/then_false.h | 29 ------------------- 1 file changed, 29 deletions(-) delete mode 100644 src/extension/alterschema/linter/then_false.h diff --git a/src/extension/alterschema/linter/then_false.h b/src/extension/alterschema/linter/then_false.h deleted file mode 100644 index f8cc3e3a2..000000000 --- a/src/extension/alterschema/linter/then_false.h +++ /dev/null @@ -1,29 +0,0 @@ -class ThenFalse final : public SchemaTransformRule { -public: - ThenFalse() - : SchemaTransformRule{ - "then_false", - "`if: S, then: false` is logically equivalent to `not: S`"} {}; - - [[nodiscard]] auto - condition(const JSON &schema, const JSON &, const Vocabularies &vocabularies, - const SchemaFrame &, const SchemaFrame::Location &, - const SchemaWalker &, const SchemaResolver &) const - -> SchemaTransformRule::Result 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.at("then").is_boolean() && - !schema.at("then").to_boolean(); - } - - auto transform(JSON &schema) const -> void override { - const auto if_schema = schema.at("if"); - schema.erase("if"); - schema.erase("then"); - schema.assign("not", if_schema); - } -}; From da424069802534df73cb1c969f8342a3410e495f Mon Sep 17 00:00:00 2001 From: karan-palan Date: Thu, 7 Aug 2025 01:05:57 +0530 Subject: [PATCH 06/10] attempt to fix macos ci Signed-off-by: karan-palan --- src/extension/alterschema/linter/else_false.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/extension/alterschema/linter/else_false.h b/src/extension/alterschema/linter/else_false.h index a24d07ae0..74864d00c 100644 --- a/src/extension/alterschema/linter/else_false.h +++ b/src/extension/alterschema/linter/else_false.h @@ -30,9 +30,7 @@ class ElseFalse final : public SchemaTransformRule { } } } else if (if_schema.is_boolean()) { - if (if_schema.to_boolean()) { - } else { - } + schema = if_schema; } } }; From ebdaaa08b8695ac354a2fae1e3346b0a9e6a0120 Mon Sep 17 00:00:00 2001 From: karan-palan Date: Mon, 11 Aug 2025 10:58:30 +0530 Subject: [PATCH 07/10] check for then and add tests related to it Signed-off-by: karan-palan --- src/extension/alterschema/linter/else_false.h | 27 +++++--- .../alterschema_lint_2019_09_test.cc | 61 +++++++++++++++++++ .../alterschema_lint_2020_12_test.cc | 61 +++++++++++++++++++ .../alterschema_lint_draft7_test.cc | 61 +++++++++++++++++++ 4 files changed, 203 insertions(+), 7 deletions(-) diff --git a/src/extension/alterschema/linter/else_false.h b/src/extension/alterschema/linter/else_false.h index 74864d00c..d4bcf4e28 100644 --- a/src/extension/alterschema/linter/else_false.h +++ b/src/extension/alterschema/linter/else_false.h @@ -15,22 +15,35 @@ class ElseFalse final : public SchemaTransformRule { "https://json-schema.org/draft/2019-09/vocab/applicator", "http://json-schema.org/draft-07/schema#"}) && schema.is_object() && schema.defines("if") && - schema.defines("else") && schema.at("else").is_boolean() && - !schema.at("else").to_boolean(); + schema.defines("else") && is_schema(schema.at("else")) && + schema.at("else").is_boolean() && !schema.at("else").to_boolean() && + (!schema.defines("then") || + (schema.at("then").is_boolean() && schema.at("then").to_boolean())); } auto transform(JSON &schema) const -> void override { - const auto if_schema = schema.at("if"); + auto if_schema = schema.at("if"); schema.erase("if"); schema.erase("else"); + if (schema.defines("then")) { + schema.erase("then"); + } if (if_schema.is_object()) { - for (const auto &entry : if_schema.as_object()) { + for (auto &entry : if_schema.as_object()) { if (!schema.defines(entry.first)) { - schema.assign(entry.first, entry.second); + schema.assign(entry.first, std::move(entry.second)); } } - } else if (if_schema.is_boolean()) { - schema = if_schema; + } else if (if_schema.is_boolean() && !if_schema.to_boolean()) { + auto metadata = JSON::make_object(); + if (schema.defines("$schema")) { + metadata.assign("$schema", std::move(schema.at("$schema"))); + } + if (schema.defines("$id")) { + metadata.assign("$id", std::move(schema.at("$id"))); + } + schema = std::move(metadata); + schema.assign("not", JSON::make_object()); } } }; diff --git a/test/alterschema/alterschema_lint_2019_09_test.cc b/test/alterschema/alterschema_lint_2019_09_test.cc index 78a19a666..0a52594d5 100644 --- a/test/alterschema/alterschema_lint_2019_09_test.cc +++ b/test/alterschema/alterschema_lint_2019_09_test.cc @@ -2376,3 +2376,64 @@ TEST(AlterSchema_lint_2019_09, else_false_1) { EXPECT_EQ(document, expected); } + +TEST(AlterSchema_lint_2019_09, else_false_2) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "if": { + "properties": { + "flag": { + "const": true + } + } + }, + "then": true, + "else": 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", + "properties": { + "flag": { + "const": true + } + } + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_2019_09, else_false_3) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "if": true, + "else": 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, else_false_4) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "if": false, + "else": 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", + "not": {} + })JSON"); + + EXPECT_EQ(document, expected); +} diff --git a/test/alterschema/alterschema_lint_2020_12_test.cc b/test/alterschema/alterschema_lint_2020_12_test.cc index 400b66cd9..93dad0ed1 100644 --- a/test/alterschema/alterschema_lint_2020_12_test.cc +++ b/test/alterschema/alterschema_lint_2020_12_test.cc @@ -2610,3 +2610,64 @@ TEST(AlterSchema_lint_2020_12, else_false_1) { EXPECT_EQ(document, expected); } + +TEST(AlterSchema_lint_2020_12, else_false_2) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "if": { + "properties": { + "flag": { + "const": true + } + } + }, + "then": true, + "else": 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/2020-12/schema", + "properties": { + "flag": { + "const": true + } + } + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_2020_12, else_false_3) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "if": true, + "else": 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/2020-12/schema" + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_2020_12, else_false_4) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "if": false, + "else": 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/2020-12/schema", + "not": {} + })JSON"); + + EXPECT_EQ(document, expected); +} diff --git a/test/alterschema/alterschema_lint_draft7_test.cc b/test/alterschema/alterschema_lint_draft7_test.cc index 34499e72c..31ff9e4dd 100644 --- a/test/alterschema/alterschema_lint_draft7_test.cc +++ b/test/alterschema/alterschema_lint_draft7_test.cc @@ -1917,3 +1917,64 @@ TEST(AlterSchema_lint_draft7, else_false_1) { EXPECT_EQ(document, expected); } + +TEST(AlterSchema_lint_draft7, else_false_2) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "if": { + "properties": { + "flag": { + "const": true + } + } + }, + "then": true, + "else": 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#", + "properties": { + "flag": { + "const": true + } + } + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_draft7, else_false_3) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "if": true, + "else": 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, else_false_4) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "if": false, + "else": 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#", + "not": {} + })JSON"); + + EXPECT_EQ(document, expected); +} From a65eb14a474962cf1cfbe40bed9a10cee3f6f682 Mon Sep 17 00:00:00 2001 From: karan-palan Date: Mon, 11 Aug 2025 16:43:07 +0530 Subject: [PATCH 08/10] add more tests Signed-off-by: karan-palan --- src/extension/alterschema/linter/else_false.h | 38 ++++++--- .../alterschema_lint_2019_09_test.cc | 81 +++++++++++++++++++ .../alterschema_lint_2020_12_test.cc | 81 +++++++++++++++++++ .../alterschema_lint_draft7_test.cc | 81 +++++++++++++++++++ 4 files changed, 271 insertions(+), 10 deletions(-) diff --git a/src/extension/alterschema/linter/else_false.h b/src/extension/alterschema/linter/else_false.h index d4bcf4e28..3395a3d02 100644 --- a/src/extension/alterschema/linter/else_false.h +++ b/src/extension/alterschema/linter/else_false.h @@ -9,16 +9,34 @@ class ElseFalse final : public SchemaTransformRule { const SchemaFrame &, const SchemaFrame::Location &, const SchemaWalker &, const SchemaResolver &) const -> SchemaTransformRule::Result 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("else") && is_schema(schema.at("else")) && - schema.at("else").is_boolean() && !schema.at("else").to_boolean() && - (!schema.defines("then") || - (schema.at("then").is_boolean() && schema.at("then").to_boolean())); + if (!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#"})) { + return false; + } + + if (!schema.is_object() || !schema.defines("if") || + !schema.defines("else") || !is_schema(schema.at("else")) || + !schema.at("else").is_boolean() || schema.at("else").to_boolean() || + !is_schema(schema.at("if"))) { + return false; + } + + if (schema.defines("then") && + (!schema.at("then").is_boolean() || !schema.at("then").to_boolean())) { + return false; + } + + if (schema.at("if").is_object()) { + for (const auto &entry : schema.at("if").as_object()) { + if (schema.defines(entry.first)) { + return false; + } + } + } + + return true; } 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 0a52594d5..2e86f930f 100644 --- a/test/alterschema/alterschema_lint_2019_09_test.cc +++ b/test/alterschema/alterschema_lint_2019_09_test.cc @@ -2437,3 +2437,84 @@ TEST(AlterSchema_lint_2019_09, else_false_4) { EXPECT_EQ(document, expected); } + +TEST(AlterSchema_lint_2019_09, else_false_5) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "type": "object", + "properties": { + "name": { "type": "string" } + }, + "if": { + "properties": { + "name": { "type": "number" } + } + }, + "else": 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", + "type": "object", + "properties": { + "name": { "type": "string" } + }, + "if": { + "properties": { + "name": { "type": "number" } + } + }, + "else": false + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_2019_09, else_false_6) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "if": { + "properties": { + "flag": { "const": true } + } + }, + "else": 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", + "properties": { + "flag": { "const": true } + } + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_2019_09, else_false_7) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "if": { + "type": "object" + }, + "then": false, + "else": 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", + "if": { + "type": "object" + }, + "then": false, + "else": false + })JSON"); + + EXPECT_EQ(document, expected); +} diff --git a/test/alterschema/alterschema_lint_2020_12_test.cc b/test/alterschema/alterschema_lint_2020_12_test.cc index 93dad0ed1..13427a5d6 100644 --- a/test/alterschema/alterschema_lint_2020_12_test.cc +++ b/test/alterschema/alterschema_lint_2020_12_test.cc @@ -2671,3 +2671,84 @@ TEST(AlterSchema_lint_2020_12, else_false_4) { EXPECT_EQ(document, expected); } + +TEST(AlterSchema_lint_2020_12, else_false_5) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "name": { "type": "string" } + }, + "if": { + "properties": { + "name": { "type": "number" } + } + }, + "else": 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/2020-12/schema", + "type": "object", + "properties": { + "name": { "type": "string" } + }, + "if": { + "properties": { + "name": { "type": "number" } + } + }, + "else": false + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_2020_12, else_false_6) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "if": { + "properties": { + "flag": { "const": true } + } + }, + "else": 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/2020-12/schema", + "properties": { + "flag": { "const": true } + } + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_2020_12, else_false_7) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "if": { + "type": "object" + }, + "then": false, + "else": 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/2020-12/schema", + "if": { + "type": "object" + }, + "then": false, + "else": 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 31ff9e4dd..0a3645a67 100644 --- a/test/alterschema/alterschema_lint_draft7_test.cc +++ b/test/alterschema/alterschema_lint_draft7_test.cc @@ -1978,3 +1978,84 @@ TEST(AlterSchema_lint_draft7, else_false_4) { EXPECT_EQ(document, expected); } + +TEST(AlterSchema_lint_draft7, else_false_5) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "name": { "type": "string" } + }, + "if": { + "properties": { + "name": { "type": "number" } + } + }, + "else": 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#", + "type": "object", + "properties": { + "name": { "type": "string" } + }, + "if": { + "properties": { + "name": { "type": "number" } + } + }, + "else": false + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_draft7, else_false_6) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "if": { + "properties": { + "flag": { "const": true } + } + }, + "else": 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#", + "properties": { + "flag": { "const": true } + } + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_draft7, else_false_7) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "if": { + "type": "object" + }, + "then": false, + "else": 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#", + "if": { + "type": "object" + }, + "then": false, + "else": false + })JSON"); + + EXPECT_EQ(document, expected); +} From b0c7520b1b6e2df82c5157d2ca4e95ad82984913 Mon Sep 17 00:00:00 2001 From: karan-palan Date: Mon, 11 Aug 2025 17:12:13 +0530 Subject: [PATCH 09/10] attempt to fix ci Signed-off-by: karan-palan --- src/extension/alterschema/linter/else_false.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extension/alterschema/linter/else_false.h b/src/extension/alterschema/linter/else_false.h index 3395a3d02..0c3f4c697 100644 --- a/src/extension/alterschema/linter/else_false.h +++ b/src/extension/alterschema/linter/else_false.h @@ -49,7 +49,7 @@ class ElseFalse final : public SchemaTransformRule { if (if_schema.is_object()) { for (auto &entry : if_schema.as_object()) { if (!schema.defines(entry.first)) { - schema.assign(entry.first, std::move(entry.second)); + schema.assign(entry.first, entry.second); } } } else if (if_schema.is_boolean() && !if_schema.to_boolean()) { From ce704511b8a3ea19ebd69940fd97f69928433c36 Mon Sep 17 00:00:00 2001 From: karan-palan Date: Mon, 18 Aug 2025 17:03:57 +0530 Subject: [PATCH 10/10] chore: chain statements and add more tests Signed-off-by: karan-palan --- src/extension/alterschema/linter/else_false.h | 65 ++++++++----------- .../alterschema_lint_2019_09_test.cc | 52 +++++++++++++++ .../alterschema_lint_2020_12_test.cc | 52 +++++++++++++++ 3 files changed, 130 insertions(+), 39 deletions(-) diff --git a/src/extension/alterschema/linter/else_false.h b/src/extension/alterschema/linter/else_false.h index 0c3f4c697..a616fb083 100644 --- a/src/extension/alterschema/linter/else_false.h +++ b/src/extension/alterschema/linter/else_false.h @@ -9,56 +9,43 @@ class ElseFalse final : public SchemaTransformRule { const SchemaFrame &, const SchemaFrame::Location &, const SchemaWalker &, const SchemaResolver &) const -> SchemaTransformRule::Result override { - if (!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#"})) { - return false; - } - - if (!schema.is_object() || !schema.defines("if") || - !schema.defines("else") || !is_schema(schema.at("else")) || - !schema.at("else").is_boolean() || schema.at("else").to_boolean() || - !is_schema(schema.at("if"))) { - return false; - } - - if (schema.defines("then") && - (!schema.at("then").is_boolean() || !schema.at("then").to_boolean())) { - return false; - } - - if (schema.at("if").is_object()) { - for (const auto &entry : schema.at("if").as_object()) { - if (schema.defines(entry.first)) { - return false; - } - } - } - - return true; + 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("else") && is_schema(schema.at("else")) && + schema.at("else").is_boolean() && !schema.at("else").to_boolean() && + is_schema(schema.at("if")) && + (!schema.defines("then") || (schema.at("then").is_boolean() && + schema.at("then").to_boolean())) && + (!schema.at("if").is_object() || [&schema](const JSON &if_schema) { + for (const auto &entry : if_schema.as_object()) { + if (schema.defines(entry.first)) { + return false; + } + } + return true; + }(schema.at("if"))); } auto transform(JSON &schema) const -> void override { auto if_schema = schema.at("if"); schema.erase("if"); schema.erase("else"); - if (schema.defines("then")) { - schema.erase("then"); - } + schema.erase("then"); + if (if_schema.is_object()) { for (auto &entry : if_schema.as_object()) { - if (!schema.defines(entry.first)) { - schema.assign(entry.first, entry.second); - } + schema.assign(entry.first, entry.second); } } else if (if_schema.is_boolean() && !if_schema.to_boolean()) { auto metadata = JSON::make_object(); - if (schema.defines("$schema")) { - metadata.assign("$schema", std::move(schema.at("$schema"))); - } - if (schema.defines("$id")) { - metadata.assign("$id", std::move(schema.at("$id"))); + for (const auto &entry : schema.as_object()) { + if (entry.first.starts_with("$")) { + metadata.assign(entry.first, entry.second); + } } schema = std::move(metadata); schema.assign("not", JSON::make_object()); diff --git a/test/alterschema/alterschema_lint_2019_09_test.cc b/test/alterschema/alterschema_lint_2019_09_test.cc index 2e86f930f..d7037efae 100644 --- a/test/alterschema/alterschema_lint_2019_09_test.cc +++ b/test/alterschema/alterschema_lint_2019_09_test.cc @@ -2518,3 +2518,55 @@ TEST(AlterSchema_lint_2019_09, else_false_7) { EXPECT_EQ(document, expected); } + +TEST(AlterSchema_lint_2019_09, else_false_8) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "$id": "https://example.com/schema", + "$anchor": "root", + "$comment": "Test schema with metadata", + "if": false, + "else": 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", + "$id": "https://example.com/schema", + "$anchor": "root", + "$comment": "Test schema with metadata", + "not": {} + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_2019_09, else_false_9) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "$id": "https://example.com/complex", + "$anchor": "main", + "$ref": "#/$defs/base", + "$defs": { + "base": { "type": "string" } + }, + "if": false, + "else": 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", + "$id": "https://example.com/complex", + "$anchor": "main", + "$ref": "#/$defs/base", + "$defs": { + "base": { "type": "string" } + }, + "not": {} + })JSON"); + + EXPECT_EQ(document, expected); +} diff --git a/test/alterschema/alterschema_lint_2020_12_test.cc b/test/alterschema/alterschema_lint_2020_12_test.cc index 13427a5d6..c836f9d7e 100644 --- a/test/alterschema/alterschema_lint_2020_12_test.cc +++ b/test/alterschema/alterschema_lint_2020_12_test.cc @@ -2752,3 +2752,55 @@ TEST(AlterSchema_lint_2020_12, else_false_7) { EXPECT_EQ(document, expected); } + +TEST(AlterSchema_lint_2020_12, else_false_8) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://example.com/schema", + "$anchor": "root", + "$comment": "Test schema with metadata", + "if": false, + "else": 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/2020-12/schema", + "$id": "https://example.com/schema", + "$anchor": "root", + "$comment": "Test schema with metadata", + "not": {} + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_2020_12, else_false_9) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://example.com/complex", + "$anchor": "main", + "$ref": "#/$defs/base", + "$defs": { + "base": { "type": "string" } + }, + "if": false, + "else": 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/2020-12/schema", + "$id": "https://example.com/complex", + "$anchor": "main", + "$ref": "#/$defs/base", + "$defs": { + "base": { "type": "string" } + }, + "not": {} + })JSON"); + + EXPECT_EQ(document, expected); +}