Return the correct type at the union and interface
This commit is contained in:
parent
7fb48f6382
commit
945730db06
|
@ -38,6 +38,7 @@ pub fn generate(interface_args: &args::Interface, input: &DeriveInput) -> Result
|
|||
let mut registry_types = Vec::new();
|
||||
let mut possible_types = Vec::new();
|
||||
let mut collect_inline_fields = Vec::new();
|
||||
let mut get_introspection_typename = Vec::new();
|
||||
|
||||
for field in &fields.unnamed {
|
||||
if let Type::Path(p) = &field.ty {
|
||||
|
@ -66,6 +67,9 @@ pub fn generate(interface_args: &args::Interface, input: &DeriveInput) -> Result
|
|||
unreachable!()
|
||||
}
|
||||
});
|
||||
get_introspection_typename.push(quote! {
|
||||
#ident::#enum_name(obj) => <#p as #crate_name::Type>::type_name()
|
||||
})
|
||||
} else {
|
||||
return Err(Error::new_spanned(field, "Invalid type"));
|
||||
}
|
||||
|
@ -225,6 +229,12 @@ pub fn generate(interface_args: &args::Interface, input: &DeriveInput) -> Result
|
|||
std::borrow::Cow::Borrowed(#gql_typename)
|
||||
}
|
||||
|
||||
fn introspection_type_name(&self) -> std::borrow::Cow<'static, str> {
|
||||
match self {
|
||||
#(#get_introspection_typename),*
|
||||
}
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut #crate_name::registry::Registry) -> String {
|
||||
registry.create_type::<Self, _>(|registry| {
|
||||
#(#registry_types)*
|
||||
|
|
|
@ -35,6 +35,7 @@ pub fn generate(interface_args: &args::Interface, input: &DeriveInput) -> Result
|
|||
let mut registry_types = Vec::new();
|
||||
let mut possible_types = Vec::new();
|
||||
let mut collect_inline_fields = Vec::new();
|
||||
let mut get_introspection_typename = Vec::new();
|
||||
|
||||
for field in &fields.unnamed {
|
||||
if let Type::Path(p) = &field.ty {
|
||||
|
@ -62,6 +63,9 @@ pub fn generate(interface_args: &args::Interface, input: &DeriveInput) -> Result
|
|||
unreachable!()
|
||||
}
|
||||
});
|
||||
get_introspection_typename.push(quote! {
|
||||
#ident::#enum_name(obj) => <#p as #crate_name::Type>::type_name()
|
||||
})
|
||||
} else {
|
||||
return Err(Error::new_spanned(field, "Invalid type"));
|
||||
}
|
||||
|
@ -78,6 +82,12 @@ pub fn generate(interface_args: &args::Interface, input: &DeriveInput) -> Result
|
|||
std::borrow::Cow::Borrowed(#gql_typename)
|
||||
}
|
||||
|
||||
fn introspection_type_name(&self) -> std::borrow::Cow<'static, str> {
|
||||
match self {
|
||||
#(#get_introspection_typename),*
|
||||
}
|
||||
}
|
||||
|
||||
fn create_type_info(registry: &mut #crate_name::registry::Registry) -> String {
|
||||
registry.create_type::<Self, _>(|registry| {
|
||||
#(#registry_types)*
|
||||
|
|
|
@ -18,6 +18,13 @@ pub trait Type {
|
|||
format!("{}!", Self::type_name())
|
||||
}
|
||||
|
||||
/// Introspection type name
|
||||
///
|
||||
/// Is the return value of field `__type`, the interface and union should return the current type, and the others return `Type::type_name`.
|
||||
fn introspection_type_name(&self) -> Cow<'static, str> {
|
||||
Self::type_name()
|
||||
}
|
||||
|
||||
/// Create type information in the registry and return qualified typename.
|
||||
fn create_type_info(registry: &mut registry::Registry) -> String;
|
||||
|
||||
|
|
|
@ -282,20 +282,7 @@ impl Registry {
|
|||
cache_control: Default::default(),
|
||||
},
|
||||
);
|
||||
let mut ty = f(self);
|
||||
if let Type::Object { fields, .. } = &mut ty {
|
||||
fields.insert(
|
||||
"__typename".to_string(),
|
||||
Field {
|
||||
name: "__typename".to_string(),
|
||||
description: None,
|
||||
args: Default::default(),
|
||||
ty: "String!".to_string(),
|
||||
deprecation: None,
|
||||
cache_control: Default::default(),
|
||||
},
|
||||
);
|
||||
}
|
||||
let ty = f(self);
|
||||
self.types.insert(name.to_string(), ty);
|
||||
}
|
||||
T::qualified_type_name()
|
||||
|
|
|
@ -45,8 +45,10 @@ pub fn collect_fields<'a, T: ObjectType + Send + Sync>(
|
|||
let ctx_field = ctx.with_field(field);
|
||||
let field_name = ctx_field.result_name().to_string();
|
||||
futures.push(Box::pin(
|
||||
future::ok::<serde_json::Value, Error>(T::type_name().to_string().into())
|
||||
.map_ok(move |value| (field_name, value)),
|
||||
future::ok::<serde_json::Value, Error>(
|
||||
root.introspection_type_name().to_string().into(),
|
||||
)
|
||||
.map_ok(move |value| (field_name, value)),
|
||||
));
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,9 @@ impl<'a> Visitor<'a> for FieldsOnCorrectType {
|
|||
.field_by_name(&field.name)
|
||||
.is_none()
|
||||
{
|
||||
if let Some(registry::Type::Union { .. }) = ctx.parent_type() {
|
||||
if let Some(registry::Type::Union { .. }) | Some(registry::Type::Interface { .. }) =
|
||||
ctx.parent_type()
|
||||
{
|
||||
if field.name == "__typename" {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -480,24 +480,26 @@ fn visit_selection<'a, V: Visitor<'a>>(
|
|||
v.enter_selection(ctx, selection);
|
||||
match selection {
|
||||
Selection::Field(field) => {
|
||||
if let Some(schema_field) = ctx.current_type().field_by_name(&field.name) {
|
||||
ctx.with_type(
|
||||
ctx.registry
|
||||
.basic_type_by_typename(&schema_field.ty)
|
||||
.unwrap(),
|
||||
|ctx| {
|
||||
visit_field(v, ctx, field);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
ctx.report_error(
|
||||
vec![field.position],
|
||||
format!(
|
||||
"Cannot query field \"{}\" on type \"{}\".",
|
||||
field.name,
|
||||
ctx.current_type().name()
|
||||
),
|
||||
);
|
||||
if field.name != "__typename" {
|
||||
if let Some(schema_field) = ctx.current_type().field_by_name(&field.name) {
|
||||
ctx.with_type(
|
||||
ctx.registry
|
||||
.basic_type_by_typename(&schema_field.ty)
|
||||
.unwrap(),
|
||||
|ctx| {
|
||||
visit_field(v, ctx, field);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
ctx.report_error(
|
||||
vec![field.position],
|
||||
format!(
|
||||
"Cannot query field \"{}\" on type \"{}\".",
|
||||
field.name,
|
||||
ctx.current_type().name()
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Selection::FragmentSpread(fragment_spread) => {
|
||||
|
|
Loading…
Reference in New Issue
Block a user