Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions graphql_client/tests/custom_scalars/query.graphql
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
query CustomScalarQuery {
address
}

query AnotherCustomScalarQuery {
address
}
36 changes: 36 additions & 0 deletions graphql_client/tests/custom_scalars_module.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use graphql_client::*;
use serde_json::json;

use std::net::Ipv4Addr;

mod scalars {
// Important! The NetworkAddress scalar should deserialize to an Ipv4Addr from the Rust std library.
pub type NetworkAddress = super::Ipv4Addr;
}

graphql_queries!(
query_path = "tests/custom_scalars/query.graphql",
schema_path = "tests/custom_scalars/schema.graphql"
custom_scalars_module = "scalars"
);

#[test]
fn custom_scalars() {
let valid_response = json!({
"address": "127.0.1.2",
});

let valid_addr =
serde_json::from_value::<custom_scalar_query::ResponseData>(valid_response).unwrap();

assert_eq!(
valid_addr.address.unwrap(),
"127.0.1.2".parse::<Ipv4Addr>().unwrap()
);

let invalid_response = json!({
"address": "localhost",
});

assert!(serde_json::from_value::<custom_scalar_query::ResponseData>(invalid_response).is_err());
}
14 changes: 14 additions & 0 deletions graphql_client/tests/module_visibility.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
mod inner {
use graphql_client::*;

graphql_queries!(
query_path = "tests/module_visibility/query.graphql",
schema_path = "tests/module_visibility/schema.graphql",
module_visibility = "pub"
);
}

#[test]
fn module_visibility() {
let _ = inner::test_query::ResponseData { value: None };
}
3 changes: 3 additions & 0 deletions graphql_client/tests/module_visibility/query.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
query TestQuery {
value
}
7 changes: 7 additions & 0 deletions graphql_client/tests/module_visibility/schema.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
schema {
query: QueryRoot
}

type QueryRoot {
value: String
}
12 changes: 12 additions & 0 deletions graphql_client/tests/shared_fragments.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use graphql_client::*;

graphql_queries!(
query_path = "tests/shared_fragments/query.graphql",
schema_path = "tests/shared_fragments/schema.graphql",
);

#[test]
fn shared_fragments() {
let _: common::FragmentReference = a::ResponseData { in_fragment: None };
let _: a::ResponseData = b::ResponseData { in_fragment: None };
}
11 changes: 11 additions & 0 deletions graphql_client/tests/shared_fragments/query.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
fragment FragmentReference on QueryRoot {
inFragment
}

query A {
...FragmentReference
}

query B {
...FragmentReference
}
8 changes: 8 additions & 0 deletions graphql_client/tests/shared_fragments/schema.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
schema {
query: QueryRoot
}

type QueryRoot {
extra: String
inFragment: String
}
17 changes: 2 additions & 15 deletions graphql_client_cli/src/generate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use std::fs::File;
use std::io::Write as _;
use std::path::PathBuf;
use std::process::Stdio;
use syn::{token::Paren, token::Pub, VisRestricted, Visibility};

