Skip to content

Commit

Permalink
Remove minProperties if less than or equal to required (#210)
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 9, 2024
1 parent 266eacd commit bb285c6
Show file tree
Hide file tree
Showing 8 changed files with 324 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 @@ -34,6 +34,7 @@ noa_library(NAMESPACE sourcemeta PROJECT alterschema NAME linter
redundant/items_schema_default.h
redundant/max_contains_without_contains.h
redundant/min_contains_without_contains.h
redundant/min_properties_covered_by_required.h
redundant/pattern_properties_default.h
redundant/properties_default.h
redundant/then_without_if.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 @@ -44,6 +44,7 @@ auto contains_any(const T &container, const T &values) -> bool {
#include "redundant/items_schema_default.h"
#include "redundant/max_contains_without_contains.h"
#include "redundant/min_contains_without_contains.h"
#include "redundant/min_properties_covered_by_required.h"
#include "redundant/pattern_properties_default.h"
#include "redundant/properties_default.h"
#include "redundant/then_without_if.h"
Expand Down Expand Up @@ -88,6 +89,7 @@ auto add(Bundle &bundle, const LinterCategory category) -> void {
bundle.add<ItemsSchemaDefault>();
bundle.add<MaxContainsWithoutContains>();
bundle.add<MinContainsWithoutContains>();
bundle.add<MinPropertiesCoveredByRequired>();
bundle.add<PatternPropertiesDefault>();
bundle.add<PropertiesDefault>();
bundle.add<ThenWithoutIf>();
Expand Down
31 changes: 31 additions & 0 deletions src/linter/redundant/min_properties_covered_by_required.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
class MinPropertiesCoveredByRequired final : public Rule {
public:
MinPropertiesCoveredByRequired()
: Rule{"min_properties_covered_by_required",
"Setting `minProperties` to a number less than `required` does "
"not add any further constraint"} {};

[[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#"}) &&
schema.is_object() && schema.defines("minProperties") &&
schema.at("minProperties").is_integer() &&
schema.defines("required") && schema.at("required").is_array() &&
schema.at("required").unique() &&
schema.at("required").size() >=
static_cast<std::uint64_t>(
schema.at("minProperties").to_integer());
}

auto transform(Transformer &transformer) const -> void override {
transformer.erase("minProperties");
}
};
58 changes: 58 additions & 0 deletions test/linter/2019_09_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -874,3 +874,61 @@ TEST(Lint_2019_09, pattern_properties_default_1) {

EXPECT_EQ(document, expected);
}

TEST(Lint_2019_09, min_properties_covered_by_required_1) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "https://json-schema.org/draft/2019-09/schema",
"required": [ "foo", "bar", "bar", "baz" ],
"minProperties": 3
})JSON");

LINT_AND_FIX(document);

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

EXPECT_EQ(document, expected);
}

TEST(Lint_2019_09, min_properties_covered_by_required_2) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "https://json-schema.org/draft/2019-09/schema",
"required": [ "foo", "bar", "bar", "baz" ],
"minProperties": 4
})JSON");

LINT_AND_FIX(document);

const sourcemeta::jsontoolkit::JSON expected =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "https://json-schema.org/draft/2019-09/schema",
"required": [ "bar", "baz", "foo" ],
"minProperties": 4
})JSON");

EXPECT_EQ(document, expected);
}

TEST(Lint_2019_09, min_properties_covered_by_required_3) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "https://json-schema.org/draft/2019-09/schema",
"required": [ "foo", "bar", "bar", "baz" ],
"minProperties": 2
})JSON");

LINT_AND_FIX(document);

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

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

EXPECT_EQ(document, expected);
}

TEST(Lint_2020_12, min_properties_covered_by_required_1) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [ "foo", "bar", "bar", "baz" ],
"minProperties": 3
})JSON");

LINT_AND_FIX(document);

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

EXPECT_EQ(document, expected);
}

TEST(Lint_2020_12, min_properties_covered_by_required_2) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [ "foo", "bar", "bar", "baz" ],
"minProperties": 4
})JSON");

