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