Skip to content

Commit

Permalink
Simplify equal numeric bounds to enum/const (#232)
Browse files Browse the repository at this point in the history
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
  • Loading branch information
jviotti authored Sep 11, 2024
1 parent 3bb509b commit 361377e
Show file tree
Hide file tree
Showing 11 changed files with 364 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/linter/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ noa_library(NAMESPACE sourcemeta PROJECT alterschema NAME linter
# Simplify
simplify/dependencies_property_tautology.h
simplify/dependent_required_tautology.h
simplify/equal_numeric_bounds_to_enum.h
simplify/maximum_real_for_integer.h
simplify/minimum_real_for_integer.h
simplify/single_type_array.h
Expand Down
2 changes: 2 additions & 0 deletions src/linter/linter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ template <typename T> auto every_item_is_boolean(const T &container) -> bool {
// Simplify
#include "simplify/dependencies_property_tautology.h"
#include "simplify/dependent_required_tautology.h"
#include "simplify/equal_numeric_bounds_to_enum.h"
#include "simplify/maximum_real_for_integer.h"
#include "simplify/minimum_real_for_integer.h"
#include "simplify/single_type_array.h"
Expand Down Expand Up @@ -189,6 +190,7 @@ auto add(Bundle &bundle, const LinterCategory category) -> void {
case LinterCategory::Simplify:
bundle.add<DependenciesPropertyTautology>();
bundle.add<DependentRequiredTautology>();
bundle.add<EqualNumericBoundsToEnum>();
bundle.add<MaximumRealForInteger>();
bundle.add<MinimumRealForInteger>();
bundle.add<SingleTypeArray>();
Expand Down
41 changes: 41 additions & 0 deletions src/linter/simplify/equal_numeric_bounds_to_enum.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
class EqualNumericBoundsToEnum final : public Rule {
public:
EqualNumericBoundsToEnum()
: Rule{"equal_numeric_bounds_to_enum",
"Setting `minimum` and `maximum` to the same number only leaves "
"one possible value"} {};

[[nodiscard]] auto
condition(const sourcemeta::jsontoolkit::JSON &schema, const std::string &,
const std::set<std::string> &vocabularies,
const sourcemeta::jsontoolkit::Pointer &) const -> bool override {
return contains_any(
vocabularies,
{"https://json-schema.org/draft/2020-12/vocab/validation",
"https://json-schema.org/draft/2019-09/vocab/validation",
"http://json-schema.org/draft-07/schema#",
"http://json-schema.org/draft-06/schema#",
"http://json-schema.org/draft-04/schema#",
"http://json-schema.org/draft-03/schema#",
"http://json-schema.org/draft-02/hyper-schema#",
"http://json-schema.org/draft-01/hyper-schema#"}) &&
schema.is_object() && schema.defines("type") &&
schema.at("type").is_string() &&
(schema.at("type").to_string() == "integer" ||
schema.at("type").to_string() == "number") &&
schema.defines("minimum") && schema.at("minimum").is_number() &&
schema.defines("maximum") && schema.at("maximum").is_number() &&
schema.at("minimum") == schema.at("maximum");
}

auto transform(sourcemeta::alterschema::Transformer &transformer) const
-> void override {
sourcemeta::jsontoolkit::JSON values =
sourcemeta::jsontoolkit::JSON::make_array();
values.push_back(transformer.schema().at("minimum"));
transformer.assign("enum", std::move(values));
transformer.erase("type");
transformer.erase("minimum");
transformer.erase("maximum");
}
};
40 changes: 40 additions & 0 deletions test/linter/2019_09_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1699,3 +1699,43 @@ TEST(Lint_2019_09, min_items_given_min_contains_2) {

EXPECT_EQ(document, expected);
}

TEST(Lint_2019_09, equal_numeric_bounds_to_enum_1) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "https://json-schema.org/draft/2019-09/schema",
"type": "integer",
"minimum": 3,
"maximum": 3
})JSON");

LINT_AND_FIX_FOR_READABILITY(document);

const sourcemeta::jsontoolkit::JSON expected =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "https://json-schema.org/draft/2019-09/schema",
"const": 3
})JSON");

EXPECT_EQ(document, expected);
}

TEST(Lint_2019_09, equal_numeric_bounds_to_enum_2) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "https://json-schema.org/draft/2019-09/schema",
"type": "integer",
"minimum": 3,
"maximum": 3
})JSON");

LINT_AND_FIX_FOR_ANALYSIS(document);

const sourcemeta::jsontoolkit::JSON expected =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "https://json-schema.org/draft/2019-09/schema",
"enum": [ 3 ]
})JSON");

EXPECT_EQ(document, expected);
}
40 changes: 40 additions & 0 deletions test/linter/2020_12_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1856,3 +1856,43 @@ TEST(Lint_2020_12, min_items_given_min_contains_2) {

EXPECT_EQ(document, expected);
}

TEST(Lint_2020_12, equal_numeric_bounds_to_enum_1) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "integer",
"minimum": 3,
"maximum": 3
})JSON");

LINT_AND_FIX_FOR_READABILITY(document);

const sourcemeta::jsontoolkit::JSON expected =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "https://json-schema.org/draft/2020-12/schema",
"const": 3
})JSON");

EXPECT_EQ(document, expected);
}

TEST(Lint_2020_12, equal_numeric_bounds_to_enum_2) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "integer",
"minimum": 3,
"maximum": 3
})JSON");

