1#![warn(clippy::pedantic, clippy::nursery)]
2#![allow(
3 clippy::option_if_let_else,
4 clippy::or_fun_call,
5 clippy::module_name_repetitions
6)]
7
8mod ast;
9mod error_ext;
10mod expand;
11mod kw;
12mod parse;
13mod span;
14
15use ast::{Child, Children};
16use expand::root_children_tokens;
17use proc_macro2::{Span, TokenStream};
18use proc_macro_error2::abort;
19use quote::quote;
20use syn::spanned::Spanned;
21
22#[must_use]
23pub fn mview_impl(input: TokenStream) -> TokenStream {
24 proc_macro_error2::set_dummy(quote! { () });
27
28 let children = match syn::parse2::<Children>(input) {
29 Ok(tree) => tree,
30 Err(e) => return e.to_compile_error(),
31 };
32
33 if children.len() == 1 {
37 let child = children.into_vec().remove(0);
38 match child {
39 Child::Node(node) => quote! {
40 { #[allow(unused_braces)] #node }
41 },
42 Child::Slot(slot, _) => abort!(
43 slot.span(),
44 "slots should be inside a parent that supports slots"
45 ),
46 }
47 } else {
48 if let Some(slot) = children.slot_children().next() {
50 abort!(
51 slot.tag().span(),
52 "slots should be inside a parent that supports slots"
53 );
54 };
55
56 let fragment = root_children_tokens(children.node_children(), Span::call_site());
57 quote! {
58 {
59 #[allow(unused_braces)]
60 #fragment
61 }
62 }
63 }
64}