i_slint_compiler/passes/
unique_id.rs1use crate::diagnostics::BuildDiagnostics;
5use crate::langtype::ElementType;
6use crate::object_tree::*;
7use smol_str::{format_smolstr, SmolStr, ToSmolStr};
8use std::collections::HashMap;
9use std::rc::Rc;
10
11pub fn assign_unique_id(doc: &Document) {
15 let mut count = 0;
16 doc.visit_all_used_components(|component| {
17 if !component.is_global() {
18 assign_unique_id_in_component(component, &mut count)
19 }
20 });
21 rename_globals(doc, count);
22}
23
24fn assign_unique_id_in_component(component: &Rc<Component>, count: &mut u32) {
25 recurse_elem_including_sub_components(component, &(), &mut |elem, _| {
26 *count += 1;
27 let mut elem_mut = elem.borrow_mut();
28 let old_id = if !elem_mut.id.is_empty() {
29 elem_mut.id.clone()
30 } else {
31 elem_mut.base_type.to_smolstr().to_ascii_lowercase().into()
32 };
33 elem_mut.id = format_smolstr!("{}-{}", old_id, count);
34
35 let enclosing = elem_mut.enclosing_component.upgrade().unwrap();
36 if Rc::ptr_eq(elem, &enclosing.root_element) {
37 for o in enclosing.optimized_elements.borrow().iter() {
38 *count += 1;
39 let mut elem_mut = o.borrow_mut();
40 elem_mut.id = format_smolstr!("optimized-{}-{}", elem_mut.id, count);
41 }
42 }
43 });
44}
45
46fn rename_globals(doc: &Document, mut count: u32) {
48 for g in &doc.used_types.borrow().globals {
49 count += 1;
50 let mut root = g.root_element.borrow_mut();
51 if matches!(&root.base_type, ElementType::Builtin(_)) {
52 root.id.clone_from(&g.id);
54 } else if let Some(s) = g.exported_global_names.borrow().first() {
55 root.id = s.to_smolstr();
56 } else {
57 root.id = format_smolstr!("{}-{}", g.id, count);
58 }
59 }
60}
61
62pub fn check_unique_id(doc: &Document, diag: &mut BuildDiagnostics) {
64 for component in &doc.inner_components {
65 check_unique_id_in_component(component, diag);
66 }
67}
68
69fn check_unique_id_in_component(component: &Rc<Component>, diag: &mut BuildDiagnostics) {
70 struct SeenId {
71 element: ElementRc,
72 error_reported: bool,
73 }
74 let mut seen_ids: HashMap<SmolStr, SeenId> = HashMap::new();
75
76 recurse_elem(&component.root_element, &(), &mut |elem, _| {
77 let elem_bor = elem.borrow();
78 let id = &elem_bor.id;
79 if !id.is_empty() {
80 if let Some(other_loc) = seen_ids.get_mut(id) {
81 debug_assert!(!Rc::ptr_eq(&other_loc.element, elem));
82 let message = format!("duplicated element id '{id}'");
83 if !other_loc.error_reported {
84 diag.push_error(message.clone(), &*other_loc.element.borrow());
85 other_loc.error_reported = true;
86 }
87 diag.push_error(message, &*elem_bor);
88 } else {
89 seen_ids
90 .insert(id.clone(), SeenId { element: elem.clone(), error_reported: false });
91 }
92 }
93 })
94}