Skip to content

Commit a2b6bbd

Browse files
authored
Merge pull request #116 from mathstuf/only-output-required-structs
Only output required structs
2 parents 0e497bd + 185807f commit a2b6bbd

25 files changed

+134
-37
lines changed
Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,3 @@
1-
//! We define the custom scalars present in the GitHub schema. More precise types could be provided here (see tests), as long as they are deserializable.
1+
//! We define the custom scalars present in the GitHub query. More precise types could be provided here (see tests), as long as they are deserializable.
22
3-
pub type X509Certificate = String;
43
pub type URI = String;
5-
pub type HTML = String;
6-
pub type GitTimestamp = String;
7-
pub type GitSSHRemote = String;
8-
pub type GitObjectID = String;
9-
pub type Date = String;
10-
pub type DateTime = String;

examples/github/src/main.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,7 @@ extern crate prettytable;
2020
use graphql_client::*;
2121
use structopt::StructOpt;
2222

23-
type X509Certificate = String;
2423
type URI = String;
25-
type HTML = String;
26-
type GitTimestamp = String;
27-
type GitSSHRemote = String;
28-
type GitObjectID = String;
29-
type Date = String;
30-
type DateTime = String;
3124

3225
#[derive(GraphQLQuery)]
3326
#[graphql(

examples/github/src/query_1.graphql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
query RepoView($owner: String!, $name: String!) {
22
repository(owner: $owner, name: $name) {
3+
homepageUrl
34
stargazers {
45
totalCount
56
}

graphql_client_codegen/src/codegen.rs

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ pub fn response_for_query(
3737
name: fragment.name,
3838
selection: Selection::from(&fragment.selection_set),
3939
on,
40+
is_required: false.into(),
4041
},
4142
);
4243
}
@@ -97,11 +98,23 @@ pub fn response_for_query(
9798
.schema
9899
.enums
99100
.values()
100-
.map(|enm| enm.to_rust(&context));
101+
.filter_map(|enm| {
102+
if enm.is_required.get() {
103+
Some(enm.to_rust(&context))
104+
} else {
105+
None
106+
}
107+
});
101108
let fragment_definitions: Result<Vec<TokenStream>, _> = context
102109
.fragments
103110
.values()
104-
.map(|fragment| fragment.to_rust(&context))
111+
.filter_map(|fragment| {
112+
if fragment.is_required.get() {
113+
Some(fragment.to_rust(&context))
114+
} else {
115+
None
116+
}
117+
})
105118
.collect();
106119
let fragment_definitions = fragment_definitions?;
107120
let variables_struct = operation.expand_variables(&context);
@@ -110,23 +123,39 @@ pub fn response_for_query(
110123
.schema
111124
.inputs
112125
.values()
113-
.map(|i| i.to_rust(&context))
126+
.filter_map(|i| {
127+
if i.is_required.get() {
128+
Some(i.to_rust(&context))
129+
} else {
130+
None
131+
}
132+
})
114133
.collect();
115134
let input_object_definitions = input_object_definitions?;
116135

117136
let scalar_definitions: Vec<TokenStream> = context
118137
.schema
119138
.scalars
120139
.values()
121-
.map(|s| s.to_rust())
140+
.filter_map(|s| {
141+
if s.is_required.get() {
142+
Some(s.to_rust())
143+
} else {
144+
None
145+
}
146+
})
122147
.collect();
123148

124149
let response_derives = context.response_derives();
125150

126151
Ok(quote! {
152+
#[allow(dead_code)]
127153
type Boolean = bool;
154+
#[allow(dead_code)]
128155
type Float = f64;
156+
#[allow(dead_code)]
129157
type Int = i64;
158+
#[allow(dead_code)]
130159
type ID = String;
131160

132161
#(#scalar_definitions)*

graphql_client_codegen/src/enums.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use proc_macro2::{Ident, Span, TokenStream};
2+
use std::cell::Cell;
23

34
pub const ENUMS_PREFIX: &str = "";
45

@@ -13,6 +14,7 @@ pub struct GqlEnum {
1314
pub description: Option<String>,
1415
pub name: String,
1516
pub variants: Vec<EnumVariant>,
17+
pub is_required: Cell<bool>,
1618
}
1719

1820
impl GqlEnum {

graphql_client_codegen/src/field_type.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@ impl FieldType {
2222
};
2323
match &self {
2424
FieldType::Named(ref name) => {
25-
let full_name = if context.schema.scalars.contains_key(name) || DEFAULT_SCALARS
25+
let full_name = if context.schema.scalars.get(name).map(|s| s.is_required.set(true)).is_some() || DEFAULT_SCALARS
2626
.iter()
2727
.any(|elem| elem == name)
2828
{
2929
name.clone()
30-
} else if context.schema.enums.contains_key(name) {
30+
} else if context.schema.enums.get(name).map(|enm| enm.is_required.set(true)).is_some() {
3131
format!("{}{}", ENUMS_PREFIX, name)
3232
} else {
3333
if prefix.is_empty() {

graphql_client_codegen/src/fragments.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
use proc_macro2::{Ident, Span, TokenStream};
22
use query::QueryContext;
33
use selection::Selection;
4+
use std::cell::Cell;
45

56
#[derive(Debug, PartialEq)]
67
pub struct GqlFragment {
78
pub name: String,
89
pub on: String,
910
pub selection: Selection,
11+
pub is_required: Cell<bool>,
1012
}
1113

1214
impl GqlFragment {

graphql_client_codegen/src/inputs.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,39 @@ use introspection_response;
66
use objects::GqlObjectField;
77
use proc_macro2::{Ident, Span, TokenStream};
88
use query::QueryContext;
9+
use schema::Schema;
910
use std::collections::HashMap;
11+
use std::cell::Cell;
1012

1113
/// Represents an input object type from a GraphQL schema
1214
#[derive(Debug, Clone, PartialEq)]
1315
pub struct GqlInput {
1416
pub description: Option<String>,
1517
pub name: String,
1618
pub fields: HashMap<String, GqlObjectField>,
19+
pub is_required: Cell<bool>,
1720
}
1821

1922
impl GqlInput {
23+
pub(crate) fn require(&self, schema: &Schema) {
24+
if self.is_required.get() {
25+
return;
26+
}
27+
self.is_required.set(true);
28+
self.fields
29+
.values()
30+
.for_each(|field| {
31+
schema.require(&field.type_.inner_name_string());
32+
})
33+
}
34+
2035
pub(crate) fn to_rust(&self, context: &QueryContext) -> Result<TokenStream, failure::Error> {
2136
let name = Ident::new(&self.name, Span::call_site());
2237
let mut fields: Vec<&GqlObjectField> = self.fields.values().collect();
2338
fields.sort_unstable_by(|a, b| a.name.cmp(&b.name));
2439
let fields = fields.iter().map(|field| {
2540
let ty = field.type_.to_rust(&context, "");
41+
context.schema.require(&field.type_.inner_name_string());
2642
let original_name = &field.name;
2743
let snake_case_name = field.name.to_snake_case();
2844
let rename = ::shared::field_rename_annotation(&original_name, &snake_case_name);
@@ -59,6 +75,7 @@ impl ::std::convert::From<graphql_parser::schema::InputObjectType> for GqlInput
5975
};
6076
(name, field)
6177
}).collect(),
78+
is_required: false.into(),
6279
}
6380
}
6481
}
@@ -87,6 +104,7 @@ impl ::std::convert::From<introspection_response::FullType> for GqlInput {
87104
};
88105
(name, field)
89106
}).collect(),
107+
is_required: false.into(),
90108
}
91109
}
92110
}
@@ -132,6 +150,7 @@ mod tests {
132150
),
133151
].into_iter()
134152
.collect(),
153+
is_required: false.into(),
135154
};
136155

137156
let expected: String = vec![

graphql_client_codegen/src/interfaces.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use query::QueryContext;
55
use selection::{Selection, SelectionItem};
66
use shared::*;
77
use std::borrow::Cow;
8+
use std::cell::Cell;
89
use std::collections::HashSet;
910
use unions::union_variants;
1011

@@ -14,6 +15,7 @@ pub struct GqlInterface {
1415
pub implemented_by: HashSet<String>,
1516
pub name: String,
1617
pub fields: Vec<GqlObjectField>,
18+
pub is_required: Cell<bool>,
1719
}
1820

1921
impl GqlInterface {
@@ -23,6 +25,7 @@ impl GqlInterface {
2325
name: name.into_owned(),
2426
implemented_by: HashSet::new(),
2527
fields: vec![],
28+
is_required: false.into(),
2629
}
2730
}
2831

graphql_client_codegen/src/objects.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,18 @@ use field_type::FieldType;
55
use graphql_parser::schema;
66
use proc_macro2::{Ident, Span, TokenStream};
77
use query::QueryContext;
8+
use schema::Schema;
89
use selection::*;
910
use shared::{field_impls_for_selection, response_fields_for_selection};
1011
use std::borrow::Cow;
12+
use std::cell::Cell;
1113

1214
#[derive(Debug, Clone, PartialEq)]
1315
pub struct GqlObject {
1416
pub description: Option<String>,
1517
pub fields: Vec<GqlObjectField>,
1618
pub name: String,
19+
pub is_required: Cell<bool>,
1720
}
1821

1922
#[derive(Clone, Debug, PartialEq, Hash)]
@@ -60,6 +63,7 @@ impl GqlObject {
6063
description: description.map(|s| s.to_owned()),
6164
name: name.into_owned(),
6265
fields: vec![typename_field()],
66+
is_required: false.into(),
6367
}
6468
}
6569

@@ -105,6 +109,18 @@ impl GqlObject {
105109
item
106110
}
107111

112+
pub(crate) fn require(&self, schema: &Schema) {
113+
if self.is_required.get() {
114+
return;
115+
}
116+
self.is_required.set(true);
117+
self.fields
118+
.iter()
119+
.for_each(|field| {
120+
schema.require(&field.type_.inner_name_string());
121+
})
122+
}
123+
108124
pub(crate) fn response_for_selection(
109125
&self,
110126
query_context: &QueryContext,

0 commit comments

Comments
 (0)