/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use crate::interface::FfiDefinition; use crate::{ComponentInterface, VisitMut}; use std::collections::BTreeSet; use uniffi_meta::Type; impl ComponentInterface { /// A generic interface for mutating items in the [`ComponentInterface`]. /// /// Walk down the [`ComponentInterface`] and adjust the names of each type /// based on the naming conventions of the supported languages. /// /// Each suppoerted language implements the [`VisitMut`] Trait and is able /// to alter the functions, enums etc. to its own naming conventions. pub fn visit_mut(&mut self, visitor: &V) { for type_ in self.types.type_definitions.values_mut() { visitor.visit_type(type_); } let mut all_known_types_altered: BTreeSet = BTreeSet::new(); for type_ in self.types.all_known_types.iter() { let mut type_altered = type_.clone(); visitor.visit_type(&mut type_altered); all_known_types_altered.insert(type_altered); } self.types.all_known_types = all_known_types_altered; let errors_clone = self.errors.clone(); for enum_item in self.enums.iter_mut() { let is_error = errors_clone.contains(enum_item.name()); visitor.visit_enum(is_error, enum_item); for variant in enum_item.variants.iter_mut() { visitor.visit_variant(is_error, variant); for field in variant.fields.iter_mut() { visitor.visit_field(field); visitor.visit_type(&mut field.type_); } } } for record_item in self.records.iter_mut() { visitor.visit_record(record_item); for field in &mut record_item.fields { visitor.visit_field(field); visitor.visit_type(&mut field.type_); } } for function in self.functions.iter_mut() { visitor.visit_function(function); if function.clone().return_type.is_some() { let mut return_type = function.clone().return_type.unwrap(); visitor.visit_type(&mut return_type); function.return_type = Some(return_type); } if let Some(error_type) = function.throws_type() { let mut error_type = error_type.clone(); visitor.visit_type(&mut error_type); function.throws = Some(error_type); } for argument in function.arguments.iter_mut() { visitor.visit_argument(argument); visitor.visit_type(&mut argument.type_); } } for object in self.objects.iter_mut() { // Capture original object name before any renaming let object_name = object.name().to_string(); visitor.visit_object(object); for method in object.methods.iter_mut() { visitor.visit_method(&object_name, method); for argument in method.arguments.iter_mut() { visitor.visit_argument(argument); visitor.visit_type(&mut argument.type_); } if method.clone().return_type.is_some() { let mut return_type = method.clone().return_type.unwrap(); visitor.visit_type(&mut return_type); method.return_type = Some(return_type); } if let Some(error_type) = method.throws_type() { let mut error_type = error_type.clone(); visitor.visit_type(&mut error_type); method.throws = Some(error_type); } } for constructor in object.constructors.iter_mut() { visitor.visit_constructor(&object_name, constructor); for argument in constructor.arguments.iter_mut() { visitor.visit_argument(argument); visitor.visit_type(&mut argument.type_); } } } for callback_interface in self.callback_interfaces.iter_mut() { visitor.visit_callback_interface(callback_interface); for method in callback_interface.methods.iter_mut() { visitor.visit_method(&callback_interface.name, method); for argument in method.arguments.iter_mut() { visitor.visit_argument(argument); visitor.visit_type(&mut argument.type_); } } for ffi_arg in callback_interface.ffi_init_callback.arguments.iter_mut() { visitor.visit_ffi_argument(ffi_arg); } } let mut throw_types_altered: BTreeSet = BTreeSet::new(); for throw_type in self.callback_interface_throws_types.iter() { let mut type_ = throw_type.clone(); visitor.visit_type(&mut type_); throw_types_altered.insert(type_); } self.callback_interface_throws_types = throw_types_altered; for ffi_definition in self.ffi_definitions() { if let FfiDefinition::Struct(mut ffi_struct) = ffi_definition { for field in ffi_struct.fields.iter_mut() { visitor.visit_ffi_field(field); } } } self.errors = self .errors .drain() .map(|mut name| { visitor.visit_error_name(&mut name); name }) .collect() } }