diff --git a/src/linter/CMakeLists.txt b/src/linter/CMakeLists.txt index 49b36ee..2d37c86 100644 --- a/src/linter/CMakeLists.txt +++ b/src/linter/CMakeLists.txt @@ -29,6 +29,7 @@ noa_library(NAMESPACE sourcemeta PROJECT alterschema NAME linter redundant/else_without_if.h redundant/empty_dependencies.h redundant/empty_dependent_required.h + redundant/if_without_then_else.h redundant/items_array_default.h redundant/items_schema_default.h redundant/max_contains_without_contains.h diff --git a/src/linter/linter.cc b/src/linter/linter.cc index 7ce22f9..1dc9dfb 100644 --- a/src/linter/linter.cc +++ b/src/linter/linter.cc @@ -39,6 +39,7 @@ auto contains_any(const T &container, const T &values) -> bool { #include "redundant/else_without_if.h" #include "redundant/empty_dependencies.h" #include "redundant/empty_dependent_required.h" +#include "redundant/if_without_then_else.h" #include "redundant/items_array_default.h" #include "redundant/items_schema_default.h" #include "redundant/max_contains_without_contains.h" @@ -82,6 +83,7 @@ auto add(Bundle &bundle, const LinterCategory category) -> void { bundle.add(); bundle.add(); bundle.add(); + bundle.add(); bundle.add(); bundle.add(); bundle.add(); diff --git a/src/linter/redundant/if_without_then_else.h b/src/linter/redundant/if_without_then_else.h new file mode 100644 index 0000000..5a9735a --- /dev/null +++ b/src/linter/redundant/if_without_then_else.h @@ -0,0 +1,24 @@ +class IfWithoutThenElse final : public Rule { +public: + IfWithoutThenElse() + : Rule{"if_without_then_else", + "The `if` keyword is meaningless " + "without the presence of the `then` or `else` keywords"} {}; + + [[nodiscard]] auto + condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &, + const std::set &vocabularies, + const sourcemeta::jsontoolkit::Pointer &) const -> bool override { + return contains_any( + vocabularies, + {"https://json-schema.org/draft/2020-12/vocab/applicator", + "https://json-schema.org/draft/2019-09/vocab/applicator", + "http://json-schema.org/draft-07/schema#"}) && + schema.is_object() && schema.defines("if") && + !schema.defines("then") && !schema.defines("else"); + } + + auto transform(Transformer &transformer) const -> void override { + transformer.erase("if"); + } +}; diff --git a/test/linter/2019_09_test.cc b/test/linter/2019_09_test.cc index 939b004..59023e8 100644 --- a/test/linter/2019_09_test.cc +++ b/test/linter/2019_09_test.cc @@ -262,6 +262,23 @@ TEST(Lint_2019_09, else_without_if_2) { EXPECT_EQ(document, expected); } +TEST(Lint_2019_09, if_without_then_else_1) { + sourcemeta::jsontoolkit::JSON document = + sourcemeta::jsontoolkit::parse(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "if": true + })JSON"); + + LINT_AND_FIX(document); + + const sourcemeta::jsontoolkit::JSON expected = + sourcemeta::jsontoolkit::parse(R"JSON({ + "$schema": "https://json-schema.org/draft/2019-09/schema" + })JSON"); + + EXPECT_EQ(document, expected); +} + TEST(Lint_2019_09, unevaluated_properties_default_1) { sourcemeta::jsontoolkit::JSON document = sourcemeta::jsontoolkit::parse(R"JSON({ @@ -824,7 +841,7 @@ TEST(Lint_2019_09, dependent_required_tautology_2) { EXPECT_EQ(document, expected); } -TEST(Lint_2019_09, properties_default) { +TEST(Lint_2019_09, properties_default_1) { sourcemeta::jsontoolkit::JSON document = sourcemeta::jsontoolkit::parse(R"JSON({ "$schema": "https://json-schema.org/draft/2019-09/schema", @@ -841,7 +858,7 @@ TEST(Lint_2019_09, properties_default) { EXPECT_EQ(document, expected); } -TEST(Lint_2019_09, pattern_properties_default) { +TEST(Lint_2019_09, pattern_properties_default_1) { sourcemeta::jsontoolkit::JSON document = sourcemeta::jsontoolkit::parse(R"JSON({ "$schema": "https://json-schema.org/draft/2019-09/schema", diff --git a/test/linter/2020_12_test.cc b/test/linter/2020_12_test.cc index e19707d..3a54d5d 100644 --- a/test/linter/2020_12_test.cc +++ b/test/linter/2020_12_test.cc @@ -262,6 +262,23 @@ TEST(Lint_2020_12, else_without_if_2) { EXPECT_EQ(document, expected); } +TEST(Lint_2020_12, if_without_then_else_1) { + sourcemeta::jsontoolkit::JSON document = + sourcemeta::jsontoolkit::parse(R"JSON({ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "if": true + })JSON"); + + LINT_AND_FIX(document); + + const sourcemeta::jsontoolkit::JSON expected = + sourcemeta::jsontoolkit::parse(R"JSON({ + "$schema": "https://json-schema.org/draft/2020-12/schema" + })JSON"); + + EXPECT_EQ(document, expected); +} + TEST(Lint_2020_12, unevaluated_properties_default_1) { sourcemeta::jsontoolkit::JSON document = sourcemeta::jsontoolkit::parse(R"JSON({ @@ -807,7 +824,7 @@ TEST(Lint_2020_12, dependent_required_tautology_2) { EXPECT_EQ(document, expected); } -TEST(Lint_2020_12, properties_default) { +TEST(Lint_2020_12, properties_default_1) { sourcemeta::jsontoolkit::JSON document = sourcemeta::jsontoolkit::parse(R"JSON({ "$schema": "https://json-schema.org/draft/2020-12/schema", @@ -824,7 +841,7 @@ TEST(Lint_2020_12, properties_default) { EXPECT_EQ(document, expected); } -TEST(Lint_2020_12, pattern_properties_default) { +TEST(Lint_2020_12, pattern_properties_default_1) { sourcemeta::jsontoolkit::JSON document = sourcemeta::jsontoolkit::parse(R"JSON({ "$schema": "https://json-schema.org/draft/2020-12/schema", diff --git a/test/linter/draft1_test.cc b/test/linter/draft1_test.cc index af4eadf..f998732 100644 --- a/test/linter/draft1_test.cc +++ b/test/linter/draft1_test.cc @@ -220,7 +220,7 @@ TEST(Lint_draft1, minimum_real_for_integer_1) { EXPECT_EQ(document, expected); } -TEST(Lint_draft1, properties_default) { +TEST(Lint_draft1, properties_default_1) { sourcemeta::jsontoolkit::JSON document = sourcemeta::jsontoolkit::parse(R"JSON({ "$schema": "http://json-schema.org/draft-01/schema#", diff --git a/test/linter/draft2_test.cc b/test/linter/draft2_test.cc index 7aaf3d1..bcd989d 100644 --- a/test/linter/draft2_test.cc +++ b/test/linter/draft2_test.cc @@ -220,7 +220,7 @@ TEST(Lint_draft2, minimum_real_for_integer_1) { EXPECT_EQ(document, expected); } -TEST(Lint_draft2, properties_default) { +TEST(Lint_draft2, properties_default_1) { sourcemeta::jsontoolkit::JSON document = sourcemeta::jsontoolkit::parse(R"JSON({ "$schema": "http://json-schema.org/draft-02/schema#", diff --git a/test/linter/draft3_test.cc b/test/linter/draft3_test.cc index 3f85ab7..5f6676d 100644 --- a/test/linter/draft3_test.cc +++ b/test/linter/draft3_test.cc @@ -269,7 +269,7 @@ TEST(Lint_draft3, dependent_required_tautology_2) { EXPECT_EQ(document, expected); } -TEST(Lint_draft3, properties_default) { +TEST(Lint_draft3, properties_default_1) { sourcemeta::jsontoolkit::JSON document = sourcemeta::jsontoolkit::parse(R"JSON({ "$schema": "http://json-schema.org/draft-03/schema#", @@ -286,7 +286,7 @@ TEST(Lint_draft3, properties_default) { EXPECT_EQ(document, expected); } -TEST(Lint_draft3, pattern_properties_default) { +TEST(Lint_draft3, pattern_properties_default_1) { sourcemeta::jsontoolkit::JSON document = sourcemeta::jsontoolkit::parse(R"JSON({ "$schema": "http://json-schema.org/draft-03/schema#", diff --git a/test/linter/draft4_test.cc b/test/linter/draft4_test.cc index 6eebdd8..f2bcde5 100644 --- a/test/linter/draft4_test.cc +++ b/test/linter/draft4_test.cc @@ -323,7 +323,7 @@ TEST(Lint_draft4, dependent_required_tautology_2) { EXPECT_EQ(document, expected); } -TEST(Lint_draft4, properties_default) { +TEST(Lint_draft4, properties_default_1) { sourcemeta::jsontoolkit::JSON document = sourcemeta::jsontoolkit::parse(R"JSON({ "$schema": "http://json-schema.org/draft-04/schema#", @@ -340,7 +340,7 @@ TEST(Lint_draft4, properties_default) { EXPECT_EQ(document, expected); } -TEST(Lint_draft4, pattern_properties_default) { +TEST(Lint_draft4, pattern_properties_default_1) { sourcemeta::jsontoolkit::JSON document = sourcemeta::jsontoolkit::parse(R"JSON({ "$schema": "http://json-schema.org/draft-04/schema#", diff --git a/test/linter/draft6_test.cc b/test/linter/draft6_test.cc index 4456855..acfdbc2 100644 --- a/test/linter/draft6_test.cc +++ b/test/linter/draft6_test.cc @@ -474,7 +474,7 @@ TEST(Lint_draft6, dependent_required_tautology_2) { EXPECT_EQ(document, expected); } -TEST(Lint_draft6, properties_default) { +TEST(Lint_draft6, properties_default_1) { sourcemeta::jsontoolkit::JSON document = sourcemeta::jsontoolkit::parse(R"JSON({ "$schema": "http://json-schema.org/draft-06/schema#", @@ -491,7 +491,7 @@ TEST(Lint_draft6, properties_default) { EXPECT_EQ(document, expected); } -TEST(Lint_draft6, pattern_properties_default) { +TEST(Lint_draft6, pattern_properties_default_1) { sourcemeta::jsontoolkit::JSON document = sourcemeta::jsontoolkit::parse(R"JSON({ "$schema": "http://json-schema.org/draft-06/schema#", diff --git a/test/linter/draft7_test.cc b/test/linter/draft7_test.cc index 88d766f..b6b4a3f 100644 --- a/test/linter/draft7_test.cc +++ b/test/linter/draft7_test.cc @@ -169,6 +169,23 @@ TEST(Lint_draft7, else_without_if_2) { EXPECT_EQ(document, expected); } +TEST(Lint_draft7, if_without_then_else_1) { + sourcemeta::jsontoolkit::JSON document = + sourcemeta::jsontoolkit::parse(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#", + "if": true + })JSON"); + + LINT_AND_FIX(document); + + const sourcemeta::jsontoolkit::JSON expected = + sourcemeta::jsontoolkit::parse(R"JSON({ + "$schema": "http://json-schema.org/draft-07/schema#" + })JSON"); + + EXPECT_EQ(document, expected); +} + TEST(Lint_draft7, additional_properties_default_1) { sourcemeta::jsontoolkit::JSON document = sourcemeta::jsontoolkit::parse(R"JSON({ @@ -565,7 +582,7 @@ TEST(Lint_draft7, dependent_required_tautology_2) { EXPECT_EQ(document, expected); } -TEST(Lint_draft7, properties_default) { +TEST(Lint_draft7, properties_default_1) { sourcemeta::jsontoolkit::JSON document = sourcemeta::jsontoolkit::parse(R"JSON({ "$schema": "http://json-schema.org/draft-07/schema#", @@ -582,7 +599,7 @@ TEST(Lint_draft7, properties_default) { EXPECT_EQ(document, expected); } -TEST(Lint_draft7, pattern_properties_default) { +TEST(Lint_draft7, pattern_properties_default_1) { sourcemeta::jsontoolkit::JSON document = sourcemeta::jsontoolkit::parse(R"JSON({ "$schema": "http://json-schema.org/draft-07/schema#",