-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[WIP] Port exiting linter rules from JSON Toolkit
Signed-off-by: Juan Cruz Viotti <[email protected]>
- Loading branch information
Showing
21 changed files
with
559 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
noa_library(NAMESPACE sourcemeta PROJECT alterschema NAME linter | ||
FOLDER "Alterschema/Linter" | ||
SOURCES linter.cc | ||
# Rules | ||
additional_properties_default.h | ||
const_with_type.h | ||
content_media_type_without_encoding.h | ||
content_schema_default.h | ||
content_schema_without_media_type.h | ||
else_without_if.h | ||
enum_to_const.h | ||
enum_with_type.h | ||
items_array_default.h | ||
items_schema_default.h | ||
max_contains_without_contains.h | ||
min_contains_without_contains.h | ||
single_type_array.h | ||
then_without_if.h | ||
unevaluated_items_default.h | ||
unevaluated_properties_default.h) | ||
|
||
if(ALTERSCHEMA_INSTALL) | ||
noa_library_install(NAMESPACE sourcemeta PROJECT alterschema NAME linter) | ||
endif() | ||
|
||
target_link_libraries(sourcemeta_alterschema_linter PUBLIC | ||
sourcemeta::alterschema::engine) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
class AdditionalPropertiesDefault final : public Rule { | ||
public: | ||
AdditionalPropertiesDefault() | ||
: Rule{"additional_properties_default", | ||
"Setting the `additionalProperties` keyword to the true schema " | ||
"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/applicator", | ||
"https://json-schema.org/draft/2019-09/vocab/applicator", | ||
"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("additionalProperties") && | ||
((schema.at("additionalProperties").is_boolean() && | ||
schema.at("additionalProperties").to_boolean()) || | ||
(schema.at("additionalProperties").is_object() && | ||
schema.at("additionalProperties").empty())); | ||
} | ||
|
||
auto transform(Transformer &transformer) const -> void override { | ||
transformer.erase("additionalProperties"); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
class ConstWithType final : public Rule { | ||
public: | ||
ConstWithType() | ||
: Rule{"const_with_type", | ||
"Setting `type` alongside `const` is considered an anti-pattern, " | ||
"as the constant already implies its respective type"} {}; | ||
|
||
[[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#"}) && | ||
schema.is_object() && schema.defines("type") && | ||
schema.defines("const"); | ||
} | ||
|
||
auto transform(Transformer &transformer) const -> void override { | ||
transformer.erase("type"); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
class ContentMediaTypeWithoutEncoding final : public Rule { | ||
public: | ||
ContentMediaTypeWithoutEncoding() | ||
: Rule{"content_media_type_without_encoding", | ||
"The `contentMediaType` keyword is meaningless " | ||
"without the presence of the `contentEncoding` keyword"} {}; | ||
|
||
[[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/content", | ||
"https://json-schema.org/draft/2019-09/vocab/content", | ||
"http://json-schema.org/draft-07/schema#"}) && | ||
schema.is_object() && schema.defines("contentMediaType") && | ||
!schema.defines("contentEncoding"); | ||
} | ||
|
||
auto transform(Transformer &transformer) const -> void override { | ||
transformer.erase("contentMediaType"); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
class ContentSchemaDefault final : public Rule { | ||
public: | ||
ContentSchemaDefault() | ||
: Rule{"content_schema_default", | ||
"Setting the `contentSchema` keyword to the true schema " | ||
"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/content", | ||
"https://json-schema.org/draft/2019-09/vocab/content"}) && | ||
schema.is_object() && schema.defines("contentSchema") && | ||
((schema.at("contentSchema").is_boolean() && | ||
schema.at("contentSchema").to_boolean()) || | ||
(schema.at("contentSchema").is_object() && | ||
schema.at("contentSchema").empty())); | ||
} | ||
|
||
auto transform(Transformer &transformer) const -> void override { | ||
transformer.erase("contentSchema"); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
class ContentSchemaWithoutMediaType final : public Rule { | ||
public: | ||
ContentSchemaWithoutMediaType() | ||
: Rule{"content_schema_without_media_type", | ||
"The `contentSchema` keyword is meaningless without the presence " | ||
"of the `contentMediaType` keyword"} {}; | ||
|
||
[[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/content", | ||
"https://json-schema.org/draft/2019-09/vocab/content"}) && | ||
schema.is_object() && schema.defines("contentSchema") && | ||
!schema.defines("contentMediaType"); | ||
} | ||
|
||
auto transform(Transformer &transformer) const -> void override { | ||
transformer.erase("contentSchema"); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
class ElseWithoutIf final : public Rule { | ||
public: | ||
ElseWithoutIf() | ||
: Rule{"else_without_if", "The `else` keyword is meaningless " | ||
"without the presence of the `if` keyword"} {}; | ||
|
||
[[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/applicator", | ||
"https://json-schema.org/draft/2019-09/vocab/applicator", | ||
"http://json-schema.org/draft-07/schema#"}) && | ||
schema.is_object() && schema.defines("else") && | ||
!schema.defines("if"); | ||
} | ||
|
||
auto transform(Transformer &transformer) const -> void override { | ||
transformer.erase("else"); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
class EnumToConst final : public Rule { | ||
public: | ||
EnumToConst() | ||
: Rule("enum_to_const", | ||
"An `enum` of a single value can be expressed as `const`") {}; | ||
|
||
[[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#"}) && | ||
schema.is_object() && !schema.defines("const") && | ||
schema.defines("enum") && schema.at("enum").is_array() && | ||
schema.at("enum").size() == 1; | ||
} | ||
|
||
auto transform(Transformer &transformer) const -> void override { | ||
transformer.assign("const", transformer.schema().at("enum").front()); | ||
transformer.erase("enum"); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
class EnumWithType final : public Rule { | ||
public: | ||
EnumWithType() | ||
: Rule{ | ||
"enum_with_type", | ||
"Setting `type` alongside `enum` is considered an anti-pattern, as " | ||
"the enumeration choices already imply their respective types"} {}; | ||
|
||
[[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.defines("enum"); | ||
} | ||
|
||
auto transform(Transformer &transformer) const -> void override { | ||
transformer.erase("type"); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
#ifndef SOURCEMETA_ALTERSCHEMA_LINTER_H_ | ||
#define SOURCEMETA_ALTERSCHEMA_LINTER_H_ | ||
|
||
#include "linter_export.h" | ||
|
||
#include <sourcemeta/alterschema/engine.h> | ||
|
||
namespace sourcemeta::alterschema { | ||
|
||
/// @ingroup linter | ||
/// The category of a built-in transformation rule | ||
enum class LinterCategory { | ||
/// Rules that make use of newer features within the same dialect | ||
Modernize, | ||
|
||
/// Rules that detect common anti-patterns | ||
AntiPattern, | ||
|
||
/// Rules that simplify the given schema | ||
Simplify, | ||
|
||
/// Rules that remove schema redundancies | ||
Redundant | ||
}; | ||
|
||
/// Add a set of built-in linter rules given a category | ||
auto lint(Bundle &bundle, const LinterCategory category) -> void; | ||
|
||
} // namespace sourcemeta::alterschema | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
class ItemsArrayDefault final : public Rule { | ||
public: | ||
ItemsArrayDefault() | ||
: Rule{"items_array_default", | ||
"Setting the `items` keyword to the empty array " | ||
"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/2019-09/vocab/applicator", | ||
"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("items") && | ||
schema.at("items").is_array() && schema.at("items").empty(); | ||
} | ||
|
||
auto transform(Transformer &transformer) const -> void override { | ||
transformer.erase("items"); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
class ItemsSchemaDefault final : public Rule { | ||
public: | ||
ItemsSchemaDefault() | ||
: Rule{"items_schema_default", | ||
"Setting the `items` keyword to the true schema " | ||
"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/applicator", | ||
"https://json-schema.org/draft/2019-09/vocab/applicator", | ||
"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("items") && | ||
((schema.at("items").is_boolean() && | ||
schema.at("items").to_boolean()) || | ||
(schema.at("items").is_object() && schema.at("items").empty())); | ||
} | ||
|
||
auto transform(Transformer &transformer) const -> void override { | ||
transformer.erase("items"); | ||
} | ||
}; |
Oops, something went wrong.