Skip to main content

apollo_smith/
variable.rs

1use crate::description::Description;
2use crate::directive::Directive;
3use crate::directive::DirectiveLocation;
4use crate::input_value::InputValue;
5use crate::name::Name;
6use crate::ty::Ty;
7use crate::DocumentBuilder;
8use apollo_compiler::ast;
9use apollo_compiler::Node;
10use arbitrary::Result as ArbitraryResult;
11use indexmap::IndexMap;
12
13/// The __variableDef type represents a variable definition
14///
15/// *VariableDefinition*:
16///     Description? Variable : Type DefaultValue? Directives[Const]?
17///
18/// Detailed documentation can be found in [GraphQL spec](https://spec.graphql.org/September2025/#sec-Language.Variables).
19#[derive(Debug, Clone)]
20pub struct VariableDef {
21    description: Option<Description>,
22    name: Name,
23    ty: Ty,
24    default_value: Option<InputValue>,
25    directives: IndexMap<Name, Directive>,
26}
27
28impl From<VariableDef> for ast::VariableDefinition {
29    fn from(x: VariableDef) -> Self {
30        Self {
31            description: x.description.map(Into::into),
32            name: x.name.into(),
33            ty: Node::new(x.ty.into()),
34            default_value: x.default_value.map(|x| Node::new(x.into())),
35            directives: Directive::to_ast(x.directives),
36        }
37    }
38}
39
40impl DocumentBuilder<'_> {
41    /// Create an arbitrary list of `VariableDef`
42    pub fn variable_definitions(&mut self) -> ArbitraryResult<Vec<VariableDef>> {
43        (0..self.u.int_in_range(0..=7usize)?)
44            .map(|_| self.variable_definition()) // TODO do not generate duplication variable name
45            .collect()
46    }
47
48    /// Create an arbitrary `VariableDef`
49    pub fn variable_definition(&mut self) -> ArbitraryResult<VariableDef> {
50        let name = self.type_name()?;
51        let ty = self.choose_ty(&self.list_existing_input_types())?;
52        let default_value = self
53            .u
54            .arbitrary()
55            .unwrap_or(false)
56            .then(|| self.input_value_for_type(&ty))
57            .transpose()?;
58        let directives = self.directives(DirectiveLocation::VariableDefinition)?;
59
60        Ok(VariableDef {
61            description: None,
62            name,
63            ty,
64            default_value,
65            directives,
66        })
67    }
68}