mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-03 15:14:35 +00:00
Add aggregating BuildDiagnostics
This type aggregates different per-file diagnostics into a similar interface, in preparation for reporting diagnostics from multiple source files.
This commit is contained in:
parent
5dc53f0f79
commit
ada5f68908
6 changed files with 115 additions and 23 deletions
|
@ -1,3 +1,6 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct Span {
|
pub struct Span {
|
||||||
pub offset: usize,
|
pub offset: usize,
|
||||||
|
@ -206,3 +209,86 @@ impl quote::ToTokens for FileDiagnostics {
|
||||||
quote!(#(#diags)*).to_tokens(tokens);
|
quote!(#(#diags)*).to_tokens(tokens);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct BuildDiagnostics {
|
||||||
|
per_input_file_diagnostics: HashMap<PathBuf, FileDiagnostics>,
|
||||||
|
internal_errors: Option<FileDiagnostics>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BuildDiagnostics {
|
||||||
|
pub fn add(&mut self, diagnostics: FileDiagnostics) {
|
||||||
|
match self.per_input_file_diagnostics.get_mut(&diagnostics.current_path) {
|
||||||
|
Some(existing_diags) => existing_diags.inner.extend(diagnostics.inner),
|
||||||
|
None => {
|
||||||
|
self.per_input_file_diagnostics
|
||||||
|
.insert(diagnostics.current_path.clone(), diagnostics);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_internal_error(&mut self, err: Diagnostic) {
|
||||||
|
self.internal_errors
|
||||||
|
.get_or_insert_with(|| FileDiagnostics {
|
||||||
|
current_path: "[internal error]".into(),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.inner
|
||||||
|
.push(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn iter(&self) -> impl Iterator<Item = &FileDiagnostics> {
|
||||||
|
self.per_input_file_diagnostics.values().chain(self.internal_errors.iter())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_iter(self) -> impl Iterator<Item = FileDiagnostics> {
|
||||||
|
self.per_input_file_diagnostics
|
||||||
|
.into_iter()
|
||||||
|
.map(|(_, diag)| diag)
|
||||||
|
.chain(self.internal_errors.into_iter())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn iter_mut(&mut self) -> impl Iterator<Item = &mut FileDiagnostics> {
|
||||||
|
self.per_input_file_diagnostics.values_mut().chain(self.internal_errors.iter_mut())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn has_error(&self) -> bool {
|
||||||
|
self.iter().any(|diag| diag.has_error())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_string_vec(&self) -> Vec<String> {
|
||||||
|
self.iter()
|
||||||
|
.flat_map(|diag| {
|
||||||
|
diag.to_string_vec()
|
||||||
|
.iter()
|
||||||
|
.map(|err| format!("{}: {}", diag.current_path.to_string_lossy(), err))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print(self) {
|
||||||
|
self.into_iter().for_each(|diag| diag.print());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "display-diagnostics")]
|
||||||
|
pub fn check_and_exit_on_error(self) -> Self {
|
||||||
|
if self.has_error() {
|
||||||
|
self.print();
|
||||||
|
std::process::exit(-1);
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "proc_macro_span")]
|
||||||
|
pub fn map_offsets_to_span(&mut self, span_map: &[crate::parser::Token]) {
|
||||||
|
self.iter_mut().for_each(|diag| diag.map_offsets_to_span(span_map))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "proc_macro_span")]
|
||||||
|
impl quote::ToTokens for BuildDiagnostics {
|
||||||
|
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
|
||||||
|
self.iter().for_each(|diag| diag.to_tokens(tokens))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ The module responsible for the code generation.
|
||||||
There is one sub module for every language
|
There is one sub module for every language
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::diagnostics::FileDiagnostics;
|
use crate::diagnostics::BuildDiagnostics;
|
||||||
use crate::object_tree::{Component, ElementRc};
|
use crate::object_tree::{Component, ElementRc};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ pub fn generate(
|
||||||
format: OutputFormat,
|
format: OutputFormat,
|
||||||
destination: &mut impl std::io::Write,
|
destination: &mut impl std::io::Write,
|
||||||
component: &Rc<Component>,
|
component: &Rc<Component>,
|
||||||
diag: &mut FileDiagnostics,
|
diag: &mut BuildDiagnostics,
|
||||||
) -> std::io::Result<()> {
|
) -> std::io::Result<()> {
|
||||||
#![allow(unused_variables)]
|
#![allow(unused_variables)]
|
||||||
#![allow(unreachable_code)]
|
#![allow(unreachable_code)]
|
||||||
|
|
|
@ -127,7 +127,7 @@ mod cpp_ast {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::diagnostics::{CompilerDiagnostic, FileDiagnostics};
|
use crate::diagnostics::{BuildDiagnostics, CompilerDiagnostic};
|
||||||
use crate::expression_tree::Expression;
|
use crate::expression_tree::Expression;
|
||||||
use crate::object_tree::{Component, Element, ElementRc, RepeatedElementInfo};
|
use crate::object_tree::{Component, Element, ElementRc, RepeatedElementInfo};
|
||||||
use crate::parser::Spanned;
|
use crate::parser::Spanned;
|
||||||
|
@ -360,7 +360,7 @@ fn handle_repeater(
|
||||||
/// Returns the text of the C++ code produced by the given root component
|
/// Returns the text of the C++ code produced by the given root component
|
||||||
pub fn generate(
|
pub fn generate(
|
||||||
component: &Rc<Component>,
|
component: &Rc<Component>,
|
||||||
diag: &mut FileDiagnostics,
|
diag: &mut BuildDiagnostics,
|
||||||
) -> Option<impl std::fmt::Display> {
|
) -> Option<impl std::fmt::Display> {
|
||||||
let mut file = File::default();
|
let mut file = File::default();
|
||||||
|
|
||||||
|
@ -377,7 +377,7 @@ pub fn generate(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_component(file: &mut File, component: &Rc<Component>, diag: &mut FileDiagnostics) {
|
fn generate_component(file: &mut File, component: &Rc<Component>, diag: &mut BuildDiagnostics) {
|
||||||
let component_id = component_id(component);
|
let component_id = component_id(component);
|
||||||
let mut component_struct = Struct { name: component_id.clone(), ..Default::default() };
|
let mut component_struct = Struct { name: component_id.clone(), ..Default::default() };
|
||||||
|
|
||||||
|
@ -405,7 +405,7 @@ fn generate_component(file: &mut File, component: &Rc<Component>, diag: &mut Fil
|
||||||
span: property_decl.type_location.clone(),
|
span: property_decl.type_location.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
diag.push_compiler_error(err);
|
diag.push_internal_error(err.into());
|
||||||
"".into()
|
"".into()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -454,7 +454,8 @@ fn generate_component(file: &mut File, component: &Rc<Component>, diag: &mut Fil
|
||||||
.ty()
|
.ty()
|
||||||
.cpp_type()
|
.cpp_type()
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
diag.push_compiler_error(CompilerDiagnostic {
|
diag.push_internal_error(
|
||||||
|
CompilerDiagnostic {
|
||||||
message: "Cannot map property type to C++".into(),
|
message: "Cannot map property type to C++".into(),
|
||||||
span: parent_element
|
span: parent_element
|
||||||
.borrow()
|
.borrow()
|
||||||
|
@ -462,7 +463,9 @@ fn generate_component(file: &mut File, component: &Rc<Component>, diag: &mut Fil
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|n| n.span())
|
.map(|n| n.span())
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
});
|
}
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
String::default()
|
String::default()
|
||||||
})
|
})
|
||||||
.to_owned();
|
.to_owned();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*! module for the Rust code generator
|
/*! module for the Rust code generator
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::diagnostics::{CompilerDiagnostic, FileDiagnostics};
|
use crate::diagnostics::{BuildDiagnostics, CompilerDiagnostic};
|
||||||
use crate::expression_tree::{Expression, NamedReference, OperatorClass, Path};
|
use crate::expression_tree::{Expression, NamedReference, OperatorClass, Path};
|
||||||
use crate::object_tree::{Component, ElementRc};
|
use crate::object_tree::{Component, ElementRc};
|
||||||
use crate::parser::Spanned;
|
use crate::parser::Spanned;
|
||||||
|
@ -38,7 +38,7 @@ fn rust_type(
|
||||||
/// Generate the rust code for the given component.
|
/// Generate the rust code for the given component.
|
||||||
///
|
///
|
||||||
/// Fill the diagnostic in case of error.
|
/// Fill the diagnostic in case of error.
|
||||||
pub fn generate(component: &Rc<Component>, diag: &mut FileDiagnostics) -> Option<TokenStream> {
|
pub fn generate(component: &Rc<Component>, diag: &mut BuildDiagnostics) -> Option<TokenStream> {
|
||||||
let mut extra_components = vec![];
|
let mut extra_components = vec![];
|
||||||
let mut declared_property_vars = vec![];
|
let mut declared_property_vars = vec![];
|
||||||
let mut declared_property_types = vec![];
|
let mut declared_property_types = vec![];
|
||||||
|
@ -66,7 +66,7 @@ pub fn generate(component: &Rc<Component>, diag: &mut FileDiagnostics) -> Option
|
||||||
let rust_property_type =
|
let rust_property_type =
|
||||||
rust_type(&property_decl.property_type, &property_decl.type_location)
|
rust_type(&property_decl.property_type, &property_decl.type_location)
|
||||||
.unwrap_or_else(|err| {
|
.unwrap_or_else(|err| {
|
||||||
diag.push_compiler_error(err);
|
diag.push_internal_error(err.into());
|
||||||
quote!().into()
|
quote!().into()
|
||||||
});
|
});
|
||||||
declared_property_types.push(rust_property_type.clone());
|
declared_property_types.push(rust_property_type.clone());
|
||||||
|
@ -141,7 +141,7 @@ pub fn generate(component: &Rc<Component>, diag: &mut FileDiagnostics) -> Option
|
||||||
&item.node.as_ref().map_or_else(Default::default, |n| n.span()),
|
&item.node.as_ref().map_or_else(Default::default, |n| n.span()),
|
||||||
)
|
)
|
||||||
.unwrap_or_else(|err| {
|
.unwrap_or_else(|err| {
|
||||||
diag.push_compiler_error(err);
|
diag.push_internal_error(err.into());
|
||||||
quote!().into()
|
quote!().into()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -291,7 +291,7 @@ pub fn generate(component: &Rc<Component>, diag: &mut FileDiagnostics) -> Option
|
||||||
.map_or_else(Default::default, |n| n.span()),
|
.map_or_else(Default::default, |n| n.span()),
|
||||||
)
|
)
|
||||||
.unwrap_or_else(|err| {
|
.unwrap_or_else(|err| {
|
||||||
diag.push_compiler_error(err);
|
diag.push_internal_error(err.into());
|
||||||
quote!().into()
|
quote!().into()
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
|
@ -53,14 +53,17 @@ pub fn compile_syntax_node<DocNode: Into<parser::syntax_nodes::Document>>(
|
||||||
doc_node: DocNode,
|
doc_node: DocNode,
|
||||||
mut diagnostics: diagnostics::FileDiagnostics,
|
mut diagnostics: diagnostics::FileDiagnostics,
|
||||||
compiler_config: &CompilerConfiguration,
|
compiler_config: &CompilerConfiguration,
|
||||||
) -> (object_tree::Document, diagnostics::FileDiagnostics) {
|
) -> (object_tree::Document, diagnostics::BuildDiagnostics) {
|
||||||
let type_registry = typeregister::TypeRegister::builtin();
|
let type_registry = typeregister::TypeRegister::builtin();
|
||||||
let doc =
|
let doc =
|
||||||
crate::object_tree::Document::from_node(doc_node.into(), &mut diagnostics, &type_registry);
|
crate::object_tree::Document::from_node(doc_node.into(), &mut diagnostics, &type_registry);
|
||||||
|
|
||||||
run_passes(&doc, &mut diagnostics, compiler_config);
|
run_passes(&doc, &mut diagnostics, compiler_config);
|
||||||
|
|
||||||
(doc, diagnostics)
|
let mut all_diagnostics = diagnostics::BuildDiagnostics::default();
|
||||||
|
all_diagnostics.add(diagnostics);
|
||||||
|
|
||||||
|
(doc, all_diagnostics)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_passes(
|
pub fn run_passes(
|
||||||
|
|
|
@ -222,7 +222,7 @@ fn rtti_for<T: 'static + Default + rtti::BuiltinItem + vtable::HasStaticVTable<I
|
||||||
pub fn load(
|
pub fn load(
|
||||||
source: String,
|
source: String,
|
||||||
path: &std::path::Path,
|
path: &std::path::Path,
|
||||||
) -> Result<Rc<ComponentDescription>, sixtyfps_compilerlib::diagnostics::FileDiagnostics> {
|
) -> Result<Rc<ComponentDescription>, sixtyfps_compilerlib::diagnostics::BuildDiagnostics> {
|
||||||
let (syntax_node, diag) = parser::parse(source, Some(path));
|
let (syntax_node, diag) = parser::parse(source, Some(path));
|
||||||
let compiler_config = CompilerConfiguration::default();
|
let compiler_config = CompilerConfiguration::default();
|
||||||
let (tree, diag) = compile_syntax_node(syntax_node, diag, &compiler_config);
|
let (tree, diag) = compile_syntax_node(syntax_node, diag, &compiler_config);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue