Source code

Revision control

Copy as Markdown

Other Tools

/* 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<V: VisitMut>(&mut self, visitor: &V) {
for type_ in self.types.type_definitions.values_mut() {
visitor.visit_type(type_);
}
let mut all_known_types_altered: BTreeSet<Type> = 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<Type> = 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()
}
}