mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-01 22:31:14 +00:00
Rework the Rust entry point API for the interpreter
Switch to the stateful `ComponentCompiler` concept that we discussed for the C++ API.
This commit is contained in:
parent
6de1c4e3b5
commit
4a9cd954b8
9 changed files with 169 additions and 119 deletions
|
@ -62,14 +62,11 @@ fn load(mut cx: FunctionContext) -> JsResult<JsValue> {
|
||||||
}
|
}
|
||||||
None => vec![],
|
None => vec![],
|
||||||
};
|
};
|
||||||
let compiler_config =
|
let mut compiler = sixtyfps_interpreter::ComponentCompiler::new();
|
||||||
sixtyfps_interpreter::CompilerConfiguration::new().with_include_paths(include_paths);
|
compiler.set_include_paths(include_paths);
|
||||||
let (c, diags) = spin_on::spin_on(sixtyfps_interpreter::ComponentDefinition::from_path(
|
let c = spin_on::spin_on(compiler.build_from_path(path));
|
||||||
path,
|
|
||||||
compiler_config,
|
|
||||||
));
|
|
||||||
|
|
||||||
sixtyfps_interpreter::print_diagnostics(&diags);
|
sixtyfps_interpreter::print_diagnostics(&compiler.diagnostics());
|
||||||
|
|
||||||
let c = if let Some(c) = c { c } else { return cx.throw_error("Compilation error") };
|
let c = if let Some(c) = c { c } else { return cx.throw_error("Compilation error") };
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ pub async fn compile_from_string(
|
||||||
#[cfg(feature = "console_error_panic_hook")]
|
#[cfg(feature = "console_error_panic_hook")]
|
||||||
console_error_panic_hook::set_once();
|
console_error_panic_hook::set_once();
|
||||||
|
|
||||||
let mut config = sixtyfps_interpreter::CompilerConfiguration::new();
|
let mut compiler = sixtyfps_interpreter::ComponentCompiler::new();
|
||||||
|
|
||||||
if let Some(load_callback) = optional_import_callback {
|
if let Some(load_callback) = optional_import_callback {
|
||||||
let open_import_fallback = move |file_name: &Path| -> core::pin::Pin<
|
let open_import_fallback = move |file_name: &Path| -> core::pin::Pin<
|
||||||
|
@ -55,12 +55,10 @@ pub async fn compile_from_string(
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
config = config.with_file_loader(open_import_fallback);
|
compiler.set_file_loader(open_import_fallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (c, diags) =
|
let c = compiler.build_from_source(source, base_url.into()).await;
|
||||||
sixtyfps_interpreter::ComponentDefinition::from_source(source, base_url.into(), config)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
match c {
|
match c {
|
||||||
Some(c) => Ok(WrappedCompiledComp(c)),
|
Some(c) => Ok(WrappedCompiledComp(c)),
|
||||||
|
@ -72,7 +70,7 @@ pub async fn compile_from_string(
|
||||||
let level_key = JsValue::from_str("level");
|
let level_key = JsValue::from_str("level");
|
||||||
let mut error_as_string = String::new();
|
let mut error_as_string = String::new();
|
||||||
let array = js_sys::Array::new();
|
let array = js_sys::Array::new();
|
||||||
for d in diags.into_iter() {
|
for d in compiler.diagnostics().into_iter() {
|
||||||
let filename = d
|
let filename = d
|
||||||
.source_file()
|
.source_file()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
|
|
@ -66,6 +66,7 @@ mod passes {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// CompilationConfiguration allows configuring different aspects of the compiler.
|
/// CompilationConfiguration allows configuring different aspects of the compiler.
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct CompilerConfiguration {
|
pub struct CompilerConfiguration {
|
||||||
/// Indicate whether to embed resources such as images in the generated output or whether
|
/// Indicate whether to embed resources such as images in the generated output or whether
|
||||||
/// to retain references to the resources on the file system.
|
/// to retain references to the resources on the file system.
|
||||||
|
@ -80,7 +81,7 @@ pub struct CompilerConfiguration {
|
||||||
/// The callback should open the file specified by the given file name and
|
/// The callback should open the file specified by the given file name and
|
||||||
/// return an future that provides the text content of the file as output.
|
/// return an future that provides the text content of the file as output.
|
||||||
pub open_import_fallback:
|
pub open_import_fallback:
|
||||||
Option<Box<dyn Fn(String) -> Pin<Box<dyn Future<Output = std::io::Result<String>>>>>>,
|
Option<Rc<dyn Fn(String) -> Pin<Box<dyn Future<Output = std::io::Result<String>>>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CompilerConfiguration {
|
impl CompilerConfiguration {
|
||||||
|
|
|
@ -481,7 +481,7 @@ fn test_load_from_callback_ok() {
|
||||||
let mut compiler_config =
|
let mut compiler_config =
|
||||||
CompilerConfiguration::new(crate::generator::OutputFormat::Interpreter);
|
CompilerConfiguration::new(crate::generator::OutputFormat::Interpreter);
|
||||||
compiler_config.style = Some("ugly".into());
|
compiler_config.style = Some("ugly".into());
|
||||||
compiler_config.open_import_fallback = Some(Box::new(move |path| {
|
compiler_config.open_import_fallback = Some(Rc::new(move |path| {
|
||||||
let ok_ = ok_.clone();
|
let ok_ = ok_.clone();
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
assert_eq!(path, "../FooBar.60");
|
assert_eq!(path, "../FooBar.60");
|
||||||
|
|
|
@ -334,7 +334,124 @@ impl TryInto<Vec<Value>> for Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ComponentDescription is a representation of a compiled component from .60
|
/// ComponentCompiler is the entry point to the SixtyFPS interpreter that can be used
|
||||||
|
/// to load .60 files or compile them on-the-fly from a string.
|
||||||
|
pub struct ComponentCompiler {
|
||||||
|
config: sixtyfps_compilerlib::CompilerConfiguration,
|
||||||
|
diagnostics: Vec<Diagnostic>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ComponentCompiler {
|
||||||
|
/// Returns a new ComponentCompiler
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
config: sixtyfps_compilerlib::CompilerConfiguration::new(
|
||||||
|
sixtyfps_compilerlib::generator::OutputFormat::Interpreter,
|
||||||
|
),
|
||||||
|
diagnostics: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new configuration that includes sets the include paths used for looking up
|
||||||
|
/// `.60` imports to the specified vector of paths.
|
||||||
|
pub fn set_include_paths(&mut self, include_paths: Vec<std::path::PathBuf>) {
|
||||||
|
self.config.include_paths = include_paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new configuration that selects the style to be used for widgets.
|
||||||
|
pub fn set_style(&mut self, style: String) {
|
||||||
|
self.config.style = Some(style);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new configuration that will use the provided callback for loading.
|
||||||
|
pub fn set_file_loader(
|
||||||
|
&mut self,
|
||||||
|
file_loader_fallback: impl Fn(
|
||||||
|
&Path,
|
||||||
|
)
|
||||||
|
-> core::pin::Pin<Box<dyn core::future::Future<Output = std::io::Result<String>>>>
|
||||||
|
+ 'static,
|
||||||
|
) {
|
||||||
|
self.config.open_import_fallback =
|
||||||
|
Some(Rc::new(move |path| file_loader_fallback(Path::new(path.as_str()))));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the diagnostics that were produced in the last call to [[build_from_path]] or [[build_from_source]].
|
||||||
|
pub fn diagnostics(&self) -> &Vec<Diagnostic> {
|
||||||
|
&self.diagnostics
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compile a .60 file into a ComponentDefinition
|
||||||
|
///
|
||||||
|
/// Returns the compiled `ComponentDefinition` if there was no errors.
|
||||||
|
///
|
||||||
|
/// Any diagnostics produced during the compilation, such as warnigns or errors, are collected
|
||||||
|
/// in this ComponentCompiler and can be retrieved after the call using the [[diagnostics()]]
|
||||||
|
/// function. The [`print_diagnostics`] function can be used to display the diagnostics
|
||||||
|
/// to the users.
|
||||||
|
///
|
||||||
|
/// Diagnostics from previous calls are cleared when calling this function.
|
||||||
|
///
|
||||||
|
/// This function is `async` but in practice, this is only asynchronious if
|
||||||
|
/// [`set_file_loader`] was called and its future is actually asynchronious.
|
||||||
|
/// If that is not used, then it is fine to use a very simple executor, such as the one
|
||||||
|
/// provided by the `spin_on` crate
|
||||||
|
pub async fn build_from_path<P: AsRef<Path>>(
|
||||||
|
&mut self,
|
||||||
|
path: P,
|
||||||
|
) -> Option<ComponentDefinition> {
|
||||||
|
let path = path.as_ref();
|
||||||
|
let source = match sixtyfps_compilerlib::diagnostics::load_from_path(path) {
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(d) => {
|
||||||
|
self.diagnostics = vec![d];
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// We create here a 'static guard. That's alright because we make sure
|
||||||
|
// in this module that we only use erased component
|
||||||
|
let guard = unsafe { generativity::Guard::new(generativity::Id::new()) };
|
||||||
|
|
||||||
|
let (c, diag) =
|
||||||
|
crate::dynamic_component::load(source, path.into(), self.config.clone(), guard).await;
|
||||||
|
self.diagnostics = diag.into_iter().collect();
|
||||||
|
c.ok().map(|inner| ComponentDefinition { inner })
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compile some .60 code into a ComponentDefinition
|
||||||
|
///
|
||||||
|
/// The `path` argument will be used for diagnostics and to compute relative
|
||||||
|
/// path while importing
|
||||||
|
///
|
||||||
|
/// Any diagnostics produced during the compilation, such as warnigns or errors, are collected
|
||||||
|
/// in this ComponentCompiler and can be retrieved after the call using the [[diagnostics()]]
|
||||||
|
/// function. The [`print_diagnostics`] function can be used to display the diagnostics
|
||||||
|
/// to the users.
|
||||||
|
///
|
||||||
|
/// Diagnostics from previous calls are cleared when calling this function.
|
||||||
|
///
|
||||||
|
/// This function is `async` but in practice, this is only asynchronious if
|
||||||
|
/// [`set_file_loader`] is set and its future is actually asynchronious.
|
||||||
|
/// If that is not used, then it is fine to use a very simple executor, such as the one
|
||||||
|
/// provided by the `spin_on` crate
|
||||||
|
pub async fn build_from_source(
|
||||||
|
&mut self,
|
||||||
|
source_code: String,
|
||||||
|
path: PathBuf,
|
||||||
|
) -> Option<ComponentDefinition> {
|
||||||
|
// We create here a 'static guard. That's alright because we make sure
|
||||||
|
// in this module that we only use erased component
|
||||||
|
let guard = unsafe { generativity::Guard::new(generativity::Id::new()) };
|
||||||
|
|
||||||
|
let (c, diag) =
|
||||||
|
crate::dynamic_component::load(source_code, path, self.config.clone(), guard).await;
|
||||||
|
self.diagnostics = diag.into_iter().collect();
|
||||||
|
c.ok().map(|inner| ComponentDefinition { inner })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ComponentDefinition is a representation of a compiled component from .60
|
||||||
///
|
///
|
||||||
/// It can be constructed from a .60 file using the [`Self::from_path`] or [`Self::from_source`] functions.
|
/// It can be constructed from a .60 file using the [`Self::from_path`] or [`Self::from_source`] functions.
|
||||||
/// And then it can be instentiated with the [`Self::create`] function
|
/// And then it can be instentiated with the [`Self::create`] function
|
||||||
|
@ -344,66 +461,6 @@ pub struct ComponentDefinition {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ComponentDefinition {
|
impl ComponentDefinition {
|
||||||
/// Compile a .60 file into a ComponentDefinition
|
|
||||||
///
|
|
||||||
/// The first element of the returned tuple is going to be the compiled
|
|
||||||
/// `ComponentDefinition` if there was no errors. This function also return
|
|
||||||
/// a vector if diagnostics with errors and/or warnings.
|
|
||||||
/// The [`print_diagnostics`] function can be used to display the diagnostics
|
|
||||||
/// to the users.
|
|
||||||
///
|
|
||||||
/// This function is `async` but in practice, this is only asynchronious if
|
|
||||||
/// [`CompilerConfiguration::with_file_loader`] is set and its future is actually asynchronious.
|
|
||||||
/// If that is not used, then it is fine to use a very simple executor, such as the one
|
|
||||||
/// provided by the `spin_on` crate
|
|
||||||
pub async fn from_path<P: AsRef<Path>>(
|
|
||||||
path: P,
|
|
||||||
config: CompilerConfiguration,
|
|
||||||
) -> (Option<Self>, Vec<Diagnostic>) {
|
|
||||||
let path = path.as_ref();
|
|
||||||
let source = match sixtyfps_compilerlib::diagnostics::load_from_path(path) {
|
|
||||||
Ok(s) => s,
|
|
||||||
Err(d) => return (None, vec![d]),
|
|
||||||
};
|
|
||||||
|
|
||||||
// We create here a 'static guard. That's alright because we make sure
|
|
||||||
// in this module that we only use erased component
|
|
||||||
let guard = unsafe { generativity::Guard::new(generativity::Id::new()) };
|
|
||||||
|
|
||||||
let (c, diag) =
|
|
||||||
crate::dynamic_component::load(source, path.into(), config.config, guard).await;
|
|
||||||
(c.ok().map(|inner| Self { inner }), diag.into_iter().collect())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Compile some .60 code into a ComponentDefinition
|
|
||||||
///
|
|
||||||
/// The `path` argument will be used for diagnostics and to compute relative
|
|
||||||
/// path while importing
|
|
||||||
///
|
|
||||||
/// The first element of the returned tuple is going to be the compiled
|
|
||||||
/// `ComponentDefinition` if there was no errors. This function also return
|
|
||||||
/// a vector if diagnostics with errors and/or warnings.
|
|
||||||
/// The [`print_diagnostics`] function can be used to display the diagnostics
|
|
||||||
/// to the users.
|
|
||||||
///
|
|
||||||
/// This function is `async` but in practice, this is only asynchronious if
|
|
||||||
/// [`CompilerConfiguration::with_file_loader`] is set and its future is actually asynchronious.
|
|
||||||
/// If that is not used, then it is fine to use a very simple executor, such as the one
|
|
||||||
/// provided by the `spin_on` crate
|
|
||||||
pub async fn from_source(
|
|
||||||
source_code: String,
|
|
||||||
path: PathBuf,
|
|
||||||
config: CompilerConfiguration,
|
|
||||||
) -> (Option<Self>, Vec<Diagnostic>) {
|
|
||||||
// We create here a 'static guard. That's alright because we make sure
|
|
||||||
// in this module that we only use erased component
|
|
||||||
let guard = unsafe { generativity::Guard::new(generativity::Id::new()) };
|
|
||||||
|
|
||||||
let (c, diag) =
|
|
||||||
crate::dynamic_component::load(source_code, path, config.config, guard).await;
|
|
||||||
(c.ok().map(|inner| Self { inner }), diag.into_iter().collect())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Instantiate the component
|
/// Instantiate the component
|
||||||
pub fn create(&self) -> ComponentInstance {
|
pub fn create(&self) -> ComponentInstance {
|
||||||
ComponentInstance {
|
ComponentInstance {
|
||||||
|
@ -478,15 +535,16 @@ impl ComponentInstance {
|
||||||
/// ## Examples
|
/// ## Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use sixtyfps_interpreter::{ComponentDefinition, CompilerConfiguration, Value, SharedString};
|
/// use sixtyfps_interpreter::{ComponentDefinition, ComponentCompiler, Value, SharedString};
|
||||||
/// let code = r#"
|
/// let code = r#"
|
||||||
/// MyWin := Window {
|
/// MyWin := Window {
|
||||||
/// property <int> my_property: 42;
|
/// property <int> my_property: 42;
|
||||||
/// }
|
/// }
|
||||||
/// "#;
|
/// "#;
|
||||||
/// let (definition, diagnostics) = spin_on::spin_on(
|
/// let mut compiler = ComponentCompiler::new();
|
||||||
/// ComponentDefinition::from_source(code.into(), Default::default(), CompilerConfiguration::new()));
|
/// let definition = spin_on::spin_on(
|
||||||
/// assert!(diagnostics.is_empty(), "{:?}", diagnostics);
|
/// compiler.build_from_source(code.into(), Default::default()));
|
||||||
|
/// assert!(compiler.diagnostics().is_empty(), "{:?}", compiler.diagnostics());
|
||||||
/// let instance = definition.unwrap().create();
|
/// let instance = definition.unwrap().create();
|
||||||
/// assert_eq!(instance.get_property("my_property").unwrap(), Value::from(42));
|
/// assert_eq!(instance.get_property("my_property").unwrap(), Value::from(42));
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -517,7 +575,7 @@ impl ComponentInstance {
|
||||||
/// ## Examples
|
/// ## Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use sixtyfps_interpreter::{ComponentDefinition, CompilerConfiguration, Value, SharedString};
|
/// use sixtyfps_interpreter::{ComponentDefinition, ComponentCompiler, Value, SharedString};
|
||||||
/// use core::convert::TryInto;
|
/// use core::convert::TryInto;
|
||||||
/// let code = r#"
|
/// let code = r#"
|
||||||
/// MyWin := Window {
|
/// MyWin := Window {
|
||||||
|
@ -525,8 +583,8 @@ impl ComponentInstance {
|
||||||
/// property <int> my_prop: 12;
|
/// property <int> my_prop: 12;
|
||||||
/// }
|
/// }
|
||||||
/// "#;
|
/// "#;
|
||||||
/// let (definition, _) = spin_on::spin_on(
|
/// let definition = spin_on::spin_on(
|
||||||
/// ComponentDefinition::from_source(code.into(), Default::default(), CompilerConfiguration::new()));
|
/// ComponentCompiler::new().build_from_source(code.into(), Default::default()));
|
||||||
/// let instance = definition.unwrap().create();
|
/// let instance = definition.unwrap().create();
|
||||||
///
|
///
|
||||||
/// let instance_weak = instance.as_weak();
|
/// let instance_weak = instance.as_weak();
|
||||||
|
@ -704,7 +762,7 @@ impl CompilerConfiguration {
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut config = self.config;
|
let mut config = self.config;
|
||||||
config.open_import_fallback =
|
config.open_import_fallback =
|
||||||
Some(Box::new(move |path| file_loader_fallback(Path::new(path.as_str()))));
|
Some(Rc::new(move |path| file_loader_fallback(Path::new(path.as_str()))));
|
||||||
Self { config }
|
Self { config }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,12 +30,13 @@ executor, such as the one provided by the `spin_on` crate
|
||||||
This example load a `.60` dynamically from a path and show error if any
|
This example load a `.60` dynamically from a path and show error if any
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use sixtyfps_interpreter::{ComponentDefinition, CompilerConfiguration};
|
use sixtyfps_interpreter::{ComponentDefinition, ComponentCompiler, CompilerConfiguration};
|
||||||
|
|
||||||
let (definition, diagnostics) =
|
let mut compiler = ComponentCompiler::new();
|
||||||
spin_on::spin_on(ComponentDefinition::from_path("hello.60", CompilerConfiguration::new()));
|
let definition =
|
||||||
|
spin_on::spin_on(compiler.build_from_path("hello.60"));
|
||||||
# #[cfg(feature="print_diagnostics")]
|
# #[cfg(feature="print_diagnostics")]
|
||||||
sixtyfps_interpreter::print_diagnostics(&diagnostics);
|
sixtyfps_interpreter::print_diagnostics(&compiler.diagnostics());
|
||||||
if let Some(definition) = definition {
|
if let Some(definition) = definition {
|
||||||
let instance = definition.create();
|
let instance = definition.create();
|
||||||
instance.run();
|
instance.run();
|
||||||
|
@ -45,7 +46,7 @@ if let Some(definition) = definition {
|
||||||
This example load a `.60` from a string and set some properties
|
This example load a `.60` from a string and set some properties
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use sixtyfps_interpreter::{ComponentDefinition, CompilerConfiguration, Value, SharedString};
|
use sixtyfps_interpreter::{ComponentDefinition, ComponentCompiler, Value, SharedString};
|
||||||
|
|
||||||
let code = r#"
|
let code = r#"
|
||||||
MyWin := Window {
|
MyWin := Window {
|
||||||
|
@ -56,9 +57,10 @@ let code = r#"
|
||||||
}
|
}
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let (definition, diagnostics) =
|
let mut compiler = ComponentCompiler::new();
|
||||||
spin_on::spin_on(ComponentDefinition::from_source(code.into(), Default::default(), CompilerConfiguration::new()));
|
let definition =
|
||||||
assert!(diagnostics.is_empty());
|
spin_on::spin_on(compiler.build_from_source(code.into(), Default::default()));
|
||||||
|
assert!(compiler.diagnostics().is_empty());
|
||||||
let instance = definition.unwrap().create();
|
let instance = definition.unwrap().create();
|
||||||
instance.set_property("my_name", Value::from(SharedString::from("World"))).unwrap();
|
instance.set_property("my_name", Value::from(SharedString::from("World"))).unwrap();
|
||||||
# return; // we don't want to call run in the tests
|
# return; // we don't want to call run in the tests
|
||||||
|
|
|
@ -10,18 +10,14 @@ LICENSE END */
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn do_test(snippet: &str) -> Result<(), Box<dyn std::error::Error>> {
|
fn do_test(snippet: &str) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let config = sixtyfps_interpreter::CompilerConfiguration::new();
|
let mut compiler = sixtyfps_interpreter::ComponentCompiler::new();
|
||||||
let (component, diagnostics) =
|
let component =
|
||||||
spin_on::spin_on(sixtyfps_interpreter::ComponentDefinition::from_source(
|
spin_on::spin_on(compiler.build_from_source(snippet.into(), Default::default()));
|
||||||
snippet.into(),
|
|
||||||
Default::default(),
|
|
||||||
config,
|
|
||||||
));
|
|
||||||
|
|
||||||
#[cfg(feature = "display-diagnostics")]
|
#[cfg(feature = "display-diagnostics")]
|
||||||
sixtyfps_interpreter::print_diagnostics(&diagnostics);
|
sixtyfps_interpreter::print_diagnostics(&compiler.diagnostics());
|
||||||
|
|
||||||
for d in diagnostics {
|
for d in compiler.diagnostics() {
|
||||||
if d.level() == sixtyfps_interpreter::DiagnosticLevel::Error {
|
if d.level() == sixtyfps_interpreter::DiagnosticLevel::Error {
|
||||||
return Err(d.message().to_owned().into());
|
return Err(d.message().to_owned().into());
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,20 +15,21 @@ pub fn test(testcase: &test_driver_lib::TestCase) -> Result<(), Box<dyn Error>>
|
||||||
let include_paths = test_driver_lib::extract_include_paths(&source)
|
let include_paths = test_driver_lib::extract_include_paths(&source)
|
||||||
.map(std::path::PathBuf::from)
|
.map(std::path::PathBuf::from)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let config =
|
let mut compiler = sixtyfps_interpreter::ComponentCompiler::new();
|
||||||
sixtyfps_interpreter::CompilerConfiguration::new().with_include_paths(include_paths);
|
compiler.set_include_paths(include_paths);
|
||||||
|
|
||||||
let (component, diags) =
|
let component =
|
||||||
spin_on::spin_on(sixtyfps_interpreter::ComponentDefinition::from_source(
|
spin_on::spin_on(compiler.build_from_source(source, testcase.absolute_path.clone()));
|
||||||
source,
|
|
||||||
testcase.absolute_path.clone(),
|
|
||||||
config,
|
|
||||||
));
|
|
||||||
|
|
||||||
let component = match component {
|
let component = match component {
|
||||||
None => {
|
None => {
|
||||||
sixtyfps_interpreter::print_diagnostics(&diags);
|
sixtyfps_interpreter::print_diagnostics(&compiler.diagnostics());
|
||||||
return Err(diags.into_iter().map(|d| d.to_string()).join("\n").into());
|
return Err(compiler
|
||||||
|
.diagnostics()
|
||||||
|
.into_iter()
|
||||||
|
.map(|d| d.to_string())
|
||||||
|
.join("\n")
|
||||||
|
.into());
|
||||||
}
|
}
|
||||||
Some(c) => c,
|
Some(c) => c,
|
||||||
};
|
};
|
||||||
|
|
|
@ -37,17 +37,14 @@ fn main() -> std::io::Result<()> {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut compiler_config =
|
let mut compiler = sixtyfps_interpreter::ComponentCompiler::new();
|
||||||
sixtyfps_interpreter::CompilerConfiguration::new().with_include_paths(args.include_paths);
|
compiler.set_include_paths(args.include_paths);
|
||||||
if !args.style.is_empty() {
|
if !args.style.is_empty() {
|
||||||
compiler_config = compiler_config.with_style(args.style);
|
compiler.set_style(args.style);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (c, diags) = spin_on::spin_on(sixtyfps_interpreter::ComponentDefinition::from_path(
|
let c = spin_on::spin_on(compiler.build_from_path(args.path));
|
||||||
args.path,
|
sixtyfps_interpreter::print_diagnostics(&compiler.diagnostics());
|
||||||
compiler_config,
|
|
||||||
));
|
|
||||||
sixtyfps_interpreter::print_diagnostics(&diags);
|
|
||||||
|
|
||||||
let c = match c {
|
let c = match c {
|
||||||
Some(c) => c,
|
Some(c) => c,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue