in compiler/crates/schema-diff/src/lib.rs [105:225]
fn compare_fields(
optional_current_fields: &Option<List<FieldDefinition>>,
optional_previous_fields: Option<List<FieldDefinition>>,
) -> (Vec<TypeChange>, Vec<TypeChange>, Vec<ArgumentChange>) {
let mut added: Vec<TypeChange> = vec![];
let mut removed: Vec<TypeChange> = vec![];
let mut field_changed: Vec<ArgumentChange> = vec![];
match (optional_current_fields.as_ref(), optional_previous_fields) {
(Some(current_fields), Some(previous_fields)) => {
let mut previous_values = previous_fields
.items
.into_iter()
.map(|input| (input.name.value, input))
.collect::<FnvHashMap<_, _>>();
for field in ¤t_fields.items {
match previous_values.remove(&field.name.value) {
None => {
added.push(TypeChange {
name: field.name.value,
type_: Type::from(field.type_.clone()),
});
}
Some(previous_field) => {
let previous_field_type = Type::from(previous_field.type_.clone());
let field_type = Type::from(field.type_.clone());
if previous_field_type != field_type {
added.push(TypeChange {
name: field.name.value,
type_: field_type,
});
removed.push(TypeChange {
name: previous_field.name.value,
type_: previous_field_type,
});
} else {
match (field.arguments.as_ref(), previous_field.arguments) {
(Some(current_field_arguments), Some(previous_field_arguments)) => {
let (args_added, args_removed) = compare_input_value_definition(
¤t_field_arguments.items,
previous_field_arguments.items,
);
if !args_added.is_empty() || !args_removed.is_empty() {
field_changed.push(ArgumentChange {
name: field.name.value,
added: args_added,
removed: args_removed,
});
}
}
(Some(current_field_arguments), None) => {
let current_field_arguments = current_field_arguments.clone();
let args_added = current_field_arguments
.items
.into_iter()
.map(|InputValueDefinition { name, type_, .. }| {
TypeChange {
name: name.value,
type_: Type::from(type_),
}
})
.collect();
let args_removed = vec![];
field_changed.push(ArgumentChange {
name: field.name.value,
added: args_added,
removed: args_removed,
});
}
(None, Some(previous_field_arguments)) => {
let args_added = vec![];
let args_removed = previous_field_arguments
.items
.into_iter()
.map(|InputValueDefinition { name, type_, .. }| {
TypeChange {
name: name.value,
type_: Type::from(type_),
}
})
.collect();
field_changed.push(ArgumentChange {
name: field.name.value,
added: args_added,
removed: args_removed,
});
}
(None, None) => {}
}
}
}
}
}
removed.extend(previous_values.drain().map(|(_, field)| TypeChange {
name: field.name.value,
type_: Type::from(field.type_),
}));
}
(None, Some(previous_fields)) => {
removed.extend(previous_fields.items.into_iter().map(
|FieldDefinition { name, type_, .. }| TypeChange {
name: name.value,
type_: Type::from(type_),
},
));
}
(Some(current_fields), None) => {
let current_field_items = current_fields.items.clone();
added.extend(current_field_items.into_iter().map(
|FieldDefinition { name, type_, .. }| TypeChange {
name: name.value,
type_: Type::from(type_),
},
));
}
(None, None) => {}
}
(added, removed, field_changed)
}