Skip to content

Commit

Permalink
schema-derive: verify rename_all = "snake_case" is used
Browse files Browse the repository at this point in the history
  • Loading branch information
uint committed Jun 29, 2022
1 parent 17b6308 commit 7faefd3
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 7 deletions.
3 changes: 1 addition & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/schema-derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ license = "Apache-2.0"
[dependencies]
proc-macro2 = "1"
quote = "1"
serde_derive_internals = "0.26.0"
serde_derive_internals = { git = "https://github.com/uint/serde", branch = "expose_rename_rules" }
syn = { version = "1", features = ["full", "printing", "extra-traits"] }

[lib]
Expand Down
33 changes: 29 additions & 4 deletions packages/schema-derive/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use quote::ToTokens;
use syn::{parse_macro_input, parse_quote, ExprTuple, ItemEnum, ItemImpl, Type, Variant};
use serde_derive_internals::attr::RenameRule;
use syn::{
parse_macro_input, parse_quote, DeriveInput, ExprTuple, ItemEnum, ItemImpl, Type, Variant,
};

/// Extract the query -> response mapping out of an enum variant.
fn parse_query(v: Variant) -> ExprTuple {
Expand Down Expand Up @@ -29,6 +32,18 @@ fn to_snake_case(input: &str) -> String {
snake
}

fn verify_serde_snake_case(input: ItemEnum) -> bool {
let ctx = serde_derive_internals::Ctxt::new();
let attr = serde_derive_internals::attr::Container::from_ast(&ctx, &DeriveInput::from(input));
ctx.check().unwrap();

let rename_all_rules = attr.rename_all_rules();

[rename_all_rules.serialize(), rename_all_rules.deserialize()]
.iter()
.all(|rule| **rule == RenameRule::SnakeCase)
}

#[proc_macro_derive(QueryResponses, attributes(returns))]
pub fn query_responses_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input = parse_macro_input!(input as ItemEnum);
Expand All @@ -39,6 +54,10 @@ pub fn query_responses_derive(input: proc_macro::TokenStream) -> proc_macro::Tok
}

fn query_responses_derive_impl(input: ItemEnum) -> ItemImpl {
if !verify_serde_snake_case(input.clone()) {
panic!("queries need to be serialized as snake_case using #[serde(rename_all = \"snake_case\")]");
}

let ident = input.ident;

let responses = input.variants.into_iter().map(parse_query);
Expand Down Expand Up @@ -124,7 +143,9 @@ mod tests {
}

#[test]
#[should_panic]
#[should_panic(
expected = "queries need to be serialized as snake_case using #[serde(rename_all = \"snake_case\")]"
)]
fn panic_if_queries_are_not_snake_case1() {
let input: ItemEnum = parse_quote! {
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema, QueryResponses)]
Expand All @@ -138,7 +159,9 @@ mod tests {
}

#[test]
#[should_panic]
#[should_panic(
expected = "queries need to be serialized as snake_case using #[serde(rename_all = \"snake_case\")]"
)]
fn panic_if_queries_are_not_snake_case2() {
let input: ItemEnum = parse_quote! {
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema, QueryResponses)]
Expand All @@ -153,7 +176,9 @@ mod tests {
}

#[test]
#[should_panic]
#[should_panic(
expected = "queries need to be serialized as snake_case using #[serde(rename_all = \"snake_case\")]"
)]
fn panic_if_queries_are_not_snake_case3() {
let input: ItemEnum = parse_quote! {
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema, QueryResponses)]
Expand Down

0 comments on commit 7faefd3

Please sign in to comment.