pub(crate) struct CliCodegenParams {
pub query_path: PathBuf,
Expand Down Expand Up @@ -36,7 +35,7 @@ pub(crate) fn generate_code(params: CliCodegenParams) -> CliResult<()> {
deprecation_strategy,
no_formatting,
output_directory,
module_visibility: _module_visibility,
module_visibility,
query_path,
schema_path,
selected_operation,
Expand All @@ -51,19 +50,7 @@ pub(crate) fn generate_code(params: CliCodegenParams) -> CliResult<()> {

let mut options = GraphQLClientCodegenOptions::new(CodegenMode::Cli);

options.set_module_visibility(match _module_visibility {
Some(v) => match v.to_lowercase().as_str() {
"pub" => Visibility::Public(Pub::default()),
"inherited" => Visibility::Inherited,
_ => Visibility::Restricted(VisRestricted {
pub_token: Pub::default(),
in_token: None,
paren_token: Paren::default(),
path: syn::parse_str(&v).unwrap(),
}),
},
None => Visibility::Public(Pub::default()),
});
options.set_module_visibility_from_str(module_visibility.as_deref().unwrap_or("pub"));

options.set_fragments_other_variant(fragments_other_variant);

Expand Down
51 changes: 33 additions & 18 deletions graphql_client_codegen/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,18 @@ use quote::{quote, ToTokens};
use selection::*;
use std::collections::BTreeMap;

/// The main code generation function.
/// The main code generation function for the inputs, variables, and response types.
pub(crate) fn response_for_query(
operation_id: OperationId,
options: &GraphQLClientCodegenOptions,
query: BoundQuery<'_>,
) -> Result<TokenStream, GeneralError> {
let serde = options.serde_path();

let all_used_types = all_used_types(operation_id, &query);
let all_used_types = all_used_types(&vec![operation_id], &query);
let response_derives = render_derives(options.all_response_derives());
let variable_derives = render_derives(options.all_variable_derives());

let scalar_definitions = generate_scalar_definitions(&all_used_types, options, query);
let enum_definitions = enums::generate_enum_definitions(&all_used_types, options, query);
let fragment_definitions =
generate_fragment_definitions(&all_used_types, &response_derives, options, &query);
let input_object_definitions = inputs::generate_input_object_definitions(
&all_used_types,
options,
Expand All @@ -48,26 +44,45 @@ pub(crate) fn response_for_query(
use #serde::{Serialize, Deserialize};
use super::*;

#(#input_object_definitions)*

#variables_struct

#definitions
};

Ok(q)
}

/// The main code generation function for scalars, enums, and fragments.
pub(crate) fn common_for_queries(
all_operations: &[OperationId],
options: &GraphQLClientCodegenOptions,
query: BoundQuery<'_>,
) -> Result<TokenStream, GeneralError> {
let all_used_types = all_used_types(all_operations, &query);
let response_derives = render_derives(options.all_response_derives());

let scalar_definitions = generate_scalar_definitions(&all_used_types, options, query);
let enum_definitions = enums::generate_enum_definitions(&all_used_types, options, query);
let fragment_definitions =
generate_fragment_definitions(&all_used_types, &response_derives, options, &query);

let q = quote! {
#[allow(dead_code)]
type Boolean = bool;
pub type Boolean = bool;
#[allow(dead_code)]
type Float = f64;
pub type Float = f64;
#[allow(dead_code)]
type Int = i64;
pub type Int = i64;
#[allow(dead_code)]
type ID = String;
pub type ID = String;

#(#scalar_definitions)*

#(#enum_definitions)*

#(#input_object_definitions)*

#variables_struct

#(#fragment_definitions)*

#definitions
};

Ok(q)
Expand Down Expand Up @@ -171,9 +186,9 @@ fn generate_scalar_definitions<'a, 'schema: 'a>(
);

if let Some(custom_scalars_module) = options.custom_scalars_module() {
quote!(type #ident = #custom_scalars_module::#ident;)
quote!(pub type #ident = #custom_scalars_module::#ident;)
} else {
quote!(type #ident = super::#ident;)
quote!(pub type #ident = super::#ident;)
}
})
}
Expand Down
24 changes: 23 additions & 1 deletion graphql_client_codegen/src/codegen_options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ use crate::deprecation::DeprecationStrategy;
use crate::normalization::Normalization;
use proc_macro2::Ident;
use std::path::{Path, PathBuf};
use syn::{self, Visibility};
use syn::{
self,
token::{Paren, Pub},
VisRestricted, Visibility,
};

/// Which context is this code generation effort taking place.
#[derive(Debug)]
Expand All @@ -11,6 +15,8 @@ pub enum CodegenMode {
Cli,
/// The derive macro defined in graphql_query_derive.
Derive,
/// The function-like macro defined in graphql_queries.
FunctionLike,
}

/// Used to configure code generation.
Expand Down Expand Up @@ -174,6 +180,22 @@ impl GraphQLClientCodegenOptions {
self.module_visibility = Some(visibility);
}

/// Parse target module visibility from a string.
pub fn set_module_visibility_from_str(&mut self, visibility: &str) {
let visibility = match visibility.to_lowercase().as_str() {
"pub" => Visibility::Public(Pub::default()),
"inherited" => Visibility::Inherited,
_ => Visibility::Restricted(VisRestricted {
pub_token: Pub::default(),
in_token: None,
paren_token: Paren::default(),
path: syn::parse_str(&visibility).unwrap(),
}),
};

self.module_visibility = Some(visibility);
}

/// The name of implementation target struct.
pub fn set_struct_name(&mut self, struct_name: String) {
self.struct_name = Some(struct_name);
Expand Down
8 changes: 7 additions & 1 deletion graphql_client_codegen/src/generated_module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub(crate) struct GeneratedModule<'a> {
pub resolved_query: &'a crate::query::Query,
pub schema: &'a crate::schema::Schema,
pub options: &'a crate::GraphQLClientCodegenOptions,
pub common: &'a TokenStream,
}

impl GeneratedModule<'_> {
Expand Down Expand Up @@ -62,6 +63,7 @@ impl GeneratedModule<'_> {
let operation_name = self.operation;
let operation_name_ident = self.options.normalization().operation(self.operation);
let operation_name_ident = Ident::new(&operation_name_ident, Span::call_site());
let common = &self.common;

// Force cargo to refresh the generated code when the query file changes.
let query_include = self
Expand All @@ -79,7 +81,9 @@ impl GeneratedModule<'_> {
let impls = self.build_impls()?;

let struct_declaration: Option<_> = match self.options.mode {
CodegenMode::Cli => Some(quote!(#module_visibility struct #operation_name_ident;)),
CodegenMode::Cli | CodegenMode::FunctionLike => {
Some(quote!(#module_visibility struct #operation_name_ident;))
}
// The struct is already present in derive mode.
CodegenMode::Derive => None,
};
Expand All @@ -97,6 +101,8 @@ impl GeneratedModule<'_> {

#query_include

#common

#impls
}

Expand Down
Loading
Loading