From 5dfa8d56dc13b80af361e598fa07ffad106ca761 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 5 Jul 2024 14:59:59 +0200 Subject: [PATCH] API review of the slint interpreter Compiler api Closes #5466 --- .../src/interpreter/component_compiler.rs | 4 +- api/rs/build/lib.rs | 4 +- api/rs/macros/lib.rs | 4 +- internal/compiler/diagnostics.rs | 8 +-- internal/compiler/lib.rs | 24 ++++---- internal/compiler/load_builtins.rs | 2 +- internal/compiler/object_tree.rs | 16 +++--- internal/compiler/parser-test-macro/lib.rs | 2 +- internal/compiler/parser.rs | 2 +- internal/compiler/passes.rs | 2 +- internal/compiler/passes/check_expressions.rs | 2 +- internal/compiler/passes/check_public_api.rs | 12 ++-- internal/compiler/passes/const_propagation.rs | 2 +- internal/compiler/passes/default_geometry.rs | 2 +- internal/compiler/passes/focus_handling.rs | 4 +- .../compiler/passes/infer_aliases_types.rs | 8 +-- internal/compiler/passes/lower_layout.rs | 2 +- internal/compiler/passes/lower_tabwidget.rs | 2 +- internal/compiler/passes/resolving.rs | 20 +++---- internal/compiler/tests/consistent_styles.rs | 2 +- internal/compiler/tests/syntax_tests.rs | 10 ++-- internal/compiler/typeloader.rs | 42 +++++++------- internal/interpreter/api.rs | 55 ++++++++++++++----- internal/interpreter/dynamic_item_tree.rs | 9 ++- internal/interpreter/lib.rs | 2 +- internal/interpreter/tests.rs | 4 +- tests/doctests/main.rs | 2 +- tests/driver/cpp/cppdriver.rs | 4 +- tests/driver/interpreter/interpreter.rs | 2 +- tests/driver/rust/build.rs | 2 +- tests/screenshots/build.rs | 2 +- tools/compiler/main.rs | 2 +- tools/lsp/common.rs | 2 +- tools/lsp/common/properties.rs | 4 +- tools/lsp/common/test.rs | 2 +- tools/lsp/fmt/tool.rs | 6 +- tools/lsp/preview.rs | 6 +- tools/lsp/preview/drop_location.rs | 2 +- tools/updater/main.rs | 6 +- tools/viewer/main.rs | 18 +++--- 40 files changed, 169 insertions(+), 137 deletions(-) diff --git a/api/node/src/interpreter/component_compiler.rs b/api/node/src/interpreter/component_compiler.rs index 3dfb12cd646..faeabb3a249 100644 --- a/api/node/src/interpreter/component_compiler.rs +++ b/api/node/src/interpreter/component_compiler.rs @@ -106,7 +106,7 @@ impl JsComponentCompiler { pub fn build_from_path(&mut self, path: String) -> HashMap { let r = spin_on::spin_on(self.internal.build_from_path(PathBuf::from(path))); self.diagnostics = r.diagnostics().collect(); - r.component_names().filter_map(|n| Some((n.to_owned(), r.component(n)?.into()))).collect() + r.components().map(|c| (c.name().to_owned(), c.into())).collect() } /// Compile some .slint code into a ComponentDefinition @@ -118,6 +118,6 @@ impl JsComponentCompiler { ) -> HashMap { let r = spin_on::spin_on(self.internal.build_from_source(source_code, PathBuf::from(path))); self.diagnostics = r.diagnostics().collect(); - r.component_names().filter_map(|n| Some((n.to_owned(), r.component(n)?.into()))).collect() + r.components().map(|c| (c.name().to_owned(), c.into())).collect() } } diff --git a/api/rs/build/lib.rs b/api/rs/build/lib.rs index 9f06ee318f3..157a76125e6 100644 --- a/api/rs/build/lib.rs +++ b/api/rs/build/lib.rs @@ -362,7 +362,7 @@ pub fn compile_with_config( let mut diag = BuildDiagnostics::default(); let syntax_node = i_slint_compiler::parser::parse_file(&path, &mut diag); - if diag.has_error() { + if diag.has_errors() { let vec = diag.to_string_vec(); diag.print(); return Err(CompileError::CompileError(vec)); @@ -377,7 +377,7 @@ pub fn compile_with_config( let (doc, diag, loader) = spin_on::spin_on(i_slint_compiler::compile_syntax_node(syntax_node, diag, compiler_config)); - if diag.has_error() { + if diag.has_errors() { let vec = diag.to_string_vec(); diag.print(); return Err(CompileError::CompileError(vec)); diff --git a/api/rs/macros/lib.rs b/api/rs/macros/lib.rs index ff7faef86da..f30d4d023fc 100644 --- a/api/rs/macros/lib.rs +++ b/api/rs/macros/lib.rs @@ -388,7 +388,7 @@ pub fn slint(stream: TokenStream) -> TokenStream { }; let mut diag = BuildDiagnostics::default(); let syntax_node = parser::parse_tokens(tokens.clone(), source_file, &mut diag); - if diag.has_error() { + if diag.has_errors() { return diag.report_macro_diagnostic(&tokens); } @@ -397,7 +397,7 @@ pub fn slint(stream: TokenStream) -> TokenStream { let (root_component, diag, loader) = spin_on::spin_on(compile_syntax_node(syntax_node, diag, compiler_config)); //println!("{:#?}", tree); - if diag.has_error() { + if diag.has_errors() { return diag.report_macro_diagnostic(&tokens); } diff --git a/internal/compiler/diagnostics.rs b/internal/compiler/diagnostics.rs index 2eeb3147c27..318ccc3162d 100644 --- a/internal/compiler/diagnostics.rs +++ b/internal/compiler/diagnostics.rs @@ -367,7 +367,7 @@ impl BuildDiagnostics { } /// Return true if there is at least one compilation error for this file - pub fn has_error(&self) -> bool { + pub fn has_errors(&self) -> bool { self.inner.iter().any(|diag| diag.level == DiagnosticLevel::Error) } @@ -467,7 +467,7 @@ impl BuildDiagnostics { span_map: &[crate::parser::Token], ) -> proc_macro::TokenStream { let mut result = proc_macro::TokenStream::default(); - let mut needs_error = self.has_error(); + let mut needs_error = self.has_errors(); self.call_diagnostics( &mut (), Some(&mut |diag| { @@ -543,7 +543,7 @@ impl BuildDiagnostics { #[cfg(feature = "display-diagnostics")] #[must_use] pub fn check_and_exit_on_error(self) -> Self { - if self.has_error() { + if self.has_errors() { self.print(); std::process::exit(-1); } @@ -552,7 +552,7 @@ impl BuildDiagnostics { #[cfg(feature = "display-diagnostics")] pub fn print_warnings_and_exit_on_error(self) { - let has_error = self.has_error(); + let has_error = self.has_errors(); self.print(); if has_error { std::process::exit(-1); diff --git a/internal/compiler/lib.rs b/internal/compiler/lib.rs index 8dacbc50c11..9c1b2424fec 100644 --- a/internal/compiler/lib.rs +++ b/internal/compiler/lib.rs @@ -54,20 +54,24 @@ pub enum EmbedResourcesKind { EmbedTextures, } -#[derive(Clone, Debug, Eq, PartialEq)] -pub enum ComponentsToGenerate { - /// All exported Windows. +#[derive(Clone, Debug, Eq, PartialEq, Default)] +#[non_exhaustive] +pub enum ComponentSelection { + /// All components that inherit from Window. /// - /// When set, there will be a warning if an exported component is not a window. - AllExportedWindows, + /// Note: Components marked for export but lacking Window inheritance are not selected (this will produce a warning), + /// For compatibility reason, the last exported component is still selected even if it doesn't inherit Window, + /// and if no component is exported, the last component is selected + #[default] + ExportedWindows, /// The Last component (legacy for the viewer / interpreter) /// Only the last exported component is generated, regardless if this is a Window or not, /// (and it will be transformed in a Window) - LastComponent, + LastExported, /// The component with the given name is generated - ComponentWithName(String), + Named(String), } /// CompilationConfiguration allows configuring different aspects of the compiler. @@ -120,7 +124,7 @@ pub struct CompilerConfiguration { /// Generate debug information for elements (ids, type names) pub debug_info: bool, - pub components_to_generate: ComponentsToGenerate, + pub components_to_generate: ComponentSelection, } impl CompilerConfiguration { @@ -195,7 +199,7 @@ impl CompilerConfiguration { translation_domain: None, cpp_namespace, debug_info, - components_to_generate: ComponentsToGenerate::AllExportedWindows, + components_to_generate: ComponentSelection::ExportedWindows, } } } @@ -244,7 +248,7 @@ pub async fn compile_syntax_node( &type_registry, ); - if !diagnostics.has_error() { + if !diagnostics.has_errors() { passes::run_passes(&mut doc, &mut loader, false, &mut diagnostics).await; } else { // Don't run all the passes in case of errors because because some invariants are not met. diff --git a/internal/compiler/load_builtins.rs b/internal/compiler/load_builtins.rs index f1e743a11cb..009c002ff27 100644 --- a/internal/compiler/load_builtins.rs +++ b/internal/compiler/load_builtins.rs @@ -243,7 +243,7 @@ fn compiled( &mut crate::lookup::LookupCtx::empty_context(type_register, &mut diag), ) .maybe_convert_to(ty, &node, &mut diag); - if diag.has_error() { + if diag.has_errors() { let vec = diag.to_string_vec(); #[cfg(feature = "display-diagnostics")] diag.print(); diff --git a/internal/compiler/object_tree.rs b/internal/compiler/object_tree.rs index b6b3ea2f545..94bc02c1d7b 100644 --- a/internal/compiler/object_tree.rs +++ b/internal/compiler/object_tree.rs @@ -31,7 +31,7 @@ macro_rules! unwrap_or_continue { match $e { Some(x) => x, None => { - debug_assert!($diag.has_error()); // error should have been reported at parsing time + debug_assert!($diag.has_errors()); // error should have been reported at parsing time continue; } } @@ -91,7 +91,7 @@ impl Document { if let Type::Struct { name, .. } = &mut ty { *name = parser::identifier_text(&n.DeclaredIdentifier()); } else { - assert!(diag.has_error()); + assert!(diag.has_errors()); return; } local_registry.insert_type(ty.clone()); @@ -102,7 +102,7 @@ impl Document { local_registry: &mut TypeRegister, inner_types: &mut Vec| { let Some(name) = parser::identifier_text(&n.DeclaredIdentifier()) else { - assert!(diag.has_error()); + assert!(diag.has_errors()); return; }; let mut existing_names = HashSet::new(); @@ -929,7 +929,7 @@ impl Element { ElementType::Global } else if parent_type != ElementType::Error { // This should normally never happen because the parser does not allow for this - assert!(diag.has_error()); + assert!(diag.has_errors()); return ElementRc::default(); } else { tr.empty_type() @@ -1195,7 +1195,7 @@ impl Element { .insert(name.clone(), BindingExpression::new_uncompiled(func.clone().into()).into()) .is_some() { - assert!(diag.has_error()); + assert!(diag.has_errors()); } let mut visibility = PropertyVisibility::Private; @@ -1868,7 +1868,7 @@ pub fn type_from_node( } else if let Some(array_node) = node.ArrayType() { Type::Array(Box::new(type_from_node(array_node.Type(), diag, tr))) } else { - assert!(diag.has_error()); + assert!(diag.has_errors()); Type::Invalid } } @@ -2490,7 +2490,7 @@ impl Exports { let name_ident: SyntaxNode = component.DeclaredIdentifier().into(); let name = parser::identifier_text(&component.DeclaredIdentifier()).unwrap_or_else(|| { - debug_assert!(diag.has_error()); + debug_assert!(diag.has_errors()); String::new() }); @@ -2512,7 +2512,7 @@ impl Exports { }) .filter_map(|name_ident| { let name = parser::identifier_text(&name_ident).unwrap_or_else(|| { - debug_assert!(diag.has_error()); + debug_assert!(diag.has_errors()); String::new() }); diff --git a/internal/compiler/parser-test-macro/lib.rs b/internal/compiler/parser-test-macro/lib.rs index fd1bcabc08b..629207c1949 100644 --- a/internal/compiler/parser-test-macro/lib.rs +++ b/internal/compiler/parser-test-macro/lib.rs @@ -68,7 +68,7 @@ fn generate_test(fn_name: &str, doc: &str, extra_args: usize) -> String { let mut diag = Default::default(); let mut p = DefaultParser::new("{line}", &mut diag); {fn_name}(&mut p{follow_args}); - let has_error = p.diags.has_error(); + let has_error = p.diags.has_errors(); //#[cfg(feature = "display-diagnostics")] //p.diags.print(); assert!(!has_error); diff --git a/internal/compiler/parser.rs b/internal/compiler/parser.rs index 8f7284109ec..eac80cff02a 100644 --- a/internal/compiler/parser.rs +++ b/internal/compiler/parser.rs @@ -980,7 +980,7 @@ pub fn parse_expression_as_bindingexpression( }; let node = rowan::SyntaxNode::new_root(p.builder.finish()); - if !build_diagnostics.has_error() && token.kind() != SyntaxKind::Eof { + if !build_diagnostics.has_errors() && token.kind() != SyntaxKind::Eof { build_diagnostics.push_error_with_span( format!("Expected end of string, found \"{}\"", &token.kind()), crate::diagnostics::SourceLocation { diff --git a/internal/compiler/passes.rs b/internal/compiler/passes.rs index 2d13dc5ea80..ccb788c20ac 100644 --- a/internal/compiler/passes.rs +++ b/internal/compiler/passes.rs @@ -189,7 +189,7 @@ pub async fn run_passes( remove_return::remove_return(doc); doc.visit_all_used_components(|component| { - if !diag.has_error() { + if !diag.has_errors() { // binding loop causes panics in const_propagation const_propagation::const_propagation(component); } diff --git a/internal/compiler/passes/check_expressions.rs b/internal/compiler/passes/check_expressions.rs index 325b0134712..e649d85242e 100644 --- a/internal/compiler/passes/check_expressions.rs +++ b/internal/compiler/passes/check_expressions.rs @@ -20,7 +20,7 @@ fn check_expression(component: &Rc, e: &Expression, diag: &mut BuildD match e { Expression::MemberFunction { .. } => { // Must already have been be reported. - debug_assert!(diag.has_error()); + debug_assert!(diag.has_errors()); } Expression::BuiltinMacroReference(_, node) => { diag.push_error("Builtin function must be called".into(), node); diff --git a/internal/compiler/passes/check_public_api.rs b/internal/compiler/passes/check_public_api.rs index 54807b1cff9..ce76c594259 100644 --- a/internal/compiler/passes/check_public_api.rs +++ b/internal/compiler/passes/check_public_api.rs @@ -8,7 +8,7 @@ use std::rc::Rc; use crate::diagnostics::{BuildDiagnostics, DiagnosticLevel}; use crate::langtype::ElementType; use crate::object_tree::{Component, Document, ExportedName, PropertyVisibility}; -use crate::{CompilerConfiguration, ComponentsToGenerate}; +use crate::{CompilerConfiguration, ComponentSelection}; use itertools::Either; pub fn check_public_api( @@ -18,9 +18,7 @@ pub fn check_public_api( ) { let last = doc.last_exported_component(); - if last.is_none() - && !matches!(&config.components_to_generate, ComponentsToGenerate::ComponentWithName(_)) - { + if last.is_none() && !matches!(&config.components_to_generate, ComponentSelection::Named(_)) { let last_imported = doc .node .as_ref() @@ -36,7 +34,7 @@ pub fn check_public_api( } match &config.components_to_generate { - ComponentsToGenerate::AllExportedWindows => doc.exports.retain(|export| { + ComponentSelection::ExportedWindows => doc.exports.retain(|export| { // Warn about exported non-window (and remove them from the export unless it's the last for compatibility) if let Either::Left(c) = &export.1 { if !c.is_global() && !super::ensure_window::inherits_window(c) { @@ -52,7 +50,7 @@ pub fn check_public_api( true }), // Only keep the last component if there is one - ComponentsToGenerate::LastComponent => doc.exports.retain(|export| { + ComponentSelection::LastExported => doc.exports.retain(|export| { if let Either::Left(c) = &export.1 { c.is_global() || last.as_ref().map_or(true, |last| Rc::ptr_eq(last, c)) } else { @@ -60,7 +58,7 @@ pub fn check_public_api( } }), // Only keep the component with the given name - ComponentsToGenerate::ComponentWithName(name) => { + ComponentSelection::Named(name) => { doc.exports.retain(|export| { if let Either::Left(c) = &export.1 { c.is_global() || &c.id == name diff --git a/internal/compiler/passes/const_propagation.rs b/internal/compiler/passes/const_propagation.rs index 6022fbfa259..2df784170f5 100644 --- a/internal/compiler/passes/const_propagation.rs +++ b/internal/compiler/passes/const_propagation.rs @@ -222,7 +222,7 @@ export component Foo { ); let (doc, diag, _) = spin_on::spin_on(crate::compile_syntax_node(doc_node, test_diags, compiler_config)); - assert!(!diag.has_error()); + assert!(!diag.has_errors()); let out_binding = doc .inner_components diff --git a/internal/compiler/passes/default_geometry.rs b/internal/compiler/passes/default_geometry.rs index df6f51bc58c..316a747469e 100644 --- a/internal/compiler/passes/default_geometry.rs +++ b/internal/compiler/passes/default_geometry.rs @@ -485,7 +485,7 @@ fn test_no_property_for_100pc() { ); let (doc, diag, _) = spin_on::spin_on(crate::compile_syntax_node(doc_node, test_diags, compiler_config)); - assert!(!diag.has_error(), "{:?}", diag.to_string_vec()); + assert!(!diag.has_errors(), "{:?}", diag.to_string_vec()); let root_elem = doc.inner_components.last().unwrap().root_element.borrow(); diff --git a/internal/compiler/passes/focus_handling.rs b/internal/compiler/passes/focus_handling.rs index 79c76250b3e..ef19bdb9be8 100644 --- a/internal/compiler/passes/focus_handling.rs +++ b/internal/compiler/passes/focus_handling.rs @@ -99,7 +99,7 @@ impl<'a> LocalFocusForwards<'a> { let Expression::ElementReference(focus_target) = &forward_focus_binding.expression else { // resolve expressions pass has produced type errors - debug_assert!(diag.has_error()); + debug_assert!(diag.has_errors()); return; }; @@ -178,7 +178,7 @@ impl<'a> LocalFocusForwards<'a> { } if arguments.len() != 1 { assert!( - self.diag.has_error(), + self.diag.has_errors(), "Invalid argument generated for {} call", focus_function.name() ); diff --git a/internal/compiler/passes/infer_aliases_types.rs b/internal/compiler/passes/infer_aliases_types.rs index bc932343686..63be5339a93 100644 --- a/internal/compiler/passes/infer_aliases_types.rs +++ b/internal/compiler/passes/infer_aliases_types.rs @@ -71,7 +71,7 @@ fn resolve_alias( Type::InferredCallback | Type::InferredProperty )); // It is still unresolved because there is an error in that component - assert!(diag.has_error()); + assert!(diag.has_errors()); return; } }; @@ -79,14 +79,14 @@ fn resolve_alias( let borrow = elem.borrow(); let Some(binding) = borrow.bindings.get(prop) else { - assert!(diag.has_error()); + assert!(diag.has_errors()); return; }; let nr = match &binding.borrow().expression { Expression::Uncompiled(node) => { let Some(node) = syntax_nodes::TwoWayBinding::new(node.clone()) else { assert!( - diag.has_error(), + diag.has_errors(), "The parser only avoid missing types for two way bindings" ); return; @@ -135,7 +135,7 @@ fn resolve_alias( } else if old_type == Type::InferredCallback { if !matches!(ty, Type::Callback { .. }) { if nr.is_some() && ty == Type::Invalid { - debug_assert!(diag.has_error()); + debug_assert!(diag.has_errors()); } else { diag.push_error( format!("Binding to callback '{}' must bind to another callback", prop), diff --git a/internal/compiler/passes/lower_layout.rs b/internal/compiler/passes/lower_layout.rs index 365ce8c8b73..30d7c609a46 100644 --- a/internal/compiler/passes/lower_layout.rs +++ b/internal/compiler/passes/lower_layout.rs @@ -97,7 +97,7 @@ fn lower_element_layout( // We shouldn't lower layout if we have a Row in there. Unless the Row is the root of a repeated item, // in which case another error has been reported assert!( - diag.has_error() + diag.has_errors() && Rc::ptr_eq(&component.root_element, elem) && component .parent_element diff --git a/internal/compiler/passes/lower_tabwidget.rs b/internal/compiler/passes/lower_tabwidget.rs index 6dcc6eebdbe..5d087af06b4 100644 --- a/internal/compiler/passes/lower_tabwidget.rs +++ b/internal/compiler/passes/lower_tabwidget.rs @@ -77,7 +77,7 @@ fn process_tabwidget( continue; } if child.borrow().base_type.to_string() != "Tab" { - assert!(diag.has_error()); + assert!(diag.has_errors()); continue; } let index = tabs.len(); diff --git a/internal/compiler/passes/resolving.rs b/internal/compiler/passes/resolving.rs index 2376ecc4dd5..bfc06ed5ad9 100644 --- a/internal/compiler/passes/resolving.rs +++ b/internal/compiler/passes/resolving.rs @@ -63,11 +63,11 @@ fn resolve_expression( &mut lookup_ctx, ), SyntaxKind::TwoWayBinding => { - assert!(diag.has_error(), "Two way binding should have been resolved already (property: {property_name:?})"); + assert!(diag.has_errors(), "Two way binding should have been resolved already (property: {property_name:?})"); Expression::Invalid } _ => { - debug_assert!(diag.has_error()); + debug_assert!(diag.has_errors()); Expression::Invalid } }; @@ -166,7 +166,7 @@ impl Expression { e.maybe_convert_to(ctx.property_type.clone(), &node, ctx.diag) } else { // Binding to a callback or function shouldn't happen - assert!(ctx.diag.has_error()); + assert!(ctx.diag.has_errors()); e } } @@ -395,7 +395,7 @@ impl Expression { [x, y, z, w] => Some([*x, *y, *z, *w]), [] => None, _ => { - assert!(ctx.diag.has_error()); + assert!(ctx.diag.has_errors()); None } }; @@ -748,7 +748,7 @@ impl Expression { first } else { // There must be at least one member (parser should ensure that) - debug_assert!(ctx.diag.has_error()); + debug_assert!(ctx.diag.has_errors()); return Self::Invalid; }; @@ -936,7 +936,7 @@ impl Expression { } } Type::Invalid => { - debug_assert!(ctx.diag.has_error()); + debug_assert!(ctx.diag.has_errors()); arguments.into_iter().map(|x| x.0).collect() } _ => { @@ -1125,7 +1125,7 @@ impl Expression { exp } _ => { - assert!(ctx.diag.has_error()); + assert!(ctx.diag.has_errors()); exp } }; @@ -1443,7 +1443,7 @@ fn continue_lookup_within_element( ElementType::Builtin(b) => format!("Element '{}'", b.name), ElementType::Native(_) => unreachable!("the native pass comes later"), ElementType::Error => { - assert!(ctx.diag.has_error()); + assert!(ctx.diag.has_errors()); return; } }; @@ -1522,7 +1522,7 @@ fn resolve_two_way_bindings( let lhs_lookup = elem.borrow().lookup_property(prop_name); if lhs_lookup.property_type == Type::Invalid { // An attempt to resolve this already failed when trying to resolve the property type - assert!(diag.has_error()); + assert!(diag.has_errors()); continue; } let mut lookup_ctx = LookupCtx { @@ -1674,7 +1674,7 @@ pub fn resolve_two_way_binding( None } Expression::Invalid => { - debug_assert!(ctx.diag.has_error()); + debug_assert!(ctx.diag.has_errors()); None } _ => { diff --git a/internal/compiler/tests/consistent_styles.rs b/internal/compiler/tests/consistent_styles.rs index 0a89a511600..0a4f889bf32 100644 --- a/internal/compiler/tests/consistent_styles.rs +++ b/internal/compiler/tests/consistent_styles.rs @@ -132,7 +132,7 @@ fn load_style(style_name: String) -> Style { // ensure that the style is loaded spin_on::spin_on(loader.import_component("std-widgets.slint", "Button", &mut diag)); - if diag.has_error() { + if diag.has_errors() { #[cfg(feature = "display-diagnostics")] diag.print(); panic!("error parsing style {}", loader.compiler_config.style.as_ref().unwrap()); diff --git a/internal/compiler/tests/syntax_tests.rs b/internal/compiler/tests/syntax_tests.rs index 5a0193751de..c86f598a02a 100644 --- a/internal/compiler/tests/syntax_tests.rs +++ b/internal/compiler/tests/syntax_tests.rs @@ -15,7 +15,7 @@ //! If there are two carets: ` ^^error{some_regexp}` then it means two line above, and so on with more carets. //! `^warning{regexp}` is also supported. -use i_slint_compiler::ComponentsToGenerate; +use i_slint_compiler::ComponentSelection; use std::path::{Path, PathBuf}; #[test] @@ -186,7 +186,7 @@ fn process_file_source( let syntax_node = i_slint_compiler::parser::parse(source.clone(), Some(path), None, &mut parse_diagnostics); - let has_parse_error = parse_diagnostics.has_error(); + let has_parse_error = parse_diagnostics.has_errors(); let mut compiler_config = i_slint_compiler::CompilerConfiguration::new( i_slint_compiler::generator::OutputFormat::Interpreter, ); @@ -195,12 +195,12 @@ fn process_file_source( compiler_config.style = Some("fluent".into()); compiler_config.components_to_generate = if source.contains("config:generate_all_exported_windows") { - ComponentsToGenerate::AllExportedWindows + ComponentSelection::ExportedWindows } else { // Otherwise we'd have lots of warnings about not inheriting Window - ComponentsToGenerate::LastComponent + ComponentSelection::LastExported }; - let compile_diagnostics = if !parse_diagnostics.has_error() { + let compile_diagnostics = if !parse_diagnostics.has_errors() { let (_, build_diags, _) = spin_on::spin_on(i_slint_compiler::compile_syntax_node( syntax_node.clone(), parse_diagnostics, diff --git a/internal/compiler/typeloader.rs b/internal/compiler/typeloader.rs index 40658392c0c..725b94f548b 100644 --- a/internal/compiler/typeloader.rs +++ b/internal/compiler/typeloader.rs @@ -1104,7 +1104,7 @@ impl TypeLoader { let mut state = state.borrow_mut(); let state = &mut *state; - let raw_type_loader = if !state.diag.has_error() { + let raw_type_loader = if !state.diag.has_errors() { crate::passes::run_passes(&mut doc, state.tl, keep_raw, state.diag).await } else { None @@ -1135,7 +1135,7 @@ impl TypeLoader { let mut state = state.borrow_mut(); let state = &mut *state; - if !state.diag.has_error() { + if !state.diag.has_errors() { crate::passes::run_import_passes(&doc, state.tl, state.diag); } state.tl.all_documents.docs.insert(path, doc); @@ -1165,7 +1165,7 @@ impl TypeLoader { ) .await; - if state.borrow().diag.has_error() { + if state.borrow().diag.has_errors() { // If there was error (esp parse error) we don't want to report further error in this document. // because they might be nonsense (TODO: we should check that the parse error were really in this document). // But we still want to create a document to give better error messages in the root document. @@ -1304,7 +1304,7 @@ impl TypeLoader { let import_uri = match maybe_import_uri { Some(import_uri) => import_uri, None => { - debug_assert!(state.borrow().diag.has_error()); + debug_assert!(state.borrow().diag.has_errors()); return None; } }; @@ -1451,8 +1451,8 @@ fn test_dependency_loading() { ®istry, )); - assert!(!test_diags.has_error()); - assert!(!build_diagnostics.has_error()); + assert!(!test_diags.has_errors()); + assert!(!build_diagnostics.has_errors()); assert!(foreign_imports.is_empty()); } @@ -1493,9 +1493,9 @@ fn test_dependency_loading_from_rust() { ®istry, )); - assert!(!test_diags.has_error()); + assert!(!test_diags.has_errors()); assert!(test_diags.is_empty()); // also no warnings - assert!(!build_diagnostics.has_error()); + assert!(!build_diagnostics.has_errors()); assert!(build_diagnostics.is_empty()); // also no warnings assert!(foreign_imports.is_empty()); } @@ -1542,8 +1542,8 @@ X := XX {} ®istry, )); assert!(ok.get()); - assert!(!test_diags.has_error()); - assert!(!build_diagnostics.has_error()); + assert!(!test_diags.has_errors()); + assert!(!build_diagnostics.has_errors()); } #[test] @@ -1575,8 +1575,8 @@ component Foo { XX {} } &mut build_diagnostics, ®istry, )); - assert!(!test_diags.has_error()); - assert!(build_diagnostics.has_error()); + assert!(!test_diags.has_errors()); + assert!(build_diagnostics.has_errors()); let diags = build_diagnostics.to_string_vec(); assert_eq!( diags, @@ -1589,7 +1589,7 @@ component Foo { XX {} } &mut build_diagnostics, ®istry, )); - assert!(build_diagnostics.has_error()); + assert!(build_diagnostics.has_errors()); let diags = build_diagnostics.to_string_vec(); assert_eq!( diags, @@ -1612,7 +1612,7 @@ fn test_manual_import() { &mut build_diagnostics, )); - assert!(!build_diagnostics.has_error()); + assert!(!build_diagnostics.has_errors()); assert!(maybe_button_type.is_some()); } @@ -1632,7 +1632,7 @@ fn test_builtin_style() { let mut build_diagnostics = BuildDiagnostics::default(); let _loader = TypeLoader::new(global_registry, compiler_config, &mut build_diagnostics); - assert!(!build_diagnostics.has_error()); + assert!(!build_diagnostics.has_errors()); } #[test] @@ -1651,7 +1651,7 @@ fn test_user_style() { let mut build_diagnostics = BuildDiagnostics::default(); let _loader = TypeLoader::new(global_registry, compiler_config, &mut build_diagnostics); - assert!(!build_diagnostics.has_error()); + assert!(!build_diagnostics.has_errors()); } #[test] @@ -1670,7 +1670,7 @@ fn test_unknown_style() { let mut build_diagnostics = BuildDiagnostics::default(); let _loader = TypeLoader::new(global_registry, compiler_config, &mut build_diagnostics); - assert!(build_diagnostics.has_error()); + assert!(build_diagnostics.has_errors()); let diags = build_diagnostics.to_string_vec(); assert_eq!(diags.len(), 1); assert!(diags[0].starts_with("Style FooBar in not known. Use one of the builtin styles [")); @@ -1714,8 +1714,8 @@ import { LibraryHelperType } from "@libdir/library_helper_type.slint"; &mut build_diagnostics, ®istry, )); - assert!(!test_diags.has_error()); - assert!(!build_diagnostics.has_error()); + assert!(!test_diags.has_errors()); + assert!(!build_diagnostics.has_errors()); } #[test] @@ -1759,8 +1759,8 @@ import { E } from "@unknown/lib.slint"; &mut build_diagnostics, ®istry, )); - assert!(!test_diags.has_error()); - assert!(build_diagnostics.has_error()); + assert!(!test_diags.has_errors()); + assert!(build_diagnostics.has_errors()); let diags = build_diagnostics.to_string_vec(); assert_eq!(diags.len(), 5); assert!(diags[0].starts_with(&format!( diff --git a/internal/interpreter/api.rs b/internal/interpreter/api.rs index 63179bdc77e..1a2453b0c08 100644 --- a/internal/interpreter/api.rs +++ b/internal/interpreter/api.rs @@ -506,7 +506,7 @@ impl Default for ComponentCompiler { let mut config = i_slint_compiler::CompilerConfiguration::new( i_slint_compiler::generator::OutputFormat::Interpreter, ); - config.components_to_generate = i_slint_compiler::ComponentsToGenerate::LastComponent; + config.components_to_generate = i_slint_compiler::ComponentSelection::LastExported; Self { config, diagnostics: vec![] } } } @@ -791,7 +791,6 @@ impl Compiler { /// /// Any diagnostics produced during the compilation, such as warnings or errors, can be retrieved /// after the call using [`CompilationResult::diagnostics()`]. - /// The [`print_diagnostics`] function can be used to display the diagnostics to the users. /// /// If the file was compiled without error, the list of component names can be obtained with /// [`CompilationResult::component_names`], and the compiled components themselves with @@ -811,7 +810,10 @@ impl Compiler { Err(d) => { let mut diagnostics = i_slint_compiler::diagnostics::BuildDiagnostics::default(); diagnostics.push_compiler_error(d); - return CompilationResult { components: HashMap::new(), diagnostics }; + return CompilationResult { + components: HashMap::new(), + diagnostics: diagnostics.into_iter().collect(), + }; } }; @@ -825,7 +827,6 @@ impl Compiler { /// /// Any diagnostics produced during the compilation, such as warnings or errors, can be retrieved /// after the call using [`CompilationResult::diagnostics()`]. - /// The [`print_diagnostics`] function can be used to display the diagnostics to the users. /// /// This function is `async` but in practice, this is only asynchronous if /// [`Self::set_file_loader`] is set and its future is actually asynchronous. @@ -838,28 +839,54 @@ impl Compiler { /// The result of a compilation /// -/// If [`Self::has_error``] is true, then the compilation failed. -/// The [`Self::diagnostics`] function can be used to retrieve the diagnostics (errors and/or warnings). -/// The components names and their definitions can be retrieved using the [`Self::component_names`] -/// and [`Self::component`] functions. +/// If [`Self::has_errors()`] is true, then the compilation failed. +/// The [`Self::diagnostics()`] function can be used to retrieve the diagnostics (errors and/or warnings) +/// or [`Self::print_diagnostics()`] can be used to print them to stderr. +/// The components can be retrieved using [`Self::components()`] +#[derive(Clone)] pub struct CompilationResult { pub(crate) components: HashMap, - pub(crate) diagnostics: i_slint_compiler::diagnostics::BuildDiagnostics, + pub(crate) diagnostics: Vec, +} + +impl core::fmt::Debug for CompilationResult { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("CompilationResult") + .field("components", &self.components.keys()) + .field("diagnostics", &self.diagnostics) + .finish() + } } impl CompilationResult { /// Returns true if the compilation failed. - /// The errors can be retrieved using the [`Self::diagnostics`] function. - /// And printed to the console using the [`print_diagnostics`] function. - pub fn has_error(&self) -> bool { - self.diagnostics.has_error() + /// The errors can be retrieved using the [`Self::diagnostics()`] function. + pub fn has_errors(&self) -> bool { + self.diagnostics().any(|diag| diag.level() == DiagnosticLevel::Error) } /// Return an iterator over the diagnostics. + /// + /// You can also call [`Self::print_diagnostics()`] to output the diagnostics to stderr pub fn diagnostics(&self) -> impl Iterator + '_ { self.diagnostics.iter().cloned() } + /// Print the diagnostics to stderr + /// + /// The diagnostics are printed in the same style as rustc errors + /// + /// This function is available when the `display-diagnostics` is enabled. + #[cfg(feature = "display-diagnostics")] + pub fn print_diagnostics(&self) { + print_diagnostics(&self.diagnostics) + } + + /// Returns an iterator over the compiled components. + pub fn components(&self) -> impl Iterator + '_ { + self.components.values().cloned() + } + /// Returns the names of the components that were compiled. pub fn component_names(&self) -> impl Iterator + '_ { self.components.keys().map(|s| s.as_str()) @@ -2040,7 +2067,7 @@ fn test_multi_components() { ), ); - assert!(!result.has_error(), "Error {:?}", result.diagnostics().collect::>()); + assert!(!result.has_errors(), "Error {:?}", result.diagnostics().collect::>()); let mut components = result.component_names().collect::>(); components.sort(); assert_eq!(components, vec!["Bar", "Xyz"]); diff --git a/internal/interpreter/dynamic_item_tree.rs b/internal/interpreter/dynamic_item_tree.rs index 3c7eceed7c6..14a3989f973 100644 --- a/internal/interpreter/dynamic_item_tree.rs +++ b/internal/interpreter/dynamic_item_tree.rs @@ -840,8 +840,11 @@ pub async fn load( let (path, mut diag, loader) = i_slint_compiler::load_root_file(&path, version, &path, source, diag, compiler_config) .await; - if diag.has_error() { - return CompilationResult { components: HashMap::new(), diagnostics: diag }; + if diag.has_errors() { + return CompilationResult { + components: HashMap::new(), + diagnostics: diag.into_iter().collect(), + }; } #[cfg(feature = "highlight")] @@ -870,7 +873,7 @@ pub async fn load( diag.push_error_with_span("No component found".into(), Default::default()); }; - CompilationResult { diagnostics: diag, components } + CompilationResult { diagnostics: diag.into_iter().collect(), components } } pub(crate) fn generate_item_tree<'id>( diff --git a/internal/interpreter/lib.rs b/internal/interpreter/lib.rs index 7cc75209b1f..4d9f22c9073 100644 --- a/internal/interpreter/lib.rs +++ b/internal/interpreter/lib.rs @@ -30,7 +30,7 @@ let compiler = Compiler::default(); let result = spin_on::spin_on(compiler.build_from_path("hello.slint")); let diagnostics : Vec<_> = result.diagnostics().collect(); # #[cfg(feature="print_diagnostics")] -slint_interpreter::print_diagnostics(&diagnostics); +diagnostics.print(); if let Some(definition) = result.component("Foo") { let instance = definition.create().unwrap(); instance.run().unwrap(); diff --git a/internal/interpreter/tests.rs b/internal/interpreter/tests.rs index 6da33eaf3b4..a465449fb1f 100644 --- a/internal/interpreter/tests.rs +++ b/internal/interpreter/tests.rs @@ -19,7 +19,7 @@ fn reuse_window() { let mut compiler = Compiler::default(); compiler.set_style("fluent".into()); let result = spin_on::spin_on(compiler.build_from_source(code.into(), Default::default())); - assert!(!result.has_error(), "{:?}", result.diagnostics().collect::>()); + assert!(!result.has_errors(), "{:?}", result.diagnostics().collect::>()); let definition = result.component("MainWindow").unwrap(); let instance = definition.create().unwrap(); assert_eq!( @@ -33,7 +33,7 @@ fn reuse_window() { let mut compiler = Compiler::default(); compiler.set_style("fluent".into()); let result = spin_on::spin_on(compiler.build_from_source(code.into(), Default::default())); - assert!(!result.has_error(), "{:?}", result.diagnostics().collect::>()); + assert!(!result.has_errors(), "{:?}", result.diagnostics().collect::>()); let definition = result.component("MainWindow").unwrap(); let instance = definition.create_with_existing_window(handle.window()).unwrap(); drop(handle); diff --git a/tests/doctests/main.rs b/tests/doctests/main.rs index c94796b3069..f6776b77c48 100644 --- a/tests/doctests/main.rs +++ b/tests/doctests/main.rs @@ -11,7 +11,7 @@ fn do_test(snippet: &str, path: &str) -> Result<(), Box> let diagnostics = result.diagnostics().collect::>(); slint_interpreter::print_diagnostics(&diagnostics); - if result.has_error() { + if result.has_errors() { return Err(format!("Error when loading {snippet:?} in {path:?}: {diagnostics:?}").into()); } Ok(()) diff --git a/tests/driver/cpp/cppdriver.rs b/tests/driver/cpp/cppdriver.rs index f51fef9b73b..29433b61b30 100644 --- a/tests/driver/cpp/cppdriver.rs +++ b/tests/driver/cpp/cppdriver.rs @@ -31,7 +31,7 @@ pub fn test(testcase: &test_driver_lib::TestCase) -> Result<(), Box> let (root_component, diag, loader) = spin_on::spin_on(compile_syntax_node(syntax_node, diag, compiler_config)); - if diag.has_error() { + if diag.has_errors() { let vec = diag.to_string_vec(); return Err(vec.join("\n").into()); } @@ -45,7 +45,7 @@ pub fn test(testcase: &test_driver_lib::TestCase) -> Result<(), Box> &loader.compiler_config, )?; - if diag.has_error() { + if diag.has_errors() { let vec = diag.to_string_vec(); return Err(vec.join("\n").into()); } diff --git a/tests/driver/interpreter/interpreter.rs b/tests/driver/interpreter/interpreter.rs index ca5f98d3f6a..abc7fa7befa 100644 --- a/tests/driver/interpreter/interpreter.rs +++ b/tests/driver/interpreter/interpreter.rs @@ -23,7 +23,7 @@ pub fn test(testcase: &test_driver_lib::TestCase) -> Result<(), Box> let result = spin_on::spin_on(compiler.build_from_source(source, testcase.absolute_path.clone())); - if result.has_error() { + if result.has_errors() { let diagnostics = result.diagnostics().collect::>(); slint_interpreter::print_diagnostics(&diagnostics); diff --git a/tests/driver/rust/build.rs b/tests/driver/rust/build.rs index 62199b1bada..3ca40944217 100644 --- a/tests/driver/rust/build.rs +++ b/tests/driver/rust/build.rs @@ -145,7 +145,7 @@ fn generate_source( let (root_component, diag, loader) = spin_on::spin_on(compile_syntax_node(syntax_node, diag, compiler_config)); - if diag.has_error() { + if diag.has_errors() { diag.print_warnings_and_exit_on_error(); return Err(std::io::Error::new( std::io::ErrorKind::Other, diff --git a/tests/screenshots/build.rs b/tests/screenshots/build.rs index 0cfbdad2af7..173938bf6c3 100644 --- a/tests/screenshots/build.rs +++ b/tests/screenshots/build.rs @@ -166,7 +166,7 @@ fn generate_source( let (root_component, diag, loader) = spin_on::spin_on(compile_syntax_node(syntax_node, diag, compiler_config)); - if diag.has_error() { + if diag.has_errors() { diag.print_warnings_and_exit_on_error(); return Err(std::io::Error::new( std::io::ErrorKind::Other, diff --git a/tools/compiler/main.rs b/tools/compiler/main.rs index 1f6da5521ec..b1c8b38fdd6 100644 --- a/tools/compiler/main.rs +++ b/tools/compiler/main.rs @@ -74,7 +74,7 @@ fn main() -> std::io::Result<()> { let mut diag = BuildDiagnostics::default(); let syntax_node = parser::parse_file(&args.path, &mut diag); //println!("{:#?}", syntax_node); - if diag.has_error() { + if diag.has_errors() { diag.print(); std::process::exit(-1); } diff --git a/tools/lsp/common.rs b/tools/lsp/common.rs index 7c743ba3bd3..3079a6c872f 100644 --- a/tools/lsp/common.rs +++ b/tools/lsp/common.rs @@ -172,7 +172,7 @@ impl DocumentCache { // Always load the widgets so we can auto-complete them let mut diag = BuildDiagnostics::default(); self.0.import_component("std-widgets.slint", "StyleMetrics", &mut diag).await; - assert!(!diag.has_error()); + assert!(!diag.has_errors()); } pub async fn load_url( diff --git a/tools/lsp/common/properties.rs b/tools/lsp/common/properties.rs index 78cda9f0267..6767254c671 100644 --- a/tools/lsp/common/properties.rs +++ b/tools/lsp/common/properties.rs @@ -479,7 +479,7 @@ fn set_binding_on_existing_property( new_expression: String, diag: &mut BuildDiagnostics, ) -> Result<(SetBindingResponse, Option)> { - let workspace_edit = (!diag.has_error()) + let workspace_edit = (!diag.has_errors()) .then(|| { create_workspace_edit_for_set_binding_on_existing_property( uri, @@ -585,7 +585,7 @@ fn set_binding_on_known_property( new_expression: &str, diag: &mut BuildDiagnostics, ) -> Result<(SetBindingResponse, Option)> { - let workspace_edit = if diag.has_error() { + let workspace_edit = if diag.has_errors() { None } else { create_workspace_edit_for_set_binding_on_known_property( diff --git a/tools/lsp/common/test.rs b/tools/lsp/common/test.rs index e2dd4d3e02c..4f063f0f4c8 100644 --- a/tools/lsp/common/test.rs +++ b/tools/lsp/common/test.rs @@ -116,7 +116,7 @@ pub fn recompile_test_with_sources( for d in diagnostics.iter() { i_slint_core::debug_log!(" {d}"); } - assert!(!diagnostics.has_error()); + assert!(!diagnostics.has_errors()); if !allow_warnings { assert!(diagnostics.is_empty()); } diff --git a/tools/lsp/fmt/tool.rs b/tools/lsp/fmt/tool.rs index 91b9f3b8bb0..e48b752587f 100644 --- a/tools/lsp/fmt/tool.rs +++ b/tools/lsp/fmt/tool.rs @@ -48,7 +48,7 @@ fn process_rust_file(source: String, mut file: impl Write) -> std::io::Result<() let syntax_node = i_slint_compiler::parser::parse(code.to_owned(), None, None, &mut diag); let len = syntax_node.text_range().end().into(); visit_node(syntax_node, &mut file)?; - if diag.has_error() { + if diag.has_errors() { file.write_all(&code.as_bytes()[len..])?; diag.print(); } @@ -78,7 +78,7 @@ fn process_markdown_file(source: String, mut file: impl Write) -> std::io::Resul let syntax_node = i_slint_compiler::parser::parse(code.to_owned(), None, None, &mut diag); let len = syntax_node.text_range().end().into(); visit_node(syntax_node, &mut file)?; - if diag.has_error() { + if diag.has_errors() { file.write_all(&code.as_bytes()[len..])?; diag.print(); } @@ -95,7 +95,7 @@ fn process_slint_file( let syntax_node = i_slint_compiler::parser::parse(source.clone(), Some(&path), None, &mut diag); let len = syntax_node.node.text_range().end().into(); visit_node(syntax_node, &mut file)?; - if diag.has_error() { + if diag.has_errors() { file.write_all(&source.as_bytes()[len..])?; diag.print(); } diff --git a/tools/lsp/preview.rs b/tools/lsp/preview.rs index 933117c2a74..20e87b20b30 100644 --- a/tools/lsp/preview.rs +++ b/tools/lsp/preview.rs @@ -1005,9 +1005,9 @@ async fn parse_source( let cc = builder.compiler_configuration(i_slint_core::InternalToken); cc.components_to_generate = if let Some(name) = component { - i_slint_compiler::ComponentsToGenerate::ComponentWithName(name) + i_slint_compiler::ComponentSelection::Named(name) } else { - i_slint_compiler::ComponentsToGenerate::LastComponent + i_slint_compiler::ComponentSelection::LastExported }; #[cfg(target_arch = "wasm32")] { @@ -1023,7 +1023,7 @@ async fn parse_source( let result = builder.build_from_source(source_code, path).await; - let compiled = result.component_names().next().and_then(|name| result.component(name)); + let compiled = result.components().next(); (result.diagnostics().collect(), compiled) } diff --git a/tools/lsp/preview/drop_location.rs b/tools/lsp/preview/drop_location.rs index 66d08817fad..bc3628d2414 100644 --- a/tools/lsp/preview/drop_location.rs +++ b/tools/lsp/preview/drop_location.rs @@ -780,7 +780,7 @@ pub fn workspace_edit_compiles( let _ = preview::poll_once(document_cache.load_url(&u, None, c, &mut diag)); } - !diag.has_error() + !diag.has_errors() } /// Find the Element to insert into. None means we can not insert at this point. diff --git a/tools/updater/main.rs b/tools/updater/main.rs index 71ca0a93075..3d6cfbae153 100644 --- a/tools/updater/main.rs +++ b/tools/updater/main.rs @@ -71,7 +71,7 @@ fn process_rust_file(source: String, mut file: impl Write, args: &Cli) -> std::i let len = syntax_node.text_range().end().into(); let mut state = init_state(&syntax_node, &mut diag); visit_node(syntax_node, &mut file, &mut state, args)?; - if diag.has_error() { + if diag.has_errors() { file.write_all(&code.as_bytes()[len..])?; diag.print(); } @@ -103,7 +103,7 @@ fn process_markdown_file(source: String, mut file: impl Write, args: &Cli) -> st let len = syntax_node.text_range().end().into(); let mut state = init_state(&syntax_node, &mut diag); visit_node(syntax_node, &mut file, &mut state, args)?; - if diag.has_error() { + if diag.has_errors() { file.write_all(&code.as_bytes()[len..])?; diag.print(); } @@ -128,7 +128,7 @@ fn process_file( let len = syntax_node.node.text_range().end().into(); let mut state = init_state(&syntax_node, &mut diag); visit_node(syntax_node, &mut file, &mut state, args)?; - if diag.has_error() { + if diag.has_errors() { file.write_all(&source.as_bytes()[len..])?; diag.print(); } diff --git a/tools/viewer/main.rs b/tools/viewer/main.rs index b281d46e1d9..ccd5bd66b8b 100644 --- a/tools/viewer/main.rs +++ b/tools/viewer/main.rs @@ -4,7 +4,7 @@ #![doc = include_str!("README.md")] use clap::Parser; -use i_slint_compiler::ComponentsToGenerate; +use i_slint_compiler::ComponentSelection; use i_slint_core::model::{Model, ModelRc}; use i_slint_core::SharedVector; use itertools::Itertools; @@ -104,11 +104,11 @@ fn main() -> Result<()> { let fswatcher = if args.auto_reload { Some(start_fswatch_thread(args.clone())?) } else { None }; let compiler = init_compiler(&args, fswatcher); let r = spin_on::spin_on(compiler.build_from_path(&args.path)); - slint_interpreter::print_diagnostics(&r.diagnostics().collect::>()); - if r.has_error() { + r.print_diagnostics(); + if r.has_errors() { std::process::exit(-1); } - let Some(c) = r.component_names().next().and_then(|n| r.component(n)) else { + let Some(c) = r.components().next() else { match args.component { Some(name) => { eprintln!("Component '{name}' not found in file '{}'", args.path.display()); @@ -208,8 +208,8 @@ fn init_compiler( compiler.compiler_configuration(i_slint_core::InternalToken).components_to_generate = match &args.component { - Some(component) => ComponentsToGenerate::ComponentWithName(component.clone()), - None => ComponentsToGenerate::LastComponent, + Some(component) => ComponentSelection::Named(component.clone()), + None => ComponentSelection::LastExported, }; compiler @@ -297,8 +297,8 @@ fn start_fswatch_thread(args: Cli) -> Result>) { let compiler = init_compiler(&args, Some(fswatcher)); let r = compiler.build_from_path(&args.path).await; - slint_interpreter::print_diagnostics(&r.diagnostics().collect::>()); - if let Some(c) = r.component_names().next().and_then(|n| r.component(n)) { + r.print_diagnostics(); + if let Some(c) = r.components().next() { CURRENT_INSTANCE.with(|current| { let mut current = current.borrow_mut(); if let Some(handle) = current.take() { @@ -317,7 +317,7 @@ async fn reload(args: Cli, fswatcher: Arc>) { } eprintln!("Successful reload of {}", args.path.display()); }); - } else if !r.has_error() { + } else if !r.has_errors() { match &args.component { Some(name) => println!("Component {name} not found"), None => println!("No component found"),