From d8c5e5dc581766a1f37fd16f3aae679b4e26e962 Mon Sep 17 00:00:00 2001 From: AcE Date: Tue, 10 Mar 2026 12:28:38 +0530 Subject: [PATCH 1/3] feat(linter): add const_and_enum_conflict rule Signed-off-by: AcE --- src/extension/alterschema/CMakeLists.txt | 1 + src/extension/alterschema/alterschema.cc | 2 + .../linter/const_and_enum_conflict.h | 29 ++++++++ .../alterschema_lint_2019_09_test.cc | 74 +++++++++++++++++++ .../alterschema_lint_2020_12_test.cc | 74 +++++++++++++++++++ .../alterschema_lint_draft6_test.cc | 74 +++++++++++++++++++ .../alterschema_lint_draft7_test.cc | 74 +++++++++++++++++++ 7 files changed, 328 insertions(+) create mode 100644 src/extension/alterschema/linter/const_and_enum_conflict.h diff --git a/src/extension/alterschema/CMakeLists.txt b/src/extension/alterschema/CMakeLists.txt index ee43cbbab..0bfaf06df 100644 --- a/src/extension/alterschema/CMakeLists.txt +++ b/src/extension/alterschema/CMakeLists.txt @@ -71,6 +71,7 @@ sourcemeta_library(NAMESPACE sourcemeta PROJECT core NAME alterschema # Linter linter/comment_trim.h + linter/const_and_enum_conflict.h linter/content_schema_default.h linter/definitions_to_defs.h linter/dependencies_default.h diff --git a/src/extension/alterschema/alterschema.cc b/src/extension/alterschema/alterschema.cc index 131b20c7b..82c0b0e22 100644 --- a/src/extension/alterschema/alterschema.cc +++ b/src/extension/alterschema/alterschema.cc @@ -99,6 +99,7 @@ inline auto APPLIES_TO_POINTERS(std::vector &&keywords) // Linter #include "linter/comment_trim.h" +#include "linter/const_and_enum_conflict.h" #include "linter/content_schema_default.h" #include "linter/definitions_to_defs.h" #include "linter/dependencies_default.h" @@ -207,6 +208,7 @@ auto add(SchemaTransformer &bundle, const AlterSchemaMode mode) -> void { if (mode == AlterSchemaMode::Linter) { bundle.add(); + bundle.add(); bundle.add(); bundle.add(); bundle.add(); diff --git a/src/extension/alterschema/linter/const_and_enum_conflict.h b/src/extension/alterschema/linter/const_and_enum_conflict.h new file mode 100644 index 000000000..c6f39a467 --- /dev/null +++ b/src/extension/alterschema/linter/const_and_enum_conflict.h @@ -0,0 +1,29 @@ +class ConstAndEnumConflict final : public SchemaTransformRule { +public: + using mutates = std::false_type; + using reframe_after_transform = std::false_type; + ConstAndEnumConflict() + : SchemaTransformRule{ + "const_and_enum_conflict", + "The `const` and `enum` keywords are mutually exclusive; " + "use one or the other, not both"} {}; + + [[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 { + ONLY_CONTINUE_IF(vocabularies.contains_any( + {Vocabularies::Known::JSON_Schema_2020_12_Validation, + Vocabularies::Known::JSON_Schema_2019_09_Validation, + Vocabularies::Known::JSON_Schema_Draft_7, + Vocabularies::Known::JSON_Schema_Draft_6}) && + schema.is_object() && schema.defines("const") && + schema.defines("enum")); + return APPLIES_TO_KEYWORDS("const", "enum"); + } +}; diff --git a/test/alterschema/alterschema_lint_2019_09_test.cc b/test/alterschema/alterschema_lint_2019_09_test.cc index b68b20641..55018b0a1 100644 --- a/test/alterschema/alterschema_lint_2019_09_test.cc +++ b/test/alterschema/alterschema_lint_2019_09_test.cc @@ -4494,3 +4494,77 @@ TEST(AlterSchema_lint_2019_09, empty_object_as_true_1) { EXPECT_EQ(document, expected); } + +TEST(AlterSchema_lint_2019_09, const_and_enum_conflict_1) { + const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "title": "Test", + "description": "Test description", + "examples": [ 1 ], + "const": 1, + "enum": [ 1, 2, 3 ] + })JSON"); + + LINT_WITHOUT_FIX(document, result, traces); + + EXPECT_FALSE(result.first); + EXPECT_EQ(traces.size(), 1); + EXPECT_LINT_TRACE(traces, 0, "", "const_and_enum_conflict", + "The `const` and `enum` keywords are mutually exclusive; " + "use one or the other, not both", + false); +} + +TEST(AlterSchema_lint_2019_09, const_and_enum_conflict_2) { + const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "title": "Test", + "description": "Test description", + "examples": [ 1 ], + "const": "foo" + })JSON"); + + LINT_WITHOUT_FIX(document, result, traces); + + EXPECT_TRUE(result.first); + EXPECT_EQ(traces.size(), 0); +} + +TEST(AlterSchema_lint_2019_09, const_and_enum_conflict_3) { + const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "title": "Test", + "description": "Test description", + "examples": [ 1 ], + "enum": [ 1, 2, 3 ] + })JSON"); + + LINT_WITHOUT_FIX(document, result, traces); + + EXPECT_TRUE(result.first); + EXPECT_EQ(traces.size(), 0); +} + +TEST(AlterSchema_lint_2019_09, const_and_enum_conflict_4) { + const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "title": "Test", + "description": "Test description", + "examples": [ {} ], + "properties": { + "foo": { + "const": 1, + "enum": [ 1, 2, 3 ] + } + } + })JSON"); + + LINT_WITHOUT_FIX(document, result, traces); + + EXPECT_FALSE(result.first); + EXPECT_EQ(traces.size(), 1); + EXPECT_LINT_TRACE(traces, 0, "/properties/foo", "const_and_enum_conflict", + "The `const` and `enum` keywords are mutually exclusive; " + "use one or the other, not both", + false); +} diff --git a/test/alterschema/alterschema_lint_2020_12_test.cc b/test/alterschema/alterschema_lint_2020_12_test.cc index ba496eff7..719e7703a 100644 --- a/test/alterschema/alterschema_lint_2020_12_test.cc +++ b/test/alterschema/alterschema_lint_2020_12_test.cc @@ -9664,3 +9664,77 @@ TEST(AlterSchema_lint_2020_12, object_oneof_required_not_required_6) { "can be elevated", true); } + +TEST(AlterSchema_lint_2020_12, const_and_enum_conflict_1) { + const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Test", + "description": "Test description", + "examples": [ 1 ], + "const": 1, + "enum": [ 1, 2, 3 ] + })JSON"); + + LINT_WITHOUT_FIX(document, result, traces); + + EXPECT_FALSE(result.first); + EXPECT_EQ(traces.size(), 1); + EXPECT_LINT_TRACE(traces, 0, "", "const_and_enum_conflict", + "The `const` and `enum` keywords are mutually exclusive; " + "use one or the other, not both", + false); +} + +TEST(AlterSchema_lint_2020_12, const_and_enum_conflict_2) { + const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Test", + "description": "Test description", + "examples": [ 1 ], + "const": "foo" + })JSON"); + + LINT_WITHOUT_FIX(document, result, traces); + + EXPECT_TRUE(result.first); + EXPECT_EQ(traces.size(), 0); +} + +TEST(AlterSchema_lint_2020_12, const_and_enum_conflict_3) { + const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Test", + "description": "Test description", + "examples": [ 1 ], + "enum": [ 1, 2, 3 ] + })JSON"); + + LINT_WITHOUT_FIX(document, result, traces); + + EXPECT_TRUE(result.first); + EXPECT_EQ(traces.size(), 0); +} + +TEST(AlterSchema_lint_2020_12, const_and_enum_conflict_4) { + const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Test", + "description": "Test description", + "examples": [ {} ], + "properties": { + "foo": { + "const": 1, + "enum": [ 1, 2, 3 ] + } + } + })JSON"); + + LINT_WITHOUT_FIX(document, result, traces); + + EXPECT_FALSE(result.first); + EXPECT_EQ(traces.size(), 1); + EXPECT_LINT_TRACE(traces, 0, "/properties/foo", "const_and_enum_conflict", + "The `const` and `enum` keywords are mutually exclusive; " + "use one or the other, not both", + false); +} diff --git a/test/alterschema/alterschema_lint_draft6_test.cc b/test/alterschema/alterschema_lint_draft6_test.cc index 6193d80bb..300a7788b 100644 --- a/test/alterschema/alterschema_lint_draft6_test.cc +++ b/test/alterschema/alterschema_lint_draft6_test.cc @@ -2929,3 +2929,77 @@ TEST(AlterSchema_lint_draft6, empty_object_as_true_1) { EXPECT_EQ(document, expected); } + +TEST(AlterSchema_lint_draft6, const_and_enum_conflict_1) { + const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-06/schema#", + "title": "Test", + "description": "Test description", + "examples": [ 1 ], + "const": 1, + "enum": [ 1, 2, 3 ] + })JSON"); + + LINT_WITHOUT_FIX(document, result, traces); + + EXPECT_FALSE(result.first); + EXPECT_EQ(traces.size(), 1); + EXPECT_LINT_TRACE(traces, 0, "", "const_and_enum_conflict", + "The `const` and `enum` keywords are mutually exclusive; " + "use one or the other, not both", + false); +} + +TEST(AlterSchema_lint_draft6, const_and_enum_conflict_2) { + const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-06/schema#", + "title": "Test", + "description": "Test description", + "examples": [ 1 ], + "const": "foo" + })JSON"); + + LINT_WITHOUT_FIX(document, result, traces); + + EXPECT_TRUE(result.first); + EXPECT_EQ(traces.size(), 0); +} + +TEST(AlterSchema_lint_draft6, const_and_enum_conflict_3) { + const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-06/schema#", + "title": "Test", + "description": "Test description", + "examples": [ 1 ], + "enum": [ 1, 2, 3 ] + })JSON"); + + LINT_WITHOUT_FIX(document, result, traces); + + EXPECT_TRUE(result.first); + EXPECT_EQ(traces.size(), 0); +} + +TEST(AlterSchema_lint_draft6, const_and_enum_conflict_4) { + const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-06/schema#", + "title": "Test", + "description": "Test description", + "examples": [ {} ], + "properties": { + "foo": { + "const": 1, + "enum": [ 1, 2, 3 ] + } + } + })JSON"); + + LINT_WITHOUT_FIX(document, result, traces); + + EXPECT_FALSE(result.first); + EXPECT_EQ(traces.size(), 1); + EXPECT_LINT_TRACE(traces, 0, "/properties/foo", "const_and_enum_conflict", + "The `const` and `enum` keywords are mutually exclusive; " + "use one or the other, not both", + false); +} diff --git a/test/alterschema/alterschema_lint_draft7_test.cc b/test/alterschema/alterschema_lint_draft7_test.cc index 14b0734c2..dc159b7f4 100644 --- a/test/alterschema/alterschema_lint_draft7_test.cc +++ b/test/alterschema/alterschema_lint_draft7_test.cc @@ -3507,3 +3507,77 @@ TEST(AlterSchema_lint_draft7, "illustrate the expected data", false); } + +TEST(AlterSchema_lint_draft7, const_and_enum_conflict_1) { + const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Test", + "description": "Test description", + "examples": [ 1 ], + "const": 1, + "enum": [ 1, 2, 3 ] + })JSON"); + + LINT_WITHOUT_FIX(document, result, traces); + + EXPECT_FALSE(result.first); + EXPECT_EQ(traces.size(), 1); + EXPECT_LINT_TRACE(traces, 0, "", "const_and_enum_conflict", + "The `const` and `enum` keywords are mutually exclusive; " + "use one or the other, not both", + false); +} + +TEST(AlterSchema_lint_draft7, const_and_enum_conflict_2) { + const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Test", + "description": "Test description", + "examples": [ 1 ], + "const": "foo" + })JSON"); + + LINT_WITHOUT_FIX(document, result, traces); + + EXPECT_TRUE(result.first); + EXPECT_EQ(traces.size(), 0); +} + +TEST(AlterSchema_lint_draft7, const_and_enum_conflict_3) { + const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Test", + "description": "Test description", + "examples": [ 1 ], + "enum": [ 1, 2, 3 ] + })JSON"); + + LINT_WITHOUT_FIX(document, result, traces); + + EXPECT_TRUE(result.first); + EXPECT_EQ(traces.size(), 0); +} + +TEST(AlterSchema_lint_draft7, const_and_enum_conflict_4) { + const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Test", + "description": "Test description", + "examples": [ {} ], + "properties": { + "foo": { + "const": 1, + "enum": [ 1, 2, 3 ] + } + } + })JSON"); + + LINT_WITHOUT_FIX(document, result, traces); + + EXPECT_FALSE(result.first); + EXPECT_EQ(traces.size(), 1); + EXPECT_LINT_TRACE(traces, 0, "/properties/foo", "const_and_enum_conflict", + "The `const` and `enum` keywords are mutually exclusive; " + "use one or the other, not both", + false); +} From 15b06059dfadb8cfc5f793e0b3c5e57ec5d7e6d5 Mon Sep 17 00:00:00 2001 From: AcE Date: Sat, 14 Mar 2026 08:57:14 +0530 Subject: [PATCH 2/3] feat(linter): split const/enum conflict rule and add edge case tests Signed-off-by: AcE --- src/extension/alterschema/CMakeLists.txt | 3 +- src/extension/alterschema/alterschema.cc | 6 +- .../alterschema/linter/const_in_enum.h | 34 ++++ ...nd_enum_conflict.h => const_not_in_enum.h} | 13 +- .../alterschema_lint_2019_09_test.cc | 159 +++++++++++++++--- .../alterschema_lint_2020_12_test.cc | 159 +++++++++++++++--- .../alterschema_lint_draft6_test.cc | 159 +++++++++++++++--- .../alterschema_lint_draft7_test.cc | 159 +++++++++++++++--- 8 files changed, 575 insertions(+), 117 deletions(-) create mode 100644 src/extension/alterschema/linter/const_in_enum.h rename src/extension/alterschema/linter/{const_and_enum_conflict.h => const_not_in_enum.h} (71%) diff --git a/src/extension/alterschema/CMakeLists.txt b/src/extension/alterschema/CMakeLists.txt index 0bfaf06df..d8ca0fd94 100644 --- a/src/extension/alterschema/CMakeLists.txt +++ b/src/extension/alterschema/CMakeLists.txt @@ -71,7 +71,8 @@ sourcemeta_library(NAMESPACE sourcemeta PROJECT core NAME alterschema # Linter linter/comment_trim.h - linter/const_and_enum_conflict.h + linter/const_in_enum.h + linter/const_not_in_enum.h linter/content_schema_default.h linter/definitions_to_defs.h linter/dependencies_default.h diff --git a/src/extension/alterschema/alterschema.cc b/src/extension/alterschema/alterschema.cc index 82c0b0e22..30e697aec 100644 --- a/src/extension/alterschema/alterschema.cc +++ b/src/extension/alterschema/alterschema.cc @@ -99,7 +99,8 @@ inline auto APPLIES_TO_POINTERS(std::vector &&keywords) // Linter #include "linter/comment_trim.h" -#include "linter/const_and_enum_conflict.h" +#include "linter/const_in_enum.h" +#include "linter/const_not_in_enum.h" #include "linter/content_schema_default.h" #include "linter/definitions_to_defs.h" #include "linter/dependencies_default.h" @@ -208,7 +209,8 @@ auto add(SchemaTransformer &bundle, const AlterSchemaMode mode) -> void { if (mode == AlterSchemaMode::Linter) { bundle.add(); - bundle.add(); + bundle.add(); + bundle.add(); bundle.add(); bundle.add(); bundle.add(); diff --git a/src/extension/alterschema/linter/const_in_enum.h b/src/extension/alterschema/linter/const_in_enum.h new file mode 100644 index 000000000..0161d8dc0 --- /dev/null +++ b/src/extension/alterschema/linter/const_in_enum.h @@ -0,0 +1,34 @@ +class ConstInEnum final : public SchemaTransformRule { +public: + using mutates = std::true_type; + using reframe_after_transform = std::true_type; + ConstInEnum() + : SchemaTransformRule{ + "const_in_enum", + "If the `const` and `enum` keyword overlap, then `enum` is " + "redundant and can be removed"} {}; + + [[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 { + ONLY_CONTINUE_IF(vocabularies.contains_any( + {Vocabularies::Known::JSON_Schema_2020_12_Validation, + Vocabularies::Known::JSON_Schema_2019_09_Validation, + Vocabularies::Known::JSON_Schema_Draft_7, + Vocabularies::Known::JSON_Schema_Draft_6}) && + schema.is_object() && schema.defines("const") && + schema.defines("enum") && schema.at("enum").is_array() && + schema.at("enum").contains(schema.at("const"))); + return APPLIES_TO_KEYWORDS("const", "enum"); + } + + auto transform(JSON &schema, const Result &) const -> void override { + schema.erase("enum"); + } +}; diff --git a/src/extension/alterschema/linter/const_and_enum_conflict.h b/src/extension/alterschema/linter/const_not_in_enum.h similarity index 71% rename from src/extension/alterschema/linter/const_and_enum_conflict.h rename to src/extension/alterschema/linter/const_not_in_enum.h index c6f39a467..4aff28f9e 100644 --- a/src/extension/alterschema/linter/const_and_enum_conflict.h +++ b/src/extension/alterschema/linter/const_not_in_enum.h @@ -1,12 +1,12 @@ -class ConstAndEnumConflict final : public SchemaTransformRule { +class ConstNotInEnum final : public SchemaTransformRule { public: using mutates = std::false_type; using reframe_after_transform = std::false_type; - ConstAndEnumConflict() + ConstNotInEnum() : SchemaTransformRule{ - "const_and_enum_conflict", - "The `const` and `enum` keywords are mutually exclusive; " - "use one or the other, not both"} {}; + "const_not_in_enum", + "Do not set the `const` and `enum` keyword at the same time, " + "mainly when their values diverge"} {}; [[nodiscard]] auto condition(const sourcemeta::core::JSON &schema, @@ -23,7 +23,8 @@ class ConstAndEnumConflict final : public SchemaTransformRule { Vocabularies::Known::JSON_Schema_Draft_7, Vocabularies::Known::JSON_Schema_Draft_6}) && schema.is_object() && schema.defines("const") && - schema.defines("enum")); + schema.defines("enum") && schema.at("enum").is_array() && + !schema.at("enum").contains(schema.at("const"))); return APPLIES_TO_KEYWORDS("const", "enum"); } }; diff --git a/test/alterschema/alterschema_lint_2019_09_test.cc b/test/alterschema/alterschema_lint_2019_09_test.cc index 55018b0a1..81863c7da 100644 --- a/test/alterschema/alterschema_lint_2019_09_test.cc +++ b/test/alterschema/alterschema_lint_2019_09_test.cc @@ -4495,66 +4495,171 @@ TEST(AlterSchema_lint_2019_09, empty_object_as_true_1) { EXPECT_EQ(document, expected); } -TEST(AlterSchema_lint_2019_09, const_and_enum_conflict_1) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ +TEST(AlterSchema_lint_2019_09, const_in_enum_1) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "https://json-schema.org/draft/2019-09/schema", "title": "Test", "description": "Test description", - "examples": [ 1 ], + "examples": [1], "const": 1, - "enum": [ 1, 2, 3 ] + "enum": [1, 2, 3] })JSON"); - LINT_WITHOUT_FIX(document, result, traces); + LINT_AND_FIX(document, result, traces); - EXPECT_FALSE(result.first); - EXPECT_EQ(traces.size(), 1); - EXPECT_LINT_TRACE(traces, 0, "", "const_and_enum_conflict", - "The `const` and `enum` keywords are mutually exclusive; " - "use one or the other, not both", - false); + EXPECT_TRUE(result.first); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "title": "Test", + "description": "Test description", + "examples": [1], + "const": 1 + })JSON"); + + EXPECT_EQ(document, expected); } -TEST(AlterSchema_lint_2019_09, const_and_enum_conflict_2) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ +TEST(AlterSchema_lint_2019_09, const_without_enum) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "https://json-schema.org/draft/2019-09/schema", "title": "Test", "description": "Test description", - "examples": [ 1 ], + "examples": [1], "const": "foo" })JSON"); - LINT_WITHOUT_FIX(document, result, traces); + LINT_AND_FIX(document, result, traces); EXPECT_TRUE(result.first); - EXPECT_EQ(traces.size(), 0); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "title": "Test", + "description": "Test description", + "examples": [1], + "const": "foo" + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_2019_09, enum_without_const) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "title": "Test", + "description": "Test description", + "examples": [1], + "enum": [1, 2, 3] + })JSON"); + + LINT_AND_FIX(document, result, traces); + + EXPECT_TRUE(result.first); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "title": "Test", + "description": "Test description", + "examples": [1], + "enum": [1, 2, 3] + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_2019_09, const_in_enum_4) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "title": "Test", + "description": "Test description", + "examples": [{}], + "properties": { + "foo": { + "const": 1, + "enum": [1, 2, 3] + } + } + })JSON"); + + LINT_AND_FIX(document, result, traces); + + EXPECT_TRUE(result.first); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "title": "Test", + "description": "Test description", + "examples": [{}], + "properties": { + "foo": { + "const": 1 + } + } + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_2019_09, const_in_enum_edge_case_preserves_siblings) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "$id": "https://example.com/schemas/my-schema", + "description": "Edge case schema", + "examples": [{}], + "title": "Edge Case Schema", + "x-custom-annotation": "should not be deleted", + "const": 1, + "enum": [1, 2, 3] + })JSON"); + + LINT_AND_FIX(document, result, traces); + + EXPECT_TRUE(result.first); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "$id": "https://example.com/schemas/my-schema", + "description": "Edge case schema", + "examples": [{}], + "title": "Edge Case Schema", + "x-custom-annotation": "should not be deleted", + "const": 1 + })JSON"); + + EXPECT_EQ(document, expected); } -TEST(AlterSchema_lint_2019_09, const_and_enum_conflict_3) { +TEST(AlterSchema_lint_2019_09, const_not_in_enum_1) { const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "https://json-schema.org/draft/2019-09/schema", "title": "Test", "description": "Test description", - "examples": [ 1 ], - "enum": [ 1, 2, 3 ] + "examples": [1], + "const": 1, + "enum": [2, 3] })JSON"); LINT_WITHOUT_FIX(document, result, traces); - EXPECT_TRUE(result.first); - EXPECT_EQ(traces.size(), 0); + EXPECT_FALSE(result.first); + EXPECT_EQ(traces.size(), 1); + EXPECT_LINT_TRACE(traces, 0, "", "const_not_in_enum", + "Do not set the `const` and `enum` keyword at the same " + "time, mainly when their values diverge", + false); } -TEST(AlterSchema_lint_2019_09, const_and_enum_conflict_4) { +TEST(AlterSchema_lint_2019_09, const_not_in_enum_2) { const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "https://json-schema.org/draft/2019-09/schema", "title": "Test", "description": "Test description", - "examples": [ {} ], + "examples": [{}], "properties": { "foo": { "const": 1, - "enum": [ 1, 2, 3 ] + "enum": [2, 3] } } })JSON"); @@ -4563,8 +4668,8 @@ TEST(AlterSchema_lint_2019_09, const_and_enum_conflict_4) { EXPECT_FALSE(result.first); EXPECT_EQ(traces.size(), 1); - EXPECT_LINT_TRACE(traces, 0, "/properties/foo", "const_and_enum_conflict", - "The `const` and `enum` keywords are mutually exclusive; " - "use one or the other, not both", + EXPECT_LINT_TRACE(traces, 0, "/properties/foo", "const_not_in_enum", + "Do not set the `const` and `enum` keyword at the same " + "time, mainly when their values diverge", false); } diff --git a/test/alterschema/alterschema_lint_2020_12_test.cc b/test/alterschema/alterschema_lint_2020_12_test.cc index 719e7703a..0d99b32c9 100644 --- a/test/alterschema/alterschema_lint_2020_12_test.cc +++ b/test/alterschema/alterschema_lint_2020_12_test.cc @@ -9665,66 +9665,171 @@ TEST(AlterSchema_lint_2020_12, object_oneof_required_not_required_6) { true); } -TEST(AlterSchema_lint_2020_12, const_and_enum_conflict_1) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ +TEST(AlterSchema_lint_2020_12, const_in_enum_1) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "Test", "description": "Test description", - "examples": [ 1 ], + "examples": [1], "const": 1, - "enum": [ 1, 2, 3 ] + "enum": [1, 2, 3] })JSON"); - LINT_WITHOUT_FIX(document, result, traces); + LINT_AND_FIX(document, result, traces); - EXPECT_FALSE(result.first); - EXPECT_EQ(traces.size(), 1); - EXPECT_LINT_TRACE(traces, 0, "", "const_and_enum_conflict", - "The `const` and `enum` keywords are mutually exclusive; " - "use one or the other, not both", - false); + EXPECT_TRUE(result.first); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Test", + "description": "Test description", + "examples": [1], + "const": 1 + })JSON"); + + EXPECT_EQ(document, expected); } -TEST(AlterSchema_lint_2020_12, const_and_enum_conflict_2) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ +TEST(AlterSchema_lint_2020_12, const_without_enum) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "Test", "description": "Test description", - "examples": [ 1 ], + "examples": [1], "const": "foo" })JSON"); - LINT_WITHOUT_FIX(document, result, traces); + LINT_AND_FIX(document, result, traces); EXPECT_TRUE(result.first); - EXPECT_EQ(traces.size(), 0); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Test", + "description": "Test description", + "examples": [1], + "const": "foo" + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_2020_12, enum_without_const) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Test", + "description": "Test description", + "examples": [1], + "enum": [1, 2, 3] + })JSON"); + + LINT_AND_FIX(document, result, traces); + + EXPECT_TRUE(result.first); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Test", + "description": "Test description", + "examples": [1], + "enum": [1, 2, 3] + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_2020_12, const_in_enum_4) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Test", + "description": "Test description", + "examples": [{}], + "properties": { + "foo": { + "const": 1, + "enum": [1, 2, 3] + } + } + })JSON"); + + LINT_AND_FIX(document, result, traces); + + EXPECT_TRUE(result.first); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Test", + "description": "Test description", + "examples": [{}], + "properties": { + "foo": { + "const": 1 + } + } + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_2020_12, const_in_enum_edge_case_preserves_siblings) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://example.com/schemas/my-schema", + "description": "Edge case schema", + "examples": [{}], + "title": "Edge Case Schema", + "x-custom-annotation": "should not be deleted", + "const": 1, + "enum": [1, 2, 3] + })JSON"); + + LINT_AND_FIX(document, result, traces); + + EXPECT_TRUE(result.first); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://example.com/schemas/my-schema", + "description": "Edge case schema", + "examples": [{}], + "title": "Edge Case Schema", + "x-custom-annotation": "should not be deleted", + "const": 1 + })JSON"); + + EXPECT_EQ(document, expected); } -TEST(AlterSchema_lint_2020_12, const_and_enum_conflict_3) { +TEST(AlterSchema_lint_2020_12, const_not_in_enum_1) { const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "Test", "description": "Test description", - "examples": [ 1 ], - "enum": [ 1, 2, 3 ] + "examples": [1], + "const": 1, + "enum": [2, 3] })JSON"); LINT_WITHOUT_FIX(document, result, traces); - EXPECT_TRUE(result.first); - EXPECT_EQ(traces.size(), 0); + EXPECT_FALSE(result.first); + EXPECT_EQ(traces.size(), 1); + EXPECT_LINT_TRACE(traces, 0, "", "const_not_in_enum", + "Do not set the `const` and `enum` keyword at the same " + "time, mainly when their values diverge", + false); } -TEST(AlterSchema_lint_2020_12, const_and_enum_conflict_4) { +TEST(AlterSchema_lint_2020_12, const_not_in_enum_2) { const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "Test", "description": "Test description", - "examples": [ {} ], + "examples": [{}], "properties": { "foo": { "const": 1, - "enum": [ 1, 2, 3 ] + "enum": [2, 3] } } })JSON"); @@ -9733,8 +9838,8 @@ TEST(AlterSchema_lint_2020_12, const_and_enum_conflict_4) { EXPECT_FALSE(result.first); EXPECT_EQ(traces.size(), 1); - EXPECT_LINT_TRACE(traces, 0, "/properties/foo", "const_and_enum_conflict", - "The `const` and `enum` keywords are mutually exclusive; " - "use one or the other, not both", + EXPECT_LINT_TRACE(traces, 0, "/properties/foo", "const_not_in_enum", + "Do not set the `const` and `enum` keyword at the same " + "time, mainly when their values diverge", false); } diff --git a/test/alterschema/alterschema_lint_draft6_test.cc b/test/alterschema/alterschema_lint_draft6_test.cc index 300a7788b..b83ee9909 100644 --- a/test/alterschema/alterschema_lint_draft6_test.cc +++ b/test/alterschema/alterschema_lint_draft6_test.cc @@ -2930,66 +2930,171 @@ TEST(AlterSchema_lint_draft6, empty_object_as_true_1) { EXPECT_EQ(document, expected); } -TEST(AlterSchema_lint_draft6, const_and_enum_conflict_1) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ +TEST(AlterSchema_lint_draft6, const_in_enum_1) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "http://json-schema.org/draft-06/schema#", "title": "Test", "description": "Test description", - "examples": [ 1 ], + "examples": [1], "const": 1, - "enum": [ 1, 2, 3 ] + "enum": [1, 2, 3] })JSON"); - LINT_WITHOUT_FIX(document, result, traces); + LINT_AND_FIX(document, result, traces); - EXPECT_FALSE(result.first); - EXPECT_EQ(traces.size(), 1); - EXPECT_LINT_TRACE(traces, 0, "", "const_and_enum_conflict", - "The `const` and `enum` keywords are mutually exclusive; " - "use one or the other, not both", - false); + EXPECT_TRUE(result.first); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-06/schema#", + "title": "Test", + "description": "Test description", + "examples": [1], + "const": 1 + })JSON"); + + EXPECT_EQ(document, expected); } -TEST(AlterSchema_lint_draft6, const_and_enum_conflict_2) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ +TEST(AlterSchema_lint_draft6, const_without_enum) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "http://json-schema.org/draft-06/schema#", "title": "Test", "description": "Test description", - "examples": [ 1 ], + "examples": [1], "const": "foo" })JSON"); - LINT_WITHOUT_FIX(document, result, traces); + LINT_AND_FIX(document, result, traces); EXPECT_TRUE(result.first); - EXPECT_EQ(traces.size(), 0); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-06/schema#", + "title": "Test", + "description": "Test description", + "examples": [1], + "const": "foo" + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_draft6, enum_without_const) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-06/schema#", + "title": "Test", + "description": "Test description", + "examples": [1], + "enum": [1, 2, 3] + })JSON"); + + LINT_AND_FIX(document, result, traces); + + EXPECT_TRUE(result.first); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-06/schema#", + "title": "Test", + "description": "Test description", + "examples": [1], + "enum": [1, 2, 3] + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_draft6, const_in_enum_4) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-06/schema#", + "title": "Test", + "description": "Test description", + "examples": [{}], + "properties": { + "foo": { + "const": 1, + "enum": [1, 2, 3] + } + } + })JSON"); + + LINT_AND_FIX(document, result, traces); + + EXPECT_TRUE(result.first); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-06/schema#", + "title": "Test", + "description": "Test description", + "examples": [{}], + "properties": { + "foo": { + "const": 1 + } + } + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_draft6, const_in_enum_edge_case_preserves_siblings) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-06/schema#", + "$id": "https://example.com/schemas/my-schema", + "description": "Edge case schema", + "examples": [{}], + "title": "Edge Case Schema", + "x-custom-annotation": "should not be deleted", + "const": 1, + "enum": [1, 2, 3] + })JSON"); + + LINT_AND_FIX(document, result, traces); + + EXPECT_TRUE(result.first); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-06/schema#", + "$id": "https://example.com/schemas/my-schema", + "description": "Edge case schema", + "examples": [{}], + "title": "Edge Case Schema", + "x-custom-annotation": "should not be deleted", + "const": 1 + })JSON"); + + EXPECT_EQ(document, expected); } -TEST(AlterSchema_lint_draft6, const_and_enum_conflict_3) { +TEST(AlterSchema_lint_draft6, const_not_in_enum_1) { const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "http://json-schema.org/draft-06/schema#", "title": "Test", "description": "Test description", - "examples": [ 1 ], - "enum": [ 1, 2, 3 ] + "examples": [1], + "const": 1, + "enum": [2, 3] })JSON"); LINT_WITHOUT_FIX(document, result, traces); - EXPECT_TRUE(result.first); - EXPECT_EQ(traces.size(), 0); + EXPECT_FALSE(result.first); + EXPECT_EQ(traces.size(), 1); + EXPECT_LINT_TRACE(traces, 0, "", "const_not_in_enum", + "Do not set the `const` and `enum` keyword at the same " + "time, mainly when their values diverge", + false); } -TEST(AlterSchema_lint_draft6, const_and_enum_conflict_4) { +TEST(AlterSchema_lint_draft6, const_not_in_enum_2) { const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "http://json-schema.org/draft-06/schema#", "title": "Test", "description": "Test description", - "examples": [ {} ], + "examples": [{}], "properties": { "foo": { "const": 1, - "enum": [ 1, 2, 3 ] + "enum": [2, 3] } } })JSON"); @@ -2998,8 +3103,8 @@ TEST(AlterSchema_lint_draft6, const_and_enum_conflict_4) { EXPECT_FALSE(result.first); EXPECT_EQ(traces.size(), 1); - EXPECT_LINT_TRACE(traces, 0, "/properties/foo", "const_and_enum_conflict", - "The `const` and `enum` keywords are mutually exclusive; " - "use one or the other, not both", + EXPECT_LINT_TRACE(traces, 0, "/properties/foo", "const_not_in_enum", + "Do not set the `const` and `enum` keyword at the same " + "time, mainly when their values diverge", false); } diff --git a/test/alterschema/alterschema_lint_draft7_test.cc b/test/alterschema/alterschema_lint_draft7_test.cc index dc159b7f4..434573a5f 100644 --- a/test/alterschema/alterschema_lint_draft7_test.cc +++ b/test/alterschema/alterschema_lint_draft7_test.cc @@ -3508,66 +3508,171 @@ TEST(AlterSchema_lint_draft7, false); } -TEST(AlterSchema_lint_draft7, const_and_enum_conflict_1) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ +TEST(AlterSchema_lint_draft7, const_in_enum_1) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "http://json-schema.org/draft-07/schema#", "title": "Test", "description": "Test description", - "examples": [ 1 ], + "examples": [1], "const": 1, - "enum": [ 1, 2, 3 ] + "enum": [1, 2, 3] })JSON"); - LINT_WITHOUT_FIX(document, result, traces); + LINT_AND_FIX(document, result, traces); - EXPECT_FALSE(result.first); - EXPECT_EQ(traces.size(), 1); - EXPECT_LINT_TRACE(traces, 0, "", "const_and_enum_conflict", - "The `const` and `enum` keywords are mutually exclusive; " - "use one or the other, not both", - false); + EXPECT_TRUE(result.first); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Test", + "description": "Test description", + "examples": [1], + "const": 1 + })JSON"); + + EXPECT_EQ(document, expected); } -TEST(AlterSchema_lint_draft7, const_and_enum_conflict_2) { - const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ +TEST(AlterSchema_lint_draft7, const_without_enum) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "http://json-schema.org/draft-07/schema#", "title": "Test", "description": "Test description", - "examples": [ 1 ], + "examples": [1], "const": "foo" })JSON"); - LINT_WITHOUT_FIX(document, result, traces); + LINT_AND_FIX(document, result, traces); EXPECT_TRUE(result.first); - EXPECT_EQ(traces.size(), 0); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Test", + "description": "Test description", + "examples": [1], + "const": "foo" + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_draft7, enum_without_const) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Test", + "description": "Test description", + "examples": [1], + "enum": [1, 2, 3] + })JSON"); + + LINT_AND_FIX(document, result, traces); + + EXPECT_TRUE(result.first); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Test", + "description": "Test description", + "examples": [1], + "enum": [1, 2, 3] + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_draft7, const_in_enum_4) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Test", + "description": "Test description", + "examples": [{}], + "properties": { + "foo": { + "const": 1, + "enum": [1, 2, 3] + } + } + })JSON"); + + LINT_AND_FIX(document, result, traces); + + EXPECT_TRUE(result.first); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Test", + "description": "Test description", + "examples": [{}], + "properties": { + "foo": { + "const": 1 + } + } + })JSON"); + + EXPECT_EQ(document, expected); +} + +TEST(AlterSchema_lint_draft7, const_in_enum_edge_case_preserves_siblings) { + sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://example.com/schemas/my-schema", + "description": "Edge case schema", + "examples": [{}], + "title": "Edge Case Schema", + "x-custom-annotation": "should not be deleted", + "const": 1, + "enum": [1, 2, 3] + })JSON"); + + LINT_AND_FIX(document, result, traces); + + EXPECT_TRUE(result.first); + + const sourcemeta::core::JSON expected = sourcemeta::core::parse_json(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "https://example.com/schemas/my-schema", + "description": "Edge case schema", + "examples": [{}], + "title": "Edge Case Schema", + "x-custom-annotation": "should not be deleted", + "const": 1 + })JSON"); + + EXPECT_EQ(document, expected); } -TEST(AlterSchema_lint_draft7, const_and_enum_conflict_3) { +TEST(AlterSchema_lint_draft7, const_not_in_enum_1) { const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "http://json-schema.org/draft-07/schema#", "title": "Test", "description": "Test description", - "examples": [ 1 ], - "enum": [ 1, 2, 3 ] + "examples": [1], + "const": 1, + "enum": [2, 3] })JSON"); LINT_WITHOUT_FIX(document, result, traces); - EXPECT_TRUE(result.first); - EXPECT_EQ(traces.size(), 0); + EXPECT_FALSE(result.first); + EXPECT_EQ(traces.size(), 1); + EXPECT_LINT_TRACE(traces, 0, "", "const_not_in_enum", + "Do not set the `const` and `enum` keyword at the same " + "time, mainly when their values diverge", + false); } -TEST(AlterSchema_lint_draft7, const_and_enum_conflict_4) { +TEST(AlterSchema_lint_draft7, const_not_in_enum_2) { const sourcemeta::core::JSON document = sourcemeta::core::parse_json(R"JSON({ "$schema": "http://json-schema.org/draft-07/schema#", "title": "Test", "description": "Test description", - "examples": [ {} ], + "examples": [{}], "properties": { "foo": { "const": 1, - "enum": [ 1, 2, 3 ] + "enum": [2, 3] } } })JSON"); @@ -3576,8 +3681,8 @@ TEST(AlterSchema_lint_draft7, const_and_enum_conflict_4) { EXPECT_FALSE(result.first); EXPECT_EQ(traces.size(), 1); - EXPECT_LINT_TRACE(traces, 0, "/properties/foo", "const_and_enum_conflict", - "The `const` and `enum` keywords are mutually exclusive; " - "use one or the other, not both", + EXPECT_LINT_TRACE(traces, 0, "/properties/foo", "const_not_in_enum", + "Do not set the `const` and `enum` keyword at the same " + "time, mainly when their values diverge", false); } From d985399db3a53bd20b4aa3f399a562f9ff783761 Mon Sep 17 00:00:00 2001 From: AcE Date: Tue, 17 Mar 2026 21:49:16 +0530 Subject: [PATCH 3/3] refactor(alterschema): move const_in_enum to common Signed-off-by: AcE --- src/extension/alterschema/CMakeLists.txt | 2 +- src/extension/alterschema/alterschema.cc | 4 ++-- src/extension/alterschema/{linter => common}/const_in_enum.h | 0 3 files changed, 3 insertions(+), 3 deletions(-) rename src/extension/alterschema/{linter => common}/const_in_enum.h (100%) diff --git a/src/extension/alterschema/CMakeLists.txt b/src/extension/alterschema/CMakeLists.txt index d8ca0fd94..3d3c88df9 100644 --- a/src/extension/alterschema/CMakeLists.txt +++ b/src/extension/alterschema/CMakeLists.txt @@ -24,6 +24,7 @@ sourcemeta_library(NAMESPACE sourcemeta PROJECT core NAME alterschema common/anyof_false_simplify.h common/anyof_remove_false_schemas.h common/anyof_true_simplify.h + common/const_in_enum.h common/const_with_type.h common/orphan_definitions.h common/content_media_type_without_encoding.h @@ -71,7 +72,6 @@ sourcemeta_library(NAMESPACE sourcemeta PROJECT core NAME alterschema # Linter linter/comment_trim.h - linter/const_in_enum.h linter/const_not_in_enum.h linter/content_schema_default.h linter/definitions_to_defs.h diff --git a/src/extension/alterschema/alterschema.cc b/src/extension/alterschema/alterschema.cc index 30e697aec..be4bf3ba9 100644 --- a/src/extension/alterschema/alterschema.cc +++ b/src/extension/alterschema/alterschema.cc @@ -52,6 +52,7 @@ inline auto APPLIES_TO_POINTERS(std::vector &&keywords) #include "common/anyof_false_simplify.h" #include "common/anyof_remove_false_schemas.h" #include "common/anyof_true_simplify.h" +#include "common/const_in_enum.h" #include "common/const_with_type.h" #include "common/content_media_type_without_encoding.h" #include "common/content_schema_without_media_type.h" @@ -99,7 +100,6 @@ inline auto APPLIES_TO_POINTERS(std::vector &&keywords) // Linter #include "linter/comment_trim.h" -#include "linter/const_in_enum.h" #include "linter/const_not_in_enum.h" #include "linter/content_schema_default.h" #include "linter/definitions_to_defs.h" @@ -178,6 +178,7 @@ auto add(SchemaTransformer &bundle, const AlterSchemaMode mode) -> void { bundle.add(); bundle.add(); bundle.add(); + bundle.add(); bundle.add(); bundle.add(); bundle.add(); @@ -209,7 +210,6 @@ auto add(SchemaTransformer &bundle, const AlterSchemaMode mode) -> void { if (mode == AlterSchemaMode::Linter) { bundle.add(); - bundle.add(); bundle.add(); bundle.add(); bundle.add(); diff --git a/src/extension/alterschema/linter/const_in_enum.h b/src/extension/alterschema/common/const_in_enum.h similarity index 100% rename from src/extension/alterschema/linter/const_in_enum.h rename to src/extension/alterschema/common/const_in_enum.h