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