//! Example usage of `apollo-parser` to check for unused vars in a given GraphQL //! query. use apollo_parser::cst; use apollo_parser::Parser; use std::fs; use std::path::Path; fn are_variables_unused() { // Example mutation with variables. let file = Path::new("crates/apollo-parser/examples/graph_check_mutation.graphql"); let src = fs::read_to_string(file).expect("Could not read schema file."); let parser = Parser::new(&src); let cst = parser.parse(); assert_eq!(0, cst.errors().len()); let doc = cst.document(); for def in doc.definitions() { if let cst::Definition::OperationDefinition(op_def) = def { assert_eq!(op_def.name().unwrap().text(), "GraphCheckMutation"); let variable_defs = op_def.variable_definitions(); // We grab all the variables defined in the mutation let variables: Vec = variable_defs .iter() .flat_map(|v| v.variable_definitions()) .filter_map(|v| Some(v.variable()?.text().to_string())) .collect(); if let Some(selection_set) = op_def.selection_set() { let mut vec = Vec::default(); // Get the variables defined in the mutation's selection set. let used_vars = get_variables_from_selection(&mut vec, selection_set); // Compare the two sets of variables. assert!(do_variables_match(&variables, used_vars)); } } } } fn get_variables_from_selection( used_vars: &mut Vec, selection_set: cst::SelectionSet, ) -> &Vec { for selection in selection_set.selections() { match selection { cst::Selection::Field(field) => { let arguments = field.arguments(); let mut vars: Vec = arguments .iter() .flat_map(|a| a.arguments()) .filter_map(|v| { if let cst::Value::Variable(var) = v.value()? { return Some(var.text().to_string()); } None }) .collect(); used_vars.append(&mut vars); if let Some(selection_set) = field.selection_set() { get_variables_from_selection(used_vars, selection_set); } } _ => unimplemented!(), } } used_vars } fn do_variables_match(a: &[String], b: &[String]) -> bool { let matching = a.iter().zip(b.iter()).filter(|&(a, b)| a == b).count(); matching == a.len() && matching == b.len() } fn main() { are_variables_unused(); }