Skip to content
Snippets Groups Projects
Commit 7ad7bf05 authored by MrGVSV's avatar MrGVSV
Browse files

Empty widget arguments create unit type props

Implemented WidgetProps over the unit type ('()') so that widget's
without the need for props can be defined without them
parent edd9ce71
No related branches found
No related tags found
No related merge requests found
......@@ -15,8 +15,8 @@ pub trait SealedWidget {}
/// all implementors of [Widget].
pub trait BaseWidget: SealedWidget + std::fmt::Debug + Send + Sync {
fn constructor<P: WidgetProps>(props: P) -> Self
where
Self: Sized;
where
Self: Sized;
fn get_id(&self) -> Index;
fn set_id(&mut self, id: Index);
fn get_props(&self) -> &dyn WidgetProps;
......@@ -32,8 +32,8 @@ pub trait Widget: std::fmt::Debug + Clone + Default + PartialEq + AsAny + Send +
/// Construct the widget with the given props
fn constructor(props: Self::Props) -> Self
where
Self: Sized;
where
Self: Sized;
/// Get this widget's ID
fn get_id(&self) -> Index;
......@@ -79,12 +79,12 @@ pub trait WidgetProps: std::fmt::Debug + AsAny + Send + Sync {
}
impl<T> BaseWidget for T
where
T: Widget + Clone + PartialEq + Default,
where
T: Widget + Clone + PartialEq + Default,
{
fn constructor<P: WidgetProps>(props: P) -> Self
where
Self: Sized,
where
Self: Sized,
{
let props: Box<dyn Any> = Box::new(props);
Widget::constructor(*props.downcast::<<T as Widget>::Props>().unwrap())
......@@ -120,3 +120,23 @@ where
}
impl<T> SealedWidget for T where T: Widget {}
impl WidgetProps for () {
fn get_children(&self) -> Option<Children> {
None
}
fn set_children(&mut self, _children: Option<Children>) {}
fn get_styles(&self) -> Option<Style> {
None
}
fn get_on_event(&self) -> Option<OnEvent> {
None
}
fn get_focusable(&self) -> Option<bool> {
None
}
}
\ No newline at end of file
use crate::get_core_crate;
use proc_macro::TokenStream;
use proc_macro2::Ident;
use proc_macro_error::emit_error;
use quote::quote;
use quote::{format_ident, quote};
use syn::spanned::Spanned;
use syn::{FnArg, Pat, Type};
use syn::{FnArg, parse_quote, Pat, Signature, Type};
const DEFAULT_PROP_IDENT: &str = "__props";
pub struct WidgetArguments {
pub focusable: bool,
......@@ -19,43 +22,10 @@ pub fn create_function_widget(f: syn::ItemFn, _widget_arguments: WidgetArguments
let struct_name = f.sig.ident.clone();
let (impl_generics, ty_generics, where_clause) = f.sig.generics.split_for_impl();
if f.sig.inputs.len() != 1 {
let span = if f.sig.inputs.len() > 0 {
f.sig.inputs.span()
} else {
f.sig.span()
};
emit_error!(
span,
"Functional widgets expect exactly one argument (their props), but was given {}",
f.sig.inputs.len()
);
}
let (props, prop_type) = match f.sig.inputs.first().unwrap() {
FnArg::Typed(typed) => {
let ident = match *typed.pat.clone() {
Pat::Ident(ident) => ident.ident,
err => {
emit_error!(err.span(), "Expected identifier, but got {:?}", err);
return TokenStream::new();
}
};
let ty = match *typed.ty.clone() {
Type::Path(type_path) => type_path.path,
err => {
emit_error!(err.span(), "Invalid widget prop type: {:?}", err);
return TokenStream::new();
}
};
(ident, ty)
}
FnArg::Receiver(receiver) => {
emit_error!(receiver.span(), "Functional widget cannot use 'self'");
return TokenStream::new();
}
let (props, prop_type) = if let Some(parsed) = get_props(&f.sig) {
parsed
} else {
return TokenStream::new();
};
let block = f.block;
......@@ -112,3 +82,52 @@ pub fn create_function_widget(f: syn::ItemFn, _widget_arguments: WidgetArguments
}
})
}
fn get_props(signature: &Signature) -> Option<(Ident, Type)> {
if signature.inputs.len() > 1 {
let span = if signature.inputs.len() > 0 {
signature.inputs.span()
} else {
signature.span()
};
emit_error!(
span,
"Functional widgets expect at most one argument (their props), but was given {}",
signature.inputs.len()
);
return None;
}
if signature.inputs.len() == 0 {
let ident = format_ident!("{}", DEFAULT_PROP_IDENT);
let ty: Type = parse_quote!{()};
return Some((ident, ty));
}
match signature.inputs.first().unwrap() {
FnArg::Typed(typed) => {
let ident = match *typed.pat.clone() {
Pat::Ident(ident) => ident.ident,
err => {
emit_error!(err.span(), "Expected identifier, but got {:?}", err);
return None;
}
};
let ty = *typed.ty.clone();
match &ty {
Type::Path(..) => {},
err => {
emit_error!(err.span(), "Invalid widget prop type: {:?}", err);
return None;
}
};
Some((ident, ty))
}
FnArg::Receiver(receiver) => {
emit_error!(receiver.span(), "Functional widget cannot use 'self'");
return None;
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment