mirror of
https://github.com/slint-ui/slint.git
synced 2025-08-04 10:50:00 +00:00
Add export { ... } from "....slint";
syntax. (#5533)
This commit is contained in:
parent
033e4de9b9
commit
66370b6bda
35 changed files with 324 additions and 434 deletions
|
@ -29,7 +29,8 @@ struct LoadedDocuments {
|
|||
|
||||
pub enum ImportKind {
|
||||
ImportList(syntax_nodes::ImportSpecifier),
|
||||
ModuleReexport(syntax_nodes::ExportModule), // re-export all types, as per export * from "foo".
|
||||
/// re-export types, as per `export ... from "foo"``.
|
||||
ModuleReexport(syntax_nodes::ExportsList),
|
||||
}
|
||||
|
||||
pub struct ImportedTypes {
|
||||
|
@ -739,6 +740,7 @@ impl TypeLoader {
|
|||
.await
|
||||
}
|
||||
|
||||
// This function could be async when MSRV >= 1.77, but until then, we need to return a Box
|
||||
fn load_dependencies_recursively_impl<'a: 'b, 'b>(
|
||||
state: &'a RefCell<BorrowedTypeLoader<'a>>,
|
||||
doc: &'b syntax_nodes::Document,
|
||||
|
@ -747,88 +749,114 @@ impl TypeLoader {
|
|||
) -> core::pin::Pin<Box<dyn std::future::Future<Output = (Vec<ImportedTypes>, Exports)> + 'b>>
|
||||
{
|
||||
let mut foreign_imports = vec![];
|
||||
let mut dependencies = Self::collect_dependencies(state, doc)
|
||||
.filter_map(|mut import| {
|
||||
let resolved_import = if let Some((path, _)) = state.borrow().tl.resolve_import_path(Some(&import.import_uri_token.clone().into()), &import.file) {
|
||||
path.to_string_lossy().to_string()
|
||||
} else {
|
||||
import.file.clone()
|
||||
};
|
||||
if resolved_import.ends_with(".slint") || resolved_import.ends_with(".60") || import.file.starts_with('@') {
|
||||
Some(Box::pin(async move {
|
||||
let file = import.file.as_str();
|
||||
let doc_path = Self::ensure_document_loaded(
|
||||
state,
|
||||
file,
|
||||
Some(import.import_uri_token.clone().into()),
|
||||
import_stack.clone()
|
||||
)
|
||||
.await?;
|
||||
let mut state = state.borrow_mut();
|
||||
let state = &mut *state;
|
||||
let doc = state.tl.all_documents.docs.get(&doc_path).unwrap();
|
||||
match &import.import_kind {
|
||||
ImportKind::ImportList(imported_types) => {
|
||||
let mut imported_types =
|
||||
ImportedName::extract_imported_names(imported_types).peekable();
|
||||
if imported_types.peek().is_some() {
|
||||
Self::register_imported_types(doc, &import, imported_types, registry_to_populate, state.diag);
|
||||
} else {
|
||||
state.diag.push_error("Import names are missing. Please specify which types you would like to import".into(), &import.import_uri_token.parent());
|
||||
}
|
||||
None
|
||||
}
|
||||
ImportKind::ModuleReexport(export_module_syntax_node) => {
|
||||
let mut exports = Exports::default();
|
||||
exports.add_reexports(
|
||||
doc.exports.iter().map(|(exported_name, compo_or_type)| {
|
||||
(
|
||||
ExportedName {
|
||||
name: exported_name.name.clone(),
|
||||
name_ident: (**export_module_syntax_node).clone(),
|
||||
},
|
||||
compo_or_type.clone(),
|
||||
)
|
||||
}),
|
||||
state.diag,
|
||||
);
|
||||
Some((exports, export_module_syntax_node.clone()))
|
||||
}
|
||||
}
|
||||
}))
|
||||
} else {
|
||||
import.file = resolved_import;
|
||||
foreign_imports.push(import);
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let mut dependencies_futures = vec![];
|
||||
for mut import in Self::collect_dependencies(state, doc) {
|
||||
let resolved_import = if let Some((path, _)) = state
|
||||
.borrow()
|
||||
.tl
|
||||
.resolve_import_path(Some(&import.import_uri_token.clone().into()), &import.file)
|
||||
{
|
||||
path.to_string_lossy().to_string()
|
||||
} else {
|
||||
import.file.clone()
|
||||
};
|
||||
if !(resolved_import.ends_with(".slint")
|
||||
|| resolved_import.ends_with(".60")
|
||||
|| import.file.starts_with('@'))
|
||||
{
|
||||
import.file = resolved_import;
|
||||
foreign_imports.push(import);
|
||||
continue;
|
||||
}
|
||||
dependencies_futures.push(Box::pin(async move {
|
||||
let file = import.file.as_str();
|
||||
let doc_path = Self::ensure_document_loaded(
|
||||
state,
|
||||
file,
|
||||
Some(import.import_uri_token.clone().into()),
|
||||
import_stack.clone(),
|
||||
)
|
||||
.await;
|
||||
(import, doc_path)
|
||||
}));
|
||||
}
|
||||
|
||||
Box::pin(async move {
|
||||
let mut reexports = None;
|
||||
let mut has_star_reexport = false;
|
||||
std::future::poll_fn(|cx| {
|
||||
dependencies.retain_mut(|fut| {
|
||||
let core::task::Poll::Ready(export) = fut.as_mut().poll(cx) else {
|
||||
dependencies_futures.retain_mut(|fut| {
|
||||
let core::task::Poll::Ready((import, doc_path)) = fut.as_mut().poll(cx) else {
|
||||
return true;
|
||||
};
|
||||
let Some((exports, node)) = export else { return false };
|
||||
if reexports.is_none() {
|
||||
reexports = Some(exports);
|
||||
} else {
|
||||
state.borrow_mut().diag.push_error(
|
||||
"re-exporting modules is only allowed once per file".into(),
|
||||
&node,
|
||||
);
|
||||
};
|
||||
let Some(doc_path) = doc_path else { return false };
|
||||
let mut state = state.borrow_mut();
|
||||
let state = &mut *state;
|
||||
let doc = state.tl.all_documents.docs.get(&doc_path).unwrap();
|
||||
match &import.import_kind {
|
||||
ImportKind::ImportList(imported_types) => {
|
||||
let mut imported_types =
|
||||
ImportedName::extract_imported_names(imported_types).peekable();
|
||||
if imported_types.peek().is_some() {
|
||||
Self::register_imported_types(
|
||||
doc,
|
||||
&import,
|
||||
imported_types,
|
||||
registry_to_populate,
|
||||
state.diag,
|
||||
);
|
||||
} else {
|
||||
state.diag.push_error("Import names are missing. Please specify which types you would like to import".into(), &import.import_uri_token.parent());
|
||||
}
|
||||
}
|
||||
ImportKind::ModuleReexport(export_module_syntax_node) => {
|
||||
let exports = reexports.get_or_insert_with(|| Exports::default());
|
||||
if let Some(star_reexport) = export_module_syntax_node
|
||||
.ExportModule()
|
||||
.and_then(|x| x.child_token(SyntaxKind::Star))
|
||||
{
|
||||
if has_star_reexport {
|
||||
state.diag.push_error("re-exporting modules is only allowed once per file".into(), &star_reexport);
|
||||
return false;
|
||||
}
|
||||
has_star_reexport = true;
|
||||
exports.add_reexports(
|
||||
doc.exports.iter().map(|(exported_name, compo_or_type)| {
|
||||
let exported_name = ExportedName {
|
||||
name: exported_name.name.clone(),
|
||||
name_ident: (**export_module_syntax_node).clone(),
|
||||
};
|
||||
(exported_name, compo_or_type.clone())
|
||||
}),
|
||||
state.diag,
|
||||
);
|
||||
} else if export_module_syntax_node.ExportSpecifier().next().is_none() {
|
||||
state.diag.push_error("Import names are missing. Please specify which types you would like to re-export".into(), export_module_syntax_node);
|
||||
} else {
|
||||
let e = export_module_syntax_node
|
||||
.ExportSpecifier()
|
||||
.filter_map(|e| {
|
||||
let (imported_name, exported_name) =
|
||||
ExportedName::from_export_specifier(&e);
|
||||
let Some(r) = doc.exports.find(&imported_name) else {
|
||||
state.diag.push_error(format!("No exported type called '{imported_name}' found in {doc_path:?}"), &e);
|
||||
return None;
|
||||
};
|
||||
Some((exported_name, r))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
exports.add_reexports(e, state.diag);
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
});
|
||||
if dependencies.is_empty() {
|
||||
if dependencies_futures.is_empty() {
|
||||
core::task::Poll::Ready(())
|
||||
} else {
|
||||
core::task::Poll::Pending
|
||||
}
|
||||
})
|
||||
.await;
|
||||
}).await;
|
||||
(foreign_imports, reexports.unwrap_or_default())
|
||||
})
|
||||
}
|
||||
|
@ -1264,10 +1292,12 @@ impl TypeLoader {
|
|||
(maybe_import_uri, ImportKind::ImportList(import))
|
||||
})
|
||||
.chain(
|
||||
// process `export * from "foo"`
|
||||
doc.ExportsList().flat_map(|exports| exports.ExportModule()).map(|reexport| {
|
||||
let maybe_import_uri = reexport.child_token(SyntaxKind::StringLiteral);
|
||||
(maybe_import_uri, ImportKind::ModuleReexport(reexport))
|
||||
// process `export ... from "foo"`
|
||||
doc.ExportsList().filter_map(|exports| {
|
||||
exports.ExportModule().map(|reexport| {
|
||||
let maybe_import_uri = reexport.child_token(SyntaxKind::StringLiteral);
|
||||
(maybe_import_uri, ImportKind::ModuleReexport(exports))
|
||||
})
|
||||
}),
|
||||
)
|
||||
.filter_map(|(maybe_import_uri, type_specifier)| {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue