async_graphql_derive/
output_type.rs1use proc_macro2::{Ident, Span};
2use quote::quote;
3use syn::{Error, GenericArgument, PathArguments, Result, Type};
4
5pub enum OutputType<'a> {
6 Value(&'a Type),
7 Result(&'a Type),
8}
9
10impl<'a> OutputType<'a> {
11 pub fn parse(input: &'a Type) -> Result<Self> {
12 let ty = if let Type::Path(p) = input {
13 if p.path.segments.last().unwrap().ident == "Result"
14 || p.path.segments.last().unwrap().ident == "FieldResult"
15 {
16 if let PathArguments::AngleBracketed(args) =
17 &p.path.segments.last().unwrap().arguments
18 {
19 if args.args.is_empty() {
20 return Err(Error::new_spanned(input, "Invalid type"));
21 }
22 let mut res = None;
23 for arg in &args.args {
24 if let GenericArgument::Type(value_ty) = arg {
25 res = Some(OutputType::Result(value_ty));
26 break;
27 }
28 }
29 if res.is_none() {
30 return Err(Error::new_spanned(input, "Invalid type"));
31 }
32 res.unwrap()
33 } else {
34 return Err(Error::new_spanned(input, "Invalid type"));
35 }
36 } else {
37 OutputType::Value(input)
38 }
39 } else {
40 OutputType::Value(input)
41 };
42 Ok(ty)
43 }
44
45 pub fn value_type(&self) -> Type {
46 let tokens = match self {
47 OutputType::Value(ty) => quote! {#ty},
48 OutputType::Result(ty) => quote! {#ty},
49 };
50 let mut ty = syn::parse2::<syn::Type>(tokens).unwrap();
51 Self::remove_lifecycle(&mut ty);
52 ty
53 }
54
55 fn remove_lifecycle(ty: &mut Type) {
56 match ty {
57 Type::Reference(r) => {
58 r.lifetime = None;
59 Self::remove_lifecycle(&mut r.elem);
60 }
61 Type::Path(r) => {
62 for s in &mut r.path.segments {
63 if let PathArguments::AngleBracketed(args) = &mut s.arguments {
64 for arg in &mut args.args {
65 match arg {
66 GenericArgument::Lifetime(lt) => {
67 lt.ident = Ident::new("_", Span::call_site());
68 }
69 GenericArgument::Type(ty) => {
70 Self::remove_lifecycle(ty);
71 }
72 _ => {}
73 }
74 }
75 }
76 }
77 }
78 _ => {}
79 }
80 }
81}