LINT_AND_FIX_FOR_ANALYSIS(document);

const sourcemeta::jsontoolkit::JSON expected =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "https://json-schema.org/draft/2020-12/schema",
"enum": [ 3 ]
})JSON");

EXPECT_EQ(document, expected);
}
40 changes: 40 additions & 0 deletions test/linter/draft1_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -534,3 +534,43 @@ TEST(Lint_draft1, boolean_true_1) {

EXPECT_EQ(document, expected);
}

TEST(Lint_draft1, equal_numeric_bounds_to_enum_1) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-01/schema#",
"type": "integer",
"minimum": 3,
"maximum": 3
})JSON");

LINT_AND_FIX_FOR_READABILITY(document);

const sourcemeta::jsontoolkit::JSON expected =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-01/schema#",
"enum": [ 3 ]
})JSON");

EXPECT_EQ(document, expected);
}

TEST(Lint_draft1, equal_numeric_bounds_to_enum_2) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-01/schema#",
"type": "integer",
"minimum": 3,
"maximum": 3
})JSON");

LINT_AND_FIX_FOR_ANALYSIS(document);

const sourcemeta::jsontoolkit::JSON expected =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-01/schema#",
"enum": [ 3 ]
})JSON");

EXPECT_EQ(document, expected);
}
40 changes: 40 additions & 0 deletions test/linter/draft2_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -534,3 +534,43 @@ TEST(Lint_draft2, boolean_true_1) {

EXPECT_EQ(document, expected);
}

TEST(Lint_draft2, equal_numeric_bounds_to_enum_1) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-02/schema#",
"type": "integer",
"minimum": 3,
"maximum": 3
})JSON");

LINT_AND_FIX_FOR_READABILITY(document);

const sourcemeta::jsontoolkit::JSON expected =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-02/schema#",
"enum": [ 3 ]
})JSON");

EXPECT_EQ(document, expected);
}

TEST(Lint_draft2, equal_numeric_bounds_to_enum_2) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-02/schema#",
"type": "integer",
"minimum": 3,
"maximum": 3
})JSON");

LINT_AND_FIX_FOR_ANALYSIS(document);

const sourcemeta::jsontoolkit::JSON expected =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-02/schema#",
"enum": [ 3 ]
})JSON");

EXPECT_EQ(document, expected);
}
40 changes: 40 additions & 0 deletions test/linter/draft3_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -600,3 +600,43 @@ TEST(Lint_draft3, boolean_true_1) {

EXPECT_EQ(document, expected);
}

TEST(Lint_draft3, equal_numeric_bounds_to_enum_1) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-03/schema#",
"type": "integer",
"minimum": 3,
"maximum": 3
})JSON");

LINT_AND_FIX_FOR_READABILITY(document);

const sourcemeta::jsontoolkit::JSON expected =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-03/schema#",
"enum": [ 3 ]
})JSON");

EXPECT_EQ(document, expected);
}

TEST(Lint_draft3, equal_numeric_bounds_to_enum_2) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-03/schema#",
"type": "integer",
"minimum": 3,
"maximum": 3
})JSON");

LINT_AND_FIX_FOR_ANALYSIS(document);

const sourcemeta::jsontoolkit::JSON expected =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-03/schema#",
"enum": [ 3 ]
})JSON");

EXPECT_EQ(document, expected);
}
40 changes: 40 additions & 0 deletions test/linter/draft4_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -780,3 +780,43 @@ TEST(Lint_draft4, min_properties_implicit_2) {

EXPECT_EQ(document, expected);
}

TEST(Lint_draft4, equal_numeric_bounds_to_enum_1) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "integer",
"minimum": 3,
"maximum": 3
})JSON");

LINT_AND_FIX_FOR_READABILITY(document);

const sourcemeta::jsontoolkit::JSON expected =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-04/schema#",
"enum": [ 3 ]
})JSON");

EXPECT_EQ(document, expected);
}

TEST(Lint_draft4, equal_numeric_bounds_to_enum_2) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "integer",
"minimum": 3,
"maximum": 3
})JSON");

LINT_AND_FIX_FOR_ANALYSIS(document);

const sourcemeta::jsontoolkit::JSON expected =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-04/schema#",
"enum": [ 3 ]
})JSON");

EXPECT_EQ(document, expected);
}
40 changes: 40 additions & 0 deletions test/linter/draft6_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1169,3 +1169,43 @@ TEST(Lint_draft6, min_properties_implicit_2) {

EXPECT_EQ(document, expected);
}

TEST(Lint_draft6, equal_numeric_bounds_to_enum_1) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-06/schema#",
"type": "integer",
"minimum": 3,
"maximum": 3
})JSON");

LINT_AND_FIX_FOR_READABILITY(document);

const sourcemeta::jsontoolkit::JSON expected =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-06/schema#",
"const": 3
})JSON");

EXPECT_EQ(document, expected);
}

TEST(Lint_draft6, equal_numeric_bounds_to_enum_2) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-06/schema#",
"type": "integer",
"minimum": 3,
"maximum": 3
})JSON");

LINT_AND_FIX_FOR_ANALYSIS(document);

const sourcemeta::jsontoolkit::JSON expected =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-06/schema#",
"enum": [ 3 ]
})JSON");

EXPECT_EQ(document, expected);
}
Loading

0 comments on commit 361377e

Please sign in to comment.