LINT_AND_FIX(document);

const sourcemeta::jsontoolkit::JSON expected =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [ "bar", "baz", "foo" ],
"minProperties": 4
})JSON");

EXPECT_EQ(document, expected);
}

TEST(Lint_2020_12, min_properties_covered_by_required_3) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [ "foo", "bar", "bar", "baz" ],
"minProperties": 2
})JSON");

LINT_AND_FIX(document);

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

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

EXPECT_EQ(document, expected);
}

TEST(Lint_draft4, min_properties_covered_by_required_1) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-04/schema#",
"required": [ "foo", "bar", "bar", "baz" ],
"minProperties": 3
})JSON");

LINT_AND_FIX(document);

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

EXPECT_EQ(document, expected);
}

TEST(Lint_draft4, min_properties_covered_by_required_2) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-04/schema#",
"required": [ "foo", "bar", "bar", "baz" ],
"minProperties": 4
})JSON");

LINT_AND_FIX(document);

const sourcemeta::jsontoolkit::JSON expected =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-04/schema#",
"required": [ "bar", "baz", "foo" ],
"minProperties": 4
})JSON");

EXPECT_EQ(document, expected);
}

TEST(Lint_draft4, min_properties_covered_by_required_3) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-04/schema#",
"required": [ "foo", "bar", "bar", "baz" ],
"minProperties": 2
})JSON");

LINT_AND_FIX(document);

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

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

EXPECT_EQ(document, expected);
}

TEST(Lint_draft6, min_properties_covered_by_required_1) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-06/schema#",
"required": [ "foo", "bar", "bar", "baz" ],
"minProperties": 3
})JSON");

LINT_AND_FIX(document);

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

EXPECT_EQ(document, expected);
}

TEST(Lint_draft6, min_properties_covered_by_required_2) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-06/schema#",
"required": [ "foo", "bar", "bar", "baz" ],
"minProperties": 4
})JSON");

LINT_AND_FIX(document);

const sourcemeta::jsontoolkit::JSON expected =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-06/schema#",
"required": [ "bar", "baz", "foo" ],
"minProperties": 4
})JSON");

EXPECT_EQ(document, expected);
}

TEST(Lint_draft6, min_properties_covered_by_required_3) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-06/schema#",
"required": [ "foo", "bar", "bar", "baz" ],
"minProperties": 2
})JSON");

LINT_AND_FIX(document);

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

EXPECT_EQ(document, expected);
}
58 changes: 58 additions & 0 deletions test/linter/draft7_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -615,3 +615,61 @@ TEST(Lint_draft7, pattern_properties_default_1) {

EXPECT_EQ(document, expected);
}

TEST(Lint_draft7, min_properties_covered_by_required_1) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [ "foo", "bar", "bar", "baz" ],
"minProperties": 3
})JSON");

LINT_AND_FIX(document);

const sourcemeta::jsontoolkit::JSON expected =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [ "bar", "baz", "foo" ]
})JSON");

EXPECT_EQ(document, expected);
}

TEST(Lint_draft7, min_properties_covered_by_required_2) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [ "foo", "bar", "bar", "baz" ],
"minProperties": 4
})JSON");

LINT_AND_FIX(document);

const sourcemeta::jsontoolkit::JSON expected =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [ "bar", "baz", "foo" ],
"minProperties": 4
})JSON");

EXPECT_EQ(document, expected);
}

TEST(Lint_draft7, min_properties_covered_by_required_3) {
sourcemeta::jsontoolkit::JSON document =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [ "foo", "bar", "bar", "baz" ],
"minProperties": 2
})JSON");

LINT_AND_FIX(document);

const sourcemeta::jsontoolkit::JSON expected =
sourcemeta::jsontoolkit::parse(R"JSON({
"$schema": "http://json-schema.org/draft-07/schema#",
"required": [ "bar", "baz", "foo" ]
})JSON");

EXPECT_EQ(document, expected);
}

0 comments on commit bb285c6

Please sign in to comment.