1mod apply_default_properties_from_style;
5mod binding_analysis;
6mod border_radius;
7mod check_builtin_shadowing;
8mod check_drag_area;
9mod check_expressions;
10mod check_public_api;
11mod clip;
12mod collect_custom_fonts;
13mod collect_globals;
14mod collect_init_code;
15mod collect_libraries;
16mod collect_structs_and_enums;
17mod collect_subcomponents;
18mod compile_paths;
19mod const_propagation;
20mod deduplicate_property_read;
21mod default_geometry;
22mod deprecated_rotation_origin;
23#[cfg(feature = "software-renderer")]
24mod embed_glyphs;
25mod embed_images;
26mod flickable;
27mod focus_handling;
28pub mod generate_item_indices;
29pub mod infer_aliases_types;
30mod inject_debug_hooks;
31mod inlining;
32mod key_bindings;
33mod lower_absolute_coordinates;
34mod lower_accessibility;
35mod lower_component_container;
36mod lower_layout;
37mod lower_menus;
38mod lower_platform;
39mod lower_popups;
40mod lower_property_to_element;
41mod lower_radiogroup;
42mod lower_repeated_rows;
43mod lower_shadows;
44mod lower_states;
45mod lower_tabwidget;
46mod lower_text_input_interface;
47mod lower_timers;
48mod lower_tooltips;
49pub mod materialize_fake_properties;
50pub mod move_declarations;
51mod optimize_useless_rectangles;
52mod purity_check;
53mod remove_aliases;
54mod remove_return;
55mod remove_unused_properties;
56mod repeater_component;
57pub mod resolve_native_classes;
58pub mod resolving;
59mod unique_id;
60mod visible;
61mod windows;
62mod z_order;
63
64use crate::expression_tree::Expression;
65use smol_str::SmolStr;
66
67pub use binding_analysis::GlobalAnalysis;
68
69pub fn ignore_debug_hooks(expr: &Expression) -> &Expression {
70 let mut expr = expr;
71 loop {
72 match expr {
73 Expression::DebugHook { expression, .. } => expr = expression.as_ref(),
74 _ => return expr,
75 }
76 }
77}
78
79pub async fn run_passes(
80 doc: &mut crate::object_tree::Document,
81 type_loader: &mut crate::typeloader::TypeLoader,
82 keep_raw: bool,
83 diag: &mut crate::diagnostics::BuildDiagnostics,
84) -> Option<crate::typeloader::TypeLoader> {
85 let style_metrics = {
86 let mut build_diags_to_ignore = crate::diagnostics::BuildDiagnostics::default();
88 type_loader
91 .import_component("style-base.slint", "StyleMetrics", &mut build_diags_to_ignore)
92 .await
93 .unwrap_or_else(|| panic!("can't load style metrics"))
94 };
95
96 let palette = {
97 let mut build_diags_to_ignore = crate::diagnostics::BuildDiagnostics::default();
99 type_loader
102 .import_component("style-base.slint", "Palette", &mut build_diags_to_ignore)
103 .await
104 .unwrap_or_else(|| panic!("can't load palette"))
105 };
106
107 let global_type_registry = type_loader.global_type_registry.clone();
108
109 run_import_passes(doc, type_loader, diag);
110 check_public_api::check_public_api(doc, &type_loader.compiler_config, diag);
111
112 let raw_type_loader =
113 keep_raw.then(|| crate::typeloader::snapshot_with_extra_doc(type_loader, doc).unwrap());
114
115 collect_libraries::collect_libraries(doc);
116 collect_subcomponents::collect_subcomponents(doc);
117 lower_tooltips::lower_tooltips(doc, type_loader, diag).await;
118 lower_tabwidget::lower_tabwidget(doc, type_loader, diag).await;
119 lower_radiogroup::lower_radiogroup(doc, type_loader, diag).await;
120 lower_menus::lower_menus(doc, type_loader, diag).await;
121 lower_component_container::lower_component_container(doc, type_loader, diag);
122 collect_subcomponents::collect_subcomponents(doc);
123
124 doc.visit_all_used_components(|component| {
125 apply_default_properties_from_style::apply_default_properties_from_style(
126 component,
127 &style_metrics,
128 &palette,
129 diag,
130 );
131 lower_states::lower_states(component, diag);
132 lower_text_input_interface::lower_text_input_interface(component);
133 compile_paths::compile_paths(component, &doc.local_registry, diag);
134 repeater_component::process_repeater_components(component);
135 lower_popups::lower_popups(component, &doc.local_registry, diag);
136 collect_init_code::collect_init_code(component);
137 lower_timers::lower_timers(component, diag);
138 });
139
140 inlining::inline(doc, inlining::InlineSelection::InlineOnlyRequiredComponents, diag);
141 collect_subcomponents::collect_subcomponents(doc);
142
143 for root_component in doc.exported_roots() {
144 focus_handling::call_focus_on_init(&root_component);
145 windows::ensure_window(&root_component, &doc.local_registry, &style_metrics, diag);
146 }
147 if let Some(popup_menu_impl) = &doc.popup_menu_impl {
148 focus_handling::call_focus_on_init(popup_menu_impl);
149 }
150
151 doc.visit_all_used_components(|component| {
152 border_radius::handle_border_radius(component, diag);
153 check_drag_area::check_drag_area(component, diag);
154 deprecated_rotation_origin::handle_rotation_origin(component, diag);
155 flickable::handle_flickable(component, &global_type_registry.borrow());
156 lower_layout::lower_layouts(component, type_loader, &style_metrics, diag);
157 default_geometry::default_geometry(component, diag);
158 lower_layout::synthesize_layoutinfo_v_with_constraint(component);
159 lower_layout::synthesize_layoutinfo_h_with_constraint(component);
160 lower_absolute_coordinates::lower_absolute_coordinates(component);
161 z_order::reorder_by_z_order(component, diag);
162 lower_property_to_element::lower_property_to_element(
163 component,
164 core::iter::once("opacity"),
165 core::iter::empty(),
166 None,
167 &SmolStr::new_static("Opacity"),
168 &global_type_registry.borrow(),
169 diag,
170 );
171 lower_property_to_element::lower_property_to_element(
172 component,
173 core::iter::once("cache-rendering-hint"),
174 core::iter::empty(),
175 None,
176 &SmolStr::new_static("Layer"),
177 &global_type_registry.borrow(),
178 diag,
179 );
180 visible::handle_visible(component, &global_type_registry.borrow(), diag);
181 lower_shadows::lower_shadow_properties(component, &doc.local_registry, diag);
182 lower_property_to_element::lower_transform_properties(
183 component,
184 &global_type_registry.borrow(),
185 diag,
186 );
187 clip::handle_clip(component, &global_type_registry.borrow(), diag);
188 if type_loader.compiler_config.accessibility {
189 lower_accessibility::lower_accessibility_properties(component, diag);
190 }
191 lower_repeated_rows::lower_repeated_rows(component, &global_type_registry.borrow());
192 materialize_fake_properties::materialize_fake_properties(component);
193 lower_layout::check_popup_layout(component);
194 });
195 for root_component in doc.exported_roots() {
196 lower_layout::check_window_layout(&root_component);
197 }
198 collect_globals::collect_globals(doc, diag);
199
200 if type_loader.compiler_config.inline_all_elements {
201 inlining::inline(doc, inlining::InlineSelection::InlineAllComponents, diag);
202 doc.used_types.borrow_mut().sub_components.clear();
203 }
204
205 let global_analysis =
206 binding_analysis::binding_analysis(doc, &type_loader.compiler_config, diag);
207 collect_globals::mark_library_globals(doc);
208 unique_id::assign_unique_id(doc);
209
210 doc.visit_all_used_components(|component| {
211 key_bindings::warn_duplicates(component, diag);
212 lower_platform::lower_platform(component, type_loader);
213
214 if !type_loader.compiler_config.debug_info {
219 optimize_useless_rectangles::optimize_useless_rectangles(component);
220 }
221 move_declarations::move_declarations(component);
222 });
223
224 remove_aliases::remove_aliases(doc, diag);
225 remove_return::remove_return(doc);
226
227 doc.visit_all_used_components(|component| {
228 if !diag.has_errors() {
229 const_propagation::const_propagation(component, &global_analysis);
231 }
232 deduplicate_property_read::deduplicate_property_read(component);
233 if !component.is_global() && !component.is_interface() {
234 resolve_native_classes::resolve_native_classes(component);
235 }
236 });
237
238 remove_unused_properties::remove_unused_properties(doc);
239 collect_globals::collect_globals(doc, diag);
241 collect_structs_and_enums::collect_structs_and_enums(doc);
242
243 doc.visit_all_used_components(|component| {
244 if !component.is_global() {
245 generate_item_indices::generate_item_indices(component);
246 }
247 });
248
249 #[cfg(feature = "software-renderer")]
252 let font_collection = (type_loader.compiler_config.embed_resources
253 == crate::EmbedResourcesKind::EmbedTextures)
254 .then(|| {
255 let custom = embed_glyphs::read_custom_fonts(
256 std::iter::once(&*doc).chain(type_loader.all_documents()),
257 diag,
258 );
259 embed_glyphs::shared_font_collection(custom)
260 });
261 #[cfg(not(feature = "software-renderer"))]
262 let font_collection: Option<embed_images::SharedFontCollection> = None;
263
264 embed_images::embed_images(
265 doc,
266 type_loader.compiler_config.embed_resources,
267 type_loader.compiler_config.const_scale_factor.unwrap_or(1.),
268 &type_loader.compiler_config.resource_url_mapper,
269 font_collection.as_ref(),
270 diag,
271 )
272 .await;
273
274 #[cfg(feature = "bundle-translations")]
275 if let Some(path) = &type_loader.compiler_config.translation_path_bundle {
276 match crate::translations::TranslationsBuilder::load_translations(
277 path,
278 type_loader.compiler_config.translation_domain.as_deref().unwrap_or(""),
279 ) {
280 Ok(builder) => {
281 doc.translation_builder = Some(builder);
282 }
283 Err(err) => {
284 diag.push_error(
285 format!("Cannot load bundled translation: {err}"),
286 doc.node.as_ref().expect("Unexpected empty document"),
287 );
288 }
289 }
290 }
291
292 match type_loader.compiler_config.embed_resources {
293 #[cfg(feature = "software-renderer")]
294 crate::EmbedResourcesKind::EmbedTextures => {
295 let mut characters_seen = std::collections::HashSet::new();
296
297 let sf = type_loader.compiler_config.const_scale_factor.unwrap_or(1.) as f64;
298
299 let mut font_pixel_sizes = vec![(12. * sf) as i16];
301 use i_slint_common::sharedfontique::fontique;
302 let mut font_weights = vec![fontique::FontWeight::NORMAL.value() as u16];
303 doc.visit_all_used_components(|component| {
304 embed_glyphs::collect_font_sizes_used(component, sf, &mut font_pixel_sizes);
305 embed_glyphs::collect_font_weights_used(component, &mut font_weights);
306 embed_glyphs::scan_string_literals(component, &mut characters_seen);
307 });
308
309 #[cfg(feature = "bundle-translations")]
311 if let Some(translation_builder) = doc.translation_builder.as_ref() {
312 translation_builder.collect_characters_seen(&mut characters_seen);
313 }
314
315 embed_glyphs::embed_glyphs(
316 doc,
317 &type_loader.compiler_config,
318 font_pixel_sizes,
319 font_weights,
320 characters_seen,
321 font_collection.as_ref().expect("EmbedTextures builds the shared font collection"),
322 diag,
323 );
324 }
325 _ => {
326 collect_custom_fonts::collect_custom_fonts(
328 doc,
329 std::iter::once(&*doc).chain(type_loader.all_documents()),
330 type_loader.compiler_config.embed_resources
331 == crate::EmbedResourcesKind::EmbedAllResources,
332 );
333 }
334 };
335
336 raw_type_loader
337}
338
339pub fn run_import_passes(
341 doc: &crate::object_tree::Document,
342 type_loader: &crate::typeloader::TypeLoader,
343 diag: &mut crate::diagnostics::BuildDiagnostics,
344) {
345 inject_debug_hooks::inject_debug_hooks(doc, type_loader);
346 infer_aliases_types::resolve_aliases(doc, diag);
347 resolving::resolve_expressions(doc, type_loader, diag);
348 purity_check::purity_check(doc, diag);
349 focus_handling::replace_forward_focus_bindings_with_focus_functions(doc, diag);
350 check_expressions::check_expressions(doc, diag);
351 check_builtin_shadowing::check_builtin_shadowing(doc, diag);
352 windows::warn_about_child_windows(doc, diag);
353 unique_id::check_unique_id(doc, diag);
354}