apollo_smith/
input_object.rs1use crate::description::Description;
2use crate::directive::Directive;
3use crate::directive::DirectiveLocation;
4use crate::input_value::InputValueDef;
5use crate::name::Name;
6use crate::DocumentBuilder;
7use apollo_compiler::ast;
8use apollo_compiler::Node;
9use arbitrary::Result as ArbitraryResult;
10use indexmap::IndexMap;
11
12#[derive(Debug, Clone)]
23pub struct InputObjectTypeDef {
24 pub(crate) name: Name,
25 pub(crate) description: Option<Description>,
26 pub(crate) fields: Vec<InputValueDef>,
28 pub(crate) directives: IndexMap<Name, Directive>,
30 pub(crate) extend: bool,
31}
32
33impl From<InputObjectTypeDef> for ast::Definition {
34 fn from(x: InputObjectTypeDef) -> Self {
35 if x.extend {
36 ast::InputObjectTypeExtension {
37 name: x.name.into(),
38 directives: Directive::to_ast(x.directives),
39 fields: x.fields.into_iter().map(|x| Node::new(x.into())).collect(),
40 }
41 .into()
42 } else {
43 ast::InputObjectTypeDefinition {
44 description: x.description.map(Into::into),
45 name: x.name.into(),
46 directives: Directive::to_ast(x.directives),
47 fields: x.fields.into_iter().map(|x| Node::new(x.into())).collect(),
48 }
49 .into()
50 }
51 }
52}
53
54impl TryFrom<apollo_parser::cst::InputObjectTypeDefinition> for InputObjectTypeDef {
55 type Error = crate::FromError;
56
57 fn try_from(
58 input_object: apollo_parser::cst::InputObjectTypeDefinition,
59 ) -> Result<Self, Self::Error> {
60 Ok(Self {
61 name: input_object
62 .name()
63 .expect("object type definition must have a name")
64 .into(),
65 description: input_object.description().map(Description::from),
66 directives: input_object
67 .directives()
68 .map(Directive::convert_directives)
69 .transpose()?
70 .unwrap_or_default(),
71 extend: false,
72 fields: input_object
73 .input_fields_definition()
74 .map(|input_fields| {
75 input_fields
76 .input_value_definitions()
77 .map(InputValueDef::try_from)
78 .collect::<Result<_, _>>()
79 })
80 .transpose()?
81 .unwrap_or_default(),
82 })
83 }
84}
85
86impl TryFrom<apollo_parser::cst::InputObjectTypeExtension> for InputObjectTypeDef {
87 type Error = crate::FromError;
88
89 fn try_from(
90 input_object: apollo_parser::cst::InputObjectTypeExtension,
91 ) -> Result<Self, Self::Error> {
92 Ok(Self {
93 name: input_object
94 .name()
95 .expect("object type definition must have a name")
96 .into(),
97 directives: input_object
98 .directives()
99 .map(Directive::convert_directives)
100 .transpose()?
101 .unwrap_or_default(),
102 extend: true,
103 fields: input_object
104 .input_fields_definition()
105 .map(|input_fields| {
106 input_fields
107 .input_value_definitions()
108 .map(InputValueDef::try_from)
109 .collect::<Result<Vec<_>, crate::FromError>>()
110 })
111 .transpose()?
112 .unwrap_or_default(),
113 description: None,
114 })
115 }
116}
117
118impl DocumentBuilder<'_> {
119 pub fn input_object_type_definition(&mut self) -> ArbitraryResult<InputObjectTypeDef> {
121 let extend = !self.input_object_type_defs.is_empty() && self.u.arbitrary().unwrap_or(false);
122 let name = if extend {
123 let available_input_objects: Vec<&Name> = self
124 .input_object_type_defs
125 .iter()
126 .filter_map(|input_object| {
127 if input_object.extend {
128 None
129 } else {
130 Some(&input_object.name)
131 }
132 })
133 .collect();
134 (*self.u.choose(&available_input_objects)?).clone()
135 } else {
136 self.type_name()?
137 };
138 let description = self
139 .u
140 .arbitrary()
141 .unwrap_or(false)
142 .then(|| self.description())
143 .transpose()?;
144 let fields = self.input_values_def()?;
145
146 Ok(InputObjectTypeDef {
147 description,
148 directives: self.directives(DirectiveLocation::InputObject)?,
149 name,
150 extend,
151 fields,
152 })
153 }
154}