diff --git a/internal/compiler/generator/cpp.rs b/internal/compiler/generator/cpp.rs index ba64bc206..5216a33ad 100644 --- a/internal/compiler/generator/cpp.rs +++ b/internal/compiler/generator/cpp.rs @@ -777,6 +777,8 @@ pub fn generate(doc: &Document) -> impl std::fmt::Display { generate_public_component(&mut file, &conditional_includes, &llr); + generate_type_aliases(&mut file, doc); + file.after_includes = format!( "static_assert({x} == SLINT_VERSION_MAJOR && {y} == SLINT_VERSION_MINOR && {z} == SLINT_VERSION_PATCH, \ \"This file was generated with Slint compiler version {x}.{y}.{z}, but the Slint library used is \" \ @@ -3250,3 +3252,31 @@ fn return_compile_expression( } } } + +fn generate_type_aliases(file: &mut File, doc: &Document) { + let type_aliases = doc + .exports + .iter() + .filter_map(|export| match &export.1 { + Either::Left(component) if !component.is_global() => { + Some((&export.0.name, &component.id)) + } + Either::Right(ty) => match &ty { + Type::Struct { name: Some(name), node: Some(_), .. } => { + Some((&export.0.name, name)) + } + Type::Enumeration(en) => Some((&export.0.name, &en.name)), + _ => None, + }, + _ => None, + }) + .filter(|(export_name, type_name)| export_name != type_name) + .map(|(export_name, type_name)| { + Declaration::TypeAlias(TypeAlias { + old_name: ident(&type_name), + new_name: ident(&export_name), + }) + }); + + file.declarations.extend(type_aliases); +} diff --git a/internal/compiler/generator/rust.rs b/internal/compiler/generator/rust.rs index 187321739..4e2ee5a54 100644 --- a/internal/compiler/generator/rust.rs +++ b/internal/compiler/generator/rust.rs @@ -186,6 +186,7 @@ pub fn generate(doc: &Document) -> TokenStream { }); let resource_symbols = generate_resources(doc); + let named_exports = generate_named_exports(doc); quote! { #[allow(non_snake_case)] @@ -210,7 +211,7 @@ pub fn generate(doc: &Document) -> TokenStream { #(#resource_symbols)* const _THE_SAME_VERSION_MUST_BE_USED_FOR_THE_COMPILER_AND_THE_RUNTIME : slint::#version_check = slint::#version_check; } - pub use #compo_module::{#compo_id #(,#structs_and_enums_ids)* #(,#globals_ids)* }; + pub use #compo_module::{#compo_id #(,#structs_and_enums_ids)* #(,#globals_ids)* #(,#named_exports)*}; pub use slint::{ComponentHandle as _, Global as _, ModelExt as _}; } } @@ -2715,3 +2716,28 @@ fn generate_resources(doc: &Document) -> Vec { }) .collect() } + +fn generate_named_exports(doc: &Document) -> Vec { + doc.exports + .iter() + .filter_map(|export| match &export.1 { + Either::Left(component) if !component.is_global() => { + Some((&export.0.name, &component.id)) + } + Either::Right(ty) => match &ty { + Type::Struct { name: Some(name), node: Some(_), .. } => { + Some((&export.0.name, name)) + } + Type::Enumeration(en) => Some((&export.0.name, &en.name)), + _ => None, + }, + _ => None, + }) + .filter(|(export_name, type_name)| export_name != type_name) + .map(|(export_name, type_name)| { + let type_id = ident(&type_name); + let export_id = ident(&export_name); + quote!(#type_id as #export_id) + }) + .collect::>() +} diff --git a/internal/compiler/passes/collect_structs_and_enums.rs b/internal/compiler/passes/collect_structs_and_enums.rs index dc6f14cc0..b18309cb8 100644 --- a/internal/compiler/passes/collect_structs_and_enums.rs +++ b/internal/compiler/passes/collect_structs_and_enums.rs @@ -13,9 +13,9 @@ use std::rc::Rc; pub fn collect_structs_and_enums(doc: &Document) { let mut hash = BTreeMap::new(); - for (name, exp) in doc.exports.iter() { + for (_, exp) in doc.exports.iter() { if let Some(ty) = exp.as_ref().right() { - hash.insert(String::clone(name), ty.clone()); + maybe_collect_object(ty, &mut hash); } } @@ -35,25 +35,25 @@ pub fn collect_structs_and_enums(doc: &Document) { } } -fn collect_types_in_component(root_component: &Rc, hash: &mut BTreeMap) { - let mut maybe_collect_object = |ty: &Type| { - visit_declared_type(ty, &mut |name, sub_ty| { - hash.entry(name.clone()).or_insert_with(|| sub_ty.clone()); - }); - }; +fn maybe_collect_object(ty: &Type, hash: &mut BTreeMap) { + visit_declared_type(ty, &mut |name, sub_ty| { + hash.entry(name.clone()).or_insert_with(|| sub_ty.clone()); + }); +} +fn collect_types_in_component(root_component: &Rc, hash: &mut BTreeMap) { recurse_elem_including_sub_components_no_borrow(root_component, &(), &mut |elem, _| { for x in elem.borrow().property_declarations.values() { - maybe_collect_object(&x.property_type); + maybe_collect_object(&x.property_type, hash); } }); visit_all_expressions(root_component, |expr, _| { expr.visit_recursive(&mut |expr| match expr { - Expression::Struct { ty, .. } => maybe_collect_object(ty), - Expression::Array { element_ty, .. } => maybe_collect_object(element_ty), + Expression::Struct { ty, .. } => maybe_collect_object(ty, hash), + Expression::Array { element_ty, .. } => maybe_collect_object(element_ty, hash), Expression::EnumerationValue(ev) => { - maybe_collect_object(&Type::Enumeration(ev.enumeration.clone())) + maybe_collect_object(&Type::Enumeration(ev.enumeration.clone()), hash) } _ => (), }) diff --git a/tests/cases/exports/named_exports.slint b/tests/cases/exports/named_exports.slint new file mode 100644 index 000000000..c1784d697 --- /dev/null +++ b/tests/cases/exports/named_exports.slint @@ -0,0 +1,26 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.1 OR LicenseRef-Slint-commercial + +//include_path: ../../helper_components +import { ExportedStruct, ExportEnum } from "export_structs.slint"; +export { ExportedStruct as NamedStruct, ExportEnum as NamedEnum } +component TestCase inherits Rectangle { + in-out property st; + in-out property en: ExportEnum.Bonjour; +} +export { TestCase as NamedTestCase } + +/* + +```cpp +auto handle = NamedTestCase::create(); +const TestCase &instance = *handle; +assert(instance.get_en() == NamedEnum::Bonjour); +``` + +```rust +let instance = NamedTestCase::new().unwrap(); +assert_eq!(instance.get_en(), NamedEnum::Bonjour); +``` + +*/