1use crate::description::Description;
2use crate::directive::Directive;
3use crate::directive::DirectiveLocation;
4use crate::name::Name;
5use crate::DocumentBuilder;
6use apollo_compiler::ast;
7use arbitrary::Result as ArbitraryResult;
8use indexmap::IndexMap;
9
10#[derive(Debug, Clone)]
18pub struct ScalarTypeDef {
19 pub(crate) name: Name,
20 pub(crate) description: Option<Description>,
21 pub(crate) directives: IndexMap<Name, Directive>,
22 pub(crate) extend: bool,
23}
24
25impl From<ScalarTypeDef> for ast::Definition {
26 fn from(x: ScalarTypeDef) -> Self {
27 if x.extend {
28 ast::ScalarTypeExtension {
29 name: x.name.into(),
30 directives: Directive::to_ast(x.directives),
31 }
32 .into()
33 } else {
34 ast::ScalarTypeDefinition {
35 description: x.description.map(Into::into),
36 name: x.name.into(),
37 directives: Directive::to_ast(x.directives),
38 }
39 .into()
40 }
41 }
42}
43
44impl TryFrom<apollo_parser::cst::ScalarTypeDefinition> for ScalarTypeDef {
45 type Error = crate::FromError;
46
47 fn try_from(scalar_def: apollo_parser::cst::ScalarTypeDefinition) -> Result<Self, Self::Error> {
48 Ok(Self {
49 description: scalar_def
50 .description()
51 .and_then(|d| d.string_value())
52 .map(|s| Description::from(Into::<String>::into(s))),
53 name: scalar_def.name().unwrap().into(),
54 directives: scalar_def
55 .directives()
56 .map(Directive::convert_directives)
57 .transpose()?
58 .unwrap_or_default(),
59 extend: false,
60 })
61 }
62}
63
64impl TryFrom<apollo_parser::cst::ScalarTypeExtension> for ScalarTypeDef {
65 type Error = crate::FromError;
66
67 fn try_from(scalar_def: apollo_parser::cst::ScalarTypeExtension) -> Result<Self, Self::Error> {
68 Ok(Self {
69 description: None,
70 name: scalar_def.name().unwrap().into(),
71 directives: scalar_def
72 .directives()
73 .map(Directive::convert_directives)
74 .transpose()?
75 .unwrap_or_default(),
76 extend: true,
77 })
78 }
79}
80
81impl DocumentBuilder<'_> {
82 pub fn scalar_type_definition(&mut self) -> ArbitraryResult<ScalarTypeDef> {
84 let extend = !self.scalar_type_defs.is_empty() && self.u.arbitrary().unwrap_or(false);
85 let name = if extend {
86 let available_scalars: Vec<&Name> = self
87 .scalar_type_defs
88 .iter()
89 .filter_map(|scalar| {
90 if scalar.extend {
91 None
92 } else {
93 Some(&scalar.name)
94 }
95 })
96 .collect();
97 (*self.u.choose(&available_scalars)?).clone()
98 } else {
99 self.type_name()?
100 };
101 let description = self
102 .u
103 .arbitrary()
104 .unwrap_or(false)
105 .then(|| self.description())
106 .transpose()?;
107 let directives = self.directives(DirectiveLocation::Scalar)?;
108 let extend = !directives.is_empty() && self.u.arbitrary().unwrap_or(false);
110
111 Ok(ScalarTypeDef {
112 name,
113 description,
114 directives,
115 extend,
116 })
117 }
118}